1<?php 2 3require_once DOKU_INC.'lib/plugins/odt/ODT/XMLUtil.php'; 4require_once DOKU_INC.'lib/plugins/odt/ODT/styles/ODTStyle.php'; 5 6/** 7 * ODTStyleSet: Abstract class defining the interface a style set/template 8 * needs to implement towards the ODT renderer. 9 * 10 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 11 * @author LarsDW223 12 */ 13abstract class ODTStyleSet 14{ 15 protected $styles = array(); 16 protected $styles_by_name = array(); 17 protected $auto_styles = array(); 18 protected $auto_styles_by_name = array(); 19 protected $master_styles = array(); 20 protected $master_styles_by_name = array(); 21 22 /** 23 * Read/import style source. 24 * 25 * @param $source (optional) 26 */ 27 abstract public function import($source); 28 29 /** 30 * Export $element styles (e.g. 'office:styles' or 'office:automatic-styles') 31 * 32 * @param $element The style element to export 33 * @return string The ODT XML encoded $element style 34 */ 35 abstract public function export($element); 36 37 /** 38 * The function needs to be able to return a style name 39 * for the following basic styles used by the renderer: 40 * - standard 41 * - body 42 * - heading1 43 * - heading2 44 * - heading3 45 * - heading4 46 * - heading5 47 * - heading6 48 * - list 49 * - numbering 50 * - table content 51 * - table heading 52 * - preformatted 53 * - source code 54 * - source file 55 * - horizontal line 56 * - footnote 57 * - emphasis 58 * - strong 59 * - graphics 60 * - monospace 61 * - quotation1 62 * - quotation2 63 * - quotation3 64 * - quotation4 65 * - quotation5 66 * 67 * @param $style 68 * @return mixed 69 */ 70 abstract public function getStyleName($style); 71 72 /** 73 * @param null $source 74 */ 75 public function importFromODTFile($sourceFile, $root_element, $overwrite=false) { 76 if (empty($sourceFile) || empty($root_element)) { 77 return false; 78 } 79 80 // Get file contents 81 $styles_xml_content = file_get_contents ($sourceFile); 82 if (empty($styles_xml_content)) { 83 return false; 84 } 85 86 return $this->importFromODT($styles_xml_content, $root_element, $overwrite); 87 } 88 89 public function importFromODT($styles_xml_content, $root_element, $overwrite=false) { 90 if (empty($styles_xml_content) || empty($root_element)) { 91 return false; 92 } 93 94 // Only import known style elements 95 switch ($root_element) { 96 case 'office:styles': 97 case 'office:automatic-styles': 98 case 'office:master-styles': 99 $style_elements = XMLUtil::getElementContent($root_element, $styles_xml_content, $end); 100 break; 101 102 default: 103 return false; 104 } 105 106 $pos = 0; 107 $max = strlen($style_elements); 108 while ($pos < $max) { 109 $xml_code = XMLUtil::getNextElement($element, substr($style_elements, $pos), $end); 110 if (!isset($xml_code)) { 111 break; 112 } 113 $pos += $end; 114 115 // Create new ODTStyle 116 $object = ODTStyle::importODTStyle($xml_code); 117 if ( isset($object) ) { 118 // Success, add it 119 switch ($root_element) { 120 case 'office:styles': 121 $this->addStyle($object, $overwrite); 122 break; 123 case 'office:automatic-styles': 124 $this->addAutomaticStyle($object, $overwrite); 125 break; 126 case 'office:master-styles': 127 $this->addMasterStyle($object, $overwrite); 128 break; 129 } 130 } 131 } 132 return true; 133 } 134 135 /** 136 * @param null $destination 137 */ 138 public function exportToODT($root_element) { 139 $export = NULL; 140 switch ($root_element) { 141 case 'office:styles': 142 $export = &$this->styles; 143 break; 144 case 'office:automatic-styles': 145 $export = &$this->auto_styles; 146 break; 147 case 'office:master-styles': 148 $export = &$this->master_styles; 149 break; 150 } 151 if (isset($export)) { 152 $office_styles = "<".$root_element.">\n"; 153 foreach ($export as $style) { 154 $office_styles .= $style->toString(); 155 } 156 $office_styles .= "</".$root_element.">\n"; 157 return $office_styles; 158 } 159 return NULL; 160 } 161 162 /** 163 * @param null $source 164 */ 165 public function addStyle(ODTStyle $new, $overwrite=false) { 166 return $this->addStyleInternal 167 ($this->styles, $this->styles_by_name, $new, $overwrite); 168 } 169 170 /** 171 * @param null $source 172 */ 173 public function addAutomaticStyle(ODTStyle $new, $overwrite=false) { 174 return $this->addStyleInternal 175 ($this->auto_styles, $this->auto_styles_by_name, $new, $overwrite); 176 } 177 178 /** 179 * @param null $source 180 */ 181 public function addMasterStyle(ODTStyle $new, $overwrite=false) { 182 return $this->addStyleInternal 183 ($this->master_styles, $this->master_styles_by_name, $new, $overwrite); 184 } 185 186 /** 187 * @param null $source 188 */ 189 public function addStyleInternal(&$dest, &$dest_by_name, ODTStyle $new, $overwrite=false) { 190 if ($new->isDefault()) { 191 // The key for a default style is the family. 192 $family = $new->getFamily(); 193 194 // Search for default style with same family. 195 for ($index = 0 ; $index < count($dest) ; $index++) { 196 if ($dest [$index]->isDefault() && 197 $dest [$index]->getFamily() == $family) { 198 // Only overwrite it if allowed. 199 if ($overwrite) { 200 $dest [$index] = $new; 201 } 202 return false; 203 } 204 } 205 206 // Default style for that family does not exist yet, add it. 207 $dest [] = $new; 208 } else { 209 // The key for a normal style is the name. 210 $name = $new->getProperty('style-name'); 211 212 if (!isset($dest_by_name [$name])) { 213 $dest [] = $new; 214 if (!empty($name)) { 215 $dest_by_name [$name] = $new; 216 } 217 return true; 218 } elseif ($overwrite) { 219 for ($index = 0 ; $index < count($dest) ; $index++) { 220 if ($dest [$index] == $dest_by_name [$name]) { 221 $dest [$index] = $new; 222 break; 223 } 224 } 225 $dest_by_name [$name] = $new; 226 return true; 227 } 228 } 229 230 // Do not overwrite an already existing style. 231 return false; 232 } 233 234 /** 235 * The function style checks if a style with the given $name already exists. 236 * 237 * @param $name Name of the style to check 238 * @return boolean 239 */ 240 public function styleExists ($name) { 241 if (isset($this->auto_styles_by_name [$name])) { 242 return true; 243 } 244 if (isset($this->styles_by_name [$name])) { 245 return true; 246 } 247 if (isset($this->master_styles_by_name [$name])) { 248 return true; 249 } 250 return false; 251 } 252 253 /** 254 * The function returns the style with the given name 255 * 256 * @param $name Name of the style 257 * @return ODTStyle or NULL 258 */ 259 public function getStyle ($name) { 260 if (isset($this->auto_styles_by_name [$name])) { 261 return $this->auto_styles_by_name [$name]; 262 } 263 if (isset($this->styles_by_name [$name])) { 264 return $this->styles_by_name [$name]; 265 } 266 if (isset($this->master_styles_by_name [$name])) { 267 return $this->master_styles_by_name [$name]; 268 } 269 return NULL; 270 } 271 272 /** 273 * The function returns the style at the given index 274 * 275 * @param $element Element of the style e.g. 'office:styles' 276 * @return ODTStyle or NULL 277 */ 278 public function getStyleAtIndex($element, $index) { 279 switch ($element) { 280 case 'office:styles': 281 return $this->styles [$index]; 282 case 'office:automatic-styles': 283 return $this->auto_styles [$index]; 284 case 'office:master-styles': 285 return $this->master_styles [$index]; 286 } 287 return NULL; 288 } 289 290 public function getStyleCount($element) { 291 switch ($element) { 292 case 'office:styles': 293 return count($this->styles); 294 case 'office:automatic-styles': 295 return count($this->auto_styles); 296 case 'office:master-styles': 297 return count($this->master_styles); 298 } 299 return -1; 300 } 301 302 /** 303 * @param null $source 304 */ 305 public function getDefaultStyle($family) { 306 // Search for default style with same family. 307 for ($index = 0 ; $index < count($this->styles) ; $index++) { 308 if ($this->styles [$index]->isDefault() && 309 $this->styles [$index]->getFamily() == $family) { 310 return $this->styles [$index]; 311 } 312 } 313 return NULL; 314 } 315 316 /** 317 * Get styles array. 318 */ 319 public function getStyles() { 320 return $this->styles; 321 } 322 323 /** 324 * Get automatci/common styles array. 325 */ 326 public function getAutomaticStyles() { 327 return $this->auto_styles; 328 } 329 330 /** 331 * Get master styles array. 332 */ 333 public function getMasterStyles() { 334 return $this->master_styles; 335 } 336} 337