add contents

This commit is contained in:
Trevor Batley
2025-10-09 15:04:29 +11:00
parent 170362eec1
commit bce7dd054a
2537 changed files with 301282 additions and 0 deletions

View File

@@ -0,0 +1,208 @@
<?php
/**
* ODTMasterPageStyle: class for ODT text list styles.
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author LarsDW223
*/
require_once DOKU_INC.'lib/plugins/odt/ODT/XMLUtil.php';
require_once DOKU_INC.'lib/plugins/odt/ODT/styles/ODTStyle.php';
/**
* The ODTMasterPageStyle class
*/
class ODTMasterPageStyle extends ODTStyle
{
static $master_fields = array(
// Fields belonging to "style:master-page"
'style-name' => array ('style:name', 'style', false),
'style-display-name' => array ('style:display-name', 'style', false),
'style-page-layout-name' => array ('style:page-layout-name', 'style', false),
'draw-style-name' => array ('draw:style-name', 'style', false),
'style-next' => array ('style:next-style-name', 'style', true),
);
static $header_footer_fields = array(
// Fields belonging to "style:header", "style:footer",
// "style:header-left" and "style:footer-left"
// The content/child-elements of "style:header" are saved as is
'style-display' => array ('style:display', 'header', true),
);
protected $master_style = array();
protected $style_header = array();
protected $style_footer = array();
protected $style_header_left = array();
protected $style_footer_left = array();
protected $content_header = NULL;
protected $content_footer = NULL;
protected $content_header_left = NULL;
protected $content_footer_left = NULL;
/**
* Get the element name for the ODT XML encoding of the style.
*/
public function getElementName() {
return 'style:master-page';
}
/**
* Set style properties by importing values from a properties array.
* Properties might be disabled by setting them in $disabled.
* The style must have been previously created.
*
* @param $properties Properties to be imported
* @param $disabled Properties to be ignored
*/
public function importProperties($properties, $disabled=array()) {
$this->importPropertiesInternal(self::$master_fields, $properties, $disabled, $this->master_style);
}
/**
* Check if a style is a common style.
*
* @return bool Is common style
*/
public function mustBeCommonStyle() {
return false;
}
/**
* Set a property.
*
* @param $property The name of the property to set
* @param $value New value to set
*/
public function setProperty($property, $value) {
if (array_key_exists ($property, self::$master_fields)) {
$this->setPropertyInternal
($property, self::$master_fields [$property][0], $value, self::$master_fields [$property][1], $this->master_style);
return;
}
}
/**
* Get the value of a property.
*
* @param $property The property name
* @return string The current value of the property
*/
public function getProperty($property) {
if (array_key_exists ($property, self::$master_fields)) {
return $this->master_style [$property]['value'];
}
return NULL;
}
/**
* Create new style by importing ODT style definition.
*
* @param $xmlCode Style definition in ODT XML format
* @return ODTStyle New specific style
*/
static public function importODTStyle($xmlCode) {
$style = new ODTMasterPageStyle();
// Get attributes for element 'style:master-page'
$open = XMLUtil::getElementOpenTag('style:master-page', $xmlCode);
if (!empty($open)) {
$style->importODTStyleInternal(self::$master_fields, $open, $style->master_style);
}
// Get attributes for element 'style:header'
$open = XMLUtil::getElementOpenTag('style:header', $xmlCode);
if (!empty($open)) {
$style->importODTStyleInternal(self::$header_footer_fields, $open, $style->style_header);
$content_header = XMLUtil::getElementContent ('style:header', $xmlCode);
}
// Get attributes for element 'style:footer'
$open = XMLUtil::getElementOpenTag('style:footer', $xmlCode);
if (!empty($open)) {
$style->importODTStyleInternal(self::$header_footer_fields, $open, $style->style_footer);
$content_footer = XMLUtil::getElementContent ('style:footer', $xmlCode);
}
// Get attributes for element 'style:header-left'
$open = XMLUtil::getElementOpenTag('style:header-left', $xmlCode);
if (!empty($open)) {
$style->importODTStyleInternal(self::$header_footer_fields, $open, $style->style_header_left);
$content_header_left = XMLUtil::getElementContent ('style:header-left', $xmlCode);
}
// Get attributes for element 'style:footer-left'
$open = XMLUtil::getElementOpenTag('style:footer-left', $xmlCode);
if (!empty($open)) {
$style->importODTStyleInternal(self::$header_footer_fields, $open, $style->style_footer_left);
$content_footer_left = XMLUtil::getElementContent ('style:footer-left', $xmlCode);
}
return $style;
}
/**
* Encode current style values in a string and return it.
*
* @return string ODT XML encoded style
*/
public function toString() {
$style = '';
$master = '';
$header = '';
$footer = '';
$header_left = '';
$footer_left = '';
// Get master style ODT properties
foreach ($this->master_style as $property => $items) {
$master .= $items ['odt_property'].'="'.$items ['value'].'" ';
}
// Get header ODT properties
foreach ($this->style_header as $property => $items) {
$header .= $items ['odt_property'].'="'.$items ['value'].'" ';
}
// Get footer ODT properties
foreach ($this->style_footer as $property => $items) {
$footer .= $items ['odt_property'].'="'.$items ['value'].'" ';
}
// Get header-left ODT properties
foreach ($this->style_header_left as $property => $items) {
$header_left .= $items ['odt_property'].'="'.$items ['value'].'" ';
}
// Get footer-left ODT properties
foreach ($this->style_footer_left as $property => $items) {
$footer_left .= $items ['odt_property'].'="'.$items ['value'].'" ';
}
// Build style.
$style = '<style:master-page '.$master.">\n";
if ( !empty($header) || !empty($content_header) ) {
$style .= '<style:header '.$header.">\n";
$style .= $content_header;
$style .= '</style:header>'."\n";
}
if ( !empty($footer) || !empty($content_footer) ) {
$style .= '<style:footer '.$footer.">\n";
$style .= $content_footer;
$style .= '</style:footer>'."\n";
}
if ( !empty($header_left) || !empty($content_header_left) ) {
$style .= '<style:header-left '.$header_left.">\n";
$style .= $content_header_left;
$style .= '</style:header-left>'."\n";
}
if ( !empty($footer_left) || !empty($content_footer_left) ) {
$style .= '<style:footer-left '.$footer_left.">\n";
$style .= $content_footer_left;
$style .= '</style:footer-left>'."\n";
}
$style .= '</style:master-page'.">\n";
return $style;
}
}

View File

@@ -0,0 +1,363 @@
<?php
/**
* ODTPageLayoutStyle: class for ODT page layout styles.
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author LarsDW223
*/
require_once DOKU_INC.'lib/plugins/odt/ODT/XMLUtil.php';
require_once DOKU_INC.'lib/plugins/odt/ODT/styles/ODTStyle.php';
/**
* The ODTPageLayoutStyle class
*/
class ODTPageLayoutStyle extends ODTStyle
{
static $page_layout_fields = array(
// Fields belonging to "style:master-page"
'style-name' => array ('style:name', 'style', false),
'style-page-usage' => array ('style:page-usage', 'style', false),
);
static $layout_props_fields = array(
// Fields belonging to "style:page-layout-properties"
'width' => array ('fo:page-width', 'props', true),
'height' => array ('fo:page-height', 'props', true),
'num-format' => array ('style:num-format', 'props', true),
'num-letter-sync' => array ('style:num-letter-sync', 'props', true),
'num-prefix' => array ('style:num-prefix', 'props', true),
'num-suffix' => array ('style:num-suffix', 'props', true),
'paper-tray-name' => array ('style:paper-tray-name', 'props', true),
'print-orientation' => array ('style:print-orientation', 'props', true),
'margin-left' => array ('fo:margin-left', 'props', true),
'margin-right' => array ('fo:margin-right', 'props', true),
'margin-top' => array ('fo:margin-top', 'props', true),
'margin-bottom' => array ('fo:margin-bottom', 'props', true),
'margin' => array ('fo:margin', 'props', true),
'border' => array ('fo:border', 'props', true),
'border-top' => array ('fo:border-top', 'props', true),
'border-right' => array ('fo:border-right', 'props', true),
'border-bottom' => array ('fo:border-bottom', 'props', true),
'border-left' => array ('fo:border-left', 'props', true),
'border-line-width' => array ('style:border-line-width', 'props', true),
'border-line-width-top' => array ('style:border-line-width-top', 'props', true),
'border-line-width-bottom' => array ('style:border-line-width-bottom', 'props', true),
'border-line-width-left' => array ('style:border-line-width-left', 'props', true),
'border-line-width-right' => array ('style:border-line-width-right', 'props', true),
'padding' => array ('fo:padding', 'props', true),
'padding-top' => array ('fo:padding-top', 'props', true),
'padding-bottom' => array ('fo:padding-bottom', 'props', true),
'padding-left' => array ('fo:padding-left', 'props', true),
'padding-right' => array ('fo:padding-right', 'props', true),
'shadow' => array ('style:shadow', 'props', true),
'background-color' => array ('fo:background-color', 'props', true),
'register-truth-ref-style-name' => array ('style:register-truth-ref-style-name', 'props', true),
'print' => array ('style:print', 'props', true),
'print-page-order' => array ('style:print-page-order', 'props', true),
'first-page-number' => array ('style:first-page-number', 'props', true),
'scale-to' => array ('style:scale-to', 'props', true),
'scale-to-pages' => array ('style:scale-to-pages', 'props', true),
'table-centering' => array ('style:table-centering', 'props', true),
'footnote-max-height' => array ('style:footnote-max-height', 'props', true),
'writing-mode' => array ('style:writing-mode', 'props', true),
'layout-grid-mode' => array ('style:layout-grid-mode', 'props', true),
'layout-grid-standard-mode' => array ('style:layout-grid-standard-mode', 'props', true),
'layout-grid-base-height' => array ('style:layout-grid-base-height', 'props', true),
'layout-grid-ruby-height' => array ('style:layout-grid-ruby-height', 'props', true),
'layout-grid-lines' => array ('style:layout-grid-lines', 'props', true),
'layout-grid-base-width' => array ('style:layout-grid-base-width', 'props', true),
'layout-grid-color' => array ('style:layout-grid-color', 'props', true),
'layout-grid-ruby-below' => array ('style:layout-grid-ruby-below', 'props', true),
'layout-grid-print' => array ('style:layout-grid-print', 'props', true),
'layout-grid-display' => array ('style:layout-grid-display', 'props', true),
'layout-grid-snap-to' => array ('style:layout-grid-snap-to', 'props', true),
);
static $bgi_fields = array(
// Fields belonging to "style:background-image"
// The content of element "style:background-image" will be saved as is
'repeat' => array ('style:repeat', 'bgi', true),
'position' => array ('style:position', 'bgi', true),
'filter-name' => array ('style:filter-name', 'bgi', true),
'opacity' => array ('draw:opacity', 'bgi', true),
'xlink-type' => array ('xlink:type', 'bgi', true),
'xlink-href' => array ('xlink:href', 'bgi', true),
'xlink-show' => array ('xlink:show', 'bgi', true),
'xlink-actuate' => array ('xlink:actuate', 'bgi', true),
);
static $columns_fields = array(
// Fields belonging to "style:columns"
// The content of element "style:columns" will be saved as is
'column-count' => array ('fo:column-count', 'columns', true),
'column-gap' => array ('fo:column-gap', 'columns', true),
'column-gap' => array ('fo:column-gap', 'columns', true),
);
static $footnote_fields = array(
// Fields belonging to "style:footnote-sep"
'ftsep-width' => array ('style:width', 'ftsep', true),
'ftsep-rel-width' => array ('style:rel-width', 'ftsep', true),
'ftsep-color' => array ('style:color', 'ftsep', true),
'ftsep-line-style' => array ('style:line-style', 'ftsep', true),
'ftsep-adjustment' => array ('style:adjustment', 'ftsep', true),
'ftsep-distance-before-sep' => array ('style:distance-before-sep', 'ftsep', true),
'ftsep-distance-after-sep' => array ('style:distance-after-sep', 'ftsep', true),
);
protected $page_layout_style = array();
protected $layout_props = array();
protected $bgi_props = array();
protected $columns_props = array();
protected $footnote_props = array();
protected $content_bgi = NULL;
protected $content_columns = NULL;
protected $content_header = NULL;
protected $content_footer = NULL;
/**
* Get the element name for the ODT XML encoding of the style.
*/
public function getElementName() {
return 'style:page-layout';
}
/**
* Set style properties by importing values from a properties array.
* Properties might be disabled by setting them in $disabled.
* The style must have been previously created.
*
* @param $properties Properties to be imported
* @param $disabled Properties to be ignored
*/
public function importProperties($properties, $disabled=array()) {
$this->importPropertiesInternal(self::$page_layout_fields, $properties, $disabled, $this->page_layout_style);
$this->importPropertiesInternal(self::$layout_props_fields, $properties, $disabled, $this->layout_props);
$this->importPropertiesInternal(self::$bgi_fields, $properties, $disabled, $this->bgi_props);
$this->importPropertiesInternal(self::$columns_fields, $properties, $disabled, $this->columns_props);
$this->importPropertiesInternal(self::$footnote_props, $properties, $disabled, $this->footnote_fields);
}
/**
* Check if a style is a common style.
*
* @return bool Is common style
*/
public function mustBeCommonStyle() {
return false;
}
/**
* Set a property.
*
* @param $property The name of the property to set
* @param $value New value to set
*/
public function setProperty($property, $value) {
if (array_key_exists ($property, self::$page_layout_fields)) {
$this->setPropertyInternal
($property, self::$page_layout_fields [$property][0], $value, self::$page_layout_fields [$property][1], $this->page_layout_style);
return;
}
if (array_key_exists ($property, self::$layout_props_fields)) {
$this->setPropertyInternal
($property, self::$layout_props_fields [$property][0], $value, self::$layout_props_fields [$property][1], $this->layout_props);
return;
}
if (array_key_exists ($property, self::$bgi_fields)) {
$this->setPropertyInternal
($property, self::$bgi_fields [$property][0], $value, self::$bgi_fields [$property][1], $this->bgi_props);
return;
}
if (array_key_exists ($property, self::$columns_fields)) {
$this->setPropertyInternal
($property, self::$columns_fields [$property][0], $value, self::$columns_fields [$property][1], $this->columns_props);
return;
}
if (array_key_exists ($property, self::$footnote_fields)) {
$this->setPropertyInternal
($property, self::$footnote_fields [$property][0], $value, self::$footnote_fields [$property][1], $this->footnote_props);
return;
}
}
/**
* Get the value of a property.
*
* @param $property The property name
* @return string The current value of the property
*/
public function getProperty($property) {
if (array_key_exists ($property, self::$page_layout_fields)) {
return $this->page_layout_style [$property]['value'];
}
if (array_key_exists ($property, self::$layout_props_fields)) {
return $this->layout_props [$property]['value'];
}
if (array_key_exists ($property, self::$bgi_fields)) {
return $this->bgi_props [$property]['value'];
}
if (array_key_exists ($property, self::$columns_fields)) {
return $this->columns_props [$property]['value'];
}
if (array_key_exists ($property, self::$footnote_fields)) {
return $this->footnote_props [$property]['value'];
}
return NULL;
}
/**
* Create new style by importing ODT style definition.
*
* @param $xmlCode Style definition in ODT XML format
* @return ODTStyle New specific style
*/
static public function importODTStyle($xmlCode) {
$style = new ODTPageLayoutStyle();
// Get attributes for element 'style:master-page'
$open = XMLUtil::getElementOpenTag('style:page-layout', $xmlCode);
if (!empty($open)) {
$style->importODTStyleInternal(self::$page_layout_fields, $open, $style->page_layout_style);
$childs = XMLUtil::getElementContent ('style:page-layout', $xmlCode);
if (!empty($childs)) {
// Get attributes for element 'style:page-layout-properties'
$open = XMLUtil::getElementOpenTag('style:page-layout-properties', $childs);
$style->content_header = XMLUtil::getElement ('style:header-style', $childs);
$style->content_footer = XMLUtil::getElement ('style:footer-style', $childs);
if (!empty($open)) {
$style->importODTStyleInternal(self::$layout_props_fields, $open, $style->layout_props);
$childs = XMLUtil::getElementContent ('style:page-layout-properties', $xmlCode);
if (!empty($childs)) {
// Get 'style:background-image'
$open = XMLUtil::getElementOpenTag('style:background-image', $childs);
if (!empty($open)) {
$style->importODTStyleInternal(self::$bgi_fields, $open, $style->bgi_props);
$style->content_bgi = XMLUtil::getElementContent ('style:background-image', $childs);
}
// Get 'style:columns'
$open = XMLUtil::getElementOpenTag('style:columns', $childs);
if (!empty($open)) {
$style->importODTStyleInternal(self::$columns_fields, $open, $style->columns_props);
$style->content_columns = XMLUtil::getElementContent ('style:columns', $childs);
}
// Get 'style:footnote-sep'
$open = XMLUtil::getElementOpenTag('style:footnote-sep', $childs);
if (!empty($open)) {
$style->importODTStyleInternal(self::$footnote_fields, $open, $style->footnote_props);
}
}
}
}
}
return $style;
}
/**
* Encode current style values in a string and return it.
*
* @return string ODT XML encoded style
*/
public function toString() {
$layout_style = '';
$layout = '';
$bgi = '';
$columns = '';
$footnote = '';
// Get page layout style ODT properties
foreach ($this->page_layout_style as $property => $items) {
$layout_style .= $items ['odt_property'].'="'.$items ['value'].'" ';
}
// Get page layout properties ODT properties
foreach ($this->layout_props as $property => $items) {
$layout .= $items ['odt_property'].'="'.$items ['value'].'" ';
}
// Get background-image ODT properties
foreach ($this->bgi_props as $property => $items) {
$bgi .= $items ['odt_property'].'="'.$items ['value'].'" ';
}
// Get columns ODT properties
foreach ($this->columns_props as $property => $items) {
$columns .= $items ['odt_property'].'="'.$items ['value'].'" ';
}
// Get footnote-sep ODT properties
foreach ($this->footnote_props as $property => $items) {
$footnote .= $items ['odt_property'].'="'.$items ['value'].'" ';
}
// Build style.
$style = '<style:page-layout '.$layout_style.">\n";
if ( !empty($layout) || !empty($bgi) || !empty($columns) || !empty($footnote) ||
!empty($this->content_bgi) || !empty($this->content_columns) ) {
$style .= '<style:page-layout-properties '.$layout.">\n";
if ( !empty($bgi) || !empty($this->content_bgi) ) {
$style .= '<style:background-image '.$bgi.">\n";
$style .= $this->content_bgi;
$style .= '</style:background-image>'."\n";
}
if ( !empty($columns) || !empty($content_columns) ) {
$style .= '<style:columns '.$columns.">\n";
$style .= $this->content_columns;
$style .= '</style:columns>'."\n";
}
if ( !empty($footnote) ) {
$style .= '<style:footnote-sep '.$footnote."/>\n";
}
$style .= '</style:page-layout-properties>'."\n";
}
$style .= $this->content_header;
$style .= $this->content_footer;
$style .= '</style:page-layout'.">\n";
return $style;
}
/**
* This function creates a page layout style with the parameters given in $properies.
*
* The currently supported properties are:
* style-name, width, height, margin-top, margin-bottom, margin-right and margin-left.
* All properties except the style-name are expected to be numeric values.
* The function will add 'cm' itself, so do not add any units.
*
* The function returns the name of the new style or NULL if all relevant properties are empty.
*
* @author LarsDW223
*
* @param $properties
* @param null $disabled_props
* @return ODTUnknownStyle or NULL
*/
public static function createPageLayoutStyle(array $properties, array $disabled_props = NULL) {
// Create style name (if not given).
$style_name = $properties ['style-name'];
if ( empty($style_name) ) {
$style_name = self::getNewStylename ('Page');
$properties ['style-name'] = $style_name;
}
$style = '<style:page-layout style:name="'.$style_name.'">
<style:page-layout-properties fo:page-width="'.$properties ['width'].'cm" fo:page-height="'.$properties ['height'].'cm" style:num-format="1" style:print-orientation="landscape" fo:margin-top="'.$properties ['margin-top'].'cm" fo:margin-bottom="'.$properties ['margin-bottom'].'cm" fo:margin-left="'.$properties ['margin-left'].'cm" fo:margin-right="'.$properties ['margin-right'].'cm" style:writing-mode="lr-tb" style:footnote-max-height="0cm">
<style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.1cm" style:distance-after-sep="0.1cm" style:adjustment="left" style:rel-width="25%" style:color="#000000"/>
</style:page-layout-properties>
<style:header-style/>
<style:footer-style/>
</style:page-layout>';
return self::importODTStyle($style);
}
}

View File

@@ -0,0 +1,497 @@
<?php
/**
* ODTParagraphStyle: class for ODT paragraph styles.
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author LarsDW223
*/
require_once DOKU_PLUGIN.'odt/ODT/XMLUtil.php';
require_once 'ODTStyle.php';
ODTStyleStyle::register('ODTParagraphStyle');
/**
* The ODTParagraphStyle class
*/
class ODTParagraphStyle extends ODTStyleStyle
{
static $paragraph_fields = array(
'line-height' => array ('fo:line-height', 'paragraph', true),
'line-height-at-least' => array ('style:line-height-at-least', 'paragraph', true),
'line-spacing' => array ('style:line-spacing', 'paragraph', true),
'font-independent-line-spacing' => array ('style:font-independent-line-spacing', 'paragraph', true),
'text-align' => array ('fo:text-align', 'paragraph', true),
'text-align-last' => array ('fo:text-align-last', 'paragraph', true),
'justify-single-word' => array ('style:justify-single-word', 'paragraph', true),
'keep-together' => array ('fo:keep-together', 'paragraph', true),
'widows' => array ('fo:widows', 'paragraph', true),
'orphans' => array ('fo:orphans', 'paragraph', true),
'tab-stop-distance' => array ('style:tab-stop-distance', 'paragraph', true),
'hyphenation-keep' => array ('fo:hyphenation-keep', 'paragraph', true),
'hyphenation-ladder-count' => array ('fo:hyphenation-ladder-count', 'paragraph', true),
'register-true' => array ('style:register-true', 'paragraph', true),
'text-indent' => array ('fo:text-indent', 'paragraph', true),
'auto-text-indent' => array ('style:auto-text-indent', 'paragraph', true),
'margin' => array ('fo:margin', 'paragraph', true),
'margin-top' => array ('fo:margin-top', 'paragraph', true),
'margin-right' => array ('fo:margin-right', 'paragraph', true),
'margin-bottom' => array ('fo:margin-bottom', 'paragraph', true),
'margin-left' => array ('fo:margin-left', 'paragraph', true),
'break-before' => array ('fo:break-before', 'paragraph', true),
'break-after' => array ('fo:break-after', 'paragraph', true),
'background-color' => array ('fo:background-color', 'paragraph', true),
'border' => array ('fo:border', 'paragraph', true),
'border-top' => array ('fo:border-top', 'paragraph', true),
'border-right' => array ('fo:border-right', 'paragraph', true),
'border-bottom' => array ('fo:border-bottom', 'paragraph', true),
'border-left' => array ('fo:border-left', 'paragraph', true),
'border-line-width' => array ('style:border-line-width', 'paragraph', true),
'border-line-width-top' => array ('style:border-line-width-top', 'paragraph', true),
'border-line-width-bottom' => array ('style:border-line-width-bottom', 'paragraph', true),
'border-line-width-left' => array ('style:border-line-width-left', 'paragraph', true),
'border-line-width-right' => array ('style:border-line-width-right', 'paragraph', true),
'join-border' => array ('style:join-border', 'paragraph', true),
'padding' => array ('fo:padding', 'paragraph', true),
'padding-top' => array ('fo:padding-top', 'paragraph', true),
'padding-bottom' => array ('fo:padding-bottom', 'paragraph', true),
'padding-left' => array ('fo:padding-left', 'paragraph', true),
'padding-right' => array ('fo:padding-right', 'paragraph', true),
'shadow' => array ('style:shadow', 'paragraph', true),
'keep-with-next' => array ('fo:keep-with-next', 'paragraph', true),
'number-lines' => array ('text:number-lines', 'paragraph', true),
'line-number' => array ('text:line-number', 'paragraph', true),
'text-autospace' => array ('style:text-autospace', 'paragraph', true),
'punctuation-wrap' => array ('style:punctuation-wrap', 'paragraph', true),
'line-break' => array ('style:line-break', 'paragraph', true),
'vertical-align' => array ('style:vertical-align', 'paragraph', true),
'writing-mode' => array ('style:writing-mode', 'paragraph', true),
'writing-mode-automatic' => array ('style:writing-mode-automatic', 'paragraph', true),
'snap-to-layout-grid' => array ('style:snap-to-layout-grid', 'paragraph', true),
'page-number' => array ('style:page-number', 'paragraph', true),
'background-transparency' => array ('style:background-transparency', 'paragraph', true),
);
// Additional fields for child element tab-stop.
static $tab_stop_fields = array(
'style-position' => array ('style:position', 'tab-stop', true),
'style-type' => array ('style:type', 'tab-stop', true),
'style-leader-type' => array ('style:leader-type', 'tab-stop', true),
'style-leader-style' => array ('style:leader-style', 'tab-stop', true),
'style-leader-width' => array ('style:leader-width', 'tab-stop', true),
'style-leader-color' => array ('style:leader-color', 'tab-stop', true),
'style-leader-text' => array ('style:leader-text', 'tab-stop', true),
);
protected $style_properties = array();
protected $text_properties = array();
protected $tab_stops = array();
/**
* Constructor.
*/
public function __construct() {
parent::__construct();
}
/**
* Set style properties by importing values from a properties array.
* Properties might be disabled by setting them in $disabled.
* The style must have been previously created.
*
* @param $properties Properties to be imported
* @param $disabled Properties to be ignored
*/
public function importProperties($properties, $disabled=array()) {
foreach ($properties as $property => $value) {
if ($disabled [$property] == 0) {
$this->setProperty($property, $value);
}
}
}
/**
* Check if a style is a common style.
*
* @return bool Is common style
*/
public function mustBeCommonStyle() {
return false;
}
/**
* Get the style family of a style.
*
* @return string Style family
*/
static public function getFamily() {
return 'paragraph';
}
/**
* Set a property.
*
* @param $property The name of the property to set
* @param $value New value to set
*/
public function setProperty($property, $value) {
$style_fields = ODTStyleStyle::getStyleProperties ();
if (array_key_exists ($property, $style_fields)) {
$this->setPropertyInternal
($property, $style_fields [$property][0], $value, $style_fields [$property][1], $this->style_properties);
return;
}
// FIXME: currently with setProperty there always will only be one tab-stop.
// Maybe in the future supply a function "add tab stop" or something.
if (array_key_exists ($property, self::$tab_stop_fields)) {
if ($this->tab_stops [0] == NULL) {
$this->tab_stops [0] = array();
}
$this->setPropertyInternal
($property, self::$tab_stop_fields [$property][0], $value, self::$tab_stop_fields [$property][1], $this->tab_stops[0]);
return;
}
// Compare with paragraph fields before text fields first!
// So, paragraph properties get precedence.
if (array_key_exists ($property, self::$paragraph_fields)) {
$this->setPropertyInternal
($property, self::$paragraph_fields [$property][0], $value, self::$paragraph_fields [$property][1]);
return;
}
$text_fields = ODTTextStyle::getTextProperties ();
if (array_key_exists ($property, $text_fields)) {
$this->setPropertyInternal
($property, $text_fields [$property][0], $value, $text_fields [$property][1], $this->text_properties);
return;
}
}
/**
* Get the value of a property.
*
* @param $property The property name
* @return string The current value of the property
*/
public function getProperty($property) {
$style_fields = ODTStyleStyle::getStyleProperties ();
if (array_key_exists ($property, $style_fields)) {
return $this->style_properties [$property]['value'];
}
$paragraph_fields = self::$paragraph_fields;
if (array_key_exists ($property, $paragraph_fields)) {
return parent::getProperty($property);
}
$text_fields = ODTTextStyle::getTextProperties ();
if (array_key_exists ($property, $text_fields)) {
return $this->text_properties [$property]['value'];
}
return parent::getProperty($property);
}
/**
* Create new style by importing ODT style definition.
*
* @param $xmlCode Style definition in ODT XML format
* @return ODTStyle New specific style
*/
static public function importODTStyle($xmlCode) {
$style = new ODTParagraphStyle();
$attrs = 0;
$open = XMLUtil::getElementOpenTag('style:style', $xmlCode);
if (!empty($open)) {
$attrs += $style->importODTStyleInternal(ODTStyleStyle::getStyleProperties (), $open, $style->style_properties);
} else {
$open = XMLUtil::getElementOpenTag('style:default-style', $xmlCode);
if (!empty($open)) {
$style->setDefault(true);
$attrs += $style->importODTStyleInternal(ODTStyleStyle::getStyleProperties (), $open, $style->style_properties);
}
}
$open = XMLUtil::getElementOpenTag('style:paragraph-properties', $xmlCode);
if (!empty($open)) {
$attrs += $style->importODTStyleInternal(self::$paragraph_fields, $xmlCode);
}
$open = XMLUtil::getElementOpenTag('style:text-properties', $xmlCode);
if (!empty($open)) {
$attrs += $style->importODTStyleInternal(ODTTextStyle::getTextProperties (), $open, $style->text_properties);
}
// Get all tab-stops.
$tabs = XMLUtil::getElementContent('style:tab-stops', $xmlCode);
if ($tabs != NULL) {
$max = strlen($tabs);
$pos = 0;
$index = 0;
$tab = XMLUtil::getElement('style:tab-stop', $tabs, $end);
$pos = $end;
while ($tab != NULL) {
$style->tab_stops [$index] = array();
$attrs += $style->importODTStyleInternal(self::$tab_stop_fields, $tab, $style->tab_stops [$index]);
$index++;
$tab = XMLUtil::getElement('style:tab-stop', substr ($tabs, $pos), $end);
$pos += $end;
}
}
// If style has no meaningfull content then throw it away
if ( $attrs == 0 ) {
return NULL;
}
return $style;
}
static public function getParagraphProperties () {
return self::$paragraph_fields;
}
/**
* Encode current style values in a string and return it.
*
* @return string ODT XML encoded style
*/
public function toString() {
$style = '';
$para_props = '';
$text_props = '';
$tab_stops_props = '';
// Get style contents
foreach ($this->style_properties as $property => $items) {
if ($items ['odt_property'] != 'style:family') {
$style .= $items ['odt_property'].'="'.$items ['value'].'" ';
}
}
$style .= 'style:family="'.$this->getFamily().'" ';
// Get paragraph properties ODT properties
foreach ($this->properties as $property => $items) {
$para_props .= $items ['odt_property'].'="'.$items ['value'].'" ';
}
// Get text properties
foreach ($this->text_properties as $property => $items) {
$text_props .= $items ['odt_property'].'="'.$items ['value'].'" ';
}
// Get tab-stops properties
for ($index = 0 ; $index < count($this->tab_stops) ; $index++) {
$tab_stops_props .= '<style:tab-stop ';
foreach ($this->tab_stops[$index] as $property => $items) {
$tab_stops_props .= $items ['odt_property'].'="'.$items ['value'].'" ';
}
$tab_stops_props .= '/>';
}
// Build style.
if (!$this->isDefault()) {
$style = '<style:style '.$style.">\n";
} else {
$style = '<style:default-style '.$style.">\n";
}
if (!empty($para_props) || !empty($tab_stops_props)) {
if (empty($tab_stops_props)) {
$style .= '<style:paragraph-properties '.$para_props."/>\n";
} else {
$style .= '<style:paragraph-properties '.$para_props.">\n";
$style .= '<style:tab-stops>'."\n";
$style .= $tab_stops_props."\n";
$style .= '</style:tab-stops>'."\n";
$style .= '</style:paragraph-properties>'."\n";
}
}
if (!empty($text_props)) {
$style .= '<style:text-properties '.$text_props."/>\n";
}
if (!$this->isDefault()) {
$style .= '</style:style>'."\n";
} else {
$style .= '</style:default-style>'."\n";
}
return $style;
}
/**
* This function creates a paragraph style using the style as set in the assoziative array $properties.
* The parameters in the array should be named as the CSS property names e.g. 'color' or 'background-color'.
* Properties which shall not be used in the style can be disabled by setting the value in disabled_props
* to 1 e.g. $disabled_props ['color'] = 1 would block the usage of the color property.
*
* The currently supported properties are:
* background-color, color, font-style, font-weight, font-size, border, font-family, font-variant, letter-spacing,
* vertical-align, line-height, background-image
*
* The function returns the name of the new style or NULL if all relevant properties are empty.
*
* @author LarsDW223
* @param $properties
* @param null $disabled_props
* @return ODTParagraphStyle or NULL
*/
public static function createParagraphStyle(array $properties, array $disabled_props = NULL, ODTDocument $doc=NULL){
// Convert 'text-decoration'.
if ( $properties ['text-decoration'] == 'line-through' ) {
$properties ['text-line-through-style'] = 'solid';
}
if ( $properties ['text-decoration'] == 'underline' ) {
$properties ['text-underline-style'] = 'solid';
}
if ( $properties ['text-decoration'] == 'overline' ) {
$properties ['text-overline-style'] = 'solid';
}
// If the property 'vertical-align' has the value 'sub' or 'super'
// then for ODT it needs to be converted to the corresponding 'text-position' property.
// Replace sub and super with text-position.
$valign = $properties ['vertical-align'];
if (!empty($valign)) {
if ( $valign == 'sub' ) {
$properties ['text-position'] = '-33% 100%';
unset($properties ['vertical-align']);
} elseif ( $valign == 'super' ) {
$properties ['text-position'] = '33% 100%';
unset($properties ['vertical-align']);
}
}
// Separate country from language
$lang = $properties ['lang'];
$country = $properties ['country'];
if ( !empty($lang) ) {
$parts = preg_split ('/-/', $lang);
$lang = $parts [0];
$country = $parts [1];
$properties ['country'] = trim($country);
$properties ['lang'] = trim($lang);
}
if (!empty($properties ['country'])) {
if (empty($properties ['country-asian'])) {
$properties ['country-asian'] = $properties ['country'];
}
if (empty($properties ['country-complex'])) {
$properties ['country-complex'] = $properties ['country'];
}
}
// Always set 'auto-text-indent = false' if 'text-indent' is set.
if (!empty($properties ['text-indent'])) {
$properties ['auto-text-indent'] = 'false';
$length = strlen ($properties ['text-indent']);
if ( $length > 0 && $properties ['text-indent'] [$length-1] == '%' && $doc != NULL ) {
// Percentage value needs to be converted to absolute value.
// ODT standard says that percentage value should work if used in a common style.
// This did not work with LibreOffice 4.4.3.2.
$value = trim ($properties ['text-indent'], '%');
$properties ['text-indent'] = $doc->getAbsWidthMindMargins ($value).'cm';
}
}
// Eventually create parent for font-size
$save = $disabled_props ['font-size'];
$odt_fo_size = '';
if ( empty ($disabled_props ['font-size']) ) {
$odt_fo_size = $properties ['font-size'];
}
$parent = '';
$length = strlen ($odt_fo_size);
if ( $length > 0 && $odt_fo_size [$length-1] == '%' && $doc != NULL) {
// A font-size in percent is only supported in common style definitions, not in automatic
// styles. Create a common style and set it as parent for this automatic style.
$name = 'Size'.trim ($odt_fo_size, '%').'pc';
$style_obj = ODTTextStyle::createSizeOnlyTextStyle ($name, $odt_fo_size);
$doc->addStyle($style_obj);
$parent = $style_obj->getProperty('style-name');
if (!empty($parent)) {
$properties ['style-parent'] = $parent;
}
}
// Create style name (if not given).
$style_name = $properties ['style-name'];
if ( empty($style_name) ) {
$style_name = self::getNewStylename ('Paragraph');
$properties ['style-name'] = $style_name;
}
// FIXME: fix missing tab stop handling...
//case 'tab-stop':
// $tab .= $params [$property]['name'].'="'.$value.'" ';
// $tab .= self::writeExtensionNames ($params [$property]['name'], $value);
// break;
// Create empty paragraph style.
$object = new ODTParagraphStyle();
if ($object == NULL) {
return NULL;
}
// Import our properties
$object->importProperties($properties, $disabled_props);
// Restore $disabled_props
$disabled_props ['font-size'] = $save;
return $object;
}
/**
* Simple helper function for creating a paragrapg style for a pagebreak.
*
* @author LarsDW223
*
* @param string $parent Name of the parent style to set
* @param string $before Pagebreak before or after?
* @return ODTParagraphStyle
*/
public static function createPagebreakStyle($style_name, $parent=NULL,$before=true) {
$properties = array();
$properties ['style-name'] = $style_name;
if ( !empty($parent) ) {
$properties ['style-parent'] = $parent;
}
if ($before == true ) {
$properties ['break-before'] = 'page';
} else {
$properties ['break-after'] = 'page';
}
return self::createParagraphStyle($properties);
}
/**
* Set a property.
*
* @param $property The name of the property to set
* @param $value New value to set
*/
public static function copyLayoutProperties(ODTParagraphStyle $source, ODTParagraphStyle $dest, array $disabled=NULL) {
// DO NOT COPY STYLE FIELDS/PROPERTIES
// Copy $tab_stop_fields
foreach (self::$tab_stop_fields as $property => $fields) {
$value = $source->getProperty($property);
if ($value != NULL && $disabled [$property] == 0) {
$dest -> setProperty($property, $value);
}
}
// Copy $paragraph_fields
foreach (self::$paragraph_fields as $property => $fields) {
$value = $source->getProperty($property);
if ($value != NULL && $disabled [$property] == 0) {
$dest -> setProperty($property, $value);
}
}
// Copy $text_fields
$text_fields = ODTTextStyle::getTextProperties ();
foreach ($text_fields as $property => $fields) {
$value = $source->getProperty($property);
if ($value != NULL && $disabled [$property] == 0) {
$dest -> setProperty($property, $value);
}
}
}
}

View File

@@ -0,0 +1,248 @@
<?php
/**
* ODTStyle: base class for ODT styles.
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author LarsDW223
*/
require_once 'ODTUnknownStyle.php';
require_once 'ODTStyleStyle.php';
require_once 'ODTTextOutlineStyle.php';
require_once 'ODTTextListStyle.php';
require_once 'ODTMasterPageStyle.php';
require_once 'ODTPageLayoutStyle.php';
require_once 'ODTTextStyle.php';
require_once 'ODTParagraphStyle.php';
require_once 'ODTTableStyle.php';
require_once 'ODTTableRowStyle.php';
require_once 'ODTTableColumnStyle.php';
require_once 'ODTTableCellStyle.php';
/**
* The ODTStyle class
*/
abstract class ODTStyle
{
protected static $style_base_name = 'PluginODTAutoStyle_';
protected static $style_count = 0;
protected $properties = array();
/**
* Get the element name for the ODT XML encoding of the style.
*
* @param $properties Properties to be imported
* @param $disabled Properties to be ignored
*/
abstract public function getElementName();
/**
* Set style properties by importing values from a properties array.
* Properties might be disabled by setting them in $disabled.
* The style must have been previously created.
*
* @param $properties Properties to be imported
* @param $disabled Properties to be ignored
*/
abstract public function importProperties($properties, $disabled=array());
/**
* Check if a style is a common style.
*
* @return bool Is common style
*/
abstract public function mustBeCommonStyle();
/**
* Encode current style values in a string and return it.
*
* @return string ODT XML encoded style
*/
abstract public function toString();
/**
* Set a property.
*
* @param $property The name of the property to set
* @param $value New value to set
*/
abstract public function setProperty($property, $value);
/**
* Get the value of a property.
*
* @param $property The property name
* @return string The current value of the property
*/
public function getProperty($property) {
return $this->properties [$property]['value'];
}
/**
* Get the value of a property.
*
* @param $property The property name
* @param $properties Properties array to query the value from,
* or NULL for using ours.
* @return string The current value of the property
*/
public function getPropertyInternal($property, $properties=NULL) {
if ( $properties === NULL ) {
return $this->properties [$property]['value'];
} else {
return $properties [$property]['value'];
}
}
/**
* Get the value of a property.
*
* @param $property The property name
* @return string The current value of the property
*/
public function getPropertySection($property) {
return $this->properties [$property]['section'];
}
/**
* Create new style by importing ODT style definition.
*
* @param $xmlCode Style definition in ODT XML format
* @return ODTStyle New specific style
*/
static public function importODTStyle($xmlCode) {
$matches = array();
$pattern = '/<(\w)+[^\s\/>]+/';
if (preg_match ($pattern, $xmlCode, $matches) !== 1) {
return NULL;
}
$element = trim ($matches [0], '"<>');
$style = NULL;
switch ($element) {
case 'style:style':
case 'style:default-style':
$style = ODTStyleStyle::importODTStyle($xmlCode);
break;
case 'text:outline-style':
$style = ODTTextOutlineStyle::importODTStyle($xmlCode);
break;
case 'text:list-style':
$style = ODTTextListStyle::importODTStyle($xmlCode);
break;
case 'style:master-page':
$style = ODTMasterPageStyle::importODTStyle($xmlCode);
break;
case 'style:page-layout':
$style = ODTPageLayoutStyle::importODTStyle($xmlCode);
break;
default:
break;
}
if ($style != NULL ) {
return $style;
}
// Unknown/not implemented style.
// Create generic style which can not be changed.
$unknown = ODTUnknownStyle::importODTStyle($xmlCode);
$unknown->setElementName($element);
return $unknown;
}
/**
* Set a property.
*
* @param $property The name of the property to set
* @param $value New value to set
*/
protected function setPropertyInternal($property, $odt_property, $value, $section, &$dest=NULL) {
if ($value !== NULL) {
if ( $dest === NULL ) {
$this->properties [$property] = array ('odt_property' => $odt_property,
'value' => $value,
'section' => $section);
} else {
$dest [$property] = array ('odt_property' => $odt_property,
'value' => $value,
'section' => $section);
}
} else {
if ( $dest === NULL ) {
unset ($this->properties [$property]);
} else {
unset ($dest [$property]);
}
}
}
/**
* Import ODT style definition according to given fields into given style.
*
* @param $style ODTStyle object for storing the properties
* @param $fields Properties accepted by the object/class
* @param $xmlCode Style definition in ODT XML format
* @return integer Number of meaningful properties found
*/
protected function importODTStyleInternal(array $fields, $xmlCode, &$properties=NULL) {
$attrs = 0;
foreach ($fields as $property => $field) {
// The pattern is specified in that way that it also reads in empty attributes.
// Sometimes an empty attribute is not the same as an not existing one. E.g.
// in ODT XML '<text:outline-level-style text:level="3" style:num-format="" >'
// has NOT the same meaning as '<text:outline-level-style text:level="3" >'!!!
// So DO NOT change the '*' in the pattern to '+'!
if (preg_match ('/'.$field[0].'="[^"]*"/', $xmlCode, $matches) === 1) {
$value = substr ($matches [0], strlen($field[0].'="'));
$value = trim ($value, '"<>');
$this->setPropertyInternal($property, $field[0], $value, $field[1], $properties);
if ( $field[2] == true ) {
$attrs++;
}
}
}
return $attrs;
}
/**
* Set style properties by importing values from a properties array.
* Properties might be disabled by setting them in $disabled.
* The style must have been previously created. Only those properties
* will be accepted that are mentioned in the fields array.
*
* @param $style ODTStyle object for storing the properties
* @param $fields Properties accepted by the object/class
* @param $properties Properties to be imported
* @param $disabled Properties to be ignored
*/
protected function importPropertiesInternal(array $fields, $properties, $disabled, &$dest=NULL) {
foreach ($properties as $property => $value) {
if ($disabled [$property] == 0 && array_key_exists ($property, $fields)) {
$this->setPropertyInternal($property, $fields[$property][0], $value, $fields[$property][1], $dest);
}
}
}
/**
* Is this style a default style?
* Needs to be overwritten if a style could also be a default style.
*
* @return boolean Always false.
*/
public function isDefault() {
return false;
}
/**
* This function creates a new style name. All functions of this class which create a new
* style/style name shall use this function to create the style name. By doing so it is
* guaranteed that all style names created by this class are unique.
*
* The function returns the name of the new style or NULL if all relevant properties are empty.
*/
public static function getNewStylename ($type = '') {
self::$style_count++;
$style_name = self::$style_base_name.$type.'_'.self::$style_count;
return $style_name;
}
}

View File

@@ -0,0 +1,242 @@
<?php
/**
* ODTStyleStyle: class for ODT style styles.
* (Elements style:style and style:default-style)
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author LarsDW223
*/
require_once DOKU_PLUGIN.'odt/ODT/styles/ODTStyle.php';
//require_once 'ODTTextStyle.php';
//require_once 'ODTParagraphStyle.php';
//require_once 'ODTTableStyle.php';
//require_once 'ODTTableRowStyle.php';
//require_once 'ODTTableColumnStyle.php';
//require_once 'ODTTableCellStyle.php';
//require_once DOKU_PLUGIN.'odt/ODT/styles/ODTParagraphStyle.php';
//require_once DOKU_PLUGIN.'odt/ODT/styles/ODTTableStyle.php';
//require_once DOKU_PLUGIN.'odt/ODT/styles/ODTTableRowStyle.php';
//require_once DOKU_PLUGIN.'odt/ODT/styles/ODTTableCellStyle.php';
/**
* The ODTStyleStyle class
*/
abstract class ODTStyleStyle extends ODTStyle
{
// Style properties/attributes common to each
// style:style and style:default-style element
static $style_fields = array(
'style-name' => array ('style:name', 'style', false),
'style-display-name' => array ('style:display-name', 'style', false),
'style-parent' => array ('style:parent-style-name', 'style', false),
'style-class' => array ('style:class', 'style', true),
'style-family' => array ('style:family', 'style', true),
'style-next' => array ('style:next-style-name', 'style', true),
'style-list-level' => array ('style:list-level', 'style', true),
'style-list-style-name' => array ('style:list-style-name', 'style', true),
'style-master-page-name' => array ('style:master-page-name', 'style', true),
'style-auto-update' => array ('style:auto-update', 'style', true),
'style-data-style-name' => array ('style:data-style-name', 'style', true),
'style-percentage-data-style-name' => array ('style:percentage-data-style-name', 'style', true),
'style-default-outline-level' => array ('style:default-outline-level', 'style', true),
);
static $get_family_callbacks = NULL;
static $import_odt_callbacks = NULL;
protected $is_default = false;
/**
* Constructor.
*/
public function __construct() {
if (self::$get_family_callbacks === NULL)
self::$get_family_callbacks = array();
if (self::$import_odt_callbacks === NULL)
self::$import_odt_callbacks = array();
}
static public function register ($classname) {
self::$get_family_callbacks [] = array($classname, 'getFamily');
self::$import_odt_callbacks [] = array($classname, 'importODTStyle');
}
/**
* Get the element name for the ODT XML encoding of the style.
*
* @param $properties Properties to be imported
* @param $disabled Properties to be ignored
*/
public function getElementName() {
if ($this->isDefault() == true) {
return 'style:default-style';
}
return 'style:style';
}
/**
* Mark style as default style or not.
*
* @param $is_default
*/
public function setDefault($is_default) {
$this->is_default = $is_default;
}
/**
* Is this style a default style?
*
* @return boolean Is this a default style?
*/
public function isDefault() {
return $this->is_default;
}
/**
* Encode current style values in a string and return it.
*
* @return string ODT XML encoded style
*/
public function toString() {
//FIXME: Handling for background-image-section
$style = '';
$text = '';
$paragraph = '';
$table = '';
$table_column = '';
$table_row = '';
$table_cell = '';
$tab_stop = '';
$image = '';
foreach ($this->properties as $property => $items) {
switch ($items ['section']) {
case 'style':
$style .= $items ['odt_property'].'="'.$items ['value'].'" ';
break;
case 'text':
$text .= $items ['odt_property'].'="'.$items ['value'].'" ';
break;
case 'paragraph':
$paragraph .= $items ['odt_property'].'="'.$items ['value'].'" ';
break;
case 'table':
$table .= $items ['odt_property'].'="'.$items ['value'].'" ';
break;
case 'table-column':
$table_column .= $items ['odt_property'].'="'.$items ['value'].'" ';
break;
case 'table-row':
$table_row .= $items ['odt_property'].'="'.$items ['value'].'" ';
break;
case 'table-cell':
$table_cell .= $items ['odt_property'].'="'.$items ['value'].'" ';
break;
case 'tab-stop':
$tab_stop .= $items ['odt_property'].'="'.$items ['value'].'" ';
break;
case 'table-cell-background-image':
$image .= $items ['odt_property'].'="'.$items ['value'].'" ';
break;
}
}
// Build style.
$element = $this->getElementName();
$style = '<'.$element.' '.$style.'>'."\n";
if ( !empty($paragraph) ) {
if ( empty($tab_stop) ) {
$style .= ' <style:paragraph-properties '.$paragraph.'/>'."\n";
} else {
$style .= ' <style:paragraph-properties '.$paragraph.'>'."\n";
$style .= ' <style:tab-stops><style:tab-stop '.$tab_stop.'/></style:tab-stops>'."\n";
$style .= ' </style:paragraph-properties>'."\n";
}
}
if ( !empty($text) ) {
$style .= ' <style:text-properties '.$text.'/>'."\n";
}
if ( !empty($table) ) {
$style .= ' <style:table-properties '.$table.'/>'."\n";
}
if ( !empty($table_column) ) {
$style .= ' <style:table-column-properties '.$table_column.'/>'."\n";
}
if ( !empty($table_row) ) {
$style .= ' <style:table-row-properties '.$table_row.'/>'."\n";
}
if ( !empty($table_cell) ) {
if (empty($image)) {
$style .= ' <style:table-cell-properties '.$table_cell.'/>'."\n";
} else {
$style .= ' <style:table-cell-properties '.$table_cell.'>'."\n";
$style .=' <style:background-image '.$image.'/>'."\n";
$style .= ' </style:table-cell-properties>';
}
}
$style .= '</'.$element.'>'."\n";
return $style;
}
/**
* Create new style by importing ODT style definition.
*
* @param $xmlCode Style definition in ODT XML format
* @return ODTStyle New specific style
*/
static public function importODTStyle($xmlCode) {
$matches = array();
if (preg_match ('/style:family="[^"]+"/', $xmlCode, $matches) !== 1) {
return NULL;
}
$family = substr ($matches [0], strlen('style:family='));
$family = trim ($family, '"<>');
for ($index = 0 ; $index < count(self::$get_family_callbacks) ; $index++ ) {
$curr_family = call_user_func(self::$get_family_callbacks [$index]);
if ($curr_family == $family) {
return call_user_func(self::$import_odt_callbacks [$index], $xmlCode);
}
}
// Unknown/not implemented style family.
// Return NULL, in this case ODTStyle will create a generic unknown style.
return NULL;
}
/**
* Set style properties by importing values from a properties array.
* Properties might be disabled by setting them in $disabled.
* The style must have been previously created. Only those properties
* will be accepted that are mentioned in the fields array.
*
* @param $style ODTStyle object for storing the properties
* @param $fields Properties accepted by the object/class
* @param $properties Properties to be imported
* @param $disabled Properties to be ignored
*/
protected function importPropertiesInternal(array $fields, $properties, $disabled, &$dest=NULL) {
parent::importPropertiesInternal($fields, $properties, $disabled, $dest);
}
/**
* The function deletes all properties that do not belong to the styles section,
* e.g. text properties or paragraph properties.
*/
public function clearLayoutProperties() {
foreach ($this->properties as $property => $items) {
switch ($items ['section']) {
case 'style':
// Keep it.
break;
default:
// Delete everything that does not belong to the styles section.
$this->properties [$property] = NULL;
unset ($this->properties [$property]);
break;
}
}
}
static public function getStyleProperties () {
return self::$style_fields;
}
}

View File

@@ -0,0 +1,224 @@
<?php
/**
* ODTTableCellStyle: class for ODT table cell styles.
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author LarsDW223
*/
require_once DOKU_INC.'lib/plugins/odt/ODT/XMLUtil.php';
require_once 'ODTStyle.php';
ODTStyleStyle::register('ODTTableCellStyle');
/**
* The ODTTableCellStyle class
*/
class ODTTableCellStyle extends ODTStyleStyle
{
static $table_cell_fields = array(
'vertical-align' => array ('style:vertical-align', 'table-cell', true),
'text-align-source' => array ('style:text-align-source', 'table-cell', true),
'direction' => array ('style:direction', 'table-cell', true),
'glyph-orientation-vertical' => array ('style:glyph-orientation-vertical', 'table-cell', true),
'writing-mode' => array ('style:writing-mode', 'table-cell', true),
'shadow' => array ('style:shadow', 'table-cell', true),
'background-color' => array ('fo:background-color', 'table-cell', true),
'border' => array ('fo:border', 'table-cell', true),
'border-top' => array ('fo:border-top', 'table-cell', true),
'border-right' => array ('fo:border-right', 'table-cell', true),
'border-bottom' => array ('fo:border-bottom', 'table-cell', true),
'border-left' => array ('fo:border-left', 'table-cell', true),
'diagonal-tl-br' => array ('style:diagonal-tl-br', 'table-cell', true),
'diagonal-tl-br-widths' => array ('style:diagonal-tl-br-widths', 'table-cell', true),
'diagonal-bl-tr' => array ('style:diagonal-bl-tr', 'table-cell', true),
'diagonal-bl-tr-widths' => array ('style:diagonal-bl-tr-widths', 'table-cell', true),
'border-line-width' => array ('style:border-line-width', 'table-cell', true),
'border-line-width-top' => array ('style:border-line-width-top', 'table-cell', true),
'border-line-width-bottom' => array ('style:border-line-width-bottom', 'table-cell', true),
'border-line-width-left' => array ('style:border-line-width-left', 'table-cell', true),
'border-line-width-right' => array ('style:border-line-width-right', 'table-cell', true),
'padding' => array ('fo:padding', 'table-cell', true),
'padding-top' => array ('fo:padding-top', 'table-cell', true),
'padding-right' => array ('fo:padding-right', 'table-cell', true),
'padding-bottom' => array ('fo:padding-bottom', 'table-cell', true),
'padding-left' => array ('fo:padding-left', 'table-cell', true),
'wrap-option' => array ('fo:wrap-option', 'table-cell', true),
'rotation-angle' => array ('style:rotation-angle', 'table-cell', true),
'rotation-align' => array ('style:rotation-align', 'table-cell', true),
'cell-protect' => array ('style:cell-protect', 'table-cell', true),
'print-content' => array ('style:print-content', 'table-cell', true),
'decimal-places' => array ('style:decimal-places', 'table-cell', true),
'repeat-content' => array ('style:repeat-content', 'table-cell', true),
'shrink-to-fit' => array ('style:shrink-to-fit', 'table-cell', true),
// Fields for background-image
// (see '<define name="style-background-image"> in relax-ng schema)'
'repeat' => array ('style:repeat', 'table-cell-background-image', true),
'position' => array ('style:position', 'table-cell-background-image', true),
'style:filter-name' => array ('style:filter-name', 'table-cell-background-image', true),
'opacity' => array ('draw:opacity', 'table-cell-background-image', true),
'type' => array ('xlink:type', 'table-cell-background-image', true),
'href' => array ('xlink:href', 'table-cell-background-image', true),
'show' => array ('xlink:show', 'table-cell-background-image', true),
'actuate' => array ('xlink:actuate', 'table-cell-background-image', true),
'binary-data' => array ('office:binary-data', 'table-cell-background-image', true),
'base64Binary' => array ('base64Binary', 'table-cell-background-image', true),
);
/**
* Constructor.
*/
public function __construct() {
parent::__construct();
}
/**
* Set style properties by importing values from a properties array.
* Properties might be disabled by setting them in $disabled.
* The style must have been previously created.
*
* @param $properties Properties to be imported
* @param $disabled Properties to be ignored
*/
public function importProperties($properties, $disabled=array()) {
$this->importPropertiesInternal(ODTStyleStyle::getStyleProperties (), $properties, $disabled);
$this->importPropertiesInternal(ODTTextStyle::getTextProperties (), $properties, $disabled);
$this->importPropertiesInternal(ODTParagraphStyle::getParagraphProperties (), $properties, $disabled);
$this->importPropertiesInternal(self::$table_cell_fields, $properties, $disabled);
$this->setProperty('style-family', $this->getFamily());
}
/**
* Check if a style is a common style.
*
* @return bool Is common style
*/
public function mustBeCommonStyle() {
return false;
}
/**
* Get the style family of a style.
*
* @return string Style family
*/
static public function getFamily() {
return 'table-cell';
}
/**
* Set a property.
*
* @param $property The name of the property to set
* @param $value New value to set
*/
public function setProperty($property, $value) {
$style_fields = ODTStyleStyle::getStyleProperties ();
if (array_key_exists ($property, $style_fields)) {
$this->setPropertyInternal
($property, $style_fields [$property][0], $value, $style_fields [$property][1]);
return;
}
if (array_key_exists ($property, self::$table_cell_fields)) {
$this->setPropertyInternal
($property, self::$table_cell_fields [$property][0], $value, self::$table_cell_fields [$property][1]);
return;
}
$paragraph_fields = ODTParagraphStyle::getParagraphProperties ();
if (array_key_exists ($property, $paragraph_fields)) {
$this->setPropertyInternal
($property, $paragraph_fields [$property][0], $value, $paragraph_fields [$property][1]);
return;
}
$text_fields = ODTTextStyle::getTextProperties ();
if (array_key_exists ($property, $text_fields)) {
$this->setPropertyInternal
($property, $text_fields [$property][0], $value, $text_fields [$property][1]);
return;
}
}
/**
* Create new style by importing ODT style definition.
*
* @param $xmlCode Style definition in ODT XML format
* @return ODTStyle New specific style
*/
static public function importODTStyle($xmlCode) {
$style = new ODTTableCellStyle();
$attrs = 0;
$open = XMLUtil::getElementOpenTag('style:style', $xmlCode);
if (!empty($open)) {
$attrs += $style->importODTStyleInternal(ODTStyleStyle::getStyleProperties (), $open);
} else {
$open = XMLUtil::getElementOpenTag('style:default-style', $xmlCode);
if (!empty($open)) {
$style->setDefault(true);
$attrs += $style->importODTStyleInternal(ODTStyleStyle::getStyleProperties (), $open);
}
}
$open = XMLUtil::getElementOpenTag('style:paragraph-properties', $xmlCode);
if (!empty($open)) {
$attrs += $style->importODTStyleInternal(ODTParagraphStyle::getParagraphProperties (), $xmlCode);
}
$open = XMLUtil::getElementOpenTag('style:text-properties', $xmlCode);
if (!empty($open)) {
$attrs += $style->importODTStyleInternal(ODTTextStyle::getTextProperties (), $open);
}
$open = XMLUtil::getElementOpenTag('style:table-cell-properties', $xmlCode);
if (!empty($open)) {
$attrs += $style->importODTStyleInternal(self::$table_cell_fields, $open);
}
// If style has no meaningfull content then throw it away
if ( $attrs == 0 ) {
return NULL;
}
return $style;
}
static public function getTableCellProperties () {
return self::$table_cell_fields;
}
/**
* This function creates a table cell style using the style as set in the assoziative array $properties.
* The parameters in the array should be named as the CSS property names e.g. 'color' or 'background-color'.
* Properties which shall not be used in the style can be disabled by setting the value in disabled_props
* to 1 e.g. $disabled_props ['color'] = 1 would block the usage of the color property.
*
* The currently supported properties are:
* background-color, vertical-align
*
* The function returns the name of the new style or NULL if all relevant properties are empty.
*
* @author LarsDW223
* @param $properties
* @param null $disabled_props
* @return ODTTableCellStyle or NULL
*/
public static function createTableCellStyle(array $properties, array $disabled_props = NULL){
// Create style name (if not given).
$style_name = $properties ['style-name'];
if ( empty($style_name) ) {
$style_name = self::getNewStylename ('TableCell');
$properties ['style-name'] = $style_name;
}
// Create empty table cell style.
$object = new ODTTableCellStyle();
if ($object == NULL) {
return NULL;
}
// Import our properties
$object->importProperties($properties, $disabled_props);
return $object;
}
}

View File

@@ -0,0 +1,179 @@
<?php
/**
* ODTTableColumnStyle: class for ODT table column styles.
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author LarsDW223
*/
require_once DOKU_INC.'lib/plugins/odt/ODT/XMLUtil.php';
require_once 'ODTStyle.php';
ODTStyleStyle::register('ODTTableColumnStyle');
/**
* The ODTTableColumnStyle class
*/
class ODTTableColumnStyle extends ODTStyleStyle
{
static $table_column_fields = array(
'column-width' => array ('style:column-width', 'table-column', true),
'rel-column-width' => array ('style:rel-column-width', 'table-column', true),
'use-optimal-column-width' => array ('style:use-optimal-column-width', 'table-column', true),
'break-before' => array ('fo:break-before', 'table-column', true),
'break-after' => array ('fo:break-after', 'table-column', true),
);
/**
* Constructor.
*/
public function __construct() {
parent::__construct();
}
/**
* Set style properties by importing values from a properties array.
* Properties might be disabled by setting them in $disabled.
* The style must have been previously created.
*
* @param $properties Properties to be imported
* @param $disabled Properties to be ignored
*/
public function importProperties($properties, $disabled=array()) {
$this->importPropertiesInternal(ODTStyleStyle::getStyleProperties (), $properties, $disabled);
$this->importPropertiesInternal(self::$table_column_fields, $properties, $disabled);
$this->setProperty('style-family', $this->getFamily());
}
/**
* Check if a style is a common style.
*
* @return bool Is common style
*/
public function mustBeCommonStyle() {
return false;
}
/**
* Get the style family of a style.
*
* @return string Style family
*/
static public function getFamily() {
return 'table-column';
}
/**
* Set a property.
*
* @param $property The name of the property to set
* @param $value New value to set
*/
public function setProperty($property, $value) {
$style_fields = ODTStyleStyle::getStyleProperties ();
if (array_key_exists ($property, $style_fields)) {
$this->setPropertyInternal
($property, $style_fields [$property][0], $value, $style_fields [$property][1]);
return;
}
if (array_key_exists ($property, self::$table_column_fields)) {
$this->setPropertyInternal
($property, self::$table_column_fields [$property][0], $value, self::$table_column_fields [$property][1]);
return;
}
}
/**
* Create new style by importing ODT style definition.
*
* @param $xmlCode Style definition in ODT XML format
* @return ODTStyle New specific style
*/
static public function importODTStyle($xmlCode) {
$style = new ODTTableColumnStyle();
$attrs = 0;
$open = XMLUtil::getElementOpenTag('style:style', $xmlCode);
if (!empty($open)) {
$attrs += $style->importODTStyleInternal(ODTStyleStyle::getStyleProperties (), $open);
} else {
$open = XMLUtil::getElementOpenTag('style:default-style', $xmlCode);
if (!empty($open)) {
$style->setDefault(true);
$attrs += $style->importODTStyleInternal(ODTStyleStyle::getStyleProperties (), $open);
}
}
$open = XMLUtil::getElementOpenTag('style:table-column-properties', $xmlCode);
if (!empty($open)) {
$attrs += $style->importODTStyleInternal(self::$table_column_fields, $open);
}
// If style has no meaningfull content then throw it away
if ( $attrs == 0 ) {
return NULL;
}
return $style;
}
static public function getTableColumnProperties () {
return self::$table_column_fields;
}
/**
* This function creates a table column style using the style as set in the assoziative array $properties.
* The parameters in the array should be named as the CSS property names e.g. 'color' or 'background-color'.
* Properties which shall not be used in the style can be disabled by setting the value in disabled_props
* to 1 e.g. $disabled_props ['color'] = 1 would block the usage of the color property.
*
* The currently supported properties are:
* width
*
* The function returns the name of the new style or NULL if all relevant properties are empty.
*
* @author LarsDW223
*
* @param $style
* @param $properties
* @param null $disabled_props
* @param null $style_name
* @return ODTUnknownStyle or NULL
*/
public static function createTableColumnStyle(array $properties, array $disabled_props = NULL){
// Create style name (if not given).
$style_name = $properties ['style-name'];
if ( empty($style_name) ) {
$style_name = self::getNewStylename ('TableColumn');
$properties ['style-name'] = $style_name;
}
// Convert width to ODT format
$table_co_width = $properties ['width'];
if ( !empty ($table_co_width) ) {
$length = strlen ($table_co_width);
if ( $table_co_width [$length-1] != '%' ) {
$properties ['column-width'] = $table_co_width;
} else {
// Columns have a specific syntax for relative width in %!
// Change % to *.
// Also mutiply with 10:
// For some reason values for two columns like 10* and 90* do not give the result 10% and 90%.
// But 100* and 900* do give the wanted reuslt! (weird)
$table_co_width = trim ($table_co_width, '%');
$properties ['rel-column-width'] = ($table_co_width*10).'*';
}
}
// Create empty table column style.
$object = new ODTTableColumnStyle();
if ($object == NULL) {
return NULL;
}
// Import our properties
$object->importProperties($properties, $disabled_props);
return $object;
}
}

View File

@@ -0,0 +1,182 @@
<?php
/**
* ODTTableRowStyle: class for ODT table row styles.
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author LarsDW223
* @package ODT\Styles\ODTTableRowStyle
*/
/** Include XMLUtil and ODTStyle */
require_once DOKU_INC.'lib/plugins/odt/ODT/XMLUtil.php';
require_once 'ODTStyle.php';
ODTStyleStyle::register('ODTTableRowStyle');
/**
* The ODTTableRowStyle class.
*/
class ODTTableRowStyle extends ODTStyleStyle
{
/** var array List of properties belonging to an ODT table. */
static $table_row_fields = array(
'row-height' => array ('style:row-height', 'table-row', true),
'min-row-height' => array ('style:min-row-height', 'table-row', true),
'use-optimal-row-height' => array ('style:use-optimal-row-height', 'table-row', true),
'background-color' => array ('fo:background-color', 'table-row', true),
'background-color' => array ('fo:background-color', 'table-row', true),
'break-before' => array ('fo:break-before', 'table-row', true),
'break-after' => array ('fo:break-after', 'table-row', true),
'keep-together' => array ('fo:keep-together', 'table-row', true),
// Fields for background-image
// (see '<define name="style-background-image"> in relax-ng schema)'
'repeat' => array ('style:repeat', 'table-row-background-image', true),
'position' => array ('style:position', 'table-row-background-image', true),
'style:filter-name' => array ('style:filter-name', 'table-row-background-image', true),
'opacity' => array ('draw:opacity', 'table-row-background-image', true),
'type' => array ('xlink:type', 'table-row-background-image', true),
'href' => array ('xlink:href', 'table-row-background-image', true),
'show' => array ('xlink:show', 'table-row-background-image', true),
'actuate' => array ('xlink:actuate', 'table-row-background-image', true),
'binary-data' => array ('office:binary-data', 'table-row-background-image', true),
'base64Binary' => array ('base64Binary', 'table-row-background-image', true),
);
/**
* Constructor.
*/
public function __construct() {
parent::__construct();
}
/**
* Set style properties by importing values from a properties array.
* Properties might be disabled by setting them in $disabled.
* The style must have been previously created.
*
* @param $properties Properties to be imported
* @param $disabled Properties to be ignored
*/
public function importProperties($properties, $disabled=array()) {
$this->importPropertiesInternal(ODTStyleStyle::getStyleProperties (), $properties, $disabled);
$this->importPropertiesInternal(self::$table_row_fields, $properties, $disabled);
$this->setProperty('style-family', $this->getFamily());
}
/**
* Check if a style is a common style.
*
* @return bool Is common style
*/
public function mustBeCommonStyle() {
return false;
}
/**
* Get the style family of a style.
*
* @return string Style family
*/
static public function getFamily() {
return 'table-row';
}
/**
* Set a property.
*
* @param $property The name of the property to set
* @param $value New value to set
*/
public function setProperty($property, $value) {
$style_fields = ODTStyleStyle::getStyleProperties ();
if (array_key_exists ($property, $style_fields)) {
$this->setPropertyInternal
($property, $style_fields [$property][0], $value, $style_fields [$property][1]);
return;
}
if (array_key_exists ($property, self::$table_row_fields)) {
$this->setPropertyInternal
($property, self::$table_row_fields [$property][0], $value, self::$table_row_fields [$property][1]);
return;
}
}
/**
* Create new style by importing ODT style definition.
*
* @param $xmlCode Style definition in ODT XML format
* @return ODTStyle New specific style
*/
static public function importODTStyle($xmlCode) {
$style = new ODTTableRowStyle();
$attrs = 0;
$open = XMLUtil::getElementOpenTag('style:style', $xmlCode);
if (!empty($open)) {
$attrs += $style->importODTStyleInternal(ODTStyleStyle::getStyleProperties (), $open);
} else {
$open = XMLUtil::getElementOpenTag('style:default-style', $xmlCode);
if (!empty($open)) {
$style->setDefault(true);
$attrs += $style->importODTStyleInternal(ODTStyleStyle::getStyleProperties (), $open);
}
}
$open = XMLUtil::getElementOpenTag('style:table-row-properties', $xmlCode);
if (!empty($open)) {
$attrs += $style->importODTStyleInternal(self::$table_row_fields, $open);
}
// If style has no meaningfull content then throw it away
if ( $attrs == 0 ) {
return NULL;
}
return $style;
}
/**
* Return an array listing the properties belonging to an ODT table row.
*
* @return array Properties
*/
static public function getTableRowProperties () {
return self::$table_row_fields;
}
/**
* This function creates a table row style using the style as set in the assoziative array $properties.
* The parameters in the array should be named as the CSS property names e.g. 'color' or 'background-color'.
* Properties which shall not be used in the style can be disabled by setting the value in disabled_props
* to 1 e.g. $disabled_props ['color'] = 1 would block the usage of the color property.
*
* The currently supported properties are:
* height, background-color
*
* The function returns the name of the new style or NULL if all relevant properties are empty.
*
* @author LarsDW223
* @param array $properties
* @param array|null $disabled_props
* @return ODTTableRowStyle
*/
public static function createTableRowStyle(array $properties, array $disabled_props = NULL){
// Create style name (if not given).
$style_name = $properties ['style-name'];
if ( empty($style_name) ) {
$style_name = self::getNewStylename ('TableRow');
$properties ['style-name'] = $style_name;
}
// Create empty table row style.
$object = new ODTTableRowStyle();
if ($object == NULL) {
return NULL;
}
// Import our properties
$object->importProperties($properties, $disabled_props);
return $object;
}
}

View File

@@ -0,0 +1,226 @@
<?php
/**
* ODTTableStyle: class for ODT table styles.
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author LarsDW223
* @package ODT\Styles\ODTTableStyle
*/
/** Include XMLUtil and ODTStyle */
require_once DOKU_INC.'lib/plugins/odt/ODT/XMLUtil.php';
require_once 'ODTStyle.php';
ODTStyleStyle::register('ODTTableStyle');
/**
* The ODTTableStyle class.
*/
class ODTTableStyle extends ODTStyleStyle
{
/** var array List of properties belonging to an ODT table. */
static $table_fields = array(
'width' => array ('style:width', 'table', true),
'rel-width' => array ('style:rel-width', 'table', true),
'align' => array ('table:align', 'table', true),
'margin-left' => array ('fo:margin-left', 'table', true),
'margin-right' => array ('fo:margin-right', 'table', true),
'margin-top' => array ('fo:margin-top', 'table', true),
'margin-bottom' => array ('fo:margin-bottom', 'table', true),
'margin' => array ('fo:margin', 'table', true),
'page-number' => array ('style:page-number', 'table', true),
'break-before' => array ('fo:break-before', 'table', true),
'break-after' => array ('fo:break-after', 'table', true),
'background-color' => array ('fo:background-color', 'table', true),
'shadow' => array ('style:shadow', 'table', true),
'keep-with-next' => array ('fo:keep-with-next', 'table', true),
'may-break-between-rows' => array ('style:may-break-between-rows', 'table', true),
'border-model' => array ('table:border-model', 'table', true),
'writing-mode' => array ('style:writing-mode', 'table', true),
'display' => array ('table:display', 'table', true),
// Fields for background-image
// (see '<define name="style-background-image"> in relax-ng schema)'
'repeat' => array ('style:repeat', 'table-background-image', true),
'position' => array ('style:position', 'table-background-image', true),
'style:filter-name' => array ('style:filter-name', 'table-background-image', true),
'opacity' => array ('draw:opacity', 'table-background-image', true),
'type' => array ('xlink:type', 'table-background-image', true),
'href' => array ('xlink:href', 'table-background-image', true),
'show' => array ('xlink:show', 'table-background-image', true),
'actuate' => array ('xlink:actuate', 'table-background-image', true),
'binary-data' => array ('office:binary-data', 'table-background-image', true),
'base64Binary' => array ('base64Binary', 'table-background-image', true),
);
/**
* Constructor.
*/
public function __construct() {
parent::__construct();
}
/**
* Set style properties by importing values from a properties array.
* Properties might be disabled by setting them in $disabled.
* The style must have been previously created.
*
* @param $properties Properties to be imported
* @param $disabled Properties to be ignored
*/
public function importProperties($properties, $disabled=array()) {
$this->importPropertiesInternal(ODTStyleStyle::getStyleProperties (), $properties, $disabled);
$this->importPropertiesInternal(self::$table_fields, $properties, $disabled);
$this->setProperty('style-family', $this->getFamily());
}
/**
* Check if a style is a common style.
*
* @return bool Is common style
*/
public function mustBeCommonStyle() {
return false;
}
/**
* Get the style family of a style.
*
* @return string Style family
*/
static public function getFamily() {
return 'table';
}
/**
* Set a property.
*
* @param $property The name of the property to set
* @param $value New value to set
*/
public function setProperty($property, $value) {
$style_fields = ODTStyleStyle::getStyleProperties ();
if (array_key_exists ($property, $style_fields)) {
$this->setPropertyInternal
($property, $style_fields [$property][0], $value, $style_fields [$property][1]);
return;
}
if (array_key_exists ($property, self::$table_fields)) {
$this->setPropertyInternal
($property, self::$table_fields [$property][0], $value, self::$table_fields [$property][1]);
return;
}
}
/**
* Create new style by importing ODT style definition.
*
* @param $xmlCode Style definition in ODT XML format
* @return ODTStyle New specific style
*/
static public function importODTStyle($xmlCode) {
$style = new ODTTableStyle();
$attrs = 0;
$open = XMLUtil::getElementOpenTag('style:style', $xmlCode);
if (!empty($open)) {
$attrs += $style->importODTStyleInternal(ODTStyleStyle::getStyleProperties (), $open);
} else {
$open = XMLUtil::getElementOpenTag('style:default-style', $xmlCode);
if (!empty($open)) {
$style->setDefault(true);
$attrs += $style->importODTStyleInternal(ODTStyleStyle::getStyleProperties (), $open);
}
}
$open = XMLUtil::getElementOpenTag('style:table-properties', $xmlCode);
if (!empty($open)) {
$attrs += $style->importODTStyleInternal(self::$table_fields, $open);
}
// If style has no meaningfull content then throw it away
if ( $attrs == 0 ) {
return NULL;
}
return $style;
}
/**
* Return an array listing the properties belonging to an ODT table.
*
* @return array Properties
*/
static public function getTableProperties () {
return self::$table_fields;
}
/**
* This function creates a table table style using the style as set in the assoziative array $properties.
* The parameters in the array should be named as the CSS property names e.g. 'color' or 'background-color'.
* Properties which shall not be used in the style can be disabled by setting the value in disabled_props
* to 1 e.g. $disabled_props ['color'] = 1 would block the usage of the color property.
*
* The currently supported properties are:
* width, border-collapse, background-color
*
* The function returns the name of the new style or NULL if all relevant properties are empty.
*
* @author LarsDW223
* @param array $properties Properties for the table style
* @param array|null $disabled_props Ignored properties.
* @param int $max_width_cm Max. allowed table width.
* @return ODTTableStyle|NULL
*/
public static function createTableTableStyle(array $properties, array $disabled_props = NULL, $max_width_cm = 17){
// If we want to change the table width we must set table:align to something else
// than "margins". Otherwise the width will not be changed.
if (empty($properties ['align'])) {
$properties ['align'] = 'center';
}
if ($properties ['margin-left'] == '0') {
unset($properties ['margin-left']);
}
if ($properties ['margin-right'] == '0') {
unset($properties ['margin-right']);
}
// If no width specified always set 100%
if (empty ($properties ['width'])) {
$properties ['width'] = '100%';
}
// If relative width set, then move value to property 'rel-width'!
if ( $properties ['width'] [strlen($properties ['width'])-1] == '%' ) {
$properties ['rel-width'] = $properties ['width'];
unset($properties ['width']);
}
// Convert property 'border-model' to ODT
if ( !empty ($properties ['border-model']) ) {
if ( $properties ['border-model'] == 'collapse' ) {
$properties ['border-model'] = 'collapsing';
} else {
$properties ['border-model'] = 'separating';
}
}
// Create style name (if not given).
$style_name = $properties ['style-name'];
if ( empty($style_name) ) {
$style_name = self::getNewStylename ('Table');
$properties ['style-name'] = $style_name;
}
// Create empty table style.
$object = new ODTTableStyle();
if ($object == NULL) {
return NULL;
}
// Import our properties
$object->importProperties($properties, $disabled_props);
return $object;
}
}

View File

@@ -0,0 +1,376 @@
<?php
/**
* ODTTextListStyle: class for ODT text list styles.
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author LarsDW223
*/
require_once DOKU_INC.'lib/plugins/odt/ODT/XMLUtil.php';
require_once DOKU_INC.'lib/plugins/odt/ODT/styles/ODTStyle.php';
require_once DOKU_INC.'lib/plugins/odt/ODT/styles/ODTTextStyle.php';
/**
* The ODTTextListStyle class
*/
class ODTTextListStyle extends ODTStyle
{
static $list_fields = array(
// Fields belonging to "text:list-style"
'style-name' => array ('style:name', 'style', false),
'style-display-name' => array ('style:display-name', 'style', false),
'consecutive-numbering' => array ('text:consecutive-numbering', 'style', true),
);
static $style_number_fields = array(
// Fields belonging to "text:list-level-style-number"
'level' => array ('text:level', 'style-attr', true),
'text-style-name' => array ('text:style-name', 'style-attr', true),
'num-format' => array ('style:num-format', 'style-attr', true),
'num-letter-sync' => array ('style:num-letter-sync', 'style-attr', true),
'num-prefix' => array ('style:num-prefix', 'style-attr', true),
'num-suffix' => array ('style:num-suffix', 'style-attr', true),
'display-levels' => array ('text:display-levels', 'style-attr', true),
'start-value' => array ('text:start-value', 'style-attr', true),
);
static $style_bullet_fields = array(
// Fields belonging to "text:list-level-style-bullet"
'level' => array ('text:level', 'style-attr', true),
'text-style-name' => array ('text:style-name', 'style-attr', true),
'text-bullet-char' => array ('text:bullet-char', 'style-attr', true),
'num-prefix' => array ('style:num-prefix', 'style-attr', true),
'num-suffix' => array ('style:num-suffix', 'style-attr', true),
'text-bullet-relative-size' => array ('text:bullet-relative-size', 'style-attr', true),
);
static $style_image_fields = array(
// Fields belonging to "text:list-level-style-image"
'level' => array ('text:level', 'style-attr', true),
'type' => array ('xlink:type', 'style-attr', true),
'href' => array ('xlink:href', 'style-attr', true),
'show' => array ('xlink:show', 'style-attr', true),
'actuate' => array ('xlink:actuate', 'style-attr', true),
'binary-data' => array ('office:binary-data', 'style-attr', true),
'base64Binary' => array ('base64Binary', 'style-attr', true),
);
static $list_level_props_fields = array(
// Fields belonging to "style-list-level-properties"
'text-align' => array ('fo:text-align', 'level-list', true),
'text-space-before' => array ('text:space-before', 'level-list', true),
'text-min-label-width' => array ('text:min-label-width', 'level-list', true),
'text-min-label-distance' => array ('text:min-label-distance', 'level-list', true),
'font-name' => array ('style:font-name', 'level-list', true),
'width' => array ('fo:width', 'level-list', true),
'height' => array ('fo:height', 'level-list', true),
'vertical-rel' => array ('style:vertical-rel', 'level-list', true),
'vertical-pos' => array ('style:vertical-pos', 'level-list', true),
'list-level-position-and-space-mode' => array ('text:list-level-position-and-space-mode', 'level-list', true),
);
static $label_align_fields = array(
// Fields belonging to "style:list-level-label-alignment"
'label-followed-by' => array ('text:label-followed-by', 'level-label', true),
'list-tab-stop-position' => array ('text:list-tab-stop-position', 'level-label', true),
'text-indent' => array ('fo:text-indent', 'level-label', true),
'margin-left' => array ('fo:margin-left', 'level-label', true),
);
protected $list_level_styles = array();
/**
* Get the element name for the ODT XML encoding of the style.
*/
public function getElementName() {
return 'text:list-style';
}
/**
* Set style properties by importing values from a properties array.
* Properties might be disabled by setting them in $disabled.
* The style must have been previously created.
*
* @param $properties Properties to be imported
* @param $disabled Properties to be ignored
*/
public function importProperties($properties, $disabled=array()) {
$this->importPropertiesInternal(ODTTextStyle::getTextProperties (), $properties, $disabled);
$this->importPropertiesInternal(self::$list_fields, $properties, $disabled);
}
/**
* Check if a style is a common style.
*
* @return bool Is common style
*/
public function mustBeCommonStyle() {
return false;
}
/**
* Set a property.
* For a TextListStyle we can only set the style main properties here.
* All properties specific for a level need to be set using setPropertyForLevel().
*
* @param $property The name of the property to set
* @param $value New value to set
*/
public function setProperty($property, $value) {
if (array_key_exists ($property, self::$list_fields)) {
$this->setPropertyInternal
($property, self::$list_fields [$property][0], $value, self::$list_fields [$property][1]);
return;
}
}
/**
* Create new style by importing ODT style definition.
*
* @param $xmlCode Style definition in ODT XML format
* @return ODTStyle New specific style
*/
static public function importODTStyle($xmlCode) {
$style = new ODTTextListStyle();
$attrs = 0;
$open = XMLUtil::getElementOpenTag('text:list-style', $xmlCode);
if (!empty($open)) {
// This properties are stored in the properties of ODTStyle
$attrs += $style->importODTStyleInternal(self::$list_fields, $open);
$content = XMLUtil::getElementContent('text:list-style', $xmlCode);
}
$pos = 0;
$end = 0;
$max = strlen ($content);
$text_fields = ODTTextStyle::getTextProperties ();
while ($pos < $max)
{
// Get XML code for next level.
$level = XMLUtil::getNextElement($element, substr($content, $pos), $end);
$level_content = XMLUtil::getNextElementContent($element, $level, $ignore);
if (!empty($level)) {
$list_style_properties = array();
$list_level_properties = array();
$label_properties = array();
$text_properties = array();
$properties = array();
switch ($element) {
case 'text:list-level-style-number':
$attrs += $style->importODTStyleInternal(self::$style_number_fields, $level, $list_style_properties);
$list_level_style = 'number';
break;
case 'text:list-level-style-bullet':
$attrs += $style->importODTStyleInternal(self::$style_bullet_fields, $level, $list_style_properties);
$list_level_style = 'bullet';
break;
case 'text:list-level-style-image':
$attrs += $style->importODTStyleInternal(self::$style_image_fields, $level, $list_style_properties);
$list_level_style = 'image';
break;
}
$temp_content = XMLUtil::getElement('style:text-properties', $level_content);
$attrs += $style->importODTStyleInternal($text_fields, $temp_content, $text_properties);
$temp_content = XMLUtil::getElementOpenTag('style:list-level-properties', $level_content);
$attrs += $style->importODTStyleInternal(self::$list_level_props_fields, $temp_content, $list_level_properties);
$temp_content = XMLUtil::getElement('style:list-level-label-alignment', $level_content);
$attrs += $style->importODTStyleInternal(self::$label_align_fields, $temp_content, $label_properties);
// Assign properties array to our level array
$level_number = $style->getPropertyInternal('level', $list_style_properties);
$properties ['list-style'] = $list_style_properties;
$properties ['list-level'] = $list_level_properties;
$properties ['label'] = $label_properties;
$properties ['text'] = $text_properties;
$style->list_level_styles [$level_number] = $properties;
// Set special property 'list-level-style' to remember element to encode
// on call to toString()!
$style->setPropertyForLevel($level_number, 'list-level-style', $list_level_style);
}
$pos += $end;
}
// If style has no meaningfull content then throw it away
if ( $attrs == 0 ) {
return NULL;
}
return $style;
}
/**
* Encode current style values in a string and return it.
*
* @return string ODT XML encoded style
*/
public function toString() {
$style = '';
$levels = '';
// The style properties are stored in the properties of ODTStyle
foreach ($this->properties as $property => $items) {
$style .= $items ['odt_property'].'="'.$items ['value'].'" ';
}
// The level properties are stored in our level properties
$level_number = 0;
foreach ($this->list_level_styles as $key => $properties) {
$level_number++;
$element = $this->getPropertyFromLevel($level_number, 'list-level-style');
switch ($element) {
case 'number':
$fields = self::$style_number_fields;
break;
case 'bullet':
$fields = self::$style_bullet_fields;
break;
case 'image':
$fields = self::$style_image_fields;
break;
}
$element = 'text:list-level-style-'.$element;
$style_attr = '';
foreach ($this->list_level_styles [$level_number]['list-style'] as $property => $items) {
// Only add fields/properties which are allowed for the specific list-level-style
if ($property != 'list-level-style' && array_key_exists ($property, $fields)) {
$style_attr .= $items ['odt_property'].'="'.$items ['value'].'" ';
}
}
$level_list = '';
foreach ($this->list_level_styles [$level_number]['list-level'] as $property => $items) {
$level_list .= $items ['odt_property'].'="'.$items ['value'].'" ';
}
$level_label = '';
foreach ($this->list_level_styles [$level_number]['label'] as $property => $items) {
$level_label .= $items ['odt_property'].'="'.$items ['value'].'" ';
}
$text = '';
foreach ($this->list_level_styles [$level_number]['text'] as $property => $items) {
$text .= $items ['odt_property'].'="'.$items ['value'].'" ';
}
$levels .= ' <'.$element.' '.$style_attr.">\n";
if (!empty($level_list)) {
if (empty($level_label)) {
$levels .= ' <style:list-level-properties '.$level_list."/>\n";
} else {
$levels .= ' <style:list-level-properties '.$level_list.">\n";
$levels .= ' <style:list-level-label-alignment '.$level_label."/>\n";
$levels .= " </style:list-level-properties>\n";
}
}
if (!empty($text)) {
$levels .= ' <style:text-properties '.$text.'/>'."\n";
}
$levels .= " </".$element.">\n";
}
// Build style.
$element = $this->getElementName();
$style = '<'.$element.' '.$style.">\n";
if ( !empty($levels) ) {
$style .= $levels;
}
$style .= '</'.$element.">\n";
return $style;
}
/**
* Get the value of a property for text outline level $level.
*
* @param $level The text outline level (usually 1 to 10)
* @param $property The property name
* @return string The current value of the property
*/
public function getPropertyFromLevel($level, $property) {
if ($property == 'list-level-style') {
// Property 'list-level-style' is a special property just to remember
// which element needs to be encoded on a call to toString().
// It may not be included in the output of toString()!!!
return $this->getPropertyInternal('list-level-style', $this->list_level_styles [$level]['list-style']);
}
$text_fields = ODTTextStyle::getTextProperties ();
if (array_key_exists ($property, $text_fields)) {
return $this->getPropertyInternal($property, $this->list_level_styles [$level]['text']);
}
$element = $this->getPropertyInternal('list-level-style', $this->list_level_styles [$level]['list-style']);
switch ($element) {
case 'number':
$fields = self::$style_number_fields;
break;
case 'bullet':
$fields = self::$style_bullet_fields;
break;
case 'image':
$fields = self::$style_image_fields;
break;
}
if (array_key_exists ($property, $fields)) {
return $this->getPropertyInternal($property, $this->list_level_styles [$level]['list-style']);
}
if (array_key_exists ($property, self::$list_level_props_fields)) {
return $this->getPropertyInternal($property, $this->list_level_styles [$level]['list-level']);
}
if (array_key_exists ($property, self::$label_align_fields)) {
return $this->getPropertyInternal($property, $this->list_level_styles [$level]['label']);
}
}
/**
* Set a property for a specific level.
*
* @param $level The level for which to set the property (1 to 10)
* @param $property The name of the property to set
* @param $value New value to set
*/
public function setPropertyForLevel($level, $property, $value) {
if ($property == 'list-level-style') {
// Property 'list-level-style' is a special property just to remember
// which element needs to be encoded on a call to toString().
// It may not be included in the output of toString()!!!
$this->setPropertyInternal
($property, 'list-level-style', $value, 'list-level-style', $this->list_level_styles [$level]['list-style']);
} else {
// First check fields/properties common to each list-level-style
$text_fields = ODTTextStyle::getTextProperties ();
if (array_key_exists ($property, $text_fields)) {
$this->setPropertyInternal
($property, $text_fields [$property][0], $value, $text_fields [$property][1], $this->list_level_styles [$level]['text']);
return;
}
if (array_key_exists ($property, self::$list_level_props_fields)) {
$this->setPropertyInternal
($property, self::$list_level_props_fields [$property][0], $value, self::$list_level_props_fields [$property][1], $this->list_level_styles [$level]['list-level']);
return;
}
if (array_key_exists ($property, self::$label_align_fields)) {
$this->setPropertyInternal
($property, self::$label_align_fields [$property][0], $value, self::$label_align_fields [$property][1], $this->list_level_styles [$level]['label']);
return;
}
// Now check fields specific to the list-level-style.
$element = $this->getPropertyFromLevel ($level, 'list-level-style');
switch ($element) {
case 'number':
$fields = self::$style_number_fields;
break;
case 'bullet':
$fields = self::$style_bullet_fields;
break;
case 'image':
$fields = self::$style_image_fields;
break;
}
if (array_key_exists ($property, $fields)) {
$this->setPropertyInternal
($property, $fields [$property][0], $value, $fields [$property][1], $this->list_level_styles [$level]['list-style']);
}
}
}
}

View File

@@ -0,0 +1,242 @@
<?php
/**
* ODTTextOutlineStyle: class for ODT text outline styles.
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author LarsDW223
*/
require_once DOKU_INC.'lib/plugins/odt/ODT/XMLUtil.php';
require_once DOKU_INC.'lib/plugins/odt/ODT/styles/ODTStyle.php';
require_once DOKU_INC.'lib/plugins/odt/ODT/styles/ODTTextStyle.php';
/**
* The ODTTextOutlineStyle class
*/
class ODTTextOutlineStyle extends ODTStyle
{
static $outline_fields = array(
// Fields belonging to "text:outline-style"
'style-name' => array ('style:name', 'style', false),
// Fields belonging to "text:outline-level-style"
'level' => array ('text:level', 'level', true),
'text-style-name' => array ('text:style-name', 'level', true),
'num-format' => array ('style:num-format', 'level', true),
'num-letter-sync' => array ('style:num-letter-sync', 'level', true),
'num-prefix' => array ('style:num-prefix', 'level', true),
'num-suffix' => array ('style:num-suffix', 'level', true),
'display-levels' => array ('text:display-levels', 'level', true),
'start-value' => array ('text:start-value', 'level', true),
// Fields belonging to "style-list-level-properties"
'text-align' => array ('fo:text-align', 'level-list', true),
'text-space-before' => array ('text:space-before', 'level-list', true),
'text-min-label-width' => array ('text:min-label-width', 'level-list', true),
'text-min-label-distance' => array ('text:min-label-distance', 'level-list', true),
'font-name' => array ('style:font-name', 'level-list', true),
'width' => array ('fo:width', 'level-list', true),
'height' => array ('fo:height', 'level-list', true),
'vertical-rel' => array ('style:vertical-rel', 'level-list', true),
'vertical-pos' => array ('style:vertical-pos', 'level-list', true),
'list-level-position-and-space-mode' => array ('text:list-level-position-and-space-mode', 'level-list', true),
// Fields belonging to "style:list-level-label-alignment"
'label-followed-by' => array ('text:label-followed-by', 'level-label', true),
'list-tab-stop-position' => array ('text:list-tab-stop-position', 'level-label', true),
'text-indent' => array ('fo:text-indent', 'level-label', true),
'margin-left' => array ('fo:margin-left', 'level-label', true),
);
protected $outline_level_styles = array();
/**
* Get the element name for the ODT XML encoding of the style.
*/
public function getElementName() {
return 'text:outline-style';
}
/**
* Set style properties by importing values from a properties array.
* Properties might be disabled by setting them in $disabled.
* The style must have been previously created.
*
* @param $properties Properties to be imported
* @param $disabled Properties to be ignored
*/
public function importProperties($properties, $disabled=array()) {
$this->importPropertiesInternal(ODTTextStyle::getTextProperties (), $properties, $disabled);
$this->importPropertiesInternal(self::$outline_fields, $properties, $disabled);
}
/**
* Check if a style is a common style.
*
* @return bool Is common style
*/
public function mustBeCommonStyle() {
return false;
}
/**
* Set a property.
*
* @param $property The name of the property to set
* @param $value New value to set
*/
public function setProperty($property, $value) {
$text_fields = ODTTextStyle::getTextProperties ();
if (array_key_exists ($property, $style_fields)) {
$this->setPropertyInternal
($property, $text_fields [$property][0], $value, $text_fields [$property][1]);
return;
}
if (array_key_exists ($property, self::$outline_fields)) {
$this->setPropertyInternal
($property, self::$outline_fields [$property][0], $value, self::$outline_fields [$property][1]);
return;
}
}
/**
* Create new style by importing ODT style definition.
*
* @param $xmlCode Style definition in ODT XML format
* @return ODTStyle New specific style
*/
static public function importODTStyle($xmlCode) {
$style = new ODTTextOutlineStyle();
$attrs = 0;
$open = XMLUtil::getElementOpenTag('text:outline-style', $xmlCode);
if (!empty($open)) {
// This properties are stored in the properties of ODTStyle
$attrs += $style->importODTStyleInternal(self::$outline_fields, $open);
}
$pos = 0;
$end = 0;
$max = strlen ($xmlCode);
$level = XMLUtil::getElement('text:outline-level-style', substr($xmlCode, $pos), $end);
$pos += $end;
$text_fields = ODTTextStyle::getTextProperties ();
$check = 0;
while ($level != NULL)
{
// We can have multiple level definitons with all the same properties.
// So we store this in our own array. The "text:level" is the array key.
if (!empty($level)) {
$properties = array();
$attrs += $style->importODTStyleInternal($text_fields, $level, $properties);
$attrs += $style->importODTStyleInternal(self::$outline_fields, $level, $properties);
// Assign properties array to our level array
$level_number = $style->getPropertyInternal('level', $properties);
$style->outline_level_styles [$level_number] = $properties;
}
// Get XML code for next level.
$level = XMLUtil::getElement('text:outline-level-style', substr($xmlCode, $pos), $end);
$pos += $end;
if ($pos >= $max) {
break;
}
}
// If style has no meaningfull content then throw it away
if ( $attrs == 0 ) {
return NULL;
}
return $style;
}
/**
* Encode current style values in a string and return it.
*
* @return string ODT XML encoded style
*/
public function toString() {
$style = '';
$levels = '';
// The style properties are stored in the properties of ODTStyle
foreach ($this->properties as $property => $items) {
$style .= $items ['odt_property'].'="'.$items ['value'].'" ';
}
// The level properties are stored in our level properties
foreach ($this->outline_level_styles as $key => $properties) {
$level = '';
$level_list = '';
$level_label = '';
$text = '';
foreach ($properties as $property => $items) {
switch ($items ['section']) {
case 'level':
$level .= $items ['odt_property'].'="'.$items ['value'].'" ';
break;
case 'level-list':
$level_list .= $items ['odt_property'].'="'.$items ['value'].'" ';
break;
case 'level-label':
$level_label .= $items ['odt_property'].'="'.$items ['value'].'" ';
break;
case 'text':
$text .= $items ['odt_property'].'="'.$items ['value'].'" ';
break;
}
}
$levels .= ' <text:outline-level-style '.$level.">\n";
if (!empty($level_list)) {
if (empty($level_label)) {
$levels .= ' <style:list-level-properties '.$level_list."/>\n";
} else {
$levels .= ' <style:list-level-properties '.$level_list.">\n";
$levels .= ' <style:list-level-label-alignment '.$level_label."/>\n";
$levels .= " </style:list-level-properties>\n";
}
}
if (!empty($text)) {
$levels .= ' <style:text-properties '.$text.'/>';
}
$levels .= " </text:outline-level-style>\n";
}
// Build style.
$element = $this->getElementName();
$style = '<'.$element.' '.$style.">\n";
if ( !empty($levels) ) {
$style .= $levels;
}
$style .= '</'.$element.">\n";
return $style;
}
/**
* Get the value of a property for text outline level $level.
*
* @param $level The text outline level (usually 1 to 10)
* @param $property The property name
* @return string The current value of the property
*/
public function getPropertyFromLevel($level, $property) {
return $this->getPropertyInternal($property, $this->outline_level_styles [$level]);
}
/**
* Set a property.
*
* @param $property The name of the property to set
* @param $value New value to set
*/
public function setPropertyForLevel($level, $property, $value) {
if (array_key_exists ($property, self::$outline_fields)) {
$this->setPropertyInternal
($property, self::$outline_fields [$property][0], $value, self::$outline_fields [$property][1], $this->outline_level_styles [$level]);
return;
}
}
}

View File

@@ -0,0 +1,337 @@
<?php
/**
* ODTTextStyle: class for ODT text styles.
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author LarsDW223
*/
require_once DOKU_PLUGIN . 'odt/ODT/XMLUtil.php';
require_once 'ODTStyle.php';
ODTStyleStyle::register('ODTTextStyle');
/**
* The ODTTextStyle class
*/
class ODTTextStyle extends ODTStyleStyle
{
static $text_fields = array(
'padding' => array ('fo:padding', 'text', true),
'padding-top' => array ('fo:padding-top', 'text', true),
'padding-right' => array ('fo:padding-right', 'text', true),
'padding-bottom' => array ('fo:padding-bottom', 'text', true),
'padding-left' => array ('fo:padding-left', 'text', true),
'border' => array ('fo:border', 'text', true),
'border-top' => array ('fo:border-top', 'text', true),
'border-right' => array ('fo:border-right', 'text', true),
'border-bottom' => array ('fo:border-bottom', 'text', true),
'border-left' => array ('fo:border-left', 'text', true),
'color' => array ('fo:color', 'text', true),
'background-color' => array ('fo:background-color', 'text', true),
'background-image' => array ('fo:background-image', 'text', true),
'font-style' => array ('fo:font-style', 'text', true),
'font-style-asian' => array ('style:font-style-asian', 'text', true),
'font-style-complex' => array ('style:font-style-complex', 'text', true),
'font-weight' => array ('fo:font-weight', 'text', true),
'font-weight-asian' => array ('style:font-weight-asian', 'text', true),
'font-weight-complex' => array ('style:font-weight-complex', 'text', true),
'font-size' => array ('fo:font-size', 'text', true),
'font-size-asian' => array ('style:font-size-asian', 'text', true),
'font-size-complex' => array ('style:font-size-complex', 'text', true),
'font-family' => array ('fo:font-family', 'text', true),
'font-family-asian' => array ('style:font-family-asian', 'text', true),
'font-family-complex' => array ('style:font-family-complex', 'text', true),
'font-variant' => array ('fo:font-variant', 'text', true),
'letter-spacing' => array ('fo:letter-spacing', 'text', true),
'vertical-align' => array ('style:vertical-align', 'text', true),
'display' => array ('text:display', 'text', true),
'lang' => array ('fo:language', 'text', true),
'lang-asian' => array ('style:language-asian', 'text', true),
'lang-complex' => array ('style:language-complex', 'text', true),
'country' => array ('fo:country', 'text', true),
'country-asian' => array ('style:country-asian', 'text', true),
'country-complex' => array ('style:country-complex', 'text', true),
'text-transform' => array ('fo:text-transform', 'text', true),
'use-window-font-color' => array ('style:use-window-font-color', 'text', true),
'text-outline' => array ('style:text-outline', 'text', true),
'text-line-through-type' => array ('style:text-line-through-type', 'text', true),
'text-line-through-style' => array ('style:text-line-through-style', 'text', true),
'text-line-through-width' => array ('style:text-line-through-width', 'text', true),
'text-line-through-color' => array ('style:text-line-through-color', 'text', true),
'text-line-through-text' => array ('style:text-line-through-text', 'text', true),
'text-line-through-text-style' => array ('style:text-line-through-text-style', 'text', true),
'text-position' => array ('style:text-position', 'text', true),
'font-name' => array ('style:font-name', 'text', true),
'font-name-asian' => array ('style:font-name-asian', 'text', true),
'font-name-complex' => array ('style:font-name-complex', 'text', true),
'font-family-generic' => array ('style:font-family-generic', 'text', true),
'font-family-generic-asian' => array ('style:font-family-generic-asian', 'text', true),
'font-family-generic-complex' => array ('style:font-family-generic-complex', 'text', true),
'font-style-name' => array ('style:font-style-name', 'text', true),
'font-style-name-asian' => array ('style:font-style-name-asian', 'text', true),
'font-style-name-complex' => array ('style:font-style-name-complex', 'text', true),
'font-pitch' => array ('style:font-pitch', 'text', true),
'font-pitch-asian' => array ('style:font-pitch-asian', 'text', true),
'font-pitch-complex' => array ('style:font-pitch-complex', 'text', true),
'font-charset' => array ('style:font-charset', 'text', true),
'font-charset-asian' => array ('style:font-charset-asian', 'text', true),
'font-charset-complex' => array ('style:font-charset-complex', 'text', true),
'font-size-rel' => array ('style:font-size-rel', 'text', true),
'font-size-rel-asian' => array ('style:font-size-rel-asian', 'text', true),
'font-size-rel-complex' => array ('style:font-size-rel-complex', 'text', true),
'script-type' => array ('style:script-type', 'text', true),
'script' => array ('fo:script', 'text', true),
'script-asian' => array ('style:script-asian', 'text', true),
'script-complex' => array ('style:script-complex', 'text', true),
'rfc-language-tag' => array ('style:rfc-language-tag', 'text', true),
'rfc-language-tag-asian' => array ('style:rfc-language-tag-asian', 'text', true),
'rfc-language-tag-complex' => array ('style:rfc-language-tag-complex', 'text', true),
'rfc-language-tag-complex' => array ('style:rfc-language-tag-complex', 'text', true),
'font-relief' => array ('style:font-relief', 'text', true),
'text-shadow' => array ('fo:text-shadow', 'text', true),
'text-underline-type' => array ('style:text-underline-type', 'text', true),
'text-underline-style' => array ('style:text-underline-style', 'text', true),
'text-underline-width' => array ('style:text-underline-width', 'text', true),
'text-underline-color' => array ('style:text-underline-color', 'text', true),
'text-overline-type' => array ('style:text-overline-type', 'text', true),
'text-overline-style' => array ('style:text-overline-style', 'text', true),
'text-overline-width' => array ('style:text-overline-width', 'text', true),
'text-overline-color' => array ('style:text-overline-color', 'text', true),
'text-overline-mode' => array ('style:text-overline-mode', 'text', true),
'text-underline-mode' => array ('style:text-underline-mode', 'text', true),
'text-line-through-mode' => array ('style:text-line-through-mode', 'text', true),
'letter-kerning' => array ('style:letter-kerning', 'text', true),
'text-blinking' => array ('style:text-blinking', 'text', true),
'text-combine' => array ('style:text-combine', 'text', true),
'text-combine-start-char' => array ('style:text-combine-start-char', 'text', true),
'text-combine-end-char' => array ('style:text-combine-end-char', 'text', true),
'text-emphasize' => array ('style:text-emphasize', 'text', true),
'text-scale' => array ('style:text-scale', 'text', true),
'text-rotation-angle' => array ('style:text-rotation-angle', 'text', true),
'text-rotation-scale' => array ('style:text-rotation-scale', 'text', true),
'hyphenate' => array ('fo:hyphenate', 'text', true),
'hyphenation-remain-char-count' => array ('fo:hyphenation-remain-char-count', 'text', true),
'hyphenation-push-char-count' => array ('fo:hyphenation-push-char-count', 'text', true),
'condition' => array ('text:condition', 'text', true),
);
/**
* Constructor.
*/
public function __construct() {
parent::__construct();
}
/**
* Set style properties by importing values from a properties array.
* Properties might be disabled by setting them in $disabled.
* The style must have been previously created.
*
* @param $properties Properties to be imported
* @param $disabled Properties to be ignored
*/
public function importProperties($properties, $disabled=array()) {
$this->importPropertiesInternal(ODTStyleStyle::getStyleProperties (), $properties, $disabled);
$this->importPropertiesInternal(self::$text_fields, $properties, $disabled);
$this->setProperty('style-family', $this->getFamily());
}
/**
* Check if a style is a common style.
*
* @return bool Is common style
*/
public function mustBeCommonStyle() {
return false;
}
/**
* Get the style family of a style.
*
* @return string Style family
*/
static public function getFamily() {
return 'text';
}
/**
* Set a property.
*
* @param $property The name of the property to set
* @param $value New value to set
*/
public function setProperty($property, $value) {
$style_fields = ODTStyleStyle::getStyleProperties ();
if (array_key_exists ($property, $style_fields)) {
$this->setPropertyInternal
($property, $style_fields [$property][0], $value, $style_fields [$property][1]);
return;
}
if (array_key_exists ($property, self::$text_fields)) {
$this->setPropertyInternal
($property, self::$text_fields [$property][0], $value, self::$text_fields [$property][1]);
return;
}
}
/**
* Create new style by importing ODT style definition.
*
* @param $xmlCode Style definition in ODT XML format
* @return ODTStyle New specific style
*/
static public function importODTStyle($xmlCode) {
$style = new ODTTextStyle();
$attrs = 0;
$open = XMLUtil::getElementOpenTag('style:style', $xmlCode);
if (!empty($open)) {
$attrs += $style->importODTStyleInternal(ODTStyleStyle::getStyleProperties (), $open);
} else {
$open = XMLUtil::getElementOpenTag('style:default-style', $xmlCode);
if (!empty($open)) {
$style->setDefault(true);
$attrs += $style->importODTStyleInternal(ODTStyleStyle::getStyleProperties (), $open);
}
}
$open = XMLUtil::getElementOpenTag('style:text-properties', $xmlCode);
if (!empty($open)) {
$attrs += $style->importODTStyleInternal(self::$text_fields, $open);
}
// If style has no meaningfull content then throw it away
if ( $attrs == 0 ) {
return NULL;
}
return $style;
}
static public function getTextProperties () {
return self::$text_fields;
}
/**
* This function creates a text style using the style as set in the assoziative array $properties.
* The parameters in the array should be named as the CSS property names e.g. 'color' or 'background-color'.
* Properties which shall not be used in the style can be disabled by setting the value in disabled_props
* to 1 e.g. $disabled_props ['color'] = 1 would block the usage of the color property.
*
* The currently supported properties are:
* background-color, color, font-style, font-weight, font-size, border, font-family, font-variant, letter-spacing,
* vertical-align, background-image
*
* The function returns the name of the new style or NULL if all relevant properties are empty.
*
* @author LarsDW223
* @param $properties
* @param null $disabled_props
* @return ODTTextStyle or NULL
*/
public static function createTextStyle(array $properties, array $disabled_props = NULL, ODTDocument $doc=NULL){
// Convert 'text-decoration'.
if ( $properties ['text-decoration'] == 'line-through' ) {
$properties ['text-line-through-style'] = 'solid';
}
if ( $properties ['text-decoration'] == 'underline' ) {
$properties ['text-underline-style'] = 'solid';
}
if ( $properties ['text-decoration'] == 'overline' ) {
$properties ['text-overline-style'] = 'solid';
}
// If the property 'vertical-align' has the value 'sub' or 'super'
// then for ODT it needs to be converted to the corresponding 'text-position' property.
// Replace sub and super with text-position.
$valign = $properties ['vertical-align'];
if (!empty($valign)) {
if ( $valign == 'sub' ) {
$properties ['text-position'] = '-33% 100%';
unset($properties ['vertical-align']);
} elseif ( $valign == 'super' ) {
$properties ['text-position'] = '33% 100%';
unset($properties ['vertical-align']);
}
}
// Separate country from language
$lang = $properties ['lang'];
$country = $properties ['country'];
if ( !empty($lang) ) {
$parts = preg_split ('/-/', $lang);
$lang = $parts [0];
$country = $parts [1];
$properties ['country'] = trim($country);
$properties ['lang'] = trim($lang);
}
if (!empty($properties ['country'])) {
if (empty($properties ['country-asian'])) {
$properties ['country-asian'] = $properties ['country'];
}
if (empty($properties ['country-complex'])) {
$properties ['country-complex'] = $properties ['country'];
}
}
// Extra handling for font-size in '%'
$save = $disabled_props ['font-size'];
$odt_fo_size = '';
if ( empty ($disabled_props ['font-size']) ) {
$odt_fo_size = $properties ['font-size'];
}
$length = strlen ($odt_fo_size);
if ( $length > 0 && $odt_fo_size [$length-1] == '%' && $doc != NULL) {
// A font-size in percent is only supported in common style definitions, not in automatic
// styles. Create a common style and set it as parent for this automatic style.
$name = 'Size'.trim ($odt_fo_size, '%').'pc';
$style_obj = self::createSizeOnlyTextStyle ($name, $odt_fo_size);
$doc->addStyle($style_obj);
$parent = $style_obj->getProperty('style-name');
if (!empty($parent)) {
$properties ['style-parent'] = $parent;
}
}
// Create style name (if not given).
$style_name = $properties ['style-name'];
if ( empty($style_name) ) {
$style_name = self::getNewStylename ('Text');
$properties ['style-name'] = $style_name;
}
// Create empty text style.
$object = new ODTTextStyle();
if ($object == NULL) {
return NULL;
}
// Import our properties
$object->importProperties($properties, $disabled_props);
// Restore $disabled_props
$disabled_props ['font-size'] = $save;
return $object;
}
/**
* Simple helper function for creating a text style $name setting the specfied font size $size.
*
* @author LarsDW223
*
* @param string $name
* @param string $size
* @return ODTTextStyle
*/
public static function createSizeOnlyTextStyle ($name, $size) {
$properties = array();
$properties ['style-name'] = $name;
$properties ['style-display-name'] = $name;
$properties ['font-size'] = $size;
$properties ['font-size-asian'] = $size;
$properties ['font-size-complex'] = $size;
return self::createTextStyle($properties);
}
}

View File

@@ -0,0 +1,227 @@
<?php
/**
* ODTUnknownStyle: class for unknown/not implemented ODT style families.
* The goal is to at least read in not supported style faimlies and return
* the original content on a call to toString().
*
* The following has to be taken into account:
* - the properties of an ODTUnknownStyle can not be changed.
* - so setProperty() and importProperties() will do nothing.
*
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
* @author LarsDW223
*/
require_once DOKU_INC.'lib/plugins/odt/ODT/styles/ODTStyle.php';
/**
* The ODTUnknownStyle class
*/
class ODTUnknownStyle extends ODTStyle
{
// At least try to read in a name
static $unknown_fields = array(
'style-name' => array ('style:name', 'style', false),
'style-family' => array ('style:family', 'style', false),
);
protected $element_name = NULL;
protected $style_content = NULL;
/**
* Get the element name for the ODT XML encoding of the style.
*
* @return string The element name
*/
public function getElementName() {
return ($this::element_name);
}
/**
* Set the element name.
*
* @param $element_name The element name to set
*/
public function setElementName($element_name) {
$this->element_name = $element_name;
}
/**
* Set style properties by importing values from a properties array.
* Properties might be disabled by setting them in $disabled.
* The style must have been previously created.
*
* Not supported, just a dummy!
*
* @param $properties Properties to be imported
* @param $disabled Properties to be ignored
*/
public function importProperties($properties, $disabled=array()) {
}
/**
* Check if a style is a common style.
*
* @return bool Is common style
*/
public function mustBeCommonStyle() {
return false;
}
/**
* Set a property.
*
* Not supported, just a dummy.
*
* @param $property The name of the property to set
* @param $value New value to set
*/
public function setProperty($property, $value) {
}
/**
* Set style content. This will be returned on toString().
*
* @param $style_content The complete ODT XML style definition.
*/
public function setStyleContent($style_content) {
$this->importODTStyleInternal(self::$unknown_fields, $style_content);
$this->style_content = $style_content."\n";
}
/**
* Create new style by importing ODT style definition.
*
* @param $xmlCode Style definition in ODT XML format
* @return ODTStyle New specific style
*/
static public function importODTStyle($xmlCode) {
$style = new ODTUnknownStyle();
$style->setStyleContent($xmlCode);
return $style;
}
/**
* Encode current style values in a string and return it.
*
* @return string ODT XML encoded style
*/
public function toString() {
return $this->style_content;
}
/**
* Is the style a default style?
*
* @return boolean Is default.
*/
public function isDefault() {
if ($this->element_name == 'style:default-style') {
return true;
}
return false;
}
/**
* Get the style family of a style.
*
* @return string|NULL Style family
*/
public function getFamily() {
return $this->getProperty('style-family');
}
/**
* The function deletes all properties that do not belong to the styles section,
* e.g. text properties or paragraph properties.
* For unknown styles this is just a dummy doing nothing.
*/
public function clearLayoutProperties() {
}
/**
* This function creates a frame style for multiple columns, using the style as set in the assoziative array $properties.
* The parameters in the array should be named as the CSS property names e.g. 'color' or 'background-color'.
* Properties which shall not be used in the style can be disabled by setting the value in disabled_props
* to 1 e.g. $disabled_props ['color'] = 1 would block the usage of the color property.
*
* The currently supported properties are:
* column-count, column-rule, column-gap
*
* The function returns the name of the new style or NULL if all relevant properties are empty.
*
* @author LarsDW223
*
* @param $style
* @param $properties
* @param null $disabled_props
* @return ODTUnknownStyle or NULL
*/
public static function createMultiColumnFrameStyle(array $properties, array $disabled_props = NULL) {
$attrs = 0;
$columns = '';
if ( empty ($disabled_props ['column-count']) ) {
$columns = $properties ['column-count'];
$attrs++;
}
$rule_width = '';
if ( empty ($disabled_props ['column-rule-width']) ) {
$rule_width = $properties ['column-rule-width'];
$attrs++;
}
$rule_style = '';
if ( empty ($disabled_props ['column-rule-style']) ) {
$rule_style = $properties ['column-rule-style'];
$attrs++;
}
$rule_color = '';
if ( empty ($disabled_props ['column-rule-color']) ) {
$rule_color = $properties ['column-rule-color'];
$attrs++;
}
$gap = '';
if ( empty ($disabled_props ['column-gap']) ) {
$gap = $properties ['column-gap'];
$attrs++;
}
// If all relevant properties are empty or disabled, then there
// are no attributes for our style. Return NULL to indicate 'no style required'.
if ( $attrs == 0 ) {
return NULL;
}
// Create style name (if not given).
$style_name = $properties ['style-name'];
if ( empty($style_name) ) {
$style_name = self::getNewStylename ('Frame');
$properties ['style-name'] = $style_name;
}
$width = '1000*';
$style = '<style:style style:name="'.$style_name.'" style:family="graphic" style:parent-style-name="Frame">
<style:graphic-properties fo:border="none" style:vertical-pos="top" style:vertical-rel="paragraph-content" style:horizontal-pos="center" style:horizontal-rel="paragraph">
<style:columns fo:column-count="'.$columns.'" fo:column-gap="'.$gap.'">
<style:column-sep style:style="'.$rule_style.'" style:color="'.$rule_color.'" style:width="'.$rule_width.'"/>
<style:column style:rel-width="'.$width.'" fo:start-indent="0cm" fo:end-indent="0cm"/>
<style:column style:rel-width="'.$width.'" fo:start-indent="0cm" fo:end-indent="0cm"/>
<style:column style:rel-width="'.$width.'" fo:start-indent="0cm" fo:end-indent="0cm"/>
</style:columns>
</style:graphic-properties></style:style>';
// Create empty frame style.
// Not supported yet, so we create an "unknown" style
$object = new ODTUnknownStyle();
if ($object == NULL) {
return NULL;
}
$object->setStyleContent($style);
return $object;
}
}