Enable image in HTML writer
This commit is contained in:
parent
9c738f7eae
commit
2829fd8216
|
|
@ -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
|
- ListItem: Ability to create custom list and reset list number - @ivanlanin GH-10 GH-198
|
||||||
- ODT Writer: Basic table writing support - @ivanlanin
|
- ODT Writer: Basic table writing support - @ivanlanin
|
||||||
- Image: Keep image aspect ratio if only 1 dimension styled - @japonicus GH-194
|
- 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
|
- 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 initiated using DomPDF - @ivanlanin GH-68
|
- PDF Writer: Basic PDF writer using DomPDF: All HTML element except image - @ivanlanin GH-68
|
||||||
|
|
||||||
### Bugfixes
|
### Bugfixes
|
||||||
|
|
||||||
|
|
|
||||||
114
docs/intro.rst
114
docs/intro.rst
|
|
@ -62,63 +62,63 @@ Below are the supported features for each file formats.
|
||||||
Writers
|
Writers
|
||||||
~~~~~~~
|
~~~~~~~
|
||||||
|
|
||||||
+-------------------------------------------------+--------+-------+-------+
|
+-------------------------------------------------+--------+-------+-------+-------+-------+
|
||||||
| Features | DOCX | ODT | RTF |
|
| Features | DOCX | ODT | RTF | HTML | PDF |
|
||||||
+=========================+=======================+========+=======+=======+
|
+=========================+=======================+========+=======+=======+=======+=======+
|
||||||
| **Document Properties** | Standard | | | |
|
| **Document Properties** | Standard | ✓ | | | | |
|
||||||
+ +-----------------------+--------+-------+-------+
|
+ +-----------------------+--------+-------+-------+-------+-------+
|
||||||
| | Extended | | | |
|
| | Extended | ✓ | | | | |
|
||||||
+ +-----------------------+--------+-------+-------+
|
+ +-----------------------+--------+-------+-------+-------+-------+
|
||||||
| | UserDefined | | | |
|
| | UserDefined | ✓ | | | | |
|
||||||
+-------------------------+-----------------------+--------+-------+-------+
|
+-------------------------+-----------------------+--------+-------+-------+-------+-------+
|
||||||
| **Element Type** | Text | ✓ | ✓ | ✓ |
|
| **Element Type** | Text | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||||
+ +-----------------------+--------+-------+-------+
|
+ +-----------------------+--------+-------+-------+-------+-------+
|
||||||
| | Text Run | ✓ | ✓ | ✓ |
|
| | Text Run | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||||
+ +-----------------------+--------+-------+-------+
|
+ +-----------------------+--------+-------+-------+-------+-------+
|
||||||
| | Title | ✓ | | |
|
| | Title | ✓ | | | ✓ | ✓ |
|
||||||
+ +-----------------------+--------+-------+-------+
|
+ +-----------------------+--------+-------+-------+-------+-------+
|
||||||
| | Link | ✓ | | |
|
| | Link | ✓ | | | ✓ | ✓ |
|
||||||
+ +-----------------------+--------+-------+-------+
|
+ +-----------------------+--------+-------+-------+-------+-------+
|
||||||
| | Preserve Text | ✓ | | |
|
| | Preserve Text | ✓ | | | | |
|
||||||
+ +-----------------------+--------+-------+-------+
|
+ +-----------------------+--------+-------+-------+-------+-------+
|
||||||
| | Text Break | ✓ | ✓ | ✓ |
|
| | Text Break | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||||
+ +-----------------------+--------+-------+-------+
|
+ +-----------------------+--------+-------+-------+-------+-------+
|
||||||
| | Page Break | ✓ | | |
|
| | Page Break | ✓ | | | | |
|
||||||
+ +-----------------------+--------+-------+-------+
|
+ +-----------------------+--------+-------+-------+-------+-------+
|
||||||
| | List | ✓ | | |
|
| | List | ✓ | | | | |
|
||||||
+ +-----------------------+--------+-------+-------+
|
+ +-----------------------+--------+-------+-------+-------+-------+
|
||||||
| | Table | ✓ | | |
|
| | Table | ✓ | ✓ | | ✓ | ✓ |
|
||||||
+ +-----------------------+--------+-------+-------+
|
+ +-----------------------+--------+-------+-------+-------+-------+
|
||||||
| | Image | ✓ | | |
|
| | Image | ✓ | | | ✓ | |
|
||||||
+ +-----------------------+--------+-------+-------+
|
+ +-----------------------+--------+-------+-------+-------+-------+
|
||||||
| | Object | ✓ | | |
|
| | Object | ✓ | | | | |
|
||||||
+ +-----------------------+--------+-------+-------+
|
+ +-----------------------+--------+-------+-------+-------+-------+
|
||||||
| | Watermark | ✓ | | |
|
| | Watermark | ✓ | | | | |
|
||||||
+ +-----------------------+--------+-------+-------+
|
+ +-----------------------+--------+-------+-------+-------+-------+
|
||||||
| | Table of Contents | ✓ | | |
|
| | Table of Contents | ✓ | | | | |
|
||||||
+ +-----------------------+--------+-------+-------+
|
+ +-----------------------+--------+-------+-------+-------+-------+
|
||||||
| | Header | ✓ | | |
|
| | Header | ✓ | | | | |
|
||||||
+ +-----------------------+--------+-------+-------+
|
+ +-----------------------+--------+-------+-------+-------+-------+
|
||||||
| | Footer | ✓ | | |
|
| | Footer | ✓ | | | | |
|
||||||
+ +-----------------------+--------+-------+-------+
|
+ +-----------------------+--------+-------+-------+-------+-------+
|
||||||
| | Footnote | ✓ | | |
|
| | Footnote | ✓ | | | | |
|
||||||
+ +-----------------------+--------+-------+-------+
|
+ +-----------------------+--------+-------+-------+-------+-------+
|
||||||
| | Endnote | ✓ | | |
|
| | Endnote | ✓ | | | | |
|
||||||
+-------------------------+-----------------------+--------+-------+-------+
|
+-------------------------+-----------------------+--------+-------+-------+-------+-------+
|
||||||
| **Graphs** | 2D basic graphs | | | |
|
| **Graphs** | 2D basic graphs | | | | | |
|
||||||
+ +-----------------------+--------+-------+-------+
|
+ +-----------------------+--------+-------+-------+-------+-------+
|
||||||
| | 2D advanced graphs | | | |
|
| | 2D advanced graphs | | | | | |
|
||||||
+ +-----------------------+--------+-------+-------+
|
+ +-----------------------+--------+-------+-------+-------+-------+
|
||||||
| | 3D graphs | | | |
|
| | 3D graphs | | | | | |
|
||||||
+-------------------------+-----------------------+--------+-------+-------+
|
+-------------------------+-----------------------+--------+-------+-------+-------+-------+
|
||||||
| **Math** | OMML support | | | |
|
| **Math** | OMML support | | | | | |
|
||||||
+ +-----------------------+--------+-------+-------+
|
+ +-----------------------+--------+-------+-------+-------+-------+
|
||||||
| | MathML support | | | |
|
| | MathML support | | | | | |
|
||||||
+-------------------------+-----------------------+--------+-------+-------+
|
+-------------------------+-----------------------+--------+-------+-------+-------+-------+
|
||||||
| **Bonus** | Encryption | | | |
|
| **Bonus** | Encryption | | | | | |
|
||||||
+ +-----------------------+--------+-------+-------+
|
+ +-----------------------+--------+-------+-------+-------+-------+
|
||||||
| | Protection | | | |
|
| | Protection | | | | | |
|
||||||
+-------------------------+-----------------------+--------+-------+-------+
|
+-------------------------+-----------------------+--------+-------+-------+-------+-------+
|
||||||
|
|
||||||
|
|
||||||
Readers
|
Readers
|
||||||
|
|
|
||||||
|
|
@ -126,6 +126,16 @@ class Image extends AbstractElement
|
||||||
return $this->source;
|
return $this->source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get image source type
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getSourceType()
|
||||||
|
{
|
||||||
|
return $this->sourceType;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get image media ID
|
* Get image media ID
|
||||||
*
|
*
|
||||||
|
|
@ -324,6 +334,9 @@ class Image extends AbstractElement
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set proportional width/height if one dimension not available
|
* Set proportional width/height if one dimension not available
|
||||||
|
*
|
||||||
|
* @param integer $actualWidth
|
||||||
|
* @param integer $actualHeight
|
||||||
*/
|
*/
|
||||||
private function setProportionalSize($actualWidth, $actualHeight)
|
private function setProportionalSize($actualWidth, $actualHeight)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -164,11 +164,7 @@ abstract class AbstractWriter implements WriterInterface
|
||||||
protected function getTempFile($filename)
|
protected function getTempFile($filename)
|
||||||
{
|
{
|
||||||
// Temporary directory
|
// Temporary directory
|
||||||
$tempDir = sys_get_temp_dir() . '/PHPWordMedia/';
|
$this->setTempDir();
|
||||||
if (!is_dir($tempDir)) {
|
|
||||||
mkdir($tempDir);
|
|
||||||
}
|
|
||||||
$this->tempDir = $tempDir;
|
|
||||||
|
|
||||||
// Temporary file
|
// Temporary file
|
||||||
$this->originalFilename = $filename;
|
$this->originalFilename = $filename;
|
||||||
|
|
@ -184,23 +180,30 @@ abstract class AbstractWriter implements WriterInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cleanup temporary file
|
* Get temporary directory
|
||||||
*
|
|
||||||
* If a temporary file was used, copy it to the correct file stream
|
|
||||||
*/
|
*/
|
||||||
protected function getTempDir()
|
protected function getTempDir()
|
||||||
{
|
{
|
||||||
return $this->tempDir;
|
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
|
* Cleanup temporary file
|
||||||
*
|
|
||||||
* If a temporary file was used, copy it to the correct file stream
|
|
||||||
*/
|
*/
|
||||||
protected function cleanupTempFile()
|
protected function cleanupTempFile()
|
||||||
{
|
{
|
||||||
// File
|
|
||||||
if ($this->originalFilename != $this->tempFilename) {
|
if ($this->originalFilename != $this->tempFilename) {
|
||||||
if (copy($this->tempFilename, $this->originalFilename) === false) {
|
if (copy($this->tempFilename, $this->originalFilename) === false) {
|
||||||
throw new Exception("Could not copy temporary zip file {$this->tempFilename} to {$this->originalFilename}.");
|
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);
|
@unlink($this->tempFilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Directory
|
$this->clearTempDir();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear temporary directory
|
||||||
|
*/
|
||||||
|
protected function clearTempDir()
|
||||||
|
{
|
||||||
if (is_dir($this->tempDir)) {
|
if (is_dir($this->tempDir)) {
|
||||||
$this->deleteDir($this->tempDir);
|
$this->deleteDir($this->tempDir);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,13 @@ use PhpOffice\PhpWord\TOC;
|
||||||
*/
|
*/
|
||||||
class HTML extends AbstractWriter implements WriterInterface
|
class HTML extends AbstractWriter implements WriterInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Is the current writer creating PDF?
|
||||||
|
*
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
protected $isPdf = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create new instance
|
* Create new instance
|
||||||
*/
|
*/
|
||||||
|
|
@ -53,9 +60,11 @@ class HTML extends AbstractWriter implements WriterInterface
|
||||||
public function save($filename = null)
|
public function save($filename = null)
|
||||||
{
|
{
|
||||||
if (!is_null($this->getPhpWord())) {
|
if (!is_null($this->getPhpWord())) {
|
||||||
|
$this->setTempDir();
|
||||||
$hFile = fopen($filename, 'w') or die("can't open file");
|
$hFile = fopen($filename, 'w') or die("can't open file");
|
||||||
fwrite($hFile, $this->writeDocument());
|
fwrite($hFile, $this->writeDocument());
|
||||||
fclose($hFile);
|
fclose($hFile);
|
||||||
|
$this->clearTempDir();
|
||||||
} else {
|
} else {
|
||||||
throw new Exception("No PHPWord assigned.");
|
throw new Exception("No PHPWord assigned.");
|
||||||
}
|
}
|
||||||
|
|
@ -421,7 +430,18 @@ class HTML extends AbstractWriter implements WriterInterface
|
||||||
*/
|
*/
|
||||||
private function writeImage($element, $withoutP = false)
|
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 = '<img border="0" src="' . $imageData . '"/>';
|
||||||
|
if (!$withoutP) {
|
||||||
|
$html = '<p>' . $html . '</p>' . PHP_EOL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $html;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -597,4 +617,42 @@ class HTML extends AbstractWriter implements WriterInterface
|
||||||
|
|
||||||
return $string;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,6 @@ abstract class AbstractRenderer extends \PhpOffice\PhpWord\Writer\HTML
|
||||||
public function __construct(PhpWord $phpWord)
|
public function __construct(PhpWord $phpWord)
|
||||||
{
|
{
|
||||||
parent::__construct($phpWord);
|
parent::__construct($phpWord);
|
||||||
$this->setTempDir(sys_get_temp_dir());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -141,36 +140,11 @@ abstract class AbstractRenderer extends \PhpOffice\PhpWord\Writer\HTML
|
||||||
return $this;
|
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
|
* Save PhpWord to PDF file, pre-save
|
||||||
*
|
*
|
||||||
* @param string $pFilename Name of the file to save as
|
* @param string $pFilename Name of the file to save as
|
||||||
|
* @return resource
|
||||||
*/
|
*/
|
||||||
protected function prepareForSave($pFilename = null)
|
protected function prepareForSave($pFilename = null)
|
||||||
{
|
{
|
||||||
|
|
@ -178,6 +152,8 @@ abstract class AbstractRenderer extends \PhpOffice\PhpWord\Writer\HTML
|
||||||
if ($fileHandle === false) {
|
if ($fileHandle === false) {
|
||||||
throw new Exception("Could not open file $pFilename for writing.");
|
throw new Exception("Could not open file $pFilename for writing.");
|
||||||
}
|
}
|
||||||
|
$this->isPdf = true;
|
||||||
|
|
||||||
return $fileHandle;
|
return $fileHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -181,6 +181,8 @@ class Word2007 extends AbstractWriter implements WriterInterface
|
||||||
/**
|
/**
|
||||||
* Add file to package
|
* Add file to package
|
||||||
*
|
*
|
||||||
|
* Get the actual source from an archive image
|
||||||
|
*
|
||||||
* @param mixed $objZip
|
* @param mixed $objZip
|
||||||
* @param string $source
|
* @param string $source
|
||||||
* @param string $target
|
* @param string $target
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,9 @@ class SettingsTest extends \PHPUnit_Framework_TestCase
|
||||||
$this->assertFalse(Settings::setZipClass('foo'));
|
$this->assertFalse(Settings::setZipClass('foo'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test set/get PDF renderer
|
||||||
|
*/
|
||||||
public function testSetGetPdfRenderer()
|
public function testSetGetPdfRenderer()
|
||||||
{
|
{
|
||||||
$domPdfPath = realpath(PHPWORD_TESTS_BASE_DIR . '/../vendor/dompdf/dompdf');
|
$domPdfPath = realpath(PHPWORD_TESTS_BASE_DIR . '/../vendor/dompdf/dompdf');
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue