From ab96c75b08c010dd6e824da1e3b9180257b55af5 Mon Sep 17 00:00:00 2001 From: Roman Syroeshko Date: Sat, 22 Mar 2014 10:06:08 +0400 Subject: [PATCH] https://github.com/PHPOffice/PHPWord/issues/58 - Part VIII (Autoloader). --- README.md | 2 +- Tests/PhpWord/AutoloaderTest.php | 41 +- Tests/PhpWord/IOFactoryTest.php | 2 +- Tests/PhpWord/MediaTest.php | 12 +- Tests/PhpWord/Reader/Word2007Test.php | 8 +- Tests/PhpWord/Section/FooterTest.php | 2 +- Tests/PhpWord/Section/HeaderTest.php | 4 +- Tests/PhpWord/Section/ImageTest.php | 26 +- Tests/PhpWord/Section/MemoryImageTest.php | 12 +- Tests/PhpWord/Section/ObjectTest.php | 12 +- Tests/PhpWord/Section/Table/CellTest.php | 8 +- Tests/PhpWord/Section/TextRunTest.php | 2 +- Tests/PhpWord/SectionTest.php | 4 +- Tests/PhpWord/Shared/FileTest.php | 6 +- Tests/PhpWord/Shared/FontTest.php | 2 +- Tests/PhpWord/Style/FontTest.php | 2 +- Tests/PhpWord/Style/ParagraphTest.php | 2 +- Tests/PhpWord/Style/TabsTest.php | 2 +- Tests/PhpWord/TemplateTest.php | 18 +- Tests/PhpWord/Writer/ODText/ContentTest.php | 6 +- Tests/PhpWord/Writer/ODTextTest.php | 16 +- Tests/PhpWord/Writer/RTFTest.php | 10 +- Tests/PhpWord/Writer/Word2007/BaseTest.php | 8 +- .../PhpWord/Writer/Word2007/DocumentTest.php | 4 +- .../PhpWord/Writer/Word2007/FootnotesTest.php | 2 +- Tests/PhpWord/Writer/Word2007/StylesTest.php | 2 +- Tests/PhpWord/Writer/Word2007Test.php | 12 +- Tests/PhpWordTest.php | 6 +- Tests/_inc/TestHelperDOCX.php | 2 +- Tests/bootstrap.php | 17 +- changelog.txt | 2 +- composer.json | 4 +- phpunit.xml.dist | 6 +- samples/Sample_01_SimpleText.php | 2 +- samples/Sample_02_TabStops.php | 2 +- samples/Sample_03_Sections.php | 2 +- samples/Sample_04_Textrun.php | 2 +- samples/Sample_05_Multicolumn.php | 2 +- samples/Sample_06_Footnote.php | 2 +- samples/Sample_07_TemplateCloneRow.php | 2 +- samples/Sample_08_ParagraphPagination.php | 2 +- samples/Sample_09_Tables.php | 2 +- samples/Sample_10_EastAsianFontStyle.php | 2 +- samples/Sample_11_ReadWord2007.php | 2 +- samples/Sample_12_HeaderFooter.php | 2 +- samples/Sample_13_Images.php | 2 +- samples/Sample_14_ListItem.php | 2 +- samples/Sample_15_Link.php | 2 +- samples/Sample_16_Object.php | 2 +- samples/Sample_17_TitleTOC.php | 2 +- samples/Sample_18_Watermark.php | 2 +- samples/Sample_19_TextBreak.php | 2 +- src/Autoloader.php | 64 ++ src/DocumentProperties.php | 606 ++++++++++ src/Exceptions/Exception.php | 6 + src/Exceptions/InvalidImageException.php | 13 + src/Exceptions/InvalidStyleException.php | 15 + .../UnsupportedImageTypeException.php | 13 + src/Footnote.php | 124 ++ src/HashTable.php | 209 ++++ src/IOFactory.php | 80 ++ src/Media.php | 347 ++++++ src/PhpWord.php | 233 ++++ src/Reader/AbstractReader.php | 110 ++ src/Reader/IReader.php | 46 + src/Reader/Word2007.php | 452 ++++++++ src/Section.php | 453 ++++++++ src/Section/Footer.php | 217 ++++ src/Section/Footer/PreserveText.php | 130 +++ src/Section/Footnote.php | 151 +++ src/Section/Header.php | 299 +++++ src/Section/Image.php | 177 +++ src/Section/Link.php | 174 +++ src/Section/ListItem.php | 101 ++ src/Section/MemoryImage.php | 233 ++++ src/Section/Object.php | 179 +++ src/Section/PageBreak.php | 38 + src/Section/Settings.php | 728 ++++++++++++ src/Section/Table.php | 163 +++ src/Section/Table/Cell.php | 350 ++++++ src/Section/Table/Row.php | 139 +++ src/Section/Text.php | 154 +++ src/Section/TextBreak.php | 122 ++ src/Section/TextRun.php | 184 +++ src/Section/Title.php | 145 +++ src/Settings.php | 63 ++ src/Shared/Drawing.php | 162 +++ src/Shared/File.php | 76 ++ src/Shared/Font.php | 90 ++ src/Shared/String.php | 109 ++ src/Shared/XMLWriter.php | 155 +++ src/Shared/ZipStreamWrapper.php | 183 +++ src/Style.php | 161 +++ src/Style/Cell.php | 343 ++++++ src/Style/Font.php | 544 +++++++++ src/Style/Image.php | 175 +++ src/Style/ListItem.php | 80 ++ src/Style/Paragraph.php | 508 +++++++++ src/Style/Row.php | 88 ++ src/Style/TOC.php | 139 +++ src/Style/Tab.php | 146 +++ src/Style/Table.php | 94 ++ src/Style/TableFull.php | 443 ++++++++ src/Style/Tabs.php | 63 ++ src/TOC.php | 155 +++ src/Template.php | 292 +++++ src/Writer/IWriter.php | 39 + src/Writer/ODText.php | 282 +++++ src/Writer/ODText/Content.php | 412 +++++++ src/Writer/ODText/Manifest.php | 132 +++ src/Writer/ODText/Meta.php | 96 ++ src/Writer/ODText/Mimetype.php | 46 + src/Writer/ODText/Styles.php | 273 +++++ src/Writer/ODText/WriterPart.php | 66 ++ src/Writer/RTF.php | 482 ++++++++ src/Writer/Word2007.php | 301 +++++ src/Writer/Word2007/Base.php | 1003 +++++++++++++++++ src/Writer/Word2007/ContentTypes.php | 228 ++++ src/Writer/Word2007/DocProps.php | 186 +++ src/Writer/Word2007/Document.php | 506 +++++++++ src/Writer/Word2007/DocumentRels.php | 182 +++ src/Writer/Word2007/Footer.php | 90 ++ src/Writer/Word2007/Footnotes.php | 87 ++ src/Writer/Word2007/FootnotesRels.php | 89 ++ src/Writer/Word2007/Header.php | 94 ++ src/Writer/Word2007/Rels.php | 115 ++ src/Writer/Word2007/Styles.php | 399 +++++++ src/Writer/Word2007/WriterPart.php | 49 + src/_staticDocParts/_doc.png | Bin 0 -> 1157 bytes src/_staticDocParts/_ppt.png | Bin 0 -> 1886 bytes src/_staticDocParts/_xls.png | Bin 0 -> 1924 bytes src/_staticDocParts/fontTable.xml | 2 + src/_staticDocParts/numbering.xml | 2 + src/_staticDocParts/settings.xml | 48 + src/_staticDocParts/theme1.xml | 2 + src/_staticDocParts/webSettings.xml | 2 + 136 files changed, 15881 insertions(+), 158 deletions(-) create mode 100644 src/Autoloader.php create mode 100644 src/DocumentProperties.php create mode 100644 src/Exceptions/Exception.php create mode 100644 src/Exceptions/InvalidImageException.php create mode 100644 src/Exceptions/InvalidStyleException.php create mode 100644 src/Exceptions/UnsupportedImageTypeException.php create mode 100644 src/Footnote.php create mode 100644 src/HashTable.php create mode 100644 src/IOFactory.php create mode 100644 src/Media.php create mode 100644 src/PhpWord.php create mode 100644 src/Reader/AbstractReader.php create mode 100644 src/Reader/IReader.php create mode 100644 src/Reader/Word2007.php create mode 100644 src/Section.php create mode 100644 src/Section/Footer.php create mode 100644 src/Section/Footer/PreserveText.php create mode 100644 src/Section/Footnote.php create mode 100644 src/Section/Header.php create mode 100644 src/Section/Image.php create mode 100644 src/Section/Link.php create mode 100644 src/Section/ListItem.php create mode 100644 src/Section/MemoryImage.php create mode 100644 src/Section/Object.php create mode 100644 src/Section/PageBreak.php create mode 100644 src/Section/Settings.php create mode 100644 src/Section/Table.php create mode 100644 src/Section/Table/Cell.php create mode 100644 src/Section/Table/Row.php create mode 100644 src/Section/Text.php create mode 100644 src/Section/TextBreak.php create mode 100644 src/Section/TextRun.php create mode 100644 src/Section/Title.php create mode 100644 src/Settings.php create mode 100644 src/Shared/Drawing.php create mode 100644 src/Shared/File.php create mode 100644 src/Shared/Font.php create mode 100644 src/Shared/String.php create mode 100644 src/Shared/XMLWriter.php create mode 100644 src/Shared/ZipStreamWrapper.php create mode 100644 src/Style.php create mode 100644 src/Style/Cell.php create mode 100644 src/Style/Font.php create mode 100644 src/Style/Image.php create mode 100644 src/Style/ListItem.php create mode 100644 src/Style/Paragraph.php create mode 100644 src/Style/Row.php create mode 100644 src/Style/TOC.php create mode 100644 src/Style/Tab.php create mode 100644 src/Style/Table.php create mode 100644 src/Style/TableFull.php create mode 100644 src/Style/Tabs.php create mode 100644 src/TOC.php create mode 100644 src/Template.php create mode 100644 src/Writer/IWriter.php create mode 100644 src/Writer/ODText.php create mode 100644 src/Writer/ODText/Content.php create mode 100644 src/Writer/ODText/Manifest.php create mode 100644 src/Writer/ODText/Meta.php create mode 100644 src/Writer/ODText/Mimetype.php create mode 100644 src/Writer/ODText/Styles.php create mode 100644 src/Writer/ODText/WriterPart.php create mode 100644 src/Writer/RTF.php create mode 100644 src/Writer/Word2007.php create mode 100644 src/Writer/Word2007/Base.php create mode 100644 src/Writer/Word2007/ContentTypes.php create mode 100644 src/Writer/Word2007/DocProps.php create mode 100644 src/Writer/Word2007/Document.php create mode 100644 src/Writer/Word2007/DocumentRels.php create mode 100644 src/Writer/Word2007/Footer.php create mode 100644 src/Writer/Word2007/Footnotes.php create mode 100644 src/Writer/Word2007/FootnotesRels.php create mode 100644 src/Writer/Word2007/Header.php create mode 100644 src/Writer/Word2007/Rels.php create mode 100644 src/Writer/Word2007/Styles.php create mode 100644 src/Writer/Word2007/WriterPart.php create mode 100644 src/_staticDocParts/_doc.png create mode 100644 src/_staticDocParts/_ppt.png create mode 100644 src/_staticDocParts/_xls.png create mode 100644 src/_staticDocParts/fontTable.xml create mode 100644 src/_staticDocParts/numbering.xml create mode 100644 src/_staticDocParts/settings.xml create mode 100644 src/_staticDocParts/theme1.xml create mode 100644 src/_staticDocParts/webSettings.xml diff --git a/README.md b/README.md index b46cd0f0..e401de24 100755 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # PhpWord -[![Build Status](https://travis-ci.org/PHPOffice/PhpWord.png?branch=master)](https://travis-ci.org/PHPOffice/PhpWord) +[![Build Status](https://travis-ci.org/PhpOffice/PhpWord.png?branch=master)](https://travis-ci.org/PhpOffice/PhpWord) [![Latest Stable Version](https://poser.pugx.org/phpoffice/phpword/v/stable.png)](https://packagist.org/packages/phpoffice/phpword) [![Total Downloads](https://poser.pugx.org/phpoffice/phpword/downloads.png)](https://packagist.org/packages/phpoffice/phpword) [![Latest Unstable Version](https://poser.pugx.org/phpoffice/phpword/v/unstable.png)](https://packagist.org/packages/phpoffice/phpword) [![License](https://poser.pugx.org/phpoffice/phpword/license.png)](https://packagist.org/packages/phpoffice/phpword) __OpenXML - Read, Write and Create Word documents in PHP.__ diff --git a/Tests/PhpWord/AutoloaderTest.php b/Tests/PhpWord/AutoloaderTest.php index cc244688..8c3d50f9 100644 --- a/Tests/PhpWord/AutoloaderTest.php +++ b/Tests/PhpWord/AutoloaderTest.php @@ -1,49 +1,36 @@ assertContains(array('PHPWord_Autoloader', 'load'), spl_autoload_functions()); - $this->assertContains(array('PHPWord_Autoloader', 'autoload'), spl_autoload_functions()); - } - - public function testAutoloadLegacy() - { - $this->assertNull( - PHPWord_Autoloader::load('Foo'), - 'PHPWord_Autoloader::load() is trying to load classes outside of the PhpWord namespace' - ); - $this->assertTrue( - PHPWord_Autoloader::load('PhpWord'), - 'PHPWord_Autoloader::load() failed to autoload the PhpWord class' + Autoloader::register(); + $this->assertContains( + array('PhpOffice\\PhpWord\\Autoloader', 'autoload'), + \spl_autoload_functions() ); } public function testAutoload() { - $declared = get_declared_classes(); - $declaredCount = count($declared); + $declared = \get_declared_classes(); + $declaredCount = \count($declared); Autoloader::autoload('Foo'); $this->assertEquals( $declaredCount, - count(get_declared_classes()), - 'PhpOffice\\PhpWord\\Autoloader::autoload() is trying to load classes ' . - 'outside of the PhpOffice\\PhpWord namespace' + \count(get_declared_classes()), + 'PhpOffice\\PhpWord\\Autoloader::autoload() is trying to load classes ' + . 'outside of the PhpOffice\\PhpWord namespace' ); // TODO change this class to the main PhpWord class when it is namespaced - Autoloader::autoload( - 'PhpOffice\\PhpWord\\Exceptions\\InvalidStyleException' - ); + Autoloader::autoload('PhpOffice\\PhpWord\\Exceptions\\InvalidStyleException'); $this->assertTrue( - in_array('PhpOffice\\PhpWord\\Exceptions\\InvalidStyleException', get_declared_classes()), - 'PhpOffice\\PhpWord\\Autoloader::autoload() failed to autoload the ' . - 'PhpOffice\\PhpWord\\Exceptions\\InvalidStyleException class' + \in_array('PhpOffice\\PhpWord\\Exceptions\\InvalidStyleException', \get_declared_classes()), + 'PhpOffice\\PhpWord\\Autoloader::autoload() failed to autoload the ' + . 'PhpOffice\\PhpWord\\Exceptions\\InvalidStyleException class' ); } } \ No newline at end of file diff --git a/Tests/PhpWord/IOFactoryTest.php b/Tests/PhpWord/IOFactoryTest.php index c5d5aa75..d10bcfeb 100644 --- a/Tests/PhpWord/IOFactoryTest.php +++ b/Tests/PhpWord/IOFactoryTest.php @@ -1,7 +1,7 @@ addImage(PHPWORD_TESTS_DIR_ROOT . "/_files/images/mars_noext_jpg"); - $section->addImage(PHPWORD_TESTS_DIR_ROOT . "/_files/images/mars.jpg"); - $section->addImage(PHPWORD_TESTS_DIR_ROOT . "/_files/images/mario.gif"); - $section->addImage(PHPWORD_TESTS_DIR_ROOT . "/_files/images/firefox.png"); - $section->addImage(PHPWORD_TESTS_DIR_ROOT . "/_files/images/duke_nukem.bmp"); - $section->addImage(PHPWORD_TESTS_DIR_ROOT . "/_files/images/angela_merkel.tif"); + $section->addImage(\PHPWORD_TESTS_BASE_DIR . "/_files/images/mars_noext_jpg"); + $section->addImage(\PHPWORD_TESTS_BASE_DIR . "/_files/images/mars.jpg"); + $section->addImage(\PHPWORD_TESTS_BASE_DIR . "/_files/images/mario.gif"); + $section->addImage(\PHPWORD_TESTS_BASE_DIR . "/_files/images/firefox.png"); + $section->addImage(\PHPWORD_TESTS_BASE_DIR . "/_files/images/duke_nukem.bmp"); + $section->addImage(\PHPWORD_TESTS_BASE_DIR . "/_files/images/angela_merkel.tif"); $elements = $section->getElements(); $this->assertEquals(6, count($elements)); diff --git a/Tests/PhpWord/Reader/Word2007Test.php b/Tests/PhpWord/Reader/Word2007Test.php index 53d10d0d..40219d34 100644 --- a/Tests/PhpWord/Reader/Word2007Test.php +++ b/Tests/PhpWord/Reader/Word2007Test.php @@ -26,7 +26,7 @@ class Word2007Test extends \PHPUnit_Framework_TestCase { $dir = join( DIRECTORY_SEPARATOR, - array(PHPWORD_TESTS_DIR_ROOT, '_files', 'documents') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'documents') ); $object = new Word2007; $file = $dir . DIRECTORY_SEPARATOR . 'reader.docx'; @@ -42,7 +42,7 @@ class Word2007Test extends \PHPUnit_Framework_TestCase { $dir = join( DIRECTORY_SEPARATOR, - array(PHPWORD_TESTS_DIR_ROOT, '_files', 'documents') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'documents') ); $object = new Word2007; $file = $dir . DIRECTORY_SEPARATOR . 'foo.docx'; @@ -57,10 +57,10 @@ class Word2007Test extends \PHPUnit_Framework_TestCase { $dir = join( DIRECTORY_SEPARATOR, - array(PHPWORD_TESTS_DIR_ROOT, '_files', 'documents') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'documents') ); $file = $dir . DIRECTORY_SEPARATOR . 'reader.docx'; $object = IOFactory::load($file); - $this->assertInstanceOf('PhpOffice\\PhpWord', $object); + $this->assertInstanceOf('PhpOffice\\PhpWord\\PhpWord', $object); } } \ No newline at end of file diff --git a/Tests/PhpWord/Section/FooterTest.php b/Tests/PhpWord/Section/FooterTest.php index 0052a651..9b6682e8 100644 --- a/Tests/PhpWord/Section/FooterTest.php +++ b/Tests/PhpWord/Section/FooterTest.php @@ -74,7 +74,7 @@ class FooterTest extends \PHPUnit_Framework_TestCase { $src = \join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'images', 'earth.jpg') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'images', 'earth.jpg') ); $oFooter = new Footer(1); $element = $oFooter->addImage($src); diff --git a/Tests/PhpWord/Section/HeaderTest.php b/Tests/PhpWord/Section/HeaderTest.php index ee5a4512..270fd71c 100644 --- a/Tests/PhpWord/Section/HeaderTest.php +++ b/Tests/PhpWord/Section/HeaderTest.php @@ -70,7 +70,7 @@ class HeaderTest extends \PHPUnit_Framework_TestCase { $src = \join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'images', 'earth.jpg') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'images', 'earth.jpg') ); $oHeader = new Header(1); $element = $oHeader->addImage($src); @@ -113,7 +113,7 @@ class HeaderTest extends \PHPUnit_Framework_TestCase { $src = \join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'images', 'earth.jpg') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'images', 'earth.jpg') ); $oHeader = new Header(1); $element = $oHeader->addWatermark($src); diff --git a/Tests/PhpWord/Section/ImageTest.php b/Tests/PhpWord/Section/ImageTest.php index 931dc812..4067f218 100644 --- a/Tests/PhpWord/Section/ImageTest.php +++ b/Tests/PhpWord/Section/ImageTest.php @@ -12,7 +12,7 @@ class ImageTest extends \PHPUnit_Framework_TestCase { $src = \join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'images', 'firefox.png') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'images', 'firefox.png') ); $oImage = new Image($src); @@ -27,7 +27,7 @@ class ImageTest extends \PHPUnit_Framework_TestCase { $src = \join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'images', 'firefox.png') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'images', 'firefox.png') ); $oImage = new Image( $src, @@ -43,12 +43,12 @@ class ImageTest extends \PHPUnit_Framework_TestCase */ public function testValidImageTypes() { - new Image(PHPWORD_TESTS_DIR_ROOT . "/_files/images/mars_noext_jpg"); - new Image(PHPWORD_TESTS_DIR_ROOT . "/_files/images/mars.jpg"); - new Image(PHPWORD_TESTS_DIR_ROOT . "/_files/images/mario.gif"); - new Image(PHPWORD_TESTS_DIR_ROOT . "/_files/images/firefox.png"); - new Image(PHPWORD_TESTS_DIR_ROOT . "/_files/images/duke_nukem.bmp"); - new Image(PHPWORD_TESTS_DIR_ROOT . "/_files/images/angela_merkel.tif"); + new Image(\PHPWORD_TESTS_BASE_DIR . "/_files/images/mars_noext_jpg"); + new Image(\PHPWORD_TESTS_BASE_DIR . "/_files/images/mars.jpg"); + new Image(\PHPWORD_TESTS_BASE_DIR . "/_files/images/mario.gif"); + new Image(\PHPWORD_TESTS_BASE_DIR . "/_files/images/firefox.png"); + new Image(\PHPWORD_TESTS_BASE_DIR . "/_files/images/duke_nukem.bmp"); + new Image(\PHPWORD_TESTS_BASE_DIR . "/_files/images/angela_merkel.tif"); } /** @@ -57,7 +57,7 @@ class ImageTest extends \PHPUnit_Framework_TestCase */ public function testImageNotFound() { - new Image(PHPWORD_TESTS_DIR_ROOT . "/_files/images/thisisnotarealimage"); + new Image(\PHPWORD_TESTS_BASE_DIR . "/_files/images/thisisnotarealimage"); } /** @@ -66,14 +66,14 @@ class ImageTest extends \PHPUnit_Framework_TestCase */ public function testInvalidImageTypes() { - new Image(PHPWORD_TESTS_DIR_ROOT . "/_files/images/alexz-johnson.pcx"); + new Image(\PHPWORD_TESTS_BASE_DIR . "/_files/images/alexz-johnson.pcx"); } public function testStyle() { $oImage = new Image(\join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'images', 'earth.jpg') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'images', 'earth.jpg') ), array('width' => 210, 'height' => 210, 'align' => 'center')); $this->assertInstanceOf('PhpOffice\\PhpWord\\Style\\Image', $oImage->getStyle()); @@ -83,7 +83,7 @@ class ImageTest extends \PHPUnit_Framework_TestCase { $oImage = new Image(\join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'images', 'earth.jpg') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'images', 'earth.jpg') )); $iVal = rand(1, 1000); @@ -95,7 +95,7 @@ class ImageTest extends \PHPUnit_Framework_TestCase { $oImage = new Image(\join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'images', 'earth.jpg') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'images', 'earth.jpg') )); $oImage->setIsWatermark(true); diff --git a/Tests/PhpWord/Section/MemoryImageTest.php b/Tests/PhpWord/Section/MemoryImageTest.php index 8c28e0bf..4476badd 100644 --- a/Tests/PhpWord/Section/MemoryImageTest.php +++ b/Tests/PhpWord/Section/MemoryImageTest.php @@ -9,7 +9,7 @@ class MemoryImageTest extends \PHPUnit_Framework_TestCase { $src = \join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'images', 'firefox.png') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'images', 'firefox.png') ); $oMemoryImage = new MemoryImage($src); @@ -26,7 +26,7 @@ class MemoryImageTest extends \PHPUnit_Framework_TestCase { $src = \join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'images', 'mario.gif') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'images', 'mario.gif') ); $oMemoryImage = new MemoryImage($src); @@ -43,7 +43,7 @@ class MemoryImageTest extends \PHPUnit_Framework_TestCase { $src = \join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'images', 'earth.jpg') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'images', 'earth.jpg') ); $oMemoryImage = new MemoryImage($src); @@ -60,7 +60,7 @@ class MemoryImageTest extends \PHPUnit_Framework_TestCase { $oMemoryImage = new MemoryImage(\join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'images', 'duke_nukem.bmp') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'images', 'duke_nukem.bmp') )); $this->assertInstanceOf('PhpOffice\\PhpWord\\Section\\MemoryImage', $oMemoryImage); @@ -74,7 +74,7 @@ class MemoryImageTest extends \PHPUnit_Framework_TestCase { $oMemoryImage = new MemoryImage(\join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'images', 'earth.jpg') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'images', 'earth.jpg') ), array('width' => 210, 'height' => 210, 'align' => 'center')); $this->assertInstanceOf('PhpOffice\\PhpWord\\Style\\Image', $oMemoryImage->getStyle()); @@ -84,7 +84,7 @@ class MemoryImageTest extends \PHPUnit_Framework_TestCase { $oMemoryImage = new MemoryImage(\join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'images', 'earth.jpg') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'images', 'earth.jpg') )); $iVal = rand(1, 1000); diff --git a/Tests/PhpWord/Section/ObjectTest.php b/Tests/PhpWord/Section/ObjectTest.php index 467b76c9..cae33458 100644 --- a/Tests/PhpWord/Section/ObjectTest.php +++ b/Tests/PhpWord/Section/ObjectTest.php @@ -9,7 +9,7 @@ class ObjectTest extends \PHPUnit_Framework_TestCase { $src = \join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'documents', 'sheet.xls') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'documents', 'sheet.xls') ); $oObject = new Object($src); @@ -22,7 +22,7 @@ class ObjectTest extends \PHPUnit_Framework_TestCase { $src = \join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'xsl', 'passthrough.xsl') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'xsl', 'passthrough.xsl') ); $oObject = new Object($src); @@ -35,7 +35,7 @@ class ObjectTest extends \PHPUnit_Framework_TestCase { $src = \join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'documents', 'sheet.xls') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'documents', 'sheet.xls') ); $oObject = new Object($src, array('width' => '230px')); @@ -48,7 +48,7 @@ class ObjectTest extends \PHPUnit_Framework_TestCase { $src = \join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'documents', 'sheet.xls') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'documents', 'sheet.xls') ); $oObject = new Object($src); @@ -61,7 +61,7 @@ class ObjectTest extends \PHPUnit_Framework_TestCase { $src = \join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'documents', 'sheet.xls') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'documents', 'sheet.xls') ); $oObject = new Object($src); @@ -74,7 +74,7 @@ class ObjectTest extends \PHPUnit_Framework_TestCase { $src = \join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'documents', 'sheet.xls') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'documents', 'sheet.xls') ); $oObject = new Object($src); diff --git a/Tests/PhpWord/Section/Table/CellTest.php b/Tests/PhpWord/Section/Table/CellTest.php index b2e3937d..a328a2a8 100644 --- a/Tests/PhpWord/Section/Table/CellTest.php +++ b/Tests/PhpWord/Section/Table/CellTest.php @@ -91,7 +91,7 @@ class CellTest extends \PHPUnit_Framework_TestCase { $src = \join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'images', 'earth.jpg') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'images', 'earth.jpg') ); $oCell = new Cell('section', 1); $element = $oCell->addImage($src); @@ -104,7 +104,7 @@ class CellTest extends \PHPUnit_Framework_TestCase { $src = \join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'images', 'earth.jpg') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'images', 'earth.jpg') ); $oCell = new Cell('header', 1); $element = $oCell->addImage($src); @@ -117,7 +117,7 @@ class CellTest extends \PHPUnit_Framework_TestCase { $src = \join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'images', 'earth.jpg') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'images', 'earth.jpg') ); $oCell = new Cell('footer', 1); $element = $oCell->addImage($src); @@ -163,7 +163,7 @@ class CellTest extends \PHPUnit_Framework_TestCase { $src = \join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'documents', 'sheet.xls') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'documents', 'sheet.xls') ); $oCell = new Cell('section', 1); $element = $oCell->addObject($src); diff --git a/Tests/PhpWord/Section/TextRunTest.php b/Tests/PhpWord/Section/TextRunTest.php index adf1ffbe..a5579cde 100644 --- a/Tests/PhpWord/Section/TextRunTest.php +++ b/Tests/PhpWord/Section/TextRunTest.php @@ -77,7 +77,7 @@ class TextRunTest extends \PHPUnit_Framework_TestCase { $src = \join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'images', 'earth.jpg') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'images', 'earth.jpg') ); $oTextRun = new TextRun(); $element = $oTextRun->addImage($src); diff --git a/Tests/PhpWord/SectionTest.php b/Tests/PhpWord/SectionTest.php index 7982d4af..dc90f808 100644 --- a/Tests/PhpWord/SectionTest.php +++ b/Tests/PhpWord/SectionTest.php @@ -76,11 +76,11 @@ class SectionTest extends \PHPUnit_Framework_TestCase { $objectSource = join( DIRECTORY_SEPARATOR, - array(PHPWORD_TESTS_DIR_ROOT, '_files', 'documents', 'sheet.xls') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'documents', 'sheet.xls') ); $imageSource = join( DIRECTORY_SEPARATOR, - array(PHPWORD_TESTS_DIR_ROOT, '_files', 'images', 'PhpWord.png') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'images', 'PhpWord.png') ); $imageUrl = 'http://php.net//images/logos/php-med-trans-light.gif'; diff --git a/Tests/PhpWord/Shared/FileTest.php b/Tests/PhpWord/Shared/FileTest.php index b02cb918..197a318e 100644 --- a/Tests/PhpWord/Shared/FileTest.php +++ b/Tests/PhpWord/Shared/FileTest.php @@ -15,7 +15,7 @@ class FileTest extends \PHPUnit_Framework_TestCase */ public function testFileExists() { - $dir = join(DIRECTORY_SEPARATOR, array(PHPWORD_TESTS_DIR_ROOT, '_files', 'templates')); + $dir = join(DIRECTORY_SEPARATOR, array(\PHPWORD_TESTS_BASE_DIR, '_files', 'templates')); chdir($dir); $this->assertTrue(File::file_exists('blank.docx')); } @@ -24,7 +24,7 @@ class FileTest extends \PHPUnit_Framework_TestCase */ public function testNoFileExists() { - $dir = join(DIRECTORY_SEPARATOR, array(PHPWORD_TESTS_DIR_ROOT, '_files', 'templates')); + $dir = join(DIRECTORY_SEPARATOR, array(\PHPWORD_TESTS_BASE_DIR, '_files', 'templates')); chdir($dir); $this->assertFalse(File::file_exists('404.docx')); } @@ -34,7 +34,7 @@ class FileTest extends \PHPUnit_Framework_TestCase */ public function testRealpath() { - $dir = join(DIRECTORY_SEPARATOR, array(PHPWORD_TESTS_DIR_ROOT, '_files', 'templates')); + $dir = join(DIRECTORY_SEPARATOR, array(\PHPWORD_TESTS_BASE_DIR, '_files', 'templates')); chdir($dir); $file = 'blank.docx'; $expected = $dir . DIRECTORY_SEPARATOR . $file; diff --git a/Tests/PhpWord/Shared/FontTest.php b/Tests/PhpWord/Shared/FontTest.php index f4379900..0a662a3f 100644 --- a/Tests/PhpWord/Shared/FontTest.php +++ b/Tests/PhpWord/Shared/FontTest.php @@ -1,7 +1,7 @@ load( \join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'xsl', 'remove_tables_by_needle.xsl') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'xsl', 'remove_tables_by_needle.xsl') ) ); foreach (array('${employee.', '${scoreboard.') as $needle) { @@ -65,7 +65,7 @@ final class TemplateTest extends \PHPUnit_Framework_TestCase { $expectedDocumentFqfn = \join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'documents', 'without_table_macros.docx') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'documents', 'without_table_macros.docx') ); $actualDocumentZip = new \ZipArchive(); @@ -96,7 +96,7 @@ final class TemplateTest extends \PHPUnit_Framework_TestCase $template = new Template( \join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'templates', 'blank.docx') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'templates', 'blank.docx') ) ); @@ -104,7 +104,7 @@ final class TemplateTest extends \PHPUnit_Framework_TestCase $xslDOMDocument->load( \join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'xsl', 'passthrough.xsl') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'xsl', 'passthrough.xsl') ) ); @@ -126,7 +126,7 @@ final class TemplateTest extends \PHPUnit_Framework_TestCase $template = new Template( \join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'templates', 'corrupted_main_document_part.docx') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'templates', 'corrupted_main_document_part.docx') ) ); @@ -134,7 +134,7 @@ final class TemplateTest extends \PHPUnit_Framework_TestCase $xslDOMDocument->load( \join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'xsl', 'passthrough.xsl') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'xsl', 'passthrough.xsl') ) ); @@ -155,7 +155,7 @@ final class TemplateTest extends \PHPUnit_Framework_TestCase { $template = \join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'templates', 'clone-row.docx') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'templates', 'clone-row.docx') ); $expectedVar = array('tableHeader', 'userId', 'userName', 'userLocation'); $docName = 'clone-test-result.docx'; diff --git a/Tests/PhpWord/Writer/ODText/ContentTest.php b/Tests/PhpWord/Writer/ODText/ContentTest.php index 7ebff776..ce3a7b3b 100644 --- a/Tests/PhpWord/Writer/ODText/ContentTest.php +++ b/Tests/PhpWord/Writer/ODText/ContentTest.php @@ -1,7 +1,7 @@ assertInstanceOf('PhpOffice\\PhpWord', $object->getPhpWord()); + $this->assertInstanceOf('PhpOffice\\PhpWord\\PhpWord', $object->getPhpWord()); $this->assertInstanceOf('PhpOffice\\PhpWord\\HashTable', $object->getDrawingHashTable()); $this->assertEquals('./', $object->getDiskCachingDirectory()); @@ -52,15 +52,15 @@ class ODTextTest extends \PHPUnit_Framework_TestCase { $imageSrc = \join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'images', 'PhpWord.png') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'images', 'PhpWord.png') ); $objectSrc = \join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'documents', 'sheet.xls') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'documents', 'sheet.xls') ); $file = \join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'temp.odt') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'temp.odt') ); $phpWord = new PhpWord(); @@ -129,9 +129,9 @@ class ODTextTest extends \PHPUnit_Framework_TestCase public function testSetGetUseDiskCaching() { $object = new ODText(); - $object->setUseDiskCaching(true, PHPWORD_TESTS_DIR_ROOT); + $object->setUseDiskCaching(true, \PHPWORD_TESTS_BASE_DIR); $this->assertTrue($object->getUseDiskCaching()); - $this->assertEquals(PHPWORD_TESTS_DIR_ROOT, $object->getDiskCachingDirectory()); + $this->assertEquals(\PHPWORD_TESTS_BASE_DIR, $object->getDiskCachingDirectory()); } /** @@ -142,7 +142,7 @@ class ODTextTest extends \PHPUnit_Framework_TestCase { $dir = \join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, 'foo') + array(\PHPWORD_TESTS_BASE_DIR, 'foo') ); $object = new ODText($phpWord); diff --git a/Tests/PhpWord/Writer/RTFTest.php b/Tests/PhpWord/Writer/RTFTest.php index ecce8732..3b6cb723 100644 --- a/Tests/PhpWord/Writer/RTFTest.php +++ b/Tests/PhpWord/Writer/RTFTest.php @@ -1,7 +1,7 @@ assertInstanceOf('PhpOffice\\PhpWord', $object->getPhpWord()); + $this->assertInstanceOf('PhpOffice\\PhpWord\\PhpWord', $object->getPhpWord()); $this->assertInstanceOf('PhpOffice\\PhpWord\\HashTable', $object->getDrawingHashTable()); } @@ -65,15 +65,15 @@ class RTFTest extends \PHPUnit_Framework_TestCase { $imageSrc = \join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'images', 'PhpWord.png') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'images', 'PhpWord.png') ); $objectSrc = \join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'documents', 'sheet.xls') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'documents', 'sheet.xls') ); $file = \join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, '_files', 'temp.rtf') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'temp.rtf') ); $phpWord = new PhpWord(); diff --git a/Tests/PhpWord/Writer/Word2007/BaseTest.php b/Tests/PhpWord/Writer/Word2007/BaseTest.php index c62ba3ac..1d00e06e 100644 --- a/Tests/PhpWord/Writer/Word2007/BaseTest.php +++ b/Tests/PhpWord/Writer/Word2007/BaseTest.php @@ -1,7 +1,7 @@ 'justify', 'spaceBefore' => 120, 'spaceAfter' => 120); $imageSrc = join( DIRECTORY_SEPARATOR, - array(PHPWORD_TESTS_DIR_ROOT, '_files', 'images', 'earth.jpg') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'images', 'earth.jpg') ); $phpWord = new PhpWord(); @@ -298,7 +298,7 @@ class BaseTest extends \PHPUnit_Framework_TestCase $phpWord = new PhpWord(); $section = $phpWord->createSection(); $section->addImage( - PHPWORD_TESTS_DIR_ROOT . '/_files/images/earth.jpg', + \PHPWORD_TESTS_BASE_DIR . '/_files/images/earth.jpg', array( 'marginTop' => -1, 'marginLeft' => -1, @@ -322,7 +322,7 @@ class BaseTest extends \PHPUnit_Framework_TestCase { $imageSrc = join( DIRECTORY_SEPARATOR, - array(PHPWORD_TESTS_DIR_ROOT, '_files', 'images', 'earth.jpg') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'images', 'earth.jpg') ); $phpWord = new PhpWord(); diff --git a/Tests/PhpWord/Writer/Word2007/DocumentTest.php b/Tests/PhpWord/Writer/Word2007/DocumentTest.php index da54a7f4..056e7b55 100644 --- a/Tests/PhpWord/Writer/Word2007/DocumentTest.php +++ b/Tests/PhpWord/Writer/Word2007/DocumentTest.php @@ -1,7 +1,7 @@ save($file); $this->assertTrue(file_exists($file)); @@ -90,7 +90,7 @@ class Word2007Test extends \PHPUnit_Framework_TestCase $phpWord = new PhpWord(); $section = $phpWord->createSection(); foreach ($images as $source => $target) { - $section->addImage(PHPWORD_TESTS_DIR_ROOT . "/_files/images/{$source}"); + $section->addImage(\PHPWORD_TESTS_BASE_DIR . "/_files/images/{$source}"); } $doc = TestHelperDOCX::getDocument($phpWord); @@ -98,7 +98,7 @@ class Word2007Test extends \PHPUnit_Framework_TestCase foreach ($images as $source => $target) { $this->assertFileEquals( - PHPWORD_TESTS_DIR_ROOT . "/_files/images/{$source}", + \PHPWORD_TESTS_BASE_DIR . "/_files/images/{$source}", $mediaPath . "/section_image{$target}" ); } @@ -111,7 +111,7 @@ class Word2007Test extends \PHPUnit_Framework_TestCase public function testSetGetUseDiskCaching() { $object = new Word2007(); - $object->setUseDiskCaching(true, PHPWORD_TESTS_DIR_ROOT); + $object->setUseDiskCaching(true, \PHPWORD_TESTS_BASE_DIR); $this->assertTrue($object->getUseDiskCaching()); } @@ -124,7 +124,7 @@ class Word2007Test extends \PHPUnit_Framework_TestCase { $dir = \join( \DIRECTORY_SEPARATOR, - array(\PHPWORD_TESTS_DIR_ROOT, 'foo') + array(\PHPWORD_TESTS_BASE_DIR, 'foo') ); $object = new Word2007(); diff --git a/Tests/PhpWordTest.php b/Tests/PhpWordTest.php index ca0dded1..73841bd7 100644 --- a/Tests/PhpWordTest.php +++ b/Tests/PhpWordTest.php @@ -1,7 +1,7 @@ assertInstanceOf( @@ -150,7 +150,7 @@ class PhpWordTest extends \PHPUnit_Framework_TestCase { $templateFqfn = \join( \DIRECTORY_SEPARATOR, - array(PHPWORD_TESTS_DIR_ROOT, '_files', 'templates', 'blanks.docx') + array(\PHPWORD_TESTS_BASE_DIR, '_files', 'templates', 'blanks.docx') ); $phpWord = new PhpWord(); $phpWord->loadTemplate($templateFqfn); diff --git a/Tests/_inc/TestHelperDOCX.php b/Tests/_inc/TestHelperDOCX.php index 5345c4eb..0e63dcf8 100644 --- a/Tests/_inc/TestHelperDOCX.php +++ b/Tests/_inc/TestHelperDOCX.php @@ -1,7 +1,7 @@ - + ./Tests/PhpWord/ - ./Classes + ./src - + \ No newline at end of file diff --git a/samples/Sample_01_SimpleText.php b/samples/Sample_01_SimpleText.php index a1aafea9..34a93ecf 100755 --- a/samples/Sample_01_SimpleText.php +++ b/samples/Sample_01_SimpleText.php @@ -2,7 +2,7 @@ // Init error_reporting(E_ALL); define('EOL', (PHP_SAPI == 'cli') ? PHP_EOL : '
'); -require_once '../Classes/PhpWord.php'; +require_once '../src/PhpWord.php'; // New Word Document echo date('H:i:s') , " Create new PhpWord object" , EOL; diff --git a/samples/Sample_02_TabStops.php b/samples/Sample_02_TabStops.php index 9d3ef32f..5eef59a8 100755 --- a/samples/Sample_02_TabStops.php +++ b/samples/Sample_02_TabStops.php @@ -2,7 +2,7 @@ // Init error_reporting(E_ALL); define('EOL', (PHP_SAPI == 'cli') ? PHP_EOL : '
'); -require_once '../Classes/PhpWord.php'; +require_once '../src/PhpWord.php'; // New Word Document echo date('H:i:s') , ' Create new PhpWord object' , EOL; diff --git a/samples/Sample_03_Sections.php b/samples/Sample_03_Sections.php index 542b2d5c..e066097c 100755 --- a/samples/Sample_03_Sections.php +++ b/samples/Sample_03_Sections.php @@ -2,7 +2,7 @@ // Init error_reporting(E_ALL); define('EOL', (PHP_SAPI == 'cli') ? PHP_EOL : '
'); -require_once '../Classes/PhpWord.php'; +require_once '../src/PhpWord.php'; // New Word Document echo date('H:i:s') , ' Create new PhpWord object' , EOL; diff --git a/samples/Sample_04_Textrun.php b/samples/Sample_04_Textrun.php index c7b8c354..c0b6cf3a 100644 --- a/samples/Sample_04_Textrun.php +++ b/samples/Sample_04_Textrun.php @@ -2,7 +2,7 @@ // Init error_reporting(E_ALL); define('EOL', (PHP_SAPI == 'cli') ? PHP_EOL : '
'); -require_once '../Classes/PhpWord.php'; +require_once '../src/PhpWord.php'; // New Word Document echo date('H:i:s') , ' Create new PhpWord object' , EOL; diff --git a/samples/Sample_05_Multicolumn.php b/samples/Sample_05_Multicolumn.php index 942d851d..2095f24a 100644 --- a/samples/Sample_05_Multicolumn.php +++ b/samples/Sample_05_Multicolumn.php @@ -2,7 +2,7 @@ // Init error_reporting(E_ALL); define('EOL', (PHP_SAPI == 'cli') ? PHP_EOL : '
'); -require_once '../Classes/PhpWord.php'; +require_once '../src/PhpWord.php'; // New Word Document echo date('H:i:s') , " Create new PhpWord object" , EOL; diff --git a/samples/Sample_06_Footnote.php b/samples/Sample_06_Footnote.php index 73555a44..9fc2cc57 100755 --- a/samples/Sample_06_Footnote.php +++ b/samples/Sample_06_Footnote.php @@ -2,7 +2,7 @@ // Init error_reporting(E_ALL); define('EOL', (PHP_SAPI == 'cli') ? PHP_EOL : '
'); -require_once '../Classes/PhpWord.php'; +require_once '../src/PhpWord.php'; // New Word Document echo date('H:i:s') , " Create new PhpWord object" , EOL; diff --git a/samples/Sample_07_TemplateCloneRow.php b/samples/Sample_07_TemplateCloneRow.php index e41bffbd..f2feb155 100755 --- a/samples/Sample_07_TemplateCloneRow.php +++ b/samples/Sample_07_TemplateCloneRow.php @@ -2,7 +2,7 @@ // Init error_reporting(E_ALL); define('EOL', (PHP_SAPI == 'cli') ? PHP_EOL : '
'); -require_once '../Classes/PhpWord.php'; +require_once '../src/PhpWord.php'; // New Word document echo date('H:i:s') , " Create new PhpWord object" , EOL; diff --git a/samples/Sample_08_ParagraphPagination.php b/samples/Sample_08_ParagraphPagination.php index 757a9aa7..cb52f7f0 100644 --- a/samples/Sample_08_ParagraphPagination.php +++ b/samples/Sample_08_ParagraphPagination.php @@ -2,7 +2,7 @@ // Init error_reporting(E_ALL); define('EOL', (PHP_SAPI == 'cli') ? PHP_EOL : '
'); -require_once '../Classes/PhpWord.php'; +require_once '../src/PhpWord.php'; // New Word document echo date('H:i:s') , " Create new PhpWord object" , EOL; diff --git a/samples/Sample_09_Tables.php b/samples/Sample_09_Tables.php index 0750f35e..ec65e104 100644 --- a/samples/Sample_09_Tables.php +++ b/samples/Sample_09_Tables.php @@ -2,7 +2,7 @@ // Init error_reporting(E_ALL); define('EOL', (PHP_SAPI == 'cli') ? PHP_EOL : '
'); -require_once '../Classes/PhpWord.php'; +require_once '../src/PhpWord.php'; // New Word Document echo date('H:i:s') , ' Create new PhpWord object' , EOL; diff --git a/samples/Sample_10_EastAsianFontStyle.php b/samples/Sample_10_EastAsianFontStyle.php index 506406a1..e3d19260 100644 --- a/samples/Sample_10_EastAsianFontStyle.php +++ b/samples/Sample_10_EastAsianFontStyle.php @@ -2,7 +2,7 @@ // Init error_reporting(E_ALL); define('EOL', (PHP_SAPI == 'cli') ? PHP_EOL : '
'); -require_once '../Classes/PhpWord.php'; +require_once '../src/PhpWord.php'; // New Word Document echo date('H:i:s') , ' Create new PhpWord object' , EOL; diff --git a/samples/Sample_11_ReadWord2007.php b/samples/Sample_11_ReadWord2007.php index b5ff7cf0..3ba4905e 100644 --- a/samples/Sample_11_ReadWord2007.php +++ b/samples/Sample_11_ReadWord2007.php @@ -2,7 +2,7 @@ // Init error_reporting(E_ALL); define('EOL', (PHP_SAPI == 'cli') ? PHP_EOL : '
'); -require_once '../Classes/PhpWord.php'; +require_once '../src/PhpWord.php'; // Read contents $name = basename(__FILE__, '.php'); diff --git a/samples/Sample_12_HeaderFooter.php b/samples/Sample_12_HeaderFooter.php index d410f76e..86ff9190 100644 --- a/samples/Sample_12_HeaderFooter.php +++ b/samples/Sample_12_HeaderFooter.php @@ -2,7 +2,7 @@ // Init error_reporting(E_ALL); define('EOL', (PHP_SAPI == 'cli') ? PHP_EOL : '
'); -require_once '../Classes/PhpWord.php'; +require_once '../src/PhpWord.php'; // New Word document echo date('H:i:s') , " Create new PhpWord object" , EOL; diff --git a/samples/Sample_13_Images.php b/samples/Sample_13_Images.php index f406f4c0..744b8b37 100644 --- a/samples/Sample_13_Images.php +++ b/samples/Sample_13_Images.php @@ -6,7 +6,7 @@ // Init error_reporting(E_ALL); define('EOL', (PHP_SAPI == 'cli') ? PHP_EOL : '
'); -require_once '../Classes/PhpWord.php'; +require_once '../src/PhpWord.php'; // New Word document echo date('H:i:s'), " Create new PhpWord object", EOL; diff --git a/samples/Sample_14_ListItem.php b/samples/Sample_14_ListItem.php index b587ec63..78dca727 100644 --- a/samples/Sample_14_ListItem.php +++ b/samples/Sample_14_ListItem.php @@ -6,7 +6,7 @@ // Init error_reporting(E_ALL); define('EOL', (PHP_SAPI == 'cli') ? PHP_EOL : '
'); -require_once '../Classes/PhpWord.php'; +require_once '../src/PhpWord.php'; // New Word document echo date('H:i:s'), " Create new PhpWord object", EOL; diff --git a/samples/Sample_15_Link.php b/samples/Sample_15_Link.php index f0cc82d9..2907fc4e 100644 --- a/samples/Sample_15_Link.php +++ b/samples/Sample_15_Link.php @@ -6,7 +6,7 @@ // Init error_reporting(E_ALL); define('EOL', (PHP_SAPI == 'cli') ? PHP_EOL : '
'); -require_once '../Classes/PhpWord.php'; +require_once '../src/PhpWord.php'; // New Word document echo date('H:i:s'), " Create new PhpWord object", EOL; diff --git a/samples/Sample_16_Object.php b/samples/Sample_16_Object.php index 40dc8c6a..06206d9c 100644 --- a/samples/Sample_16_Object.php +++ b/samples/Sample_16_Object.php @@ -6,7 +6,7 @@ // Init error_reporting(E_ALL); define('EOL', (PHP_SAPI == 'cli') ? PHP_EOL : '
'); -require_once '../Classes/PhpWord.php'; +require_once '../src/PhpWord.php'; // New Word document echo date('H:i:s'), " Create new PhpWord object", EOL; diff --git a/samples/Sample_17_TitleTOC.php b/samples/Sample_17_TitleTOC.php index a083770b..a3aa36c3 100644 --- a/samples/Sample_17_TitleTOC.php +++ b/samples/Sample_17_TitleTOC.php @@ -6,7 +6,7 @@ // Init error_reporting(E_ALL); define('EOL', (PHP_SAPI == 'cli') ? PHP_EOL : '
'); -require_once '../Classes/PhpWord.php'; +require_once '../src/PhpWord.php'; // New Word document echo date('H:i:s'), " Create new PhpWord object", EOL; diff --git a/samples/Sample_18_Watermark.php b/samples/Sample_18_Watermark.php index 6f5d1eee..667b7c65 100644 --- a/samples/Sample_18_Watermark.php +++ b/samples/Sample_18_Watermark.php @@ -6,7 +6,7 @@ // Init error_reporting(E_ALL); define('EOL', (PHP_SAPI == 'cli') ? PHP_EOL : '
'); -require_once '../Classes/PhpWord.php'; +require_once '../src/PhpWord.php'; // New Word document echo date('H:i:s'), " Create new PhpWord object", EOL; diff --git a/samples/Sample_19_TextBreak.php b/samples/Sample_19_TextBreak.php index 145b8300..78f689aa 100644 --- a/samples/Sample_19_TextBreak.php +++ b/samples/Sample_19_TextBreak.php @@ -6,7 +6,7 @@ // Init error_reporting(E_ALL); define('EOL', (PHP_SAPI == 'cli') ? PHP_EOL : '
'); -require_once '../Classes/PhpWord.php'; +require_once '../src/PhpWord.php'; // New Word document echo date('H:i:s'), " Create new PhpWord object", EOL; diff --git a/src/Autoloader.php b/src/Autoloader.php new file mode 100644 index 00000000..ca762c6a --- /dev/null +++ b/src/Autoloader.php @@ -0,0 +1,64 @@ +_creator = ''; + $this->_lastModifiedBy = $this->_creator; + $this->_created = time(); + $this->_modified = time(); + $this->_title = ''; + $this->_subject = ''; + $this->_description = ''; + $this->_keywords = ''; + $this->_category = ''; + $this->_company = ''; + $this->_manager = ''; + } + + /** + * Get Creator + * + * @return string + */ + public function getCreator() + { + return $this->_creator; + } + + /** + * Set Creator + * + * @param string $pValue + * @return PhpOffice\PhpWord\DocumentProperties + */ + public function setCreator($pValue = '') + { + $this->_creator = $pValue; + return $this; + } + + /** + * Get Last Modified By + * + * @return string + */ + public function getLastModifiedBy() + { + return $this->_lastModifiedBy; + } + + /** + * Set Last Modified By + * + * @param string $pValue + * @return PhpOffice\PhpWord\DocumentProperties + */ + public function setLastModifiedBy($pValue = '') + { + $this->_lastModifiedBy = $pValue; + return $this; + } + + /** + * Get Created + * + * @return datetime + */ + public function getCreated() + { + return $this->_created; + } + + /** + * Set Created + * + * @param datetime $pValue + * @return PhpOffice\PhpWord\DocumentProperties + */ + public function setCreated($pValue = null) + { + if (is_null($pValue)) { + $pValue = time(); + } + $this->_created = $pValue; + return $this; + } + + /** + * Get Modified + * + * @return datetime + */ + public function getModified() + { + return $this->_modified; + } + + /** + * Set Modified + * + * @param datetime $pValue + * @return PhpOffice\PhpWord\DocumentProperties + */ + public function setModified($pValue = null) + { + if (is_null($pValue)) { + $pValue = time(); + } + $this->_modified = $pValue; + return $this; + } + + /** + * Get Title + * + * @return string + */ + public function getTitle() + { + return $this->_title; + } + + /** + * Set Title + * + * @param string $pValue + * @return PhpOffice\PhpWord\DocumentProperties + */ + public function setTitle($pValue = '') + { + $this->_title = $pValue; + return $this; + } + + /** + * Get Description + * + * @return string + */ + public function getDescription() + { + return $this->_description; + } + + /** + * Set Description + * + * @param string $pValue + * @return PhpOffice\PhpWord\DocumentProperties + */ + public function setDescription($pValue = '') + { + $this->_description = $pValue; + return $this; + } + + /** + * Get Subject + * + * @return string + */ + public function getSubject() + { + return $this->_subject; + } + + /** + * Set Subject + * + * @param string $pValue + * @return PhpOffice\PhpWord\DocumentProperties + */ + public function setSubject($pValue = '') + { + $this->_subject = $pValue; + return $this; + } + + /** + * Get Keywords + * + * @return string + */ + public function getKeywords() + { + return $this->_keywords; + } + + /** + * Set Keywords + * + * @param string $pValue + * @return PhpOffice\PhpWord\DocumentProperties + */ + public function setKeywords($pValue = '') + { + $this->_keywords = $pValue; + return $this; + } + + /** + * Get Category + * + * @return string + */ + public function getCategory() + { + return $this->_category; + } + + /** + * Set Category + * + * @param string $pValue + * @return PhpOffice\PhpWord\DocumentProperties + */ + public function setCategory($pValue = '') + { + $this->_category = $pValue; + return $this; + } + + /** + * Get Company + * + * @return string + */ + public function getCompany() + { + return $this->_company; + } + + /** + * Set Company + * + * @param string $pValue + * @return PhpOffice\PhpWord\DocumentProperties + */ + public function setCompany($pValue = '') + { + $this->_company = $pValue; + return $this; + } + + /** + * Get Manager + * + * @return string + */ + public function getManager() + { + return $this->_manager; + } + + /** + * Set Manager + * + * @param string $pValue + * @return PhpOffice\PhpWord\DocumentProperties + */ + public function setManager($pValue = '') + { + $this->_manager = $pValue; + return $this; + } + + /** + * Get a List of Custom Property Names + * + * @return array of string + */ + public function getCustomProperties() + { + return array_keys($this->_customProperties); + } + + /** + * Check if a Custom Property is defined + * + * @param string $propertyName + * @return boolean + */ + public function isCustomPropertySet($propertyName) + { + return isset($this->_customProperties[$propertyName]); + } + + /** + * Get a Custom Property Value + * + * @param string $propertyName + * @return string + */ + public function getCustomPropertyValue($propertyName) + { + if (isset($this->_customProperties[$propertyName])) { + return $this->_customProperties[$propertyName]['value']; + } + + } + + /** + * Get a Custom Property Type + * + * @param string $propertyName + * @return string + */ + public function getCustomPropertyType($propertyName) + { + if (isset($this->_customProperties[$propertyName])) { + return $this->_customProperties[$propertyName]['type']; + } + + } + + /** + * Set a Custom Property + * + * @param string $propertyName + * @param mixed $propertyValue + * @param string $propertyType + * 'i': Integer + * 'f': Floating Point + * 's': String + * 'd': Date/Time + * 'b': Boolean + * @return PhpOffice\PhpWord\DocumentProperties + */ + public function setCustomProperty($propertyName, $propertyValue = '', $propertyType = null) + { + if (($propertyType === null) || (!in_array($propertyType, array( + self::PROPERTY_TYPE_INTEGER, + self::PROPERTY_TYPE_FLOAT, + self::PROPERTY_TYPE_STRING, + self::PROPERTY_TYPE_DATE, + self::PROPERTY_TYPE_BOOLEAN + )))) { + if ($propertyValue === null) { + $propertyType = self::PROPERTY_TYPE_STRING; + } elseif (is_float($propertyValue)) { + $propertyType = self::PROPERTY_TYPE_FLOAT; + } elseif (is_int($propertyValue)) { + $propertyType = self::PROPERTY_TYPE_INTEGER; + } elseif (is_bool($propertyValue)) { + $propertyType = self::PROPERTY_TYPE_BOOLEAN; + } else { + $propertyType = self::PROPERTY_TYPE_STRING; + } + } + + $this->_customProperties[$propertyName] = array( + 'value' => $propertyValue, + 'type' => $propertyType + ); + return $this; + } + + /** + * Convert document propery based on type + * + * @param mixed $propertyValue + * @param string $propertyType + * @return mixed + */ + public static function convertProperty($propertyValue, $propertyType) + { + switch ($propertyType) { + case 'empty': // Empty + return ''; + break; + case 'null': // Null + return null; + break; + case 'i1': // 1-Byte Signed Integer + case 'i2': // 2-Byte Signed Integer + case 'i4': // 4-Byte Signed Integer + case 'i8': // 8-Byte Signed Integer + case 'int': // Integer + return (int) $propertyValue; + break; + case 'ui1': // 1-Byte Unsigned Integer + case 'ui2': // 2-Byte Unsigned Integer + case 'ui4': // 4-Byte Unsigned Integer + case 'ui8': // 8-Byte Unsigned Integer + case 'uint': // Unsigned Integer + return abs((int) $propertyValue); + break; + case 'r4': // 4-Byte Real Number + case 'r8': // 8-Byte Real Number + case 'decimal': // Decimal + return (float) $propertyValue; + break; + case 'lpstr': // LPSTR + case 'lpwstr': // LPWSTR + case 'bstr': // Basic String + return $propertyValue; + break; + case 'date': // Date and Time + case 'filetime': // File Time + return strtotime($propertyValue); + break; + case 'bool': // Boolean + return ($propertyValue == 'true') ? true : false; + break; + case 'cy': // Currency + case 'error': // Error Status Code + case 'vector': // Vector + case 'array': // Array + case 'blob': // Binary Blob + case 'oblob': // Binary Blob Object + case 'stream': // Binary Stream + case 'ostream': // Binary Stream Object + case 'storage': // Binary Storage + case 'ostorage': // Binary Storage Object + case 'vstream': // Binary Versioned Stream + case 'clsid': // Class ID + case 'cf': // Clipboard Data + return $propertyValue; + break; + } + + return $propertyValue; + } + + /** + * Convert document property type + * + * @param string $propertyType + * @return mixed + */ + public static function convertPropertyType($propertyType) + { + switch ($propertyType) { + case 'i1': // 1-Byte Signed Integer + case 'i2': // 2-Byte Signed Integer + case 'i4': // 4-Byte Signed Integer + case 'i8': // 8-Byte Signed Integer + case 'int': // Integer + case 'ui1': // 1-Byte Unsigned Integer + case 'ui2': // 2-Byte Unsigned Integer + case 'ui4': // 4-Byte Unsigned Integer + case 'ui8': // 8-Byte Unsigned Integer + case 'uint': // Unsigned Integer + return self::PROPERTY_TYPE_INTEGER; + break; + case 'r4': // 4-Byte Real Number + case 'r8': // 8-Byte Real Number + case 'decimal': // Decimal + return self::PROPERTY_TYPE_FLOAT; + break; + case 'empty': // Empty + case 'null': // Null + case 'lpstr': // LPSTR + case 'lpwstr': // LPWSTR + case 'bstr': // Basic String + return self::PROPERTY_TYPE_STRING; + break; + case 'date': // Date and Time + case 'filetime': // File Time + return self::PROPERTY_TYPE_DATE; + break; + case 'bool': // Boolean + return self::PROPERTY_TYPE_BOOLEAN; + break; + case 'cy': // Currency + case 'error': // Error Status Code + case 'vector': // Vector + case 'array': // Array + case 'blob': // Binary Blob + case 'oblob': // Binary Blob Object + case 'stream': // Binary Stream + case 'ostream': // Binary Stream Object + case 'storage': // Binary Storage + case 'ostorage': // Binary Storage Object + case 'vstream': // Binary Versioned Stream + case 'clsid': // Class ID + case 'cf': // Clipboard Data + return self::PROPERTY_TYPE_UNKNOWN; + break; + } + return self::PROPERTY_TYPE_UNKNOWN; + } +} diff --git a/src/Exceptions/Exception.php b/src/Exceptions/Exception.php new file mode 100644 index 00000000..72f5cfed --- /dev/null +++ b/src/Exceptions/Exception.php @@ -0,0 +1,6 @@ +addFromSource($pSource); + } + } + + /** + * Add HashTable items from source + * + * @param PhpOffice\PhpWord\IComparable[] $pSource Source array to create HashTable from + * @throws Exception + */ + public function addFromSource($pSource = null) + { + // Check if an array was passed + if ($pSource == null) { + return; + } elseif (!is_array($pSource)) { + throw new Exception('Invalid array parameter passed.'); + } + + foreach ($pSource as $item) { + $this->add($item); + } + } + + /** + * Add HashTable item + * + * @param PhpOffice\PhpWord\IComparable $pSource Item to add + * @throws Exception + */ + public function add(IComparable $pSource = null) + { + // Determine hashcode + $hashCode = null; + $hashIndex = $pSource->getHashIndex(); + if (is_null($hashIndex)) { + $hashCode = $pSource->getHashCode(); + } elseif (isset ($this->_keyMap[$hashIndex])) { + $hashCode = $this->_keyMap[$hashIndex]; + } else { + $hashCode = $pSource->getHashCode(); + } + + // Add value + if (!isset($this->_items[$hashCode])) { + $this->_items[$hashCode] = $pSource; + $index = count($this->_items) - 1; + $this->_keyMap[$index] = $hashCode; + $pSource->setHashIndex($index); + } else { + $pSource->setHashIndex($this->_items[$hashCode]->getHashIndex()); + } + } + + /** + * Remove HashTable item + * + * @param PhpOffice\PhpWord\IComparable $pSource Item to remove + * @throws Exception + */ + public function remove(IComparable $pSource = null) + { + if (isset($this->_items[$pSource->getHashCode()])) { + unset($this->_items[$pSource->getHashCode()]); + + $deleteKey = -1; + foreach ($this->_keyMap as $key => $value) { + if ($deleteKey >= 0) { + $this->_keyMap[$key - 1] = $value; + } + + if ($value == $pSource->getHashCode()) { + $deleteKey = $key; + } + } + unset($this->_keyMap[count($this->_keyMap) - 1]); + } + } + + /** + * Clear HashTable + * + */ + public function clear() + { + $this->_items = array(); + $this->_keyMap = array(); + } + + /** + * @return int + */ + public function count() + { + return count($this->_items); + } + + /** + * @param string $pHashCode + * @return int Index + */ + public function getIndexForHashCode($pHashCode = '') + { + return array_search($pHashCode, $this->_keyMap); + } + + /** + * @param int $pIndex + * @return PhpOffice\PhpWord\IComparable + */ + public function getByIndex($pIndex = 0) + { + if (isset($this->_keyMap[$pIndex])) { + return $this->getByHashCode($this->_keyMap[$pIndex]); + } + + return null; + } + + /** + * @param string $pHashCode + * @return PhpOffice\PhpWord\IComparable + * + */ + public function getByHashCode($pHashCode = '') + { + if (isset($this->_items[$pHashCode])) { + return $this->_items[$pHashCode]; + } + + return null; + } + + /** + * @return PhpOffice\PhpWord\IComparable[] + */ + public function toArray() + { + return $this->_items; + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() + { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } + } + } +} \ No newline at end of file diff --git a/src/IOFactory.php b/src/IOFactory.php new file mode 100644 index 00000000..88810f79 --- /dev/null +++ b/src/IOFactory.php @@ -0,0 +1,80 @@ +load($filename); + } +} \ No newline at end of file diff --git a/src/Media.php b/src/Media.php new file mode 100644 index 00000000..2656b3fd --- /dev/null +++ b/src/Media.php @@ -0,0 +1,347 @@ + array(), + 'embeddings' => array(), + 'links' => array() + ); + + /** + * Header Media Elements + * + * @var array + */ + private static $_headerMedia = array(); + + /** + * Footer Media Elements + * + * @var array + */ + private static $_footerMedia = array(); + + /** + * ObjectID Counter + * + * @var int + */ + private static $_objectId = 1325353440; + + /** + * Add new Section Media Element + * + * @param string $src + * @param string $type + * @param PhpOffice\PhpWord\Section\MemoryImage|null $memoryImage + * @return mixed + */ + public static function addSectionMediaElement($src, $type, MemoryImage $memoryImage = null) + { + $mediaId = md5($src); + $key = ($type === 'image') ? 'images' : 'embeddings'; + + if (!array_key_exists($mediaId, self::$_sectionMedia[$key])) { + $cImg = self::countSectionMediaElements('images'); + $cObj = self::countSectionMediaElements('embeddings'); + $rID = self::countSectionMediaElements() + 7; + + $media = array(); + + $folder = null; + $file = null; + if ($type === 'image') { + $cImg++; + //Detect if it's a memory image first by php ext and second by regex + $isMemImage = false; + if (stripos(strrev($src), strrev('.php')) === 0) { + $isMemImage = true; + } + if (!$isMemImage) { + $isMemImage = (filter_var($src, FILTER_VALIDATE_URL) !== false); + } + $extension = ''; + if ($isMemImage) { + $extension = $memoryImage->getImageExtension(); + $media['isMemImage'] = true; + $media['createfunction'] = $memoryImage->getImageCreateFunction(); + $media['imagefunction'] = $memoryImage->getImageFunction(); + } else { + $imageType = exif_imagetype($src); + if ($imageType === IMAGETYPE_JPEG) { + $extension = 'jpg'; + } elseif ($imageType === IMAGETYPE_GIF) { + $extension = 'gif'; + } elseif ($imageType === IMAGETYPE_PNG) { + $extension = 'png'; + } elseif ($imageType === IMAGETYPE_BMP) { + $extension = 'bmp'; + } elseif ($imageType === IMAGETYPE_TIFF_II || $imageType === IMAGETYPE_TIFF_MM) { + $extension = 'tif'; + } + } + + $folder = 'media'; + $file = $type . $cImg . '.' . strtolower($extension); + } elseif ($type === 'oleObject') { + $cObj++; + $folder = 'embedding'; + $file = $type . $cObj . '.bin'; + } + + $media['source'] = $src; + $media['target'] = "$folder/section_$file"; + $media['type'] = $type; + $media['rID'] = $rID; + + self::$_sectionMedia[$key][$mediaId] = $media; + + if ($type === 'oleObject') { + return array($rID, ++self::$_objectId); + } + + return $rID; + } + + if ($type === 'oleObject') { + $rID = self::$_sectionMedia[$key][$mediaId]['rID']; + return array($rID, ++self::$_objectId); + } + return self::$_sectionMedia[$key][$mediaId]['rID']; + } + + /** + * Add new Section Link Element + * + * @param string $linkSrc + * @return mixed + */ + public static function addSectionLinkElement($linkSrc) + { + $rID = self::countSectionMediaElements() + 7; + + $link = array(); + $link['target'] = $linkSrc; + $link['rID'] = $rID; + $link['type'] = 'hyperlink'; + + self::$_sectionMedia['links'][] = $link; + + return $rID; + } + + /** + * Get Section Media Elements + * + * @param string $key + * @return array + */ + public static function getSectionMediaElements($key = null) + { + if (!is_null($key)) { + return self::$_sectionMedia[$key]; + } + + $arrImages = self::$_sectionMedia['images']; + $arrObjects = self::$_sectionMedia['embeddings']; + $arrLinks = self::$_sectionMedia['links']; + return array_merge($arrImages, $arrObjects, $arrLinks); + } + + /** + * Get Section Media Elements Count + * + * @param string $key + * @return int + */ + public static function countSectionMediaElements($key = null) + { + if (!is_null($key)) { + return count(self::$_sectionMedia[$key]); + } + + $cImages = count(self::$_sectionMedia['images']); + $cObjects = count(self::$_sectionMedia['embeddings']); + $cLinks = count(self::$_sectionMedia['links']); + return ($cImages + $cObjects + $cLinks); + } + + /** + * Add new Header Media Element + * + * @param int $headerCount + * @param string $src + * @param PhpOffice\PhpWord\Section\MemoryImage|null $memoryImage + * @return int + */ + public static function addHeaderMediaElement($headerCount, $src, MemoryImage $memoryImage = null) + { + $mediaId = md5($src); + $key = 'header' . $headerCount; + + if (!array_key_exists($key, self::$_headerMedia)) { + self::$_headerMedia[$key] = array(); + } + + if (!array_key_exists($mediaId, self::$_headerMedia[$key])) { + $cImg = self::countHeaderMediaElements($key); + $rID = $cImg + 1; + + $cImg++; + $inf = pathinfo($src); + $isMemImage = (substr(strtolower($inf['extension']), 0, 3) == 'php') ? true : false; + + $media = array(); + if ($isMemImage) { + $ext = $memoryImage->getImageExtension(); + $media['isMemImage'] = true; + $media['createfunction'] = $memoryImage->getImageCreateFunction(); + $media['imagefunction'] = $memoryImage->getImageFunction(); + } else { + $ext = $inf['extension']; + if ($ext == 'jpeg') { // Office crashes when adding a jpEg Image, so rename to jpg + $ext = 'jpg'; + } + } + $file = 'image' . $cImg . '.' . strtolower($ext); + + $media['source'] = $src; + $media['target'] = 'media/' . $key . '_' . $file; + $media['type'] = 'image'; + $media['rID'] = $rID; + + self::$_headerMedia[$key][$mediaId] = $media; + + return $rID; + } + return self::$_headerMedia[$key][$mediaId]['rID']; + } + + /** + * Get Header Media Elements Count + * + * @param string $key + * @return int + */ + public static function countHeaderMediaElements($key) + { + return count(self::$_headerMedia[$key]); + } + + /** + * Get Header Media Elements + * + * @return int + */ + public static function getHeaderMediaElements() + { + return self::$_headerMedia; + } + + /** + * Add new Footer Media Element + * + * @param int $footerCount + * @param string $src + * @param PhpOffice\PhpWord\Section\MemoryImage|null $memoryImage + * @return int + */ + public static function addFooterMediaElement($footerCount, $src, MemoryImage $memoryImage = null) + { + $mediaId = md5($src); + $key = 'footer' . $footerCount; + + if (!array_key_exists($key, self::$_footerMedia)) { + self::$_footerMedia[$key] = array(); + } + + if (!array_key_exists($mediaId, self::$_footerMedia[$key])) { + $cImg = self::countFooterMediaElements($key); + $rID = $cImg + 1; + + $cImg++; + $inf = pathinfo($src); + $isMemImage = (substr(strtolower($inf['extension']), 0, 3) == 'php') ? true : false; + + $media = array(); + if ($isMemImage) { + $ext = $memoryImage->getImageExtension(); + $media['isMemImage'] = true; + $media['createfunction'] = $memoryImage->getImageCreateFunction(); + $media['imagefunction'] = $memoryImage->getImageFunction(); + } else { + $ext = $inf['extension']; + if ($ext == 'jpeg') { // Office crashes when adding a jpEg Image, so rename to jpg + $ext = 'jpg'; + } + } + $file = 'image' . $cImg . '.' . strtolower($ext); + + $media['source'] = $src; + $media['target'] = 'media/' . $key . '_' . $file; + $media['type'] = 'image'; + $media['rID'] = $rID; + + self::$_footerMedia[$key][$mediaId] = $media; + + return $rID; + } + return self::$_footerMedia[$key][$mediaId]['rID']; + } + + /** + * Get Footer Media Elements Count + * + * @param string $key + * @return int + */ + public static function countFooterMediaElements($key) + { + return count(self::$_footerMedia[$key]); + } + + /** + * Get Footer Media Elements + * + * @return int + */ + public static function getFooterMediaElements() + { + return self::$_footerMedia; + } +} diff --git a/src/PhpWord.php b/src/PhpWord.php new file mode 100644 index 00000000..e08ec041 --- /dev/null +++ b/src/PhpWord.php @@ -0,0 +1,233 @@ +_documentProperties = new DocumentProperties(); + $this->_defaultFontName = self::DEFAULT_FONT_NAME; + $this->_defaultFontSize = self::DEFAULT_FONT_SIZE; + } + + /** + * @return PhpOffice\PhpWord\DocumentProperties + */ + public function getDocumentProperties() + { + return $this->_documentProperties; + } + + /** + * @param PhpOffice\PhpWord\DocumentProperties $documentProperties + * @return PhpOffice\PhpWord + */ + public function setDocumentProperties(DocumentProperties $documentProperties) + { + $this->_documentProperties = $documentProperties; + + return $this; + } + + /** + * @param PhpOffice\PhpWord\Section\Settings $settings + * @return PhpOffice\PhpWord\Section + */ + public function createSection($settings = null) + { + $section = new Section(\count($this->_sections) + 1, $settings); + $this->_sections[] = $section; + + return $section; + } + + /** + * @return string + */ + public function getDefaultFontName() + { + return $this->_defaultFontName; + } + + /** + * @param string $fontName + */ + public function setDefaultFontName($fontName) + { + $this->_defaultFontName = $fontName; + } + + /** + * @return string + */ + public function getDefaultFontSize() + { + return $this->_defaultFontSize; + } + + /** + * @param int $fontSize + */ + public function setDefaultFontSize($fontSize) + { + $this->_defaultFontSize = $fontSize; + } + + /** + * Set default paragraph style definition to styles.xml + * + * @param array $styles Paragraph style definition + */ + public function setDefaultParagraphStyle($styles) + { + Style::setDefaultParagraphStyle($styles); + } + + /** + * Adds a paragraph style definition to styles.xml + * + * @param $styleName string + * @param $styles array + */ + public function addParagraphStyle($styleName, $styles) + { + Style::addParagraphStyle($styleName, $styles); + } + + /** + * Adds a font style definition to styles.xml + * + * @param $styleName string + * @param $styles array + */ + public function addFontStyle($styleName, $styleFont, $styleParagraph = null) + { + Style::addFontStyle($styleName, $styleFont, $styleParagraph); + } + + /** + * Adds a table style definition to styles.xml + * + * @param $styleName string + * @param $styles array + */ + public function addTableStyle($styleName, $styleTable, $styleFirstRow = null) + { + Style::addTableStyle($styleName, $styleTable, $styleFirstRow); + } + + /** + * Adds a heading style definition to styles.xml + * + * @param $titleCount int + * @param $styles array + */ + public function addTitleStyle($titleCount, $styleFont, $styleParagraph = null) + { + Style::addTitleStyle($titleCount, $styleFont, $styleParagraph); + } + + /** + * Adds a hyperlink style to styles.xml + * + * @param $styleName string + * @param $styles array + */ + public function addLinkStyle($styleName, $styles) + { + Style::addLinkStyle($styleName, $styles); + } + + /** + * @return PhpOffice\PhpWord\Section[] + */ + public function getSections() + { + return $this->_sections; + } + + /** + * @param string $filename Fully qualified filename. + * @return PhpOffice\PhpWord\Template + * @throws PhpOffice\PhpWord\Exceptions\Exception + */ + public function loadTemplate($filename) + { + if (\file_exists($filename)) { + return new Template($filename); + } else { + throw new Exception("Template file {$filename} not found."); + } + } +} \ No newline at end of file diff --git a/src/Reader/AbstractReader.php b/src/Reader/AbstractReader.php new file mode 100644 index 00000000..f92980cb --- /dev/null +++ b/src/Reader/AbstractReader.php @@ -0,0 +1,110 @@ +readDataOnly; + return true; + } + + /** + * Set read data only + * + * @param bool $pValue + * @return PhpOffice\PhpWord\Reader\IReader + */ + public function setReadDataOnly($pValue = true) + { + $this->readDataOnly = $pValue; + return $this; + } + + /** + * Open file for reading + * + * @param string $pFilename + * @return resource + * @throws Exception + */ + protected function openFile($pFilename) + { + // Check if file exists + if (!file_exists($pFilename) || !is_readable($pFilename)) { + throw new Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + // Open file + $this->fileHandle = fopen($pFilename, 'r'); + if ($this->fileHandle === false) { + throw new Exception("Could not open file " . $pFilename . " for reading."); + } + } + + /** + * Can the current IReader read the file? + * + * @param string $pFilename + * @return bool + */ + public function canRead($pFilename) + { + // Check if file exists + try { + $this->openFile($pFilename); + } catch (Exception $e) { + return false; + } + fclose($this->fileHandle); + return true; + } +} \ No newline at end of file diff --git a/src/Reader/IReader.php b/src/Reader/IReader.php new file mode 100644 index 00000000..94db13e5 --- /dev/null +++ b/src/Reader/IReader.php @@ -0,0 +1,46 @@ +open($pFilename) === true) { + // check if it is an OOXML archive + $rels = simplexml_load_string($this->getFromZipArchive($zip, "_rels/.rels")); + if ($rels !== false) { + foreach ($rels->Relationship as $rel) { + switch ($rel["Type"]) { + case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument": + if (basename($rel["Target"]) == 'document.xml') { + $return = true; + } + break; + + } + } + } + $zip->close(); + } + + return $return; + } + + /** + * @param ZipArchive $archive + * @param string $fileName + * @param bool $removeNamespace + * @return mixed + */ + public function getFromZipArchive($archive, $fileName = '', $removeNamespace = false) + { + // Root-relative paths + if (strpos($fileName, '//') !== false) { + $fileName = substr($fileName, strpos($fileName, '//') + 1); + } + $fileName = File::realpath($fileName); + + // Apache POI fixes + $contents = $archive->getFromName($fileName); + if ($contents === false) { + $contents = $archive->getFromName(substr($fileName, 1)); + } + + // Remove namespaces from elements and attributes name + if ($removeNamespace) { + $contents = preg_replace('~(canRead($pFilename)) { + return null; + } + + // Initialisations + $word = new PhpWord(); + $zip = new ZipArchive(); + $zip->open($pFilename); + + // Read properties and documents + $rels = simplexml_load_string($this->getFromZipArchive($zip, "_rels/.rels")); + foreach ($rels->Relationship as $rel) { + switch ($rel["Type"]) { + // Core properties + case "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties": + $xmlCore = simplexml_load_string($this->getFromZipArchive($zip, "{$rel['Target']}")); + if (is_object($xmlCore)) { + $xmlCore->registerXPathNamespace("dc", "http://purl.org/dc/elements/1.1/"); + $xmlCore->registerXPathNamespace("dcterms", "http://purl.org/dc/terms/"); + $xmlCore->registerXPathNamespace("cp", "http://schemas.openxmlformats.org/package/2006/metadata/core-properties"); + $docProps = $word->getDocumentProperties(); + $docProps->setCreator((string)self::arrayItem($xmlCore->xpath("dc:creator"))); + $docProps->setLastModifiedBy((string)self::arrayItem($xmlCore->xpath("cp:lastModifiedBy"))); + $docProps->setCreated(strtotime(self::arrayItem($xmlCore->xpath("dcterms:created")))); + $docProps->setModified(strtotime(self::arrayItem($xmlCore->xpath("dcterms:modified")))); + $docProps->setTitle((string)self::arrayItem($xmlCore->xpath("dc:title"))); + $docProps->setDescription((string)self::arrayItem($xmlCore->xpath("dc:description"))); + $docProps->setSubject((string)self::arrayItem($xmlCore->xpath("dc:subject"))); + $docProps->setKeywords((string)self::arrayItem($xmlCore->xpath("cp:keywords"))); + $docProps->setCategory((string)self::arrayItem($xmlCore->xpath("cp:category"))); + } + break; + // Extended properties + case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties": + $xmlCore = simplexml_load_string($this->getFromZipArchive($zip, "{$rel['Target']}")); + if (is_object($xmlCore)) { + $docProps = $word->getDocumentProperties(); + if (isset($xmlCore->Company)) { + $docProps->setCompany((string)$xmlCore->Company); + } + if (isset($xmlCore->Manager)) { + $docProps->setManager((string)$xmlCore->Manager); + } + } + break; + // Custom properties + case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties": + $xmlCore = simplexml_load_string($this->getFromZipArchive($zip, "{$rel['Target']}")); + if (is_object($xmlCore)) { + $docProps = $word->getDocumentProperties(); + foreach ($xmlCore as $xmlProperty) { + $cellDataOfficeAttributes = $xmlProperty->attributes(); + if (isset($cellDataOfficeAttributes['name'])) { + $propertyName = (string)$cellDataOfficeAttributes['name']; + $cellDataOfficeChildren = $xmlProperty->children("http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes"); + $attributeType = $cellDataOfficeChildren->getName(); + $attributeValue = (string)$cellDataOfficeChildren->{$attributeType}; + $attributeValue = DocumentProperties::convertProperty($attributeValue, $attributeType); + $attributeType = DocumentProperties::convertPropertyType($attributeType); + $docProps->setCustomProperty($propertyName, $attributeValue, $attributeType); + } + } + } + break; + // Document + case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument": + $dir = dirname($rel["Target"]); + $archive = "$dir/_rels/" . basename($rel["Target"]) . ".rels"; + $relsDoc = simplexml_load_string($this->getFromZipArchive($zip, $archive)); + $relsDoc->registerXPathNamespace("rel", "http://schemas.openxmlformats.org/package/2006/relationships"); + $xpath = self::arrayItem( + $relsDoc->xpath("rel:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles']") + ); + $xmlDoc = simplexml_load_string($this->getFromZipArchive($zip, "{$rel['Target']}", true)); + if (is_object($xmlDoc)) { + $section = $word->createSection(); + + foreach ($xmlDoc->body->children() as $elm) { + $elmName = $elm->getName(); + if ($elmName == 'p') { // Paragraph/section + // Create new section if section setting found + if ($elm->pPr->sectPr) { + $section->setSettings($this->loadSectionSettings($elm->pPr)); + $section = $word->createSection(); + continue; + } + // Has w:r? It's either text or textrun + if ($elm->r) { + // w:r = 1? It's a plain paragraph + if (count($elm->r) == 1) { + $section->addText( + $elm->r->t, + $this->loadFontStyle($elm->r) + ); + // w:r more than 1? It's a textrun + } else { + $textRun = $section->createTextRun(); + foreach ($elm->r as $r) { + $textRun->addText( + $r->t, + $this->loadFontStyle($r) + ); + } + } + // No, it's a textbreak + } else { + $section->addTextBreak(); + } + } elseif ($elmName == 'sectPr') { + // Last section setting + $section->setSettings($this->loadSectionSettings($xmlDoc->body)); + } + } + } + break; + } + } + + // Read styles + $docRels = simplexml_load_string($this->getFromZipArchive($zip, "word/_rels/document.xml.rels")); + foreach ($docRels->Relationship as $rel) { + switch ($rel["Type"]) { + case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles": + $xmlStyle = simplexml_load_string($this->getFromZipArchive($zip, "word/{$rel['Target']}", true)); + if (is_object($xmlStyle)) { + foreach ($xmlStyle->children() as $elm) { + if ($elm->getName() != 'style') { + continue; + } + $pStyle = null; + $fStyle = null; + $hasParagraphStyle = isset($elm->pPr); + $hasFontStyle = isset($elm->rPr); + $styleName = (string)$elm->name['val']; + if ($hasParagraphStyle) { + $pStyle = $this->loadParagraphStyle($elm); + if (!$hasFontStyle) { + $word->addParagraphStyle($styleName, $pStyle); + } + } + if ($hasFontStyle) { + $fStyle = $this->loadFontStyle($elm); + $word->addFontStyle($styleName, $fStyle, $pStyle); + } + } + } + break; + } + } + $zip->close(); + + return $word; + } + + /** + * Load section settings from SimpleXMLElement + * + * @param SimpleXMLElement $elm + * @return array|string|null + * + * @todo Implement gutter + */ + private function loadSectionSettings($elm) + { + if ($xml = $elm->sectPr) { + $setting = array(); + if ($xml->type) { + $setting['breakType'] = (string)$xml->type['val']; + } + if ($xml->pgSz) { + if (isset($xml->pgSz['w'])) { + $setting['pageSizeW'] = (int)$xml->pgSz['w']; + } + if (isset($xml->pgSz['h'])) { + $setting['pageSizeH'] = (int)$xml->pgSz['h']; + } + if (isset($xml->pgSz['orient'])) { + $setting['orientation'] = (string)$xml->pgSz['orient']; + } + } + if ($xml->pgMar) { + if (isset($xml->pgMar['top'])) { + $setting['topMargin'] = (int)$xml->pgMar['top']; + } + if (isset($xml->pgMar['left'])) { + $setting['leftMargin'] = (int)$xml->pgMar['left']; + } + if (isset($xml->pgMar['bottom'])) { + $setting['bottomMargin'] = (int)$xml->pgMar['bottom']; + } + if (isset($xml->pgMar['right'])) { + $setting['rightMargin'] = (int)$xml->pgMar['right']; + } + if (isset($xml->pgMar['header'])) { + $setting['headerHeight'] = (int)$xml->pgMar['header']; + } + if (isset($xml->pgMar['footer'])) { + $setting['footerHeight'] = (int)$xml->pgMar['footer']; + } + if (isset($xml->pgMar['gutter'])) { + // $setting['gutter'] = (int)$xml->pgMar['gutter']; + } + } + if ($xml->cols) { + if (isset($xml->cols['num'])) { + $setting['colsNum'] = (int)$xml->cols['num']; + } + if (isset($xml->cols['space'])) { + $setting['colsSpace'] = (int)$xml->cols['space']; + } + } + return $setting; + } + return null; + } + + /** + * Load paragraph style from SimpleXMLElement + * + * @param SimpleXMLElement $elm + * @return array|string|null + */ + private function loadParagraphStyle($elm) + { + if ($xml = $elm->pPr) { + if ($xml->pStyle) { + return (string)$xml->pStyle['val']; + } + $style = array(); + if ($xml->jc) { + $style['align'] = (string)$xml->jc['val']; + } + if ($xml->ind) { + if (isset($xml->ind->left)) { + $style['indent'] = (int)$xml->ind->left; + } + if (isset($xml->ind->hanging)) { + $style['hanging'] = (int)$xml->ind->hanging; + } + if (isset($xml->ind->line)) { + $style['spacing'] = (int)$xml->ind->line; + } + } + if ($xml->spacing) { + if (isset($xml->spacing['after'])) { + $style['spaceAfter'] = (int)$xml->spacing['after']; + } + if (isset($xml->spacing['before'])) { + $style['spaceBefore'] = (int)$xml->spacing['before']; + } + if (isset($xml->spacing['line'])) { + $style['spacing'] = (int)$xml->spacing['line']; + } + } + if ($xml->basedOn) { + $style['basedOn'] = (string)$xml->basedOn['val']; + } + if ($xml->next) { + $style['next'] = (string)$xml->next['val']; + } + if ($xml->widowControl) { + $style['widowControl'] = false; + } + if ($xml->keepNext) { + $style['keepNext'] = true; + } + if ($xml->keepLines) { + $style['keepLines'] = true; + } + if ($xml->pageBreakBefore) { + $style['pageBreakBefore'] = true; + } + return $style; + } + return null; + } + + /** + * Load font style from SimpleXMLElement + * + * @param SimpleXMLElement $elm + * @return array|string|null + */ + private function loadFontStyle($elm) + { + if ($xml = $elm->rPr) { + if ($xml->rStyle) { + return (string)$xml->rStyle['val']; + } + $style = array(); + if ($xml->rFonts) { + $style['name'] = (string)$xml->rFonts['ascii']; + } + if ($xml->sz) { + $style['size'] = (int)$xml->sz['val'] / 2; + } + if ($xml->color) { + $style['color'] = (string)$xml->color['val']; + } + if ($xml->b) { + $style['bold'] = true; + } + if ($xml->i) { + $style['italic'] = true; + } + if ($xml->u) { + $style['underline'] = (string)$xml->u['val']; + } + if ($xml->strike) { + $style['strikethrough'] = true; + } + if ($xml->highlight) { + $style['fgColor'] = (string)$xml->highlight['val']; + } + if ($xml->vertAlign) { + if ($xml->vertAlign['val'] == 'superscript') { + $style['superScript'] = true; + } else { + $style['subScript'] = true; + } + } + return $style; + } + return null; + } + + /** + * @param array $array + * @param mixed $key + * @return mixed|null + */ + private static function arrayItem($array, $key = 0) + { + return (isset($array[$key]) ? $array[$key] : null); + } +} \ No newline at end of file diff --git a/src/Section.php b/src/Section.php new file mode 100644 index 00000000..cfcb6bc9 --- /dev/null +++ b/src/Section.php @@ -0,0 +1,453 @@ +_sectionCount = $sectionCount; + $this->_settings = new Settings(); + $this->setSettings($settings); + } + + /** + * Set Section Settings + * + * @param array $settings + */ + public function setSettings($settings = null) + { + if (!is_null($settings) && is_array($settings)) { + foreach ($settings as $key => $value) { + if (substr($key, 0, 1) != '_') { + $key = '_' . $key; + } + $this->_settings->setSettingValue($key, $value); + } + } + } + + /** + * Get Section Settings + * + * @return PhpOffice\PhpWord\Section\Settings + */ + public function getSettings() + { + return $this->_settings; + } + + /** + * Add a Text Element + * + * @param string $text + * @param mixed $styleFont + * @param mixed $styleParagraph + * @return PhpOffice\PhpWord\Section\Text + */ + public function addText($text, $styleFont = null, $styleParagraph = null) + { + if (!String::IsUTF8($text)) { + $text = utf8_encode($text); + } + $text = new Text($text, $styleFont, $styleParagraph); + $this->_elementCollection[] = $text; + return $text; + } + + /** + * Add a Link Element + * + * @param string $linkSrc + * @param string $linkName + * @param mixed $styleFont + * @param mixed $styleParagraph + * @return PhpOffice\PhpWord\Section\Link + */ + public function addLink($linkSrc, $linkName = null, $styleFont = null, $styleParagraph = null) + { + if (!String::IsUTF8($linkSrc)) { + $linkSrc = utf8_encode($linkSrc); + } + if (!is_null($linkName)) { + if (!String::IsUTF8($linkName)) { + $linkName = utf8_encode($linkName); + } + } + + $link = new Link($linkSrc, $linkName, $styleFont, $styleParagraph); + $rID = Media::addSectionLinkElement($linkSrc); + $link->setRelationId($rID); + + $this->_elementCollection[] = $link; + return $link; + } + + /** + * Add a TextBreak Element + * + * @param int $count + * @param null|string|array|PhpOffice\PhpWord\Style\Font $fontStyle + * @param null|string|array|PhpOffice\PhpWord\Style\Paragraph $paragraphStyle + */ + public function addTextBreak($count = 1, $fontStyle = null, $paragraphStyle = null) + { + for ($i = 1; $i <= $count; $i++) { + $this->_elementCollection[] = new TextBreak($fontStyle, $paragraphStyle); + } + } + + /** + * Add a PageBreak Element + */ + public function addPageBreak() + { + $this->_elementCollection[] = new PageBreak(); + } + + /** + * Add a Table Element + * + * @param mixed $style + * @return PhpOffice\PhpWord\Section\Table + */ + public function addTable($style = null) + { + $table = new Table('section', $this->_sectionCount, $style); + $this->_elementCollection[] = $table; + return $table; + } + + /** + * Add a ListItem Element + * + * @param string $text + * @param int $depth + * @param mixed $styleFont + * @param mixed $styleList + * @param mixed $styleParagraph + * @return PhpOffice\PhpWord\Section\ListItem + */ + public function addListItem($text, $depth = 0, $styleFont = null, $styleList = null, $styleParagraph = null) + { + if (!String::IsUTF8($text)) { + $text = utf8_encode($text); + } + $listItem = new ListItem($text, $depth, $styleFont, $styleList, $styleParagraph); + $this->_elementCollection[] = $listItem; + return $listItem; + } + + /** + * Add a OLE-Object Element + * + * @param string $src + * @param mixed $style + * @return PhpOffice\PhpWord\Section\Object + * @throws Exception + */ + public function addObject($src, $style = null) + { + $object = new Object($src, $style); + + if (!is_null($object->getSource())) { + $inf = pathinfo($src); + $ext = $inf['extension']; + if (strlen($ext) == 4 && strtolower(substr($ext, -1)) == 'x') { + $ext = substr($ext, 0, -1); + } + + $iconSrc = \PHPWORD_BASE_DIR . '_staticDocParts/'; + if (!file_exists($iconSrc . '_' . $ext . '.png')) { + $iconSrc = $iconSrc . '_default.png'; + } else { + $iconSrc .= '_' . $ext . '.png'; + } + + $rIDimg = Media::addSectionMediaElement($iconSrc, 'image'); + $data = Media::addSectionMediaElement($src, 'oleObject'); + $rID = $data[0]; + $objectId = $data[1]; + + $object->setRelationId($rID); + $object->setObjectId($objectId); + $object->setImageRelationId($rIDimg); + + $this->_elementCollection[] = $object; + return $object; + } + throw new Exception('Source does not exist or unsupported object type.'); + } + + /** + * Add a Image Element + * + * @param string $src + * @param mixed $style + * @return PhpOffice\PhpWord\Section\Image + * @throws Exception + */ + public function addImage($src, $style = null) + { + $image = new Image($src, $style); + + if (!is_null($image->getSource())) { + $rID = Media::addSectionMediaElement($src, 'image'); + $image->setRelationId($rID); + + $this->_elementCollection[] = $image; + return $image; + } + throw new Exception('Source does not exist or unsupported image type.'); + } + + /** + * Add a by PHP created Image Element + * + * @param string $link + * @param mixed $style + * @return PhpOffice\PhpWord\Section\MemoryImage + * @throws Exception + */ + public function addMemoryImage($link, $style = null) + { + $memoryImage = new MemoryImage($link, $style); + if (!is_null($memoryImage->getSource())) { + $rID = Media::addSectionMediaElement($link, 'image', $memoryImage); + $memoryImage->setRelationId($rID); + + $this->_elementCollection[] = $memoryImage; + return $memoryImage; + } + throw new Exception('Unsupported image type.'); + } + + /** + * Add a Table-of-Contents Element + * + * @param mixed $styleFont + * @param mixed $styleTOC + * @return PhpOffice\PhpWord\TOC + */ + public function addTOC($styleFont = null, $styleTOC = null) + { + $toc = new TOC($styleFont, $styleTOC); + $this->_elementCollection[] = $toc; + return $toc; + } + + /** + * Add a Title Element + * + * @param string $text + * @param int $depth + * @return PhpOffice\PhpWord\Section\Title + */ + public function addTitle($text, $depth = 1) + { + if (!String::IsUTF8($text)) { + $text = utf8_encode($text); + } + $styles = Style::getStyles(); + if (array_key_exists('Heading_' . $depth, $styles)) { + $style = 'Heading' . $depth; + } else { + $style = null; + } + + $title = new Title($text, $depth, $style); + + $data = TOC::addTitle($text, $depth); + $anchor = $data[0]; + $bookmarkId = $data[1]; + + $title->setAnchor($anchor); + $title->setBookmarkId($bookmarkId); + + $this->_elementCollection[] = $title; + return $title; + } + + /** + * Create a new TextRun + * + * @param mixed $styleParagraph + * @return PhpOffice\PhpWord\Section\TextRun + */ + public function createTextRun($styleParagraph = null) + { + $textRun = new TextRun($styleParagraph); + $this->_elementCollection[] = $textRun; + return $textRun; + } + + /** + * Get all Elements + * + * @return array + */ + public function getElements() + { + return $this->_elementCollection; + } + + /** + * Create a new Header + * + * @return PhpOffice\PhpWord\Section\Header + */ + public function createHeader() + { + $header = new Header($this->_sectionCount); + $this->_headers[] = $header; + return $header; + } + + /** + * Get Headers + * + * @return array + */ + public function getHeaders() + { + return $this->_headers; + } + + /** + * Is there a header for this section that is for the first page only? + * + * If any of the Header instances have a type of Header::FIRST then this method returns true. + * False otherwise. + * + * @return Boolean + */ + public function hasDifferentFirstPage() + { + $value = array_filter($this->_headers, function (Header &$header) { + return $header->getType() == Header::FIRST; + }); + return count($value) > 0; + } + + /** + * Create a new Footer + * + * @return PhpOffice\PhpWord\Section\Footer + */ + public function createFooter() + { + $footer = new Footer($this->_sectionCount); + $this->_footer = $footer; + return $footer; + } + + /** + * Get Footer + * + * @return PhpOffice\PhpWord\Section\Footer + */ + public function getFooter() + { + return $this->_footer; + } + + /** + * Create a new Footnote Element + * + * @param mixed $styleParagraph + * @return PhpOffice\PhpWord\Section\Footnote + */ + public function createFootnote($styleParagraph = null) + { + $footnote = new Footnote($styleParagraph); + $refID = Footnote::addFootnoteElement($footnote); + $footnote->setReferenceId($refID); + $this->_elementCollection[] = $footnote; + return $footnote; + } +} \ No newline at end of file diff --git a/src/Section/Footer.php b/src/Section/Footer.php new file mode 100644 index 00000000..8c88bd84 --- /dev/null +++ b/src/Section/Footer.php @@ -0,0 +1,217 @@ +_footerCount = $sectionCount; + } + + /** + * Add a Text Element + * + * @param string $text + * @param mixed $styleFont + * @param mixed $styleParagraph + * @return PhpOffice\PhpWord\Section\Text + */ + public function addText($text, $styleFont = null, $styleParagraph = null) + { + if (!String::IsUTF8($text)) { + $text = utf8_encode($text); + } + $text = new Text($text, $styleFont, $styleParagraph); + $this->_elementCollection[] = $text; + return $text; + } + + /** + * Add TextBreak + * + * @param int $count + * @param null|string|array|PhpOffice\PhpWord\Style\Font $fontStyle + * @param null|string|array|PhpOffice\PhpWord\Style\Paragraph $paragraphStyle + */ + public function addTextBreak($count = 1, $fontStyle = null, $paragraphStyle = null) + { + for ($i = 1; $i <= $count; $i++) { + $this->_elementCollection[] = new TextBreak($fontStyle, $paragraphStyle); + } + } + + /** + * Create a new TextRun + * + * @return PhpOffice\PhpWord\Section\TextRun + */ + public function createTextRun($styleParagraph = null) + { + $textRun = new TextRun($styleParagraph); + $this->_elementCollection[] = $textRun; + return $textRun; + } + + /** + * Add a Table Element + * + * @param mixed $style + * @return PhpOffice\PhpWord\Section\Table + */ + public function addTable($style = null) + { + $table = new Table('footer', $this->_footerCount, $style); + $this->_elementCollection[] = $table; + return $table; + } + + /** + * Add a Image Element + * + * @param string $src + * @param mixed $style + * @return Image + */ + public function addImage($src, $style = null) + { + $image = new Image($src, $style); + + if (!is_null($image->getSource())) { + $rID = Media::addFooterMediaElement($this->_footerCount, $src); + $image->setRelationId($rID); + + $this->_elementCollection[] = $image; + return $image; + } else { + throw new Exception('Src does not exist or invalid image type.'); + } + } + + /** + * Add a by PHP created Image Element + * + * @param string $link + * @param mixed $style + * @return PhpOffice\PhpWord\Section\MemoryImage + */ + public function addMemoryImage($link, $style = null) + { + $memoryImage = new MemoryImage($link, $style); + if (!is_null($memoryImage->getSource())) { + $rID = Media::addFooterMediaElement($this->_footerCount, $link, $memoryImage); + $memoryImage->setRelationId($rID); + + $this->_elementCollection[] = $memoryImage; + return $memoryImage; + } else { + throw new Exception('Unsupported image type.'); + } + } + + /** + * Add a PreserveText Element + * + * @param string $text + * @param mixed $styleFont + * @param mixed $styleParagraph + * @return PhpOffice\PhpWord\Section\Footer\PreserveText + */ + public function addPreserveText($text, $styleFont = null, $styleParagraph = null) + { + if (!String::IsUTF8($text)) { + $text = utf8_encode($text); + } + $ptext = new PreserveText($text, $styleFont, $styleParagraph); + $this->_elementCollection[] = $ptext; + return $ptext; + } + + /** + * Get Footer Relation ID + */ + public function getRelationId() + { + return $this->_rId; + } + + /** + * Set Footer Relation ID + * + * @param int $rId + */ + public function setRelationId($rId) + { + $this->_rId = $rId; + } + + /** + * Get all Footer Elements + * @return array + */ + public function getElements() + { + return $this->_elementCollection; + } + + /** + * Get Footer Count + */ + public function getFooterCount() + { + return $this->_footerCount; + } +} diff --git a/src/Section/Footer/PreserveText.php b/src/Section/Footer/PreserveText.php new file mode 100644 index 00000000..fa9f8a86 --- /dev/null +++ b/src/Section/Footer/PreserveText.php @@ -0,0 +1,130 @@ +_styleFont = new Font('text'); + + foreach ($styleFont as $key => $value) { + if (substr($key, 0, 1) != '_') { + $key = '_' . $key; + } + $this->_styleFont->setStyleValue($key, $value); + } + } else { + $this->_styleFont = $styleFont; + } + + // Set paragraph style + if (is_array($styleParagraph)) { + $this->_styleParagraph = new Paragraph(); + + foreach ($styleParagraph as $key => $value) { + if (substr($key, 0, 1) != '_') { + $key = '_' . $key; + } + $this->_styleParagraph->setStyleValue($key, $value); + } + } else { + $this->_styleParagraph = $styleParagraph; + } + + $matches = preg_split('/({.*?})/', $text, null, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); + if (isset($matches[0])) { + $this->_text = $matches[0]; + } + + return $this; + } + + /** + * Get Text style + * + * @return PhpOffice\PhpWord\Style\Font + */ + public function getFontStyle() + { + return $this->_styleFont; + } + + /** + * Get Paragraph style + * + * @return PhpOffice\PhpWord\Style\Paragraph + */ + public function getParagraphStyle() + { + return $this->_styleParagraph; + } + + /** + * Get Text content + * + * @return string + */ + public function getText() + { + return $this->_text; + } +} diff --git a/src/Section/Footnote.php b/src/Section/Footnote.php new file mode 100644 index 00000000..e5b6e6d8 --- /dev/null +++ b/src/Section/Footnote.php @@ -0,0 +1,151 @@ +_elementCollection = array(); + + // Set paragraph style + if (is_array($styleParagraph)) { + $this->_styleParagraph = new Paragraph(); + + foreach ($styleParagraph as $key => $value) { + if (substr($key, 0, 1) != '_') { + $key = '_' . $key; + } + $this->_styleParagraph->setStyleValue($key, $value); + } + } else { + $this->_styleParagraph = $styleParagraph; + } + } + + + /** + * Add a Text Element + * + * @var string $text + * @var mixed $styleFont + * @return PhpOffice\PhpWord\Section\Text + */ + public function addText($text = null, $styleFont = null) + { + $givenText = $text; + $text = new Text($givenText, $styleFont); + $this->_elementCollection[] = $text; + return $text; + } + + /** + * Add a Link Element + * + * @param string $linkSrc + * @param string $linkName + * @param mixed $styleFont + * @return PhpOffice\PhpWord\Section\Link + */ + public function addLink($linkSrc, $linkName = null, $styleFont = null) + { + + $link = new Link($linkSrc, $linkName, $styleFont); + $rID = PhpOffice\PhpWord\Footnote::addFootnoteLinkElement($linkSrc); + $link->setRelationId($rID); + + $this->_elementCollection[] = $link; + return $link; + } + + /** + * Get Footnote content + * + * @return array + */ + public function getElements() + { + return $this->_elementCollection; + } + + /** + * Get Paragraph style + * + * @return PhpOffice\PhpWord\Style\Paragraph + */ + public function getParagraphStyle() + { + return $this->_styleParagraph; + } + + /** + * Get Footnote Reference ID + * + * @return int + */ + public function getReferenceId() + { + return $this->_refId; + } + + /** + * Set Footnote Reference ID + * + * @param int $refId + */ + public function setReferenceId($refId) + { + $this->_refId = $refId; + } +} diff --git a/src/Section/Header.php b/src/Section/Header.php new file mode 100644 index 00000000..6067945b --- /dev/null +++ b/src/Section/Header.php @@ -0,0 +1,299 @@ +_headerCount = $sectionCount; + } + + /** + * Add a Text Element + * + * @param string $text + * @param mixed $styleFont + * @param mixed $styleParagraph + * @return PhpOffice\PhpWord\Section\Text + */ + public function addText($text, $styleFont = null, $styleParagraph = null) + { + if (!String::IsUTF8($text)) { + $text = utf8_encode($text); + } + $text = new Text($text, $styleFont, $styleParagraph); + $this->_elementCollection[] = $text; + return $text; + } + + /** + * Add TextBreak + * + * @param int $count + * @param null|string|array|PhpOffice\PhpWord\Style\Font $fontStyle + * @param null|string|array|PhpOffice\PhpWord\Style\Paragraph $paragraphStyle + */ + public function addTextBreak($count = 1, $fontStyle = null, $paragraphStyle = null) + { + for ($i = 1; $i <= $count; $i++) { + $this->_elementCollection[] = new TextBreak($fontStyle, $paragraphStyle); + } + } + + /** + * Create a new TextRun + * + * @return PhpOffice\PhpWord\Section\TextRun + */ + public function createTextRun($styleParagraph = null) + { + $textRun = new TextRun($styleParagraph); + $this->_elementCollection[] = $textRun; + return $textRun; + } + + /** + * Add a Table Element + * + * @param mixed $style + * @return PhpOffice\PhpWord\Section\Table + */ + public function addTable($style = null) + { + $table = new Table('header', $this->_headerCount, $style); + $this->_elementCollection[] = $table; + return $table; + } + + /** + * Add a Image Element + * + * @param string $src + * @param mixed $style + * @return PhpOffice\PhpWord\Section\Image + */ + public function addImage($src, $style = null) + { + $image = new Image($src, $style); + + if (!is_null($image->getSource())) { + $rID = Media::addHeaderMediaElement($this->_headerCount, $src); + $image->setRelationId($rID); + + $this->_elementCollection[] = $image; + return $image; + } else { + throw new Exception('Src does not exist or invalid image type.'); + } + } + + /** + * Add a by PHP created Image Element + * + * @param string $link + * @param mixed $style + * @return PhpOffice\PhpWord\Section\MemoryImage + */ + public function addMemoryImage($link, $style = null) + { + $memoryImage = new MemoryImage($link, $style); + if (!is_null($memoryImage->getSource())) { + $rID = Media::addHeaderMediaElement($this->_headerCount, $link, $memoryImage); + $memoryImage->setRelationId($rID); + + $this->_elementCollection[] = $memoryImage; + return $memoryImage; + } else { + throw new Exception('Unsupported image type.'); + } + } + + /** + * Add a PreserveText Element + * + * @param string $text + * @param mixed $styleFont + * @param mixed $styleParagraph + * @return PhpOffice\PhpWord\Section\Footer\PreserveText + */ + public function addPreserveText($text, $styleFont = null, $styleParagraph = null) + { + if (!String::IsUTF8($text)) { + $text = utf8_encode($text); + } + $ptext = new PreserveText($text, $styleFont, $styleParagraph); + $this->_elementCollection[] = $ptext; + return $ptext; + } + + /** + * Add a Watermark Element + * + * @param string $src + * @param mixed $style + * @return PhpOffice\PhpWord\Section\Image + */ + public function addWatermark($src, $style = null) + { + $image = new Image($src, $style, true); + + if (!is_null($image->getSource())) { + $rID = Media::addHeaderMediaElement($this->_headerCount, $src); + $image->setRelationId($rID); + + $this->_elementCollection[] = $image; + return $image; + } else { + throw new Exception('Src does not exist or invalid image type.'); + } + } + + /** + * Get Header Relation ID + */ + public function getRelationId() + { + return $this->_rId; + } + + /** + * Set Header Relation ID + * + * @param int $rId + */ + public function setRelationId($rId) + { + $this->_rId = $rId; + } + + /** + * Get all Header Elements + */ + public function getElements() + { + return $this->_elementCollection; + } + + /** + * Get Header Count + */ + public function getHeaderCount() + { + return $this->_headerCount; + } + + /** + * Get Header Type + */ + public function getType() + { + return $this->_type; + } + + /** + * Reset back to default + */ + public function resetType() + { + return $this->_type = self::AUTO; + } + + /** + * First page only header + */ + public function firstPage() + { + return $this->_type = self::FIRST; + } + + /** + * Even numbered Pages only + */ + public function evenPage() + { + return $this->_type = self::EVEN; + } +} diff --git a/src/Section/Image.php b/src/Section/Image.php new file mode 100644 index 00000000..8762e8ca --- /dev/null +++ b/src/Section/Image.php @@ -0,0 +1,177 @@ +_src = $src; + $this->_isWatermark = $isWatermark; + $this->_style = new PhpOffice\PhpWord\Style\Image(); + + if (!is_null($style) && is_array($style)) { + foreach ($style as $key => $value) { + if (substr($key, 0, 1) != '_') { + $key = '_' . $key; + } + $this->_style->setStyleValue($key, $value); + } + } + + if (isset($style['wrappingStyle'])) { + $this->_style->setWrappingStyle($style['wrappingStyle']); + } + + if ($this->_style->getWidth() == null && $this->_style->getHeight() == null) { + $imgData = getimagesize($this->_src); + $this->_style->setWidth($imgData[0]); + $this->_style->setHeight($imgData[1]); + } + } + + /** + * Get Image style + * + * @return PhpOffice\PhpWord\Style\Image + */ + public function getStyle() + { + return $this->_style; + } + + /** + * Get Image Relation ID + * + * @return int + */ + public function getRelationId() + { + return $this->_rId; + } + + /** + * Set Image Relation ID + * + * @param int $rId + */ + public function setRelationId($rId) + { + $this->_rId = $rId; + } + + /** + * Get Image Source + * + * @return string + */ + public function getSource() + { + return $this->_src; + } + + /** + * Get Image Media ID + * + * @return string + */ + public function getMediaId() + { + return md5($this->_src); + } + + /** + * Get IsWatermark + * + * @return int + */ + public function getIsWatermark() + { + return $this->_isWatermark; + } + + /** + * Set IsWatermark + * + * @param bool $pValue + */ + public function setIsWatermark($pValue) + { + $this->_isWatermark = $pValue; + } +} diff --git a/src/Section/Link.php b/src/Section/Link.php new file mode 100644 index 00000000..5c3cc9fe --- /dev/null +++ b/src/Section/Link.php @@ -0,0 +1,174 @@ +_linkSrc = $linkSrc; + $this->_linkName = $linkName; + + // Set font style + if (is_array($styleFont)) { + $this->_styleFont = new Font('text'); + + foreach ($styleFont as $key => $value) { + if (substr($key, 0, 1) != '_') { + $key = '_' . $key; + } + $this->_styleFont->setStyleValue($key, $value); + } + } else { + $this->_styleFont = $styleFont; + } + + // Set paragraph style + if (is_array($styleParagraph)) { + $this->_styleParagraph = new Paragraph(); + + foreach ($styleParagraph as $key => $value) { + if (substr($key, 0, 1) != '_') { + $key = '_' . $key; + } + $this->_styleParagraph->setStyleValue($key, $value); + } + } else { + $this->_styleParagraph = $styleParagraph; + } + + return $this; + } + + /** + * Get Link Relation ID + * + * @return int + */ + public function getRelationId() + { + return $this->_rId; + } + + /** + * Set Link Relation ID + * + * @param int $rId + */ + public function setRelationId($rId) + { + $this->_rId = $rId; + } + + /** + * Get Link source + * + * @return string + */ + public function getLinkSrc() + { + return $this->_linkSrc; + } + + /** + * Get Link name + * + * @return string + */ + public function getLinkName() + { + return $this->_linkName; + } + + /** + * Get Text style + * + * @return PhpOffice\PhpWord\Style\Font + */ + public function getFontStyle() + { + return $this->_styleFont; + } + + /** + * Get Paragraph style + * + * @return PhpOffice\PhpWord\Style\Paragraph + */ + public function getParagraphStyle() + { + return $this->_styleParagraph; + } +} diff --git a/src/Section/ListItem.php b/src/Section/ListItem.php new file mode 100644 index 00000000..2aaf4c34 --- /dev/null +++ b/src/Section/ListItem.php @@ -0,0 +1,101 @@ +_style = new PhpOffice\PhpWord\Style\ListItem(); + $this->_textObject = new Text($text, $styleFont, $styleParagraph); + $this->_depth = $depth; + + if (!is_null($styleList) && is_array($styleList)) { + foreach ($styleList as $key => $value) { + if (substr($key, 0, 1) != '_') { + $key = '_' . $key; + } + $this->_style->setStyleValue($key, $value); + } + } + } + + /** + * Get ListItem style + */ + public function getStyle() + { + return $this->_style; + } + + /** + * Get ListItem TextRun + */ + public function getTextObject() + { + return $this->_textObject; + } + + /** + * Get ListItem depth + */ + public function getDepth() + { + return $this->_depth; + } +} diff --git a/src/Section/MemoryImage.php b/src/Section/MemoryImage.php new file mode 100644 index 00000000..4d81ee87 --- /dev/null +++ b/src/Section/MemoryImage.php @@ -0,0 +1,233 @@ +_imageType = $imgData['mime']; + + $_supportedImageTypes = array('image/jpeg', 'image/gif', 'image/png'); + + if (in_array($this->_imageType, $_supportedImageTypes)) { + $this->_src = $src; + $this->_style = new Image(); + + if (!is_null($style) && is_array($style)) { + foreach ($style as $key => $value) { + if (substr($key, 0, 1) != '_') { + $key = '_' . $key; + } + $this->_style->setStyleValue($key, $value); + } + } + + if ($this->_style->getWidth() == null && $this->_style->getHeight() == null) { + $this->_style->setWidth($imgData[0]); + $this->_style->setHeight($imgData[1]); + } + + $this->_setFunctions(); + } + } + + /** + * Set Functions + */ + private function _setFunctions() + { + switch ($this->_imageType) { + case 'image/png': + $this->_imageCreateFunc = 'imagecreatefrompng'; + $this->_imageFunc = 'imagepng'; + $this->_imageExtension = 'png'; + break; + case 'image/gif': + $this->_imageCreateFunc = 'imagecreatefromgif'; + $this->_imageFunc = 'imagegif'; + $this->_imageExtension = 'gif'; + break; + case 'image/jpeg': + case 'image/jpg': + $this->_imageCreateFunc = 'imagecreatefromjpeg'; + $this->_imageFunc = 'imagejpeg'; + $this->_imageExtension = 'jpg'; + break; + } + } + + /** + * Get Image style + * + * @return PhpOffice\PhpWord\Style\Image + */ + public function getStyle() + { + return $this->_style; + } + + /** + * Get Image Relation ID + * + * @return int + */ + public function getRelationId() + { + return $this->_rId; + } + + /** + * Set Image Relation ID + * + * @param int $rId + */ + public function setRelationId($rId) + { + $this->_rId = $rId; + } + + /** + * Get Image Source + * + * @return string + */ + public function getSource() + { + return $this->_src; + } + + /** + * Get Image Media ID + * + * @return string + */ + public function getMediaId() + { + return md5($this->_src); + } + + /** + * Get Image Type + * + * @return string + */ + public function getImageType() + { + return $this->_imageType; + } + + /** + * Get Image Create Function + * + * @return string + */ + public function getImageCreateFunction() + { + return $this->_imageCreateFunc; + } + + /** + * Get Image Function + * + * @return string + */ + public function getImageFunction() + { + return $this->_imageFunc; + } + + /** + * Get Image Extension + * + * @return string + */ + public function getImageExtension() + { + return $this->_imageExtension; + } +} diff --git a/src/Section/Object.php b/src/Section/Object.php new file mode 100644 index 00000000..2569478a --- /dev/null +++ b/src/Section/Object.php @@ -0,0 +1,179 @@ +_src = $src; + $this->_style = new Image(); + + if (!is_null($style) && is_array($style)) { + foreach ($style as $key => $value) { + if (substr($key, 0, 1) != '_') { + $key = '_' . $key; + } + $this->_style->setStyleValue($key, $value); + } + } + + return $this; + } else { + return false; + } + } + + /** + * Get Image style + * + * @return PhpOffice\PhpWord\Style\Image + */ + public function getStyle() + { + return $this->_style; + } + + /** + * Get Source + * + * @return string + */ + public function getSource() + { + return $this->_src; + } + + /** + * Get Object Relation ID + * + * @return int + */ + public function getRelationId() + { + return $this->_rId; + } + + /** + * Set Object Relation ID + * + * @param int $rId + */ + public function setRelationId($rId) + { + $this->_rId = $rId; + } + + /** + * Get Image Relation ID + * + * @return int + */ + public function getImageRelationId() + { + return $this->_rIdImg; + } + + /** + * Set Image Relation ID + * + * @param int $rId + */ + public function setImageRelationId($rId) + { + $this->_rIdImg = $rId; + } + + /** + * Get Object ID + * + * @return int + */ + public function getObjectId() + { + return $this->_objId; + } + + /** + * Set Object ID + * + * @param int $objId + */ + public function setObjectId($objId) + { + $this->_objId = $objId; + } +} diff --git a/src/Section/PageBreak.php b/src/Section/PageBreak.php new file mode 100644 index 00000000..ebf7f31f --- /dev/null +++ b/src/Section/PageBreak.php @@ -0,0 +1,38 @@ +_orientation = null; + $this->_marginTop = 1418; + $this->_marginLeft = 1418; + $this->_marginRight = 1418; + $this->_marginBottom = 1134; + $this->_pageSizeW = $this->_defaultPageSizeW; + $this->_pageSizeH = $this->_defaultPageSizeH; + $this->_borderTopSize = null; + $this->_borderTopColor = null; + $this->_borderLeftSize = null; + $this->_borderLeftColor = null; + $this->_borderRightSize = null; + $this->_borderRightColor = null; + $this->_borderBottomSize = null; + $this->_borderBottomColor = null; + $this->headerHeight = 720; // set default header and footer to 720 twips (.5 inches) + $this->footerHeight = 720; + $this->_colsNum = 1; + $this->_colsSpace = 720; + $this->_breakType = null; + } + + /** + * Set Setting Value + * + * @param string $key + * @param string $value + */ + public function setSettingValue($key, $value) + { + if ($key == '_orientation' && $value == 'landscape') { + $this->setLandscape(); + } elseif ($key == '_orientation' && is_null($value)) { + $this->setPortrait(); + } elseif ($key == '_borderSize') { + $this->setBorderSize($value); + } elseif ($key == '_borderColor') { + $this->setBorderColor($value); + } else { + $this->$key = $value; + } + } + + /** + * Get Margin Top + * + * @return int + */ + public function getMarginTop() + { + return $this->_marginTop; + } + + /** + * Set Margin Top + * + * @param int $pValue + */ + public function setMarginTop($pValue = '') + { + $this->_marginTop = $pValue; + return $this; + } + + /** + * Get Margin Left + * + * @return int + */ + public function getMarginLeft() + { + return $this->_marginLeft; + } + + /** + * Set Margin Left + * + * @param int $pValue + */ + public function setMarginLeft($pValue = '') + { + $this->_marginLeft = $pValue; + return $this; + } + + /** + * Get Margin Right + * + * @return int + */ + public function getMarginRight() + { + return $this->_marginRight; + } + + /** + * Set Margin Right + * + * @param int $pValue + */ + public function setMarginRight($pValue = '') + { + $this->_marginRight = $pValue; + return $this; + } + + /** + * Get Margin Bottom + * + * @return int + */ + public function getMarginBottom() + { + return $this->_marginBottom; + } + + /** + * Set Margin Bottom + * + * @param int $pValue + */ + public function setMarginBottom($pValue = '') + { + $this->_marginBottom = $pValue; + return $this; + } + + /** + * Set Landscape Orientation + */ + public function setLandscape() + { + $this->_orientation = 'landscape'; + $this->_pageSizeW = $this->_defaultPageSizeH; + $this->_pageSizeH = $this->_defaultPageSizeW; + } + + /** + * Set Portrait Orientation + */ + public function setPortrait() + { + $this->_orientation = null; + $this->_pageSizeW = $this->_defaultPageSizeW; + $this->_pageSizeH = $this->_defaultPageSizeH; + } + + /** + * Get Page Size Width + * + * @return int + */ + public function getPageSizeW() + { + return $this->_pageSizeW; + } + + /** + * Get Page Size Height + * + * @return int + */ + public function getPageSizeH() + { + return $this->_pageSizeH; + } + + /** + * Get Page Orientation + * + * @return string + */ + public function getOrientation() + { + return $this->_orientation; + } + + /** + * Set Border Size + * + * @param int $pValue + */ + public function setBorderSize($pValue = null) + { + $this->_borderTopSize = $pValue; + $this->_borderLeftSize = $pValue; + $this->_borderRightSize = $pValue; + $this->_borderBottomSize = $pValue; + } + + /** + * Get Border Size + * + * @return array + */ + public function getBorderSize() + { + $t = $this->getBorderTopSize(); + $l = $this->getBorderLeftSize(); + $r = $this->getBorderRightSize(); + $b = $this->getBorderBottomSize(); + + return array($t, $l, $r, $b); + } + + /** + * Set Border Color + * + * @param string $pValue + */ + public function setBorderColor($pValue = null) + { + $this->_borderTopColor = $pValue; + $this->_borderLeftColor = $pValue; + $this->_borderRightColor = $pValue; + $this->_borderBottomColor = $pValue; + } + + /** + * Get Border Color + * + * @return array + */ + public function getBorderColor() + { + $t = $this->getBorderTopColor(); + $l = $this->getBorderLeftColor(); + $r = $this->getBorderRightColor(); + $b = $this->getBorderBottomColor(); + + return array($t, $l, $r, $b); + } + + /** + * Set Border Top Size + * + * @param int $pValue + */ + public function setBorderTopSize($pValue = null) + { + $this->_borderTopSize = $pValue; + } + + /** + * Get Border Top Size + * + * @return int + */ + public function getBorderTopSize() + { + return $this->_borderTopSize; + } + + /** + * Set Border Top Color + * + * @param string $pValue + */ + public function setBorderTopColor($pValue = null) + { + $this->_borderTopColor = $pValue; + } + + /** + * Get Border Top Color + * + * @return string + */ + public function getBorderTopColor() + { + return $this->_borderTopColor; + } + + /** + * Set Border Left Size + * + * @param int $pValue + */ + public function setBorderLeftSize($pValue = null) + { + $this->_borderLeftSize = $pValue; + } + + /** + * Get Border Left Size + * + * @return int + */ + public function getBorderLeftSize() + { + return $this->_borderLeftSize; + } + + /** + * Set Border Left Color + * + * @param string $pValue + */ + public function setBorderLeftColor($pValue = null) + { + $this->_borderLeftColor = $pValue; + } + + /** + * Get Border Left Color + * + * @return string + */ + public function getBorderLeftColor() + { + return $this->_borderLeftColor; + } + + /** + * Set Border Right Size + * + * @param int $pValue + */ + public function setBorderRightSize($pValue = null) + { + $this->_borderRightSize = $pValue; + } + + /** + * Get Border Right Size + * + * @return int + */ + public function getBorderRightSize() + { + return $this->_borderRightSize; + } + + /** + * Set Border Right Color + * + * @param string $pValue + */ + public function setBorderRightColor($pValue = null) + { + $this->_borderRightColor = $pValue; + } + + /** + * Get Border Right Color + * + * @return string + */ + public function getBorderRightColor() + { + return $this->_borderRightColor; + } + + /** + * Set Border Bottom Size + * + * @param int $pValue + */ + public function setBorderBottomSize($pValue = null) + { + $this->_borderBottomSize = $pValue; + } + + /** + * Get Border Bottom Size + * + * @return int + */ + public function getBorderBottomSize() + { + return $this->_borderBottomSize; + } + + /** + * Set Border Bottom Color + * + * @param string $pValue + */ + public function setBorderBottomColor($pValue = null) + { + $this->_borderBottomColor = $pValue; + } + + /** + * Get Border Bottom Color + * + * @return string + */ + public function getBorderBottomColor() + { + return $this->_borderBottomColor; + } + + /** + * @param null|int $pageNumberingStart + * @return $this + */ + public function setPageNumberingStart($pageNumberingStart = null) + { + $this->pageNumberingStart = $pageNumberingStart; + return $this; + } + + /** + * @return null|int + */ + public function getPageNumberingStart() + { + return $this->pageNumberingStart; + } + + /** + * Get Header Height + * + * @return int + */ + public function getHeaderHeight() + { + return $this->headerHeight; + } + + /** + * Set Header Height + * + * @param int $pValue + */ + public function setHeaderHeight($pValue = '') + { + if (!is_numeric($pValue)) { + $pValue = 720; + } + $this->headerHeight = $pValue; + return $this; + } + + /** + * Get Footer Height + * + * @return int + */ + public function getFooterHeight() + { + return $this->footerHeight; + } + + /** + * Set Footer Height + * + * @param int $pValue + */ + public function setFooterHeight($pValue = '') + { + if (!is_numeric($pValue)) { + $pValue = 720; + } + $this->footerHeight = $pValue; + return $this; + } + + /** + * Set Section Columns Count + * + * @param int $pValue + */ + public function setColsNum($pValue = '') + { + if (!is_numeric($pValue)) { + $pValue = 1; + } + $this->_colsNum = $pValue; + return $this; + } + + /** + * Get Section Columns Count + * + * @return int + */ + public function getColsNum() + { + return $this->_colsNum; + } + + /** + * Set Section Space Between Columns + * + * @param int $pValue + */ + public function setColsSpace($pValue = '') + { + if (!is_numeric($pValue)) { + $pValue = 720; + } + $this->_colsSpace = $pValue; + return $this; + } + + /** + * Get Section Space Between Columns + * + * @return int + */ + public function getColsSpace() + { + return $this->_colsSpace; + } + + /** + * Set Break Type + * + * @param string $pValue + */ + public function setBreakType($pValue = null) + { + $this->_breakType = $pValue; + return $this; + } + + /** + * Get Break Type + * + * @return string + */ + public function getBreakType() + { + return $this->_breakType; + } +} diff --git a/src/Section/Table.php b/src/Section/Table.php new file mode 100644 index 00000000..a06b41ac --- /dev/null +++ b/src/Section/Table.php @@ -0,0 +1,163 @@ +_insideOf = $insideOf; + $this->_pCount = $pCount; + + if (!is_null($style)) { + if (is_array($style)) { + $this->_style = new PhpOffice\PhpWord\Style\Table(); + + foreach ($style as $key => $value) { + if (substr($key, 0, 1) != '_') { + $key = '_' . $key; + } + $this->_style->setStyleValue($key, $value); + } + } else { + $this->_style = $style; + } + } + } + + /** + * Add a row + * + * @param int $height + */ + public function addRow($height = null, $style = null) + { + $row = new Row($this->_insideOf, $this->_pCount, $height, $style); + $this->_rows[] = $row; + return $row; + } + + /** + * Add a cell + * + * @param int $width + * @param mixed $style + * @return PhpOffice\PhpWord\Section\Table\Cell + */ + public function addCell($width = null, $style = null) + { + $i = count($this->_rows) - 1; + $cell = $this->_rows[$i]->addCell($width, $style); + return $cell; + } + + /** + * Get all rows + * + * @return array + */ + public function getRows() + { + return $this->_rows; + } + + /** + * Get table style + * + * @return PhpOffice\PhpWord\Style\Table + */ + public function getStyle() + { + return $this->_style; + } + + /** + * Set table width + * + * @var int $width + */ + public function setWidth($width) + { + $this->_width = $width; + } + + /** + * Get table width + * + * @return int + */ + public function getWidth() + { + return $this->_width; + } +} diff --git a/src/Section/Table/Cell.php b/src/Section/Table/Cell.php new file mode 100644 index 00000000..0088ceb0 --- /dev/null +++ b/src/Section/Table/Cell.php @@ -0,0 +1,350 @@ +_insideOf = $insideOf; + $this->_pCount = $pCount; + $this->_width = $width; + $this->_style = new PhpOffice\PhpWord\Style\Cell(); + + if (!is_null($style)) { + if (is_array($style)) { + foreach ($style as $key => $value) { + if (substr($key, 0, 1) != '_') { + $key = '_' . $key; + } + $this->_style->setStyleValue($key, $value); + } + } else { + $this->_style = $style; + } + } + } + + /** + * Add a Text Element + * + * @param string $text + * @param mixed $style + * @return PhpOffice\PhpWord\Section\Text + */ + public function addText($text, $styleFont = null, $styleParagraph = null) + { + if (!String::IsUTF8($text)) { + $text = utf8_encode($text); + } + $text = new Text($text, $styleFont, $styleParagraph); + $this->_elementCollection[] = $text; + return $text; + } + + /** + * Add a Link Element + * + * @param string $linkSrc + * @param string $linkName + * @param mixed $style + * @return PhpOffice\PhpWord\Section\Link + */ + public function addLink($linkSrc, $linkName = null, $style = null) + { + if ($this->_insideOf == 'section') { + if (!String::IsUTF8($linkSrc)) { + $linkSrc = utf8_encode($linkSrc); + } + if (!is_null($linkName)) { + if (!String::IsUTF8($linkName)) { + $linkName = utf8_encode($linkName); + } + } + + $link = new Link($linkSrc, $linkName, $style); + $rID = Media::addSectionLinkElement($linkSrc); + $link->setRelationId($rID); + + $this->_elementCollection[] = $link; + return $link; + } else { + throw new Exception('Unsupported Link header / footer reference'); + return false; + } + } + + /** + * Add TextBreak + * + * @param int $count + * @param null|string|array|PhpOffice\PhpWord\Style\Font $fontStyle + * @param null|string|array|PhpOffice\PhpWord\Style\Paragraph $paragraphStyle + */ + public function addTextBreak($count = 1, $fontStyle = null, $paragraphStyle = null) + { + for ($i = 1; $i <= $count; $i++) { + $this->_elementCollection[] = new TextBreak($fontStyle, $paragraphStyle); + } + } + + /** + * Add a ListItem Element + * + * @param string $text + * @param int $depth + * @param mixed $styleText + * @param mixed $styleList + * @return PhpOffice\PhpWord\Section\ListItem + */ + public function addListItem($text, $depth = 0, $styleText = null, $styleList = null) + { + if (!String::IsUTF8($text)) { + $text = utf8_encode($text); + } + $listItem = new ListItem($text, $depth, $styleText, $styleList); + $this->_elementCollection[] = $listItem; + return $listItem; + } + + /** + * Add a Image Element + * + * @param string $src + * @param mixed $style + * @return PhpOffice\PhpWord\Section\Image + */ + public function addImage($src, $style = null) + { + $image = new Image($src, $style); + + if (!is_null($image->getSource())) { + if ($this->_insideOf == 'section') { + $rID = Media::addSectionMediaElement($src, 'image'); + } elseif ($this->_insideOf == 'header') { + $rID = Media::addHeaderMediaElement($this->_pCount, $src); + } elseif ($this->_insideOf == 'footer') { + $rID = Media::addFooterMediaElement($this->_pCount, $src); + } + $image->setRelationId($rID); + + $this->_elementCollection[] = $image; + return $image; + } else { + throw new Exception('Source does not exist or unsupported image type.'); + } + } + + /** + * Add a by PHP created Image Element + * + * @param string $link + * @param mixed $style + * @return PhpOffice\PhpWord\Section\MemoryImage + */ + public function addMemoryImage($link, $style = null) + { + $memoryImage = new MemoryImage($link, $style); + if (!is_null($memoryImage->getSource())) { + if ($this->_insideOf == 'section') { + $rID = Media::addSectionMediaElement($link, 'image', $memoryImage); + } elseif ($this->_insideOf == 'header') { + $rID = Media::addHeaderMediaElement($this->_pCount, $link, $memoryImage); + } elseif ($this->_insideOf == 'footer') { + $rID = Media::addFooterMediaElement($this->_pCount, $link, $memoryImage); + } + $memoryImage->setRelationId($rID); + + $this->_elementCollection[] = $memoryImage; + return $memoryImage; + } else { + throw new Exception('Unsupported image type.'); + } + } + + /** + * Add a OLE-Object Element + * + * @param string $src + * @param mixed $style + * @return PhpOffice\PhpWord\Section\Object + */ + public function addObject($src, $style = null) + { + $object = new Object($src, $style); + + if (!is_null($object->getSource())) { + $inf = pathinfo($src); + $ext = $inf['extension']; + if (strlen($ext) == 4 && strtolower(substr($ext, -1)) == 'x') { + $ext = substr($ext, 0, -1); + } + + $iconSrc = \PHPWORD_BASE_DIR . '_staticDocParts/'; + if (!file_exists($iconSrc . '_' . $ext . '.png')) { + $iconSrc = $iconSrc . '_default.png'; + } else { + $iconSrc .= '_' . $ext . '.png'; + } + + $rIDimg = Media::addSectionMediaElement($iconSrc, 'image'); + $data = Media::addSectionMediaElement($src, 'oleObject'); + $rID = $data[0]; + $objectId = $data[1]; + + $object->setRelationId($rID); + $object->setObjectId($objectId); + $object->setImageRelationId($rIDimg); + + $this->_elementCollection[] = $object; + return $object; + } else { + throw new Exception('Source does not exist or unsupported object type.'); + } + } + + /** + * Add a PreserveText Element + * + * @param string $text + * @param mixed $styleFont + * @param mixed $styleParagraph + * @return PhpOffice\PhpWord\Section\Footer\PreserveText + */ + public function addPreserveText($text, $styleFont = null, $styleParagraph = null) + { + if ($this->_insideOf == 'footer' || $this->_insideOf == 'header') { + if (!String::IsUTF8($text)) { + $text = utf8_encode($text); + } + $ptext = new PreserveText($text, $styleFont, $styleParagraph); + $this->_elementCollection[] = $ptext; + return $ptext; + } else { + throw new Exception('addPreserveText only supported in footer/header.'); + } + } + + /** + * Create a new TextRun + * + * @return PhpOffice\PhpWord\Section\TextRun + */ + public function createTextRun($styleParagraph = null) + { + $textRun = new TextRun($styleParagraph); + $this->_elementCollection[] = $textRun; + return $textRun; + } + + /** + * Get all Elements + * + * @return array + */ + public function getElements() + { + return $this->_elementCollection; + } + + /** + * Get Cell Style + * + * @return PhpOffice\PhpWord\Style\Cell + */ + public function getStyle() + { + return $this->_style; + } + + /** + * Get Cell width + * + * @return int + */ + public function getWidth() + { + return $this->_width; + } +} diff --git a/src/Section/Table/Row.php b/src/Section/Table/Row.php new file mode 100644 index 00000000..de9822b3 --- /dev/null +++ b/src/Section/Table/Row.php @@ -0,0 +1,139 @@ +_insideOf = $insideOf; + $this->_pCount = $pCount; + $this->_height = $height; + $this->_style = new PhpOffice\PhpWord\Style\Row(); + + if (!is_null($style)) { + if (is_array($style)) { + + foreach ($style as $key => $value) { + if (substr($key, 0, 1) != '_') { + $key = '_' . $key; + } + $this->_style->setStyleValue($key, $value); + } + } + } + } + + /** + * Add a cell + * + * @param int $width + * @param mixed $style + * @return PhpOffice\PhpWord\Section\Table\Cell + */ + public function addCell($width = null, $style = null) + { + $cell = new Cell($this->_insideOf, $this->_pCount, $width, $style); + $this->_cells[] = $cell; + return $cell; + } + + /** + * Get all cells + * + * @return array + */ + public function getCells() + { + return $this->_cells; + } + + /** + * Get row style + * + * @return PhpOffice\PhpWord\Style\Row + */ + public function getStyle() + { + return $this->_style; + } + + /** + * Get row height + * + * @return int + */ + public function getHeight() + { + return $this->_height; + } +} diff --git a/src/Section/Text.php b/src/Section/Text.php new file mode 100644 index 00000000..3e51bc86 --- /dev/null +++ b/src/Section/Text.php @@ -0,0 +1,154 @@ +setText($text); + $paragraphStyle = $this->setParagraphStyle($paragraphStyle); + $this->setFontStyle($fontStyle, $paragraphStyle); + } + + /** + * Set Text style + * + * @param null|array|PhpOffice\PhpWord\Style\Font $style + * @param null|array|PhpOffice\PhpWord\Style\Paragraph $paragraphStyle + * @return PhpOffice\PhpWord\Style\Font + */ + public function setFontStyle($style = null, $paragraphStyle = null) + { + if ($style instanceof Font) { + $this->fontStyle = $style; + $this->setParagraphStyle($paragraphStyle); + } elseif (is_array($style)) { + $this->fontStyle = new Font('text', $paragraphStyle); + $this->fontStyle->setArrayStyle($style); + } elseif (null === $style) { + $this->fontStyle = new Font('text', $paragraphStyle); + } else { + $this->fontStyle = $style; + $this->setParagraphStyle($paragraphStyle); + } + return $this->fontStyle; + } + + /** + * Get Text style + * + * @return PhpOffice\PhpWord\Style\Font + */ + public function getFontStyle() + { + return $this->fontStyle; + } + + /** + * Set Paragraph style + * + * @param null|array|PhpOffice\PhpWord\Style\Paragraph $style + * @return null|PhpOffice\PhpWord\Style\Paragraph + */ + public function setParagraphStyle($style = null) + { + if (is_array($style)) { + $this->paragraphStyle = new Paragraph; + $this->paragraphStyle->setArrayStyle($style); + } elseif ($style instanceof Paragraph) { + $this->paragraphStyle = $style; + } elseif (null === $style) { + $this->paragraphStyle = new Paragraph; + } else { + $this->paragraphStyle = $style; + } + return $this->paragraphStyle; + } + + /** + * Get Paragraph style + * + * @return PhpOffice\PhpWord\Style\Paragraph + */ + public function getParagraphStyle() + { + return $this->paragraphStyle; + } + + /** + * @param string $text + * @return $this + */ + public function setText($text) + { + $this->text = $text; + return $this; + } + + /** + * Get Text content + * + * @return string + */ + public function getText() + { + return $this->text; + } +} diff --git a/src/Section/TextBreak.php b/src/Section/TextBreak.php new file mode 100644 index 00000000..cd296c74 --- /dev/null +++ b/src/Section/TextBreak.php @@ -0,0 +1,122 @@ +setParagraphStyle($paragraphStyle); + } + if (!is_null($fontStyle)) { + $this->setFontStyle($fontStyle, $paragraphStyle); + } + } + + /** + * Set Text style + * + * @param null|array|PhpOffice\PhpWord\Style\Font $style + * @param null|array|PhpOffice\PhpWord\Style\Paragraph $paragraphStyle + * @return PhpOffice\PhpWord\Style\Font + */ + public function setFontStyle($style = null, $paragraphStyle = null) + { + if ($style instanceof Font) { + $this->fontStyle = $style; + $this->setParagraphStyle($paragraphStyle); + } elseif (is_array($style)) { + $this->fontStyle = new Font('text', $paragraphStyle); + $this->fontStyle->setArrayStyle($style); + } else { + $this->fontStyle = $style; + $this->setParagraphStyle($paragraphStyle); + } + return $this->fontStyle; + } + + /** + * Get Text style + * + * @return PhpOffice\PhpWord\Style\Font + */ + public function getFontStyle() + { + return $this->fontStyle; + } + + /** + * Set Paragraph style + * + * @param null|array|PhpOffice\PhpWord\Style\Paragraph $style + * @return null|PhpOffice\PhpWord\Style\Paragraph + */ + public function setParagraphStyle($style = null) + { + if (is_array($style)) { + $this->paragraphStyle = new Paragraph; + $this->paragraphStyle->setArrayStyle($style); + } elseif ($style instanceof Paragraph) { + $this->paragraphStyle = $style; + } else { + $this->paragraphStyle = $style; + } + return $this->paragraphStyle; + } + + /** + * Get Paragraph style + * + * @return PhpOffice\PhpWord\Style\Paragraph + */ + public function getParagraphStyle() + { + return $this->paragraphStyle; + } +} \ No newline at end of file diff --git a/src/Section/TextRun.php b/src/Section/TextRun.php new file mode 100644 index 00000000..4cee06d6 --- /dev/null +++ b/src/Section/TextRun.php @@ -0,0 +1,184 @@ +_elementCollection = array(); + + // Set paragraph style + if (is_array($styleParagraph)) { + $this->_styleParagraph = new Paragraph(); + + foreach ($styleParagraph as $key => $value) { + if (substr($key, 0, 1) != '_') { + $key = '_' . $key; + } + $this->_styleParagraph->setStyleValue($key, $value); + } + } else { + $this->_styleParagraph = $styleParagraph; + } + } + + + /** + * Add a Text Element + * + * @var string $text + * @var mixed $styleFont + * @return PhpOffice\PhpWord\Section\Text + */ + public function addText($text = null, $styleFont = null) + { + if (!String::IsUTF8($text)) { + $text = utf8_encode($text); + } + $text = new Text($text, $styleFont); + $this->_elementCollection[] = $text; + return $text; + } + + /** + * Add a Link Element + * + * @param string $linkSrc + * @param string $linkName + * @param mixed $styleFont + * @return PhpOffice\PhpWord\Section\Link + */ + public function addLink($linkSrc, $linkName = null, $styleFont = null) + { + $linkSrc = utf8_encode($linkSrc); + if (!is_null($linkName)) { + $linkName = utf8_encode($linkName); + } + + $link = new Link($linkSrc, $linkName, $styleFont); + $rID = Media::addSectionLinkElement($linkSrc); + $link->setRelationId($rID); + + $this->_elementCollection[] = $link; + return $link; + } + + /** + * Add a Image Element + * + * @param string $imageSrc + * @param mixed $styleFont + * @return PhpOffice\PhpWord\Section\Image + */ + public function addImage($imageSrc, $style = null) + { + $image = new Image($imageSrc, $style); + + if (!is_null($image->getSource())) { + $rID = Media::addSectionMediaElement($imageSrc, 'image'); + $image->setRelationId($rID); + + $this->_elementCollection[] = $image; + return $image; + } else { + throw new Exception('Source does not exist or unsupported image type.'); + } + } + + /** + * Add TextBreak + * + * @param int $count + * @param null|string|array|PhpOffice\PhpWord\Style\Font $fontStyle + * @param null|string|array|PhpOffice\PhpWord\Style\Paragraph $paragraphStyle + */ + public function addTextBreak($count = 1, $fontStyle = null, $paragraphStyle = null) + { + for ($i = 1; $i <= $count; $i++) { + $this->_elementCollection[] = new TextBreak($fontStyle, $paragraphStyle); + } + } + + /** + * Create a new Footnote Element + * + * @param string $text + * @return PhpOffice\PhpWord\Section\Footnote + */ + public function createFootnote($styleParagraph = null) + { + $footnote = new PhpOffice\PhpWord\Section\Footnote($styleParagraph); + $refID = PhpOffice\PhpWord\Footnote::addFootnoteElement($footnote); + $footnote->setReferenceId($refID); + $this->_elementCollection[] = $footnote; + return $footnote; + } + + /** + * Get TextRun content + * + * @return string + */ + public function getElements() + { + return $this->_elementCollection; + } + + /** + * Get Paragraph style + * + * @return PhpOffice\PhpWord\Style\Paragraph + */ + public function getParagraphStyle() + { + return $this->_styleParagraph; + } +} \ No newline at end of file diff --git a/src/Section/Title.php b/src/Section/Title.php new file mode 100644 index 00000000..fdc31ac8 --- /dev/null +++ b/src/Section/Title.php @@ -0,0 +1,145 @@ +_style = $style; + } + + $this->_text = $text; + $this->_depth = $depth; + + return $this; + } + + /** + * Set Anchor + * + * @var int $anchor + */ + public function setAnchor($anchor) + { + $this->_anchor = $anchor; + } + + /** + * Get Anchor + * + * @return int + */ + public function getAnchor() + { + return $this->_anchor; + } + + /** + * Set Bookmark ID + * + * @var int $bookmarkId + */ + public function setBookmarkId($bookmarkId) + { + $this->_bookmarkId = $bookmarkId; + } + + /** + * Get Anchor + * + * @return int + */ + public function getBookmarkId() + { + return $this->_bookmarkId; + } + + /** + * Get Title Text content + * + * @return string + */ + public function getText() + { + return $this->_text; + } + + /** + * Get Title style + * + * @return string + */ + public function getStyle() + { + return $this->_style; + } +} diff --git a/src/Settings.php b/src/Settings.php new file mode 100644 index 00000000..8eb3a60f --- /dev/null +++ b/src/Settings.php @@ -0,0 +1,63 @@ + 0) { + unset($pathArray[$i]); + unset($pathArray[$i - 1]); + break; + } + } + } + $returnValue = implode('/', $pathArray); + } + + // Return + return $returnValue; + } +} diff --git a/src/Shared/Font.php b/src/Shared/Font.php new file mode 100644 index 00000000..adee50ad --- /dev/null +++ b/src/Shared/Font.php @@ -0,0 +1,90 @@ +) + * element or in the shared string element. + * + * @param string $value Value to unescape + * @return string + */ + public static function ControlCharacterOOXML2PHP($value = '') + { + if (empty(self::$_controlCharacters)) { + self::_buildControlCharacters(); + } + + return str_replace(array_keys(self::$_controlCharacters), array_values(self::$_controlCharacters), $value); + } + + /** + * Convert from PHP control character to OpenXML escaped control character + * + * Excel 2007 team: + * ---------------- + * That's correct, control characters are stored directly in the shared-strings table. + * We do encode characters that cannot be represented in XML using the following escape sequence: + * _xHHHH_ where H represents a hexadecimal character in the character's value... + * So you could end up with something like _x0008_ in a string (either in a cell value () + * element or in the shared string element. + * + * @param string $value Value to escape + * @return string + */ + public static function ControlCharacterPHP2OOXML($value = '') + { + if (empty(self::$_controlCharacters)) { + self::_buildControlCharacters(); + } + + return str_replace(array_values(self::$_controlCharacters), array_keys(self::$_controlCharacters), $value); + } + + /** + * Check if a string contains UTF-8 data + * + * @param string $value + * @return boolean + */ + public static function IsUTF8($value = '') + { + return $value === '' || preg_match('/^./su', $value) === 1; + } +} diff --git a/src/Shared/XMLWriter.php b/src/Shared/XMLWriter.php new file mode 100644 index 00000000..2334997f --- /dev/null +++ b/src/Shared/XMLWriter.php @@ -0,0 +1,155 @@ +_xmlWriter = new XMLWriter(); + + // Open temporary storage + if ($pTemporaryStorage == self::STORAGE_MEMORY) { + $this->_xmlWriter->openMemory(); + } else { + // Create temporary filename + $this->_tempFileName = @tempnam($pTemporaryStorageFolder, 'xml'); + + // Open storage + if ($this->_xmlWriter->openUri($this->_tempFileName) === false) { + // Fallback to memory... + $this->_xmlWriter->openMemory(); + } + } + + // Set xml Compatibility + $compatibility = Settings::getCompatibility(); + if ($compatibility) { + $this->_xmlWriter->setIndent(false); + $this->_xmlWriter->setIndentString(''); + } else { + $this->_xmlWriter->setIndent(true); + $this->_xmlWriter->setIndentString(' '); + } + } + + /** + * Destructor + */ + public function __destruct() + { + // Desctruct XMLWriter + unset($this->_xmlWriter); + + // Unlink temporary files + if ($this->_tempFileName != '') { + @unlink($this->_tempFileName); + } + } + + /** + * Get written data + * + * @return $data + */ + public function getData() + { + if ($this->_tempFileName == '') { + return $this->_xmlWriter->outputMemory(true); + } else { + $this->_xmlWriter->flush(); + return file_get_contents($this->_tempFileName); + } + } + + /** + * Catch function calls (and pass them to internal XMLWriter) + * + * @param unknown_type $function + * @param unknown_type $args + */ + public function __call($function, $args) + { + try { + @call_user_func_array(array($this->_xmlWriter, $function), $args); + } catch (Exception $ex) { + // Do nothing! + } + } + + /** + * Fallback method for writeRaw, introduced in PHP 5.2 + * + * @param string $text + * @return string + */ + public function writeRaw($text) + { + if (isset($this->_xmlWriter) && is_object($this->_xmlWriter) && (method_exists($this->_xmlWriter, 'writeRaw'))) { + return $this->_xmlWriter->writeRaw($text); + } + + return $this->text($text); + } +} diff --git a/src/Shared/ZipStreamWrapper.php b/src/Shared/ZipStreamWrapper.php new file mode 100644 index 00000000..4a8bac6c --- /dev/null +++ b/src/Shared/ZipStreamWrapper.php @@ -0,0 +1,183 @@ +_archive = new ZipArchive(); + $this->_archive->open($url['host']); + + $this->_fileNameInArchive = $url['fragment']; + $this->_position = 0; + $this->_data = $this->_archive->getFromName($this->_fileNameInArchive); + + return true; + } + + /** + * Stat stream + */ + public function stream_stat() + { + return $this->_archive->statName($this->_fileNameInArchive); + } + + /** + * Read stream + */ + public function stream_read($count) + { + $ret = substr($this->_data, $this->_position, $count); + $this->_position += strlen($ret); + return $ret; + } + + /** + * Tell stream + */ + public function stream_tell() + { + return $this->_position; + } + + /** + * EOF stream + */ + public function stream_eof() + { + return $this->_position >= strlen($this->_data); + } + + /** + * Seek stream + */ + public function stream_seek($offset, $whence) + { + switch ($whence) { + case SEEK_SET: + if ($offset < strlen($this->_data) && $offset >= 0) { + $this->_position = $offset; + return true; + } else { + return false; + } + break; + + case SEEK_CUR: + if ($offset >= 0) { + $this->_position += $offset; + return true; + } else { + return false; + } + break; + + case SEEK_END: + if (strlen($this->_data) + $offset >= 0) { + $this->_position = strlen($this->_data) + $offset; + return true; + } else { + return false; + } + break; + + default: + return false; + } + } +} \ No newline at end of file diff --git a/src/Style.php b/src/Style.php new file mode 100644 index 00000000..387dc468 --- /dev/null +++ b/src/Style.php @@ -0,0 +1,161 @@ + $value) { + if (substr($key, 0, 1) != '_') { + $key = '_' . $key; + } + $style->setStyleValue($key, $value); + } + + self::$_styleElements[$styleName] = $style; + } + } + + /** + * @param string $styleName + * @param array $styleFont + * @param array $styleParagraph + */ + public static function addFontStyle($styleName, $styleFont, $styleParagraph = null) + { + if (!array_key_exists($styleName, self::$_styleElements)) { + $font = new Font('text', $styleParagraph); + foreach ($styleFont as $key => $value) { + if (substr($key, 0, 1) != '_') { + $key = '_' . $key; + } + $font->setStyleValue($key, $value); + } + self::$_styleElements[$styleName] = $font; + } + } + + /** + * @param string $styleName + * @param array $styles + */ + public static function addLinkStyle($styleName, $styles) + { + if (!array_key_exists($styleName, self::$_styleElements)) { + $style = new Font('link'); + foreach ($styles as $key => $value) { + if (substr($key, 0, 1) != '_') { + $key = '_' . $key; + } + $style->setStyleValue($key, $value); + } + + self::$_styleElements[$styleName] = $style; + } + } + + /** + * @param string $styleName + * @param array $styles + */ + public static function addTableStyle($styleName, $styleTable, $styleFirstRow = null) + { + if (!array_key_exists($styleName, self::$_styleElements)) { + $style = new TableFull($styleTable, $styleFirstRow); + + self::$_styleElements[$styleName] = $style; + } + } + + /** + * @param string $styleName + * @param array $styleFont + * @param array $styleParagraph + */ + public static function addTitleStyle($titleCount, $styleFont, $styleParagraph = null) + { + $styleName = 'Heading_' . $titleCount; + if (!array_key_exists($styleName, self::$_styleElements)) { + $font = new Font('title', $styleParagraph); + foreach ($styleFont as $key => $value) { + if (substr($key, 0, 1) != '_') { + $key = '_' . $key; + } + $font->setStyleValue($key, $value); + } + + self::$_styleElements[$styleName] = $font; + } + } + + /** + * @param array $styles Paragraph style definition + */ + public static function setDefaultParagraphStyle($styles) + { + self::addParagraphStyle('Normal', $styles); + } + + /** + * Get all styles + * + * @return PhpOffice\PhpWord\Style\Font[] + */ + public static function getStyles() + { + return self::$_styleElements; + } + + /** + * @param string + */ + public static function getStyle($styleName) + { + if (array_key_exists($styleName, self::$_styleElements)) { + return self::$_styleElements[$styleName]; + } else { + return null; + } + } +} \ No newline at end of file diff --git a/src/Style/Cell.php b/src/Style/Cell.php new file mode 100644 index 00000000..23cd0c07 --- /dev/null +++ b/src/Style/Cell.php @@ -0,0 +1,343 @@ +_valign = null; + $this->_textDirection = null; + $this->_bgColor = null; + $this->_borderTopSize = null; + $this->_borderTopColor = null; + $this->_borderLeftSize = null; + $this->_borderLeftColor = null; + $this->_borderRightSize = null; + $this->_borderRightColor = null; + $this->_borderBottomSize = null; + $this->_borderBottomColor = null; + $this->_defaultBorderColor = '000000'; + } + + /** + * Set style value + * + * @var string $key + * @var mixed $value + */ + public function setStyleValue($key, $value) + { + if ($key == '_borderSize') { + $this->setBorderSize($value); + } elseif ($key == '_borderColor') { + $this->setBorderColor($value); + } else { + $this->$key = $value; + } + } + + public function getVAlign() + { + return $this->_valign; + } + + public function setVAlign($pValue = null) + { + $this->_valign = $pValue; + } + + public function getTextDirection() + { + return $this->_textDirection; + } + + public function setTextDirection($pValue = null) + { + $this->_textDirection = $pValue; + } + + public function getBgColor() + { + return $this->_bgColor; + } + + public function setBgColor($pValue = null) + { + $this->_bgColor = $pValue; + } + + public function setBorderSize($pValue = null) + { + $this->_borderTopSize = $pValue; + $this->_borderLeftSize = $pValue; + $this->_borderRightSize = $pValue; + $this->_borderBottomSize = $pValue; + } + + public function getBorderSize() + { + $t = $this->getBorderTopSize(); + $l = $this->getBorderLeftSize(); + $r = $this->getBorderRightSize(); + $b = $this->getBorderBottomSize(); + + return array($t, $l, $r, $b); + } + + public function setBorderColor($pValue = null) + { + $this->_borderTopColor = $pValue; + $this->_borderLeftColor = $pValue; + $this->_borderRightColor = $pValue; + $this->_borderBottomColor = $pValue; + } + + public function getBorderColor() + { + $t = $this->getBorderTopColor(); + $l = $this->getBorderLeftColor(); + $r = $this->getBorderRightColor(); + $b = $this->getBorderBottomColor(); + + return array($t, $l, $r, $b); + } + + public function setBorderTopSize($pValue = null) + { + $this->_borderTopSize = $pValue; + } + + public function getBorderTopSize() + { + return $this->_borderTopSize; + } + + public function setBorderTopColor($pValue = null) + { + $this->_borderTopColor = $pValue; + } + + public function getBorderTopColor() + { + return $this->_borderTopColor; + } + + public function setBorderLeftSize($pValue = null) + { + $this->_borderLeftSize = $pValue; + } + + public function getBorderLeftSize() + { + return $this->_borderLeftSize; + } + + public function setBorderLeftColor($pValue = null) + { + $this->_borderLeftColor = $pValue; + } + + public function getBorderLeftColor() + { + return $this->_borderLeftColor; + } + + public function setBorderRightSize($pValue = null) + { + $this->_borderRightSize = $pValue; + } + + public function getBorderRightSize() + { + return $this->_borderRightSize; + } + + public function setBorderRightColor($pValue = null) + { + $this->_borderRightColor = $pValue; + } + + public function getBorderRightColor() + { + return $this->_borderRightColor; + } + + + public function setBorderBottomSize($pValue = null) + { + $this->_borderBottomSize = $pValue; + } + + public function getBorderBottomSize() + { + return $this->_borderBottomSize; + } + + public function setBorderBottomColor($pValue = null) + { + $this->_borderBottomColor = $pValue; + } + + public function getBorderBottomColor() + { + return $this->_borderBottomColor; + } + + public function getDefaultBorderColor() + { + return $this->_defaultBorderColor; + } + + public function setGridSpan($pValue = null) + { + $this->_gridSpan = $pValue; + } + + public function getGridSpan() + { + return $this->_gridSpan; + } + + public function setVMerge($pValue = null) + { + $this->_vMerge = $pValue; + } + + public function getVMerge() + { + return $this->_vMerge; + } +} diff --git a/src/Style/Font.php b/src/Style/Font.php new file mode 100644 index 00000000..7551200b --- /dev/null +++ b/src/Style/Font.php @@ -0,0 +1,544 @@ +_type = $type; + + if ($paragraphStyle instanceof Paragraph) { + $this->_paragraphStyle = $paragraphStyle; + } elseif (is_array($paragraphStyle)) { + $this->_paragraphStyle = new Paragraph; + $this->_paragraphStyle->setArrayStyle($paragraphStyle); + } else { + $this->_paragraphStyle = $paragraphStyle; + } + } + + /** + * @param array $style + * @return $this + */ + public function setArrayStyle(array $style = array()) + { + foreach ($style as $key => $value) { + if ($key === 'line-height') { + $this->setLineHeight($value); + null; + } elseif (substr($key, 0, 1) !== '_') { + $key = '_' . $key; + } + $this->setStyleValue($key, $value); + } + + return $this; + } + + /** + * Set style value + * + * @param string $key + * @param mixed $value + */ + public function setStyleValue($key, $value) + { + $method = 'set' . substr($key, 1); + if (method_exists($this, $method)) { + $this->$method($value); + } + } + + /** + * Get font name + * + * @return bool + */ + public function getName() + { + return $this->_name; + } + + /** + * Set font name + * + * @param string $pValue + * @return PhpOffice\PhpWord\Style\Font + */ + public function setName($pValue = PhpWord::DEFAULT_FONT_NAME) + { + if (is_null($pValue) || $pValue == '') { + $pValue = PhpWord::DEFAULT_FONT_NAME; + } + $this->_name = $pValue; + return $this; + } + + + /** + * Get font size + * + * @return int|float + */ + public function getSize() + { + return $this->_size; + } + + /** + * Set font size + * + * @param int|float $pValue + * @return PhpOffice\PhpWord\Style\Font + */ + public function setSize($pValue = PhpWord::DEFAULT_FONT_SIZE) + { + if (!is_numeric($pValue)) { + $pValue = PhpWord::DEFAULT_FONT_SIZE; + } + $this->_size = $pValue; + return $this; + } + + /** + * Get bold + * + * @return bool + */ + public function getBold() + { + return $this->_bold; + } + + /** + * Set bold + * + * @param bool $pValue + * @return PhpOffice\PhpWord\Style\Font + */ + public function setBold($pValue = false) + { + if (!is_bool($pValue)) { + $pValue = false; + } + $this->_bold = $pValue; + return $this; + } + + /** + * Get italics + * + * @return bool + */ + public function getItalic() + { + return $this->_italic; + } + + /** + * Set italics + * + * @param bool $pValue + * @return PhpOffice\PhpWord\Style\Font + */ + public function setItalic($pValue = false) + { + if (!is_bool($pValue)) { + $pValue = false; + } + $this->_italic = $pValue; + return $this; + } + + /** + * Get superscript + * + * @return bool + */ + public function getSuperScript() + { + return $this->_superScript; + } + + /** + * Set superscript + * + * @param bool $pValue + * @return PhpOffice\PhpWord\Style\Font + */ + public function setSuperScript($pValue = false) + { + if (!is_bool($pValue)) { + $pValue = false; + } + $this->_superScript = $pValue; + $this->_subScript = !$pValue; + return $this; + } + + /** + * Get superscript + * + * @return bool + */ + public function getSubScript() + { + return $this->_subScript; + } + + /** + * Set subscript + * + * @param bool $pValue + * @return PhpOffice\PhpWord\Style\Font + */ + public function setSubScript($pValue = false) + { + if (!is_bool($pValue)) { + $pValue = false; + } + $this->_subScript = $pValue; + $this->_superScript = !$pValue; + return $this; + } + + /** + * Get underline + * + * @return string + */ + public function getUnderline() + { + return $this->_underline; + } + + /** + * Set underline + * + * @param string $pValue + * @return PhpOffice\PhpWord\Style\Font + */ + public function setUnderline($pValue = self::UNDERLINE_NONE) + { + if ($pValue == '') { + $pValue = self::UNDERLINE_NONE; + } + $this->_underline = $pValue; + return $this; + } + + /** + * Get strikethrough + * + * @return bool + */ + public function getStrikethrough() + { + return $this->_strikethrough; + } + + /** + * Set strikethrough + * + * @param bool $pValue + * @return PhpOffice\PhpWord\Style\Font + */ + public function setStrikethrough($pValue = false) + { + if (!is_bool($pValue)) { + $pValue = false; + } + $this->_strikethrough = $pValue; + return $this; + } + + /** + * Get font color + * + * @return string + */ + public function getColor() + { + return $this->_color; + } + + /** + * Set font color + * + * @param string $pValue + * @return PhpOffice\PhpWord\Style\Font + */ + public function setColor($pValue = PhpWord::DEFAULT_FONT_COLOR) + { + if (is_null($pValue) || $pValue == '') { + $pValue = PhpWord::DEFAULT_FONT_COLOR; + } + $this->_color = $pValue; + return $this; + } + + /** + * Get foreground/highlight color + * + * @return bool + */ + public function getFgColor() + { + return $this->_fgColor; + } + + /** + * Set foreground/highlight color + * + * @param string $pValue + * @return PhpOffice\PhpWord\Style\Font + */ + public function setFgColor($pValue = null) + { + $this->_fgColor = $pValue; + return $this; + } + + /** + * Get style type + * + * @return string + */ + public function getStyleType() + { + return $this->_type; + } + + /** + * Get paragraph style + * + * @return PhpOffice\PhpWord\Style\Paragraph + */ + public function getParagraphStyle() + { + return $this->_paragraphStyle; + } + + /** + * Set the line height + * + * @param int|float|string $lineHeight + * @return $this + * @throws InvalidStyleException + */ + public function setLineHeight($lineHeight) + { + if (is_string($lineHeight)) { + $lineHeight = floatval(preg_replace('/[^0-9\.\,]/', '', $lineHeight)); + } + + if ((!is_integer($lineHeight) && !is_float($lineHeight)) || !$lineHeight) { + throw new InvalidStyleException('Line height must be a valid number'); + } + + $this->lineHeight = $lineHeight; + $this->getParagraphStyle()->setLineHeight($lineHeight); + return $this; + } + + /** + * @return int|float + */ + public function getLineHeight() + { + return $this->lineHeight; + } + + /** + * Get Font Content Type + * + * @return bool + */ + public function getHint() + { + return $this->_hint; + } + + /** + * Set Font Content Type + * + * @param string $pValue + * @return PhpOffice\PhpWord\Style\Font + */ + public function setHint($pValue = PhpWord::DEFAULT_FONT_CONTENT_TYPE) + { + if (is_null($pValue) || $pValue == '') { + $pValue = PhpWord::DEFAULT_FONT_CONTENT_TYPE; + } + $this->_hint = $pValue; + return $this; + } +} diff --git a/src/Style/Image.php b/src/Style/Image.php new file mode 100644 index 00000000..fbc074be --- /dev/null +++ b/src/Style/Image.php @@ -0,0 +1,175 @@ +_width = null; + $this->_height = null; + $this->_align = null; + $this->_marginTop = null; + $this->_marginLeft = null; + $this->setWrappingStyle(self::WRAPPING_STYLE_INLINE); + } + + public function setStyleValue($key, $value) + { + $this->$key = $value; + } + + public function getWidth() + { + return $this->_width; + } + + public function setWidth($pValue = null) + { + $this->_width = $pValue; + } + + public function getHeight() + { + return $this->_height; + } + + public function setHeight($pValue = null) + { + $this->_height = $pValue; + } + + public function getAlign() + { + return $this->_align; + } + + public function setAlign($pValue = null) + { + $this->_align = $pValue; + } + + /** + * Get Margin Top + * + * @return int + */ + public function getMarginTop() + { + return $this->_marginTop; + } + + /** + * Set Margin Top + * + * @param int $pValue + * @return $this + */ + public function setMarginTop($pValue = null) + { + $this->_marginTop = $pValue; + return $this; + } + + /** + * Get Margin Left + * + * @return int + */ + public function getMarginLeft() + { + return $this->_marginLeft; + } + + /** + * Set Margin Left + * + * @param int $pValue + * @return $this + */ + public function setMarginLeft($pValue = null) + { + $this->_marginLeft = $pValue; + return $this; + } + + /** + * @param string $wrappingStyle + * @throws InvalidArgumentException + * @return $this + */ + public function setWrappingStyle($wrappingStyle) + { + switch ($wrappingStyle) { + case self::WRAPPING_STYLE_BEHIND: + case self::WRAPPING_STYLE_INFRONT: + case self::WRAPPING_STYLE_INLINE: + case self::WRAPPING_STYLE_SQUARE: + case self::WRAPPING_STYLE_TIGHT: + $this->wrappingStyle = $wrappingStyle; + break; + default: + throw new InvalidArgumentException('Wrapping style does not exists'); + break; + } + return $this; + } + + /** + * @return string + */ + public function getWrappingStyle() + { + return $this->wrappingStyle; + } +} diff --git a/src/Style/ListItem.php b/src/Style/ListItem.php new file mode 100644 index 00000000..458e08e8 --- /dev/null +++ b/src/Style/ListItem.php @@ -0,0 +1,80 @@ +_listType = self::TYPE_BULLET_FILLED; + } + + /** + * Set style value + * + * @param string $key + * @param string $value + */ + public function setStyleValue($key, $value) + { + $this->$key = $value; + } + + /** + * Set List Type + * + * @param int $pValue + */ + public function setListType($pValue = self::TYPE_BULLET_FILLED) + { + $this->_listType = $pValue; + } + + /** + * Get List Type + */ + public function getListType() + { + return $this->_listType; + } +} diff --git a/src/Style/Paragraph.php b/src/Style/Paragraph.php new file mode 100644 index 00000000..87827448 --- /dev/null +++ b/src/Style/Paragraph.php @@ -0,0 +1,508 @@ + $value) { + if ($key === 'line-height') { + null; + } elseif (substr($key, 0, 1) !== '_') { + $key = '_' . $key; + } + $this->setStyleValue($key, $value); + } + + return $this; + } + + /** + * Set Style value + * + * @param string $key + * @param mixed $value + */ + public function setStyleValue($key, $value) + { + if ($key == '_indent' || $key == '_hanging') { + $value = $value * 720; + } elseif ($key == '_spacing') { + $value += 240; // because line height of 1 matches 240 twips + } elseif ($key === 'line-height') { + $this->setLineHeight($value); + return; + } + $this->$key = $value; + $method = 'set' . substr($key, 1); + if (method_exists($this, $method)) { + $this->$method($value); + } + } + + /** + * Get Paragraph Alignment + * + * @return string + */ + public function getAlign() + { + return $this->_align; + } + + /** + * Set Paragraph Alignment + * + * @param string $pValue + * @return PhpOffice\PhpWord\Style\Paragraph + */ + public function setAlign($pValue = null) + { + if (strtolower($pValue) == 'justify') { + // justify becames both + $pValue = 'both'; + } + $this->_align = $pValue; + return $this; + } + + /** + * Get Space before Paragraph + * + * @return string + */ + public function getSpaceBefore() + { + return $this->_spaceBefore; + } + + /** + * Set Space before Paragraph + * + * @param int $pValue + * @return PhpOffice\PhpWord\Style\Paragraph + */ + public function setSpaceBefore($pValue = null) + { + $this->_spaceBefore = $pValue; + return $this; + } + + /** + * Get Space after Paragraph + * + * @return string + */ + public function getSpaceAfter() + { + return $this->_spaceAfter; + } + + /** + * Set Space after Paragraph + * + * @param int $pValue + * @return PhpOffice\PhpWord\Style\Paragraph + */ + public function setSpaceAfter($pValue = null) + { + $this->_spaceAfter = $pValue; + return $this; + } + + /** + * Get Spacing between breaks + * + * @return int + */ + public function getSpacing() + { + return $this->_spacing; + } + + /** + * Set Spacing between breaks + * + * @param int $pValue + * @return PhpOffice\PhpWord\Style\Paragraph + */ + public function setSpacing($pValue = null) + { + $this->_spacing = $pValue; + return $this; + } + + /** + * Get indentation + * + * @return int + */ + public function getIndent() + { + return $this->_indent; + } + + /** + * Set indentation + * + * @param int $pValue + * @return PhpOffice\PhpWord\Style\Paragraph + */ + public function setIndent($pValue = null) + { + $this->_indent = $pValue; + return $this; + } + + /** + * Get hanging + * + * @return int + */ + public function getHanging() + { + return $this->_hanging; + } + + /** + * Set hanging + * + * @param int $pValue + * @return PhpOffice\PhpWord\Style\Paragraph + */ + public function setHanging($pValue = null) + { + $this->_hanging = $pValue; + return $this; + } + + /** + * Get tabs + * + * @return PhpOffice\PhpWord\Style\Tabs + */ + public function getTabs() + { + return $this->_tabs; + } + + /* + * Set tabs + * + * @param array $pValue + * @return PhpOffice\PhpWord\Style\Paragraph + */ + public function setTabs($pValue = null) + { + if (is_array($pValue)) { + $this->_tabs = new Tabs($pValue); + } + return $this; + } + + /** + * Get parent style ID + * + * @return string + */ + public function getBasedOn() + { + return $this->_basedOn; + } + + /** + * Set parent style ID + * + * @param string $pValue + * @return PhpOffice\PhpWord\Style\Paragraph + */ + public function setBasedOn($pValue = 'Normal') + { + $this->_basedOn = $pValue; + return $this; + } + + /** + * Get style for next paragraph + * + * @return string + */ + public function getNext() + { + return $this->_next; + } + + /** + * Set style for next paragraph + * + * @param string $pValue + * @return PhpOffice\PhpWord\Style\Paragraph + */ + public function setNext($pValue = null) + { + $this->_next = $pValue; + return $this; + } + + /** + * Get allow first/last line to display on a separate page setting + * + * @return bool + */ + public function getWidowControl() + { + return $this->_widowControl; + } + + /** + * Set keep paragraph with next paragraph setting + * + * @param bool $pValue + * @return PhpOffice\PhpWord\Style\Paragraph + */ + public function setWidowControl($pValue = true) + { + if (!is_bool($pValue)) { + $pValue = true; + } + $this->_widowControl = $pValue; + return $this; + } + + /** + * Get keep paragraph with next paragraph setting + * + * @return bool + */ + public function getKeepNext() + { + return $this->_keepNext; + } + + /** + * Set keep paragraph with next paragraph setting + * + * @param bool $pValue + * @return PhpOffice\PhpWord\Style\Paragraph + */ + public function setKeepNext($pValue = false) + { + if (!is_bool($pValue)) { + $pValue = false; + } + $this->_keepNext = $pValue; + return $this; + } + + /** + * Get keep all lines on one page setting + * + * @return bool + */ + public function getKeepLines() + { + return $this->_keepLines; + } + + /** + * Set keep all lines on one page setting + * + * @param bool $pValue + * @return PhpOffice\PhpWord\Style\Paragraph + */ + public function setKeepLines($pValue = false) + { + if (!is_bool($pValue)) { + $pValue = false; + } + $this->_keepLines = $pValue; + return $this; + } + + /** + * Get start paragraph on next page setting + * + * @return bool + */ + public function getPageBreakBefore() + { + return $this->_pageBreakBefore; + } + + /** + * Set start paragraph on next page setting + * + * @param bool $pValue + * @return PhpOffice\PhpWord\Style\Paragraph + */ + public function setPageBreakBefore($pValue = false) + { + if (!is_bool($pValue)) { + $pValue = false; + } + $this->_pageBreakBefore = $pValue; + return $this; + } + + /** + * Set the line height + * + * @param int|float|string $lineHeight + * @return $this + * @throws InvalidStyleException + */ + public function setLineHeight($lineHeight) + { + if (is_string($lineHeight)) { + $lineHeight = floatval(preg_replace('/[^0-9\.\,]/', '', $lineHeight)); + } + + if ((!is_integer($lineHeight) && !is_float($lineHeight)) || !$lineHeight) { + throw new InvalidStyleException('Line height must be a valid number'); + } + + $this->lineHeight = $lineHeight; + $this->setSpacing($lineHeight * self::LINE_HEIGHT); + return $this; + } + + /** + * @return int|float + */ + public function getLineHeight() + { + return $this->lineHeight; + } +} diff --git a/src/Style/Row.php b/src/Style/Row.php new file mode 100644 index 00000000..5431dd20 --- /dev/null +++ b/src/Style/Row.php @@ -0,0 +1,88 @@ +$key = $value; + } + + public function setTblHeader($pValue = false) + { + if (!is_bool($pValue)) { + $pValue = false; + } + $this->_tblHeader = $pValue; + return $this; + } + + public function getTblHeader() + { + return $this->_tblHeader; + } + + public function setCantSplit($pValue = false) + { + if (!is_bool($pValue)) { + $pValue = false; + } + $this->_cantSplit = $pValue; + return $this; + } + + public function getCantSplit() + { + return $this->_cantSplit; + } +} diff --git a/src/Style/TOC.php b/src/Style/TOC.php new file mode 100644 index 00000000..b7da1059 --- /dev/null +++ b/src/Style/TOC.php @@ -0,0 +1,139 @@ +_tabPos = 9062; + $this->_tabLeader = self::TABLEADER_DOT; + $this->_indent = 200; + } + + /** + * Get Tab Position + * + * @return int + */ + public function getTabPos() + { + return $this->_tabPos; + } + + /** + * Set Tab Position + * + * @param int $pValue + */ + public function setTabPos($pValue) + { + $this->_tabPos = $pValue; + } + + /** + * Get Tab Leader + * + * @return string + */ + public function getTabLeader() + { + return $this->_tabLeader; + } + + /** + * Set Tab Leader + * + * @param string $pValue + */ + public function setTabLeader($pValue = self::TABLEADER_DOT) + { + $this->_tabLeader = $pValue; + } + + /** + * Get Indent + * + * @return int + */ + public function getIndent() + { + return $this->_indent; + } + + /** + * Set Indent + * + * @param string $pValue + */ + public function setIndent($pValue) + { + $this->_indent = $pValue; + } + + /** + * Set style value + * + * @param string $key + * @param string $value + */ + public function setStyleValue($key, $value) + { + $this->$key = $value; + } +} diff --git a/src/Style/Tab.php b/src/Style/Tab.php new file mode 100644 index 00000000..b9d949e9 --- /dev/null +++ b/src/Style/Tab.php @@ -0,0 +1,146 @@ +_val = (self::isStopType($val)) ? $val : 'clear'; + + // Default to 0 if the position is non-numeric + $this->_position = (is_numeric($position)) ? intval($position) : 0; + + // Default to NULL if no tab leader + $this->_leader = (self::isLeaderType($leader)) ? $leader : null; + } + + /** + * Creates the XML DOM for the instance of Tab. + * + * @param PhpOffice\PhpWord\Shared\XMLWriter &$xmlWriter + */ + public function toXml(XMLWriter &$xmlWriter = null) + { + if (isset($xmlWriter)) { + $xmlWriter->startElement("w:tab"); + $xmlWriter->writeAttribute("w:val", $this->_val); + if (!is_null($this->_leader)) { + $xmlWriter->writeAttribute("w:leader", $this->_leader); + } + $xmlWriter->writeAttribute("w:pos", $this->_position); + $xmlWriter->endElement(); + } + } + + /** + * Test if attribute is a valid stop type. + * + * @param string $attribute + * @return bool True if it is; false otherwise. + */ + private static function isStopType($attribute) + { + return in_array($attribute, self::$_possibleStopTypes); + } + + /** + * Test if attribute is a valid leader type. + * + * @param string $attribute + * @return bool True if it is; false otherwise. + */ + private static function isLeaderType($attribute) + { + return in_array($attribute, self::$_possibleLeaders); + } +} diff --git a/src/Style/Table.php b/src/Style/Table.php new file mode 100644 index 00000000..4de56605 --- /dev/null +++ b/src/Style/Table.php @@ -0,0 +1,94 @@ +_cellMarginTop = null; + $this->_cellMarginLeft = null; + $this->_cellMarginRight = null; + $this->_cellMarginBottom = null; + } + + public function setStyleValue($key, $value) + { + $this->$key = $value; + } + + public function setCellMarginTop($pValue = null) + { + $this->_cellMarginTop = $pValue; + } + + public function getCellMarginTop() + { + return $this->_cellMarginTop; + } + + public function setCellMarginLeft($pValue = null) + { + $this->_cellMarginLeft = $pValue; + } + + public function getCellMarginLeft() + { + return $this->_cellMarginLeft; + } + + public function setCellMarginRight($pValue = null) + { + $this->_cellMarginRight = $pValue; + } + + public function getCellMarginRight() + { + return $this->_cellMarginRight; + } + + public function setCellMarginBottom($pValue = null) + { + $this->_cellMarginBottom = $pValue; + } + + public function getCellMarginBottom() + { + return $this->_cellMarginBottom; + } + + public function getCellMargin() + { + return array($this->_cellMarginTop, $this->_cellMarginLeft, $this->_cellMarginRight, $this->_cellMarginBottom); + } +} diff --git a/src/Style/TableFull.php b/src/Style/TableFull.php new file mode 100644 index 00000000..5ca7561b --- /dev/null +++ b/src/Style/TableFull.php @@ -0,0 +1,443 @@ +_firstRow = clone $this; + + unset($this->_firstRow->_firstRow); + unset($this->_firstRow->_cellMarginBottom); + unset($this->_firstRow->_cellMarginTop); + unset($this->_firstRow->_cellMarginLeft); + unset($this->_firstRow->_cellMarginRight); + unset($this->_firstRow->_borderInsideVColor); + unset($this->_firstRow->_borderInsideVSize); + unset($this->_firstRow->_borderInsideHColor); + unset($this->_firstRow->_borderInsideHSize); + foreach ($styleFirstRow as $key => $value) { + if (substr($key, 0, 1) != '_') { + $key = '_' . $key; + } + + $this->_firstRow->setStyleValue($key, $value); + } + } + + if (!is_null($styleTable) && is_array($styleTable)) { + foreach ($styleTable as $key => $value) { + if (substr($key, 0, 1) != '_') { + $key = '_' . $key; + } + $this->setStyleValue($key, $value); + } + } + } + + /** + * @param string $key + * @param mixed $value + */ + public function setStyleValue($key, $value) + { + if ($key == '_borderSize') { + $this->setBorderSize($value); + } elseif ($key == '_borderColor') { + $this->setBorderColor($value); + } elseif ($key == '_cellMargin') { + $this->setCellMargin($value); + } else { + $this->$key = $value; + } + } + + /** + * Get First Row Style + * + * @return PhpOffice\PhpWord\Style\TableFull + */ + public function getFirstRow() + { + return $this->_firstRow; + } + + /** + * Get Last Row Style + * + * @return PhpOffice\PhpWord\Style\TableFull + */ + public function getLastRow() + { + return $this->_lastRow; + } + + public function getBgColor() + { + return $this->_bgColor; + } + + public function setBgColor($pValue = null) + { + $this->_bgColor = $pValue; + } + + /** + * Set TLRBVH Border Size + * + * @param int $pValue Border size in eighths of a point (1/8 point) + */ + public function setBorderSize($pValue = null) + { + $this->_borderTopSize = $pValue; + $this->_borderLeftSize = $pValue; + $this->_borderRightSize = $pValue; + $this->_borderBottomSize = $pValue; + $this->_borderInsideHSize = $pValue; + $this->_borderInsideVSize = $pValue; + } + + /** + * Get TLRBVH Border Size + * + * @return array + */ + public function getBorderSize() + { + $t = $this->getBorderTopSize(); + $l = $this->getBorderLeftSize(); + $r = $this->getBorderRightSize(); + $b = $this->getBorderBottomSize(); + $h = $this->getBorderInsideHSize(); + $v = $this->getBorderInsideVSize(); + + return array($t, $l, $r, $b, $h, $v); + } + + /** + * Set TLRBVH Border Color + */ + public function setBorderColor($pValue = null) + { + $this->_borderTopColor = $pValue; + $this->_borderLeftColor = $pValue; + $this->_borderRightColor = $pValue; + $this->_borderBottomColor = $pValue; + $this->_borderInsideHColor = $pValue; + $this->_borderInsideVColor = $pValue; + } + + /** + * Get TLRB Border Color + * + * @return array + */ + public function getBorderColor() + { + $t = $this->getBorderTopColor(); + $l = $this->getBorderLeftColor(); + $r = $this->getBorderRightColor(); + $b = $this->getBorderBottomColor(); + $h = $this->getBorderInsideHColor(); + $v = $this->getBorderInsideVColor(); + + return array($t, $l, $r, $b, $h, $v); + } + + public function setBorderTopSize($pValue = null) + { + $this->_borderTopSize = $pValue; + } + + public function getBorderTopSize() + { + return $this->_borderTopSize; + } + + public function setBorderTopColor($pValue = null) + { + $this->_borderTopColor = $pValue; + } + + public function getBorderTopColor() + { + return $this->_borderTopColor; + } + + public function setBorderLeftSize($pValue = null) + { + $this->_borderLeftSize = $pValue; + } + + public function getBorderLeftSize() + { + return $this->_borderLeftSize; + } + + public function setBorderLeftColor($pValue = null) + { + $this->_borderLeftColor = $pValue; + } + + public function getBorderLeftColor() + { + return $this->_borderLeftColor; + } + + public function setBorderRightSize($pValue = null) + { + $this->_borderRightSize = $pValue; + } + + public function getBorderRightSize() + { + return $this->_borderRightSize; + } + + public function setBorderRightColor($pValue = null) + { + $this->_borderRightColor = $pValue; + } + + public function getBorderRightColor() + { + return $this->_borderRightColor; + } + + public function setBorderBottomSize($pValue = null) + { + $this->_borderBottomSize = $pValue; + } + + public function getBorderBottomSize() + { + return $this->_borderBottomSize; + } + + public function setBorderBottomColor($pValue = null) + { + $this->_borderBottomColor = $pValue; + } + + public function getBorderBottomColor() + { + return $this->_borderBottomColor; + } + + public function setBorderInsideHColor($pValue = null) + { + $this->_borderInsideHColor = $pValue; + } + + public function getBorderInsideHColor() + { + return (isset($this->_borderInsideHColor)) ? $this->_borderInsideHColor : null; + } + + public function setBorderInsideVColor($pValue = null) + { + $this->_borderInsideVColor = $pValue; + } + + public function getBorderInsideVColor() + { + return (isset($this->_borderInsideVColor)) ? $this->_borderInsideVColor : null; + } + + public function setBorderInsideHSize($pValue = null) + { + $this->_borderInsideHSize = $pValue; + } + + public function getBorderInsideHSize() + { + return (isset($this->_borderInsideHSize)) ? $this->_borderInsideHSize : null; + } + + public function setBorderInsideVSize($pValue = null) + { + $this->_borderInsideVSize = $pValue; + } + + public function getBorderInsideVSize() + { + return (isset($this->_borderInsideVSize)) ? $this->_borderInsideVSize : null; + } + + public function setCellMarginTop($pValue = null) + { + $this->_cellMarginTop = $pValue; + } + + public function getCellMarginTop() + { + return $this->_cellMarginTop; + } + + public function setCellMarginLeft($pValue = null) + { + $this->_cellMarginLeft = $pValue; + } + + public function getCellMarginLeft() + { + return $this->_cellMarginLeft; + } + + public function setCellMarginRight($pValue = null) + { + $this->_cellMarginRight = $pValue; + } + + public function getCellMarginRight() + { + return $this->_cellMarginRight; + } + + public function setCellMarginBottom($pValue = null) + { + $this->_cellMarginBottom = $pValue; + } + + public function getCellMarginBottom() + { + return $this->_cellMarginBottom; + } + + /** + * Set TLRB cell margin + * + * @param int $pValue Margin in twips + */ + public function setCellMargin($pValue = null) + { + $this->_cellMarginTop = $pValue; + $this->_cellMarginLeft = $pValue; + $this->_cellMarginRight = $pValue; + $this->_cellMarginBottom = $pValue; + } + + public function getCellMargin() + { + return array($this->_cellMarginTop, $this->_cellMarginLeft, $this->_cellMarginRight, $this->_cellMarginBottom); + } +} \ No newline at end of file diff --git a/src/Style/Tabs.php b/src/Style/Tabs.php new file mode 100644 index 00000000..45fdb568 --- /dev/null +++ b/src/Style/Tabs.php @@ -0,0 +1,63 @@ +_tabs = $tabs; + } + + /** + * @param PhpOffice\PhpWord\Shared\XMLWriter &$xmlWriter + */ + public function toXml(XMLWriter &$xmlWriter = null) + { + if (isset($xmlWriter)) { + $xmlWriter->startElement("w:tabs"); + foreach ($this->_tabs as &$tab) { + $tab->toXml($xmlWriter); + } + $xmlWriter->endElement(); + } + } +} diff --git a/src/TOC.php b/src/TOC.php new file mode 100644 index 00000000..932e54be --- /dev/null +++ b/src/TOC.php @@ -0,0 +1,155 @@ + $value) { + if (substr($key, 0, 1) != '_') { + $key = '_' . $key; + } + self::$_styleTOC->setStyleValue($key, $value); + } + } + + if (!is_null($styleFont)) { + if (is_array($styleFont)) { + self::$_styleFont = new Font(); + + foreach ($styleFont as $key => $value) { + if (substr($key, 0, 1) != '_') { + $key = '_' . $key; + } + self::$_styleFont->setStyleValue($key, $value); + } + } else { + self::$_styleFont = $styleFont; + } + } + } + + /** + * Add a Title + * + * @return array + */ + public static function addTitle($text, $depth = 0) + { + $anchor = '_Toc' . ++self::$_anchor; + $bookmarkId = self::$_bookmarkId++; + + $title = array(); + $title['text'] = $text; + $title['depth'] = $depth; + $title['anchor'] = $anchor; + $title['bookmarkId'] = $bookmarkId; + + self::$_titles[] = $title; + + return array($anchor, $bookmarkId); + } + + /** + * Get all titles + * + * @return array + */ + public static function getTitles() + { + return self::$_titles; + } + + /** + * Get TOC Style + * + * @return PhpOffice\PhpWord\Style\TOC + */ + public static function getStyleTOC() + { + return self::$_styleTOC; + } + + /** + * Get Font Style + * + * @return PhpOffice\PhpWord\Style\Font + */ + public static function getStyleFont() + { + return self::$_styleFont; + } +} diff --git a/src/Template.php b/src/Template.php new file mode 100644 index 00000000..f934257e --- /dev/null +++ b/src/Template.php @@ -0,0 +1,292 @@ +_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->_objZip = new ZipArchive(); + $this->_objZip->open($this->_tempFileName); + + $this->_documentXML = $this->_objZip->getFromName('word/document.xml'); + } + + /** + * Applies XSL style sheet to template's parts + * + * @param DOMDocument $xslDOMDocument + * @param array $xslOptions + * @param string $xslOptionsURI + * @throws 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) + { + $pattern = '|\$\{([^\}]+)\}|U'; + preg_match_all($pattern, $this->_documentXML, $matches); + foreach ($matches[0] as $value) { + $valueCleaned = preg_replace('/<[^>]+>/', '', $value); + $valueCleaned = preg_replace('/<\/[^>]+>/', '', $valueCleaned); + $this->_documentXML = str_replace($value, $valueCleaned, $this->_documentXML); + } + + if (substr($search, 0, 2) !== '${' && substr($search, -1) !== '}') { + $search = '${' . $search . '}'; + } + + if (!is_array($replace)) { + if (!String::IsUTF8($replace)) { + $replace = utf8_encode($replace); + } + $replace = htmlspecialchars($replace); + } else { + foreach ($replace as $key => $value) { + $replace[$key] = htmlspecialchars($value); + } + } + + $regExpDelim = '/'; + $escapedSearch = preg_quote($search, $regExpDelim); + $this->_documentXML = preg_replace("{$regExpDelim}{$escapedSearch}{$regExpDelim}u", $replace, $this->_documentXML, $limit); + } + + /** + * Returns array of all variables in template + */ + public function getVariables() + { + preg_match_all('/\$\{(.*?)}/i', $this->_documentXML, $matches); + return $matches[1]; + } + + /** + * Find the start position of the nearest table row before $offset + * + * @param int $offset + * @return int + * @throws 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 int $offset + * @return int + */ + private function _findRowEnd($offset) + { + $rowEnd = strpos($this->_documentXML, "", $offset) + 7; + return $rowEnd; + } + + /** + * Get a slice of a string + * + * @param int $startPosition + * @param int $endPosition + * @return string + */ + private function _getSlice($startPosition, $endPosition = 0) + { + if (!$endPosition) { + $endPosition = strlen($this->_documentXML); + } + return substr($this->_documentXML, $startPosition, ($endPosition - $startPosition)); + } + + /** + * Clone a table row in a template document + * + * @param string $search + * @param int $numberOfClones + * @throws 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; + } + + /** + * Save Template + * + * @return string + * @throws Exception + */ + public function save() + { + $this->_objZip->addFromString('word/document.xml', $this->_documentXML); + + // Close zip file + if ($this->_objZip->close() === false) { + throw new Exception('Could not close zip file.'); + } + + return $this->_tempFileName; + } + + /** + * Save Template As... + * + * @param string $strFilename + */ + public function saveAs($strFilename) + { + $tempFilename = $this->save(); + + if (file_exists($strFilename)) { + unlink($strFilename); + } + + rename($tempFilename, $strFilename); + } +} \ No newline at end of file diff --git a/src/Writer/IWriter.php b/src/Writer/IWriter.php new file mode 100644 index 00000000..98c15704 --- /dev/null +++ b/src/Writer/IWriter.php @@ -0,0 +1,39 @@ +setPhpWord($phpWord); + + // Set up disk caching location + $this->_diskCachingDirectory = './'; + + // Initialise writer parts + $this->_writerParts['content'] = new Content(); + $this->_writerParts['manifest'] = new Manifest(); + $this->_writerParts['meta'] = new Meta(); + $this->_writerParts['mimetype'] = new Mimetype(); + $this->_writerParts['styles'] = new Styles(); + + + // Assign parent IWriter + foreach ($this->_writerParts as $writer) { + $writer->setParentWriter($this); + } + + // Set HashTable variables + $this->_drawingHashTable = new HashTable(); + } + + /** + * Save PhpWord to file + * + * @param string $pFileName + * @throws \Exception + */ + public function save($pFilename = null) + { + if (!is_null($this->_document)) { + // If $pFilename is php://output or php://stdout, make it a temporary file... + $originalFilename = $pFilename; + if (strtolower($pFilename) == 'php://output' || strtolower($pFilename) == 'php://stdout') { + $pFilename = @tempnam('./', 'phppttmp'); + if ($pFilename == '') { + $pFilename = $originalFilename; + } + } + + // Create drawing dictionary + + // Create new ZIP file and open it for writing + $objZip = new ZipArchive(); + + // Try opening the ZIP file + if ($objZip->open($pFilename, ZIPARCHIVE::OVERWRITE) !== true) { + if ($objZip->open($pFilename, ZIPARCHIVE::CREATE) !== true) { + throw new \Exception("Could not open " . $pFilename . " for writing."); + } + } + + // Add mimetype to ZIP file + //@todo Not in ZIPARCHIVE::CM_STORE mode + $objZip->addFromString('mimetype', $this->getWriterPart('mimetype')->writeMimetype($this->_document)); + + // Add content.xml to ZIP file + $objZip->addFromString('content.xml', $this->getWriterPart('content')->writeContent($this->_document)); + + // Add meta.xml to ZIP file + $objZip->addFromString('meta.xml', $this->getWriterPart('meta')->writeMeta($this->_document)); + + // Add styles.xml to ZIP file + $objZip->addFromString('styles.xml', $this->getWriterPart('styles')->writeStyles($this->_document)); + + // Add META-INF/manifest.xml + $objZip->addFromString('META-INF/manifest.xml', $this->getWriterPart('manifest')->writeManifest($this->_document)); + + // Add media. Has not used yet. Legacy from PHPExcel. + // @codeCoverageIgnoreStart + for ($i = 0; $i < $this->getDrawingHashTable()->count(); ++$i) { + if ($this->getDrawingHashTable()->getByIndex($i) instanceof PHPWord_Shape_Drawing) { + $imageContents = null; + $imagePath = $this->getDrawingHashTable()->getByIndex($i)->getPath(); + + if (strpos($imagePath, 'zip://') !== false) { + $imagePath = substr($imagePath, 6); + $imagePathSplitted = explode('#', $imagePath); + + $imageZip = new ZipArchive(); + $imageZip->open($imagePathSplitted[0]); + $imageContents = $imageZip->getFromName($imagePathSplitted[1]); + $imageZip->close(); + unset($imageZip); + } else { + $imageContents = file_get_contents($imagePath); + } + + $objZip->addFromString('Pictures/' . str_replace(' ', '_', $this->getDrawingHashTable()->getByIndex($i)->getIndexedFilename()), $imageContents); + } elseif ($this->getDrawingHashTable()->getByIndex($i) instanceof PHPWord_Shape_MemoryDrawing) { + ob_start(); + call_user_func( + $this->getDrawingHashTable()->getByIndex($i)->getRenderingFunction(), + $this->getDrawingHashTable()->getByIndex($i)->getImageResource() + ); + $imageContents = ob_get_contents(); + ob_end_clean(); + + $objZip->addFromString('Pictures/' . str_replace(' ', '_', $this->getDrawingHashTable()->getByIndex($i)->getIndexedFilename()), $imageContents); + } + } + // @codeCoverageIgnoreEnd + + // Close file + if ($objZip->close() === false) { + throw new \Exception("Could not close zip file $pFilename."); + } + + // If a temporary file was used, copy it to the correct file stream + if ($originalFilename != $pFilename) { + if (copy($pFilename, $originalFilename) === false) { + throw new \Exception("Could not copy temporary zip file $pFilename to $originalFilename."); + } + @unlink($pFilename); + } + + } else { + throw new \Exception("PhpWord object unassigned."); + } + } + + /** + * @return PhpOffice\PhpWord + * @throws \Exception + */ + public function getPhpWord() + { + if (!is_null($this->_document)) { + return $this->_document; + } else { + throw new \Exception("No PhpWord assigned."); + } + } + + /** + * @param PhpOffice\PhpWord $phpWord + * @return PhpOffice\PhpWord\Writer\ODText + */ + public function setPhpWord(PhpWord $phpWord = null) + { + $this->_document = $phpWord; + return $this; + } + + /** + * Get PHPWord_Worksheet_BaseDrawing HashTable + * + * @return PhpOffice\PhpWord\HashTable + */ + public function getDrawingHashTable() + { + return $this->_drawingHashTable; + } + + /** + * @param string $pPartName Writer part name + * @return PhpOffice\PhpWord\Writer\ODText\WriterPart + */ + public function getWriterPart($pPartName = '') + { + if ($pPartName != '' && isset($this->_writerParts[strtolower($pPartName)])) { + return $this->_writerParts[strtolower($pPartName)]; + } else { + return null; + } + } + + /** + * Get use disk caching where possible? + * + * @return boolean + */ + public function getUseDiskCaching() + { + return $this->_useDiskCaching; + } + + /** + * Set use disk caching where possible? + * + * @param boolean $pValue + * @param string $pDirectory Disk caching directory + * @throws \Exception Exception when directory does not exist + * @return PhpOffice\PhpWord\Writer\ODText + */ + public function setUseDiskCaching($pValue = false, $pDirectory = null) + { + $this->_useDiskCaching = $pValue; + + if (!is_null($pDirectory)) { + if (is_dir($pDirectory)) { + $this->_diskCachingDirectory = $pDirectory; + } else { + throw new \Exception("Directory does not exist: $pDirectory"); + } + } + + return $this; + } + + /** + * @return string + */ + public function getDiskCachingDirectory() + { + return $this->_diskCachingDirectory; + } +} \ No newline at end of file diff --git a/src/Writer/ODText/Content.php b/src/Writer/ODText/Content.php new file mode 100644 index 00000000..c809708f --- /dev/null +++ b/src/Writer/ODText/Content.php @@ -0,0 +1,412 @@ +getParentWriter()->getUseDiskCaching()) { + $xmlWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $xmlWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY); + } + + // XML header + $xmlWriter->startDocument('1.0', 'UTF-8'); + + // office:document-content + $xmlWriter->startElement('office:document-content'); + $xmlWriter->writeAttribute('xmlns:office', 'urn:oasis:names:tc:opendocument:xmlns:office:1.0'); + $xmlWriter->writeAttribute('xmlns:style', 'urn:oasis:names:tc:opendocument:xmlns:style:1.0'); + $xmlWriter->writeAttribute('xmlns:text', 'urn:oasis:names:tc:opendocument:xmlns:text:1.0'); + $xmlWriter->writeAttribute('xmlns:table', 'urn:oasis:names:tc:opendocument:xmlns:table:1.0'); + $xmlWriter->writeAttribute('xmlns:draw', 'urn:oasis:names:tc:opendocument:xmlns:drawing:1.0'); + $xmlWriter->writeAttribute('xmlns:fo', 'urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0'); + $xmlWriter->writeAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink'); + $xmlWriter->writeAttribute('xmlns:dc', 'http://purl.org/dc/elements/1.1/'); + $xmlWriter->writeAttribute('xmlns:meta', 'urn:oasis:names:tc:opendocument:xmlns:meta:1.0'); + $xmlWriter->writeAttribute('xmlns:number', 'urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0'); + $xmlWriter->writeAttribute('xmlns:svg', 'urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0'); + $xmlWriter->writeAttribute('xmlns:chart', 'urn:oasis:names:tc:opendocument:xmlns:chart:1.0'); + $xmlWriter->writeAttribute('xmlns:dr3d', 'urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0'); + $xmlWriter->writeAttribute('xmlns:math', 'http://www.w3.org/1998/Math/MathML'); + $xmlWriter->writeAttribute('xmlns:form', 'urn:oasis:names:tc:opendocument:xmlns:form:1.0'); + $xmlWriter->writeAttribute('xmlns:script', 'urn:oasis:names:tc:opendocument:xmlns:script:1.0'); + $xmlWriter->writeAttribute('xmlns:ooo', 'http://openoffice.org/2004/office'); + $xmlWriter->writeAttribute('xmlns:ooow', 'http://openoffice.org/2004/writer'); + $xmlWriter->writeAttribute('xmlns:oooc', 'http://openoffice.org/2004/calc'); + $xmlWriter->writeAttribute('xmlns:dom', 'http://www.w3.org/2001/xml-events'); + $xmlWriter->writeAttribute('xmlns:xforms', 'http://www.w3.org/2002/xforms'); + $xmlWriter->writeAttribute('xmlns:xsd', 'http://www.w3.org/2001/XMLSchema'); + $xmlWriter->writeAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance'); + $xmlWriter->writeAttribute('xmlns:rpt', 'http://openoffice.org/2005/report'); + $xmlWriter->writeAttribute('xmlns:of', 'urn:oasis:names:tc:opendocument:xmlns:of:1.2'); + $xmlWriter->writeAttribute('xmlns:xhtml', 'http://www.w3.org/1999/xhtml'); + $xmlWriter->writeAttribute('xmlns:grddl', 'http://www.w3.org/2003/g/data-view#'); + $xmlWriter->writeAttribute('xmlns:tableooo', 'http://openoffice.org/2009/table'); + $xmlWriter->writeAttribute('xmlns:field', 'urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0'); + $xmlWriter->writeAttribute('xmlns:formx', 'urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0'); + $xmlWriter->writeAttribute('xmlns:css3t', 'http://www.w3.org/TR/css3-text/'); + $xmlWriter->writeAttribute('office:version', '1.2'); + + // We firstly search all fonts used + $_sections = $phpWord->getSections(); + $countSections = count($_sections); + if ($countSections > 0) { + $pSection = 0; + $numPStyles = 0; + $numFStyles = 0; + + foreach ($_sections as $section) { + $pSection++; + $_elements = $section->getElements(); + + foreach ($_elements as $element) { + if ($element instanceof Text) { + $fStyle = $element->getFontStyle(); + $pStyle = $element->getParagraphStyle(); + + if ($fStyle instanceof Font) { + $numFStyles++; + + $arrStyle = array( + 'color' => $fStyle->getColor(), + 'name' => $fStyle->getName() + ); + $phpWord->addFontStyle('T' . $numFStyles, $arrStyle); + $element->setFontStyle('T' . $numFStyles); + } elseif ($pStyle instanceof Paragraph) { + $numPStyles++; + + $phpWord->addParagraphStyle('P' . $numPStyles, array()); + $element->setParagraphStyle('P' . $numPStyles); + } + } + } + } + } + + // office:font-face-decls + $xmlWriter->startElement('office:font-face-decls'); + $arrFonts = array(); + + $styles = Style::getStyles(); + $numFonts = 0; + if (count($styles) > 0) { + foreach ($styles as $styleName => $style) { + // PhpOffice\PhpWord\Style\Font + if ($style instanceof Font) { + $numFonts++; + $name = $style->getName(); + if (!in_array($name, $arrFonts)) { + $arrFonts[] = $name; + + // style:font-face + $xmlWriter->startElement('style:font-face'); + $xmlWriter->writeAttribute('style:name', $name); + $xmlWriter->writeAttribute('svg:font-family', $name); + $xmlWriter->endElement(); + } + } + } + if (!in_array(PhpWord::DEFAULT_FONT_NAME, $arrFonts)) { + $xmlWriter->startElement('style:font-face'); + $xmlWriter->writeAttribute('style:name', PhpWord::DEFAULT_FONT_NAME); + $xmlWriter->writeAttribute('svg:font-family', PhpWord::DEFAULT_FONT_NAME); + $xmlWriter->endElement(); + } + } + $xmlWriter->endElement(); + + $xmlWriter->startElement('office:automatic-styles'); + $styles = Style::getStyles(); + $numPStyles = 0; + if (count($styles) > 0) { + foreach ($styles as $styleName => $style) { + if (preg_match('#^T[0-9]+$#', $styleName) != 0 + || preg_match('#^P[0-9]+$#', $styleName) != 0 + ) { + // PhpOffice\PhpWord\Style\Font + if ($style instanceof Font) { + $xmlWriter->startElement('style:style'); + $xmlWriter->writeAttribute('style:name', $styleName); + $xmlWriter->writeAttribute('style:family', 'text'); + // style:text-properties + $xmlWriter->startElement('style:text-properties'); + $xmlWriter->writeAttribute('fo:color', '#' . $style->getColor()); + $xmlWriter->writeAttribute('style:font-name', $style->getName()); + $xmlWriter->writeAttribute('style:font-name-complex', $style->getName()); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + } + if ($style instanceof Paragraph) { + $numPStyles++; + // style:style + $xmlWriter->startElement('style:style'); + $xmlWriter->writeAttribute('style:name', $styleName); + $xmlWriter->writeAttribute('style:family', 'paragraph'); + $xmlWriter->writeAttribute('style:parent-style-name', 'Standard'); + $xmlWriter->writeAttribute('style:master-page-name', 'Standard'); + // style:paragraph-properties + $xmlWriter->startElement('style:paragraph-properties'); + $xmlWriter->writeAttribute('style:page-number', 'auto'); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + } + } + } + + if ($numPStyles == 0) { + // style:style + $xmlWriter->startElement('style:style'); + $xmlWriter->writeAttribute('style:name', 'P1'); + $xmlWriter->writeAttribute('style:family', 'paragraph'); + $xmlWriter->writeAttribute('style:parent-style-name', 'Standard'); + $xmlWriter->writeAttribute('style:master-page-name', 'Standard'); + // style:paragraph-properties + $xmlWriter->startElement('style:paragraph-properties'); + $xmlWriter->writeAttribute('style:page-number', 'auto'); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + } + } + $xmlWriter->endElement(); + + // office:body + $xmlWriter->startElement('office:body'); + // office:text + $xmlWriter->startElement('office:text'); + // text:sequence-decls + $xmlWriter->startElement('text:sequence-decls'); + // text:sequence-decl + $xmlWriter->startElement('text:sequence-decl'); + $xmlWriter->writeAttribute('text:display-outline-level', 0); + $xmlWriter->writeAttribute('text:name', 'Illustration'); + $xmlWriter->endElement(); + // text:sequence-decl + $xmlWriter->startElement('text:sequence-decl'); + $xmlWriter->writeAttribute('text:display-outline-level', 0); + $xmlWriter->writeAttribute('text:name', 'Table'); + $xmlWriter->endElement(); + // text:sequence-decl + $xmlWriter->startElement('text:sequence-decl'); + $xmlWriter->writeAttribute('text:display-outline-level', 0); + $xmlWriter->writeAttribute('text:name', 'Text'); + $xmlWriter->endElement(); + // text:sequence-decl + $xmlWriter->startElement('text:sequence-decl'); + $xmlWriter->writeAttribute('text:display-outline-level', 0); + $xmlWriter->writeAttribute('text:name', 'Drawing'); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + + $_sections = $phpWord->getSections(); + $countSections = count($_sections); + $pSection = 0; + + if ($countSections > 0) { + foreach ($_sections as $section) { + $pSection++; + + $_elements = $section->getElements(); + + foreach ($_elements as $element) { + if ($element instanceof Text) { + $this->_writeText($xmlWriter, $element); + } elseif ($element instanceof TextRun) { + $this->_writeTextRun($xmlWriter, $element); + } elseif ($element instanceof TextBreak) { + $this->_writeTextBreak($xmlWriter); + } elseif ($element instanceof Link) { + $this->writeUnsupportedElement($xmlWriter, 'Link'); + } elseif ($element instanceof Title) { + $this->writeUnsupportedElement($xmlWriter, 'Title'); + } elseif ($element instanceof PageBreak) { + $this->writeUnsupportedElement($xmlWriter, 'Page Break'); + } elseif ($element instanceof Table) { + $this->writeUnsupportedElement($xmlWriter, 'Table'); + } elseif ($element instanceof ListItem) { + $this->writeUnsupportedElement($xmlWriter, 'List Item'); + } elseif ($element instanceof Image || + $element instanceof MemoryImage) { + $this->writeUnsupportedElement($xmlWriter, 'Image'); + } elseif ($element instanceof Object) { + $this->writeUnsupportedElement($xmlWriter, 'Object'); + } elseif ($element instanceof TOC) { + $this->writeUnsupportedElement($xmlWriter, 'TOC'); + } else { + $this->writeUnsupportedElement($xmlWriter, 'Element'); + } + } + + if ($pSection == $countSections) { + $this->_writeEndSection($xmlWriter, $section); + } else { + $this->_writeSection($xmlWriter, $section); + } + } + } + $xmlWriter->endElement(); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + + // Return + return $xmlWriter->getData(); + } + + /** + * Write text + * + * @param PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param PhpOffice\PhpWord\Section\Text $text + * @param bool $withoutP + */ + protected function _writeText(XMLWriter $xmlWriter = null, Text $text, $withoutP = false) + { + $styleFont = $text->getFontStyle(); + $styleParagraph = $text->getParagraphStyle(); + + // @todo Commented for TextRun. Should really checkout this value + // $SfIsObject = ($styleFont instanceof Font) ? true : false; + $SfIsObject = false; + + if ($SfIsObject) { + // Don't never be the case, because I browse all sections for cleaning all styles not declared + die('PhpWord : $SfIsObject wouldn\'t be an object'); + } else { + if (!$withoutP) { + $xmlWriter->startElement('text:p'); // text:p + } + if (empty($styleFont)) { + if (empty($styleParagraph)) { + $xmlWriter->writeAttribute('text:style-name', 'P1'); + } else { + $xmlWriter->writeAttribute('text:style-name', $text->getParagraphStyle()); + } + $xmlWriter->writeRaw($text->getText()); + } else { + if (empty($styleParagraph)) { + $xmlWriter->writeAttribute('text:style-name', 'Standard'); + } else { + $xmlWriter->writeAttribute('text:style-name', $text->getParagraphStyle()); + } + // text:span + $xmlWriter->startElement('text:span'); + $xmlWriter->writeAttribute('text:style-name', $styleFont); + $xmlWriter->writeRaw($text->getText()); + $xmlWriter->endElement(); + } + if (!$withoutP) { + $xmlWriter->endElement(); // text:p + } + } + } + + /** + * Write TextRun section + * + * @param PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param PhpOffice\PhpWord\Section\TextRun $textrun + * @todo Enable all other section types + */ + protected function _writeTextRun(XMLWriter $xmlWriter = null, TextRun $textrun) + { + $elements = $textrun->getElements(); + $xmlWriter->startElement('text:p'); + if (count($elements) > 0) { + foreach ($elements as $element) { + if ($element instanceof Text) { + $this->_writeText($xmlWriter, $element, true); + } + } + } + $xmlWriter->endElement(); + } + + /** + * Write TextBreak + */ + protected function _writeTextBreak(XMLWriter $xmlWriter = null) + { + $xmlWriter->startElement('text:p'); + $xmlWriter->writeAttribute('text:style-name', 'Standard'); + $xmlWriter->endElement(); + } + + // @codeCoverageIgnoreStart + private function _writeEndSection(XMLWriter $xmlWriter = null, Section $section = null) + { + } + + private function _writeSection(XMLWriter $xmlWriter = null, Section $section = null) + { + } + // @codeCoverageIgnoreEnd + + /** + * Write unsupported element + * + * @param PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param string $element + */ + private function writeUnsupportedElement($xmlWriter, $element) + { + $xmlWriter->startElement('text:p'); + $xmlWriter->writeRaw($element); + $xmlWriter->endElement(); + } +} \ No newline at end of file diff --git a/src/Writer/ODText/Manifest.php b/src/Writer/ODText/Manifest.php new file mode 100644 index 00000000..f27f1350 --- /dev/null +++ b/src/Writer/ODText/Manifest.php @@ -0,0 +1,132 @@ +getParentWriter()->getUseDiskCaching()) { + $xmlWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $xmlWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY); + } + + // XML header + $xmlWriter->startDocument('1.0', 'UTF-8'); + + // manifest:manifest + $xmlWriter->startElement('manifest:manifest'); + $xmlWriter->writeAttribute('xmlns:manifest', 'urn:oasis:names:tc:opendocument:xmlns:manifest:1.0'); + $xmlWriter->writeAttribute('manifest:version', '1.2'); + + // manifest:file-entry + $xmlWriter->startElement('manifest:file-entry'); + $xmlWriter->writeAttribute('manifest:media-type', 'application/vnd.oasis.opendocument.text'); + $xmlWriter->writeAttribute('manifest:version', '1.2'); + $xmlWriter->writeAttribute('manifest:full-path', '/'); + $xmlWriter->endElement(); + // manifest:file-entry + $xmlWriter->startElement('manifest:file-entry'); + $xmlWriter->writeAttribute('manifest:media-type', 'text/xml'); + $xmlWriter->writeAttribute('manifest:full-path', 'content.xml'); + $xmlWriter->endElement(); + // manifest:file-entry + $xmlWriter->startElement('manifest:file-entry'); + $xmlWriter->writeAttribute('manifest:media-type', 'text/xml'); + $xmlWriter->writeAttribute('manifest:full-path', 'meta.xml'); + $xmlWriter->endElement(); + // manifest:file-entry + $xmlWriter->startElement('manifest:file-entry'); + $xmlWriter->writeAttribute('manifest:media-type', 'text/xml'); + $xmlWriter->writeAttribute('manifest:full-path', 'styles.xml'); + $xmlWriter->endElement(); + + // Not used yet. Legacy from PHPExcel + // @codeCoverageIgnoreStart + for ($i = 0; $i < $this->getParentWriter()->getDrawingHashTable()->count(); ++$i) { + if ($this->getParentWriter()->getDrawingHashTable()->getByIndex($i) instanceof PHPWord_Shape_Drawing) { + $extension = strtolower($this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getExtension()); + $mimeType = $this->_getImageMimeType($this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getPath()); + + $xmlWriter->startElement('manifest:file-entry'); + $xmlWriter->writeAttribute('manifest:media-type', $mimeType); + $xmlWriter->writeAttribute('manifest:full-path', 'Pictures/' . str_replace(' ', '_', $this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getIndexedFilename())); + $xmlWriter->endElement(); + } elseif ($this->getParentWriter()->getDrawingHashTable()->getByIndex($i) instanceof PHPWord_Shape_MemoryDrawing) { + $extension = strtolower($this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getMimeType()); + $extension = explode('/', $extension); + $extension = $extension[1]; + + $mimeType = $this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getMimeType(); + + $xmlWriter->startElement('manifest:file-entry'); + $xmlWriter->writeAttribute('manifest:media-type', $mimeType); + $xmlWriter->writeAttribute('manifest:full-path', 'Pictures/' . str_replace(' ', '_', $this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getIndexedFilename())); + $xmlWriter->endElement(); + } + } + // @codeCoverageIgnoreEnd + + $xmlWriter->endElement(); + + // Return + return $xmlWriter->getData(); + } + + + /** + * Get image mime type + * + * @param string $pFile Filename + * @return string Mime Type + * @throws Exception + */ + private function _getImageMimeType($pFile = '') + { + if (File::file_exists($pFile)) { + $image = getimagesize($pFile); + return image_type_to_mime_type($image[2]); + } else { + throw new Exception("File $pFile does not exist"); + } + } +} diff --git a/src/Writer/ODText/Meta.php b/src/Writer/ODText/Meta.php new file mode 100644 index 00000000..1b30efa3 --- /dev/null +++ b/src/Writer/ODText/Meta.php @@ -0,0 +1,96 @@ +getParentWriter()->getUseDiskCaching()) { + $xmlWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $xmlWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY); + } + + // XML header + $xmlWriter->startDocument('1.0', 'UTF-8'); + + // office:document-meta + $xmlWriter->startElement('office:document-meta'); + $xmlWriter->writeAttribute('xmlns:office', 'urn:oasis:names:tc:opendocument:xmlns:office:1.0'); + $xmlWriter->writeAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink'); + $xmlWriter->writeAttribute('xmlns:dc', 'http://purl.org/dc/elements/1.1/'); + $xmlWriter->writeAttribute('xmlns:meta', 'urn:oasis:names:tc:opendocument:xmlns:meta:1.0'); + $xmlWriter->writeAttribute('xmlns:ooo', 'http://openoffice.org/2004/office'); + $xmlWriter->writeAttribute('xmlns:grddl', 'http://www.w3.org/2003/g/data-view#'); + $xmlWriter->writeAttribute('office:version', '1.2'); + + // office:meta + $xmlWriter->startElement('office:meta'); + + // dc:creator + $xmlWriter->writeElement('dc:creator', $phpWord->getDocumentProperties()->getLastModifiedBy()); + // dc:date + $xmlWriter->writeElement('dc:date', gmdate('Y-m-d\TH:i:s.000', $phpWord->getDocumentProperties()->getModified())); + // dc:description + $xmlWriter->writeElement('dc:description', $phpWord->getDocumentProperties()->getDescription()); + // dc:subject + $xmlWriter->writeElement('dc:subject', $phpWord->getDocumentProperties()->getSubject()); + // dc:title + $xmlWriter->writeElement('dc:title', $phpWord->getDocumentProperties()->getTitle()); + // meta:creation-date + $xmlWriter->writeElement('meta:creation-date', gmdate('Y-m-d\TH:i:s.000', $phpWord->getDocumentProperties()->getCreated())); + // meta:initial-creator + $xmlWriter->writeElement('meta:initial-creator', $phpWord->getDocumentProperties()->getCreator()); + // meta:keyword + $xmlWriter->writeElement('meta:keyword', $phpWord->getDocumentProperties()->getKeywords()); + + // @todo : Where these properties are written ? + // $phpWord->getDocumentProperties()->getCategory() + // $phpWord->getDocumentProperties()->getCompany() + + $xmlWriter->endElement(); + + $xmlWriter->endElement(); + + // Return + return $xmlWriter->getData(); + } +} diff --git a/src/Writer/ODText/Mimetype.php b/src/Writer/ODText/Mimetype.php new file mode 100644 index 00000000..59386d5a --- /dev/null +++ b/src/Writer/ODText/Mimetype.php @@ -0,0 +1,46 @@ +getParentWriter()->getUseDiskCaching()) { + $xmlWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $xmlWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY); + } + + // XML header + $xmlWriter->startDocument('1.0', 'UTF-8'); + + // Styles:Styles + $xmlWriter->startElement('office:document-styles'); + $xmlWriter->writeAttribute('xmlns:office', 'urn:oasis:names:tc:opendocument:xmlns:office:1.0'); + $xmlWriter->writeAttribute('xmlns:style', 'urn:oasis:names:tc:opendocument:xmlns:style:1.0'); + $xmlWriter->writeAttribute('xmlns:text', 'urn:oasis:names:tc:opendocument:xmlns:text:1.0'); + $xmlWriter->writeAttribute('xmlns:table', 'urn:oasis:names:tc:opendocument:xmlns:table:1.0'); + $xmlWriter->writeAttribute('xmlns:draw', 'urn:oasis:names:tc:opendocument:xmlns:drawing:1.0'); + $xmlWriter->writeAttribute('xmlns:fo', 'urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0'); + $xmlWriter->writeAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink'); + $xmlWriter->writeAttribute('xmlns:dc', 'http://purl.org/dc/elements/1.1/'); + $xmlWriter->writeAttribute('xmlns:meta', 'urn:oasis:names:tc:opendocument:xmlns:meta:1.0'); + $xmlWriter->writeAttribute('xmlns:number', 'urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0'); + $xmlWriter->writeAttribute('xmlns:svg', 'urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0'); + $xmlWriter->writeAttribute('xmlns:chart', 'urn:oasis:names:tc:opendocument:xmlns:chart:1.0'); + $xmlWriter->writeAttribute('xmlns:dr3d', 'urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0'); + $xmlWriter->writeAttribute('xmlns:math', 'http://www.w3.org/1998/Math/MathML'); + $xmlWriter->writeAttribute('xmlns:form', 'urn:oasis:names:tc:opendocument:xmlns:form:1.0'); + $xmlWriter->writeAttribute('xmlns:script', 'urn:oasis:names:tc:opendocument:xmlns:script:1.0'); + $xmlWriter->writeAttribute('xmlns:ooo', 'http://openoffice.org/2004/office'); + $xmlWriter->writeAttribute('xmlns:ooow', 'http://openoffice.org/2004/writer'); + $xmlWriter->writeAttribute('xmlns:oooc', 'http://openoffice.org/2004/calc'); + $xmlWriter->writeAttribute('xmlns:dom', 'http://www.w3.org/2001/xml-events'); + $xmlWriter->writeAttribute('xmlns:rpt', 'http://openoffice.org/2005/report'); + $xmlWriter->writeAttribute('xmlns:of', 'urn:oasis:names:tc:opendocument:xmlns:of:1.2'); + $xmlWriter->writeAttribute('xmlns:xhtml', 'http://www.w3.org/1999/xhtml'); + $xmlWriter->writeAttribute('xmlns:grddl', 'http://www.w3.org/2003/g/data-view#'); + $xmlWriter->writeAttribute('xmlns:tableooo', 'http://openoffice.org/2009/table'); + $xmlWriter->writeAttribute('xmlns:css3t', 'http://www.w3.org/TR/css3-text/'); + $xmlWriter->writeAttribute('office:version', '1.2'); + + + // office:font-face-decls + $xmlWriter->startElement('office:font-face-decls'); + $arrFonts = array(); + $styles = Style::getStyles(); + $numFonts = 0; + if (count($styles) > 0) { + foreach ($styles as $styleName => $style) { + // PhpOffice\PhpWord\Style\Font + if ($style instanceof Font) { + $numFonts++; + $name = $style->getName(); + if (!in_array($name, $arrFonts)) { + $arrFonts[] = $name; + + // style:font-face + $xmlWriter->startElement('style:font-face'); + $xmlWriter->writeAttribute('style:name', $name); + $xmlWriter->writeAttribute('svg:font-family', $name); + $xmlWriter->endElement(); + } + } + } + } + if (!in_array(PhpWord::DEFAULT_FONT_NAME, $arrFonts)) { + $xmlWriter->startElement('style:font-face'); + $xmlWriter->writeAttribute('style:name', PhpWord::DEFAULT_FONT_NAME); + $xmlWriter->writeAttribute('svg:font-family', PhpWord::DEFAULT_FONT_NAME); + $xmlWriter->endElement(); + } + $xmlWriter->endElement(); + + // office:styles + $xmlWriter->startElement('office:styles'); + + // style:default-style + $xmlWriter->startElement('style:default-style'); + $xmlWriter->writeAttribute('style:family', 'paragraph'); + + // style:paragraph-properties + $xmlWriter->startElement('style:paragraph-properties'); + $xmlWriter->writeAttribute('fo:hyphenation-ladder-count', 'no-limit'); + $xmlWriter->writeAttribute('style:text-autospace', 'ideograph-alpha'); + $xmlWriter->writeAttribute('style:punctuation-wrap', 'hanging'); + $xmlWriter->writeAttribute('style:line-break', 'strict'); + $xmlWriter->writeAttribute('style:tab-stop-distance', '1.249cm'); + $xmlWriter->writeAttribute('style:writing-mode', 'page'); + $xmlWriter->endElement(); + + // style:text-properties + $xmlWriter->startElement('style:text-properties'); + $xmlWriter->writeAttribute('style:use-window-font-color', 'true'); + $xmlWriter->writeAttribute('style:font-name', PhpWord::DEFAULT_FONT_NAME); + $xmlWriter->writeAttribute('fo:font-size', PhpWord::DEFAULT_FONT_SIZE . 'pt'); + $xmlWriter->writeAttribute('fo:language', 'fr'); + $xmlWriter->writeAttribute('fo:country', 'FR'); + $xmlWriter->writeAttribute('style:letter-kerning', 'true'); + $xmlWriter->writeAttribute('style:font-name-asian', PhpWord::DEFAULT_FONT_NAME . '2'); + $xmlWriter->writeAttribute('style:font-size-asian', PhpWord::DEFAULT_FONT_SIZE . 'pt'); + $xmlWriter->writeAttribute('style:language-asian', 'zh'); + $xmlWriter->writeAttribute('style:country-asian', 'CN'); + $xmlWriter->writeAttribute('style:font-name-complex', PhpWord::DEFAULT_FONT_NAME . '2'); + $xmlWriter->writeAttribute('style:font-size-complex', PhpWord::DEFAULT_FONT_SIZE . 'pt'); + $xmlWriter->writeAttribute('style:language-complex', 'hi'); + $xmlWriter->writeAttribute('style:country-complex', 'IN'); + $xmlWriter->writeAttribute('fo:hyphenate', 'false'); + $xmlWriter->writeAttribute('fo:hyphenation-remain-char-count', '2'); + $xmlWriter->writeAttribute('fo:hyphenation-push-char-count', '2'); + $xmlWriter->endElement(); + + $xmlWriter->endElement(); + + // Write Style Definitions + $styles = Style::getStyles(); + if (count($styles) > 0) { + foreach ($styles as $styleName => $style) { + if (preg_match('#^T[0-9]+$#', $styleName) == 0 + && preg_match('#^P[0-9]+$#', $styleName) == 0 + ) { + // PhpOffice\PhpWord\Style\Font + if ($style instanceof Font) { + // style:style + $xmlWriter->startElement('style:style'); + $xmlWriter->writeAttribute('style:name', $styleName); + $xmlWriter->writeAttribute('style:family', 'text'); + + // style:text-properties + $xmlWriter->startElement('style:text-properties'); + $xmlWriter->writeAttribute('fo:font-size', ($style->getSize()) . 'pt'); + $xmlWriter->writeAttribute('style:font-size-asian', ($style->getSize()) . 'pt'); + $xmlWriter->writeAttribute('style:font-size-complex', ($style->getSize()) . 'pt'); + if ($style->getItalic()) { + $xmlWriter->writeAttribute('fo:font-style', 'italic'); + $xmlWriter->writeAttribute('style:font-style-asian', 'italic'); + $xmlWriter->writeAttribute('style:font-style-complex', 'italic'); + } + if ($style->getBold()) { + $xmlWriter->writeAttribute('fo:font-weight', 'bold'); + $xmlWriter->writeAttribute('style:font-weight-asian', 'bold'); + } + $xmlWriter->endElement(); + $xmlWriter->endElement(); + } elseif ($style instanceof Paragraph) { + // PhpOffice\PhpWord\Style\Paragraph + // style:style + $xmlWriter->startElement('style:style'); + $xmlWriter->writeAttribute('style:name', $styleName); + $xmlWriter->writeAttribute('style:family', 'paragraph'); + + //style:paragraph-properties + $xmlWriter->startElement('style:paragraph-properties'); + $xmlWriter->writeAttribute('fo:margin-top', ((is_null($style->getSpaceBefore())) ? '0' : round(17.6 / $style->getSpaceBefore(), 2)) . 'cm'); + $xmlWriter->writeAttribute('fo:margin-bottom', ((is_null($style->getSpaceAfter())) ? '0' : round(17.6 / $style->getSpaceAfter(), 2)) . 'cm'); + $xmlWriter->writeAttribute('fo:text-align', $style->getAlign()); + $xmlWriter->endElement(); + + $xmlWriter->endElement(); + } elseif ($style instanceof TableFull) { + // PhpOffice\PhpWord\Style\TableFull + } + } + } + } + $xmlWriter->endElement(); + + // office:automatic-styles + $xmlWriter->startElement('office:automatic-styles'); + // style:page-layout + $xmlWriter->startElement('style:page-layout'); + $xmlWriter->writeAttribute('style:name', 'Mpm1'); + // style:page-layout-properties + $xmlWriter->startElement('style:page-layout-properties'); + $xmlWriter->writeAttribute('fo:page-width', "21.001cm"); + $xmlWriter->writeAttribute('fo:page-height', '29.7cm'); + $xmlWriter->writeAttribute('style:num-format', '1'); + $xmlWriter->writeAttribute('style:print-orientation', 'portrait'); + $xmlWriter->writeAttribute('fo:margin-top', '2.501cm'); + $xmlWriter->writeAttribute('fo:margin-bottom', '2cm'); + $xmlWriter->writeAttribute('fo:margin-left', '2.501cm'); + $xmlWriter->writeAttribute('fo:margin-right', '2.501cm'); + $xmlWriter->writeAttribute('style:writing-mode', 'lr-tb'); + $xmlWriter->writeAttribute('style:layout-grid-color', '#c0c0c0'); + $xmlWriter->writeAttribute('style:layout-grid-lines', '25199'); + $xmlWriter->writeAttribute('style:layout-grid-base-height', '0.423cm'); + $xmlWriter->writeAttribute('style:layout-grid-ruby-height', '0cm'); + $xmlWriter->writeAttribute('style:layout-grid-mode', 'none'); + $xmlWriter->writeAttribute('style:layout-grid-ruby-below', 'false'); + $xmlWriter->writeAttribute('style:layout-grid-print', 'false'); + $xmlWriter->writeAttribute('style:layout-grid-display', 'false'); + $xmlWriter->writeAttribute('style:layout-grid-base-width', '0.37cm'); + $xmlWriter->writeAttribute('style:layout-grid-snap-to', 'true'); + $xmlWriter->writeAttribute('style:footnote-max-height', '0cm'); + //style:footnote-sep + $xmlWriter->startElement('style:footnote-sep'); + $xmlWriter->writeAttribute('style:width', '0.018cm'); + $xmlWriter->writeAttribute('style:line-style', 'solid'); + $xmlWriter->writeAttribute('style:adjustment', 'left'); + $xmlWriter->writeAttribute('style:rel-width', '25%'); + $xmlWriter->writeAttribute('style:color', '#000000'); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + // style:header-style + $xmlWriter->startElement('style:header-style'); + $xmlWriter->endElement(); + // style:footer-style + $xmlWriter->startElement('style:footer-style'); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + + // office:master-styles + $xmlWriter->startElement('office:master-styles'); + // style:master-page + $xmlWriter->startElement('style:master-page'); + $xmlWriter->writeAttribute('style:name', 'Standard'); + $xmlWriter->writeAttribute('style:page-layout-name', 'Mpm1'); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + + $xmlWriter->endElement(); + + // Return + return $xmlWriter->getData(); + } +} diff --git a/src/Writer/ODText/WriterPart.php b/src/Writer/ODText/WriterPart.php new file mode 100644 index 00000000..06e4a404 --- /dev/null +++ b/src/Writer/ODText/WriterPart.php @@ -0,0 +1,66 @@ +_parentWriter = $pWriter; + } + + /** + * Get parent IWriter object + * + * @return PhpOffice\PhpWord\Writer\IWriter + * @throws Exception + */ + public function getParentWriter() + { + if (!is_null($this->_parentWriter)) { + return $this->_parentWriter; + } else { + throw new Exception("No parent IWriter assigned."); + } + } +} diff --git a/src/Writer/RTF.php b/src/Writer/RTF.php new file mode 100644 index 00000000..57c17fdb --- /dev/null +++ b/src/Writer/RTF.php @@ -0,0 +1,482 @@ +setPhpWord($phpWord); + + // Set HashTable variables + $this->_drawingHashTable = new HashTable(); + } + + /** + * Save PhpWord to file + * + * @param string $pFileName + * @throws \Exception + */ + public function save($pFilename = null) + { + if (!is_null($this->_document)) { + // If $pFilename is php://output or php://stdout, make it a temporary file... + $originalFilename = $pFilename; + if (strtolower($pFilename) == 'php://output' || strtolower($pFilename) == 'php://stdout') { + $pFilename = @tempnam('./', 'phppttmp'); + if ($pFilename == '') { + $pFilename = $originalFilename; + } + } + + $hFile = fopen($pFilename, 'w') or die("can't open file"); + fwrite($hFile, $this->getData()); + fclose($hFile); + + // If a temporary file was used, copy it to the correct file stream + if ($originalFilename != $pFilename) { + if (copy($pFilename, $originalFilename) === false) { + throw new \Exception("Could not copy temporary zip file $pFilename to $originalFilename."); + } + @unlink($pFilename); + } + + } else { + throw new \Exception("PhpWord object unassigned."); + } + } + + /** + * @return PhpOffice\PhpWord + * @throws \Exception + */ + public function getPhpWord() + { + if (!is_null($this->_document)) { + return $this->_document; + } else { + throw new \Exception("No PhpWord assigned."); + } + } + + /** + * @param PhpOffice\PhpWord $phpWord + * @throws \Exception + * @return PhpOffice\PhpWord\Writer\RTF + */ + public function setPhpWord(PhpWord $phpWord = null) + { + $this->_document = $phpWord; + return $this; + } + + /** + * Get PHPWord_Worksheet_BaseDrawing HashTable + * + * @return PhpOffice\PhpWord\HashTable + */ + public function getDrawingHashTable() + { + return $this->_drawingHashTable; + } + + private function getData() + { + // PhpWord object : $this->_document + $this->_fontTable = $this->getDataFont(); + $this->_colorTable = $this->getDataColor(); + + $sRTFContent = '{\rtf1'; + // Set the default character set + $sRTFContent .= '\ansi\ansicpg1252'; + // Set the default font (the first one) + $sRTFContent .= '\deff0'; + // Set the default tab size (720 twips) + $sRTFContent .= '\deftab720'; + $sRTFContent .= PHP_EOL; + // Set the font tbl group + $sRTFContent .= '{\fonttbl'; + foreach ($this->_fontTable as $idx => $font) { + $sRTFContent .= '{\f' . $idx . '\fnil\fcharset0 ' . $font . ';}'; + } + $sRTFContent .= '}' . PHP_EOL; + // Set the color tbl group + $sRTFContent .= '{\colortbl '; + foreach ($this->_colorTable as $idx => $color) { + $arrColor = Drawing::htmlToRGB($color); + $sRTFContent .= ';\red' . $arrColor[0] . '\green' . $arrColor[1] . '\blue' . $arrColor[2] . ''; + } + $sRTFContent .= ';}' . PHP_EOL; + // Set the generator + $sRTFContent .= '{\*\generator PhpWord;}' . PHP_EOL; + // Set the view mode of the document + $sRTFContent .= '\viewkind4'; + // Set the numberof bytes that follows a unicode character + $sRTFContent .= '\uc1'; + // Resets to default paragraph properties. + $sRTFContent .= '\pard'; + // No widow/orphan control + $sRTFContent .= '\nowidctlpar'; + // Applies a language to a text run (1036 : French (France)) + $sRTFContent .= '\lang1036'; + // Point size (in half-points) above which to kern character pairs + $sRTFContent .= '\kerning1'; + // Set the font size in half-points + $sRTFContent .= '\fs' . (PhpWord::DEFAULT_FONT_SIZE * 2); + $sRTFContent .= PHP_EOL; + // Body + $sRTFContent .= $this->getDataContent(); + + + $sRTFContent .= '}'; + + return $sRTFContent; + } + + private function getDataFont() + { + $phpWord = $this->_document; + + $arrFonts = array(); + // Default font : PhpWord::DEFAULT_FONT_NAME + $arrFonts[] = PhpWord::DEFAULT_FONT_NAME; + // PhpWord object : $this->_document + + // Browse styles + $styles = Style::getStyles(); + $numPStyles = 0; + if (count($styles) > 0) { + foreach ($styles as $styleName => $style) { + // PhpOffice\PhpWord\Style\Font + if ($style instanceof Font) { + if (in_array($style->getName(), $arrFonts) == false) { + $arrFonts[] = $style->getName(); + } + } + } + } + + // Search all fonts used + $_sections = $phpWord->getSections(); + $countSections = count($_sections); + if ($countSections > 0) { + $pSection = 0; + + foreach ($_sections as $section) { + $pSection++; + $_elements = $section->getElements(); + + foreach ($_elements as $element) { + if ($element instanceof Text) { + $fStyle = $element->getFontStyle(); + + if ($fStyle instanceof Font) { + if (in_array($fStyle->getName(), $arrFonts) == false) { + $arrFonts[] = $fStyle->getName(); + } + } + } + } + } + } + + return $arrFonts; + } + + private function getDataColor() + { + $phpWord = $this->_document; + + $arrColors = array(); + // PhpWord object : $this->_document + + // Browse styles + $styles = Style::getStyles(); + $numPStyles = 0; + if (count($styles) > 0) { + foreach ($styles as $styleName => $style) { + // Font + if ($style instanceof Font) { + $color = $style->getColor(); + $fgcolor = $style->getFgColor(); + if (in_array($color, $arrColors) == false && $color != PhpWord::DEFAULT_FONT_COLOR && !empty($color)) { + $arrColors[] = $color; + } + if (in_array($fgcolor, $arrColors) == false && $fgcolor != PhpWord::DEFAULT_FONT_COLOR && !empty($fgcolor)) { + $arrColors[] = $fgcolor; + } + } + } + } + + // Search all fonts used + $_sections = $phpWord->getSections(); + $countSections = count($_sections); + if ($countSections > 0) { + $pSection = 0; + + foreach ($_sections as $section) { + $pSection++; + $_elements = $section->getElements(); + + foreach ($_elements as $element) { + if ($element instanceof Text) { + $fStyle = $element->getFontStyle(); + + if ($fStyle instanceof Font) { + if (in_array($fStyle->getColor(), $arrColors) == false) { + $arrColors[] = $fStyle->getColor(); + } + if (in_array($fStyle->getFgColor(), $arrColors) == false) { + $arrColors[] = $fStyle->getFgColor(); + } + } + } + } + } + } + + return $arrColors; + } + + private function getDataContent() + { + $phpWord = $this->_document; + $sRTFBody = ''; + + $_sections = $phpWord->getSections(); + $countSections = count($_sections); + $pSection = 0; + + if ($countSections > 0) { + foreach ($_sections as $section) { + $pSection++; + $_elements = $section->getElements(); + foreach ($_elements as $element) { + if ($element instanceof Text) { + $sRTFBody .= $this->getDataContentText($element); + } elseif ($element instanceof TextBreak) { + $sRTFBody .= $this->getDataContentTextBreak(); + } elseif ($element instanceof TextRun) { + $sRTFBody .= $this->getDataContentTextRun($element); + } elseif ($element instanceof Link) { + $sRTFBody .= $this->getDataContentUnsupportedElement('Link'); + } elseif ($element instanceof Title) { + $sRTFBody .= $this->getDataContentUnsupportedElement('Title'); + } elseif ($element instanceof PageBreak) { + $sRTFBody .= $this->getDataContentUnsupportedElement('Page Break'); + } elseif ($element instanceof Table) { + $sRTFBody .= $this->getDataContentUnsupportedElement('Table'); + } elseif ($element instanceof ListItem) { + $sRTFBody .= $this->getDataContentUnsupportedElement('List Item'); + } elseif ($element instanceof Image || + $element instanceof MemoryImage) { + $sRTFBody .= $this->getDataContentUnsupportedElement('Image'); + } elseif ($element instanceof Object) { + $sRTFBody .= $this->getDataContentUnsupportedElement('Object'); + } elseif ($element instanceof TOC) { + $sRTFBody .= $this->getDataContentUnsupportedElement('TOC'); + } else { + $sRTFBody .= $this->getDataContentUnsupportedElement('Other'); + } + } + } + } + return $sRTFBody; + } + + private function getDataContentText(Text $text, $withoutP = false) + { + $sRTFText = ''; + + $styleFont = $text->getFontStyle(); + $SfIsObject = ($styleFont instanceof Font) ? true : false; + if (!$SfIsObject) { + $styleFont = Style::getStyle($styleFont); + } + + $styleParagraph = $text->getParagraphStyle(); + $SpIsObject = ($styleParagraph instanceof Paragraph) ? true : false; + if (!$SpIsObject) { + $styleParagraph = Style::getStyle($styleParagraph); + } + + if ($styleParagraph && !$withoutP) { + if ($this->_lastParagraphStyle != $text->getParagraphStyle()) { + $sRTFText .= '\pard\nowidctlpar'; + if ($styleParagraph->getSpaceAfter() != null) { + $sRTFText .= '\sa' . $styleParagraph->getSpaceAfter(); + } + if ($styleParagraph->getAlign() != null) { + if ($styleParagraph->getAlign() == 'center') { + $sRTFText .= '\qc'; + } + } + $this->_lastParagraphStyle = $text->getParagraphStyle(); + } else { + $this->_lastParagraphStyle = ''; + } + } else { + $this->_lastParagraphStyle = ''; + } + + if ($styleFont instanceof Font) { + if ($styleFont->getColor() != null) { + $idxColor = array_search($styleFont->getColor(), $this->_colorTable); + if ($idxColor !== false) { + $sRTFText .= '\cf' . ($idxColor + 1); + } + } else { + $sRTFText .= '\cf0'; + } + if ($styleFont->getName() != null) { + $idxFont = array_search($styleFont->getName(), $this->_fontTable); + if ($idxFont !== false) { + $sRTFText .= '\f' . $idxFont; + } + } else { + $sRTFText .= '\f0'; + } + if ($styleFont->getBold()) { + $sRTFText .= '\b'; + } + if ($styleFont->getBold()) { + $sRTFText .= '\i'; + } + if ($styleFont->getSize()) { + $sRTFText .= '\fs' . ($styleFont->getSize() * 2); + } + } + if ($this->_lastParagraphStyle != '' || $styleFont) { + $sRTFText .= ' '; + } + $sRTFText .= $text->getText(); + + if ($styleFont instanceof Font) { + $sRTFText .= '\cf0'; + $sRTFText .= '\f0'; + + if ($styleFont->getBold()) { + $sRTFText .= '\b0'; + } + if ($styleFont->getItalic()) { + $sRTFText .= '\i0'; + } + if ($styleFont->getSize()) { + $sRTFText .= '\fs' . (PhpWord::DEFAULT_FONT_SIZE * 2); + } + } + + if (!$withoutP) { + $sRTFText .= '\par' . PHP_EOL; + } + return $sRTFText; + } + + private function getDataContentTextRun(TextRun $textrun) + { + $sRTFText = ''; + $elements = $textrun->getElements(); + if (count($elements) > 0) { + $sRTFText .= '\pard\nowidctlpar' . PHP_EOL; + foreach ($elements as $element) { + if ($element instanceof Text) { + $sRTFText .= '{'; + $sRTFText .= $this->getDataContentText($element, true); + $sRTFText .= '}' . PHP_EOL; + } + } + $sRTFText .= '\par' . PHP_EOL; + } + return $sRTFText; + } + + private function getDataContentTextBreak() + { + $this->_lastParagraphStyle = ''; + + return '\par' . PHP_EOL; + } + + /** + * Write unsupported element + * + * @param string $element + */ + private function getDataContentUnsupportedElement($element) + { + $sRTFText = ''; + $sRTFText .= '\pard\nowidctlpar' . PHP_EOL; + $sRTFText .= "{$element}"; + $sRTFText .= '\par' . PHP_EOL; + + return $sRTFText; + } +} \ No newline at end of file diff --git a/src/Writer/Word2007.php b/src/Writer/Word2007.php new file mode 100644 index 00000000..be142870 --- /dev/null +++ b/src/Writer/Word2007.php @@ -0,0 +1,301 @@ +_document = $phpWord; + + $this->_diskCachingDirectory = './'; + + $this->_writerParts['contenttypes'] = new ContentTypes(); + $this->_writerParts['rels'] = new Rels(); + $this->_writerParts['docprops'] = new DocProps(); + $this->_writerParts['documentrels'] = new DocumentRels(); + $this->_writerParts['document'] = new Document(); + $this->_writerParts['styles'] = new Styles(); + $this->_writerParts['header'] = new Header(); + $this->_writerParts['footer'] = new Footer(); + $this->_writerParts['footnotes'] = new Footnotes(); + $this->_writerParts['footnotesrels'] = new FootnotesRels(); + + foreach ($this->_writerParts as $writer) { + $writer->setParentWriter($this); + } + } + + public function save($pFilename = null) + { + if (!is_null($this->_document)) { + + // If $pFilename is php://output or php://stdout, make it a temporary file... + $originalFilename = $pFilename; + if (strtolower($pFilename) == 'php://output' || strtolower($pFilename) == 'php://stdout') { + $pFilename = @tempnam('./', 'phppttmp'); + if ($pFilename == '') { + $pFilename = $originalFilename; + } + } + + // Create new ZIP file and open it for writing + $objZip = new ZipArchive(); + + // Try opening the ZIP file + if ($objZip->open($pFilename, ZIPARCHIVE::OVERWRITE) !== true) { + if ($objZip->open($pFilename, ZIPARCHIVE::CREATE) !== true) { + throw new Exception("Could not open " . $pFilename . " for writing."); + } + } + + + $sectionElements = array(); + $_secElements = Media::getSectionMediaElements(); + foreach ($_secElements as $element) { // loop through section media elements + if ($element['type'] != 'hyperlink') { + $this->_addFileToPackage($objZip, $element); + } + $sectionElements[] = $element; + } + + $_hdrElements = Media::getHeaderMediaElements(); + foreach ($_hdrElements as $_headerFile => $_hdrMedia) { // loop through headers + if (count($_hdrMedia) > 0) { + $objZip->addFromString('word/_rels/' . $_headerFile . '.xml.rels', $this->getWriterPart('documentrels')->writeHeaderFooterRels($_hdrMedia)); + foreach ($_hdrMedia as $element) { // loop through header media elements + $this->_addFileToPackage($objZip, $element); + } + } + } + + $_ftrElements = Media::getFooterMediaElements(); + foreach ($_ftrElements as $_footerFile => $_ftrMedia) { // loop through footers + if (count($_ftrMedia) > 0) { + $objZip->addFromString('word/_rels/' . $_footerFile . '.xml.rels', $this->getWriterPart('documentrels')->writeHeaderFooterRels($_ftrMedia)); + foreach ($_ftrMedia as $element) { // loop through footers media elements + $this->_addFileToPackage($objZip, $element); + } + } + } + + $footnoteLinks = array(); + $_footnoteElements = Footnote::getFootnoteLinkElements(); + // loop through footnote link elements + foreach ($_footnoteElements as $element) { + $footnoteLinks[] = $element; + } + + $_cHdrs = 0; + $_cFtrs = 0; + $rID = Media::countSectionMediaElements() + 6; + $_sections = $this->_document->getSections(); + + $footers = array(); + foreach ($_sections as $section) { + $_headers = $section->getHeaders(); + foreach ($_headers as $index => &$_header) { + $_cHdrs++; + $_header->setRelationId(++$rID); + $_headerFile = 'header' . $_cHdrs . '.xml'; + $sectionElements[] = array('target' => $_headerFile, 'type' => 'header', 'rID' => $rID); + $objZip->addFromString('word/' . $_headerFile, $this->getWriterPart('header')->writeHeader($_header)); + } + + $_footer = $section->getFooter(); + $footers[++$_cFtrs] = $_footer; + if (!is_null($_footer)) { + $_footer->setRelationId(++$rID); + $_footerCount = $_footer->getFooterCount(); + $_footerFile = 'footer' . $_footerCount . '.xml'; + $sectionElements[] = array('target' => $_footerFile, 'type' => 'footer', 'rID' => $rID); + $objZip->addFromString('word/' . $_footerFile, $this->getWriterPart('footer')->writeFooter($_footer)); + } + } + + if (Footnote::countFootnoteElements() > 0) { + $_allFootnotesCollection = Footnote::getFootnoteElements(); + $_footnoteFile = 'footnotes.xml'; + $sectionElements[] = array('target'=>$_footnoteFile, 'type'=>'footnotes', 'rID'=>++$rID); + $objZip->addFromString('word/'.$_footnoteFile, $this->getWriterPart('footnotes')->writeFootnotes($_allFootnotesCollection)); + if (count($footnoteLinks) > 0) { + $objZip->addFromString('word/_rels/footnotes.xml.rels', $this->getWriterPart('footnotesrels')->writeFootnotesRels($footnoteLinks)); + } + } + + // build docx file + // Write dynamic files + $objZip->addFromString( + '[Content_Types].xml', + $this->getWriterPart('contenttypes')->writeContentTypes( + $this->_imageTypes, + $this->_objectTypes, + $_cHdrs, + $footers + ) + ); + $objZip->addFromString('_rels/.rels', $this->getWriterPart('rels')->writeRelationships($this->_document)); + $objZip->addFromString('docProps/app.xml', $this->getWriterPart('docprops')->writeDocPropsApp($this->_document)); + $objZip->addFromString('docProps/core.xml', $this->getWriterPart('docprops')->writeDocPropsCore($this->_document)); + $objZip->addFromString('word/document.xml', $this->getWriterPart('document')->writeDocument($this->_document)); + $objZip->addFromString('word/_rels/document.xml.rels', $this->getWriterPart('documentrels')->writeDocumentRels($sectionElements)); + $objZip->addFromString('word/styles.xml', $this->getWriterPart('styles')->writeStyles($this->_document)); + + // Write static files + $objZip->addFile(\PHPWORD_BASE_DIR . '_staticDocParts/numbering.xml', 'word/numbering.xml'); + $objZip->addFile(\PHPWORD_BASE_DIR . '_staticDocParts/settings.xml', 'word/settings.xml'); + $objZip->addFile(\PHPWORD_BASE_DIR . '_staticDocParts/theme1.xml', 'word/theme/theme1.xml'); + $objZip->addFile(\PHPWORD_BASE_DIR . '_staticDocParts/webSettings.xml', 'word/webSettings.xml'); + $objZip->addFile(\PHPWORD_BASE_DIR . '_staticDocParts/fontTable.xml', 'word/fontTable.xml'); + + + // Close file + if ($objZip->close() === false) { + throw new Exception("Could not close zip file $pFilename."); + } + + // If a temporary file was used, copy it to the correct file stream + if ($originalFilename != $pFilename) { + if (copy($pFilename, $originalFilename) === false) { + throw new Exception("Could not copy temporary zip file $pFilename to $originalFilename."); + } + @unlink($pFilename); + } + } else { + throw new Exception("PhpWord object unassigned."); + } + } + + /** + * @param string $src + */ + private function checkContentTypes($src) + { + $extension = null; + if (stripos(strrev($src), strrev('.php')) === 0) { + $extension = 'php'; + } else { + $imageType = exif_imagetype($src); + if ($imageType === IMAGETYPE_JPEG) { + $extension = 'jpg'; + } elseif ($imageType === IMAGETYPE_GIF) { + $extension = 'gif'; + } elseif ($imageType === IMAGETYPE_PNG) { + $extension = 'png'; + } elseif ($imageType === IMAGETYPE_BMP) { + $extension = 'bmp'; + } elseif ($imageType === IMAGETYPE_TIFF_II || $imageType === IMAGETYPE_TIFF_MM) { + $extension = 'tif'; + } + } + + if (isset($extension)) { + $imageData = getimagesize($src); + $imageType = image_type_to_mime_type($imageData[2]); + $imageExtension = str_replace('.', '', image_type_to_extension($imageData[2])); + if ($imageExtension === 'jpeg') { + $imageExtension = 'jpg'; + } + if (!in_array($imageType, $this->_imageTypes)) { + $this->_imageTypes[$imageExtension] = $imageType; + } + } else { + if (!in_array($extension, $this->_objectTypes)) { + $this->_objectTypes[] = $extension; + } + } + } + + public function getWriterPart($pPartName = '') + { + if ($pPartName != '' && isset($this->_writerParts[strtolower($pPartName)])) { + return $this->_writerParts[strtolower($pPartName)]; + } else { + return null; + } + } + + public function getUseDiskCaching() + { + return $this->_useDiskCaching; + } + + public function setUseDiskCaching($pValue = false, $pDirectory = null) + { + $this->_useDiskCaching = $pValue; + + if (!is_null($pDirectory)) { + if (is_dir($pDirectory)) { + $this->_diskCachingDirectory = $pDirectory; + } else { + throw new Exception("Directory does not exist: $pDirectory"); + } + } + + return $this; + } + + private function _addFileToPackage($objZip, $element) + { + if (isset($element['isMemImage']) && $element['isMemImage']) { + $image = call_user_func($element['createfunction'], $element['source']); + ob_start(); + call_user_func($element['imagefunction'], $image); + $imageContents = ob_get_contents(); + ob_end_clean(); + $objZip->addFromString('word/' . $element['target'], $imageContents); + imagedestroy($image); + + $this->checkContentTypes($element['source']); + } else { + $objZip->addFile($element['source'], 'word/' . $element['target']); + $this->checkContentTypes($element['source']); + } + } +} diff --git a/src/Writer/Word2007/Base.php b/src/Writer/Word2007/Base.php new file mode 100644 index 00000000..f0029fc4 --- /dev/null +++ b/src/Writer/Word2007/Base.php @@ -0,0 +1,1003 @@ +getFontStyle(); + + $SfIsObject = ($styleFont instanceof Font) ? true : false; + + if (!$withoutP) { + $xmlWriter->startElement('w:p'); + + $styleParagraph = $text->getParagraphStyle(); + $SpIsObject = ($styleParagraph instanceof Paragraph) ? true : false; + + if ($SpIsObject) { + $this->_writeParagraphStyle($xmlWriter, $styleParagraph); + } elseif (!$SpIsObject && !is_null($styleParagraph)) { + $xmlWriter->startElement('w:pPr'); + $xmlWriter->startElement('w:pStyle'); + $xmlWriter->writeAttribute('w:val', $styleParagraph); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + } + } + + $strText = htmlspecialchars($text->getText()); + $strText = String::ControlCharacterPHP2OOXML($strText); + + $xmlWriter->startElement('w:r'); + + if ($SfIsObject) { + $this->_writeTextStyle($xmlWriter, $styleFont); + } elseif (!$SfIsObject && !is_null($styleFont)) { + $xmlWriter->startElement('w:rPr'); + $xmlWriter->startElement('w:rStyle'); + $xmlWriter->writeAttribute('w:val', $styleFont); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + } + + $xmlWriter->startElement('w:t'); + $xmlWriter->writeAttribute('xml:space', 'preserve'); // needed because of drawing spaces before and after text + $xmlWriter->writeRaw($strText); + $xmlWriter->endElement(); + + $xmlWriter->endElement(); // w:r + + if (!$withoutP) { + $xmlWriter->endElement(); // w:p + } + } + + protected function _writeTextRun(XMLWriter $xmlWriter = null, TextRun $textrun) + { + $elements = $textrun->getElements(); + $styleParagraph = $textrun->getParagraphStyle(); + + $SpIsObject = ($styleParagraph instanceof Paragraph) ? true : false; + + $xmlWriter->startElement('w:p'); + + if ($SpIsObject) { + $this->_writeParagraphStyle($xmlWriter, $styleParagraph); + } elseif (!$SpIsObject && !is_null($styleParagraph)) { + $xmlWriter->startElement('w:pPr'); + $xmlWriter->startElement('w:pStyle'); + $xmlWriter->writeAttribute('w:val', $styleParagraph); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + } + + if (count($elements) > 0) { + foreach ($elements as $element) { + if ($element instanceof Text) { + $this->_writeText($xmlWriter, $element, true); + } elseif ($element instanceof Link) { + $this->_writeLink($xmlWriter, $element, true); + } elseif ($element instanceof Image) { + $this->_writeImage($xmlWriter, $element, true); + } elseif ($element instanceof Footnote) { + $this->_writeFootnoteReference($xmlWriter, $element, true); + } elseif ($element instanceof TextBreak) { + $xmlWriter->writeElement('w:br'); + } + } + } + + $xmlWriter->endElement(); + } + + /** + * @param PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param PhpOffice\PhpWord\Style\Paragraph $style + * @param bool $withoutPPR + * @return void + */ + protected function _writeParagraphStyle( + XMLWriter $xmlWriter = null, + Paragraph $style, + $withoutPPR = false + ) { + + $align = $style->getAlign(); + $spacing = $style->getSpacing(); + $spaceBefore = $style->getSpaceBefore(); + $spaceAfter = $style->getSpaceAfter(); + $indent = $style->getIndent(); + $hanging = $style->getHanging(); + $tabs = $style->getTabs(); + $widowControl = $style->getWidowControl(); + $keepNext = $style->getKeepNext(); + $keepLines = $style->getKeepLines(); + $pageBreakBefore = $style->getPageBreakBefore(); + + if (!is_null($align) || !is_null($spacing) || !is_null($spaceBefore) || + !is_null($spaceAfter) || !is_null($indent) || !is_null($hanging) || + !is_null($tabs) || !is_null($widowControl) || !is_null($keepNext) || + !is_null($keepLines) || !is_null($pageBreakBefore)) { + if (!$withoutPPR) { + $xmlWriter->startElement('w:pPr'); + } + + // Alignment + if (!is_null($align)) { + $xmlWriter->startElement('w:jc'); + $xmlWriter->writeAttribute('w:val', $align); + $xmlWriter->endElement(); + } + + // Indentation + if (!is_null($indent) || !is_null($hanging)) { + $xmlWriter->startElement('w:ind'); + $xmlWriter->writeAttribute('w:firstLine', 0); + if (!is_null($indent)) { + $xmlWriter->writeAttribute('w:left', $indent); + } + if (!is_null($hanging)) { + $xmlWriter->writeAttribute('w:hanging', $hanging); + } + $xmlWriter->endElement(); + } + + // Spacing + if (!is_null($spaceBefore) || !is_null($spaceAfter) || + !is_null($spacing)) { + $xmlWriter->startElement('w:spacing'); + if (!is_null($spaceBefore)) { + $xmlWriter->writeAttribute('w:before', $spaceBefore); + } + if (!is_null($spaceAfter)) { + $xmlWriter->writeAttribute('w:after', $spaceAfter); + } + if (!is_null($spacing)) { + $xmlWriter->writeAttribute('w:line', $spacing); + $xmlWriter->writeAttribute('w:lineRule', 'auto'); + } + $xmlWriter->endElement(); + } + + // Pagination + if (!$widowControl) { + $xmlWriter->startElement('w:widowControl'); + $xmlWriter->writeAttribute('w:val', '0'); + $xmlWriter->endElement(); + } + if ($keepNext) { + $xmlWriter->startElement('w:keepNext'); + $xmlWriter->writeAttribute('w:val', '1'); + $xmlWriter->endElement(); + } + if ($keepLines) { + $xmlWriter->startElement('w:keepLines'); + $xmlWriter->writeAttribute('w:val', '1'); + $xmlWriter->endElement(); + } + if ($pageBreakBefore) { + $xmlWriter->startElement('w:pageBreakBefore'); + $xmlWriter->writeAttribute('w:val', '1'); + $xmlWriter->endElement(); + } + + // Tabs + if (!is_null($tabs)) { + $tabs->toXml($xmlWriter); + } + + if (!$withoutPPR) { + $xmlWriter->endElement(); // w:pPr + } + } + } + + protected function _writeLink(XMLWriter $xmlWriter = null, Link $link, $withoutP = false) + { + $rID = $link->getRelationId(); + $linkName = $link->getLinkName(); + if (is_null($linkName)) { + $linkName = $link->getLinkSrc(); + } + + $styleFont = $link->getFontStyle(); + $SfIsObject = ($styleFont instanceof Font) ? true : false; + + if (!$withoutP) { + $xmlWriter->startElement('w:p'); + + $styleParagraph = $link->getParagraphStyle(); + $SpIsObject = ($styleParagraph instanceof Paragraph) ? true : false; + + if ($SpIsObject) { + $this->_writeParagraphStyle($xmlWriter, $styleParagraph); + } elseif (!$SpIsObject && !is_null($styleParagraph)) { + $xmlWriter->startElement('w:pPr'); + $xmlWriter->startElement('w:pStyle'); + $xmlWriter->writeAttribute('w:val', $styleParagraph); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + } + } + + $xmlWriter->startElement('w:hyperlink'); + $xmlWriter->writeAttribute('r:id', 'rId' . $rID); + $xmlWriter->writeAttribute('w:history', '1'); + + $xmlWriter->startElement('w:r'); + if ($SfIsObject) { + $this->_writeTextStyle($xmlWriter, $styleFont); + } elseif (!$SfIsObject && !is_null($styleFont)) { + $xmlWriter->startElement('w:rPr'); + $xmlWriter->startElement('w:rStyle'); + $xmlWriter->writeAttribute('w:val', $styleFont); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + } + + $xmlWriter->startElement('w:t'); + $xmlWriter->writeAttribute('xml:space', 'preserve'); // needed because of drawing spaces before and after text + $xmlWriter->writeRaw($linkName); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + + $xmlWriter->endElement(); + + if (!$withoutP) { + $xmlWriter->endElement(); // w:p + } + } + + protected function _writePreserveText(XMLWriter $xmlWriter = null, PreserveText $textrun) + { + $styleFont = $textrun->getFontStyle(); + $styleParagraph = $textrun->getParagraphStyle(); + + $SfIsObject = ($styleFont instanceof Font) ? true : false; + $SpIsObject = ($styleParagraph instanceof Paragraph) ? true : false; + + $arrText = $textrun->getText(); + if (!is_array($arrText)) { + $arrText = array($arrText); + } + + $xmlWriter->startElement('w:p'); + + if ($SpIsObject) { + $this->_writeParagraphStyle($xmlWriter, $styleParagraph); + } elseif (!$SpIsObject && !is_null($styleParagraph)) { + $xmlWriter->startElement('w:pPr'); + $xmlWriter->startElement('w:pStyle'); + $xmlWriter->writeAttribute('w:val', $styleParagraph); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + } + + foreach ($arrText as $text) { + + if (substr($text, 0, 1) == '{') { + $text = substr($text, 1, -1); + + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:fldChar'); + $xmlWriter->writeAttribute('w:fldCharType', 'begin'); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + + $xmlWriter->startElement('w:r'); + + if ($SfIsObject) { + $this->_writeTextStyle($xmlWriter, $styleFont); + } elseif (!$SfIsObject && !is_null($styleFont)) { + $xmlWriter->startElement('w:rPr'); + $xmlWriter->startElement('w:rStyle'); + $xmlWriter->writeAttribute('w:val', $styleFont); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + } + + $xmlWriter->startElement('w:instrText'); + $xmlWriter->writeAttribute('xml:space', 'preserve'); + $xmlWriter->writeRaw($text); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:fldChar'); + $xmlWriter->writeAttribute('w:fldCharType', 'separate'); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:fldChar'); + $xmlWriter->writeAttribute('w:fldCharType', 'end'); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + } else { + $text = htmlspecialchars($text); + $text = String::ControlCharacterPHP2OOXML($text); + + $xmlWriter->startElement('w:r'); + + if ($SfIsObject) { + $this->_writeTextStyle($xmlWriter, $styleFont); + } elseif (!$SfIsObject && !is_null($styleFont)) { + $xmlWriter->startElement('w:rPr'); + $xmlWriter->startElement('w:rStyle'); + $xmlWriter->writeAttribute('w:val', $styleFont); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + } + + $xmlWriter->startElement('w:t'); + $xmlWriter->writeAttribute('xml:space', 'preserve'); + $xmlWriter->writeRaw($text); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + } + } + + $xmlWriter->endElement(); // p + } + + protected function _writeTextStyle(XMLWriter $xmlWriter = null, Font $style) + { + $font = $style->getName(); + $bold = $style->getBold(); + $italic = $style->getItalic(); + $color = $style->getColor(); + $size = $style->getSize(); + $fgColor = $style->getFgColor(); + $strikethrough = $style->getStrikethrough(); + $underline = $style->getUnderline(); + $superscript = $style->getSuperScript(); + $subscript = $style->getSubScript(); + $hint = $style->getHint(); + + $xmlWriter->startElement('w:rPr'); + + // Font + if ($font != PhpWord::DEFAULT_FONT_NAME) { + $xmlWriter->startElement('w:rFonts'); + $xmlWriter->writeAttribute('w:ascii', $font); + $xmlWriter->writeAttribute('w:hAnsi', $font); + $xmlWriter->writeAttribute('w:eastAsia', $font); + $xmlWriter->writeAttribute('w:cs', $font); + //Font Content Type + if ($hint != PhpWord::DEFAULT_FONT_CONTENT_TYPE) { + $xmlWriter->writeAttribute('w:hint', $hint); + } + $xmlWriter->endElement(); + } + + + // Color + if ($color != PhpWord::DEFAULT_FONT_COLOR) { + $xmlWriter->startElement('w:color'); + $xmlWriter->writeAttribute('w:val', $color); + $xmlWriter->endElement(); + } + + // Size + if ($size != PhpWord::DEFAULT_FONT_SIZE) { + $xmlWriter->startElement('w:sz'); + $xmlWriter->writeAttribute('w:val', $size * 2); + $xmlWriter->endElement(); + $xmlWriter->startElement('w:szCs'); + $xmlWriter->writeAttribute('w:val', $size * 2); + $xmlWriter->endElement(); + } + + // Bold + if ($bold) { + $xmlWriter->writeElement('w:b', null); + } + + // Italic + if ($italic) { + $xmlWriter->writeElement('w:i', null); + $xmlWriter->writeElement('w:iCs', null); + } + + // Underline + if (!is_null($underline) && $underline != 'none') { + $xmlWriter->startElement('w:u'); + $xmlWriter->writeAttribute('w:val', $underline); + $xmlWriter->endElement(); + } + + // Strikethrough + if ($strikethrough) { + $xmlWriter->writeElement('w:strike', null); + } + + // Foreground-Color + if (!is_null($fgColor)) { + $xmlWriter->startElement('w:highlight'); + $xmlWriter->writeAttribute('w:val', $fgColor); + $xmlWriter->endElement(); + } + + // Superscript/subscript + if ($superscript || $subscript) { + $xmlWriter->startElement('w:vertAlign'); + $xmlWriter->writeAttribute('w:val', $superscript ? 'superscript' : 'subscript'); + $xmlWriter->endElement(); + } + + $xmlWriter->endElement(); + } + + /** + * @param PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param PhpOffice\PhpWord\Section\TextBreak $element + */ + protected function _writeTextBreak($xmlWriter, $element = null) + { + $hasStyle = false; + if (!is_null($element)) { + $fontStyle = $element->getFontStyle(); + $sfIsObject = ($fontStyle instanceof Font) ? true : false; + $paragraphStyle = $element->getParagraphStyle(); + $spIsObject = ($paragraphStyle instanceof Paragraph) ? true : false; + $hasStyle = !is_null($fontStyle) || !is_null($paragraphStyle); + } + if ($hasStyle) { + // Paragraph style + $xmlWriter->startElement('w:p'); + if ($spIsObject) { + $this->_writeParagraphStyle($xmlWriter, $paragraphStyle); + } elseif (!$spIsObject && !is_null($paragraphStyle)) { + $xmlWriter->startElement('w:pPr'); + $xmlWriter->startElement('w:pStyle'); + $xmlWriter->writeAttribute('w:val', $paragraphStyle); + $xmlWriter->endElement(); // w:pStyle + $xmlWriter->endElement(); // w:pPr + } + // Font style + if (!is_null($fontStyle)) { + $xmlWriter->startElement('w:pPr'); + if ($sfIsObject) { + $this->_writeTextStyle($xmlWriter, $fontStyle); + } elseif (!$sfIsObject && !is_null($fontStyle)) { + $xmlWriter->startElement('w:rPr'); + $xmlWriter->startElement('w:rStyle'); + $xmlWriter->writeAttribute('w:val', $fontStyle); + $xmlWriter->endElement(); // w:rStyle + $xmlWriter->endElement(); // w:rPr + } + $xmlWriter->endElement(); // w:pPr + } + $xmlWriter->endElement(); // w:p + } else { + // Null element. No paragraph nor font style + $xmlWriter->writeElement('w:p', null); + } + } + + protected function _writeTable(XMLWriter $xmlWriter = null, Table $table) + { + $_rows = $table->getRows(); + $_cRows = count($_rows); + + if ($_cRows > 0) { + $xmlWriter->startElement('w:tbl'); + $tblStyle = $table->getStyle(); + $tblWidth = $table->getWidth(); + if ($tblStyle instanceof PhpOffice\PhpWord\Style\Table) { + $this->_writeTableStyle($xmlWriter, $tblStyle); + } else { + if (!empty($tblStyle)) { + $xmlWriter->startElement('w:tblPr'); + $xmlWriter->startElement('w:tblStyle'); + $xmlWriter->writeAttribute('w:val', $tblStyle); + $xmlWriter->endElement(); + if (!is_null($tblWidth)) { + $xmlWriter->startElement('w:tblW'); + $xmlWriter->writeAttribute('w:w', $tblWidth); + $xmlWriter->writeAttribute('w:type', 'pct'); + $xmlWriter->endElement(); + } + $xmlWriter->endElement(); + } + } + + for ($i = 0; $i < $_cRows; $i++) { + $row = $_rows[$i]; + $height = $row->getHeight(); + $rowStyle = $row->getStyle(); + $tblHeader = $rowStyle->getTblHeader(); + $cantSplit = $rowStyle->getCantSplit(); + + $xmlWriter->startElement('w:tr'); + + if (!is_null($height) || !is_null($tblHeader) || !is_null($cantSplit)) { + $xmlWriter->startElement('w:trPr'); + if (!is_null($height)) { + $xmlWriter->startElement('w:trHeight'); + $xmlWriter->writeAttribute('w:val', $height); + $xmlWriter->endElement(); + } + if ($tblHeader) { + $xmlWriter->startElement('w:tblHeader'); + $xmlWriter->writeAttribute('w:val', '1'); + $xmlWriter->endElement(); + } + if ($cantSplit) { + $xmlWriter->startElement('w:cantSplit'); + $xmlWriter->writeAttribute('w:val', '1'); + $xmlWriter->endElement(); + } + $xmlWriter->endElement(); + } + + foreach ($row->getCells() as $cell) { + $xmlWriter->startElement('w:tc'); + + $cellStyle = $cell->getStyle(); + $width = $cell->getWidth(); + + $xmlWriter->startElement('w:tcPr'); + $xmlWriter->startElement('w:tcW'); + $xmlWriter->writeAttribute('w:w', $width); + $xmlWriter->writeAttribute('w:type', 'dxa'); + $xmlWriter->endElement(); + + if ($cellStyle instanceof Cell) { + $this->_writeCellStyle($xmlWriter, $cellStyle); + } + + $xmlWriter->endElement(); + + $_elements = $cell->getElements(); + if (count($_elements) > 0) { + foreach ($_elements as $element) { + if ($element instanceof Text) { + $this->_writeText($xmlWriter, $element); + } elseif ($element instanceof TextRun) { + $this->_writeTextRun($xmlWriter, $element); + } elseif ($element instanceof Link) { + $this->_writeLink($xmlWriter, $element); + } elseif ($element instanceof TextBreak) { + $this->_writeTextBreak($xmlWriter, $element); + } elseif ($element instanceof ListItem) { + $this->_writeListItem($xmlWriter, $element); + } elseif ($element instanceof Image || + $element instanceof MemoryImage + ) { + $this->_writeImage($xmlWriter, $element); + } elseif ($element instanceof Object) { + $this->_writeObject($xmlWriter, $element); + } elseif ($element instanceof PreserveText) { + $this->_writePreserveText($xmlWriter, $element); + } + } + } else { + $this->_writeTextBreak($xmlWriter); + } + + $xmlWriter->endElement(); + } + $xmlWriter->endElement(); + } + $xmlWriter->endElement(); + } + } + + protected function _writeTableStyle( + XMLWriter $xmlWriter = null, + PhpOffice\PhpWord\Style\Table $style = null + ) { + $margins = $style->getCellMargin(); + $mTop = (!is_null($margins[0])) ? true : false; + $mLeft = (!is_null($margins[1])) ? true : false; + $mRight = (!is_null($margins[2])) ? true : false; + $mBottom = (!is_null($margins[3])) ? true : false; + + if ($mTop || $mLeft || $mRight || $mBottom) { + $xmlWriter->startElement('w:tblPr'); + $xmlWriter->startElement('w:tblCellMar'); + + if ($mTop) { + $xmlWriter->startElement('w:top'); + $xmlWriter->writeAttribute('w:w', $margins[0]); + $xmlWriter->writeAttribute('w:type', 'dxa'); + $xmlWriter->endElement(); + } + + if ($mLeft) { + $xmlWriter->startElement('w:left'); + $xmlWriter->writeAttribute('w:w', $margins[1]); + $xmlWriter->writeAttribute('w:type', 'dxa'); + $xmlWriter->endElement(); + } + + if ($mRight) { + $xmlWriter->startElement('w:right'); + $xmlWriter->writeAttribute('w:w', $margins[2]); + $xmlWriter->writeAttribute('w:type', 'dxa'); + $xmlWriter->endElement(); + } + + if ($mBottom) { + $xmlWriter->startElement('w:bottom'); + $xmlWriter->writeAttribute('w:w', $margins[3]); + $xmlWriter->writeAttribute('w:type', 'dxa'); + $xmlWriter->endElement(); + } + + $xmlWriter->endElement(); + $xmlWriter->endElement(); + } + } + + protected function _writeCellStyle(XMLWriter $xmlWriter = null, Cell $style = null) + { + $bgColor = $style->getBgColor(); + $valign = $style->getVAlign(); + $textDir = $style->getTextDirection(); + $brdSz = $style->getBorderSize(); + $brdCol = $style->getBorderColor(); + + $bTop = (!is_null($brdSz[0])) ? true : false; + $bLeft = (!is_null($brdSz[1])) ? true : false; + $bRight = (!is_null($brdSz[2])) ? true : false; + $bBottom = (!is_null($brdSz[3])) ? true : false; + $borders = ($bTop || $bLeft || $bRight || $bBottom) ? true : false; + + $styles = (!is_null($bgColor) || !is_null($valign) || !is_null($textDir) || $borders) ? true : false; + + if ($styles) { + if (!is_null($textDir)) { + $xmlWriter->startElement('w:textDirection'); + $xmlWriter->writeAttribute('w:val', $textDir); + $xmlWriter->endElement(); + } + + if (!is_null($bgColor)) { + $xmlWriter->startElement('w:shd'); + $xmlWriter->writeAttribute('w:val', 'clear'); + $xmlWriter->writeAttribute('w:color', 'auto'); + $xmlWriter->writeAttribute('w:fill', $bgColor); + $xmlWriter->endElement(); + } + + if (!is_null($valign)) { + $xmlWriter->startElement('w:vAlign'); + $xmlWriter->writeAttribute('w:val', $valign); + $xmlWriter->endElement(); + } + + if ($borders) { + $_defaultColor = $style->getDefaultBorderColor(); + + $xmlWriter->startElement('w:tcBorders'); + if ($bTop) { + if (is_null($brdCol[0])) { + $brdCol[0] = $_defaultColor; + } + $xmlWriter->startElement('w:top'); + $xmlWriter->writeAttribute('w:val', 'single'); + $xmlWriter->writeAttribute('w:sz', $brdSz[0]); + $xmlWriter->writeAttribute('w:color', $brdCol[0]); + $xmlWriter->endElement(); + } + + if ($bLeft) { + if (is_null($brdCol[1])) { + $brdCol[1] = $_defaultColor; + } + $xmlWriter->startElement('w:left'); + $xmlWriter->writeAttribute('w:val', 'single'); + $xmlWriter->writeAttribute('w:sz', $brdSz[1]); + $xmlWriter->writeAttribute('w:color', $brdCol[1]); + $xmlWriter->endElement(); + } + + if ($bRight) { + if (is_null($brdCol[2])) { + $brdCol[2] = $_defaultColor; + } + $xmlWriter->startElement('w:right'); + $xmlWriter->writeAttribute('w:val', 'single'); + $xmlWriter->writeAttribute('w:sz', $brdSz[2]); + $xmlWriter->writeAttribute('w:color', $brdCol[2]); + $xmlWriter->endElement(); + } + + if ($bBottom) { + if (is_null($brdCol[3])) { + $brdCol[3] = $_defaultColor; + } + $xmlWriter->startElement('w:bottom'); + $xmlWriter->writeAttribute('w:val', 'single'); + $xmlWriter->writeAttribute('w:sz', $brdSz[3]); + $xmlWriter->writeAttribute('w:color', $brdCol[3]); + $xmlWriter->endElement(); + } + + $xmlWriter->endElement(); + } + } + $gridSpan = $style->getGridSpan(); + if (!is_null($gridSpan)) { + $xmlWriter->startElement('w:gridSpan'); + $xmlWriter->writeAttribute('w:val', $gridSpan); + $xmlWriter->endElement(); + } + + $vMerge = $style->getVMerge(); + if (!is_null($vMerge)) { + $xmlWriter->startElement('w:vMerge'); + $xmlWriter->writeAttribute('w:val', $vMerge); + $xmlWriter->endElement(); + } + } + + /** + * @param PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param PhpOffice\PhpWord\Section\Image|PhpOffice\PhpWord\Section\MemoryImage $image + */ + protected function _writeImage(XMLWriter $xmlWriter = null, $image, $withoutP = false) + { + $rId = $image->getRelationId(); + + $style = $image->getStyle(); + $width = $style->getWidth(); + $height = $style->getHeight(); + $align = $style->getAlign(); + $marginTop = $style->getMarginTop(); + $marginLeft = $style->getMarginLeft(); + $wrappingStyle = $style->getWrappingStyle(); + + if (!$withoutP) { + $xmlWriter->startElement('w:p'); + + if (!is_null($align)) { + $xmlWriter->startElement('w:pPr'); + $xmlWriter->startElement('w:jc'); + $xmlWriter->writeAttribute('w:val', $align); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + } + } + + $xmlWriter->startElement('w:r'); + + $xmlWriter->startElement('w:pict'); + + $xmlWriter->startElement('v:shape'); + $xmlWriter->writeAttribute('type', '#_x0000_t75'); + + $imgStyle = ''; + if (null !== $width) { + $imgStyle .= 'width:' . $width . 'px;'; + } + if (null !== $height) { + $imgStyle .= 'height:' . $height . 'px;'; + } + if (null !== $marginTop) { + $imgStyle .= 'margin-top:' . $marginTop . 'in;'; + } + if (null !== $marginLeft) { + $imgStyle .= 'margin-left:' . $marginLeft . 'in;'; + } + + switch ($wrappingStyle) { + case PhpOffice\PhpWord\Style\Image::WRAPPING_STYLE_BEHIND: + $imgStyle .= 'position:absolute;z-index:-251658752;'; + break; + case PhpOffice\PhpWord\Style\Image::WRAPPING_STYLE_SQUARE: + $imgStyle .= 'position:absolute;z-index:251659264;mso-position-horizontal:absolute;mso-position-vertical:absolute;'; + break; + case PhpOffice\PhpWord\Style\Image::WRAPPING_STYLE_TIGHT: + $imgStyle .= 'position:absolute;z-index:251659264;mso-wrap-edited:f;mso-position-horizontal:absolute;mso-position-vertical:absolute'; + break; + case PhpOffice\PhpWord\Style\Image::WRAPPING_STYLE_INFRONT: + $imgStyle .= 'position:absolute;zz-index:251659264;mso-position-horizontal:absolute;mso-position-vertical:absolute;'; + break; + } + + $xmlWriter->writeAttribute('style', $imgStyle); + + $xmlWriter->startElement('v:imagedata'); + $xmlWriter->writeAttribute('r:id', 'rId' . $rId); + $xmlWriter->writeAttribute('o:title', ''); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + + $xmlWriter->endElement(); + + $xmlWriter->endElement(); + + if (!$withoutP) { + $xmlWriter->endElement(); // w:p + } + } + + protected function _writeWatermark(XMLWriter $xmlWriter = null, $image) + { + $rId = $image->getRelationId(); + + $style = $image->getStyle(); + $width = $style->getWidth(); + $height = $style->getHeight(); + $marginLeft = $style->getMarginLeft(); + $marginTop = $style->getMarginTop(); + + $xmlWriter->startElement('w:p'); + + $xmlWriter->startElement('w:r'); + + $xmlWriter->startElement('w:pict'); + + $xmlWriter->startElement('v:shape'); + $xmlWriter->writeAttribute('type', '#_x0000_t75'); + + $strStyle = 'position:absolute;'; + $strStyle .= ' width:' . $width . 'px;'; + $strStyle .= ' height:' . $height . 'px;'; + if (!is_null($marginTop)) { + $strStyle .= ' margin-top:' . $marginTop . 'px;'; + } + if (!is_null($marginLeft)) { + $strStyle .= ' margin-left:' . $marginLeft . 'px;'; + } + + $xmlWriter->writeAttribute('style', $strStyle); + + $xmlWriter->startElement('v:imagedata'); + $xmlWriter->writeAttribute('r:id', 'rId' . $rId); + $xmlWriter->writeAttribute('o:title', ''); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + + $xmlWriter->endElement(); + + $xmlWriter->endElement(); + + $xmlWriter->endElement(); + } + + protected function _writeTitle(XMLWriter $xmlWriter = null, Title $title) + { + $text = htmlspecialchars($title->getText()); + $text = String::ControlCharacterPHP2OOXML($text); + $anchor = $title->getAnchor(); + $bookmarkId = $title->getBookmarkId(); + $style = $title->getStyle(); + + $xmlWriter->startElement('w:p'); + + if (!empty($style)) { + $xmlWriter->startElement('w:pPr'); + $xmlWriter->startElement('w:pStyle'); + $xmlWriter->writeAttribute('w:val', $style); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + } + + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:fldChar'); + $xmlWriter->writeAttribute('w:fldCharType', 'end'); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + + $xmlWriter->startElement('w:bookmarkStart'); + $xmlWriter->writeAttribute('w:id', $bookmarkId); + $xmlWriter->writeAttribute('w:name', $anchor); + $xmlWriter->endElement(); + + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:t'); + $xmlWriter->writeRaw($text); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + + $xmlWriter->startElement('w:bookmarkEnd'); + $xmlWriter->writeAttribute('w:id', $bookmarkId); + $xmlWriter->endElement(); + + $xmlWriter->endElement(); + } + + protected function _writeFootnote(XMLWriter $xmlWriter = null, Footnote $footnote) + { + $xmlWriter->startElement('w:footnote'); + $xmlWriter->writeAttribute('w:id', $footnote->getReferenceId()); + + $styleParagraph = $footnote->getParagraphStyle(); + $SpIsObject = ($styleParagraph instanceof Paragraph) ? true : false; + + $xmlWriter->startElement('w:p'); + + if ($SpIsObject) { + $this->_writeParagraphStyle($xmlWriter, $styleParagraph); + } elseif (!$SpIsObject && !is_null($styleParagraph)) { + $xmlWriter->startElement('w:pPr'); + $xmlWriter->startElement('w:pStyle'); + $xmlWriter->writeAttribute('w:val', $styleParagraph); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + } + + $elements = $footnote->getElements(); + if (count($elements) > 0) { + foreach ($elements as $element) { + if ($element instanceof Text) { + $this->_writeText($xmlWriter, $element, true); + } elseif ($element instanceof Link) { + $this->_writeLink($xmlWriter, $element, true); + } + } + } + + $xmlWriter->endElement(); // w:p + $xmlWriter->endElement(); // w:footnote + } + + protected function _writeFootnoteReference(XMLWriter $xmlWriter = null, Footnote $footnote, $withoutP = false) + { + if (!$withoutP) { + $xmlWriter->startElement('w:p'); + } + + $xmlWriter->startElement('w:r'); + + $xmlWriter->startElement('w:footnoteReference'); + $xmlWriter->writeAttribute('w:id', $footnote->getReferenceId()); + $xmlWriter->endElement(); // w:footnoteReference + + $xmlWriter->endElement(); // w:r + + if (!$withoutP) { + $xmlWriter->endElement(); // w:p + } + } +} diff --git a/src/Writer/Word2007/ContentTypes.php b/src/Writer/Word2007/ContentTypes.php new file mode 100644 index 00000000..2d84070d --- /dev/null +++ b/src/Writer/Word2007/ContentTypes.php @@ -0,0 +1,228 @@ +getParentWriter()->getUseDiskCaching()) { + $xmlWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $xmlWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY); + } + + // XML header + $xmlWriter->startDocument('1.0', 'UTF-8', 'yes'); + + // Types + $xmlWriter->startElement('Types'); + $xmlWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/content-types'); + + // Rels + $this->_writeDefaultContentType( + $xmlWriter, + 'rels', + 'application/vnd.openxmlformats-package.relationships+xml' + ); + + // XML + $this->_writeDefaultContentType( + $xmlWriter, + 'xml', + 'application/xml' + ); + + // Add media content-types + foreach ($_imageTypes as $key => $value) { + $this->_writeDefaultContentType($xmlWriter, $key, $value); + } + + // Add embedding content-types + if (count($_objectTypes) > 0) { + $this->_writeDefaultContentType( + $xmlWriter, + 'bin', + 'application/vnd.openxmlformats-officedocument.oleObject' + ); + } + + // DocProps + $this->_writeOverrideContentType( + $xmlWriter, + '/docProps/app.xml', + 'application/vnd.openxmlformats-officedocument.extended-properties+xml' + ); + + $this->_writeOverrideContentType( + $xmlWriter, + '/docProps/core.xml', + 'application/vnd.openxmlformats-package.core-properties+xml' + ); + + // Document + $this->_writeOverrideContentType( + $xmlWriter, + '/word/document.xml', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml' + ); + + // Styles + $this->_writeOverrideContentType( + $xmlWriter, + '/word/styles.xml', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml' + ); + + // Numbering + $this->_writeOverrideContentType( + $xmlWriter, + '/word/numbering.xml', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml' + ); + + // Settings + $this->_writeOverrideContentType( + $xmlWriter, + '/word/settings.xml', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml' + ); + + // Theme1 + $this->_writeOverrideContentType( + $xmlWriter, + '/word/theme/theme1.xml', + 'application/vnd.openxmlformats-officedocument.theme+xml' + ); + + // WebSettings + $this->_writeOverrideContentType( + $xmlWriter, + '/word/webSettings.xml', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml' + ); + + // Font Table + $this->_writeOverrideContentType( + $xmlWriter, + '/word/fontTable.xml', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml' + ); + + // Footnotes + $this->_writeOverrideContentType( + $xmlWriter, + '/word/footnotes.xml', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml' + ); + + for ($i = 1; $i <= $_cHdrs; $i++) { + $this->_writeOverrideContentType( + $xmlWriter, + '/word/header' . $i . '.xml', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml' + ); + } + + for ($i = 1; $i <= count($footers); $i++) { + if (!is_null($footers[$i])) { + $this->_writeOverrideContentType( + $xmlWriter, + '/word/footer' . $i . '.xml', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml' + ); + } + } + + + $xmlWriter->endElement(); + + // Return + return $xmlWriter->getData(); + } + + /** + * Get image mime type + * + * @param string $pFile Filename + * @return string Mime Type + * @throws Exception + */ + private function _getImageMimeType($pFile = '') + { + if (File::file_exists($pFile)) { + $image = getimagesize($pFile); + return image_type_to_mime_type($image[2]); + } else { + throw new Exception("File $pFile does not exist"); + } + } + + /** + * @param PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter XML Writer + * @param string $pPartname Part name + * @param string $pContentType Content type + * @throws Exception + */ + private function _writeDefaultContentType(XMLWriter $xmlWriter = null, $pPartname = '', $pContentType = '') + { + if ($pPartname != '' && $pContentType != '') { + // Write content type + $xmlWriter->startElement('Default'); + $xmlWriter->writeAttribute('Extension', $pPartname); + $xmlWriter->writeAttribute('ContentType', $pContentType); + $xmlWriter->endElement(); + } else { + throw new Exception("Invalid parameters passed."); + } + } + + /** + * @param PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param string $pPartname Part name + * @param string $pContentType Content type + * @throws Exception + */ + private function _writeOverrideContentType(XMLWriter $xmlWriter = null, $pPartname = '', $pContentType = '') + { + if ($pPartname != '' && $pContentType != '') { + // Write content type + $xmlWriter->startElement('Override'); + $xmlWriter->writeAttribute('PartName', $pPartname); + $xmlWriter->writeAttribute('ContentType', $pContentType); + $xmlWriter->endElement(); + } else { + throw new Exception("Invalid parameters passed."); + } + } +} diff --git a/src/Writer/Word2007/DocProps.php b/src/Writer/Word2007/DocProps.php new file mode 100644 index 00000000..98a5abb8 --- /dev/null +++ b/src/Writer/Word2007/DocProps.php @@ -0,0 +1,186 @@ +getParentWriter()->getUseDiskCaching()) { + $xmlWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $xmlWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY); + } + + // XML header + $xmlWriter->startDocument('1.0', 'UTF-8', 'yes'); + + // Properties + $xmlWriter->startElement('Properties'); + $xmlWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/officeDocument/2006/extended-properties'); + $xmlWriter->writeAttribute('xmlns:vt', 'http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes'); + + // Application + $xmlWriter->writeElement('Application', 'Microsoft Office Word'); + + // ScaleCrop + $xmlWriter->writeElement('ScaleCrop', 'false'); + + // HeadingPairs + $xmlWriter->startElement('HeadingPairs'); + + // Vector + $xmlWriter->startElement('vt:vector'); + $xmlWriter->writeAttribute('size', '4'); + $xmlWriter->writeAttribute('baseType', 'variant'); + + // Variant + $xmlWriter->startElement('vt:variant'); + $xmlWriter->writeElement('vt:lpstr', 'Theme'); + $xmlWriter->endElement(); + + // Variant + $xmlWriter->startElement('vt:variant'); + $xmlWriter->writeElement('vt:i4', '1'); + $xmlWriter->endElement(); + + // Variant + $xmlWriter->startElement('vt:variant'); + $xmlWriter->writeElement('vt:lpstr', 'Slide Titles'); + $xmlWriter->endElement(); + + // Variant + $xmlWriter->startElement('vt:variant'); + $xmlWriter->writeElement('vt:i4', '1'); + $xmlWriter->endElement(); + + $xmlWriter->endElement(); + + $xmlWriter->endElement(); + + // TitlesOfParts + $xmlWriter->startElement('TitlesOfParts'); + + // Vector + $xmlWriter->startElement('vt:vector'); + $xmlWriter->writeAttribute('size', '1'); + $xmlWriter->writeAttribute('baseType', 'lpstr'); + + $xmlWriter->writeElement('vt:lpstr', 'Office Theme'); + + $xmlWriter->endElement(); + + $xmlWriter->endElement(); + + // Company + $xmlWriter->writeElement('Company', $phpWord->getDocumentProperties()->getCompany()); + + // LinksUpToDate + $xmlWriter->writeElement('LinksUpToDate', 'false'); + + // SharedDoc + $xmlWriter->writeElement('SharedDoc', 'false'); + + // HyperlinksChanged + $xmlWriter->writeElement('HyperlinksChanged', 'false'); + + // AppVersion + $xmlWriter->writeElement('AppVersion', '12.0000'); + + $xmlWriter->endElement(); + + // Return + return $xmlWriter->getData(); + } + + + public function writeDocPropsCore(PhpWord $phpWord = null) + { + // Create XML writer + $xmlWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $xmlWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $xmlWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY); + } + + // XML header + $xmlWriter->startDocument('1.0', 'UTF-8', 'yes'); + + // cp:coreProperties + $xmlWriter->startElement('cp:coreProperties'); + $xmlWriter->writeAttribute('xmlns:cp', 'http://schemas.openxmlformats.org/package/2006/metadata/core-properties'); + $xmlWriter->writeAttribute('xmlns:dc', 'http://purl.org/dc/elements/1.1/'); + $xmlWriter->writeAttribute('xmlns:dcterms', 'http://purl.org/dc/terms/'); + $xmlWriter->writeAttribute('xmlns:dcmitype', 'http://purl.org/dc/dcmitype/'); + $xmlWriter->writeAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance'); + + // dc:creator + $xmlWriter->writeElement('dc:creator', $phpWord->getDocumentProperties()->getCreator()); + + // cp:lastModifiedBy + $xmlWriter->writeElement('cp:lastModifiedBy', $phpWord->getDocumentProperties()->getLastModifiedBy()); + + // dcterms:created + $xmlWriter->startElement('dcterms:created'); + $xmlWriter->writeAttribute('xsi:type', 'dcterms:W3CDTF'); + $xmlWriter->writeRaw(date(DATE_W3C, $phpWord->getDocumentProperties()->getCreated())); + $xmlWriter->endElement(); + + // dcterms:modified + $xmlWriter->startElement('dcterms:modified'); + $xmlWriter->writeAttribute('xsi:type', 'dcterms:W3CDTF'); + $xmlWriter->writeRaw(date(DATE_W3C, $phpWord->getDocumentProperties()->getModified())); + $xmlWriter->endElement(); + + // dc:title + $xmlWriter->writeElement('dc:title', $phpWord->getDocumentProperties()->getTitle()); + + // dc:description + $xmlWriter->writeElement('dc:description', $phpWord->getDocumentProperties()->getDescription()); + + // dc:subject + $xmlWriter->writeElement('dc:subject', $phpWord->getDocumentProperties()->getSubject()); + + // cp:keywords + $xmlWriter->writeElement('cp:keywords', $phpWord->getDocumentProperties()->getKeywords()); + + // cp:category + $xmlWriter->writeElement('cp:category', $phpWord->getDocumentProperties()->getCategory()); + + $xmlWriter->endElement(); + + // Return + return $xmlWriter->getData(); + } +} diff --git a/src/Writer/Word2007/Document.php b/src/Writer/Word2007/Document.php new file mode 100644 index 00000000..f865c41c --- /dev/null +++ b/src/Writer/Word2007/Document.php @@ -0,0 +1,506 @@ +getParentWriter()->getUseDiskCaching()) { + $xmlWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $xmlWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY); + } + + // XML header + $xmlWriter->startDocument('1.0', 'UTF-8', 'yes'); + + // w:document + $xmlWriter->startElement('w:document'); + + $xmlWriter->writeAttribute('xmlns:ve', 'http://schemas.openxmlformats.org/markup-compatibility/2006'); + $xmlWriter->writeAttribute('xmlns:o', 'urn:schemas-microsoft-com:office:office'); + $xmlWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'); + $xmlWriter->writeAttribute('xmlns:m', 'http://schemas.openxmlformats.org/officeDocument/2006/math'); + $xmlWriter->writeAttribute('xmlns:v', 'urn:schemas-microsoft-com:vml'); + $xmlWriter->writeAttribute('xmlns:wp', 'http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing'); + $xmlWriter->writeAttribute('xmlns:w10', 'urn:schemas-microsoft-com:office:word'); + $xmlWriter->writeAttribute('xmlns:w', 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'); + $xmlWriter->writeAttribute('xmlns:wne', 'http://schemas.microsoft.com/office/word/2006/wordml'); + + $xmlWriter->startElement('w:body'); + + $_sections = $phpWord->getSections(); + $countSections = count($_sections); + $pSection = 0; + + if ($countSections > 0) { + foreach ($_sections as $section) { + $pSection++; + + $_elements = $section->getElements(); + + foreach ($_elements as $element) { + if ($element instanceof Text) { + $this->_writeText($xmlWriter, $element); + } elseif ($element instanceof TextRun) { + $this->_writeTextRun($xmlWriter, $element); + } elseif ($element instanceof Link) { + $this->_writeLink($xmlWriter, $element); + } elseif ($element instanceof Title) { + $this->_writeTitle($xmlWriter, $element); + } elseif ($element instanceof TextBreak) { + $this->_writeTextBreak($xmlWriter, $element); + } elseif ($element instanceof PageBreak) { + $this->_writePageBreak($xmlWriter); + } elseif ($element instanceof Table) { + $this->_writeTable($xmlWriter, $element); + } elseif ($element instanceof ListItem) { + $this->_writeListItem($xmlWriter, $element); + } elseif ($element instanceof Image || + $element instanceof MemoryImage + ) { + $this->_writeImage($xmlWriter, $element); + } elseif ($element instanceof Object) { + $this->_writeObject($xmlWriter, $element); + } elseif ($element instanceof TOC) { + $this->_writeTOC($xmlWriter); + } elseif ($element instanceof Footnote) { + $this->_writeFootnoteReference($xmlWriter, $element); + } + } + + if ($pSection == $countSections) { + $this->_writeEndSection($xmlWriter, $section); + } else { + $this->_writeSection($xmlWriter, $section); + } + } + } + + $xmlWriter->endElement(); // End w:body + $xmlWriter->endElement(); // End w:document + + // Return + return $xmlWriter->getData(); + } + + private function _writeSection(XMLWriter $xmlWriter = null, Section $section) + { + $xmlWriter->startElement('w:p'); + $xmlWriter->startElement('w:pPr'); + $this->_writeEndSection($xmlWriter, $section, 3); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + } + + private function _writeEndSection(XMLWriter $xmlWriter = null, Section $section) + { + $settings = $section->getSettings(); + $_headers = $section->getHeaders(); + $_footer = $section->getFooter(); + $pgSzW = $settings->getPageSizeW(); + $pgSzH = $settings->getPageSizeH(); + $orientation = $settings->getOrientation(); + + $marginTop = $settings->getMarginTop(); + $marginLeft = $settings->getMarginLeft(); + $marginRight = $settings->getMarginRight(); + $marginBottom = $settings->getMarginBottom(); + + $headerHeight = $settings->getHeaderHeight(); + $footerHeight = $settings->getFooterHeight(); + + $borders = $settings->getBorderSize(); + + $colsNum = $settings->getColsNum(); + $colsSpace = $settings->getColsSpace(); + $breakType = $settings->getBreakType(); + + $xmlWriter->startElement('w:sectPr'); + + foreach ($_headers as &$_header) { + $rId = $_header->getRelationId(); + $xmlWriter->startElement('w:headerReference'); + $xmlWriter->writeAttribute('w:type', $_header->getType()); + $xmlWriter->writeAttribute('r:id', 'rId' . $rId); + $xmlWriter->endElement(); + } + + if ($section->hasDifferentFirstPage()) { + $xmlWriter->startElement('w:titlePg'); + $xmlWriter->endElement(); + } + + if (!is_null($breakType)) { + $xmlWriter->startElement('w:type'); + $xmlWriter->writeAttribute('w:val', $breakType); + $xmlWriter->endElement(); + } + + if (!is_null($_footer)) { + $rId = $_footer->getRelationId(); + $xmlWriter->startElement('w:footerReference'); + $xmlWriter->writeAttribute('w:type', 'default'); + $xmlWriter->writeAttribute('r:id', 'rId' . $rId); + $xmlWriter->endElement(); + } + + $xmlWriter->startElement('w:pgSz'); + $xmlWriter->writeAttribute('w:w', $pgSzW); + $xmlWriter->writeAttribute('w:h', $pgSzH); + + if (!is_null($orientation) && strtolower($orientation) != 'portrait') { + $xmlWriter->writeAttribute('w:orient', $orientation); + } + + $xmlWriter->endElement(); + + $xmlWriter->startElement('w:pgMar'); + $xmlWriter->writeAttribute('w:top', $marginTop); + $xmlWriter->writeAttribute('w:right', $marginRight); + $xmlWriter->writeAttribute('w:bottom', $marginBottom); + $xmlWriter->writeAttribute('w:left', $marginLeft); + $xmlWriter->writeAttribute('w:header', $headerHeight); + $xmlWriter->writeAttribute('w:footer', $footerHeight); + $xmlWriter->writeAttribute('w:gutter', '0'); + $xmlWriter->endElement(); + + + if (!is_null($borders[0]) || !is_null($borders[1]) || !is_null($borders[2]) || !is_null($borders[3])) { + $borderColor = $settings->getBorderColor(); + + $xmlWriter->startElement('w:pgBorders'); + $xmlWriter->writeAttribute('w:offsetFrom', 'page'); + + if (!is_null($borders[0])) { + $xmlWriter->startElement('w:top'); + $xmlWriter->writeAttribute('w:val', 'single'); + $xmlWriter->writeAttribute('w:sz', $borders[0]); + $xmlWriter->writeAttribute('w:space', '24'); + $xmlWriter->writeAttribute('w:color', $borderColor[0]); + $xmlWriter->endElement(); + } + + if (!is_null($borders[1])) { + $xmlWriter->startElement('w:left'); + $xmlWriter->writeAttribute('w:val', 'single'); + $xmlWriter->writeAttribute('w:sz', $borders[1]); + $xmlWriter->writeAttribute('w:space', '24'); + $xmlWriter->writeAttribute('w:color', $borderColor[1]); + $xmlWriter->endElement(); + } + + if (!is_null($borders[2])) { + $xmlWriter->startElement('w:right'); + $xmlWriter->writeAttribute('w:val', 'single'); + $xmlWriter->writeAttribute('w:sz', $borders[2]); + $xmlWriter->writeAttribute('w:space', '24'); + $xmlWriter->writeAttribute('w:color', $borderColor[2]); + $xmlWriter->endElement(); + } + + if (!is_null($borders[3])) { + $xmlWriter->startElement('w:bottom'); + $xmlWriter->writeAttribute('w:val', 'single'); + $xmlWriter->writeAttribute('w:sz', $borders[3]); + $xmlWriter->writeAttribute('w:space', '24'); + $xmlWriter->writeAttribute('w:color', $borderColor[3]); + $xmlWriter->endElement(); + } + $xmlWriter->endElement(); + } + + // Page numbering + if (null !== $settings->getPageNumberingStart()) { + $xmlWriter->startElement('w:pgNumType'); + $xmlWriter->writeAttribute('w:start', $section->getSettings()->getPageNumberingStart()); + $xmlWriter->endElement(); + } + + $xmlWriter->startElement('w:cols'); + $xmlWriter->writeAttribute('w:num', $colsNum); + $xmlWriter->writeAttribute('w:space', $colsSpace); + $xmlWriter->endElement(); + + + $xmlWriter->endElement(); + } + + private function _writePageBreak(XMLWriter $xmlWriter = null) + { + $xmlWriter->startElement('w:p'); + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:br'); + $xmlWriter->writeAttribute('w:type', 'page'); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + } + + public function _writeListItem(XMLWriter $xmlWriter = null, ListItem $listItem) + { + $textObject = $listItem->getTextObject(); + $text = $textObject->getText(); + $styleParagraph = $textObject->getParagraphStyle(); + $SpIsObject = ($styleParagraph instanceof Paragraph) ? true : false; + + $depth = $listItem->getDepth(); + $listType = $listItem->getStyle()->getListType(); + + $xmlWriter->startElement('w:p'); + $xmlWriter->startElement('w:pPr'); + + if ($SpIsObject) { + $this->_writeParagraphStyle($xmlWriter, $styleParagraph, true); + } elseif (!$SpIsObject && !is_null($styleParagraph)) { + $xmlWriter->startElement('w:pStyle'); + $xmlWriter->writeAttribute('w:val', $styleParagraph); + $xmlWriter->endElement(); + } + + $xmlWriter->startElement('w:numPr'); + + $xmlWriter->startElement('w:ilvl'); + $xmlWriter->writeAttribute('w:val', $depth); + $xmlWriter->endElement(); + + $xmlWriter->startElement('w:numId'); + $xmlWriter->writeAttribute('w:val', $listType); + $xmlWriter->endElement(); + + $xmlWriter->endElement(); + $xmlWriter->endElement(); + + $this->_writeText($xmlWriter, $textObject, true); + + $xmlWriter->endElement(); + } + + protected function _writeObject(XMLWriter $xmlWriter = null, Object $object) + { + $rIdObject = $object->getRelationId(); + $rIdImage = $object->getImageRelationId(); + $shapeId = md5($rIdObject . '_' . $rIdImage); + + $objectId = $object->getObjectId(); + + $style = $object->getStyle(); + $width = $style->getWidth(); + $height = $style->getHeight(); + $align = $style->getAlign(); + + + $xmlWriter->startElement('w:p'); + + if (!is_null($align)) { + $xmlWriter->startElement('w:pPr'); + $xmlWriter->startElement('w:jc'); + $xmlWriter->writeAttribute('w:val', $align); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + } + + $xmlWriter->startElement('w:r'); + + $xmlWriter->startElement('w:object'); + $xmlWriter->writeAttribute('w:dxaOrig', '249'); + $xmlWriter->writeAttribute('w:dyaOrig', '160'); + + $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(); + + $xmlWriter->endElement(); + + $xmlWriter->startElement('o:OLEObject'); + $xmlWriter->writeAttribute('Type', 'Embed'); + $xmlWriter->writeAttribute('ProgID', 'Package'); + $xmlWriter->writeAttribute('ShapeID', $shapeId); + $xmlWriter->writeAttribute('DrawAspect', 'Icon'); + $xmlWriter->writeAttribute('ObjectID', '_' . $objectId); + $xmlWriter->writeAttribute('r:id', 'rId' . $rIdObject); + $xmlWriter->endElement(); + + $xmlWriter->endElement(); + + $xmlWriter->endElement(); // w:r + + $xmlWriter->endElement(); // w:p + } + + private function _writeTOC(XMLWriter $xmlWriter = null) + { + $titles = TOC::getTitles(); + $styleFont = TOC::getStyleFont(); + + $styleTOC = TOC::getStyleTOC(); + $fIndent = $styleTOC->getIndent(); + $tabLeader = $styleTOC->getTabLeader(); + $tabPos = $styleTOC->getTabPos(); + + $isObject = ($styleFont instanceof Font) ? true : false; + + for ($i = 0; $i < count($titles); $i++) { + $title = $titles[$i]; + $indent = ($title['depth'] - 1) * $fIndent; + + $xmlWriter->startElement('w:p'); + + $xmlWriter->startElement('w:pPr'); + + if ($isObject && !is_null($styleFont->getParagraphStyle())) { + $this->_writeParagraphStyle($xmlWriter, $styleFont->getParagraphStyle()); + } + + if ($indent > 0) { + $xmlWriter->startElement('w:ind'); + $xmlWriter->writeAttribute('w:left', $indent); + $xmlWriter->endElement(); + } + + if (!empty($styleFont) && !$isObject) { + $xmlWriter->startElement('w:pPr'); + $xmlWriter->startElement('w:pStyle'); + $xmlWriter->writeAttribute('w:val', $styleFont); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + } + + $xmlWriter->startElement('w:tabs'); + $xmlWriter->startElement('w:tab'); + $xmlWriter->writeAttribute('w:val', 'right'); + if (!empty($tabLeader)) { + $xmlWriter->writeAttribute('w:leader', $tabLeader); + } + $xmlWriter->writeAttribute('w:pos', $tabPos); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + + $xmlWriter->endElement(); // w:pPr + + + if ($i == 0) { + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:fldChar'); + $xmlWriter->writeAttribute('w:fldCharType', 'begin'); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:instrText'); + $xmlWriter->writeAttribute('xml:space', 'preserve'); + $xmlWriter->writeRaw('TOC \o "1-9" \h \z \u'); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:fldChar'); + $xmlWriter->writeAttribute('w:fldCharType', 'separate'); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + } + + $xmlWriter->startElement('w:hyperlink'); + $xmlWriter->writeAttribute('w:anchor', $title['anchor']); + $xmlWriter->writeAttribute('w:history', '1'); + + $xmlWriter->startElement('w:r'); + + if ($isObject) { + $this->_writeTextStyle($xmlWriter, $styleFont); + } + + $xmlWriter->startElement('w:t'); + $xmlWriter->writeRaw($title['text']); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + + $xmlWriter->startElement('w:r'); + $xmlWriter->writeElement('w:tab', null); + $xmlWriter->endElement(); + + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:fldChar'); + $xmlWriter->writeAttribute('w:fldCharType', 'begin'); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:instrText'); + $xmlWriter->writeAttribute('xml:space', 'preserve'); + $xmlWriter->writeRaw('PAGEREF ' . $title['anchor'] . ' \h'); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:fldChar'); + $xmlWriter->writeAttribute('w:fldCharType', 'end'); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + + $xmlWriter->endElement(); // w:hyperlink + + $xmlWriter->endElement(); // w:p + } + + $xmlWriter->startElement('w:p'); + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:fldChar'); + $xmlWriter->writeAttribute('w:fldCharType', 'end'); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + } +} diff --git a/src/Writer/Word2007/DocumentRels.php b/src/Writer/Word2007/DocumentRels.php new file mode 100644 index 00000000..176dd055 --- /dev/null +++ b/src/Writer/Word2007/DocumentRels.php @@ -0,0 +1,182 @@ +getParentWriter()->getUseDiskCaching()) { + $xmlWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $xmlWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY); + } + + // XML header + $xmlWriter->startDocument('1.0', 'UTF-8', 'yes'); + + // Relationships + $xmlWriter->startElement('Relationships'); + $xmlWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships'); + + // Relationship word/document.xml + $this->_writeRelationship( + $xmlWriter, + 1, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles', + 'styles.xml' + ); + + // Relationship word/numbering.xml + $this->_writeRelationship( + $xmlWriter, + 2, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering', + 'numbering.xml' + ); + + // Relationship word/settings.xml + $this->_writeRelationship( + $xmlWriter, + 3, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings', + 'settings.xml' + ); + + // Relationship word/settings.xml + $this->_writeRelationship( + $xmlWriter, + 4, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme', + 'theme/theme1.xml' + ); + + // Relationship word/settings.xml + $this->_writeRelationship( + $xmlWriter, + 5, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings', + 'webSettings.xml' + ); + + // Relationship word/settings.xml + $this->_writeRelationship( + $xmlWriter, + 6, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable', + 'fontTable.xml' + ); + + // Relationships to Images / Embeddings / Headers / Footers + foreach ($_relsCollection as $relation) { + $relationType = $relation['type']; + $relationName = $relation['target']; + $relationId = $relation['rID']; + $targetMode = ($relationType == 'hyperlink') ? 'External' : ''; + + $this->_writeRelationship( + $xmlWriter, + $relationId, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/' . $relationType, + $relationName, + $targetMode + ); + } + + + $xmlWriter->endElement(); + + // Return + return $xmlWriter->getData(); + } + + public function writeHeaderFooterRels($_relsCollection) + { + // Create XML writer + $xmlWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $xmlWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $xmlWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY); + } + + // XML header + $xmlWriter->startDocument('1.0', 'UTF-8', 'yes'); + + // Relationships + $xmlWriter->startElement('Relationships'); + $xmlWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships'); + + // Relationships to Images / Embeddings / Headers / Footers + foreach ($_relsCollection as $relation) { + $relationType = $relation['type']; + $relationName = $relation['target']; + $relationId = $relation['rID']; + + $this->_writeRelationship( + $xmlWriter, + $relationId, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/' . $relationType, + $relationName + ); + } + + + $xmlWriter->endElement(); + + // Return + return $xmlWriter->getData(); + } + + private function _writeRelationship(XMLWriter $xmlWriter = null, $pId = 1, $pType = '', $pTarget = '', $pTargetMode = '') + { + if ($pType != '' && $pTarget != '') { + if (strpos($pId, 'rId') === false) { + $pId = 'rId' . $pId; + } + + // Write relationship + $xmlWriter->startElement('Relationship'); + $xmlWriter->writeAttribute('Id', $pId); + $xmlWriter->writeAttribute('Type', $pType); + $xmlWriter->writeAttribute('Target', $pTarget); + + if ($pTargetMode != '') { + $xmlWriter->writeAttribute('TargetMode', $pTargetMode); + } + + $xmlWriter->endElement(); + } else { + throw new Exception("Invalid parameters passed."); + } + } +} diff --git a/src/Writer/Word2007/Footer.php b/src/Writer/Word2007/Footer.php new file mode 100644 index 00000000..f3ef2a1f --- /dev/null +++ b/src/Writer/Word2007/Footer.php @@ -0,0 +1,90 @@ +getParentWriter()->getUseDiskCaching()) { + $xmlWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $xmlWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY); + } + + // XML header + $xmlWriter->startDocument('1.0', 'UTF-8', 'yes'); + + $xmlWriter->startElement('w:ftr'); + $xmlWriter->writeAttribute('xmlns:ve', 'http://schemas.openxmlformats.org/markup-compatibility/2006'); + $xmlWriter->writeAttribute('xmlns:o', 'urn:schemas-microsoft-com:office:office'); + $xmlWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'); + $xmlWriter->writeAttribute('xmlns:m', 'http://schemas.openxmlformats.org/officeDocument/2006/math'); + $xmlWriter->writeAttribute('xmlns:v', 'urn:schemas-microsoft-com:vml'); + $xmlWriter->writeAttribute('xmlns:wp', 'http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing'); + $xmlWriter->writeAttribute('xmlns:w10', 'urn:schemas-microsoft-com:office:word'); + $xmlWriter->writeAttribute('xmlns:w', 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'); + $xmlWriter->writeAttribute('xmlns:wne', 'http://schemas.microsoft.com/office/word/2006/wordml'); + + $_elements = $footer->getElements(); + + foreach ($_elements as $element) { + if ($element instanceof Text) { + $this->_writeText($xmlWriter, $element); + } elseif ($element instanceof TextRun) { + $this->_writeTextRun($xmlWriter, $element); + } elseif ($element instanceof TextBreak) { + $this->_writeTextBreak($xmlWriter, $element); + } elseif ($element instanceof Table) { + $this->_writeTable($xmlWriter, $element); + } elseif ($element instanceof Image || + $element instanceof MemoryImage + ) { + $this->_writeImage($xmlWriter, $element); + } elseif ($element instanceof PreserveText) { + $this->_writePreserveText($xmlWriter, $element); + } + } + + $xmlWriter->endElement(); + + // Return + return $xmlWriter->getData(); + } +} diff --git a/src/Writer/Word2007/Footnotes.php b/src/Writer/Word2007/Footnotes.php new file mode 100644 index 00000000..d467859f --- /dev/null +++ b/src/Writer/Word2007/Footnotes.php @@ -0,0 +1,87 @@ +getParentWriter()->getUseDiskCaching()) { + $xmlWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $xmlWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY); + } + + // XML header + $xmlWriter->startDocument('1.0', 'UTF-8', 'yes'); + + $xmlWriter->startElement('w:footnotes'); + $xmlWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'); + $xmlWriter->writeAttribute('xmlns:w', 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'); + + // write separator and continuation separator + $xmlWriter->startElement('w:footnote'); + $xmlWriter->writeAttribute('w:id', 0); + $xmlWriter->writeAttribute('w:type', 'separator'); + $xmlWriter->startElement('w:p'); + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:separator'); + $xmlWriter->endElement(); // w:separator + $xmlWriter->endElement(); // w:r + $xmlWriter->endElement(); // w:p + $xmlWriter->endElement(); // w:footnote + + $xmlWriter->startElement('w:footnote'); + $xmlWriter->writeAttribute('w:id', 1); + $xmlWriter->writeAttribute('w:type', 'continuationSeparator'); + $xmlWriter->startElement('w:p'); + $xmlWriter->startElement('w:r'); + $xmlWriter->startElement('w:continuationSeparator'); + $xmlWriter->endElement(); // w:continuationSeparator + $xmlWriter->endElement(); // w:r + $xmlWriter->endElement(); // w:p + $xmlWriter->endElement(); // w:footnote + + + foreach ($allFootnotesCollection as $footnote) { + if ($footnote instanceof Footnote) { + $this->_writeFootnote($xmlWriter, $footnote); + } + } + + $xmlWriter->endElement(); + + // Return + return $xmlWriter->getData(); + } +} diff --git a/src/Writer/Word2007/FootnotesRels.php b/src/Writer/Word2007/FootnotesRels.php new file mode 100644 index 00000000..b1819876 --- /dev/null +++ b/src/Writer/Word2007/FootnotesRels.php @@ -0,0 +1,89 @@ +getParentWriter()->getUseDiskCaching()) { + $xmlWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $xmlWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY); + } + + // XML header + $xmlWriter->startDocument('1.0', 'UTF-8', 'yes'); + + // Relationships + $xmlWriter->startElement('Relationships'); + $xmlWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships'); + + // Relationships to Links + foreach ($_relsCollection as $relation) { + $relationType = $relation['type']; + $relationName = $relation['target']; + $relationId = $relation['rID']; + $targetMode = ($relationType == 'hyperlink') ? 'External' : ''; + + $this->_writeRelationship($xmlWriter, $relationId, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/' . $relationType, $relationName, $targetMode); + } + + $xmlWriter->endElement(); + + // Return + return $xmlWriter->getData(); + } + + private function _writeRelationship(XMLWriter $xmlWriter = null, $pId = 1, $pType = '', $pTarget = '', $pTargetMode = '') + { + if ($pType != '' && $pTarget != '') { + if (strpos($pId, 'rId') === false) { + $pId = 'rId' . $pId; + } + + // Write relationship + $xmlWriter->startElement('Relationship'); + $xmlWriter->writeAttribute('Id', $pId); + $xmlWriter->writeAttribute('Type', $pType); + $xmlWriter->writeAttribute('Target', $pTarget); + + if ($pTargetMode != '') { + $xmlWriter->writeAttribute('TargetMode', $pTargetMode); + } + + $xmlWriter->endElement(); + } else { + throw new Exception("Invalid parameters passed."); + } + } +} diff --git a/src/Writer/Word2007/Header.php b/src/Writer/Word2007/Header.php new file mode 100644 index 00000000..aef2c38a --- /dev/null +++ b/src/Writer/Word2007/Header.php @@ -0,0 +1,94 @@ +getParentWriter()->getUseDiskCaching()) { + $xmlWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $xmlWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY); + } + + // XML header + $xmlWriter->startDocument('1.0', 'UTF-8', 'yes'); + + $xmlWriter->startElement('w:hdr'); + $xmlWriter->writeAttribute('xmlns:ve', 'http://schemas.openxmlformats.org/markup-compatibility/2006'); + $xmlWriter->writeAttribute('xmlns:o', 'urn:schemas-microsoft-com:office:office'); + $xmlWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'); + $xmlWriter->writeAttribute('xmlns:m', 'http://schemas.openxmlformats.org/officeDocument/2006/math'); + $xmlWriter->writeAttribute('xmlns:v', 'urn:schemas-microsoft-com:vml'); + $xmlWriter->writeAttribute('xmlns:wp', 'http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing'); + $xmlWriter->writeAttribute('xmlns:w10', 'urn:schemas-microsoft-com:office:word'); + $xmlWriter->writeAttribute('xmlns:w', 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'); + $xmlWriter->writeAttribute('xmlns:wne', 'http://schemas.microsoft.com/office/word/2006/wordml'); + + + $_elements = $header->getElements(); + + foreach ($_elements as $element) { + if ($element instanceof Text) { + $this->_writeText($xmlWriter, $element); + } elseif ($element instanceof TextRun) { + $this->_writeTextRun($xmlWriter, $element); + } elseif ($element instanceof TextBreak) { + $this->_writeTextBreak($xmlWriter, $element); + } elseif ($element instanceof Table) { + $this->_writeTable($xmlWriter, $element); + } elseif ($element instanceof Image || + $element instanceof MemoryImage + ) { + if (!$element->getIsWatermark()) { + $this->_writeImage($xmlWriter, $element); + } else { + $this->_writeWatermark($xmlWriter, $element); + } + } elseif ($element instanceof PreserveText) { + $this->_writePreserveText($xmlWriter, $element); + } + } + + $xmlWriter->endElement(); + + // Return + return $xmlWriter->getData(); + } +} diff --git a/src/Writer/Word2007/Rels.php b/src/Writer/Word2007/Rels.php new file mode 100644 index 00000000..09de0e63 --- /dev/null +++ b/src/Writer/Word2007/Rels.php @@ -0,0 +1,115 @@ +getParentWriter()->getUseDiskCaching()) { + $xmlWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $xmlWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY); + } + + // XML header + $xmlWriter->startDocument('1.0', 'UTF-8', 'yes'); + + // Relationships + $xmlWriter->startElement('Relationships'); + $xmlWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships'); + + $relationId = 1; + + // Relationship word/document.xml + $this->_writeRelationship( + $xmlWriter, + $relationId, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument', + 'word/document.xml' + ); + + // Relationship docProps/core.xml + $this->_writeRelationship( + $xmlWriter, + ++$relationId, + 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties', + 'docProps/core.xml' + ); + + // Relationship docProps/app.xml + $this->_writeRelationship( + $xmlWriter, + ++$relationId, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties', + 'docProps/app.xml' + ); + + $xmlWriter->endElement(); + + return $xmlWriter->getData(); + } + + /** + * Write Override content type + * + * @param PhpOffice\PhpWord\Shared\XMLWriter $xmlWriter + * @param int $pId Relationship ID. rId will be prepended! + * @param string $pType Relationship type + * @param string $pTarget Relationship target + * @param string $pTargetMode Relationship target mode + * @throws Exception + */ + private function _writeRelationship(XMLWriter $xmlWriter = null, $pId = 1, $pType = '', $pTarget = '', $pTargetMode = '') + { + if ($pType != '' && $pTarget != '') { + if (strpos($pId, 'rId') === false) { + $pId = 'rId' . $pId; + } + + // Write relationship + $xmlWriter->startElement('Relationship'); + $xmlWriter->writeAttribute('Id', $pId); + $xmlWriter->writeAttribute('Type', $pType); + $xmlWriter->writeAttribute('Target', $pTarget); + + if ($pTargetMode != '') { + $xmlWriter->writeAttribute('TargetMode', $pTargetMode); + } + + $xmlWriter->endElement(); + } else { + throw new Exception("Invalid parameters passed."); + } + } +} diff --git a/src/Writer/Word2007/Styles.php b/src/Writer/Word2007/Styles.php new file mode 100644 index 00000000..81ee36ef --- /dev/null +++ b/src/Writer/Word2007/Styles.php @@ -0,0 +1,399 @@ +getParentWriter()->getUseDiskCaching()) { + $xmlWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $xmlWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY); + } + + $this->_document = $phpWord; + + // XML header + $xmlWriter->startDocument('1.0', 'UTF-8', 'yes'); + + $xmlWriter->startElement('w:styles'); + + $xmlWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'); + $xmlWriter->writeAttribute('xmlns:w', 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'); + + // Write DocDefaults + $this->_writeDocDefaults($xmlWriter); + + + // Write Style Definitions + $styles = Style::getStyles(); + + // Write normal paragraph style + $normalStyle = null; + if (array_key_exists('Normal', $styles)) { + $normalStyle = $styles['Normal']; + } + $xmlWriter->startElement('w:style'); + $xmlWriter->writeAttribute('w:type', 'paragraph'); + $xmlWriter->writeAttribute('w:default', '1'); + $xmlWriter->writeAttribute('w:styleId', 'Normal'); + $xmlWriter->startElement('w:name'); + $xmlWriter->writeAttribute('w:val', 'Normal'); + $xmlWriter->endElement(); + if (!is_null($normalStyle)) { + $this->_writeParagraphStyle($xmlWriter, $normalStyle); + } + $xmlWriter->endElement(); + + // Write other styles + if (count($styles) > 0) { + foreach ($styles as $styleName => $style) { + if ($styleName == 'Normal') { + continue; + } + if ($style instanceof Font) { + + $paragraphStyle = $style->getParagraphStyle(); + $styleType = $style->getStyleType(); + + $type = ($styleType == 'title') ? 'paragraph' : 'character'; + + if (!is_null($paragraphStyle)) { + $type = 'paragraph'; + } + + $xmlWriter->startElement('w:style'); + $xmlWriter->writeAttribute('w:type', $type); + + if ($styleType == 'title') { + $arrStyle = explode('_', $styleName); + $styleId = 'Heading' . $arrStyle[1]; + $styleName = 'heading ' . $arrStyle[1]; + $styleLink = 'Heading' . $arrStyle[1] . 'Char'; + $xmlWriter->writeAttribute('w:styleId', $styleId); + + $xmlWriter->startElement('w:link'); + $xmlWriter->writeAttribute('w:val', $styleLink); + $xmlWriter->endElement(); + } + + $xmlWriter->startElement('w:name'); + $xmlWriter->writeAttribute('w:val', $styleName); + $xmlWriter->endElement(); + + if (!is_null($paragraphStyle)) { + // Point parent style to Normal + $xmlWriter->startElement('w:basedOn'); + $xmlWriter->writeAttribute('w:val', 'Normal'); + $xmlWriter->endElement(); + $this->_writeParagraphStyle($xmlWriter, $paragraphStyle); + } + + $this->_writeTextStyle($xmlWriter, $style); + + $xmlWriter->endElement(); + + } elseif ($style instanceof Paragraph) { + $xmlWriter->startElement('w:style'); + $xmlWriter->writeAttribute('w:type', 'paragraph'); + $xmlWriter->writeAttribute('w:customStyle', '1'); + $xmlWriter->writeAttribute('w:styleId', $styleName); + + $xmlWriter->startElement('w:name'); + $xmlWriter->writeAttribute('w:val', $styleName); + $xmlWriter->endElement(); + + // Parent style + $basedOn = $style->getBasedOn(); + if (!is_null($basedOn)) { + $xmlWriter->startElement('w:basedOn'); + $xmlWriter->writeAttribute('w:val', $basedOn); + $xmlWriter->endElement(); + } + + // Next paragraph style + $next = $style->getNext(); + if (!is_null($next)) { + $xmlWriter->startElement('w:next'); + $xmlWriter->writeAttribute('w:val', $next); + $xmlWriter->endElement(); + } + + $this->_writeParagraphStyle($xmlWriter, $style); + $xmlWriter->endElement(); + + } elseif ($style instanceof TableFull) { + $xmlWriter->startElement('w:style'); + $xmlWriter->writeAttribute('w:type', 'table'); + $xmlWriter->writeAttribute('w:customStyle', '1'); + $xmlWriter->writeAttribute('w:styleId', $styleName); + + $xmlWriter->startElement('w:name'); + $xmlWriter->writeAttribute('w:val', $styleName); + $xmlWriter->endElement(); + + $xmlWriter->startElement('w:uiPriority'); + $xmlWriter->writeAttribute('w:val', '99'); + $xmlWriter->endElement(); + + $this->_writeFullTableStyle($xmlWriter, $style); + + $xmlWriter->endElement(); + } + } + } + + $xmlWriter->endElement(); // w:styles + + // Return + return $xmlWriter->getData(); + } + + private function _writeFullTableStyle(XMLWriter $xmlWriter = null, TableFull $style) + { + + $brdSz = $style->getBorderSize(); + $brdCol = $style->getBorderColor(); + $bgColor = $style->getBgColor(); + $cellMargin = $style->getCellMargin(); + + $bTop = (!is_null($brdSz[0])) ? true : false; + $bLeft = (!is_null($brdSz[1])) ? true : false; + $bRight = (!is_null($brdSz[2])) ? true : false; + $bBottom = (!is_null($brdSz[3])) ? true : false; + $bInsH = (!is_null($brdSz[4])) ? true : false; + $bInsV = (!is_null($brdSz[5])) ? true : false; + $borders = ($bTop || $bLeft || $bRight || $bBottom || $bInsH || $bInsV) ? true : false; + + $mTop = (!is_null($cellMargin[0])) ? true : false; + $mLeft = (!is_null($cellMargin[1])) ? true : false; + $mRight = (!is_null($cellMargin[2])) ? true : false; + $mBottom = (!is_null($cellMargin[3])) ? true : false; + $margins = ($mTop || $mLeft || $mRight || $mBottom) ? true : false; + + $xmlWriter->startElement('w:tblPr'); + + if ($margins) { + $xmlWriter->startElement('w:tblCellMar'); + if ($mTop) { + echo $margins[0]; + $xmlWriter->startElement('w:top'); + $xmlWriter->writeAttribute('w:w', $cellMargin[0]); + $xmlWriter->writeAttribute('w:type', 'dxa'); + $xmlWriter->endElement(); + } + if ($mLeft) { + $xmlWriter->startElement('w:left'); + $xmlWriter->writeAttribute('w:w', $cellMargin[1]); + $xmlWriter->writeAttribute('w:type', 'dxa'); + $xmlWriter->endElement(); + } + if ($mRight) { + $xmlWriter->startElement('w:right'); + $xmlWriter->writeAttribute('w:w', $cellMargin[2]); + $xmlWriter->writeAttribute('w:type', 'dxa'); + $xmlWriter->endElement(); + } + if ($mBottom) { + $xmlWriter->startElement('w:bottom'); + $xmlWriter->writeAttribute('w:w', $cellMargin[3]); + $xmlWriter->writeAttribute('w:type', 'dxa'); + $xmlWriter->endElement(); + } + $xmlWriter->endElement(); + } + + if ($borders) { + $xmlWriter->startElement('w:tblBorders'); + if ($bTop) { + $xmlWriter->startElement('w:top'); + $xmlWriter->writeAttribute('w:val', 'single'); + $xmlWriter->writeAttribute('w:sz', $brdSz[0]); + $xmlWriter->writeAttribute('w:color', $brdCol[0]); + $xmlWriter->endElement(); + } + if ($bLeft) { + $xmlWriter->startElement('w:left'); + $xmlWriter->writeAttribute('w:val', 'single'); + $xmlWriter->writeAttribute('w:sz', $brdSz[1]); + $xmlWriter->writeAttribute('w:color', $brdCol[1]); + $xmlWriter->endElement(); + } + if ($bRight) { + $xmlWriter->startElement('w:right'); + $xmlWriter->writeAttribute('w:val', 'single'); + $xmlWriter->writeAttribute('w:sz', $brdSz[2]); + $xmlWriter->writeAttribute('w:color', $brdCol[2]); + $xmlWriter->endElement(); + } + if ($bBottom) { + $xmlWriter->startElement('w:bottom'); + $xmlWriter->writeAttribute('w:val', 'single'); + $xmlWriter->writeAttribute('w:sz', $brdSz[3]); + $xmlWriter->writeAttribute('w:color', $brdCol[3]); + $xmlWriter->endElement(); + } + if ($bInsH) { + $xmlWriter->startElement('w:insideH'); + $xmlWriter->writeAttribute('w:val', 'single'); + $xmlWriter->writeAttribute('w:sz', $brdSz[4]); + $xmlWriter->writeAttribute('w:color', $brdCol[4]); + $xmlWriter->endElement(); + } + if ($bInsV) { + $xmlWriter->startElement('w:insideV'); + $xmlWriter->writeAttribute('w:val', 'single'); + $xmlWriter->writeAttribute('w:sz', $brdSz[5]); + $xmlWriter->writeAttribute('w:color', $brdCol[5]); + $xmlWriter->endElement(); + } + $xmlWriter->endElement(); + } + + $xmlWriter->endElement(); + + if (!is_null($bgColor)) { + $xmlWriter->startElement('w:tcPr'); + $xmlWriter->startElement('w:shd'); + $xmlWriter->writeAttribute('w:val', 'clear'); + $xmlWriter->writeAttribute('w:color', 'auto'); + $xmlWriter->writeAttribute('w:fill', $bgColor); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + } + + + // First Row + $firstRow = $style->getFirstRow(); + if (!is_null($firstRow)) { + $this->_writeRowStyle($xmlWriter, 'firstRow', $firstRow); + } + } + + private function _writeRowStyle(XMLWriter $xmlWriter = null, $type, TableFull $style) + { + $brdSz = $style->getBorderSize(); + $brdCol = $style->getBorderColor(); + $bgColor = $style->getBgColor(); + + $bTop = (!is_null($brdSz[0])) ? true : false; + $bLeft = (!is_null($brdSz[1])) ? true : false; + $bRight = (!is_null($brdSz[2])) ? true : false; + $bBottom = (!is_null($brdSz[3])) ? true : false; + $borders = ($bTop || $bLeft || $bRight || $bBottom) ? true : false; + + $xmlWriter->startElement('w:tblStylePr'); + $xmlWriter->writeAttribute('w:type', $type); + + $xmlWriter->startElement('w:tcPr'); + if (!is_null($bgColor)) { + $xmlWriter->startElement('w:shd'); + $xmlWriter->writeAttribute('w:val', 'clear'); + $xmlWriter->writeAttribute('w:color', 'auto'); + $xmlWriter->writeAttribute('w:fill', $bgColor); + $xmlWriter->endElement(); + } + + $xmlWriter->startElement('w:tcBorders'); + if ($bTop) { + $xmlWriter->startElement('w:top'); + $xmlWriter->writeAttribute('w:val', 'single'); + $xmlWriter->writeAttribute('w:sz', $brdSz[0]); + $xmlWriter->writeAttribute('w:color', $brdCol[0]); + $xmlWriter->endElement(); + } + if ($bLeft) { + $xmlWriter->startElement('w:left'); + $xmlWriter->writeAttribute('w:val', 'single'); + $xmlWriter->writeAttribute('w:sz', $brdSz[1]); + $xmlWriter->writeAttribute('w:color', $brdCol[1]); + $xmlWriter->endElement(); + } + if ($bRight) { + $xmlWriter->startElement('w:right'); + $xmlWriter->writeAttribute('w:val', 'single'); + $xmlWriter->writeAttribute('w:sz', $brdSz[2]); + $xmlWriter->writeAttribute('w:color', $brdCol[2]); + $xmlWriter->endElement(); + } + if ($bBottom) { + $xmlWriter->startElement('w:bottom'); + $xmlWriter->writeAttribute('w:val', 'single'); + $xmlWriter->writeAttribute('w:sz', $brdSz[3]); + $xmlWriter->writeAttribute('w:color', $brdCol[3]); + $xmlWriter->endElement(); + } + $xmlWriter->endElement(); + + $xmlWriter->endElement(); + + $xmlWriter->endElement(); + } + + + private function _writeDocDefaults(XMLWriter $xmlWriter = null) + { + $fontName = $this->_document->getDefaultFontName(); + $fontSize = $this->_document->getDefaultFontSize(); + + $xmlWriter->startElement('w:docDefaults'); + $xmlWriter->startElement('w:rPrDefault'); + $xmlWriter->startElement('w:rPr'); + + $xmlWriter->startElement('w:rFonts'); + $xmlWriter->writeAttribute('w:ascii', $fontName); + $xmlWriter->writeAttribute('w:hAnsi', $fontName); + $xmlWriter->writeAttribute('w:eastAsia', $fontName); + $xmlWriter->writeAttribute('w:cs', $fontName); + $xmlWriter->endElement(); + + $xmlWriter->startElement('w:sz'); + $xmlWriter->writeAttribute('w:val', $fontSize * 2); + $xmlWriter->endElement(); + + $xmlWriter->startElement('w:szCs'); + $xmlWriter->writeAttribute('w:val', $fontSize * 2); + $xmlWriter->endElement(); + + $xmlWriter->endElement(); + $xmlWriter->endElement(); + $xmlWriter->endElement(); + } +} diff --git a/src/Writer/Word2007/WriterPart.php b/src/Writer/Word2007/WriterPart.php new file mode 100644 index 00000000..bb8fefc3 --- /dev/null +++ b/src/Writer/Word2007/WriterPart.php @@ -0,0 +1,49 @@ +_parentWriter = $pWriter; + } + + public function getParentWriter() + { + if (!is_null($this->_parentWriter)) { + return $this->_parentWriter; + } else { + throw new Exception("No parent IWriter assigned."); + } + } +} diff --git a/src/_staticDocParts/_doc.png b/src/_staticDocParts/_doc.png new file mode 100644 index 0000000000000000000000000000000000000000..3128a803b4eb829a6eb098e3736366ebfb43cef7 GIT binary patch literal 1157 zcmV;01bX|4P)0{{R3N2#!80000PbVXQnQ*UN; zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUzQ&3D)MgRZ*0002t=Ji~3tGCGXHb!Y? zeY1m{+VJxFdy&6FRe$>X{`>s?{r>+{Y@~07x=L=rNOQ~tHG)iIn>S#t05NwhRIBRl z_y8eM=}aaf{Nayy{$g%gNH>D_Nxe|Nj6SMq`QM_4oXlvF-Hs`~3a>MO=(m zebHZq-6cqOIAXL%cG+c!+caRpt-8>Qq}@YlxrwFeQFh7zC0adWzw-3@6+2aCiq(6U z*cLo)c8Z+V-0DANw4k@}J5qNCJBTk)k0wisIcT_&qqQhfpZNLxF#dt- z_uX#SR(tRN|I)^<+{jmyZq)XA`T5O~lY>H!qAd!i^Y)K@VAX7ctD^`7k~{HkL|E zAcb-R(47;o6|y+{sa3R45JD71HAGR@7vpf|$v;_R?$z8jK%$t8Ml}-0yi}1Q1F|SK z>Z~0Q98y&Cl7CKr6~(_~;5#16{y257P9lZUBVG(^>rst~(_T%ivv^?lCYIT4yT77^ z)ChzyJzC`31&XQ%S!RV-Lf38D9_VwF;tOQ)LP?kSQAWz_(zH8`7OM2129Hy^qE>1t zp4+>Q)8P#jEhHPzBAFC z$Yh$WTgOFYr;tLvG7i5N_^adN!t%;?=Im@Oe(SghA7bbT?|%RImsdW~ba9tV${^%My7w!<$0EU(Az z^f?eP@4dSVdY3S_00XAk8zV43K27RFz3TvAz70U;N&WN8ohL$rgS!8>vW(~d29G>vf?KbCZ<^iBfdBg+S#J!O^9loZ)5&~}hRr$*06U-Xms&}joSa@!{{$ES XtjuZObd?ae00000NkvXXu0mjf9*{Wp literal 0 HcmV?d00001 diff --git a/src/_staticDocParts/_ppt.png b/src/_staticDocParts/_ppt.png new file mode 100644 index 0000000000000000000000000000000000000000..3e925f50199cf96e881dee05455b410fcc282731 GIT binary patch literal 1886 zcmV-k2ch_hP)0{{R3N2#!80000PbVXQnQ*UN; zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU#08mU+MgHT}{J4`=3l5Y_PyNxl|M>L& z>*4*!s;emi|Mc&CLQc?fRsZbb{J)<5-p=8CT>QYHHw6p-`uOdVZSI#@{@cm__VezG zROXUu|K{0_NlpLgx#W&%(_<;@mTfg0dJ4Of%qf{&CtBn2Az3Gi<++`{M z@8$pg{n&6(xit#IJ`S!*HfRwK>6LD)MKZ!+NXteO_MdtG_3-`6v63|{{JWURYEJ+E z|C~@yg+@-gRzT&1V*SLX{lcWydRzYK-~Z#&?PVta`S$(Hv;Xqz|Lx?(WlQ0SX5)ch z%49h1gh&77*#G0y{@23&*24YNzHSu}f<#T}i)Ztib@G^V!CpnYTSM-VN&VHq?t@d_ zhGW@(UEX?FkvTHfZcof_QqyNic|uV1oOiNPG~9Mp)oV@ZVI$sG9@tVF&q)=&It(oY z3$-!_u`UH*4h;YR0RQ~@|Nj24UPJ%!>i_of|K-=AMl$`+xBukU|LNWT|Nj5{``KzP z|LEMaPB{OsasTMHyj&^KWk>ppOXPGr{FGAYr-uIF((r97uSPiMoOjG&DdTN0w^Tm= z)S~~`rsaG_|K_stbTapTKIf!@^LaPtpnU(xlmE_}sZ}ekSS$ajXyt)V|Dj>!k7NJ+ z{Qtaz{h3+oVkG96aKUq0|K6(jg+>3vi{*t?<%(SYw|V~L*5hd{|K--?a5db5VB~l~ z{m!-jsB(`icXt#Q<8O7fe0 z>4|RQfMn!@Vg1dtfJ9FI=-vM5-7>lgfdBvl^hrcPRCwBA@TL=B7`15BqEU;6n?-Ur zPg#0w=i)_cR`1@jZ}R$$TW3z+ zwS48WIiZ?Vw#e1BEImU*SlA-%mH%&k{(_3$LkkWlsH&b(NujPq$I@G^&A`mo53HP5*tFh>CbB4~T2b4g=$#qL*0aD& zYauap#o+yXO3B>{R}_7YJ5bf4yv1^xH?Q#4(K&bT?wubR*MENg#eedTrB$R)HFYgI zyhymeWtI0MV3xfd^yC&W!vgcGyJaMg;R)(ml)naO(L4~VKg=y6@;?KglKD|RSspgS znkK4R6tvpn#ii|_7`nvDsmi7`TQrHqon4m4h*`U-m6{ek*`0PtNW$BjrLC~=u_q)c z=&{c?GGeZ!u8+94yb{vip88wupG#HOANGfAj))J=aOb`_@s{qO6(E-P~p75+g=g#dw5jHU;B{x(q8qJ_JPo~bWrftCu1 z;H2QmXxh`m)gVY!i;S07s<$6dP*AY6l$D)tU@%o)e%)GA(}V=BM(SELY328bc2!j? z#Yi4DBctAl=OraO5B4M^gp@W4_EFO!`(-8Vs#g>hd4Trxg6xU!>;%~pQp!Ohscg!!W`DC<4e9 z!9|f&BKfGfxf$6XP>7@$jfpCU;v<~$49GExZc#HvSQ2j$LN5^(VZ=0PKJq4D5jt-6 z#ui83-q_qiAdb8-a|3D`!VNvsF={;)Es6|8EB7gt` Y0LsdDm^Yzu*8l(j07*qoM6N<$f~$WKuK)l5 literal 0 HcmV?d00001 diff --git a/src/_staticDocParts/_xls.png b/src/_staticDocParts/_xls.png new file mode 100644 index 0000000000000000000000000000000000000000..a7d7697fc5666629b9d8bb3090339c5f557536b5 GIT binary patch literal 1924 zcmV-~2YdL5P)0{{R3N2#!80000PbVXQnQ*UN; zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU#08mU+MKVMjJ8dS}_T8hyou0{*wA87C zmvPhL)a~~1NrWgzm_<~EN>Exj*6P;k^5g?(0%wzE$L6|btYq}{@H&V*R)JDem^j_+ z;>+g3+2z`es)5Pf!teX;s?(l1cNJY^MNEetb|F z_5Ar)lT>TAX7ly=6eI}5-n?LlN-8xJ@Ksom<`OJX!7Iw5nmXINZ8)#lgP=-T-H z_fm^EUusEIeL9cJfqS}c&f3#-onmB;QswdHe5GrFyn9TKLm_Ygc$Zv6j3xT{`dgzx z;O*m`(U@PDSx1sKc(!zQvvlh6>Iz~6PMKF?s#O2~`;w@1e7bvKqEmjTX;z;-=k4a& z?b+$--CLwo|N8!Ro@n~~`IEVge6er&`t^IJaay2A=JD!;vT}&5f>o(hcD7nJZy3+& z&incPkj05>m01d66;+~A_WbpAy=rooZu9!^aGPIMrcG?9V|KD^<>%t!=iGXtWI=r* z+Uebp!i8g+UrTU2ZM0tg{``WidE)Qh|NsALY*rsA4BP3`Rbf2m^Y8lq{NL^0BrFsz zK_+IZUg7fMXp&Vrf*=+h3?(%XH%=e`007+T+u`r#=kMd?_T%mE>WjU8fV_6~{qXMc z=|E;C$l=An>%iCV*Uje0&g;L}?cCq&+TP~k{rdIh_~LT9Wa<6v8z2+Z-`8QGTl)0( zZK6;O+D8ZtY>$yY?;iD|Nj42rdl6+k>n z^yc*EnZuFR=H>nU|IzHp{Qv)dlxP3_|9Ze^ki3Ea{QWLJ81wk}?EUrj_w;3;C`$@AU0!xN!LV?n)1(VE_OG8c9S!RCwBAm`NwVFly1LMWYtc$)al+ z8QJI0_xEQ9^%n(ob~XhEFV)xAH`V9%^HcgmO^c@Q-1$ag>kd6VJ!4kZ$FeLeFF&f8 z1eA8)?oL}tRUcJbT(z_;DRFePoGx{>TI$jzYwMHNZ133EBA-yzqPONh9n)W@f0~wF zmj1M(qxf5yy71;3!khUvYh+Q^N9Gcz?#}%4cK(m~#hRL5bacLa;V?^n@q5Wy(->-7 z%j~;YnH-Y*OzAsyEh?8NF`It7XYsB0$u~P>4(PQDOb)iS zwPniH$XR)pnihrXo%T)=eC*Wd6eb|~El^;8z()6bqAAZbmPtiiLyWo>1+iBDpRe5DkAjF zzC2$lThz%~?H&E?fbtzKJ*UOpLRq5C(kg~)d&R}&eLhpwq9)dAow7~eWa{sS8><~l zyLWGjvyo9R@Aiqa6bz_q(c|jYXpZPTT3!6%vKw2vx@uCU*ama&dF30mg1Q#PN$r*4 zP`2PINJ(JLY_aJ|OPL}XY`ZH@p2|L2dgr+CS7qMR(y0afTya$u_qba46(*eF<@Jp+ zplUu^>U3O3XAaj?lK`O>{)D*O4i4c7&34R^_Otw`>!aYt<6p#6-7_GGt9`?2H92t5>h~^78a# zx3@Utae=x%@~eHfe*OB~+}yQm7r3}g^zxFFWcOmXueS$UL`@&1o4U8Z;CnO!2zKY? z@q&RTyQk_7Rr$K*RP~W*caf5kk_Hg@LV$;dhrEZ!TzQ@?)V0X(=(!jm$jK2C6Z26} zP~ha8FhLFo>gpn>YmvrEFkk?I&ju?%VD@a?g$H$kkeU_&n~rbMh5mqvKSVb1M>}Gp z7L8g&GmBP%0ah7=3MB3-9I6OggwtI}Ca=P+kW`DHMnN6F3SlywTs0Fe3iIPCIFke) zt%4W^MKB84A}sQ&NbwOgj#i + \ No newline at end of file diff --git a/src/_staticDocParts/numbering.xml b/src/_staticDocParts/numbering.xml new file mode 100644 index 00000000..ac229f40 --- /dev/null +++ b/src/_staticDocParts/numbering.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/src/_staticDocParts/settings.xml b/src/_staticDocParts/settings.xml new file mode 100644 index 00000000..5eb22891 --- /dev/null +++ b/src/_staticDocParts/settings.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/_staticDocParts/theme1.xml b/src/_staticDocParts/theme1.xml new file mode 100644 index 00000000..4fab507b --- /dev/null +++ b/src/_staticDocParts/theme1.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/src/_staticDocParts/webSettings.xml b/src/_staticDocParts/webSettings.xml new file mode 100644 index 00000000..72d28307 --- /dev/null +++ b/src/_staticDocParts/webSettings.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file