1<?php 2 3require_once DOKU_PLUGIN . 'odt/ODT/ODTDocument.php'; 4 5/** 6 * ODTParagraph: 7 * Class containing static code for handling spans. 8 * 9 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 10 */ 11class ODTSpan 12{ 13 /** 14 * Open a text span. 15 * 16 * @param string $styleName The style to use. 17 */ 18 public static function spanOpen(ODTInternalParams $params, $styleName, $element=NULL, $attributes=NULL){ 19 if (!isset($element)) { 20 $element = 'span'; 21 } 22 if (!isset($params->elementObj)) { 23 $properties = array(); 24 ODTUtility::openHTMLElement ($params, $properties, $element, $attributes); 25 } 26 27 $span = new ODTElementSpan ($styleName); 28 $params->document->state->enter($span); 29 $params->content .= $span->getOpeningTag(); 30 $span->setHTMLElement ($element); 31 } 32 33 /** 34 * This function opens a new span using the style as set in the imported CSS $import. 35 * So, the function requires the helper class 'helper_plugin_odt_cssimport'. 36 * The CSS style is selected by the element type 'span' and the specified classes in $classes. 37 * The property 'background-image' is not supported by an ODT span. This will be emulated 38 * by inserting an image manually in the span. If the url from the CSS should be converted to 39 * a local path, then the caller can specify a $baseURL. The full path will then be $baseURL/background-image. 40 * 41 * This function calls _odtSpanOpenUseProperties. See the function description for supported properties. 42 * 43 * The span should be closed by calling '_odtSpanClose'. 44 * 45 * @author LarsDW223 46 * 47 * @param helper_plugin_odt_cssimport $import 48 * @param $classes 49 * @param $baseURL 50 * @param $element 51 */ 52 public static function spanOpenUseCSS(ODTInternalParams $params, $element=NULL, $attributes=NULL){ 53 $properties = array(); 54 ODTUtility::openHTMLElement ($params, $properties, $element, $attributes); 55 $params->elementObj = $params->htmlStack->getCurrentElement(); 56 57 self::spanOpenUseProperties($params, $properties); 58 } 59 60 /** 61 * This function opens a new span using the style as set in the assoziative array $properties. 62 * The parameters in the array should be named as the CSS property names e.g. 'color' or 'background-color'. 63 * The property 'background-image' is not supported by an ODT span. This will be emulated 64 * by inserting an image manually in the span. 65 * 66 * background-color, color, font-style, font-weight, font-size, border, font-family, font-variant, letter-spacing, 67 * vertical-align, background-image (emulated) 68 * 69 * The span should be closed by calling '_odtSpanClose'. 70 * 71 * @author LarsDW223 72 * 73 * @param array $properties 74 */ 75 public static function spanOpenUseProperties(ODTInternalParams $params, $properties){ 76 $disabled = array (); 77 78 $odt_bg = $properties ['background-color']; 79 $picture = $properties ['background-image']; 80 81 if ( !empty ($picture) ) { 82 // If a picture/background-image is set, than we insert it manually here. 83 // This is a workaround because ODT does not support the background-image attribute in a span. 84 85 // Define graphic style for picture 86 $style_name = ODTStyle::getNewStylename('span_graphic'); 87 $image_style = '<style:style style:name="'.$style_name.'" style:family="graphic" style:parent-style-name="'.$params->document->getStyleName('graphics').'"><style:graphic-properties style:vertical-pos="middle" style:vertical-rel="text" style:horizontal-pos="from-left" style:horizontal-rel="paragraph" fo:background-color="'.$odt_bg.'" style:flow-with-text="true"></style:graphic-properties></style:style>'; 88 89 // Add style and image to our document 90 // (as unknown style because style-family graphic is not supported) 91 $style_obj = ODTUnknownStyle::importODTStyle($image_style); 92 $params->document->addAutomaticStyle($style_obj); 93 ODTImage::addImage ($params, $picture, NULL, NULL, NULL, NULL, $style_name); 94 } 95 96 // Create a text style for our span 97 $disabled ['background-image'] = 1; 98 $style_obj = ODTTextStyle::createTextStyle ($properties, $disabled); 99 $params->document->addAutomaticStyle($style_obj); 100 $style_name = $style_obj->getProperty('style-name'); 101 102 // Open span 103 self::spanOpen($params, $style_name); 104 } 105 106 /** 107 * Close a text span. 108 * 109 * @param string $style_name The style to use. 110 */ 111 public static function spanClose(ODTInternalParams $params) { 112 ODTUtility::closeHTMLElement ($params, $params->document->state->getHTMLElement()); 113 $params->document->closeCurrentElement($params->content); 114 } 115 116 public static function createSpanInternal (ODTInternalParams $params, $attributes) { 117 // Get properties 118 $properties = array(); 119 ODTUtility::getHTMLElementProperties ($params, $properties, 'span', $attributes); 120 121 // Create automatic style 122 $properties ['style-name'] = ODTStyle::getNewStylename ('span'); 123 $params->document->createTextStyle($properties, false); 124 125 // Return style name 126 return $properties ['style-name']; 127 } 128 129 public static function generateSpansfromHTMLCode(ODTInternalParams $params, $HTMLCode){ 130 $spans = array ('sup' => array ('open' => '<text:span text:style-name="sup">', 131 'close' => '</text:span>'), 132 'sub' => array ('open' => '<text:span text:style-name="sub">', 133 'close' => '</text:span>'), 134 'u' => array ('open' => '<text:span text:style-name="underline">', 135 'close' => '</text:span>'), 136 'em' => array ('open' => '<text:span text:style-name="Emphasis">', 137 'close' => '</text:span>'), 138 'strong' => array ('open' => '<text:span text:style-name="Strong_20_Emphasis">', 139 'close' => '</text:span>'), 140 'del' => array ('open' => '<text:span text:style-name="del">', 141 'close' => '</text:span>'), 142 ); 143 $parsed = array(); 144 145 // First examine $HTMLCode and differ between normal content, 146 // opening tags and closing tags. 147 $max = strlen ($HTMLCode); 148 $pos = 0; 149 while ($pos < $max) { 150 $found = ODTUtility::getNextTag($HTMLCode, $pos); 151 if ($found !== false) { 152 $entry = array(); 153 $entry ['content'] = substr($HTMLCode, $pos, $found [0]-$pos); 154 if ($entry ['content'] === false) { 155 $entry ['content'] = ''; 156 } 157 $parsed [] = $entry; 158 159 $tagged = substr($HTMLCode, $found [0], $found [1]-$found [0]+1); 160 $entry = array(); 161 162 if ($HTMLCode [$found[1]-1] == '/') { 163 // Element without content <abc/>, doesn'T make sense, save as content 164 $entry ['content'] = $tagged; 165 } else { 166 if ($HTMLCode [$found[0]+1] != '/') { 167 $parts = explode(' ', trim($tagged, '<> '), 2); 168 $entry ['tag-open'] = $parts [0]; 169 if ( isset($parts [1]) ) { 170 $entry ['attributes'] = $parts [1]; 171 } 172 $entry ['tag-orig'] = $tagged; 173 } else { 174 $entry ['tag-close'] = trim ($tagged, '<>/ '); 175 $entry ['tag-orig'] = $tagged; 176 } 177 } 178 $entry ['matched'] = false; 179 $parsed [] = $entry; 180 181 $pos = $found [1]+1; 182 } else { 183 $entry = array(); 184 $entry ['content'] = substr($HTMLCode, $pos); 185 $parsed [] = $entry; 186 break; 187 } 188 } 189 190 // Check each array entry. 191 $checked = array(); 192 for ($out = 0 ; $out < count($parsed) ; $out++) { 193 if (isset($checked [$out])) { 194 continue; 195 } 196 $found = &$parsed [$out]; 197 if (isset($found ['content'])) { 198 $checked [$out] = $params->document->replaceXMLEntities($found ['content']); 199 } else if (isset($found ['tag-open'])) { 200 $closed = false; 201 202 for ($in = $out+1 ; $in < count($parsed) ; $in++) { 203 $search = &$parsed [$in]; 204 if (isset($search ['tag-close']) && 205 $found ['tag-open'] == $search ['tag-close'] && 206 $search ['matched'] === false && 207 (array_key_exists($found ['tag-open'], $spans) || $found ['tag-open'] == 'span')) { 208 209 $closed = true; 210 $search ['matched'] = true; 211 212 // Known and closed tag, convert to ODT 213 if ($found ['tag-open'] != 'span') { 214 $checked [$out] = $spans [$found ['tag-open']]['open']; 215 $checked [$in] = $spans [$found ['tag-open']]['close']; 216 } else { 217 $style_name = self::createSpanInternal ($params, $found ['attributes']); 218 $checked [$out] = '<text:span text:style-name="'.$style_name.'">'; 219 $checked [$in] = '</text:span>'; 220 } 221 break; 222 } 223 } 224 225 // Known tag? Closing tag found? 226 if (!$closed) { 227 // No, save as content 228 $checked [$out] = $params->document->replaceXMLEntities($found ['tag-orig']); 229 } 230 } else if (isset($found ['tag-close'])) { 231 // If we find a closing tag it means it did not match 232 // an opening tag. Convert to content! 233 $checked [$out] = $params->document->replaceXMLEntities($found ['tag-orig']); 234 } 235 } 236 237 // Add checked entries to content 238 for ($index = 0 ; $index < count($checked) ; $index++) { 239 $params->content .= $checked [$index]; 240 } 241 } 242} 243