diff --git a/CHANGELOG.md b/CHANGELOG.md
index b06aa79c..0b9cf9a2 100755
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -32,8 +32,8 @@ This release marked heavy refactorings on internal code structure with the creat
- ListItem: Ability to create custom list and reset list number - @ivanlanin GH-10 GH-198
- ODT Writer: Basic table writing support - @ivanlanin
- Image: Keep image aspect ratio if only 1 dimension styled - @japonicus GH-194
-- HTML Writer: Basic HTML writer initiated - @ivanlanin GH-203 GH-67 GH-147
-- PDF Writer: Basic PDF writer initiated using DomPDF - @ivanlanin GH-68
+- HTML Writer: Basic HTML writer: text, textrun, link, title, textbreak, table, image (as Base64) - @ivanlanin GH-203 GH-67 GH-147
+- PDF Writer: Basic PDF writer using DomPDF: All HTML element except image - @ivanlanin GH-68
### Bugfixes
diff --git a/docs/intro.rst b/docs/intro.rst
index 0f1f3d74..53a352fe 100644
--- a/docs/intro.rst
+++ b/docs/intro.rst
@@ -62,63 +62,63 @@ Below are the supported features for each file formats.
Writers
~~~~~~~
-+-------------------------------------------------+--------+-------+-------+
-| Features | DOCX | ODT | RTF |
-+=========================+=======================+========+=======+=======+
-| **Document Properties** | Standard | | | |
-+ +-----------------------+--------+-------+-------+
-| | Extended | | | |
-+ +-----------------------+--------+-------+-------+
-| | UserDefined | | | |
-+-------------------------+-----------------------+--------+-------+-------+
-| **Element Type** | Text | ✓ | ✓ | ✓ |
-+ +-----------------------+--------+-------+-------+
-| | Text Run | ✓ | ✓ | ✓ |
-+ +-----------------------+--------+-------+-------+
-| | Title | ✓ | | |
-+ +-----------------------+--------+-------+-------+
-| | Link | ✓ | | |
-+ +-----------------------+--------+-------+-------+
-| | Preserve Text | ✓ | | |
-+ +-----------------------+--------+-------+-------+
-| | Text Break | ✓ | ✓ | ✓ |
-+ +-----------------------+--------+-------+-------+
-| | Page Break | ✓ | | |
-+ +-----------------------+--------+-------+-------+
-| | List | ✓ | | |
-+ +-----------------------+--------+-------+-------+
-| | Table | ✓ | | |
-+ +-----------------------+--------+-------+-------+
-| | Image | ✓ | | |
-+ +-----------------------+--------+-------+-------+
-| | Object | ✓ | | |
-+ +-----------------------+--------+-------+-------+
-| | Watermark | ✓ | | |
-+ +-----------------------+--------+-------+-------+
-| | Table of Contents | ✓ | | |
-+ +-----------------------+--------+-------+-------+
-| | Header | ✓ | | |
-+ +-----------------------+--------+-------+-------+
-| | Footer | ✓ | | |
-+ +-----------------------+--------+-------+-------+
-| | Footnote | ✓ | | |
-+ +-----------------------+--------+-------+-------+
-| | Endnote | ✓ | | |
-+-------------------------+-----------------------+--------+-------+-------+
-| **Graphs** | 2D basic graphs | | | |
-+ +-----------------------+--------+-------+-------+
-| | 2D advanced graphs | | | |
-+ +-----------------------+--------+-------+-------+
-| | 3D graphs | | | |
-+-------------------------+-----------------------+--------+-------+-------+
-| **Math** | OMML support | | | |
-+ +-----------------------+--------+-------+-------+
-| | MathML support | | | |
-+-------------------------+-----------------------+--------+-------+-------+
-| **Bonus** | Encryption | | | |
-+ +-----------------------+--------+-------+-------+
-| | Protection | | | |
-+-------------------------+-----------------------+--------+-------+-------+
++-------------------------------------------------+--------+-------+-------+-------+-------+
+| Features | DOCX | ODT | RTF | HTML | PDF |
++=========================+=======================+========+=======+=======+=======+=======+
+| **Document Properties** | Standard | ✓ | | | | |
++ +-----------------------+--------+-------+-------+-------+-------+
+| | Extended | ✓ | | | | |
++ +-----------------------+--------+-------+-------+-------+-------+
+| | UserDefined | ✓ | | | | |
++-------------------------+-----------------------+--------+-------+-------+-------+-------+
+| **Element Type** | Text | ✓ | ✓ | ✓ | ✓ | ✓ |
++ +-----------------------+--------+-------+-------+-------+-------+
+| | Text Run | ✓ | ✓ | ✓ | ✓ | ✓ |
++ +-----------------------+--------+-------+-------+-------+-------+
+| | Title | ✓ | | | ✓ | ✓ |
++ +-----------------------+--------+-------+-------+-------+-------+
+| | Link | ✓ | | | ✓ | ✓ |
++ +-----------------------+--------+-------+-------+-------+-------+
+| | Preserve Text | ✓ | | | | |
++ +-----------------------+--------+-------+-------+-------+-------+
+| | Text Break | ✓ | ✓ | ✓ | ✓ | ✓ |
++ +-----------------------+--------+-------+-------+-------+-------+
+| | Page Break | ✓ | | | | |
++ +-----------------------+--------+-------+-------+-------+-------+
+| | List | ✓ | | | | |
++ +-----------------------+--------+-------+-------+-------+-------+
+| | Table | ✓ | ✓ | | ✓ | ✓ |
++ +-----------------------+--------+-------+-------+-------+-------+
+| | Image | ✓ | | | ✓ | |
++ +-----------------------+--------+-------+-------+-------+-------+
+| | Object | ✓ | | | | |
++ +-----------------------+--------+-------+-------+-------+-------+
+| | Watermark | ✓ | | | | |
++ +-----------------------+--------+-------+-------+-------+-------+
+| | Table of Contents | ✓ | | | | |
++ +-----------------------+--------+-------+-------+-------+-------+
+| | Header | ✓ | | | | |
++ +-----------------------+--------+-------+-------+-------+-------+
+| | Footer | ✓ | | | | |
++ +-----------------------+--------+-------+-------+-------+-------+
+| | Footnote | ✓ | | | | |
++ +-----------------------+--------+-------+-------+-------+-------+
+| | Endnote | ✓ | | | | |
++-------------------------+-----------------------+--------+-------+-------+-------+-------+
+| **Graphs** | 2D basic graphs | | | | | |
++ +-----------------------+--------+-------+-------+-------+-------+
+| | 2D advanced graphs | | | | | |
++ +-----------------------+--------+-------+-------+-------+-------+
+| | 3D graphs | | | | | |
++-------------------------+-----------------------+--------+-------+-------+-------+-------+
+| **Math** | OMML support | | | | | |
++ +-----------------------+--------+-------+-------+-------+-------+
+| | MathML support | | | | | |
++-------------------------+-----------------------+--------+-------+-------+-------+-------+
+| **Bonus** | Encryption | | | | | |
++ +-----------------------+--------+-------+-------+-------+-------+
+| | Protection | | | | | |
++-------------------------+-----------------------+--------+-------+-------+-------+-------+
Readers
diff --git a/src/PhpWord/Element/Image.php b/src/PhpWord/Element/Image.php
index f7752b27..e4e91fe6 100755
--- a/src/PhpWord/Element/Image.php
+++ b/src/PhpWord/Element/Image.php
@@ -126,6 +126,16 @@ class Image extends AbstractElement
return $this->source;
}
+ /**
+ * Get image source type
+ *
+ * @return string
+ */
+ public function getSourceType()
+ {
+ return $this->sourceType;
+ }
+
/**
* Get image media ID
*
@@ -324,6 +334,9 @@ class Image extends AbstractElement
/**
* Set proportional width/height if one dimension not available
+ *
+ * @param integer $actualWidth
+ * @param integer $actualHeight
*/
private function setProportionalSize($actualWidth, $actualHeight)
{
diff --git a/src/PhpWord/Writer/AbstractWriter.php b/src/PhpWord/Writer/AbstractWriter.php
index 9403d724..08785ecd 100644
--- a/src/PhpWord/Writer/AbstractWriter.php
+++ b/src/PhpWord/Writer/AbstractWriter.php
@@ -164,11 +164,7 @@ abstract class AbstractWriter implements WriterInterface
protected function getTempFile($filename)
{
// Temporary directory
- $tempDir = sys_get_temp_dir() . '/PHPWordMedia/';
- if (!is_dir($tempDir)) {
- mkdir($tempDir);
- }
- $this->tempDir = $tempDir;
+ $this->setTempDir();
// Temporary file
$this->originalFilename = $filename;
@@ -184,23 +180,30 @@ abstract class AbstractWriter implements WriterInterface
}
/**
- * Cleanup temporary file
- *
- * If a temporary file was used, copy it to the correct file stream
+ * Get temporary directory
*/
protected function getTempDir()
{
return $this->tempDir;
}
+ /**
+ * Set temporary directory
+ */
+ protected function setTempDir()
+ {
+ $tempDir = sys_get_temp_dir() . '/PHPWordMedia/';
+ if (!is_dir($tempDir)) {
+ mkdir($tempDir);
+ }
+ $this->tempDir = $tempDir;
+ }
+
/**
* Cleanup temporary file
- *
- * If a temporary file was used, copy it to the correct file stream
*/
protected function cleanupTempFile()
{
- // File
if ($this->originalFilename != $this->tempFilename) {
if (copy($this->tempFilename, $this->originalFilename) === false) {
throw new Exception("Could not copy temporary zip file {$this->tempFilename} to {$this->originalFilename}.");
@@ -208,7 +211,14 @@ abstract class AbstractWriter implements WriterInterface
@unlink($this->tempFilename);
}
- // Directory
+ $this->clearTempDir();
+ }
+
+ /**
+ * Clear temporary directory
+ */
+ protected function clearTempDir()
+ {
if (is_dir($this->tempDir)) {
$this->deleteDir($this->tempDir);
}
diff --git a/src/PhpWord/Writer/HTML.php b/src/PhpWord/Writer/HTML.php
index f0720f66..1205f112 100644
--- a/src/PhpWord/Writer/HTML.php
+++ b/src/PhpWord/Writer/HTML.php
@@ -36,6 +36,13 @@ use PhpOffice\PhpWord\TOC;
*/
class HTML extends AbstractWriter implements WriterInterface
{
+ /**
+ * Is the current writer creating PDF?
+ *
+ * @var boolean
+ */
+ protected $isPdf = false;
+
/**
* Create new instance
*/
@@ -53,9 +60,11 @@ class HTML extends AbstractWriter implements WriterInterface
public function save($filename = null)
{
if (!is_null($this->getPhpWord())) {
+ $this->setTempDir();
$hFile = fopen($filename, 'w') or die("can't open file");
fwrite($hFile, $this->writeDocument());
fclose($hFile);
+ $this->clearTempDir();
} else {
throw new Exception("No PHPWord assigned.");
}
@@ -421,7 +430,18 @@ class HTML extends AbstractWriter implements WriterInterface
*/
private function writeImage($element, $withoutP = false)
{
- return $this->writeUnsupportedElement($element, $withoutP);
+ $html = $this->writeUnsupportedElement($element, $withoutP);
+ if (!$this->isPdf) {
+ $imageData = $this->getBase64ImageData($element);
+ if (!is_null($imageData)) {
+ $html = '';
+ if (!$withoutP) {
+ $html = '
' . $html . '
' . PHP_EOL; + } + } + } + + return $html; } /** @@ -597,4 +617,42 @@ class HTML extends AbstractWriter implements WriterInterface return $string; } + + /** + * Get Base64 image data + * + * @return string|null + */ + private function getBase64ImageData(Image $element) + { + $imageData = null; + $source = $element->getSource(); + $imageType = $element->getImageType(); + + // Get actual source + if ($element->getSourceType() == 'archive') { + $source = substr($source, 6); + list($zipFilename, $imageFilename) = explode('#', $source); + $zip = new \ZipArchive(); + if ($zip->open($zipFilename) !== false) { + if ($zip->locateName($imageFilename)) { + $zip->extractTo($this->getTempDir(), $imageFilename); + $actualSource = $this->getTempDir() . DIRECTORY_SEPARATOR . $imageFilename; + } + } + $zip->close(); + } else { + $actualSource = $source; + } + + // Read image binary data and convert into Base64 + if ($fp = fopen($actualSource, "rb", 0)) { + $image = fread($fp, filesize($actualSource)); + fclose($fp); + $base64 = chunk_split(base64_encode($image)); + $imageData = 'data:' . $imageType . ';base64,' . $base64; + } + + return $imageData; + } } diff --git a/src/PhpWord/Writer/PDF/AbstractRenderer.php b/src/PhpWord/Writer/PDF/AbstractRenderer.php index be48a9f2..64f196e9 100644 --- a/src/PhpWord/Writer/PDF/AbstractRenderer.php +++ b/src/PhpWord/Writer/PDF/AbstractRenderer.php @@ -69,7 +69,6 @@ abstract class AbstractRenderer extends \PhpOffice\PhpWord\Writer\HTML public function __construct(PhpWord $phpWord) { parent::__construct($phpWord); - $this->setTempDir(sys_get_temp_dir()); } /** @@ -141,36 +140,11 @@ abstract class AbstractRenderer extends \PhpOffice\PhpWord\Writer\HTML return $this; } - /** - * Get temporary storage directory - * - * @return string - */ - public function getTempDir() - { - return $this->tempDir; - } - - /** - * Set temporary storage directory - * - * @param string $pValue Temporary storage directory - * @return self - */ - public function setTempDir($pValue = '') - { - if (is_dir($pValue)) { - $this->tempDir = $pValue; - } else { - throw new Exception("Directory does not exist: $pValue"); - } - return $this; - } - /** * Save PhpWord to PDF file, pre-save * * @param string $pFilename Name of the file to save as + * @return resource */ protected function prepareForSave($pFilename = null) { @@ -178,6 +152,8 @@ abstract class AbstractRenderer extends \PhpOffice\PhpWord\Writer\HTML if ($fileHandle === false) { throw new Exception("Could not open file $pFilename for writing."); } + $this->isPdf = true; + return $fileHandle; } diff --git a/src/PhpWord/Writer/Word2007.php b/src/PhpWord/Writer/Word2007.php index 0d0c0f69..920a159c 100755 --- a/src/PhpWord/Writer/Word2007.php +++ b/src/PhpWord/Writer/Word2007.php @@ -181,6 +181,8 @@ class Word2007 extends AbstractWriter implements WriterInterface /** * Add file to package * + * Get the actual source from an archive image + * * @param mixed $objZip * @param string $source * @param string $target diff --git a/tests/PhpWord/Tests/SettingsTest.php b/tests/PhpWord/Tests/SettingsTest.php index 46efdf76..e7968355 100644 --- a/tests/PhpWord/Tests/SettingsTest.php +++ b/tests/PhpWord/Tests/SettingsTest.php @@ -39,6 +39,9 @@ class SettingsTest extends \PHPUnit_Framework_TestCase $this->assertFalse(Settings::setZipClass('foo')); } + /** + * Test set/get PDF renderer + */ public function testSetGetPdfRenderer() { $domPdfPath = realpath(PHPWORD_TESTS_BASE_DIR . '/../vendor/dompdf/dompdf');