Word2007 Writer: Refactor writer parts using composite pattern

This commit is contained in:
Ivan Lanin 2014-05-06 01:45:13 +07:00
parent 704cc2fe04
commit 4039304ba0
13 changed files with 308 additions and 143 deletions

View File

@ -18,6 +18,8 @@ This release changed PHPWord license from LGPL 2.1 to LGPL 3.
### Deprecated
- Static classes `Footnotes`, `Endnotes`, and `TOC`
- `Writer\Word2007\Part`: `Numbering::writeNumbering()`, `Settings::writeSettings()`, `WebSettings::writeWebSettings()`, `ContentTypes::writeContentTypes()`, `Styles::writeStyles()`, `Document::writeDocument()` all changed into `write()`
- `Writer\Word2007\Part\DocProps`: Split into `Writer\Word2007\Part\DocPropsCore` and `Writer\Word2007\Part\DocPropsApp`
### Miscellaneous
@ -28,6 +30,7 @@ This release changed PHPWord license from LGPL 2.1 to LGPL 3.
- Refactor: PHPMD recommendation: Change all `get...` method that returns `boolean` into `is...` or `has...` - @ivanlanin
- Docs: Create gh-pages branch for API documentation - @Progi1984 GH-154
- QA: Add `.scrutinizer.yml` and include `composer.lock` for preparation to Scrutinizer - @ivanlanin GH-186
- Word2007 Writer: Refactor writer parts using composite pattern - @ivanlanin
## 0.10.0 - 4 May 2014

View File

@ -32,14 +32,14 @@ class Word2007 extends AbstractWriter implements WriterInterface
*
* @var array
*/
private $cTypes = array('default' => array(), 'override' => array());
private $contentTypes = array('default' => array(), 'override' => array());
/**
* Document relationship
*
* @var array
*/
private $docRels = array();
private $relationships = array();
/**
* Create new Word2007 writer
@ -52,7 +52,7 @@ class Word2007 extends AbstractWriter implements WriterInterface
$this->setPhpWord($phpWord);
// Create parts
$parts = array('ContentTypes', 'Rels', 'DocProps', 'Document', 'Styles',
$parts = array('ContentTypes', 'RelsMain', 'RelsDocument', 'DocPropsApp', 'DocPropsCore', 'Document', 'Styles',
'Numbering', 'Settings', 'WebSettings', 'Header', 'Footer', 'Footnotes',
'Endnotes', 'FontTable', 'Theme');
foreach ($parts as $part) {
@ -81,7 +81,7 @@ class Word2007 extends AbstractWriter implements WriterInterface
$objZip = $this->getZipArchive($filename);
// Content types
$this->cTypes['default'] = array(
$this->contentTypes['default'] = array(
'rels' => 'application/vnd.openxmlformats-package.relationships+xml',
'xml' => 'application/xml',
);
@ -92,7 +92,7 @@ class Word2007 extends AbstractWriter implements WriterInterface
$this->addFilesToPackage($objZip, $sectionMedia);
$this->registerContentTypes($sectionMedia);
foreach ($sectionMedia as $element) {
$this->docRels[] = $element;
$this->relationships[] = $element;
}
}
@ -112,16 +112,16 @@ class Word2007 extends AbstractWriter implements WriterInterface
$this->addNotes($objZip, $rId, 'endnote');
// Write parts
$objZip->addFromString('[Content_Types].xml', $this->getWriterPart('contenttypes')->writeContentTypes($this->cTypes));
$objZip->addFromString('_rels/.rels', $this->getWriterPart('rels')->writeMainRels());
$objZip->addFromString('docProps/app.xml', $this->getWriterPart('docprops')->writeDocPropsApp($this->phpWord));
$objZip->addFromString('docProps/core.xml', $this->getWriterPart('docprops')->writeDocPropsCore($this->phpWord));
$objZip->addFromString('word/_rels/document.xml.rels', $this->getWriterPart('rels')->writeDocRels($this->docRels));
$objZip->addFromString('word/document.xml', $this->getWriterPart('document')->writeDocument($this->phpWord));
$objZip->addFromString('word/styles.xml', $this->getWriterPart('styles')->writeStyles($this->phpWord));
$objZip->addFromString('word/numbering.xml', $this->getWriterPart('numbering')->writeNumbering());
$objZip->addFromString('word/settings.xml', $this->getWriterPart('settings')->writeSettings());
$objZip->addFromString('word/webSettings.xml', $this->getWriterPart('websettings')->writeWebSettings());
$objZip->addFromString('[Content_Types].xml', $this->getWriterPart('contenttypes')->write());
$objZip->addFromString('_rels/.rels', $this->getWriterPart('relsmain')->write());
$objZip->addFromString('docProps/app.xml', $this->getWriterPart('docpropsapp')->write());
$objZip->addFromString('docProps/core.xml', $this->getWriterPart('docpropscore')->write());
$objZip->addFromString('word/_rels/document.xml.rels', $this->getWriterPart('relsdocument')->write());
$objZip->addFromString('word/document.xml', $this->getWriterPart('document')->write());
$objZip->addFromString('word/styles.xml', $this->getWriterPart('styles')->write());
$objZip->addFromString('word/numbering.xml', $this->getWriterPart('numbering')->write());
$objZip->addFromString('word/settings.xml', $this->getWriterPart('settings')->write());
$objZip->addFromString('word/webSettings.xml', $this->getWriterPart('websettings')->write());
$objZip->addFromString('word/fontTable.xml', $this->getWriterPart('fonttable')->write());
$objZip->addFromString('word/theme/theme1.xml', $this->getWriterPart('theme')->write());
@ -136,6 +136,26 @@ class Word2007 extends AbstractWriter implements WriterInterface
}
}
/**
* Get content types
*
* @return array
*/
public function getContentTypes()
{
return $this->contentTypes;
}
/**
* Get content types
*
* @return array
*/
public function getRelationships()
{
return $this->relationships;
}
/**
* Add header/footer media files
*
@ -177,8 +197,8 @@ class Word2007 extends AbstractWriter implements WriterInterface
$elmObject->setRelationId(++$rId);
$elmFile = "{$elmType}{$elmCount}.xml";
$objZip->addFromString("word/$elmFile", $this->getWriterPart($elmType)->$writeFunction($elmObject));
$this->cTypes['override']["/word/$elmFile"] = $elmType;
$this->docRels[] = array('target' => $elmFile, 'type' => $elmType, 'rID' => $rId);
$this->contentTypes['override']["/word/$elmFile"] = $elmType;
$this->relationships[] = array('target' => $elmFile, 'type' => $elmType, 'rID' => $rId);
}
}
@ -192,8 +212,8 @@ class Word2007 extends AbstractWriter implements WriterInterface
private function addNotes($objZip, &$rId, $noteType = 'footnote')
{
$noteType = ($noteType == 'endnote') ? 'endnote' : 'footnote';
$noteTypePlural = "{$noteType}s";
$method = 'get' . $noteTypePlural;
$partName = "{$noteType}s";
$method = 'get' . $partName;
$collection = $this->phpWord->$method();
// Add footnotes media files, relations, and contents
@ -202,12 +222,12 @@ class Word2007 extends AbstractWriter implements WriterInterface
$this->addFilesToPackage($objZip, $media);
$this->registerContentTypes($media);
if (!empty($media)) {
$objZip->addFromString("word/_rels/{$noteTypePlural}.xml.rels", $this->getWriterPart('rels')->writeMediaRels($media));
$objZip->addFromString("word/_rels/{$partName}.xml.rels", $this->getWriterPart('rels')->writeMediaRels($media));
}
$elements = $collection->getItems();
$objZip->addFromString("word/{$noteTypePlural}.xml", $this->getWriterPart($noteTypePlural)->write($elements));
$this->cTypes['override']["/word/{$noteTypePlural}.xml"] = $noteTypePlural;
$this->docRels[] = array('target' => "{$noteTypePlural}.xml", 'type' => $noteTypePlural, 'rID' => ++$rId);
$objZip->addFromString("word/{$partName}.xml", $this->getWriterPart($partName)->write($elements));
$this->contentTypes['override']["/word/{$partName}.xml"] = $partName;
$this->relationships[] = array('target' => "{$partName}.xml", 'type' => $partName, 'rID' => ++$rId);
}
}
@ -222,12 +242,12 @@ class Word2007 extends AbstractWriter implements WriterInterface
$mediumType = $medium['type'];
if ($mediumType == 'image') {
$extension = $medium['imageExtension'];
if (!array_key_exists($extension, $this->cTypes['default'])) {
$this->cTypes['default'][$extension] = $medium['imageType'];
if (!array_key_exists($extension, $this->contentTypes['default'])) {
$this->contentTypes['default'][$extension] = $medium['imageType'];
}
} elseif ($mediumType == 'object') {
if (!array_key_exists('bin', $this->cTypes['default'])) {
$this->cTypes['default']['bin'] = 'application/vnd.openxmlformats-officedocument.oleObject';
if (!array_key_exists('bin', $this->contentTypes['default'])) {
$this->contentTypes['default']['bin'] = 'application/vnd.openxmlformats-officedocument.oleObject';
}
}
}

View File

@ -27,11 +27,11 @@ class ContentTypes extends AbstractPart
{
/**
* Write [Content_Types].xml
*
* @param array $contentTypes
*/
public function writeContentTypes($contentTypes)
public function write()
{
$contentTypes = $this->parentWriter->getContentTypes();
$openXMLPrefix = 'application/vnd.openxmlformats-';
$wordMLPrefix = $openXMLPrefix . 'officedocument.wordprocessingml.';
$overrides = array(
@ -90,4 +90,17 @@ class ContentTypes extends AbstractPart
}
}
}
/**
* Write [Content_Types].xml
*
* @param array $contentTypes
* @deprecated 0.11.0
* @codeCoverageIgnore
*/
public function writeContentTypes($contentTypes)
{
$contentTypes = null; // dummy assignment
return $this->write();
}
}

View File

@ -0,0 +1,54 @@
<?php
/**
* This file is part of PHPWord - A pure PHP library for reading and writing
* word processing documents.
*
* PHPWord is free software distributed under the terms of the GNU Lesser
* General Public License version 3 as published by the Free Software Foundation.
*
* For the full copyright and license information, please read the LICENSE
* file that was distributed with this source code. For the full list of
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
*
* @link https://github.com/PHPOffice/PHPWord
* @copyright 2010-2014 PHPWord contributors
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
*/
namespace PhpOffice\PhpWord\Writer\Word2007\Part;
use PhpOffice\PhpWord\Exception\Exception;
use PhpOffice\PhpWord\PhpWord;
/**
* Word2007 extended document properties part writer
*
* @since 0.11.0
*/
class DocPropsApp extends AbstractPart
{
/**
* Write docProps/app.xml
*/
public function write()
{
$phpWord = $this->parentWriter->getPhpWord();
if (is_null($phpWord)) {
throw new Exception('No PhpWord assigned.');
}
$xmlWriter = $this->getXmlWriter();
$xmlWriter->startDocument('1.0', 'UTF-8', 'yes');
$xmlWriter->startElement('Properties');
$xmlWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/officeDocument/2006/extended-properties');
$xmlWriter->writeAttribute('xmlns:vt', 'http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes');
$xmlWriter->writeElement('Application', 'PHPWord');
$xmlWriter->writeElement('Company', $phpWord->getDocumentProperties()->getCompany());
$xmlWriter->writeElement('Manager', $phpWord->getDocumentProperties()->getManager());
$xmlWriter->endElement(); // Properties
return $xmlWriter->getData();
}
}

View File

@ -21,44 +21,20 @@ use PhpOffice\PhpWord\Exception\Exception;
use PhpOffice\PhpWord\PhpWord;
/**
* Word2007 document properties part writer
* Word2007 core document properties part writer
*
* @since 0.11.0
*/
class DocProps extends AbstractPart
class DocPropsCore extends AbstractPart
{
/**
* Write docProps/app.xml
*/
public function writeDocPropsApp(PhpWord $phpWord = null)
{
if (is_null($phpWord)) {
throw new Exception("No PhpWord assigned.");
}
$xmlWriter = $this->getXmlWriter();
$xmlWriter->startDocument('1.0', 'UTF-8', 'yes');
$xmlWriter->startElement('Properties');
$xmlWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/officeDocument/2006/extended-properties');
$xmlWriter->writeAttribute('xmlns:vt', 'http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes');
$xmlWriter->writeElement('Application', 'PHPWord');
$xmlWriter->writeElement('Company', $phpWord->getDocumentProperties()->getCompany());
$xmlWriter->writeElement('Manager', $phpWord->getDocumentProperties()->getManager());
$xmlWriter->endElement(); // Properties
return $xmlWriter->getData();
}
/**
* Write docProps/core.xml
*
* @param \PhpOffice\PhpWord\PhpWord $phpWord
*/
public function writeDocPropsCore(PhpWord $phpWord = null)
public function write()
{
$phpWord = $this->parentWriter->getPhpWord();
if (is_null($phpWord)) {
throw new Exception("No PhpWord assigned.");
throw new Exception('No PhpWord assigned.');
}
$xmlWriter = $this->getXmlWriter();

View File

@ -31,14 +31,14 @@ class Document extends AbstractPart
/**
* Write word/document.xml
*
* @param \PhpOffice\PhpWord\PhpWord $phpWord
* @return string
* @throws \PhpOffice\PhpWord\Exception\Exception
*/
public function writeDocument(PhpWord $phpWord = null)
public function write()
{
$phpWord = $this->parentWriter->getPhpWord();
if (is_null($phpWord)) {
throw new Exception("No PhpWord assigned.");
throw new Exception('No PhpWord assigned.');
}
$xmlWriter = $this->getXmlWriter();
$sections = $phpWord->getSections();
@ -133,4 +133,17 @@ class Document extends AbstractPart
$xmlWriter->endElement(); // w:sectPr
}
/**
* Write word/document.xml
*
* @param \PhpOffice\PhpWord\PhpWord $phpWord
* @deprecated 0.11.0
* @codeCoverageIgnore
*/
public function writeDocument(PhpWord $phpWord = null)
{
$this->parentWriter->setPhpWord($phpWord);
return $this->write();
}
}

View File

@ -29,7 +29,7 @@ class Numbering extends AbstractPart
/**
* Write word/numbering.xml
*/
public function writeNumbering()
public function write()
{
$styles = Style::getStyles();
@ -66,12 +66,6 @@ class Numbering extends AbstractPart
if (is_array($levels)) {
foreach ($levels as $levelNum => $levelObject) {
if ($levelObject instanceof NumberingLevel) {
$start = $levelObject->getStart();
$format = $levelObject->getFormat();
$restart = $levelObject->getRestart();
$suffix = $levelObject->getSuffix();
$text = $levelObject->getText();
$align = $levelObject->getAlign();
$tabPos = $levelObject->getTabPos();
$left = $levelObject->getLeft();
$hanging = $levelObject->getHanging();
@ -81,36 +75,25 @@ class Numbering extends AbstractPart
$xmlWriter->startElement('w:lvl');
$xmlWriter->writeAttribute('w:ilvl', $levelNum);
if (!is_null($start)) {
$xmlWriter->startElement('w:start');
$xmlWriter->writeAttribute('w:val', $start);
$xmlWriter->endElement(); // w:start
}
if (!is_null($format)) {
$xmlWriter->startElement('w:numFmt');
$xmlWriter->writeAttribute('w:val', $format);
$xmlWriter->endElement(); // w:numFmt
}
if (!is_null($restart)) {
$xmlWriter->startElement('w:lvlRestart');
$xmlWriter->writeAttribute('w:val', $restart);
$xmlWriter->endElement(); // w:lvlRestart
}
if (!is_null($suffix)) {
$xmlWriter->startElement('w:suff');
$xmlWriter->writeAttribute('w:val', $suffix);
$xmlWriter->endElement(); // w:suff
}
if (!is_null($text)) {
$xmlWriter->startElement('w:lvlText');
$xmlWriter->writeAttribute('w:val', $text);
$xmlWriter->endElement(); // w:start
}
if (!is_null($align)) {
$xmlWriter->startElement('w:lvlJc');
$xmlWriter->writeAttribute('w:val', $align);
$xmlWriter->endElement(); // w:lvlJc
// Numbering level properties
$properties = array(
'start' => 'start',
'format' => 'numFmt',
'restart' => 'lvlRestart',
'suffix' => 'suff',
'text' => 'lvlText',
'align' => 'lvlJc'
);
foreach ($properties as $property => $nodeName) {
$getMethod = "get{$property}";
if (!is_null($levelObject->$getMethod())) {
$xmlWriter->startElement("w:{$nodeName}");
$xmlWriter->writeAttribute('w:val', $levelObject->$getMethod());
$xmlWriter->endElement(); // w:start
}
}
// Paragraph styles
if (!is_null($tabPos) || !is_null($left) || !is_null($hanging)) {
$xmlWriter->startElement('w:pPr');
if (!is_null($tabPos)) {
@ -133,6 +116,8 @@ class Numbering extends AbstractPart
}
$xmlWriter->endElement(); // w:pPr
}
// Font styles
if (!is_null($font) || !is_null($hint)) {
$xmlWriter->startElement('w:rPr');
$xmlWriter->startElement('w:rFonts');
@ -182,4 +167,15 @@ class Numbering extends AbstractPart
{
return strtoupper(substr(md5(rand()), 0, $length));
}
/**
* Write numbering
*
* @deprecated 0.11.0
* @codeCoverageIgnore
*/
public function writeNumbering()
{
return $this->write();
}
}

View File

@ -32,43 +32,6 @@ class Rels extends AbstractPart
*/
const RELS_BASE = 'http://schemas.openxmlformats.org/';
/**
* Write _rels/.rels
*/
public function writeMainRels()
{
$xmlRels = array(
'docProps/core.xml' => 'package/2006/relationships/metadata/core-properties',
'docProps/app.xml' => 'officeDocument/2006/relationships/extended-properties',
'word/document.xml' => 'officeDocument/2006/relationships/officeDocument',
);
$xmlWriter = $this->getXmlWriter();
$this->writeRels($xmlWriter, $xmlRels);
return $xmlWriter->getData();
}
/**
* Write word/_rels/document.xml.rels
*
* @param array $mediaRels
*/
public function writeDocRels($mediaRels)
{
$xmlRels = array(
'styles.xml' => 'officeDocument/2006/relationships/styles',
'numbering.xml' => 'officeDocument/2006/relationships/numbering',
'settings.xml' => 'officeDocument/2006/relationships/settings',
'theme/theme1.xml' => 'officeDocument/2006/relationships/theme',
'webSettings.xml' => 'officeDocument/2006/relationships/webSettings',
'fontTable.xml' => 'officeDocument/2006/relationships/fontTable',
);
$xmlWriter = $this->getXmlWriter();
$this->writeRels($xmlWriter, $xmlRels, $mediaRels);
return $xmlWriter->getData();
}
/**
* Write word/_rels/(header|footer|footnotes)*.xml.rels
*
@ -90,7 +53,7 @@ class Rels extends AbstractPart
* @param null|array $mediaRels
* @param integer $relId
*/
private function writeRels(XMLWriter $xmlWriter, $xmlRels = null, $mediaRels = null, $relId = 1)
protected function writeRels(XMLWriter $xmlWriter, $xmlRels = null, $mediaRels = null, $relId = 1)
{
$xmlWriter->startDocument('1.0', 'UTF-8', 'yes');
$xmlWriter->startElement('Relationships');

View File

@ -0,0 +1,47 @@
<?php
/**
* This file is part of PHPWord - A pure PHP library for reading and writing
* word processing documents.
*
* PHPWord is free software distributed under the terms of the GNU Lesser
* General Public License version 3 as published by the Free Software Foundation.
*
* For the full copyright and license information, please read the LICENSE
* file that was distributed with this source code. For the full list of
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
*
* @link https://github.com/PHPOffice/PHPWord
* @copyright 2010-2014 PHPWord contributors
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
*/
namespace PhpOffice\PhpWord\Writer\Word2007\Part;
use PhpOffice\PhpWord\Shared\XMLWriter;
/**
* Word2007 document relationship writer
*
* @since 0.11.0
*/
class RelsDocument extends Rels
{
/**
* Write _rels/.rels
*/
public function write()
{
$xmlRels = array(
'styles.xml' => 'officeDocument/2006/relationships/styles',
'numbering.xml' => 'officeDocument/2006/relationships/numbering',
'settings.xml' => 'officeDocument/2006/relationships/settings',
'theme/theme1.xml' => 'officeDocument/2006/relationships/theme',
'webSettings.xml' => 'officeDocument/2006/relationships/webSettings',
'fontTable.xml' => 'officeDocument/2006/relationships/fontTable',
);
$xmlWriter = $this->getXmlWriter();
$this->writeRels($xmlWriter, $xmlRels, $this->parentWriter->getRelationships());
return $xmlWriter->getData();
}
}

View File

@ -0,0 +1,44 @@
<?php
/**
* This file is part of PHPWord - A pure PHP library for reading and writing
* word processing documents.
*
* PHPWord is free software distributed under the terms of the GNU Lesser
* General Public License version 3 as published by the Free Software Foundation.
*
* For the full copyright and license information, please read the LICENSE
* file that was distributed with this source code. For the full list of
* contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
*
* @link https://github.com/PHPOffice/PHPWord
* @copyright 2010-2014 PHPWord contributors
* @license http://www.gnu.org/licenses/lgpl.txt LGPL version 3
*/
namespace PhpOffice\PhpWord\Writer\Word2007\Part;
use PhpOffice\PhpWord\Shared\XMLWriter;
/**
* Word2007 main relationship writer
*
* @since 0.11.0
*/
class RelsMain extends Rels
{
/**
* Write _rels/.rels
*/
public function write()
{
$xmlRels = array(
'docProps/core.xml' => 'package/2006/relationships/metadata/core-properties',
'docProps/app.xml' => 'officeDocument/2006/relationships/extended-properties',
'word/document.xml' => 'officeDocument/2006/relationships/officeDocument',
);
$xmlWriter = $this->getXmlWriter();
$this->writeRels($xmlWriter, $xmlRels);
return $xmlWriter->getData();
}
}

View File

@ -25,7 +25,7 @@ class Settings extends AbstractPart
/**
* Write word/settings.xml
*/
public function writeSettings()
public function write()
{
$settings = array(
'w:zoom' => array('@attributes' => array('w:percent' => '100')),
@ -136,4 +136,15 @@ class Settings extends AbstractPart
$xmlWriter->endElement();
}
}
/**
* Write word/settings.xml
*
* @deprecated 0.11.0
* @codeCoverageIgnore
*/
public function writeSettings()
{
return $this->write();
}
}

View File

@ -38,12 +38,13 @@ class Styles extends AbstractPart
/**
* Write word/styles.xml
*
* @param \PhpOffice\PhpWord\PhpWord $phpWord
* @return string
*/
public function writeStyles(PhpWord $phpWord = null)
public function write()
{
$phpWord = $this->parentWriter->getPhpWord();
if (is_null($phpWord)) {
throw new Exception("No PhpWord assigned.");
throw new Exception('No PhpWord assigned.');
}
$xmlWriter = $this->getXmlWriter();
@ -219,4 +220,17 @@ class Styles extends AbstractPart
$xmlWriter->endElement(); // w:style
}
}
/**
* Write word/styles.xml
*
* @param \PhpOffice\PhpWord\PhpWord $phpWord
* @deprecated 0.11.0
* @codeCoverageIgnore
*/
public function writeStyles(PhpWord $phpWord = null)
{
$this->parentWriter->setPhpWord($phpWord);
return $this->write();
}
}

View File

@ -25,7 +25,7 @@ class WebSettings extends Settings
/**
* Write word/webSettings.xml
*/
public function writeWebSettings()
public function write()
{
$settings = array(
'w:optimizeForBrowser' => '',
@ -46,4 +46,15 @@ class WebSettings extends Settings
return $xmlWriter->getData();
}
/**
* Write word/webSettings.xml
*
* @deprecated 0.11.0
* @codeCoverageIgnore
*/
public function writeWebSettings()
{
return $this->write();
}
}