blob: c1669ba9adee6ccc169a11a3a47a24f9aefa3114 [file] [log] [blame]
<?php
/**
* File containing the ezcDocumentDocbookToOdtConverter class.
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package Document
* @version //autogen//
* @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
*/
/**
* Converter for docbook to ODT with a PHP callback based mechanism, for fast
* and easy PHP based extensible transformations.
*
* This converter does not support the full docbook standard, but only a subset
* commonly used in the document component.
*
* @package Document
* @version //autogen//
*/
class ezcDocumentDocbookToOdtConverter extends ezcDocumentElementVisitorConverter
{
/**
* Text node processor.
*
* @var ezcDocumentOdtTextProcessor
*/
protected $textProcessor;
/**
* Stores the base dir to be used during a conversion process.
*
* This is either the base dir of the document converted, if set, or the
* current working dir, if a document from string is processed.
*
* @var string
*/
private $docBaseDir;
/**
* Image locator object.
*
* Updated on each conversion.
*
* @var ezcDocumentOdtImageLocator
*/
private $imageLocator;
/**
* Meta data generator.
*
* @var ezcDocumentOdtMetaGenerator
*/
private $metaGenerator;
/**
* Construct converter
*
* Construct converter from XSLT file, which is used for the actual
*
* @param ezcDocumentDocbookToOdtConverterOptions $options
* @return void
*/
public function __construct( ezcDocumentDocbookToOdtConverterOptions $options = null )
{
parent::__construct(
$options === null ?
new ezcDocumentDocbookToOdtConverterOptions() :
$options
);
$this->textProcessor = new ezcDocumentOdtTextProcessor();
$this->metaGenerator = new ezcDocumentOdtMetaGenerator();
$styler = $this->options->styler;
// Initlize common element handlers
$this->visitorElementHandler = array(
'docbook' => array(
'article' => $ignore = new ezcDocumentDocbookToOdtIgnoreHandler( $styler ),
'book' => $ignore,
'section' => $section = new ezcDocumentDocbookToOdtSectionHandler( $styler ),
// @todo: Need to find a way to handle the meta data.
'sectioninfo' => $section,
'title' => $section,
'para' => $paragraph = new ezcDocumentDocbookToOdtParagraphHandler( $styler ),
'emphasis' => $inline = new ezcDocumentDocbookToOdtInlineHandler( $styler ),
'literal' => $inline,
'ulink' => new ezcDocumentDocbookToOdtUlinkHandler( $styler ),
'link' => new ezcDocumentDocbookToOdtLinkHandler( $styler ),
'anchor' => new ezcDocumentDocbookToOdtAnchorHandler( $styler ),
'inlinemediaobject' => $media = new ezcDocumentDocbookToOdtMediaObjectHandler( $styler ),
'mediaobject' => $media,
'itemizedlist' => $list = new ezcDocumentDocbookToOdtListHandler( $styler ),
'orderedlist' => $list,
'listitem' => $mapper = new ezcDocumentDocbookToOdtMappingHandler( $styler ),
'note' => $paragraph,
'tip' => $paragraph,
'warning' => $paragraph,
'important' => $paragraph,
'caution' => $paragraph,
'literallayout' => new ezcDocumentDocbookToOdtLiteralLayoutHandler( $styler ),
'footnote' => new ezcDocumentDocbookToOdtFootnoteHandler( $styler ),
'comment' => new ezcDocumentDocbookToOdtCommentHandler( $styler ),
'beginpage' => new ezcDocumentDocbookToOdtPageBreakHandler( $styler ),
'entry' => $table = new ezcDocumentDocbookToOdtTableHandler( $styler ),
'table' => $table,
'tbody' => $table,
'thead' => $table,
'caption' => $table,
'tr' => $table,
'td' => $table,
'row' => $table,
'tgroup' => $ignore,
// @todo: Need to handle these in a way
'blockquote' => $ignore,
'attribution' => $ignore,
'variablelist' => $deepIgnore = new ezcDocumentDocbookToOdtIgnoreHandler( $styler, true ),
'varlistentry' => $deepIgnore,
)
);
}
/**
* Converts the given DocBook $source to an ODT document.
*
* This method receives a DocBook $source document and returns the
* converters ODT document.
*
* @param ezcDocumentDocbook $source
* @return ezcDocumentOdt
*/
public function convert( $source )
{
$destination = $this->initializeDocument();
$docBookDom = $this->makeLocateable( $source->getDomDocument() );
$this->options->styler->init( $destination->ownerDocument );
$this->imageLocator = new ezcDocumentOdtImageLocator( $source );
$destination = $this->visitChildren(
$docBookDom,
$destination
);
return $this->createDocument( $destination );
}
/**
* Returns the image locator for the current conversion.
*
* @return ezcDocumentOdtImageLocator
* @access private
*/
public function getImageLocator()
{
return $this->imageLocator;
}
/**
* Reloads the DOMDocument of the given DocBook to make its elements
* locateable.
*
* @param DOMDocument $docBook
* @return DOMDocument
*/
private function makeLocateable( DOMDocument $docBook )
{
// Reload the XML document to a DOMDocument with a custom element
// class. Just registering it on the existing document seems not to
// work in all cases.
$reloaded = new DOMDocument();
$reloaded->registerNodeClass( 'DOMElement', 'ezcDocumentLocateableDomElement' );
$reloaded->loadXml( $docBook->saveXml() );
return $reloaded;
}
/**
* Initialize destination document
*
* Initialize the structure which the destination document could be build
* with. This may be an initial DOMDocument with some default elements, or
* a string, or something else.
*
* @return mixed
*/
protected function initializeDocument()
{
$odt = new DOMDocument();
$odt->preserveWhiteSpace = false;
$odt->formatOutput = true;
$odt->load( $this->options->template );
$this->generateMetaData( $odt );
$rootElements = $odt->getElementsByTagNameNS(
ezcDocumentOdt::NS_ODT_OFFICE,
'text'
);
if ( $rootElements->length !== 1 )
{
throw new ezcDocumentInvalidOdtException(
$rootElements,
"Broken ODT template '{$this->options->template}'. Missing or duplicate body element."
);
}
$root = $rootElements->item( 0 );
return $root;
}
/**
* Generates standard ODT meta data into the given $odt.
*
* Extracts the <office:meta/> element from the given $odt or creates a new
* one, if it does not exsist, and generates standard meta data into it.
*
* @param DOMDocument $odt
*/
private function generateMetaData( DOMDocument $odt )
{
$metaSections = $odt->getElementsByTagnameNS(
ezcDocumentOdt::NS_ODT_OFFICE,
'meta'
);
if ( $metaSections->length === 0 )
{
$metaSection = $odt->documentElement->appendChild(
$odt->createElementNS(
ezcDocumentOdt::NS_ODT_OFFICE,
'meta'
)
);
}
else
{
$metaSection = $metaSections->item( 0 );
}
$this->metaGenerator->generateMetaData( $metaSection );
}
/**
* Create document from structure
*
* Build a ezcDocumentDocument object from the structure created during the
* visiting process.
*
* @param mixed $content
* @return ezcDocumentDocument
*/
protected function createDocument( $content )
{
$document = $content->ownerDocument;
$odt = new ezcDocumentOdt();
$odt->setDomDocument( $document );
return $odt;
}
/**
* Visit text node.
*
* Visit a text node in the source document and transform it to the
* destination result
*
* @param DOMText $node
* @param mixed $root
* @return mixed
*/
protected function visitText( DOMText $node, $root )
{
$resNodes = $this->textProcessor->processText( $node, $root );
foreach ( $resNodes as $resNode )
{
$root->appendChild( $resNode );
}
return $root;
}
}
?>