Skip to content

Commit 2be4cbf

Browse files
committed
Refactor: Apply composite design pattern to RTF writer
1 parent 559a798 commit 2be4cbf

File tree

6 files changed

+378
-229
lines changed

6 files changed

+378
-229
lines changed

src/PhpWord/Writer/RTF.php

Lines changed: 86 additions & 229 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,11 @@
1010
namespace PhpOffice\PhpWord\Writer;
1111

1212
use PhpOffice\PhpWord\PhpWord;
13-
use PhpOffice\PhpWord\TOC;
14-
use PhpOffice\PhpWord\Element\Image;
15-
use PhpOffice\PhpWord\Element\Link;
16-
use PhpOffice\PhpWord\Element\ListItem;
17-
use PhpOffice\PhpWord\Element\Object;
18-
use PhpOffice\PhpWord\Element\PageBreak;
19-
use PhpOffice\PhpWord\Element\Table;
20-
use PhpOffice\PhpWord\Element\Text;
21-
use PhpOffice\PhpWord\Element\TextBreak;
22-
use PhpOffice\PhpWord\Element\TextRun;
23-
use PhpOffice\PhpWord\Element\Title;
2413
use PhpOffice\PhpWord\Exception\Exception;
2514
use PhpOffice\PhpWord\Shared\Drawing;
2615
use PhpOffice\PhpWord\Style;
2716
use PhpOffice\PhpWord\Style\Font;
17+
use PhpOffice\PhpWord\Writer\RTF\Element\Element as ElementWriter;
2818

2919
/**
3020
* RTF writer
@@ -77,7 +67,7 @@ public function save($pFilename = null)
7767

7868
$hFile = fopen($pFilename, 'w');
7969
if ($hFile !== false) {
80-
fwrite($hFile, $this->getData());
70+
fwrite($hFile, $this->writeDocument());
8171
fclose($hFile);
8272
} else {
8373
throw new Exception("Can't open file");
@@ -88,64 +78,123 @@ public function save($pFilename = null)
8878
}
8979
}
9080

81+
/**
82+
* Get color table
83+
*
84+
* @param mixed $value
85+
*/
86+
public function getColorTable()
87+
{
88+
return $this->colorTable;
89+
}
90+
91+
/**
92+
* Get font table
93+
*
94+
* @param mixed $value
95+
*/
96+
public function getFontTable()
97+
{
98+
return $this->fontTable;
99+
}
100+
101+
/**
102+
* Set last paragraph style
103+
*
104+
* @param mixed $value
105+
*/
106+
public function setLastParagraphStyle($value = '')
107+
{
108+
$this->lastParagraphStyle = $value;
109+
}
110+
111+
/**
112+
* Get last paragraph style
113+
*
114+
* @param mixed $value
115+
*/
116+
public function getLastParagraphStyle()
117+
{
118+
return $this->lastParagraphStyle;
119+
}
120+
91121
/**
92122
* Get all data
93123
*
94124
* @return string
95125
*/
96-
private function getData()
126+
private function writeDocument()
97127
{
98-
// PhpWord object : $this->phpWord
99128
$this->fontTable = $this->getDataFont();
100129
$this->colorTable = $this->getDataColor();
101130

102-
$sRTFContent = '{\rtf1';
103131
// Set the default character set
104-
$sRTFContent .= '\ansi\ansicpg1252';
105-
// Set the default font (the first one)
106-
$sRTFContent .= '\deff0';
107-
// Set the default tab size (720 twips)
132+
$sRTFContent = '{\rtf1';
133+
$sRTFContent .= '\ansi\ansicpg1252'; // Set the default font (the first one)
134+
$sRTFContent .= '\deff0'; // Set the default tab size (720 twips)
108135
$sRTFContent .= '\deftab720';
109136
$sRTFContent .= PHP_EOL;
137+
110138
// Set the font tbl group
111139
$sRTFContent .= '{\fonttbl';
112140
foreach ($this->fontTable as $idx => $font) {
113141
$sRTFContent .= '{\f' . $idx . '\fnil\fcharset0 ' . $font . ';}';
114142
}
115143
$sRTFContent .= '}' . PHP_EOL;
144+
116145
// Set the color tbl group
117146
$sRTFContent .= '{\colortbl ';
118147
foreach ($this->colorTable as $idx => $color) {
119148
$arrColor = Drawing::htmlToRGB($color);
120149
$sRTFContent .= ';\red' . $arrColor[0] . '\green' . $arrColor[1] . '\blue' . $arrColor[2] . '';
121150
}
122151
$sRTFContent .= ';}' . PHP_EOL;
123-
// Set the generator
124-
$sRTFContent .= '{\*\generator PhpWord;}' . PHP_EOL;
125-
// Set the view mode of the document
126-
$sRTFContent .= '\viewkind4';
127-
// Set the numberof bytes that follows a unicode character
128-
$sRTFContent .= '\uc1';
129-
// Resets to default paragraph properties.
130-
$sRTFContent .= '\pard';
131-
// No widow/orphan control
132-
$sRTFContent .= '\nowidctlpar';
133-
// Applies a language to a text run (1036 : French (France))
134-
$sRTFContent .= '\lang1036';
135-
// Point size (in half-points) above which to kern character pairs
136-
$sRTFContent .= '\kerning1';
137-
// Set the font size in half-points
138-
$sRTFContent .= '\fs' . (PhpWord::DEFAULT_FONT_SIZE * 2);
152+
153+
$sRTFContent .= '{\*\generator PhpWord;}' . PHP_EOL; // Set the generator
154+
$sRTFContent .= '\viewkind4'; // Set the view mode of the document
155+
$sRTFContent .= '\uc1'; // Set the numberof bytes that follows a unicode character
156+
$sRTFContent .= '\pard'; // Resets to default paragraph properties.
157+
$sRTFContent .= '\nowidctlpar'; // No widow/orphan control
158+
$sRTFContent .= '\lang1036'; // Applies a language to a text run (1036 : French (France))
159+
$sRTFContent .= '\kerning1'; // Point size (in half-points) above which to kern character pairs
160+
$sRTFContent .= '\fs' . (PhpWord::DEFAULT_FONT_SIZE * 2); // Set the font size in half-points
139161
$sRTFContent .= PHP_EOL;
140-
// Body
141-
$sRTFContent .= $this->getDataContent();
142162

163+
// Body
164+
$sRTFContent .= $this->writeContent();
143165

144166
$sRTFContent .= '}';
145167

146168
return $sRTFContent;
147169
}
148170

171+
/**
172+
* Get content data
173+
*
174+
* @return string
175+
*/
176+
private function writeContent()
177+
{
178+
$phpWord = $this->phpWord;
179+
$sRTFBody = '';
180+
181+
$sections = $phpWord->getSections();
182+
$countSections = count($sections);
183+
$pSection = 0;
184+
185+
if ($countSections > 0) {
186+
foreach ($sections as $section) {
187+
$pSection++;
188+
$elements = $section->getElements();
189+
foreach ($elements as $element) {
190+
$elementWriter = new ElementWriter($this, $element);
191+
$sRTFBody .= $elementWriter->write();
192+
}
193+
}
194+
}
195+
return $sRTFBody;
196+
}
197+
149198
/**
150199
* Get all fonts
151200
*
@@ -259,196 +308,4 @@ private function getDataColor()
259308

260309
return $arrColors;
261310
}
262-
263-
/**
264-
* Get content data
265-
*
266-
* @return string
267-
*/
268-
private function getDataContent()
269-
{
270-
$phpWord = $this->phpWord;
271-
$sRTFBody = '';
272-
273-
$sections = $phpWord->getSections();
274-
$countSections = count($sections);
275-
$pSection = 0;
276-
277-
if ($countSections > 0) {
278-
foreach ($sections as $section) {
279-
$pSection++;
280-
$elements = $section->getElements();
281-
foreach ($elements as $element) {
282-
if ($element instanceof Text) {
283-
$sRTFBody .= $this->getDataContentText($element);
284-
} elseif ($element instanceof TextBreak) {
285-
$sRTFBody .= $this->getDataContentTextBreak();
286-
} elseif ($element instanceof TextRun) {
287-
$sRTFBody .= $this->getDataContentTextRun($element);
288-
} elseif ($element instanceof Link) {
289-
$sRTFBody .= $this->getDataContentUnsupportedElement('Link');
290-
} elseif ($element instanceof Title) {
291-
$sRTFBody .= $this->getDataContentUnsupportedElement('Title');
292-
} elseif ($element instanceof PageBreak) {
293-
$sRTFBody .= $this->getDataContentUnsupportedElement('Page Break');
294-
} elseif ($element instanceof Table) {
295-
$sRTFBody .= $this->getDataContentUnsupportedElement('Table');
296-
} elseif ($element instanceof ListItem) {
297-
$sRTFBody .= $this->getDataContentUnsupportedElement('List Item');
298-
} elseif ($element instanceof Image) {
299-
$sRTFBody .= $this->getDataContentUnsupportedElement('Image');
300-
} elseif ($element instanceof Object) {
301-
$sRTFBody .= $this->getDataContentUnsupportedElement('Object');
302-
} elseif ($element instanceof TOC) {
303-
$sRTFBody .= $this->getDataContentUnsupportedElement('TOC');
304-
} else {
305-
$sRTFBody .= $this->getDataContentUnsupportedElement('Other');
306-
}
307-
}
308-
}
309-
}
310-
return $sRTFBody;
311-
}
312-
313-
/**
314-
* Get text element content
315-
*
316-
* @param boolean $withoutP
317-
* @return string
318-
*/
319-
private function getDataContentText(Text $text, $withoutP = false)
320-
{
321-
$sRTFText = '';
322-
323-
$styleFont = $text->getFontStyle();
324-
if (is_string($styleFont)) {
325-
$styleFont = Style::getStyle($styleFont);
326-
}
327-
328-
$styleParagraph = $text->getParagraphStyle();
329-
if (is_string($styleParagraph)) {
330-
$styleParagraph = Style::getStyle($styleParagraph);
331-
}
332-
333-
if ($styleParagraph && !$withoutP) {
334-
if ($this->lastParagraphStyle != $text->getParagraphStyle()) {
335-
$sRTFText .= '\pard\nowidctlpar';
336-
if ($styleParagraph->getSpaceAfter() != null) {
337-
$sRTFText .= '\sa' . $styleParagraph->getSpaceAfter();
338-
}
339-
if ($styleParagraph->getAlign() != null) {
340-
if ($styleParagraph->getAlign() == 'center') {
341-
$sRTFText .= '\qc';
342-
}
343-
}
344-
$this->lastParagraphStyle = $text->getParagraphStyle();
345-
} else {
346-
$this->lastParagraphStyle = '';
347-
}
348-
} else {
349-
$this->lastParagraphStyle = '';
350-
}
351-
352-
if ($styleFont instanceof Font) {
353-
if ($styleFont->getColor() != null) {
354-
$idxColor = array_search($styleFont->getColor(), $this->colorTable);
355-
if ($idxColor !== false) {
356-
$sRTFText .= '\cf' . ($idxColor + 1);
357-
}
358-
} else {
359-
$sRTFText .= '\cf0';
360-
}
361-
if ($styleFont->getName() != null) {
362-
$idxFont = array_search($styleFont->getName(), $this->fontTable);
363-
if ($idxFont !== false) {
364-
$sRTFText .= '\f' . $idxFont;
365-
}
366-
} else {
367-
$sRTFText .= '\f0';
368-
}
369-
if ($styleFont->getBold()) {
370-
$sRTFText .= '\b';
371-
}
372-
if ($styleFont->getItalic()) {
373-
$sRTFText .= '\i';
374-
}
375-
if ($styleFont->getSize()) {
376-
$sRTFText .= '\fs' . ($styleFont->getSize() * 2);
377-
}
378-
}
379-
if ($this->lastParagraphStyle != '' || $styleFont) {
380-
$sRTFText .= ' ';
381-
}
382-
$sRTFText .= $text->getText();
383-
384-
if ($styleFont instanceof Font) {
385-
$sRTFText .= '\cf0';
386-
$sRTFText .= '\f0';
387-
388-
if ($styleFont->getBold()) {
389-
$sRTFText .= '\b0';
390-
}
391-
if ($styleFont->getItalic()) {
392-
$sRTFText .= '\i0';
393-
}
394-
if ($styleFont->getSize()) {
395-
$sRTFText .= '\fs' . (PhpWord::DEFAULT_FONT_SIZE * 2);
396-
}
397-
}
398-
399-
if (!$withoutP) {
400-
$sRTFText .= '\par' . PHP_EOL;
401-
}
402-
return $sRTFText;
403-
}
404-
405-
/**
406-
* Get textrun content
407-
*
408-
* @return string
409-
*/
410-
private function getDataContentTextRun(TextRun $textrun)
411-
{
412-
$sRTFText = '';
413-
$elements = $textrun->getElements();
414-
if (count($elements) > 0) {
415-
$sRTFText .= '\pard\nowidctlpar' . PHP_EOL;
416-
foreach ($elements as $element) {
417-
if ($element instanceof Text) {
418-
$sRTFText .= '{';
419-
$sRTFText .= $this->getDataContentText($element, true);
420-
$sRTFText .= '}' . PHP_EOL;
421-
}
422-
}
423-
$sRTFText .= '\par' . PHP_EOL;
424-
}
425-
return $sRTFText;
426-
}
427-
428-
/**
429-
* Get text break content
430-
*
431-
* @return string
432-
*/
433-
private function getDataContentTextBreak()
434-
{
435-
$this->lastParagraphStyle = '';
436-
437-
return '\par' . PHP_EOL;
438-
}
439-
440-
/**
441-
* Get unsupported element content
442-
*
443-
* @param string $element
444-
*/
445-
private function getDataContentUnsupportedElement($element)
446-
{
447-
$sRTFText = '';
448-
$sRTFText .= '\pard\nowidctlpar' . PHP_EOL;
449-
$sRTFText .= "{$element}";
450-
$sRTFText .= '\par' . PHP_EOL;
451-
452-
return $sRTFText;
453-
}
454311
}

0 commit comments

Comments
 (0)