1<?php
2/**
3 * ODTTableStyle: class for ODT table styles.
4 *
5 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author     LarsDW223
7 * @package    ODT\Styles\ODTTableStyle
8 */
9
10/** Include XMLUtil and ODTStyle */
11require_once DOKU_INC.'lib/plugins/odt/ODT/XMLUtil.php';
12require_once 'ODTStyle.php';
13
14ODTStyleStyle::register('ODTTableStyle');
15
16/**
17 * The ODTTableStyle class.
18 */
19class ODTTableStyle extends ODTStyleStyle
20{
21    /** var array List of properties belonging to an ODT table. */
22    static $table_fields = array(
23        'width'                      => array ('style:width',                      'table',  true),
24        'rel-width'                  => array ('style:rel-width',                  'table',  true),
25        'align'                      => array ('table:align',                      'table',  true),
26        'margin-left'                => array ('fo:margin-left',                   'table',  true),
27        'margin-right'               => array ('fo:margin-right',                  'table',  true),
28        'margin-top'                 => array ('fo:margin-top',                    'table',  true),
29        'margin-bottom'              => array ('fo:margin-bottom',                 'table',  true),
30        'margin'                     => array ('fo:margin',                        'table',  true),
31        'page-number'                => array ('style:page-number',                'table',  true),
32        'break-before'               => array ('fo:break-before',                  'table',  true),
33        'break-after'                => array ('fo:break-after',                   'table',  true),
34        'background-color'           => array ('fo:background-color',              'table',  true),
35        'shadow'                     => array ('style:shadow',                     'table',  true),
36        'keep-with-next'             => array ('fo:keep-with-next',                'table',  true),
37        'may-break-between-rows'     => array ('style:may-break-between-rows',     'table',  true),
38        'border-model'               => array ('table:border-model',               'table',  true),
39        'writing-mode'               => array ('style:writing-mode',               'table',  true),
40        'display'                    => array ('table:display',                    'table',  true),
41
42        // Fields for background-image
43        // (see '<define name="style-background-image"> in relax-ng schema)'
44        'repeat'                     => array ('style:repeat',                     'table-background-image',  true),
45        'position'                   => array ('style:position',                   'table-background-image',  true),
46        'style:filter-name'          => array ('style:filter-name',                'table-background-image',  true),
47        'opacity'                    => array ('draw:opacity',                     'table-background-image',  true),
48        'type'                       => array ('xlink:type',                       'table-background-image',  true),
49        'href'                       => array ('xlink:href',                       'table-background-image',  true),
50        'show'                       => array ('xlink:show',                       'table-background-image',  true),
51        'actuate'                    => array ('xlink:actuate',                    'table-background-image',  true),
52        'binary-data'                => array ('office:binary-data',               'table-background-image',  true),
53        'base64Binary'               => array ('base64Binary',                     'table-background-image',  true),
54    );
55
56    /**
57     * Constructor.
58     */
59    public function __construct() {
60        parent::__construct();
61    }
62
63    /**
64     * Set style properties by importing values from a properties array.
65     * Properties might be disabled by setting them in $disabled.
66     * The style must have been previously created.
67     *
68     * @param    $properties    Properties to be imported
69     * @param    $disabled      Properties to be ignored
70     */
71    public function importProperties($properties, $disabled=array()) {
72        $this->importPropertiesInternal(ODTStyleStyle::getStyleProperties (), $properties, $disabled);
73        $this->importPropertiesInternal(self::$table_fields, $properties, $disabled);
74        $this->setProperty('style-family', $this->getFamily());
75    }
76
77    /**
78     * Check if a style is a common style.
79     *
80     * @return    bool    Is common style
81     */
82    public function mustBeCommonStyle() {
83        return false;
84    }
85
86    /**
87     * Get the style family of a style.
88     *
89     * @return    string    Style family
90     */
91    static public function getFamily() {
92        return 'table';
93    }
94
95    /**
96     * Set a property.
97     *
98     * @param    $property    The name of the property to set
99     * @param    $value       New value to set
100     */
101    public function setProperty($property, $value) {
102        $style_fields = ODTStyleStyle::getStyleProperties ();
103        if (array_key_exists ($property, $style_fields)) {
104            $this->setPropertyInternal
105                ($property, $style_fields [$property][0], $value, $style_fields [$property][1]);
106            return;
107        }
108        if (array_key_exists ($property, self::$table_fields)) {
109            $this->setPropertyInternal
110                ($property, self::$table_fields [$property][0], $value, self::$table_fields [$property][1]);
111            return;
112        }
113    }
114
115    /**
116     * Create new style by importing ODT style definition.
117     *
118     * @param     $xmlCode    Style definition in ODT XML format
119     * @return    ODTStyle    New specific style
120     */
121    static public function importODTStyle($xmlCode) {
122        $style = new ODTTableStyle();
123        $attrs = 0;
124
125        $open = XMLUtil::getElementOpenTag('style:style', $xmlCode);
126        if (!empty($open)) {
127            $attrs += $style->importODTStyleInternal(ODTStyleStyle::getStyleProperties (), $open);
128        } else {
129            $open = XMLUtil::getElementOpenTag('style:default-style', $xmlCode);
130            if (!empty($open)) {
131                $style->setDefault(true);
132                $attrs += $style->importODTStyleInternal(ODTStyleStyle::getStyleProperties (), $open);
133            }
134        }
135
136        $open = XMLUtil::getElementOpenTag('style:table-properties', $xmlCode);
137        if (!empty($open)) {
138            $attrs += $style->importODTStyleInternal(self::$table_fields, $open);
139        }
140
141        // If style has no meaningfull content then throw it away
142        if ( $attrs == 0 ) {
143            return NULL;
144        }
145
146        return $style;
147    }
148
149    /**
150     * Return an array listing the properties belonging to an ODT table.
151     *
152     * @return    array    Properties
153     */
154    static public function getTableProperties () {
155        return self::$table_fields;
156    }
157
158    /**
159     * This function creates a table table style using the style as set in the assoziative array $properties.
160     * The parameters in the array should be named as the CSS property names e.g. 'color' or 'background-color'.
161     * Properties which shall not be used in the style can be disabled by setting the value in disabled_props
162     * to 1 e.g. $disabled_props ['color'] = 1 would block the usage of the color property.
163     *
164     * The currently supported properties are:
165     * width, border-collapse, background-color
166     *
167     * The function returns the name of the new style or NULL if all relevant properties are empty.
168     *
169     * @author    LarsDW223
170     * @param     array              $properties     Properties for the table style
171     * @param     array|null         $disabled_props Ignored properties.
172     * @param     int                $max_width_cm   Max. allowed table width.
173     * @return    ODTTableStyle|NULL
174     */
175    public static function createTableTableStyle(array $properties, array $disabled_props = NULL, $max_width_cm = 17){
176        // If we want to change the table width we must set table:align to something else
177        // than "margins". Otherwise the width will not be changed.
178        if (empty($properties ['align'])) {
179            $properties ['align'] = 'center';
180        }
181        if ($properties ['margin-left'] == '0') {
182            unset($properties ['margin-left']);
183        }
184        if ($properties ['margin-right'] == '0') {
185            unset($properties ['margin-right']);
186        }
187
188        // If no width specified always set 100%
189        if (empty ($properties ['width'])) {
190            $properties ['width'] = '100%';
191        }
192
193        // If relative width set, then move value to property 'rel-width'!
194        if ( $properties ['width'] [strlen($properties ['width'])-1] == '%' ) {
195            $properties ['rel-width'] = $properties ['width'];
196            unset($properties ['width']);
197        }
198
199        // Convert property 'border-model' to ODT
200        if ( !empty ($properties ['border-model']) ) {
201            if ( $properties ['border-model'] == 'collapse' ) {
202                $properties ['border-model'] = 'collapsing';
203            } else {
204                $properties ['border-model'] = 'separating';
205            }
206        }
207
208        // Create style name (if not given).
209        $style_name = $properties ['style-name'];
210        if ( empty($style_name) ) {
211            $style_name = self::getNewStylename ('Table');
212            $properties ['style-name'] = $style_name;
213        }
214
215        // Create empty table style.
216        $object = new ODTTableStyle();
217        if (!isset($object)) {
218            return NULL;
219        }
220
221        // Import our properties
222        $object->importProperties($properties, $disabled_props);
223        return $object;
224    }
225}
226
227