|
eZ Publish
[4.0]
|
00001 <?php 00002 // 00003 // Definition of eZXMLSchema class 00004 // 00005 // Created on: <27-Mar-2006 15:28:39 ks> 00006 // 00007 // ## BEGIN COPYRIGHT, LICENSE AND WARRANTY NOTICE ## 00008 // SOFTWARE NAME: eZ Publish 00009 // SOFTWARE RELEASE: 4.0.x 00010 // COPYRIGHT NOTICE: Copyright (C) 1999-2008 eZ Systems AS 00011 // SOFTWARE LICENSE: GNU General Public License v2.0 00012 // NOTICE: > 00013 // This program is free software; you can redistribute it and/or 00014 // modify it under the terms of version 2.0 of the GNU General 00015 // Public License as published by the Free Software Foundation. 00016 // 00017 // This program is distributed in the hope that it will be useful, 00018 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00019 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00020 // GNU General Public License for more details. 00021 // 00022 // You should have received a copy of version 2.0 of the GNU General 00023 // Public License along with this program; if not, write to the Free 00024 // Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 00025 // MA 02110-1301, USA. 00026 // 00027 // 00028 // ## END COPYRIGHT, LICENSE AND WARRANTY NOTICE ## 00029 // 00030 00031 class eZXMLSchema 00032 { 00033 public $Schema = array( 00034 'section' => array( 'blockChildrenAllowed' => array( 'header', 'paragraph', 'section' ), 00035 'inlineChildrenAllowed' => false, 00036 'childrenRequired' => false, 00037 'isInline' => false, 00038 'attributes' => array( 'xmlns:image', 'xmlns:xhtml', 'xmlns:custom', 'xmlns:tmp' ) ), 00039 00040 'embed' => array( 'blockChildrenAllowed' => false, 00041 'inlineChildrenAllowed' => false, 00042 'childrenRequired' => null, 00043 'isInline' => true, 00044 'attributes' => array( 'object_id', 'node_id', 'show_path', 'size', 00045 'align', 'view', 'xhtml:id', 'class', 'target' ), 00046 'attributesDefaults' => array( 'align' => 'right', 'view' => 'embed', 'class' => '' ) ), 00047 00048 'embed-inline' => array( 'blockChildrenAllowed' => false, 00049 'inlineChildrenAllowed' => false, 00050 'childrenRequired' => null, 00051 'isInline' => true, 00052 'attributes' => array( 'object_id', 'node_id', 'show_path', 'size', 00053 'align', 'view', 'xhtml:id', 'class', 'target' ), 00054 'attributesDefaults' => array( 'align' => 'right', 'view' => 'embed-inline', 'class' => '' ) ), 00055 00056 'table' => array( 'blockChildrenAllowed' => array( 'tr' ), 00057 'inlineChildrenAllowed' => false, 00058 'childrenRequired' => true, 00059 'isInline' => false, 00060 'attributes' => array( 'class', 'width', 'border' ) ), 00061 00062 'tr' => array( 'blockChildrenAllowed' => array( 'td', 'th' ), 00063 'inlineChildrenAllowed' => false, 00064 'childrenRequired' => false, 00065 'isInline' => false, 00066 'attributes' => array( 'class' ) ), 00067 00068 'td' => array( 'blockChildrenAllowed' => array( 'header', 'paragraph', 'section', 'table' ), 00069 'inlineChildrenAllowed' => false, 00070 'childrenRequired' => false, 00071 'isInline' => false, 00072 'attributes' => array( 'class', 'xhtml:width', 'xhtml:colspan', 'xhtml:rowspan' ) ), 00073 00074 'th' => array( 'blockChildrenAllowed' => array( 'header', 'paragraph', 'section', 'table' ), 00075 'inlineChildrenAllowed' => false, 00076 'childrenRequired' => false, 00077 'isInline' => false, 00078 'attributes' => array( 'class', 'xhtml:width', 'xhtml:colspan', 'xhtml:rowspan' ) ), 00079 00080 'ol' => array( 'blockChildrenAllowed' => array( 'li' ), 00081 'inlineChildrenAllowed' => false, 00082 'childrenRequired' => true, 00083 'isInline' => false, 00084 'attributes' => array( 'class' ) ), 00085 00086 'ul' => array( 'blockChildrenAllowed' => array( 'li' ), 00087 'inlineChildrenAllowed' => false, 00088 'childrenRequired' => true, 00089 'isInline' => false, 00090 'attributes' => array( 'class' ) ), 00091 00092 'li' => array( 'blockChildrenAllowed' => array( 'paragraph' ), 00093 'inlineChildrenAllowed' => false, 00094 'childrenRequired' => true, 00095 'isInline' => false, 00096 'attributes' => array( 'class' ) ), 00097 00098 'header' => array( 'blockChildrenAllowed' => false, 00099 'inlineChildrenAllowed' => true, 00100 'childrenRequired' => true, 00101 'isInline' => false, 00102 'attributes' => array( 'class', 'anchor_name' ) ), 00103 00104 'paragraph' => array( 'blockChildrenAllowed' => array( 'line', 'link', 'embed', 'table', 'ol', 'ul', 'custom', 'literal' ), 00105 'inlineChildrenAllowed' => true, 00106 'childrenRequired' => true, 00107 'isInline' => false, 00108 'attributes' => array( 'class' ) ), 00109 00110 'line' => array( 'blockChildrenAllowed' => false, 00111 'inlineChildrenAllowed' => true, 00112 'childrenRequired' => true, 00113 'isInline' => false, 00114 'attributes' => false ), 00115 00116 'literal' => array( 'blockChildrenAllowed' => false, 00117 'inlineChildrenAllowed' => array( '#text' ), 00118 'childrenRequired' => true, 00119 'isInline' => false, 00120 'attributes' => array( 'class' ) ), 00121 00122 'strong' => array( 'blockChildrenAllowed' => false, 00123 'inlineChildrenAllowed' => true, 00124 'childrenRequired' => true, 00125 'isInline' => true, 00126 'attributes' => array( 'class' ) ), 00127 00128 'emphasize' => array( 'blockChildrenAllowed' => false, 00129 'inlineChildrenAllowed' => true, 00130 'childrenRequired' => true, 00131 'isInline' => true, 00132 'attributes' => array( 'class' ) ), 00133 00134 'link' => array( 'blockChildrenAllowed' => false, 00135 'inlineChildrenAllowed' => true, 00136 'childrenRequired' => true, 00137 'isInline' => true, 00138 'attributes' => array( 'class', 'xhtml:id', 'target', 'xhtml:title', 00139 'object_id', 'node_id', 'show_path', 'anchor_name', 00140 'url_id', 'id', 'view' ), 00141 'attributesDefaults' => array( 'target' => '_self' ) ), 00142 00143 'anchor' => array( 'blockChildrenAllowed' => false, 00144 'inlineChildrenAllowed' => false, 00145 'childrenRequired' => false, 00146 'isInline' => true, 00147 'attributes' => array( 'name' ) ), 00148 00149 'custom' => array( 'blockChildrenAllowed' => true, 00150 'inlineChildrenAllowed' => true, 00151 'childrenRequired' => false, 00152 'isInline' => null, 00153 'attributes' => array( 'name' ) ), 00154 00155 '#text' => array( 'blockChildrenAllowed' => false, 00156 'inlineChildrenAllowed' => false, 00157 'childrenRequired' => false, 00158 'isInline' => true, 00159 'attributes' => false ) 00160 ); 00161 00162 function eZXMLSchema() 00163 { 00164 //include_once( 'lib/ezutils/classes/ezini.php' ); 00165 $ini = eZINI::instance( 'content.ini' ); 00166 00167 // Get inline custom tags list 00168 $this->Schema['custom']['isInline'] = $ini->variable( 'CustomTagSettings', 'IsInline' ); 00169 if ( !is_array( $this->Schema['custom']['isInline'] ) ) 00170 $this->Schema['custom']['isInline'] = array(); 00171 00172 $this->Schema['custom']['tagList'] = $ini->variable( 'CustomTagSettings', 'AvailableCustomTags' ); 00173 if ( !is_array( $this->Schema['custom']['tagList'] ) ) 00174 $this->Schema['custom']['tagList'] = array(); 00175 00176 //include_once( 'lib/version.php' ); 00177 $eZPublishVersion = eZPublishSDK::majorVersion() + eZPublishSDK::minorVersion() * 0.1; 00178 00179 // Get all tags available classes list 00180 foreach( array_keys( $this->Schema ) as $tagName ) 00181 { 00182 if ( $ini->hasVariable( $tagName, 'AvailableClasses' ) ) 00183 { 00184 $avail = $ini->variable( $tagName, 'AvailableClasses' ); 00185 if ( is_array( $avail ) && count( $avail ) ) 00186 $this->Schema[$tagName]['classesList'] = $avail; 00187 else 00188 $this->Schema[$tagName]['classesList'] = array(); 00189 } 00190 else 00191 $this->Schema[$tagName]['classesList'] = array(); 00192 } 00193 00194 00195 // Fix for empty paragraphs setting 00196 $allowEmptyParagraph = $ini->variable( 'paragraph', 'AllowEmpty' ); 00197 $this->Schema['paragraph']['childrenRequired'] = $allowEmptyParagraph == 'true' ? false : true; 00198 00199 // Get all tags custom attributes list 00200 $ini = eZINI::instance( 'content.ini' ); 00201 foreach( array_keys( $this->Schema ) as $tagName ) 00202 { 00203 if ( $tagName == 'custom' ) 00204 { 00205 // Custom attributes of custom tags 00206 foreach( $this->Schema['custom']['tagList'] as $customTagName ) 00207 { 00208 if ( $ini->hasVariable( $customTagName, 'CustomAttributes' ) ) 00209 { 00210 $avail = $ini->variable( $customTagName, 'CustomAttributes' ); 00211 if ( is_array( $avail ) && count( $avail ) ) 00212 $this->Schema['custom']['customAttributes'][$customTagName] = $avail; 00213 else 00214 $this->Schema['custom']['customAttributes'][$customTagName] = array(); 00215 } 00216 else 00217 $this->Schema['custom']['customAttributes'][$customTagName] = array(); 00218 } 00219 } 00220 else 00221 { 00222 // Custom attributes of regular tags 00223 if ( $ini->hasVariable( $tagName, 'CustomAttributes' ) ) 00224 { 00225 $avail = $ini->variable( $tagName, 'CustomAttributes' ); 00226 if ( is_array( $avail ) && count( $avail ) ) 00227 $this->Schema[$tagName]['customAttributes'] = $avail; 00228 else 00229 $this->Schema[$tagName]['customAttributes'] = array(); 00230 } 00231 else 00232 $this->Schema[$tagName]['customAttributes'] = array(); 00233 } 00234 } 00235 } 00236 00237 static function instance() 00238 { 00239 if ( empty( $GLOBALS["eZXMLSchemaGlobalInstance"] ) ) 00240 { 00241 $GLOBALS["eZXMLSchemaGlobalInstance"] = new eZXMLSchema(); 00242 } 00243 00244 return $GLOBALS["eZXMLSchemaGlobalInstance"]; 00245 } 00246 00247 // Determines if the tag is inline 00248 function isInline( $element ) 00249 { 00250 if ( is_string( $element ) ) 00251 $elementName = $element; 00252 else 00253 $elementName = $element->nodeName; 00254 00255 $isInline = $this->Schema[$elementName]['isInline']; 00256 00257 // Special workaround for custom tags. 00258 if ( is_array( $isInline ) && !is_string( $element ) ) 00259 { 00260 $isInline = false; 00261 $name = $element->getAttribute( 'name' ); 00262 00263 if ( isset( $this->Schema['custom']['isInline'][$name] ) ) 00264 { 00265 if ( $this->Schema['custom']['isInline'][$name] == 'true' ) 00266 $isInline = true; 00267 } 00268 } 00269 return $isInline; 00270 } 00271 00272 /*! 00273 Checks if one element is allowed to be a child of another 00274 00275 \param $parent parent element: DOMNode or string 00276 \param $child child element: DOMNode or string 00277 00278 \return true if elements match schema 00279 \return false if elements don't match schema 00280 \return null in case of errors 00281 */ 00282 00283 function check( $parent, $child ) 00284 { 00285 if ( is_string( $parent ) ) 00286 $parentName = $parent; 00287 else 00288 $parentName = $parent->nodeName; 00289 00290 if ( is_string( $child ) ) 00291 $childName = $child; 00292 else 00293 $childName = $child->nodeName; 00294 00295 if ( isset( $this->Schema[$childName] ) ) 00296 { 00297 $isInline = $this->isInline( $child ); 00298 00299 if ( $isInline === true ) 00300 { 00301 $allowed = $this->Schema[$parentName]['inlineChildrenAllowed']; 00302 } 00303 elseif ( $isInline === false ) 00304 { 00305 // Special workaround for custom tags. 00306 if ( $parentName == 'custom' && !is_string( $parent ) && 00307 $parent->getAttribute( 'inline' ) != 'true' ) 00308 { 00309 $allowed = true; 00310 } 00311 else 00312 $allowed = $this->Schema[$parentName]['blockChildrenAllowed']; 00313 } 00314 else 00315 return true; 00316 00317 if ( is_array( $allowed ) ) 00318 $allowed = in_array( $childName, $allowed ); 00319 00320 if ( !$allowed ) 00321 return false; 00322 } 00323 else 00324 { 00325 return null; 00326 } 00327 return true; 00328 } 00329 00330 function childrenRequired( $element ) 00331 { 00332 //if ( !isset( $this->Schema[$element->nodeName] ) ) 00333 // return false; 00334 00335 return $this->Schema[$element->nodeName]['childrenRequired']; 00336 } 00337 00338 function hasAttributes( $element ) 00339 { 00340 //if ( !isset( $this->Schema[$element->nodeName] ) ) 00341 // return false; 00342 00343 return ( $this->Schema[$element->nodeName]['attributes'] != false ); 00344 } 00345 00346 function attributes( $element ) 00347 { 00348 return $this->Schema[$element->nodeName]['attributes']; 00349 } 00350 00351 function customAttributes( $element ) 00352 { 00353 if ( is_string( $element ) ) 00354 { 00355 return $this->Schema[$element]['customAttributes']; 00356 } 00357 else 00358 { 00359 if ( $element->nodeName == 'custom' ) 00360 { 00361 $name = $element->getAttribute( 'name' ); 00362 if ( $name ) 00363 return $this->Schema['custom']['customAttributes'][$name]; 00364 } 00365 else 00366 { 00367 return $this->Schema[$element->nodeName]['customAttributes']; 00368 } 00369 } 00370 return array(); 00371 } 00372 00373 function attrDefaultValue( $tagName, $attrName ) 00374 { 00375 if ( isset( $this->Schema[$tagName]['attributesDefaults'][$attrName] ) ) 00376 return $this->Schema[$tagName]['attributesDefaults'][$attrName]; 00377 else 00378 return array(); 00379 } 00380 00381 function attrDefaultValues( $tagName ) 00382 { 00383 if ( isset( $this->Schema[$tagName]['attributesDefaults'] ) ) 00384 return $this->Schema[$tagName]['attributesDefaults']; 00385 else 00386 return array(); 00387 } 00388 00389 function exists( $element ) 00390 { 00391 if ( is_string( $element ) ) 00392 { 00393 return isset( $this->Schema[$element] ); 00394 } 00395 else 00396 { 00397 if ( $element->nodeName == 'custom' ) 00398 { 00399 $name = $element->getAttribute( 'name' ); 00400 if ( $name ) 00401 return in_array( $name, $this->Schema['custom']['tagList'] ); 00402 } 00403 else 00404 { 00405 return isset( $this->Schema[$element->nodeName] ); 00406 } 00407 } 00408 return false; 00409 } 00410 00411 function availableElements() 00412 { 00413 return array_keys( $this->Schema ); 00414 } 00415 00416 function getClassesList( $tagName ) 00417 { 00418 if ( isset( $this->Schema[$tagName]['classesList'] ) ) 00419 return $this->Schema[$tagName]['classesList']; 00420 else 00421 return array(); 00422 } 00423 00424 function addAvailableClass( $tagName, $class ) 00425 { 00426 if ( !isset( $this->Schema[$tagName]['classesList'] ) ) 00427 $this->Schema[$tagName]['classesList'] = array(); 00428 00429 $this->Schema[$tagName]['classesList'][] = $class; 00430 } 00431 00432 function addCustomAttribute( $element, $attrName ) 00433 { 00434 if ( is_string( $element ) ) 00435 { 00436 $this->Schema[$element]['customAttributes'][] = $attrName; 00437 } 00438 else 00439 { 00440 if ( $element->nodeName == 'custom' ) 00441 { 00442 $name = $element->getAttribute( 'name' ); 00443 if ( $name ) 00444 $this->Schema['custom']['customAttributes'][$name][] = $attrName; 00445 } 00446 else 00447 { 00448 $this->Schema[$element->nodeName]['customAttributes'][] = $attrName; 00449 } 00450 } 00451 } 00452 } 00453 ?>