Skip to content

Commit 3249941

Browse files
committed
Refactor: Apply composite design pattern to HTML writer
1 parent 03ff0fb commit 3249941

File tree

17 files changed

+836
-514
lines changed

17 files changed

+836
-514
lines changed

src/PhpWord/Writer/HTML.php

Lines changed: 35 additions & 514 deletions
Large diffs are not rendered by default.
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
<?php
2+
/**
3+
* PHPWord
4+
*
5+
* @link https://github.com/PHPOffice/PHPWord
6+
* @copyright 2014 PHPWord
7+
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
8+
*/
9+
10+
namespace PhpOffice\PhpWord\Writer\HTML\Element;
11+
12+
use PhpOffice\PhpWord\Element\AbstractElement;
13+
use PhpOffice\PhpWord\Writer\HTML;
14+
15+
/**
16+
* Generic element HTML writer
17+
*
18+
* Section: Text, TextRun, Link, Title, PreserveText, TextBreak, PageBreak, Table, ListItem, Image, Object, Endnote, Footnote
19+
* Cell: Text, TextRun, Link, PreserveText, TextBreak, ListItem, Image, Object, Endnote, Footnote
20+
* TextRun: Text, Link, TextBreak, Image, Endnote, Footnote
21+
*
22+
* @since 0.10.0
23+
*/
24+
class Element
25+
{
26+
/**
27+
* Parent writer
28+
*
29+
* @var \PhpOffice\PhpWord\Writer\HTML
30+
*/
31+
protected $parentWriter;
32+
33+
/**
34+
* Element
35+
*
36+
* @var \PhpOffice\PhpWord\Element\AbstractElement
37+
*/
38+
protected $element;
39+
40+
/**
41+
* Without paragraph
42+
*
43+
* @var bool
44+
*/
45+
protected $withoutP = false;
46+
47+
/**
48+
* Create new instance
49+
*
50+
* @param bool $withoutP
51+
*/
52+
public function __construct(AbstractElement $element, $withoutP = false)
53+
{
54+
$this->element = $element;
55+
$this->withoutP = $withoutP;
56+
}
57+
58+
/**
59+
* Write element
60+
*
61+
* @return string
62+
*/
63+
public function write()
64+
{
65+
$html = '';
66+
$elmName = str_replace('PhpOffice\\PhpWord\\Element\\', '', get_class($this->element));
67+
$elmWriterClass = 'PhpOffice\\PhpWord\\Writer\\HTML\\Element\\' . $elmName;
68+
if (class_exists($elmWriterClass) === true) {
69+
$elmWriter = new $elmWriterClass($this->element, $this->withoutP);
70+
$elmWriter->setParentWriter($this->parentWriter);
71+
$html = $elmWriter->write();
72+
}
73+
74+
return $html;
75+
}
76+
77+
/**
78+
* Set parent writer
79+
*
80+
* @param \PhpOffice\PhpWord\Writer\HTML $pWriter
81+
*/
82+
public function setParentWriter(HTML $writer)
83+
{
84+
$this->parentWriter = $writer;
85+
}
86+
87+
/**
88+
* Get parent writer
89+
*
90+
* @return \PhpOffice\PhpWord\Writer\HTML
91+
* @throws \PhpOffice\PhpWord\Exception\Exception
92+
*/
93+
public function getParentWriter()
94+
{
95+
if (!is_null($this->parentWriter)) {
96+
return $this->parentWriter;
97+
} else {
98+
throw new Exception("No parent HTML Writer assigned.");
99+
}
100+
}
101+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
/**
3+
* PHPWord
4+
*
5+
* @link https://github.com/PHPOffice/PHPWord
6+
* @copyright 2014 PHPWord
7+
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
8+
*/
9+
10+
namespace PhpOffice\PhpWord\Writer\HTML\Element;
11+
12+
/**
13+
* Endnote element HTML writer
14+
*
15+
* @since 0.10.0
16+
*/
17+
class Endnote extends Note
18+
{
19+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
/**
3+
* PHPWord
4+
*
5+
* @link https://github.com/PHPOffice/PHPWord
6+
* @copyright 2014 PHPWord
7+
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
8+
*/
9+
10+
namespace PhpOffice\PhpWord\Writer\HTML\Element;
11+
12+
/**
13+
* Footnote element HTML writer
14+
*
15+
* @since 0.10.0
16+
*/
17+
class Footnote extends Note
18+
{
19+
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<?php
2+
/**
3+
* PHPWord
4+
*
5+
* @link https://github.com/PHPOffice/PHPWord
6+
* @copyright 2014 PHPWord
7+
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
8+
*/
9+
10+
namespace PhpOffice\PhpWord\Writer\HTML\Element;
11+
12+
use PhpOffice\PhpWord\Element\Image as ImageElement;
13+
use PhpOffice\PhpWord\Writer\HTML\Style\Style as StyleWriter;
14+
15+
/**
16+
* Image element HTML writer
17+
*
18+
* @since 0.10.0
19+
*/
20+
class Image extends Element
21+
{
22+
/**
23+
* Write image
24+
*
25+
* @return string
26+
*/
27+
public function write()
28+
{
29+
if (!$this->getParentWriter()->isPdf()) {
30+
$imageData = $this->getBase64ImageData($this->element);
31+
if (!is_null($imageData)) {
32+
$styleWriter = new StyleWriter();
33+
$style = $styleWriter->assembleCss(array(
34+
'width' => $this->element->getStyle()->getWidth() . 'px',
35+
'height' => $this->element->getStyle()->getHeight() . 'px',
36+
));
37+
$html = "<img border=\"0\" style=\"{$style}\" src=\"{$imageData}\"/>";
38+
if (!$this->withoutP) {
39+
$html = "<p>{$html}</p>" . PHP_EOL;
40+
}
41+
}
42+
}
43+
44+
return $html;
45+
}
46+
47+
/**
48+
* Get Base64 image data
49+
*
50+
* @return string|null
51+
*/
52+
private function getBase64ImageData(ImageElement $element)
53+
{
54+
$source = $element->getSource();
55+
$imageType = $element->getImageType();
56+
$imageData = null;
57+
$imageBinary = null;
58+
$actualSource = null;
59+
60+
// Get actual source from archive image or other source
61+
// Return null if not found
62+
if ($element->getSourceType() == ImageElement::SOURCE_ARCHIVE) {
63+
$source = substr($source, 6);
64+
list($zipFilename, $imageFilename) = explode('#', $source);
65+
66+
$zipClass = \PhpOffice\PhpWord\Settings::getZipClass();
67+
$zip = new $zipClass();
68+
if ($zip->open($zipFilename) !== false) {
69+
if ($zip->locateName($imageFilename)) {
70+
$zip->extractTo($this->getParentWriter()->getTempDir(), $imageFilename);
71+
$actualSource = $this->getParentWriter()->getTempDir() . DIRECTORY_SEPARATOR . $imageFilename;
72+
}
73+
}
74+
$zip->close();
75+
} else {
76+
$actualSource = $source;
77+
}
78+
if (is_null($actualSource)) {
79+
return null;
80+
}
81+
82+
// Read image binary data and convert into Base64
83+
if ($element->getSourceType() == ImageElement::SOURCE_GD) {
84+
$imageResource = call_user_func($element->getImageCreateFunction(), $actualSource);
85+
ob_start();
86+
call_user_func($element->getImageFunction(), $imageResource);
87+
$imageBinary = ob_get_contents();
88+
ob_end_clean();
89+
} else {
90+
if ($fileHandle = fopen($actualSource, 'rb', false)) {
91+
$imageBinary = fread($fileHandle, filesize($actualSource));
92+
fclose($fileHandle);
93+
}
94+
}
95+
if (!is_null($imageBinary)) {
96+
$base64 = chunk_split(base64_encode($imageBinary));
97+
$imageData = 'data:' . $imageType . ';base64,' . $base64;
98+
}
99+
100+
return $imageData;
101+
}
102+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
/**
3+
* PHPWord
4+
*
5+
* @link https://github.com/PHPOffice/PHPWord
6+
* @copyright 2014 PHPWord
7+
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
8+
*/
9+
10+
namespace PhpOffice\PhpWord\Writer\HTML\Element;
11+
12+
/**
13+
* Link element HTML writer
14+
*
15+
* @since 0.10.0
16+
*/
17+
class Link extends Element
18+
{
19+
/**
20+
* Write link
21+
*
22+
* @return string
23+
*/
24+
public function write()
25+
{
26+
$url = $this->element->getLinkSrc();
27+
$text = $this->element->getLinkName();
28+
if ($text == '') {
29+
$text = $url;
30+
}
31+
$html = '';
32+
if (!$this->withoutP) {
33+
$html .= "<p>" . PHP_EOL;
34+
}
35+
$html .= "<a href=\"{$url}\">{$text}</a>" . PHP_EOL;
36+
if (!$this->withoutP) {
37+
$html .= "</p>" . PHP_EOL;
38+
}
39+
40+
return $html;
41+
}
42+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
/**
3+
* PHPWord
4+
*
5+
* @link https://github.com/PHPOffice/PHPWord
6+
* @copyright 2014 PHPWord
7+
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
8+
*/
9+
10+
namespace PhpOffice\PhpWord\Writer\HTML\Element;
11+
12+
/**
13+
* ListItem element HTML writer
14+
*
15+
* @since 0.10.0
16+
*/
17+
class ListItem extends Element
18+
{
19+
/**
20+
* Write list item
21+
*
22+
* @return string
23+
*/
24+
public function write()
25+
{
26+
$text = htmlspecialchars($this->element->getTextObject()->getText());
27+
$html = '<p>' . $text . '</{$p}>' . PHP_EOL;
28+
29+
return $html;
30+
}
31+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
/**
3+
* PHPWord
4+
*
5+
* @link https://github.com/PHPOffice/PHPWord
6+
* @copyright 2014 PHPWord
7+
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
8+
*/
9+
10+
namespace PhpOffice\PhpWord\Writer\HTML\Element;
11+
12+
use PhpOffice\PhpWord\Element\Endnote;
13+
use PhpOffice\PhpWord\Element\Footnote;
14+
15+
/**
16+
* Note element HTML writer
17+
*
18+
* @since 0.10.0
19+
*/
20+
class Note extends Element
21+
{
22+
/**
23+
* Write footnote/endnote marks
24+
*
25+
* @return string
26+
*/
27+
public function write()
28+
{
29+
$noteId = count($this->getParentWriter()->getNotes()) + 1;
30+
$prefix = ($this->element instanceof Endnote) ? 'endnote' : 'footnote';
31+
$noteMark = $prefix . '-' . $this->element->getRelationId();
32+
$this->getParentWriter()->addNote($noteId, $noteMark);
33+
$html = "<a name=\"{$noteMark}\"><a href=\"#note-{$noteId}\" class=\"NoteRef\"><sup>{$noteId}</sup></a>";
34+
35+
return $html;
36+
}
37+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
/**
3+
* PHPWord
4+
*
5+
* @link https://github.com/PHPOffice/PHPWord
6+
* @copyright 2014 PHPWord
7+
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
8+
*/
9+
10+
namespace PhpOffice\PhpWord\Writer\HTML\Element;
11+
12+
/**
13+
* PageBreak element HTML writer
14+
*
15+
* @since 0.10.0
16+
*/
17+
class PageBreak extends TextBreak
18+
{
19+
}

0 commit comments

Comments
 (0)