From 7a42802b4882cfe9ecda44b2b0131bb11059c641 Mon Sep 17 00:00:00 2001 From: Ivan Lanin Date: Thu, 29 May 2014 17:37:26 +0700 Subject: [PATCH] RTF reader: Unit tests and some improvements --- CHANGELOG.md | 3 +- docs/intro.rst | 2 +- docs/src/documentation.md | 2 +- ...e_27_ReadRTF.php => Sample_28_ReadRTF.php} | 0 ...e_27_ReadRTF.rtf => Sample_28_ReadRTF.rtf} | 0 src/PhpWord/Reader/RTF/Document.php | 70 +++++++++++-------- tests/PhpWord/Tests/Reader/ODTextTest.php | 4 +- tests/PhpWord/Tests/Reader/RTFTest.php | 51 ++++++++++++++ tests/PhpWord/Tests/Reader/Word2007Test.php | 33 ++------- .../PhpWord/Tests/_files/documents/reader.rtf | 21 ++++++ 10 files changed, 126 insertions(+), 60 deletions(-) rename samples/{Sample_27_ReadRTF.php => Sample_28_ReadRTF.php} (100%) rename samples/resources/{Sample_27_ReadRTF.rtf => Sample_28_ReadRTF.rtf} (100%) create mode 100644 tests/PhpWord/Tests/Reader/RTFTest.php create mode 100644 tests/PhpWord/Tests/_files/documents/reader.rtf diff --git a/CHANGELOG.md b/CHANGELOG.md index 4584c4a4..0ccba8cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ This is the changelog between releases of PHPWord. Releases are listed in revers ## 0.11.0 - Not yet released -This release marked the change of PHPWord license from LGPL 2.1 to LGPL 3. Three new elements were added: TextBox, ListItemRun, and Field. Relative and absolute positioning for images and textboxes were added. Writer classes were refactored into parts, elements, and styles. ODT and RTF features were enhanced. Ability to add elements to PHPWord object via HTML were implemeted. +This release marked the change of PHPWord license from LGPL 2.1 to LGPL 3. Three new elements were added: TextBox, ListItemRun, and Field. Relative and absolute positioning for images and textboxes were added. Writer classes were refactored into parts, elements, and styles. ODT and RTF features were enhanced. Ability to add elements to PHPWord object via HTML were implemeted. RTF reader were initiated. ### Features @@ -30,6 +30,7 @@ This release marked the change of PHPWord license from LGPL 2.1 to LGPL 3. Three - RTF Writer: Ability to write document properties - @ivanlanin - RTF Writer: Ability to write image - @ivanlanin - Element: New `Field` element - @basjan GH-251 +- RTF Reader: Basic RTF reader - @ivanlanin GH-72 ### Bugfixes diff --git a/docs/intro.rst b/docs/intro.rst index a64fb2ad..3da729e8 100644 --- a/docs/intro.rst +++ b/docs/intro.rst @@ -124,7 +124,7 @@ Readers +---------------------------+----------------------+--------+-------+-------+ | | Custom | ✓ | | | +---------------------------+----------------------+--------+-------+-------+ -| **Element Type** | Text | ✓ | ✓ | | +| **Element Type** | Text | ✓ | ✓ | ✓ | +---------------------------+----------------------+--------+-------+-------+ | | Text Run | ✓ | | | +---------------------------+----------------------+--------+-------+-------+ diff --git a/docs/src/documentation.md b/docs/src/documentation.md index 889842f9..0f4d085b 100644 --- a/docs/src/documentation.md +++ b/docs/src/documentation.md @@ -114,7 +114,7 @@ Below are the supported features for each file formats. |-------------------------|--------------------|------|-----|-----| | **Document Properties** | Standard | ✓ | | | | | Custom | ✓ | | | -| **Element Type** | Text | ✓ | ✓ | | +| **Element Type** | Text | ✓ | ✓ | ✓ | | | Text Run | ✓ | | | | | Title | ✓ | ✓ | | | | Link | ✓ | | | diff --git a/samples/Sample_27_ReadRTF.php b/samples/Sample_28_ReadRTF.php similarity index 100% rename from samples/Sample_27_ReadRTF.php rename to samples/Sample_28_ReadRTF.php diff --git a/samples/resources/Sample_27_ReadRTF.rtf b/samples/resources/Sample_28_ReadRTF.rtf similarity index 100% rename from samples/resources/Sample_27_ReadRTF.rtf rename to samples/resources/Sample_28_ReadRTF.rtf diff --git a/src/PhpWord/Reader/RTF/Document.php b/src/PhpWord/Reader/RTF/Document.php index 84e9c1ed..cb082fdc 100644 --- a/src/PhpWord/Reader/RTF/Document.php +++ b/src/PhpWord/Reader/RTF/Document.php @@ -245,8 +245,8 @@ class Document private function flushControl($isControl = false) { if (preg_match("/^([A-Za-z]+)(-?[0-9]*) ?$/", $this->control, $match) === 1) { - list(, $control) = $match; - $this->parseControl($control); + list(, $control, $parameter) = $match; + $this->parseControl($control, $parameter); } if ($isControl === true) { @@ -271,8 +271,7 @@ class Document // Add text if it's not flagged as skipped if (!isset($this->flags['skipped'])) { - $textrun = $this->textrun->addText($this->text); - $this->flags['element'] = &$textrun; + $this->readText(); } $this->text = ''; @@ -312,30 +311,36 @@ class Document * @param string $control * @param string $parameter */ - private function parseControl($control) + private function parseControl($control, $parameter) { $controls = array( - 'par' => array(self::PARA, 'paragraph', true), - 'b' => array(self::STYL, 'bold', true), - 'i' => array(self::STYL, 'italic', true), - 'u' => array(self::STYL, 'underline', true), - 'fonttbl' => array(self::SKIP, 'fonttbl', null), - 'colortbl' => array(self::SKIP, 'colortbl', null), - 'info' => array(self::SKIP, 'info', null), - 'generator' => array(self::SKIP, 'generator', null), - 'title' => array(self::SKIP, 'title', null), - 'subject' => array(self::SKIP, 'subject', null), - 'category' => array(self::SKIP, 'category', null), - 'keywords' => array(self::SKIP, 'keywords', null), - 'comment' => array(self::SKIP, 'comment', null), - 'shppict' => array(self::SKIP, 'pic', null), - 'fldinst' => array(self::SKIP, 'link', null), + 'par' => array(self::PARA, 'paragraph', true), + 'b' => array(self::STYL, 'font', 'bold', true), + 'i' => array(self::STYL, 'font', 'italic', true), + 'u' => array(self::STYL, 'font', 'underline', true), + 'strike' => array(self::STYL, 'font', 'strikethrough',true), + 'fs' => array(self::STYL, 'font', 'size', $parameter), + 'qc' => array(self::STYL, 'paragraph', 'align', 'center'), + 'sa' => array(self::STYL, 'paragraph', 'spaceAfter', $parameter), + 'fonttbl' => array(self::SKIP, 'fonttbl', null), + 'colortbl' => array(self::SKIP, 'colortbl', null), + 'info' => array(self::SKIP, 'info', null), + 'generator' => array(self::SKIP, 'generator', null), + 'title' => array(self::SKIP, 'title', null), + 'subject' => array(self::SKIP, 'subject', null), + 'category' => array(self::SKIP, 'category', null), + 'keywords' => array(self::SKIP, 'keywords', null), + 'comment' => array(self::SKIP, 'comment', null), + 'shppict' => array(self::SKIP, 'pic', null), + 'fldinst' => array(self::SKIP, 'link', null), ); if (array_key_exists($control, $controls)) { list($function) = $controls[$control]; if (method_exists($this, $function)) { - $this->$function($controls[$control]); + $directives = $controls[$control]; + array_shift($directives); // remove the function variable; we won't need it + $this->$function($directives); } } } @@ -347,7 +352,7 @@ class Document */ private function readParagraph($directives) { - list(, $property, $value) = $directives; + list($property, $value) = $directives; $this->textrun = $this->section->addTextRun(); $this->flags[$property] = $value; } @@ -359,12 +364,8 @@ class Document */ private function readStyle($directives) { - list(, $property, $value) = $directives; - $this->flags[$property] = $value; - if (isset($this->flags['element'])) { - $element = &$this->flags['element']; - $element->getFontStyle()->setStyleValue($property, $value); - } + list($style, $property, $value) = $directives; + $this->flags['styles'][$style][$property] = $value; } /** @@ -374,8 +375,19 @@ class Document */ private function readSkip($directives) { - list(, $property) = $directives; + list($property) = $directives; $this->flags['property'] = $property; $this->flags['skipped'] = true; } + + /** + * Read text + */ + private function readText() + { + $text = $this->textrun->addText($this->text); + if (isset($this->flags['styles']['font'])) { + $text->getFontStyle()->setStyleByArray($this->flags['styles']['font']); + } + } } diff --git a/tests/PhpWord/Tests/Reader/ODTextTest.php b/tests/PhpWord/Tests/Reader/ODTextTest.php index 4120c11e..fc4d2e33 100644 --- a/tests/PhpWord/Tests/Reader/ODTextTest.php +++ b/tests/PhpWord/Tests/Reader/ODTextTest.php @@ -33,7 +33,7 @@ class ODTextTest extends \PHPUnit_Framework_TestCase public function testLoad() { $filename = __DIR__ . '/../_files/documents/reader.odt'; - $object = IOFactory::load($filename, 'ODText'); - $this->assertInstanceOf('PhpOffice\\PhpWord\\PhpWord', $object); + $phpWord = IOFactory::load($filename, 'ODText'); + $this->assertInstanceOf('PhpOffice\\PhpWord\\PhpWord', $phpWord); } } diff --git a/tests/PhpWord/Tests/Reader/RTFTest.php b/tests/PhpWord/Tests/Reader/RTFTest.php new file mode 100644 index 00000000..c495db68 --- /dev/null +++ b/tests/PhpWord/Tests/Reader/RTFTest.php @@ -0,0 +1,51 @@ +assertInstanceOf('PhpOffice\\PhpWord\\PhpWord', $phpWord); + } + + /** + * Test load exception + * + * @expectedException \Exception + * @expectedExceptionMessage Cannot read + */ + public function testLoadException() + { + $filename = __DIR__ . '/../_files/documents/foo.rtf'; + IOFactory::load($filename, 'RTF'); + } +} diff --git a/tests/PhpWord/Tests/Reader/Word2007Test.php b/tests/PhpWord/Tests/Reader/Word2007Test.php index 58890c9a..f2257012 100644 --- a/tests/PhpWord/Tests/Reader/Word2007Test.php +++ b/tests/PhpWord/Tests/Reader/Word2007Test.php @@ -28,40 +28,24 @@ use PhpOffice\PhpWord\Reader\Word2007; */ class Word2007Test extends \PHPUnit_Framework_TestCase { - /** - * Init - */ - public function tearDown() - { - } - /** * Test canRead() method */ public function testCanRead() { $object = new Word2007(); - $fqFilename = join( - DIRECTORY_SEPARATOR, - array(PHPWORD_TESTS_BASE_DIR, 'PhpWord', 'Tests', '_files', 'documents', 'reader.docx') - ); - $this->assertTrue($object->canRead($fqFilename)); + $filename = __DIR__ . '/../_files/documents/reader.docx'; + $this->assertTrue($object->canRead($filename)); } /** * Can read exception - * - * @expectedException \PhpOffice\PhpWord\Exception\Exception */ public function testCanReadFailed() { $object = new Word2007(); - $fqFilename = join( - DIRECTORY_SEPARATOR, - array(PHPWORD_TESTS_BASE_DIR, 'PhpWord', 'Tests', '_files', 'documents', 'foo.docx') - ); - $this->assertFalse($object->canRead($fqFilename)); - $object = IOFactory::load($fqFilename); + $filename = __DIR__ . '/../_files/documents/foo.docx'; + $this->assertFalse($object->canRead($filename)); } /** @@ -69,11 +53,8 @@ class Word2007Test extends \PHPUnit_Framework_TestCase */ public function testLoad() { - $fqFilename = join( - DIRECTORY_SEPARATOR, - array(PHPWORD_TESTS_BASE_DIR, 'PhpWord', 'Tests', '_files', 'documents', 'reader.docx') - ); - $object = IOFactory::load($fqFilename); - $this->assertInstanceOf('PhpOffice\\PhpWord\\PhpWord', $object); + $filename = __DIR__ . '/../_files/documents/reader.docx'; + $phpWord = IOFactory::load($filename); + $this->assertInstanceOf('PhpOffice\\PhpWord\\PhpWord', $phpWord); } } diff --git a/tests/PhpWord/Tests/_files/documents/reader.rtf b/tests/PhpWord/Tests/_files/documents/reader.rtf new file mode 100644 index 00000000..400f43a5 --- /dev/null +++ b/tests/PhpWord/Tests/_files/documents/reader.rtf @@ -0,0 +1,21 @@ +{\rtf1 +\ansi\ansicpg1252 +\deff0 +{\fonttbl{\f0\fnil\fcharset0 Arial;}{\f1\fnil\fcharset0 Times New Roman;}} +{\colortbl;\red255\green0\blue0;\red14\green0\blue0} +{\*\generator PhpWord;} + +{\info{\title }{\subject }{\category }{\keywords }{\comment }{\author }{\operator }{\creatim \yr2014\mo05\dy27\hr23\min36\sec45}{\revtim \yr2014\mo05\dy27\hr23\min36\sec45}{\company }{\manager }} +\deftab720\viewkind1\uc1\pard\nowidctlpar\lang1036\kerning1\fs20 +{Welcome to PhpWord}\par +\pard\nowidctlpar{\cf0\f0 Hello World!}\par +\par +\par +\pard\nowidctlpar{\cf0\f0\fs32\b\i I am styled by a definition.}\par +\pard\nowidctlpar{\cf0\f0 I am styled by a paragraph style definition.}\par +\pard\nowidctlpar\qc\sa100{\cf0\f0\fs32\b\i I am styled by both font and paragraph style.}\par +\pard\nowidctlpar{\cf1\f1\fs40\b\i\ul\strike\super I am inline styled.}\par +\par +{\field {\*\fldinst {HYPERLINK "http://www.google.com"}}{\fldrslt {Google}}}\par +\par +} \ No newline at end of file