|
eZ Publish
[4.0]
|
00001 <?php 00002 // 00003 // Definition of eZContentClassPackageHandler class 00004 // 00005 // Created on: <09-Mar-2004 16:11:42 kk> 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 /*! \file ezcontentobjectpackagehandler.php 00032 */ 00033 00034 /*! 00035 \class eZContentObjectPackageHandler ezcontentobjectpackagehandler.php 00036 \brief Handles content objects in the package system 00037 00038 */ 00039 00040 //include_once( 'kernel/classes/ezcontentobject.php' ); 00041 //include_once( 'kernel/classes/ezpackagehandler.php' ); 00042 00043 class eZContentObjectPackageHandler extends eZPackageHandler 00044 { 00045 const MAX_LISTED_OBJECTS = 30; 00046 00047 // If number of objects in the package is bigger than this constant, 00048 // they are stored in separate files to prevent memory overflow. 00049 // 'null' means always use separate files 00050 const STORE_OBJECTS_TO_SEPARATE_FILES_THRESHOLD = 100; 00051 00052 const INSTALL_OBJECTS_ERROR_RANGE_FROM = 1; 00053 const INSTALL_OBJECTS_ERROR_RANGE_TO = 100; 00054 const UNINSTALL_OBJECTS_ERROR_RANGE_FROM = 101; 00055 const UNINSTALL_OBJECTS_ERROR_RANGE_TO = 200; 00056 00057 /*! 00058 Constructor 00059 */ 00060 function eZContentObjectPackageHandler() 00061 { 00062 $this->eZPackageHandler( 'ezcontentobject', 00063 array( 'extract-install-content' => true ) ); 00064 } 00065 00066 /*! 00067 Fetches object stored in separate xml file 00068 */ 00069 function fetchObjectFromFile( $objectFileNode ) 00070 { 00071 $fileName = $objectFileNode->getAttribute( 'filename' ); 00072 $filePath = $this->Package->path() . '/' . $this->contentObjectDirectory() . '/' . $fileName; 00073 $dom = $this->Package->fetchDOMFromFile( $filePath ); 00074 00075 if ( $dom ) 00076 { 00077 $objectNode = $dom->documentElement; 00078 } 00079 else 00080 { 00081 eZDebug::writeError( "Can't fetch object from package file: $filePath", 'eZContentObjectPackageHandler::getObjectNodeFromFile' ); 00082 $objectNode = false; 00083 } 00084 00085 return $objectNode; 00086 } 00087 00088 function getRealObjectNode( $objectNode ) 00089 { 00090 if ( $objectNode->localName == 'object' ) 00091 { 00092 $realObjectNode = $objectNode; 00093 } 00094 else 00095 { 00096 $realObjectNode = $this->fetchObjectFromFile( $objectNode ); 00097 } 00098 return $realObjectNode; 00099 } 00100 00101 /*! 00102 \reimp 00103 Returns an explanation for the content object install item. 00104 00105 The explanaition is actually a list having the following structure: 00106 array( array( 'description' => 'Content object Foo' ), 00107 array( 'description' => 'Content object Bar' ), 00108 array( 'description' => 'Content object Baz' ) ); 00109 00110 When number of items in the above list is too high, 00111 the following array is returned instead: 00112 array( 'description' => 'NNN content objects' ); 00113 00114 00115 */ 00116 function explainInstallItem( $package, $installItem, $requestedInfo = array() ) 00117 { 00118 $this->Package = $package; 00119 00120 if ( $installItem['filename'] ) 00121 { 00122 $filename = $installItem['filename']; 00123 $subdirectory = $installItem['sub-directory']; 00124 if ( $subdirectory ) 00125 $filepath = $subdirectory . '/' . $filename . '.xml'; 00126 else 00127 $filepath = $filename . '.xml'; 00128 00129 $filepath = $package->path() . '/' . $filepath; 00130 00131 $dom = $package->fetchDOMFromFile( $filepath ); 00132 00133 if ( !$dom ) 00134 return null; 00135 00136 $content = $dom->documentElement; 00137 $objectListNode = $content->getElementsByTagName( 'object-list' )->item( 0 ); 00138 if ( $objectListNode ) 00139 { 00140 $realObjectNodes = $objectListNode->getElementsByTagName( 'object' ); 00141 } 00142 else 00143 { 00144 // If objects are stored in separate files (new format) 00145 $objectListNode = $content->getElementsByTagName( 'object-files-list' )->item( 0 ); 00146 $objectNodes = $objectListNode->getElementsByTagName( 'object-file' ); 00147 00148 if ( count( $objectNodes ) > self::MAX_LISTED_OBJECTS ) 00149 { 00150 return array( 'description' => ezi18n( 'kernel/package', '%number content objects', false, 00151 array( '%number' => count( $objectNodes ) ) ) ); 00152 } 00153 00154 $realObjectNodes = array(); 00155 foreach( $objectNodes as $objectNode ) 00156 { 00157 $realObjectNode = $this->fetchObjectFromFile( $objectNode ); 00158 if ( !$realObjectNode ) 00159 continue; 00160 00161 $realObjectNodes[] = $realObjectNode; 00162 } 00163 } 00164 00165 // create descriptions array 00166 $objectNames = array(); 00167 foreach( $realObjectNodes as $objectNode ) 00168 { 00169 $objectName = 00170 $objectNode->getAttribute( 'name' ) . 00171 ' (' . $objectNode->getAttributeNS( 'http://ez.no/ezobject', 'class_identifier' ) .')'; 00172 00173 // get info about translations. 00174 $languageInfo = array(); 00175 $versionList = $objectNode->getElementsByTagName( 'version-list' )->item( 0 ); 00176 $versions = $versionList->getElementsByTagName( 'version' ); 00177 foreach( $versions as $version ) 00178 { 00179 $versionInfo = $version->getElementsByTagName( 'object-translation' ); 00180 foreach( $versionInfo as $info ) 00181 { 00182 $languageInfo[] = $info->getAttribute( 'language' ); 00183 } 00184 } 00185 00186 $objectNames[] = array( 'description' => 00187 ezi18n( 'kernel/package', 'Content object %objectname', false, 00188 array( '%objectname' => $objectName ) ), 00189 'language_info' => $languageInfo ); 00190 } 00191 return $objectNames; 00192 } 00193 } 00194 00195 /*! 00196 Add Node list to ezcontentobject package handler. 00197 00198 \param node id 00199 \param subtree (optional, default true ) 00200 */ 00201 function addNode( $nodeID, $isSubtree = true ) 00202 { 00203 //include_once( 'kernel/classes/ezcontentobjecttreenode.php' ); 00204 $this->RootNodeIDArray[] = $nodeID; 00205 $this->NodeIDArray[] = $nodeID; 00206 00207 if ( $isSubtree ) 00208 { 00209 $nodeArray = eZContentObjectTreeNode::subTreeByNodeID( array( 'AsObject' => false ), $nodeID ); 00210 foreach( $nodeArray as $node ) 00211 { 00212 $this->NodeIDArray[] = $node['node_id']; 00213 } 00214 } 00215 } 00216 00217 /*! 00218 Generate package based on NodeArray and input options 00219 00220 \param package 00221 \param options 00222 */ 00223 function generatePackage( $package, $options ) 00224 { 00225 $this->Package = $package; 00226 $remoteIDArray = array(); 00227 $this->NodeIDArray = array_unique( $this->NodeIDArray ); 00228 foreach( $this->NodeIDArray as $nodeID ) 00229 { 00230 $this->NodeObjectArray[(string)$nodeID] = eZContentObjectTreeNode::fetch( $nodeID ); 00231 } 00232 00233 foreach( $this->RootNodeIDArray as $nodeID ) 00234 { 00235 $this->RootNodeObjectArray[(string)$nodeID] = eZContentObjectTreeNode::fetch( $nodeID ); 00236 } 00237 00238 $this->generateObjectArray( $options['node_assignment'] ); 00239 00240 $classIDArray = false; 00241 if ( $options['include_classes'] ) 00242 { 00243 $remoteIDArray['class'] = array(); 00244 $classIDArray = $this->generateClassIDArray(); 00245 00246 //include_once( 'kernel/classes/packagehandlers/ezcontentclass/ezcontentclasspackagehandler.php' ); 00247 foreach ( $classIDArray as $classID ) 00248 { 00249 eZContentClassPackageHandler::addClass( $package, $classID ); 00250 } 00251 } 00252 00253 $dom = new DOMDocument( '1.0', 'utf-8' ); 00254 $packageRoot = $dom->createElement( 'content-object' ); 00255 $dom->appendChild( $packageRoot ); 00256 00257 $objectListDOMNode = $this->createObjectListNode( $options ); 00258 $importedObjectListDOMNode = $dom->importNode( $objectListDOMNode, true ); 00259 $packageRoot->appendChild( $importedObjectListDOMNode ); 00260 00261 $overrideSettingsArray = false; 00262 $templateFilenameArray = false; 00263 if ( $options['include_templates'] ) 00264 { 00265 $overrideSettingsListNode = $this->generateOverrideSettingsArray( $options['site_access_array'], $options['minimal_template_set'] ); 00266 $importedOverrideSettingsListNode = $dom->importNode( $overrideSettingsListNode, true ); 00267 $packageRoot->appendChild( $importedOverrideSettingsListNode ); 00268 00269 $designTemplateListNode = $this->generateTemplateFilenameArray(); 00270 $importedDesignTemplateListNode = $dom->importNode( $designTemplateListNode, true ); 00271 $packageRoot->appendChild( $importedDesignTemplateListNode ); 00272 00273 $fetchAliasListNode = $this->generateFetchAliasArray(); 00274 $importedFetchAliasListNode = $dom->importNode( $fetchAliasListNode, true ); 00275 $packageRoot->appendChild( $importedFetchAliasListNode ); 00276 } 00277 00278 $siteAccessListDOMNode = $this->createSiteAccessListNode( $options ); 00279 $importedSiteAccessListDOMNode = $dom->importNode( $siteAccessListDOMNode, true ); 00280 $packageRoot->appendChild( $importedSiteAccessListDOMNode ); 00281 00282 $topNodeListDOMNode = $this->createTopNodeListDOMNode( $options ); 00283 $importedTopNodeListDOMNode = $dom->importNode( $topNodeListDOMNode, true ); 00284 $packageRoot->appendChild( $importedTopNodeListDOMNode ); 00285 00286 //$filename = substr( md5( mt_rand() ), 0, 8 ); 00287 $filename = 'contentobjects'; 00288 $this->Package->appendInstall( 'ezcontentobject', false, false, true, 00289 $filename, $this->contentObjectDirectory(), 00290 array( 'content' => $packageRoot ) ); 00291 $this->Package->appendInstall( 'ezcontentobject', false, false, false, 00292 $filename, $this->contentObjectDirectory(), 00293 array( 'content' => false ) ); 00294 } 00295 00296 /*! 00297 \private 00298 Create DOMNode for list of top nodes. 00299 00300 \param options 00301 */ 00302 function createTopNodeListDOMNode( $options ) 00303 { 00304 $dom = new DOMDocument( '1.0', 'utf-8' ); 00305 $topNodeListDOMNode = $dom->createElement( 'top-node-list' ); 00306 $dom->appendChild( $topNodeListDOMNode ); 00307 00308 foreach( $this->RootNodeObjectArray as $rootNode ) 00309 { 00310 unset( $topNode ); 00311 $topNode = $dom->createElement( 'top-node' ); 00312 $topNode->appendChild( $dom->createTextNode( $rootNode->attribute( 'name' ) ) ); 00313 $topNode->setAttribute( 'node-id', $rootNode->attribute( 'node_id' ) ); 00314 $topNode->setAttribute( 'remote-id', $rootNode->attribute( 'remote_id' ) ); 00315 $topNodeListDOMNode->appendChild( $topNode ); 00316 } 00317 00318 return $topNodeListDOMNode; 00319 } 00320 00321 /*! 00322 \private 00323 Create DOMNode for list of added siteaccesses. 00324 00325 \param options 00326 */ 00327 function createSiteAccessListNode( $options ) 00328 { 00329 $dom = new DOMDocument( '1.0', 'utf-8' ); 00330 $siteAccessListDOMNode = $dom->createElement( 'site-access-list' ); 00331 $dom->appendChild( $siteAccessListDOMNode ); 00332 00333 foreach( $options['site_access_array'] as $siteAccess ) 00334 { 00335 unset( $siteAccessNode ); 00336 $siteAccessNode = $dom->createElement( 'site-access' ); 00337 $siteAccessNode->appendChild( $dom->createTextNode( $siteAccess ) ); 00338 $siteAccessListDOMNode->appendChild( $siteAccessNode ); 00339 } 00340 00341 return $siteAccessListDOMNode; 00342 } 00343 00344 /*! 00345 \private 00346 Serializes and adds all contentobjects to package 00347 00348 \param options 00349 */ 00350 function createObjectListNode( $options ) 00351 { 00352 if ( $options['versions'] == 'current' ) 00353 { 00354 $version = true; 00355 } 00356 else 00357 { 00358 $version = false; 00359 } 00360 00361 $path = $this->Package->path() . '/' . $this->contentObjectDirectory(); 00362 if ( !file_exists( $path ) ) 00363 eZDir::mkdir( $path, false, true ); 00364 00365 $dom = new DOMDocument( '1.0', 'utf-8' ); 00366 00367 // Store objects to separate files or not 00368 $storeToMultiple = count( $this->ObjectArray ) >= self::STORE_OBJECTS_TO_SEPARATE_FILES_THRESHOLD ? true : false; 00369 if ( $storeToMultiple ) 00370 $objectListNode = $dom->createElement( 'object-files-list' ); 00371 else 00372 $objectListNode = $dom->createElement( 'object-list' ); 00373 00374 $dom->appendChild( $objectListNode ); 00375 00376 foreach( array_keys( $this->ObjectArray ) as $objectID ) 00377 { 00378 $objectNode = $this->ObjectArray[$objectID]->serialize( $this->Package, $version, $options, $this->NodeObjectArray, $this->RootNodeIDArray ); 00379 00380 if ( $storeToMultiple ) 00381 { 00382 $fileName = 'object-' . $objectNode->getAttribute( 'remote_id' ) . '.xml'; 00383 $filePath = $path . '/' . $fileName; 00384 00385 $objectFileNode = $dom->createElement( 'object-file' ); 00386 $objectFileNode->setAttribute( 'filename', $fileName ); 00387 $objectListNode->appendChild( $objectFileNode ); 00388 00389 $partDOM = new DOMDocument( '1.0', 'utf-8' ); 00390 $partDOM->formatOutput = true; 00391 $importedObjectNode = $partDOM->importNode( $objectNode, true ); 00392 $partDOM->appendChild( $importedObjectNode ); 00393 $this->Package->storeDOM( $filePath, $partDOM ); 00394 unset( $partDOM ); 00395 unset( $objectFileNode ); 00396 } 00397 else 00398 { 00399 $importedObjectNode = $dom->importNode( $objectNode, true ); 00400 $objectListNode->appendChild( $importedObjectNode ); 00401 } 00402 unset( $objectNode ); 00403 } 00404 00405 return $objectListNode; 00406 } 00407 00408 /*! 00409 \private 00410 Generate list of content objects to export, and store them to 00411 00412 \param node_assignments, 'selected' or 'main' 00413 */ 00414 function generateObjectArray( $nodeAssignment ) 00415 { 00416 foreach( $this->NodeObjectArray as $contentNode ) 00417 { 00418 if ( $nodeAssignment == 'main' ) 00419 { 00420 if ( $contentNode->attribute( 'main_node_id' ) == $contentNode->attribute( 'node_id' ) ) 00421 { 00422 $this->ObjectArray[(string)$contentNode->attribute( 'contentobject_id' )] = $contentNode->object(); 00423 } 00424 } 00425 else 00426 { 00427 $this->ObjectArray[(string)$contentNode->attribute( 'contentobject_id' )] = $contentNode->object(); 00428 } 00429 } 00430 } 00431 00432 /*! 00433 \private 00434 */ 00435 function &generateFetchAliasArray() 00436 { 00437 $dom = new DOMDocument( '1.0', 'utf-8' ); 00438 $fetchAliasListDOMNode = $dom->createElement( 'fetch-alias-list' ); 00439 $registeredAliases = array(); 00440 00441 foreach( array_keys( $this->TemplateFileArray ) as $siteAccess ) 00442 { 00443 $aliasINI = eZINI::instance( 'fetchalias.ini', 'settings', null, null, true ); 00444 $aliasINI->prependOverrideDir( "siteaccess/$siteAccess", false, 'siteaccess' ); 00445 $aliasINI->loadCache(); 00446 00447 foreach ( $this->TemplateFileArray[$siteAccess] as $filename ) 00448 { 00449 $fp = fopen( $filename, 'r' ); 00450 if ( !$fp ) 00451 { 00452 eZDebug::writeError( 'Could not open ' . $filename . ' during content object export.', 00453 'eZContentObjectPackageHandler::generateFethAliasArray()' ); 00454 continue; 00455 } 00456 00457 $str = fread( $fp, filesize( $filename ) ); 00458 00459 $matchArray = array(); 00460 preg_match_all( "#.*fetch_alias\([ ]*([a-zA-Z0-9_]+)[ |,|)]+.*#U", $str, $matchArray, PREG_PATTERN_ORDER ); 00461 00462 foreach( $matchArray[1] as $fetchAlias ) 00463 { 00464 if ( isset( $registeredAliases[$fetchAlias] ) ) 00465 { 00466 continue; 00467 } 00468 $registeredAliases[$fetchAlias] = true; 00469 00470 unset( $fetchAliasDOMNode ); 00471 $fetchAliasDOMNode = $dom->createElement( 'fetch-alias' ); 00472 $fetchAliasDOMNode->setAttribute( 'name', $fetchAlias ); 00473 $fetchAliasDOMNode->setAttribute( 'site-access', $siteAccess ); 00474 00475 $fetchBlock = $aliasINI->group( $fetchAlias ); 00476 if ( isset( $fetchBlock['Constant'] ) ) 00477 { 00478 foreach ( $fetchBlock['Constant'] as $matchKey => $value ) 00479 { 00480 if ( strpos( $matchKey, 'class_' ) === 0 && 00481 is_int( $value ) ) 00482 { 00483 $contentClass = eZContentClass::fetch( $value ); 00484 $fetchBlock['Constant']['class_remote_id'] = $contentClass->attribute( 'remote_id' ); 00485 } 00486 if ( strpos( $matchKey, 'node_' ) === 0 && 00487 is_int( $value ) ) 00488 { 00489 $contentTreeNode = eZContentObjectTreeNode::fetch( $value ); 00490 $fetchBlock['Constant']['node_remote_id'] = $contentTreeNode->attribute( 'remote_id' ); 00491 } 00492 if ( strpos( $matchKey, 'parent_node_' ) === 0 && 00493 is_int( $value ) ) 00494 { 00495 $contentTreeNode = eZContentObjectTreeNode::fetch( $value ); 00496 $fetchBlock['Constant']['parent_node_remote_id'] = $contentTreeNode->attribute( 'remote_id' ); 00497 } 00498 if ( strpos( $matchKey, 'object_' ) === 0 && 00499 is_int( $value ) ) 00500 { 00501 $contentObject = eZContentObject::fetch( $value ); 00502 $fetchBlock['Constant']['object_remote_id'] = $contentObject->attribute( 'remote_id' ); 00503 } 00504 } 00505 } 00506 $importedNode = $dom->importNode( eZContentObjectPackageHandler::createElementNodeFromArray( $fetchAlias, $fetchBlock ), true ); 00507 $fetchAliasDOMNode->appendChild( $importedNode ); 00508 $fetchAliasListDOMNode->appendChild( $fetchAliasDOMNode ); 00509 } 00510 } 00511 } 00512 return $fetchAliasListDOMNode; 00513 } 00514 00515 /*! 00516 \private 00517 */ 00518 function &generateTemplateFilenameArray() 00519 { 00520 $dom = new DOMDocument( '1.0', 'utf-8' ); 00521 00522 $templateListDOMNode = $dom->createElement( 'template-list' ); 00523 $dom->appendChild( $templateListDOMNode ); 00524 00525 //include_once( 'kernel/common/eztemplatedesignresource.php' ); 00526 00527 foreach( array_keys( $this->OverrideSettingsArray ) as $siteAccess ) 00528 { 00529 $this->TemplateFileArray[$siteAccess] = array(); 00530 $overrideArray = eZTemplateDesignResource::overrideArray( $siteAccess ); 00531 00532 foreach( $this->OverrideSettingsArray[$siteAccess] as $override ) 00533 { 00534 $customMatchArray = $overrideArray['/' . $override['Source']]['custom_match']; 00535 00536 foreach( $customMatchArray as $customMatch ) 00537 { 00538 if ( $customMatch['conditions'] == null ) 00539 { 00540 //$templateListDOMNode->appendChild( $this->createDOMNodeFromFile( $customMatch['match_file'], $siteAccess, 'design' ) ); 00541 //$this->TemplateFileArray[$siteAccess][] = $customMatch['match_file']; 00542 } 00543 else if ( count( array_diff( $customMatch['conditions'], $override['Match'] ) ) == 0 && 00544 count( array_diff( $override['Match'], $customMatch['conditions'] ) ) == 0 ) 00545 { 00546 unset( $node ); 00547 $node = $this->createDOMNodeFromFile( $customMatch['match_file'], $siteAccess, 'design' ); 00548 $importedNode = $dom->importNode( $node, true ); 00549 $templateListDOMNode->appendChild( $importedNode ); 00550 $this->TemplateFileArray[$siteAccess][] = $customMatch['match_file']; 00551 } 00552 } 00553 } 00554 } 00555 return $templateListDOMNode; 00556 00557 //TODO : add templates included in templates here. 00558 } 00559 00560 /*! 00561 \private 00562 Add file to repository and return DONNode description of file 00563 00564 \param filename 00565 \param siteaccess 00566 \param filetype (optional) 00567 */ 00568 function createDOMNodeFromFile( $filename, $siteAccess, $filetype = false ) 00569 { 00570 $path = substr( $filename, strpos( $filename, '/', 7 ) ); 00571 00572 $dom = new DOMDocument( '1.0', 'utf-8' ); 00573 $fileDOMNode = $dom->createElement( 'file' ); 00574 $fileDOMNode->setAttribute( 'site-access', $siteAccess ); 00575 00576 if ( $filetype !== false ) 00577 { 00578 $fileDOMNode->setAttribute( 'file-type', $filetype ); 00579 } 00580 00581 $dom->appendChild( $fileDOMNode ); 00582 $originalPathNode = $dom->createElement( 'original-path' ); 00583 $originalPathNode->appendChild( $dom->createTextNode( $filename ) ); 00584 $fileDOMNode->appendChild( $originalPathNode ); 00585 $pathNode = $dom->createElement( 'path' ); 00586 $pathNode->appendChild( $dom->createTextNode( $path ) ); 00587 $fileDOMNode->appendChild( $pathNode ); 00588 00589 $destinationPath = $this->Package->path() . '/' . eZContentObjectPackageHandler::contentObjectDirectory() . '/' . $path; 00590 eZDir::mkdir( eZDir::dirpath( $destinationPath ), false, true ); 00591 eZFileHandler::copy( $filename, $destinationPath ); 00592 00593 return $fileDOMNode; 00594 } 00595 00596 /*! 00597 \private 00598 Get all template overrides used by exported objects 00599 00600 \param site access array 00601 */ 00602 function &generateOverrideSettingsArray( $siteAccessArray, $minimalTemplateSet ) 00603 { 00604 $datatypeHash = array(); 00605 $simpleMatchList = array(); 00606 $regexpMatchList = array(); 00607 foreach ( $siteAccessArray as $siteAccess ) 00608 { 00609 $overrideINI = eZINI::instance( 'override.ini', 'settings', null, null, true ); 00610 $overrideINI->prependOverrideDir( "siteaccess/$siteAccess", false, 'siteaccess' ); 00611 $overrideINI->loadCache(); 00612 00613 $matchBlock = false; 00614 $blockMatchArray = array(); 00615 00616 foreach( array_keys( $this->NodeObjectArray ) as $nodeID ) 00617 { 00618 // Extract some information that will be used 00619 unset( $contentNode, $contentObject, $contentClass ); 00620 $contentNode = $this->NodeObjectArray[$nodeID]; 00621 $contentObject = $contentNode->attribute( 'object' ); 00622 $contentClass = $contentObject->attribute( 'content_class' ); 00623 $attributeList = $contentClass->fetchAttributes( false, false, false ); 00624 $datatypeList = array(); 00625 foreach ( $attributeList as $attribute ) 00626 { 00627 $datatypeList[] = $attribute['data_type_string']; 00628 if ( !isset( $datatypeHash[$attribute['data_type_string']] ) ) 00629 { 00630 //include_once( 'kernel/classes/ezdatatype.php' ); 00631 $datatype = eZDataType::create( $attribute['data_type_string'] ); 00632 $datatypeHash[$attribute['data_type_string']] = $datatype; 00633 if ( !method_exists( $datatype, 'templateList' ) ) 00634 continue; 00635 $templateList = $datatype->templateList(); 00636 if ( $templateList === false ) 00637 continue; 00638 foreach ( $templateList as $templateMatch ) 00639 { 00640 if ( is_string( $templateMatch ) ) 00641 { 00642 $simpleMatchList[] = $templateMatch; 00643 } 00644 else if ( is_array( $templateMatch ) ) 00645 { 00646 if ( $templateMatch[0] == 'regexp' ) 00647 { 00648 $regexpMatchList[] = $templateMatch[1]; 00649 } 00650 } 00651 } 00652 } 00653 } 00654 $datatypeText = implode( '|', array_unique( $datatypeList ) ); 00655 00656 foreach( array_keys( $overrideINI->groups() ) as $blockName ) 00657 { 00658 if ( isset( $blockMatchArray[$blockName] ) ) 00659 { 00660 continue; 00661 } 00662 00663 $blockData = $overrideINI->group( $blockName ); 00664 $sourceName = $blockData['Source']; 00665 $matchSettings = false; 00666 if ( isset( $blockData['Match'] ) ) 00667 $matchSettings = $blockData['Match']; 00668 00669 $matchValue = array(); 00670 $validMatch = true; 00671 $hasMatchType = false; 00672 if ( $matchSettings ) 00673 { 00674 foreach( array_keys( $matchSettings ) as $matchType ) 00675 { 00676 switch( $matchType ) 00677 { 00678 case 'object': 00679 { 00680 $hasMatchType = true; 00681 if ( $contentNode->attribute( 'contentobject_id' ) != $matchSettings[$matchType] ) 00682 { 00683 $validMatch = false; 00684 } 00685 else 00686 { 00687 $matchValue[$this->OverrideObjectRemoteID] = $contentObject->attribute( 'remote_id' ); 00688 } 00689 } break; 00690 00691 case 'node': 00692 { 00693 $hasMatchType = true; 00694 if ( $nodeID != $matchSettings[$matchType] ) 00695 { 00696 $validMatch = false; 00697 } 00698 else 00699 { 00700 $matchValue[$this->OverrideNodeRemoteID] = $contentNode->attribute( 'remote_id' ); 00701 } 00702 } break; 00703 00704 case 'parent_node': 00705 { 00706 $hasMatchType = true; 00707 if ( $contentNode->attribute( 'parent_node_id' ) != $matchSettings[$matchType] ) 00708 { 00709 $validMatch = false; 00710 } 00711 else 00712 { 00713 $parentNode = $contentNode->attribute( 'parent' ); 00714 $matchValue[$this->OverrideParentNodeRemoteID] = $parentNode->attribute( 'remote_id' ); 00715 } 00716 } break; 00717 00718 case 'class': 00719 { 00720 $hasMatchType = true; 00721 if ( $contentObject->attribute( 'contentclass_id' ) != $matchSettings[$matchType] ) 00722 { 00723 $validMatch = false; 00724 } 00725 else 00726 { 00727 $matchValue[$this->OverrideClassRemoteID] = $contentClass->attribute( 'remote_id' ); 00728 } 00729 } break; 00730 00731 case 'class_identifier': 00732 { 00733 $hasMatchType = true; 00734 if ( $contentObject->attribute( 'class_identifier' ) != $matchSettings[$matchType] ) 00735 { 00736 $validMatch = false; 00737 } 00738 } break; 00739 00740 case 'section': 00741 { 00742 $hasMatchType = true; 00743 if ( $contentObject->attribute( 'section_id' ) != $matchSettings[$matchType] ) 00744 { 00745 $validMatch = false; 00746 } 00747 } break; 00748 00749 case 'depth': 00750 { 00751 $hasMatchType = true; 00752 if ( $contentNode->attribute( 'depth' ) != $matchSettings[$matchType] ) 00753 { 00754 $validMatch = false; 00755 } 00756 } break; 00757 } 00758 00759 if ( !$validMatch ) 00760 { 00761 break; 00762 } 00763 } 00764 } 00765 else 00766 { 00767 $validMatch = false; 00768 } 00769 00770 if ( !$hasMatchType ) 00771 { 00772 // Datatype match, we include overrides for datatype templates 00773 if ( preg_match( "#^content/datatype/[a-zA-Z]+/(" . $datatypeText . ")\\.tpl$#", $sourceName ) ) 00774 { 00775 $validMatch = true; 00776 $hasMatchType = true; 00777 } 00778 else if ( in_array( $sourceName, $simpleMatchList ) ) 00779 { 00780 $validMatch = true; 00781 $hasMatchType = true; 00782 } 00783 else 00784 { 00785 foreach ( $regexpMatchList as $regexpMatch ) 00786 { 00787 if ( preg_match( $regexpMatch, $sourceName ) ) 00788 { 00789 $validMatch = true; 00790 $hasMatchType = true; 00791 } 00792 } 00793 } 00794 } 00795 00796 if ( $validMatch ) 00797 { 00798 if ( !$minimalTemplateSet or 00799 $hasMatchType ) 00800 { 00801 $blockMatchArray[$blockName] = array_merge( $blockData, 00802 $matchValue ); 00803 } 00804 } 00805 } 00806 } 00807 $this->OverrideSettingsArray[$siteAccess] = $blockMatchArray; 00808 } 00809 00810 $dom = new DOMDocument( '1.0', 'utf-8' ); 00811 00812 $overrideSettingsListDOMNode = $dom->createElement( 'override-list' ); 00813 $dom->appendChild( $overrideSettingsListDOMNode ); 00814 foreach ( $this->OverrideSettingsArray as $siteAccess => $blockMatchArray ) 00815 { 00816 foreach( $blockMatchArray as $blockName => $iniGroup ) 00817 { 00818 unset( $blockMatchNode ); 00819 $blockMatchNode = $dom->createElement( 'block' ); 00820 $blockMatchNode->setAttribute( 'name', $blockName ); 00821 $blockMatchNode->setAttribute( 'site-access', $siteAccess ); 00822 $importedNode = $dom->importNode( eZContentObjectPackageHandler::createElementNodeFromArray( $blockName, $iniGroup ), true ); 00823 $blockMatchNode->appendChild( $importedNode ); 00824 $overrideSettingsListDOMNode->appendChild( $blockMatchNode ); 00825 } 00826 } 00827 return $overrideSettingsListDOMNode; 00828 } 00829 00830 /*! 00831 \private 00832 Get list of all class objects used in by the nodes in NodeArray 00833 */ 00834 function &generateClassIDArray() 00835 { 00836 $classIDArray = array(); 00837 foreach( $this->NodeObjectArray as $nodeObject ) 00838 { 00839 $contentObject = $nodeObject->object(); 00840 $classIDArray[] = $contentObject->attribute( 'contentclass_id' ); 00841 } 00842 $classIDArray = array_unique( $classIDArray ); 00843 return $classIDArray; 00844 } 00845 00846 /*! 00847 \reimp 00848 Uninstalls all previously installed content objects. 00849 */ 00850 function uninstall( $package, $installType, $parameters, 00851 $name, $os, $filename, $subdirectory, 00852 $content, &$installParameters, 00853 &$installData ) 00854 { 00855 $this->Package = $package; 00856 00857 if ( isset( $installParameters['error']['error_code'] ) ) 00858 $errorCode = $installParameters['error']['error_code']; 00859 else 00860 $errorCode = false; 00861 00862 // Error codes reserverd for content object uninstallation 00863 if ( !$errorCode || ( $errorCode >= self::UNINSTALL_OBJECTS_ERROR_RANGE_FROM && 00864 $errorCode <= self::UNINSTALL_OBJECTS_ERROR_RANGE_TO ) ) 00865 { 00866 $objectListNode = $content->getElementsByTagName( 'object-list' )->item( 0 ); 00867 if ( $objectListNode ) 00868 { 00869 $objectNodes = $objectListNode->getElementsByTagName( 'object' ); 00870 } 00871 else 00872 { 00873 $objectListNode = $content->getElementsByTagName( 'object-files-list' )->item( 0 ); 00874 $objectNodes = $objectListNode->getElementsByTagName( 'object-file' ); 00875 } 00876 00877 // loop intentionally from the last until the first 00878 // objects need to be uninstalled in reverse order of installation 00879 for ( $i = $objectNodes->length - 1; $i >=0; $i-- ) 00880 { 00881 $objectNode = $objectNodes->item( $i ); 00882 $realObjectNode = $this->getRealObjectNode( $objectNode ); 00883 00884 $objectRemoteID = $realObjectNode->getAttribute( 'remote_id' ); 00885 $name = $realObjectNode->getAttribute( 'name' ); 00886 00887 if ( isset( $installParameters['error']['error_code'] ) && 00888 !$this->isErrorElement( $objectRemoteID, $installParameters ) ) 00889 continue; 00890 00891 if ( isset( $object ) ) 00892 { 00893 eZContentObject::clearCache( $object->attribute( 'id' ) ); 00894 unset( $object ); 00895 } 00896 $object = eZContentObject::fetchByRemoteID( $objectRemoteID ); 00897 00898 if ( $object !== null ) 00899 { 00900 $modified = $object->attribute( 'modified' ); 00901 $published = $object->attribute( 'published' ); 00902 if ( $modified > $published ) 00903 { 00904 $choosenAction = $this->errorChoosenAction( eZContentObject::PACKAGE_ERROR_MODIFIED, 00905 $installParameters, false, $this->HandlerType ); 00906 00907 if ( $choosenAction == eZContentObject::PACKAGE_KEEP ) 00908 { 00909 continue; 00910 } 00911 if ( $choosenAction != eZContentObject::PACKAGE_DELETE ) 00912 { 00913 $installParameters['error'] = array( 'error_code' => eZContentObject::PACKAGE_ERROR_MODIFIED, 00914 'element_id' => $objectRemoteID, 00915 'description' => ezi18n( 'kernel/package', 00916 "Object '%objectname' has been modified since installation. Are you sure you want to remove it?", 00917 false, array( '%objectname' => $name ) ), 00918 'actions' => array( eZContentObject::PACKAGE_DELETE => ezi18n( 'kernel/package', 'Remove' ), 00919 eZContentObject::PACKAGE_KEEP => ezi18n( 'kernel/package', 'Keep object' ) ) ); 00920 return false; 00921 } 00922 } 00923 00924 $assignedNodes = $object->attribute( 'assigned_nodes' ); 00925 $assignedNodeIDArray = array(); 00926 foreach( $assignedNodes as $node ) 00927 { 00928 $assignedNodeIDArray[] = $node->attribute( 'node_id' ); 00929 } 00930 if ( count( $assignedNodeIDArray ) == 0 ) 00931 continue; 00932 $info = eZContentObjectTreeNode::subtreeRemovalInformation( $assignedNodeIDArray ); 00933 $childrenCount = $info['total_child_count']; 00934 00935 if ( $childrenCount > 0 ) 00936 { 00937 $choosenAction = $this->errorChoosenAction( eZContentObject::PACKAGE_ERROR_HAS_CHILDREN, 00938 $installParameters, false, $this->HandlerType ); 00939 00940 if ( $choosenAction == eZContentObject::PACKAGE_KEEP ) 00941 { 00942 continue; 00943 } 00944 if ( $choosenAction != eZContentObject::PACKAGE_DELETE ) 00945 { 00946 $installParameters['error'] = array( 'error_code' => eZContentObject::PACKAGE_ERROR_HAS_CHILDREN, 00947 'element_id' => $objectRemoteID, 00948 'description' => ezi18n( 'kernel/package', 00949 "Object '%objectname' has %childrencount sub-item(s) that will be removed.", 00950 false, array( '%objectname' => $name, 00951 '%childrencount' => $childrenCount ) ), 00952 'actions' => array( eZContentObject::PACKAGE_DELETE => ezi18n( 'kernel/package', "Remove object and its sub-item(s)" ), 00953 eZContentObject::PACKAGE_KEEP => ezi18n( 'kernel/package', 'Keep object' ) ) ); 00954 return false; 00955 } 00956 } 00957 00958 eZContentObjectTreeNode::removeSubtrees( $assignedNodeIDArray, false ); 00959 00960 ////include_once( 'kernel/classes/ezcontentobjectoperations.php' ); 00961 00962 //eZContentObjectOperations::remove( $object->attribute( 'id' ) ); 00963 } 00964 else 00965 { 00966 eZDebug::writeNotice( "Can't uninstall object '$name': object not found", 'eZContentObjectPackageHandler::uninstall' ); 00967 } 00968 00969 unset( $realObjectNode ); 00970 } 00971 } 00972 return true; 00973 } 00974 00975 /*! 00976 \reimp 00977 Creates a new contentobject as defined in the xml structure. 00978 */ 00979 function install( $package, $installType, $parameters, 00980 $name, $os, $filename, $subdirectory, 00981 $content, &$installParameters, 00982 &$installData ) 00983 { 00984 $this->Package = $package; 00985 00986 if ( isset( $installParameters['error']['error_code'] ) ) 00987 $errorCode = $installParameters['error']['error_code']; 00988 else 00989 $errorCode = false; 00990 00991 // Error codes reservered for content object installation 00992 if ( !$errorCode || ( $errorCode >= self::INSTALL_OBJECTS_ERROR_RANGE_FROM && 00993 $errorCode <= self::INSTALL_OBJECTS_ERROR_RANGE_TO ) ) 00994 { 00995 $objectListNode = $content->getElementsByTagName( 'object-list' )->item( 0 ); 00996 if ( $objectListNode ) 00997 { 00998 $objectNodes = $objectListNode->getElementsByTagName( 'object' ); 00999 } 01000 else 01001 { 01002 $objectListNode = $content->getElementsByTagName( 'object-files-list' )->item( 0 ); 01003 $objectNodes = $objectListNode->getElementsByTagName( 'object-file' ); 01004 } 01005 01006 01007 if ( !$this->installContentObjects( $objectNodes, 01008 $content->getElementsByTagName( 'top-node-list' )->item( 0 ), 01009 $installParameters ) ) 01010 return false; 01011 $errorCode = false; 01012 } 01013 01014 if ( !$this->installTemplates( $content->getElementsByTagName( 'template-list' )->item( 0 ), 01015 $package, 01016 $subdirectory, 01017 $installParameters ) ) 01018 return false; 01019 01020 01021 if ( !$this->installOverrides( $content->getElementsByTagName( 'override-list' )->item( 0 ), 01022 $installParameters ) ) 01023 return false; 01024 01025 if ( !$this->installFetchAliases( $content->getElementsByTagName( 'fetch-alias-list' )->item( 0 ), 01026 $installParameters ) ) 01027 return false; 01028 01029 return true; 01030 } 01031 01032 /*! 01033 \private 01034 01035 Serialize and install content objects 01036 01037 \param object-list DOMNode 01038 \param install parameters 01039 */ 01040 function installContentObjects( $objectNodes, $topNodeListNode, &$installParameters ) 01041 { 01042 //include_once( 'kernel/classes/ezcontentobject.php' ); 01043 if ( isset( $installParameters['user_id'] ) ) 01044 $userID = $installParameters['user_id']; 01045 else 01046 $userID = eZUser::currentUserID(); 01047 01048 $handlerType = $this->handlerType(); 01049 $firstInstalledID = null; 01050 01051 foreach( $objectNodes as $objectNode ) 01052 { 01053 $realObjectNode = $this->getRealObjectNode( $objectNode ); 01054 01055 // Cycle until we reach an element where error has occured. 01056 // If action has been choosen, try install this item again, else skip it. 01057 if ( isset( $installParameters['error']['error_code'] ) && 01058 !$this->isErrorElement( $realObjectNode->getAttribute( 'remote_id' ), $installParameters ) ) 01059 continue; 01060 01061 if ( !$firstInstalledID ) 01062 $firstInstalledID = $realObjectNode->getAttribute( 'remote_id' ); 01063 01064 $newObject = eZContentObject::unserialize( $this->Package, $realObjectNode, $installParameters, $userID, $handlerType ); 01065 if ( !$newObject ) 01066 return false; 01067 01068 if ( is_object( $newObject ) ) 01069 { 01070 eZContentObject::clearCache( $newObject->attribute( 'id' ) ); 01071 unset( $newObject ); 01072 } 01073 unset( $realObjectNode ); 01074 01075 if ( isset( $installParameters['error'] ) && count( $installParameters['error'] ) ) 01076 $installParameters['error'] = array(); 01077 } 01078 01079 $this->installSuspendedNodeAssignment( $installParameters ); 01080 $this->installSuspendedObjectRelations( $installParameters ); 01081 01082 // Call postUnserialize on all installed objects 01083 foreach( $objectNodes as $objectNode ) 01084 { 01085 if ( $objectNode->localName == 'object' ) 01086 { 01087 $remoteID = $objectNode->getAttribute( 'remote_id' ); 01088 } 01089 else 01090 { 01091 $remoteID = substr( $objectNode->getAttribute( 'filename' ), 7, 32 ); 01092 } 01093 01094 // Begin from the object that we started from in the previous cycle 01095 if ( $firstInstalledID && $remoteID != $firstInstalledID ) 01096 continue; 01097 else 01098 $firstInstalledID = null; 01099 01100 $object = eZContentObject::fetchByRemoteID( $remoteID ); 01101 if ( is_object( $object ) ) 01102 { 01103 $object->postUnserialize( $this->Package ); 01104 eZContentObject::clearCache( $object->attribute( 'id' ) ); 01105 } 01106 unset( $object ); 01107 } 01108 01109 return true; 01110 } 01111 01112 /*! 01113 \private 01114 01115 \param install parameters 01116 */ 01117 function installSuspendedNodeAssignment( &$installParameters ) 01118 { 01119 if ( !isset( $installParameters['suspended-nodes'] ) ) 01120 { 01121 return; 01122 } 01123 foreach ( $installParameters['suspended-nodes'] as $parentNodeRemoteID => $suspendedNodeInfo ) 01124 { 01125 $parentNode = eZContentObjectTreeNode::fetchByRemoteID( $parentNodeRemoteID ); 01126 if ( $parentNode !== null ) 01127 { 01128 $nodeInfo = $suspendedNodeInfo['nodeinfo']; 01129 $nodeInfo['parent_node'] = $parentNode->attribute( 'node_id' ); 01130 01131 $existNodeAssignment = eZPersistentObject::fetchObject( eZNodeAssignment::definition(), 01132 null, 01133 $nodeInfo ); 01134 $nodeInfo['priority'] = $suspendedNodeInfo['priority']; 01135 if( !is_object( $existNodeAssignment ) ) 01136 { 01137 $nodeAssignment = eZNodeAssignment::create( $nodeInfo ); 01138 $nodeAssignment->store(); 01139 } 01140 01141 $contentObject = eZContentObject::fetch( $nodeInfo['contentobject_id'] ); 01142 if ( is_object( $contentObject ) && $contentObject->attribute( 'current_version' ) == $nodeInfo['contentobject_version'] ) 01143 { 01144 //include_once( 'lib/ezutils/classes/ezoperationhandler.php' ); 01145 eZOperationHandler::execute( 'content', 'publish', array( 'object_id' => $nodeInfo['contentobject_id'], 01146 'version' => $nodeInfo['contentobject_version'] ) ); 01147 } 01148 if ( isset( $nodeInfo['is_main'] ) && $nodeInfo['is_main'] ) 01149 { 01150 $existingMainNode = eZContentObjectTreeNode::fetchByRemoteID( $nodeInfo['parent_remote_id'], false ); 01151 if ( $existingMainNode ) 01152 { 01153 eZContentObjectTreeNode::updateMainNodeID( $existingMainNode['node_id'], 01154 $nodeInfo['contentobject_id'], 01155 $nodeInfo['contentobject_version'], 01156 $nodeInfo['parent_node'] ); 01157 } 01158 } 01159 } 01160 else 01161 { 01162 eZDebug::writeError( 'Can not find parent node by remote-id ID = ' . $parentNodeRemoteID, 'eZContentObjectPackageHandler::installSuspendedNodeAssignment()' ); 01163 } 01164 unset( $installParameters['suspended-nodes'][$parentNodeRemoteID] ); 01165 } 01166 } 01167 01168 /*! 01169 \private 01170 01171 Installs suspended content object relations (need for complex content-relations structure) 01172 01173 \param install parameters 01174 */ 01175 function installSuspendedObjectRelations( &$installParameters ) 01176 { 01177 if ( !isset( $installParameters['suspended-relations'] ) ) 01178 { 01179 return; 01180 } 01181 foreach( $installParameters['suspended-relations'] as $suspendedObjectRelation ) 01182 { 01183 $contentObjectID = $suspendedObjectRelation['contentobject-id']; 01184 $contentObjectVersionID = $suspendedObjectRelation['contentobject-version']; 01185 01186 $contentObjectVersion = eZContentObjectVersion::fetchVersion( $contentObjectVersionID, $contentObjectID ); 01187 if ( is_object( $contentObjectVersion ) ) 01188 { 01189 $relatedObjectRemoteID = $suspendedObjectRelation['related-object-remote-id']; 01190 $relatedObject = eZContentObject::fetchByRemoteID( $relatedObjectRemoteID ); 01191 $relatedObjectID = ( $relatedObject !== null ) ? $relatedObject->attribute( 'id' ) : null; 01192 01193 if ( $relatedObjectID ) 01194 { 01195 $relatedObject->addContentObjectRelation( $relatedObjectID, $contentObjectVersionID, $contentObjectID ); 01196 } 01197 else 01198 { 01199 eZDebug::writeError( 'Can not find related object by remote-id ID = ' . $relatedObjectRemoteID, 'eZContentObjectPackageHandler::installSuspendedObjectRelations()' ); 01200 } 01201 } 01202 } 01203 unset( $installParameters['suspended-relations'] ); 01204 } 01205 01206 /*! 01207 \private 01208 01209 Set and install templates 01210 01211 \param template list 01212 \param package 01213 \param subdirectory 01214 \param install parameters. 01215 */ 01216 function installTemplates( $templateList, $package, $subdirectory, &$installParameters ) 01217 { 01218 if ( !$templateList ) 01219 { 01220 return true; 01221 } 01222 //include_once( 'kernel/common/eztemplatedesignresource.php' ); 01223 01224 $siteAccessDesignPathArray = array(); 01225 $templateRootPath = $package->path() . '/' . $subdirectory; 01226 foreach( $templateList->getElementsByTagName( 'file' ) as $fileNode ) 01227 { 01228 $originalSiteAccess = $fileNode->getAttribute( 'site-access' ); 01229 if ( isset( $installParameters['site_access_map'][$originalSiteAccess] ) ) 01230 { 01231 $newSiteAccess = $installParameters['site_access_map'][$originalSiteAccess]; 01232 } 01233 else 01234 { 01235 $newSiteAccess = $installParameters['site_access_map']['*']; 01236 } 01237 01238 if ( !isset( $siteAccessDesignPathArray[$newSiteAccess] ) ) 01239 { 01240 $ini = eZINI::instance( 'site.ini', 'settings', null, null, true ); 01241 $ini->prependOverrideDir( "siteaccess/$newSiteAccess", false, 'siteaccess' ); 01242 $ini->loadCache(); 01243 01244 if ( isset( $installParameters['design_map'] ) ) 01245 { 01246 $designMap = $installParameters['design_map']; 01247 if ( isset( $designMap[$originalSiteAccess] ) ) 01248 $siteAccessDesignPathArray[$newSiteAccess] = eZTemplateDesignResource::designStartPath() . '/' . $designMap[$originalSiteAccess]; 01249 else 01250 $siteAccessDesignPathArray[$newSiteAccess] = eZTemplateDesignResource::designStartPath() . '/' . $designMap['*']; 01251 } 01252 else 01253 { 01254 $siteAccessDesignPathArray[$newSiteAccess] = eZTemplateDesignResource::designStartPath() . '/' . $ini->variable( "DesignSettings", "StandardDesign" ); 01255 } 01256 } 01257 01258 $path = ''; 01259 foreach( $fileNode->childNodes as $pathNode ) 01260 { 01261 if ( $pathNode->nodeName == 'path' ) 01262 { 01263 $path = $pathNode->nodeValue; 01264 break; 01265 } 01266 } 01267 01268 $sourcePath = $templateRootPath . $path; 01269 $destinationPath = $siteAccessDesignPathArray[$newSiteAccess] . $path; 01270 01271 eZDir::mkdir( eZDir::dirpath( $destinationPath ), false, true ); 01272 if ( !eZFileHandler::copy( $sourcePath, $destinationPath ) ) 01273 return false; 01274 01275 // eZDebug::writeNotice( 'Copied: "' . $sourcePath . '" to: "' . $destinationPath . '"', 01276 // 'eZContentObjectPackageHandler::installTemplates()' ); 01277 } 01278 return true; 01279 } 01280 01281 /*! 01282 \private 01283 01284 Install overrides 01285 01286 \param override list 01287 \param install parameters 01288 */ 01289 function installOverrides( $overrideListNode, &$parameters ) 01290 { 01291 if ( !$overrideListNode ) 01292 { 01293 return true; 01294 } 01295 01296 $overrideINIArray = array(); 01297 foreach( $overrideListNode->getElementsByTagName( 'block' ) as $blockNode ) 01298 { 01299 if ( isset( $parameters['site_access_map'][$blockNode->getAttribute( 'site-access' )] ) ) 01300 { 01301 $newSiteAccess = $parameters['site_access_map'][$blockNode->getAttribute( 'site-access' )]; 01302 } 01303 else 01304 { 01305 $newSiteAccess = $parameters['site_access_map']['*']; 01306 } 01307 01308 if ( !$newSiteAccess ) 01309 { 01310 eZDebug::writeError( 'SiteAccess map for : ' . $blockNode->getAttribute( 'site-access' ) . ' not set.', 01311 'eZContentObjectPackageHandler::installOverrides()' ); 01312 continue; 01313 } 01314 01315 if ( !isset( $overrideINIArray[$newSiteAccess] ) ) 01316 { 01317 $overrideINIArray[$newSiteAccess] = eZINI::instance( 'override.ini.append.php', "settings/siteaccess/$newSiteAccess", null, null, true ); 01318 } 01319 01320 $blockArray = array(); 01321 $blockName = $blockNode->getAttribute( 'name' ); 01322 $blockArray[$blockName] = eZContentObjectPackageHandler::createArrayFromDOMNode( $blockNode->getElementsByTagName( $blockName )->item( 0 ) ); 01323 01324 if ( isset( $blockArray[$blockName][$this->OverrideObjectRemoteID] ) ) 01325 { 01326 $contentObject = eZContentObject::fetchByRemoteID( $blockArray[$blockName][$this->OverrideObjectRemoteID] ); 01327 $blockArray[$blockName]['Match']['object'] = $contentObject->attribute( 'id' ); 01328 unset( $blockArray[$blockName][$this->OverrideObjectRemoteID] ); 01329 // eZDebug::writeNotice( 'Found object id: "' . $blockArray[$blockName]['Match']['object'] . '" for matchblock "[' . $blockName . '][Match][object]"', 01330 // 'eZContentObjectPackageHandler::installOverrides()' ); 01331 } 01332 if ( isset( $blockArray[$blockName][$this->OverrideNodeRemoteID] ) ) 01333 { 01334 $contentNode = eZContentObjectTreeNode::fetchByRemoteID( $blockArray[$blockName][$this->OverrideNodeRemoteID] ); 01335 $blockArray[$blockName]['Match']['node'] = $contentNode->attribute( 'node_id' ); 01336 unset( $blockArray[$blockName][$this->OverrideNodeRemoteID] ); 01337 // eZDebug::writeNotice( 'Found node id: "' . $blockArray[$blockName]['Match']['node'] . '" for matchblock "[' . $blockName . '][Match][node]"', 01338 // 'eZContentObjectPackageHandler::installOverrides()' ); 01339 } 01340 if ( isset( $blockArray[$blockName][$this->OverrideParentNodeRemoteID] ) ) 01341 { 01342 $parentContentNode = eZContentObjectTreeNode::fetchByRemoteID( $blockArray[$blockName][$this->OverrideParentNodeRemoteID] ); 01343 $blockArray[$blockName]['Match']['parent_node'] = $parentContentNode->attribute( 'node_id' ); 01344 unset( $blockArray[$blockName][$this->OverrideParentNodeRemoteID] ); 01345 // eZDebug::writeNotice( 'Found parent node id: "' . $blockArray[$blockName]['Match']['parent_node'] . '" for matchblock "[' . $blockName . '][Match][parent_node]"', 01346 // 'eZContentObjectPackageHandler::installOverrides()' ); 01347 } 01348 if ( isset( $blockArray[$blockName][$this->OverrideClassRemoteID] ) ) 01349 { 01350 $contentClass = eZContentClass::fetchByRemoteID( $blockArray[$blockName][$this->OverrideClassRemoteID] ); 01351 if ( !$contentClass ) 01352 { 01353 eZDebug::writeError( 'No content class found for RemoteID: ' . $blockArray[$blockName][$this->OverrideClassRemoteID], 01354 'eZContentObjectPackageHandler::installOverrides()' ); 01355 continue; 01356 } 01357 $blockArray[$blockName]['Match']['class'] = $contentClass->attribute( 'id' ); 01358 unset( $blockArray[$blockName][$this->OverrideClassRemoteID] ); 01359 // eZDebug::writeNotice( 'Found class id: "' . $blockArray[$blockName]['Match']['class'] . '" for matchblock "[' . $blockName . '][Match][class]"', 01360 // 'eZContentObjectPackageHandler::installOverrides()' ); 01361 } 01362 01363 $overrideINIArray[$newSiteAccess]->setVariables( $blockArray ); 01364 } 01365 01366 foreach( $overrideINIArray as $siteAccess => $iniArray ) 01367 { 01368 $overrideINIArray[$siteAccess]->save(); 01369 } 01370 01371 return true; 01372 } 01373 01374 /*! 01375 \private 01376 01377 Install fetch alias overrides 01378 01379 \param fetch alias list 01380 \param install parameters 01381 */ 01382 function installFetchAliases( $fetchAliasListNode, &$parameters ) 01383 { 01384 if ( !$fetchAliasListNode ) 01385 { 01386 return true; 01387 } 01388 01389 $fetchAliasINIArray = array(); 01390 foreach( $fetchAliasListNode->getElementsByTagName( 'fetch-alias' ) as $blockNode ) 01391 { 01392 if ( isset( $parameters['site_access_map'][$blockNode->getAttribute( 'site-access' )] ) ) 01393 { 01394 $newSiteAccess = $parameters['site_access_map'][$blockNode->getAttribute( 'site-access' )]; 01395 } 01396 else 01397 { 01398 $newSiteAccess = $parameters['site_access_map']['*']; 01399 } 01400 01401 if ( !isset( $fetchAliasINIArray[$newSiteAccess] ) ) 01402 { 01403 $fetchAliasINIArray[$newSiteAccess] = eZINI::instance( 'fetchalias.ini.append.php', "settings/siteaccess/$newSiteAccess", null, null, true ); 01404 } 01405 01406 $blockArray = array(); 01407 $blockName = $blockNode->getAttribute( 'name' ); 01408 $blockArray[$blockName] = eZContentObjectPackageHandler::createArrayFromDOMNode( $blockNode->getElementsByTagName( $blockName )->item( 0 ) ); 01409 01410 //$blockArray[$blockName] = $blockArray[$blockName][0]; 01411 01412 if ( isset( $blockArray[$blockName]['Constant'] ) && is_array( $blockArray[$blockName]['Constant'] ) && count( $blockArray[$blockName]['Constant'] ) > 0 ) 01413 { 01414 foreach( $blockArray[$blockName]['Constant'] as $matchKey => $value ) 01415 { 01416 if ( strpos( $matchKey, 'class_' ) === 0 && 01417 is_int( $value ) ) 01418 { 01419 $contentClass = eZContentClass::fetchByRemoteID( $blockArray[$blockName]['Constant']['class_remote_id'] ); 01420 $blockArray[$blockName]['Constant'][$matchKey] = $contentClass->attribute( 'id' ); 01421 unset( $blockArray[$blockName]['Constant']['class_remote_id'] ); 01422 } 01423 if( strpos( $matchKey, 'node_' ) === 0 && 01424 is_int( $value ) ) 01425 { 01426 $contentTreeNode = eZContentObjectTreeNode::fetchByRemoteID( $blockArray[$blockName]['Constant']['node_remote_id'] ); 01427 $blockArray[$blockName]['Constant'][$matchKey] = $contentTreeNode->attribute( 'node_id' ); 01428 unset( $blockArray[$blockName]['Constant']['node_remote_id'] ); 01429 } 01430 if( strpos( $matchKey, 'parent_node_' ) === 0 && 01431 is_int( $value ) ) 01432 { 01433 $contentTreeNode = eZContentObjectTreeNode::fetchByRemoteID( $blockArray[$blockName]['Constant']['parent_node_remote_id'] ); 01434 $blockArray[$blockName]['Constant'][$matchKey] = $contentTreeNode->attribute( 'node_id' ); 01435 unset( $blockArray[$blockName]['Constant']['parent_node_remote_id'] ); 01436 } 01437 if( strpos( $matchKey, 'object_' ) === 0 && 01438 is_int( $value ) ) 01439 { 01440 $contentObject = eZContentObject::fetchByRemoteID( $blockArray[$blockName]['Constant']['object_remote_id'] ); 01441 $blockArray[$blockName]['Constant'][$matchKey] = $contentTreeNode->attribute( 'id' ); 01442 unset( $blockArray[$blockName]['Constant']['object_remote_id'] ); 01443 } 01444 } 01445 } 01446 01447 $fetchAliasINIArray[$newSiteAccess]->setVariables( $blockArray ); 01448 } 01449 01450 foreach( $fetchAliasINIArray as $siteAccess => $iniFetchAlias ) 01451 { 01452 $fetchAliasINIArray[$siteAccess]->save(); 01453 } 01454 01455 return true; 01456 } 01457 01458 /*! 01459 \reimp 01460 */ 01461 function add( $packageType, $package, $cli, $parameters ) 01462 { 01463 $options = array(); 01464 foreach ( $parameters['node-list'] as $nodeItem ) 01465 { 01466 $nodeIDList = $nodeItem['node-id-list']; 01467 foreach ( $nodeIDList as $nodeIDItem ) 01468 { 01469 $this->addNode( $nodeIDItem['id'], $nodeIDItem['subtree'] ); 01470 unset( $node ); 01471 $node = false; 01472 if ( isset( $nodeIDItem['node'] ) ) 01473 { 01474 $node = $nodeIDItem['node']; 01475 } 01476 else 01477 { 01478 $node = eZContentObjectTreeNode::fetch( $nodeIDItem['id'] ); 01479 } 01480 $cli->notice( "Adding node /" . $node->pathWithNames() . " to package" ); 01481 } 01482 } 01483 $options['include_classes'] = $parameters['include-classes']; 01484 $options['include_templates'] = $parameters['include-templates']; 01485 $options['node_assignment'] = $parameters['node-assignment-type']; 01486 $options['site_access_array'] = $parameters['siteaccess-list']; 01487 $options['language_array'] = $parameters['language-list']; 01488 $options['versions'] = $parameters['version-type']; 01489 $options['related_objects'] = $parameters['related-type']; 01490 $options['embed_objects'] = $parameters['embed-type']; 01491 $options['minimal_template_set'] = $parameters['minimal-template-set']; 01492 $this->generatePackage( $package, $options ); 01493 } 01494 01495 /*! 01496 \reimp 01497 */ 01498 function handleAddParameters( $packageType, $package, $cli, $arguments ) 01499 { 01500 return $this->handleParameters( $packageType, $package, $cli, 'add', $arguments ); 01501 } 01502 01503 /*! 01504 \private 01505 */ 01506 function handleParameters( $packageType, $package, $cli, $type, $arguments ) 01507 { 01508 $nodeList = array(); 01509 $includeClasses = true; 01510 $includeTemplates = true; 01511 $siteAccessList = array(); 01512 $nodeAssignmentType = 'main'; 01513 $relatedObjectType = 'selected'; 01514 $embedObjectType = 'selected'; 01515 $versionType = 'current'; 01516 $languageList = array(); 01517 $minimalTemplateSet = false; 01518 $nodeItem = array( 'node-id-list' => array() ); 01519 $longOptions = array( 'include-classes' => 'include-classes', 01520 'include-templates' => 'include-templates', 01521 'exclude-classes' => 'exclude-classes', 01522 'exclude-templates' => 'exclude-templates', 01523 'language' => 'language', 01524 'current-version' => 'current-version', 01525 'all-versions' => 'all-versions', 01526 'node-main' => 'node-main', 01527 'node-selected' => 'node-selected', 01528 'siteaccess' => 'siteaccess', 01529 'minimal-template-set' => 'minimal-template-set' ); 01530 $shortOptions = array(); 01531 $error = false; 01532 foreach ( $arguments as $argument ) 01533 { 01534 if ( $argument[0] == '-' ) 01535 { 01536 if ( strlen( $argument ) > 1 and 01537 $argument[1] == '-' ) 01538 { 01539 $option = substr( $argument, 2 ); 01540 $valuePos = strpos( $option, '=' ); 01541 $optionValue = false; 01542 if ( $valuePos !== false ) 01543 { 01544 $optionValue = substr( $option, $valuePos + 1 ); 01545 $option = substr( $option, 0, $valuePos ); 01546 } 01547 if ( isset( $longOptions[$option] ) ) 01548 $optionName = $longOptions[$option]; 01549 else 01550 $optionName = false; 01551 } 01552 else 01553 { 01554 $option = substr( $argument, 1 ); 01555 if ( isset( $shortOptions[$option] ) ) 01556 $optionName = $shortOptions[$option]; 01557 else 01558 $optionName = false; 01559 } 01560 if ( $optionName == 'include-classes' or $optionName == 'exclude-classes' ) 01561 { 01562 if ( count( $nodeItem['node-id-list'] ) > 0 ) 01563 { 01564 $nodeList[] = $nodeItem; 01565 $nodeItem['node-id-list'] = array(); 01566 } 01567 $includeClasses = ( $optionName == 'include-classes' ); 01568 } 01569 else if ( $optionName == 'include-templates' or $optionName == 'exclude-templates' ) 01570 { 01571 if ( count( $nodeItem['node-id-list'] ) > 0 ) 01572 { 01573 $nodeList[] = $nodeItem; 01574 $nodeItem['node-id-list'] = array(); 01575 } 01576 $includeTemplates = ( $optionName == 'include-templates' ); 01577 } 01578 else if ( $optionName == 'node-main' ) 01579 { 01580 $nodeAssignmentType = 'main'; 01581 } 01582 else if ( $optionName == 'node-selected' ) 01583 { 01584 $nodeAssignmentType = 'selected'; 01585 } 01586 else if ( $optionName == 'siteaccess' ) 01587 { 01588 $siteAccessList = explode( ',', $optionValue ); 01589 } 01590 else if ( $optionName == 'language' ) 01591 { 01592 $languageList = explode( ',', $optionValue ); 01593 } 01594 else if ( $optionName == 'current-version' ) 01595 { 01596 $versionType = 'current'; 01597 } 01598 else if ( $optionName == 'all-versions' ) 01599 { 01600 $versionType = 'all'; 01601 } 01602 else if ( $optionName == 'minimal-template-set' ) 01603 { 01604 $minimalTemplateSet = true; 01605 } 01606 } 01607 else 01608 { 01609 $nodeID = false; 01610 $subtree = false; 01611 if ( is_numeric( $argument ) ) 01612 { 01613 $nodeID = (int)$argument; 01614 $node = eZContentObjectTreeNode::fetch( $nodeID ); 01615 if ( !is_object( $node ) ) 01616 { 01617 $error = true; 01618 $nodeID = false; 01619 $cli->notice( "Could not find content-node using ID " . $cli->stylize( 'emphasize', $nodeID ) ); 01620 } 01621 } 01622 else 01623 { 01624 $path = $argument; 01625 if ( preg_match( "#(.+)/\*$#", $path, $matches ) ) 01626 { 01627 $path = $matches[1]; 01628 $subtree = true; 01629 } 01630 $node = eZContentObjectTreeNode::fetchByURLPath( $path ); 01631 if ( is_object( $node ) ) 01632 { 01633 $nodeID = $node->attribute( 'node_id' ); 01634 } 01635 else 01636 { 01637 $cli->notice( "Could not find content-node using path " . $cli->stylize( 'emphasize', $path ) ); 01638 $error = true; 01639 } 01640 } 01641 if ( $nodeID ) 01642 { 01643 $nodeItem['node-id-list'][] = array( 'id' => $nodeID, 01644 'subtree' => $subtree, 01645 'node' => &$node ); 01646 } 01647 if ( $error ) 01648 return false; 01649 } 01650 } 01651 if ( count( $nodeItem['node-id-list'] ) > 0 ) 01652 { 01653 $nodeList[] = $nodeItem; 01654 } 01655 if ( count( $nodeList ) == 0 ) 01656 { 01657 $cli->error( "No objects chosen" ); 01658 return false; 01659 } 01660 if ( count( $languageList ) == 0 ) 01661 { 01662 // The default is to fetch all languages 01663 //include_once( 'kernel/classes/ezcontentlanguage.php' ); 01664 $languageList = eZContentLanguage::fetchLocaleList(); 01665 } 01666 if ( count( $siteAccessList ) == 0 ) 01667 { 01668 $ini = eZINI::instance(); 01669 $siteAccessList[] = $ini->variable( 'SiteSettings', 'DefaultAccess' ); 01670 } 01671 return array( 'node-list' => $nodeList, 01672 'include-classes' => $includeClasses, 01673 'include-templates' => $includeTemplates, 01674 'siteaccess-list' => $siteAccessList, 01675 'language-list' => $languageList, 01676 'node-assignment-type' => $nodeAssignmentType, 01677 'related-type' => $relatedObjectType, 01678 'embed-type' => $embedObjectType, 01679 'version-type' => $versionType, 01680 'minimal-template-set' => $minimalTemplateSet, 01681 ); 01682 } 01683 01684 function contentObjectDirectory() 01685 { 01686 return 'ezcontentobject'; 01687 } 01688 01689 /*! 01690 \static 01691 Creates DOMNodeElement recursivly from recursive array 01692 */ 01693 static function createElementNodeFromArray( $name, $array ) 01694 { 01695 $dom = new DOMDocument( '1.0', 'utf-8' ); 01696 $node = $dom->createElement( $name ); 01697 $dom->appendChild( $node ); 01698 01699 foreach ( $array as $arrayKey => $value ) 01700 { 01701 if ( is_array( $value ) and 01702 count( $valueKeys = array_keys( $value ) ) > 0 ) 01703 { 01704 if ( is_int( $valueKeys[0] ) ) 01705 { 01706 foreach( $value as $child ) 01707 { 01708 unset( $childNode ); 01709 unset( $importedChildNode ); 01710 $childNode = eZContentObjectPackageHandler::createElementNodeFromArray( $arrayKey, $child ); 01711 $importedChildNode = $dom->importNode( $childNode, true ); 01712 $node->appendChild( $importedChildNode ); 01713 } 01714 } 01715 else 01716 { 01717 unset( $valueNode ); 01718 unset( $importedValueNode ); 01719 $valueNode = eZContentObjectPackageHandler::createElementNodeFromArray( $arrayKey, $value ); 01720 $importedValueNode = $dom->importNode( $valueNode, true ); 01721 $node->appendChild( $importedValueNode ); 01722 } 01723 } 01724 else 01725 { 01726 $node->setAttribute( $arrayKey, $value ); 01727 } 01728 } 01729 return $node; 01730 } 01731 01732 /*! 01733 \static 01734 Creates recursive array from DOMNodeElement 01735 */ 01736 static function createArrayFromDOMNode( $domNode ) 01737 { 01738 if ( !$domNode ) 01739 { 01740 return null; 01741 } 01742 01743 $retArray = array(); 01744 foreach ( $domNode->childNodes as $childNode ) 01745 { 01746 if ( $childNode->nodeType != XML_ELEMENT_NODE ) 01747 { 01748 continue; 01749 } 01750 01751 if ( !isset( $retArray[$childNode->localName] ) ) 01752 { 01753 $retArray[$childNode->localName] = array(); 01754 } 01755 01756 // If the node has children we create an array for this element 01757 // and append to it, if not we assign it directly 01758 if ( $childNode->hasChildNodes() ) 01759 { 01760 $retArray[$childNode->localName][] = eZContentObjectPackageHandler::createArrayFromDOMNode( $childNode ); 01761 } 01762 else 01763 { 01764 $retArray[$childNode->localName] = eZContentObjectPackageHandler::createArrayFromDOMNode( $childNode ); 01765 } 01766 } 01767 foreach( $domNode->attributes as $attributeNode ) 01768 { 01769 $retArray[$attributeNode->name] = $attributeNode->value; 01770 } 01771 01772 return $retArray; 01773 } 01774 01775 public $NodeIDArray = array(); 01776 public $RootNodeIDArray = array(); 01777 public $NodeObjectArray = array(); 01778 public $ObjectArray = array(); 01779 public $RootNodeObjectArray = array(); 01780 public $OverrideSettingsArray = array(); 01781 public $TemplateFileArray = array(); 01782 public $Package = null; 01783 01784 // Static class variables - replacing match values in override.ini 01785 public $OverrideObjectRemoteID = 'content_object_remote_id'; 01786 public $OverrideNodeRemoteID = 'content_node_remote_id'; 01787 public $OverrideParentNodeRemoteID = 'parent_content_node_remote_id'; 01788 public $OverrideClassRemoteID = 'content_class_remote_id'; 01789 } 01790 01791 ?>