eZ Publish  [4.0]
ezxmlschema.php
Go to the documentation of this file.
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 ?>