Enable image in HTML writer

This commit is contained in:
Ivan Lanin 2014-04-16 12:12:32 +07:00
parent 9c738f7eae
commit 2829fd8216
8 changed files with 161 additions and 99 deletions

View File

@ -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

View File

@ -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

View File

@ -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)
{

View File

@ -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);
}

View File

@ -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 = '<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;
}
/**
* 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;
}
}

View File

@ -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;
}

View File

@ -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

View File

@ -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');