|
eZ Publish
[trunk]
|
00001 <?php 00002 /** 00003 * File containing the eZPackage class. 00004 * 00005 * @copyright Copyright (C) 1999-2012 eZ Systems AS. All rights reserved. 00006 * @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License v2 00007 * @version //autogentag// 00008 * @package kernel 00009 */ 00010 00011 /*! 00012 \defgroup package The package manager system 00013 \ingroup package 00014 \class eZPackage ezpackagehandler.php 00015 \brief Maintains eZ Publish packages 00016 00017 */ 00018 00019 class eZPackage 00020 { 00021 const VERSION = '3.5.2'; 00022 const DEVELOPMENT = false; 00023 const USE_CACHE = true; 00024 const CACHE_CODE_DATE = 1069339607; 00025 00026 const STATUS_ALREADY_EXISTS = 1; 00027 const STATUS_INVALID_NAME = 2; 00028 00029 const NON_INTERACTIVE = -1; 00030 00031 /*! 00032 Constructor 00033 */ 00034 function eZPackage( $parameters = array(), $repositoryPath = false ) 00035 { 00036 $this->setParameters( $parameters ); 00037 if ( !$repositoryPath ) 00038 $repositoryPath = eZPackage::repositoryPath(); 00039 $this->RepositoryPath = $repositoryPath; 00040 $this->RepositoryInformation = null; 00041 } 00042 00043 /** 00044 * Removes the package directory and all it's subfiles/directories. 00045 */ 00046 function remove() 00047 { 00048 $path = $this->path(); 00049 if ( file_exists( $path ) ) 00050 { 00051 eZDir::recursiveDelete( $path ); 00052 } 00053 $this->setInstalled( false ); 00054 } 00055 00056 /*! 00057 \private 00058 */ 00059 function setParameters( $parameters = array() ) 00060 { 00061 $timestamp = time(); 00062 if ( isset( $_SERVER['HOSTNAME'] ) ) 00063 $host = $_SERVER['HOSTNAME']; 00064 else if ( isset( $_SERVER['HTTP_HOST'] ) ) 00065 $host = $_SERVER['HTTP_HOST']; 00066 else 00067 $host = 'localhost'; 00068 $packaging = array( 'timestamp' => $timestamp, 00069 'host' => $host, 00070 'packager' => false ); 00071 $ezpublishVersion = eZPublishSDK::version( true ); 00072 $ezpublishNamedVersion = eZPublishSDK::version( false, false, true ); 00073 $ezpublish = array( 'version' => $ezpublishVersion, 00074 'named-version' => $ezpublishNamedVersion ); 00075 $defaults = array( 'name' => false, 00076 'development' => eZPackage::DEVELOPMENT, 00077 'summary' => false, 00078 'description' => false, 00079 'vendor' => false, 00080 'vendor-dir' => false, 00081 'priority' => false, 00082 'type' => false, 00083 'extension' => false, 00084 'install_type' => 'install', 00085 'ezpublish' => $ezpublish, 00086 'maintainers' => array(), 00087 'packaging' => $packaging, 00088 'source' => false, 00089 'documents' => array(), 00090 'groups' => array(), 00091 'changelog' => array(), 00092 'file-list' => array(), 00093 'simple-file-list' => array(), 00094 'version-number' => false, 00095 'release-number' => false, 00096 'release-timestamp' => false, 00097 'licence' => false, 00098 'state' => false, 00099 'dependencies' => array( 'provides' => array(), 00100 'requires' => array(), 00101 'obsoletes' => array(), 00102 'conflicts' => array() ), 00103 'install' => array(), 00104 'uninstall' => array() ); 00105 $this->PolicyCache = array(); 00106 $this->InstallData = array(); 00107 $this->Parameters = array_merge( $defaults, $parameters ); 00108 } 00109 00110 /*! 00111 \static 00112 \return An associative array with the possible types for a package. 00113 Each entry contains an \c id and a \c name key. 00114 */ 00115 static function typeList() 00116 { 00117 $typeList =& $GLOBALS['eZPackageTypeList']; 00118 if ( !isset( $typeList ) ) 00119 { 00120 $typeList = array(); 00121 $ini = eZINI::instance( 'package.ini' ); 00122 $types = $ini->variable( 'PackageSettings', 'TypeList' ); 00123 foreach ( $types as $typeID => $typeName ) 00124 { 00125 $typeList[] = array( 'name' => $typeName, 00126 'id' => $typeID ); 00127 } 00128 } 00129 return $typeList; 00130 } 00131 00132 /*! 00133 \static 00134 \return An associative array with the possible states for a package. 00135 Each entry contains an \c id and a \c name key. 00136 */ 00137 static function stateList() 00138 { 00139 $stateList =& $GLOBALS['eZPackageStateList']; 00140 if ( !isset( $stateList ) ) 00141 { 00142 $stateList = array(); 00143 $ini = eZINI::instance( 'package.ini' ); 00144 $states = $ini->variable( 'PackageSettings', 'StateList' ); 00145 foreach ( $states as $stateID => $stateName ) 00146 { 00147 $stateList[] = array( 'name' => $stateName, 00148 'id' => $stateID); 00149 } 00150 } 00151 return $stateList; 00152 } 00153 00154 /*! 00155 \param $repositoryID The id (string) of the repository to create the package in. 00156 If \c false it will use the \c local repository. 00157 */ 00158 static function create( $name, $parameters = array(), $repositoryPath = false, $repositoryID = false ) 00159 { 00160 $parameters['name'] = $name; 00161 $handler = new eZPackage( $parameters, $repositoryPath ); 00162 00163 // New packages always use local repository 00164 if ( $repositoryID === false ) 00165 $repositoryID = 'local'; 00166 $repositoryInformation = $handler->repositoryInformation( $repositoryID ); 00167 if ( $repositoryPath !== false ) 00168 $repositoryInformation['path'] = $repositoryPath; 00169 $handler->setCurrentRepositoryInformation( $repositoryInformation ); 00170 return $handler; 00171 } 00172 00173 /*! 00174 \return the attributes for this package. 00175 */ 00176 function attributes() 00177 { 00178 return array( 'is_local', 00179 'development', 00180 'name', 'summary', 'description', 00181 'vendor', 'vendor-dir', 'priority', 'type', 00182 'extension', 'source', 00183 'version-number', 'release-number', 'release-timestamp', 00184 'maintainers', 'documents', 'groups', 00185 'simple-file-list', 'file-list', 'file-count', 00186 'can_read', 'can_export', 'can_import', 'can_install', 00187 'changelog', 'dependencies', 00188 'is_installed', 00189 'install_type', 00190 'thumbnail-list', 00191 'install', 'uninstall', 00192 'licence', 'state', 00193 'ezpublish-version', 'ezpublish-named-version', 'packaging-timestamp', 00194 'packaging-host', 'packaging-packager' ); 00195 } 00196 00197 /*! 00198 Sets the attribute named \a $attributeName to have the value \a $attributeValue. 00199 */ 00200 function setAttribute( $attributeName, $attributeValue ) 00201 { 00202 if ( !in_array( $attributeName, 00203 array( 'development', 00204 'name', 'summary', 'description', 00205 'vendor', 'vendor-dir', 'priority', 'type', 00206 'install_type', 00207 'extension', 'source', 00208 'licence', 'state' ) ) ) 00209 return false; 00210 if ( array_key_exists( $attributeName, $this->Parameters ) and 00211 !is_array( $this->Parameters[$attributeName] )) 00212 { 00213 $this->Parameters[$attributeName] = $attributeValue; 00214 return true; 00215 } 00216 return false; 00217 } 00218 00219 /*! 00220 \return \c true if the attribute named \a $attributeName exists. 00221 */ 00222 function hasAttribute( $attributeName /*, $attributeList = false*/ ) 00223 { 00224 return in_array( $attributeName, $this->attributes() ); 00225 } 00226 00227 /*! 00228 \return the value of the attribute named \a $attributeName. 00229 */ 00230 function attribute( $attributeName /*, $attributeList = false*/ ) 00231 { 00232 if ( in_array( $attributeName, 00233 array( 'development', 00234 'name', 'summary', 'description', 00235 'vendor', 'vendor-dir', 'priority', 'type', 00236 'extension', 'source', 00237 'version-number', 'release-number', 'release-timestamp', 00238 'maintainers', 'documents', 'groups', 00239 'simple-file-list', 'file-list', 00240 'changelog', 'dependencies', 00241 'install', 'uninstall', 00242 'install_type', 00243 'licence', 'state', 'settings-files' ) ) ) 00244 return $this->Parameters[$attributeName]; 00245 else if ( $attributeName == 'is_installed' ) 00246 return $this->isInstalled; 00247 else if ( $attributeName == 'ezpublish-version' ) 00248 return $this->Parameters['ezpublish']['version']; 00249 else if ( $attributeName == 'ezpublish-named-version' ) 00250 return $this->Parameters['ezpublish']['named-version']; 00251 else if ( $attributeName == 'packaging-timestamp' ) 00252 return $this->Parameters['packaging']['timestamp']; 00253 else if ( $attributeName == 'packaging-host' ) 00254 return $this->Parameters['packaging']['host']; 00255 else if ( $attributeName == 'packaging-packager' ) 00256 return $this->Parameters['packaging']['packager']; 00257 else if ( $attributeName == 'can_read' ) 00258 { 00259 return $this->canRead(); 00260 } 00261 else if ( $attributeName == 'can_export' ) 00262 { 00263 return $this->canExport(); 00264 } 00265 else if ( $attributeName == 'can_import' ) 00266 { 00267 return $this->canImport(); 00268 } 00269 else if ( $attributeName == 'can_install' ) 00270 { 00271 return $this->canInstall(); 00272 } 00273 else if ( $attributeName == 'file-count' ) 00274 { 00275 return $this->fileCount(); 00276 } 00277 else if ( $attributeName == 'thumbnail-list' ) 00278 { 00279 return $this->thumbnailList( 'default' ); 00280 } 00281 else if ( $attributeName == 'is_local' ) 00282 { 00283 $repositoryInformation = $this->currentRepositoryInformation(); 00284 return ( $repositoryInformation['type'] == 'local' ); 00285 } 00286 00287 eZDebug::writeError( "No such attribute: $attributeName for eZPackage", __METHOD__ ); 00288 return null; 00289 } 00290 00291 static function canUsePolicyFunction( $functionName ) 00292 { 00293 $currentUser = eZUser::currentUser(); 00294 $accessResult = $currentUser->hasAccessTo( 'package', $functionName ); 00295 if ( in_array( $accessResult['accessWord'], array( 'yes', 'limited' ) ) ) 00296 { 00297 return true; 00298 } 00299 return false; 00300 } 00301 00302 function canRead() 00303 { 00304 return $this->canUsePackagePolicyFunction( 'read' ); 00305 } 00306 00307 function canExport() 00308 { 00309 return $this->canUsePackagePolicyFunction( 'export' ); 00310 } 00311 00312 function canImport() 00313 { 00314 return $this->canUsePackagePolicyFunction( 'import' ); 00315 } 00316 00317 function canInstall() 00318 { 00319 return $this->canUsePackagePolicyFunction( 'install' ); 00320 } 00321 00322 function canUsePackagePolicyFunction( $functionName ) 00323 { 00324 if ( !isset( $this->PolicyCache[$functionName] ) ) 00325 { 00326 $currentUser = eZUser::currentUser(); 00327 $accessResult = $currentUser->hasAccessTo( 'package', $functionName ); 00328 $limitationList = array(); 00329 $canUse = false; 00330 if ( $accessResult['accessWord'] == 'yes' ) 00331 { 00332 $this->PolicyCache[$functionName] = true; 00333 } 00334 else if ( $accessResult['accessWord'] == 'limited' ) 00335 { 00336 $allRoles = array(); 00337 $limitationList = $accessResult['policies']; 00338 $typeList = false; 00339 foreach( $limitationList as $limitationArray ) 00340 { 00341 foreach ( $limitationArray as $key => $limitation ) 00342 { 00343 if ( $key == 'Type' ) 00344 { 00345 if ( !is_array( $typeList ) ) 00346 $typeList = array(); 00347 $typeList = array_merge( $typeList, $limitation ); 00348 } 00349 } 00350 } 00351 if ( $typeList === false ) 00352 { 00353 $this->PolicyCache[$functionName] = true; 00354 } 00355 else 00356 { 00357 $this->PolicyCache[$functionName] = in_array( $this->attribute( 'type' ), $typeList ); 00358 } 00359 } 00360 } 00361 return $this->PolicyCache[$functionName]; 00362 } 00363 00364 static function fetchMaintainerRoleIDList( $packageType = false, $checkRoles = false ) 00365 { 00366 $allRoles = false; 00367 if ( $checkRoles ) 00368 { 00369 $currentUser = eZUser::currentUser(); 00370 $accessResult = $currentUser->hasAccessTo( 'package', 'create' ); 00371 $limitationList = array(); 00372 if ( $accessResult['accessWord'] == 'limited' ) 00373 { 00374 $allRoles = array(); 00375 $limitationList = $accessResult['policies']; 00376 foreach( $limitationList as $limitationArray ) 00377 { 00378 $allowedType = true; 00379 $allowedRoles = false; 00380 foreach ( $limitationArray as $key => $limitation ) 00381 { 00382 if ( $key == 'Role' ) 00383 { 00384 $allowedRoles = $limitation; 00385 } 00386 else if ( $key == 'Type' ) 00387 { 00388 $typeList = $limitation; 00389 if ( $packageType === false ) 00390 { 00391 $allowedType = in_array( $packageType, $typeList ); 00392 } 00393 } 00394 } 00395 if ( $allowedType and 00396 count( $allowedRoles ) > 0 ) 00397 { 00398 $allRoles = array_merge( $allRoles, $allowedRoles ); 00399 } 00400 } 00401 } 00402 } 00403 if ( is_array( $allRoles ) and count( $allRoles ) == 0 ) 00404 return array(); 00405 $ini = eZINI::instance( 'package.ini' ); 00406 $roleList = $ini->variable( 'MaintainerSettings', 'RoleList' ); 00407 if ( $allRoles !== false ) 00408 { 00409 $roleList = array_intersect( $roleList, $allRoles ); 00410 } 00411 return $roleList; 00412 } 00413 00414 static function fetchMaintainerRoleList( $packageType = false, $checkRoles = false ) 00415 { 00416 $roleList = eZPackage::fetchMaintainerRoleIDList( $packageType, $checkRoles ); 00417 $roleNameList = array(); 00418 foreach ( $roleList as $roleID ) 00419 { 00420 $roleName = eZPackage::maintainerRoleName( $roleID ); 00421 $roleNameList[] = array( 'name' => $roleName, 00422 'id' => $roleID ); 00423 } 00424 return $roleNameList; 00425 } 00426 00427 static function maintainerRoleListForRoles() 00428 { 00429 $ini = eZINI::instance( 'package.ini' ); 00430 $roleList = $ini->variable( 'MaintainerSettings', 'RoleList' ); 00431 $roleNameList = array(); 00432 foreach ( $roleList as $roleID ) 00433 { 00434 $roleName = eZPackage::maintainerRoleName( $roleID ); 00435 $roleNameList[] = array( 'name' => $roleName, 00436 'id' => $roleID ); 00437 } 00438 return $roleNameList; 00439 } 00440 00441 static function maintainerRoleName( $roleID ) 00442 { 00443 $nameMap = array( 'lead' => ezpI18n::tr( 'kernel/package', 'Lead' ), 00444 'developer' => ezpI18n::tr( 'kernel/package', 'Developer' ), 00445 'designer' => ezpI18n::tr( 'kernel/package', 'Designer' ), 00446 'contributor' => ezpI18n::tr( 'kernel/package', 'Contributor' ), 00447 'tester' => ezpI18n::tr( 'kernel/package', 'Tester' ) ); 00448 if ( isset( $nameMap[$roleID] ) ) 00449 return $nameMap[$roleID]; 00450 return false; 00451 } 00452 00453 function appendMaintainer( $name, $email, $role = false ) 00454 { 00455 $this->Parameters['maintainers'][] = array( 'name' => $name, 00456 'email' => $email, 00457 'role' => $role ); 00458 } 00459 00460 function appendDocument( $name, $mimeType = false, $os = false, $audience = false, 00461 $create = false, $data = false ) 00462 { 00463 if ( !$mimeType ) 00464 $mimeType = 'text/plain'; 00465 $this->Parameters['documents'][] = array( 'name' => $name, 00466 'mime-type' => $mimeType, 00467 'os' => $os, 00468 // 'create-document' => $create, 00469 'data' => $data, 00470 'audience' => $audience ); 00471 if ( $create ) 00472 { 00473 eZFile::create( $name, $this->path() . '/' . eZPackage::documentDirectory(), 00474 $data ); 00475 } 00476 } 00477 00478 function appendGroup( $name ) 00479 { 00480 $index = count( $this->Parameters['groups'] ); 00481 $this->Parameters['groups'][$index] = array( 'name' => $name ); 00482 } 00483 00484 function appendChange( $person, $email, $changes, 00485 $release = false, $timestamp = null ) 00486 { 00487 if ( $timestamp === null ) 00488 $timestamp = time(); 00489 if ( !is_array( $changes ) ) 00490 $changes = array( $changes ); 00491 if ( !$release ) 00492 $release = $this->Parameters['release-number']; 00493 if ( !$release ) 00494 $release = 1; 00495 $this->Parameters['changelog'][] = array( 'timestamp' => $timestamp, 00496 'person' => $person, 00497 'email' => $email, 00498 'changes' => $changes, 00499 'release' => $release ); 00500 } 00501 00502 static function md5sum( $file ) 00503 { 00504 if ( function_exists( 'md5_file' ) ) 00505 { 00506 if ( is_file( $file ) ) 00507 { 00508 return md5_file( $file ); 00509 } 00510 else 00511 { 00512 eZDebug::writeError( "Could not open file $file for md5sum calculation" ); 00513 } 00514 } 00515 else 00516 { 00517 $fd = @fopen( $file, 'rb' ); 00518 if ( $fd ) 00519 { 00520 $data = ''; 00521 while ( !@feof( $fd ) ) 00522 { 00523 $data .= @fread( $fd, 4096 ); 00524 } 00525 @fclose( $fd ); 00526 return md5( $data ); 00527 } 00528 } 00529 return false; 00530 } 00531 00532 function fileStorePath( $fileItem, $collectionName, $path = false, $installVariables = array() ) 00533 { 00534 $type = $fileItem['type']; 00535 $variableName = $fileItem['variable-name']; 00536 if ( $type == 'file' ) 00537 { 00538 $pathArray = array( $path, $fileItem['subdirectory'] ); 00539 $pathArray[] = $fileItem['name']; 00540 $path = eZDir::path( $pathArray ); 00541 } 00542 else if ( $type == 'design' ) 00543 { 00544 $roleFileName = false; 00545 $design = $fileItem['design']; 00546 switch ( $fileItem['role'] ) 00547 { 00548 case 'template': 00549 { 00550 $roleFileName = 'templates'; 00551 } break; 00552 case 'image': 00553 { 00554 $roleFileName = 'images'; 00555 } break; 00556 case 'stylesheet': 00557 { 00558 $roleFileName = 'stylesheets'; 00559 } break; 00560 case 'font': 00561 { 00562 $roleFileName = 'fonts'; 00563 } break; 00564 } 00565 if ( $variableName and 00566 isset( $installVariables[$variableName] ) ) 00567 $design = $installVariables[$variableName]; 00568 $pathArray = array( $path, 'design', $design, $roleFileName, $fileItem['subdirectory'] ); 00569 if ( $fileItem['file-type'] != 'dir' ) 00570 $pathArray[] = $fileItem['name']; 00571 $path = eZDir::path( $pathArray ); 00572 } 00573 else if ( $type == 'ini' ) 00574 { 00575 $roleValue = false; 00576 $roleFileName = false; 00577 switch ( $fileItem['role'] ) 00578 { 00579 case 'override': 00580 { 00581 $roleFileName = 'override'; 00582 } break; 00583 case 'siteaccess': 00584 { 00585 $roleFileName = 'siteaccess'; 00586 $roleValue = $fileItem['role-value']; 00587 if ( $variableName and 00588 isset( $installVariables[$variableName] ) ) 00589 $roleValue = $installVariables[$variableName]; 00590 } break; 00591 case 'standard': 00592 default: 00593 { 00594 $roleFileName = ''; 00595 } break; 00596 } 00597 $pathArray = array( $path, 'settings', $roleFileName, $roleValue, $fileItem['subdirectory'] ); 00598 if ( $fileItem['file-type'] != 'dir' ) 00599 $pathArray[] = $fileItem['name']; 00600 $path = eZDir::path( $pathArray ); 00601 } 00602 return $path; 00603 } 00604 00605 function fileItemPath( $fileItem, $collectionName, $path = false ) 00606 { 00607 if ( !$path ) 00608 { 00609 $repositoryInformation = $this->currentRepositoryInformation(); 00610 $path = $repositoryInformation['path']; 00611 } 00612 $typeDir = $fileItem['type']; 00613 if ( $fileItem['type'] == 'design' ) 00614 $typeDir .= '.' . $fileItem['design']; 00615 if ( isset( $fileItem['role'] ) && $fileItem['role'] ) 00616 { 00617 $typeDir .= '.' . $fileItem['role']; 00618 if ( $fileItem['role-value'] ) 00619 $typeDir .= '-' . $fileItem['role-value']; 00620 } 00621 $path .= '/' . $this->attribute( 'name' ) . '/' . eZPackage::filesDirectory() . '/' . $collectionName . '/' . $typeDir; 00622 if ( isset( $fileItem['subdirectory'] ) && $fileItem['subdirectory'] ) 00623 $path .= '/' . $fileItem['subdirectory']; 00624 $path .= '/' . $fileItem['name']; 00625 return $path; 00626 } 00627 00628 function fileList( $collectionName ) 00629 { 00630 $fileCollections = $this->Parameters['file-list']; 00631 if ( isset( $fileCollections[$collectionName] ) ) 00632 return $fileCollections[$collectionName]; 00633 return false; 00634 } 00635 00636 function thumbnailList( $collectionName ) 00637 { 00638 $thumbnails = array(); 00639 $fileList = $this->fileList( $collectionName ); 00640 if ( !is_array( $fileList ) ) 00641 return $thumbnails; 00642 00643 foreach ( $fileList as $fileItem ) 00644 { 00645 if ( $fileItem['type'] == 'thumbnail' ) 00646 { 00647 $thumbnails[] = $fileItem; 00648 } 00649 } 00650 return $thumbnails; 00651 } 00652 00653 function fileCount() 00654 { 00655 $count = 0; 00656 foreach ( $this->Parameters['file-list'] as $collection ) 00657 { 00658 $count += count( $collection ); 00659 } 00660 return $count; 00661 } 00662 00663 function appendFile( $file, $type, $role, 00664 $design, $filePath, $collection, 00665 $subDirectory = null, $md5 = null, 00666 $copyFile = false, $modified = null, $fileType = false, 00667 $roleValue = false, $variableName = false, 00668 $packagePath = false ) 00669 { 00670 if ( !$collection ) 00671 $collection = 'default'; 00672 if ( $subDirectory === null ) 00673 { 00674 $subDirectory = false; 00675 if ( preg_match( '#^(.+)/([^/]+)$#', $file, $matches ) ) 00676 { 00677 $subDirectory = $matches[1]; 00678 $file = $matches[2]; 00679 } 00680 } 00681 if ( $packagePath ) 00682 $subDirectory = $packagePath; 00683 00684 $fileItem = array( 'name' => $file, 00685 'subdirectory' => $subDirectory, 00686 'type' => $type, 00687 'role' => $role, 00688 'role-value' => $roleValue, 00689 'variable-name' => $variableName, 00690 'path' => $filePath, 00691 'file-type' => $fileType, 00692 'design' => $design ); 00693 if ( $md5 === null ) 00694 { 00695 $md5 = $this->md5sum( $filePath ); 00696 } 00697 $fileItem['md5'] = $md5; 00698 $this->Parameters['file-list'][$collection][] = $fileItem; 00699 00700 if ( $copyFile ) 00701 { 00702 // copying file 00703 $typeDir = $type; 00704 if ( $type == 'design' ) 00705 $typeDir .= '.' . $fileItem['design']; 00706 if ( $role ) 00707 { 00708 $typeDir .= '.' . $role; 00709 if ( $roleValue ) 00710 $typeDir .= '-' . $roleValue; 00711 } 00712 $path = $this->path() . '/' . eZPackage::filesDirectory() . '/' . $collection . '/' . $typeDir; 00713 if ( $subDirectory ) 00714 $path .= '/' . $subDirectory; 00715 if ( !file_exists( $path ) ) 00716 eZDir::mkdir( $path, false, true ); 00717 00718 if ( is_dir( $fileItem['path'] ) ) 00719 { 00720 eZDir::copy( $fileItem['path'], $path, 00721 $fileItem['name'] != false, true, false, eZDir::temporaryFileRegexp() ); 00722 } 00723 else 00724 { 00725 eZFileHandler::copy( $fileItem['path'], $path . '/' . $fileItem['name'] ); 00726 } 00727 } 00728 } 00729 00730 /*! 00731 Appends a new \c provides dependency. 00732 \note This function is only a convenience function to the general appendDependency() function. 00733 */ 00734 function appendProvides( $type, $name, $value, $parameters = false ) 00735 { 00736 $dependencyParameters = array( 'type' => $type, 00737 'name' => $name, 00738 'value' => $value ); 00739 00740 if ( $parameters !== false ) 00741 $dependencyParameters = array_merge( $dependencyParameters, $parameters ); 00742 00743 $this->appendDependency( 'provides', $dependencyParameters ); 00744 } 00745 00746 /*! 00747 Appends a new dependency item to the section \a $dependencySection. 00748 \param $dependencySection Can be one of \c provides, \c requires, \c obsoletes, \c conflicts 00749 \param $parameters A list of data specific to the dependency type. 00750 */ 00751 function appendDependency( $dependencySection, $parameters ) 00752 { 00753 if ( !in_array( $dependencySection, 00754 array( 'provides', 'requires', 00755 'obsoletes', 'conflicts' ) ) ) 00756 return false; 00757 00758 $this->Parameters['dependencies'][$dependencySection][] = $parameters; 00759 } 00760 00761 function dependencyOperatorText( $dependencyItem ) 00762 { 00763 return '='; 00764 } 00765 00766 function createDependencyText( $cli, $dependencyItem, $dependencySection ) 00767 { 00768 $text = ( $cli->stylize( 'emphasize', $dependencyItem['type'] ) . 00769 '(' . 00770 $cli->stylize( 'emphasize', $dependencyItem['name'] ) . 00771 ')' ); 00772 if ( $dependencyItem['value'] ) 00773 $text .= ' ' . $this->dependencyOperatorText( $dependencyItem ) .' ' . $cli->stylize( 'symbol', $dependencyItem['value'] ); 00774 $handler = $this->packageHandler( $dependencyItem['type'] ); 00775 if ( $handler ) 00776 { 00777 $specialText = $handler->createDependencyText( $this, $dependencyItem, $dependencySection ); 00778 if ( $specialText ) 00779 $text .= ' ( ' . $specialText . ' ) '; 00780 } 00781 return $text; 00782 } 00783 00784 function groupDependencyItemsByType( $dependencyItems ) 00785 { 00786 $types = array(); 00787 foreach ( $dependencyItems as $dependencyItem ) 00788 { 00789 if ( !isset( $types[$dependencyItem['type']] ) ) 00790 $types[$dependencyItem['type']] = array(); 00791 $types[$dependencyItem['type']][] = $dependencyItem; 00792 } 00793 return $types; 00794 } 00795 00796 /*! 00797 \return an array with dependency items which match the specified criterias. 00798 */ 00799 function dependencyItems( $dependencySection, $parameters = false ) 00800 { 00801 if ( !in_array( $dependencySection, 00802 array( 'provides', 'requires', 00803 'obsoletes', 'conflicts' ) ) ) 00804 return false; 00805 00806 if ( $parameters === false ) 00807 { 00808 return $this->Parameters['dependencies'][$dependencySection]; 00809 } 00810 00811 $matches = array(); 00812 $dependencyItems = $this->Parameters['dependencies'][$dependencySection]; 00813 foreach ( $dependencyItems as $dependencyItem ) 00814 { 00815 $found = true; 00816 00817 foreach ( $parameters as $paramName => $paramValue ) 00818 { 00819 if ( !isset( $dependencyItem[$paramName] ) || 00820 $dependencyItem[$paramName] != $paramValue ) 00821 { 00822 $found = false; 00823 break; 00824 } 00825 } 00826 00827 if ( $found ) 00828 $matches[] = $dependencyItem; 00829 } 00830 00831 return $matches; 00832 } 00833 00834 /*! 00835 \return an array with install items which match the specified criterias. 00836 */ 00837 function installItemsList( $type = false, $os = false, $name = false, $isInstall = true ) 00838 { 00839 $installName = 'install'; 00840 if ( !$isInstall ) 00841 $installName = 'uninstall'; 00842 if ( !$name and !$type and !$os ) 00843 { 00844 return $this->Parameters[$installName]; 00845 } 00846 else 00847 { 00848 $matches = array(); 00849 $installItems = $this->Parameters[$installName]; 00850 foreach ( $installItems as $installItem ) 00851 { 00852 $found = false; 00853 if ( $name and $installItem['name'] == $name ) 00854 $found = true; 00855 if ( !$found and $type and $installItem['type'] == $type ) 00856 $found = true; 00857 if ( !$found ) 00858 { 00859 if ( $os ) 00860 { 00861 if ( !$installItem['os'] ) 00862 $found = true; 00863 else if ( $os and $installItem['os'] == $os ) 00864 $found = true; 00865 } 00866 else 00867 $found = true; 00868 } 00869 if ( $found ) 00870 $matches[] = $installItem; 00871 } 00872 return $matches; 00873 } 00874 } 00875 00876 function appendInstall( $type, $name, $os = false, $isInstall = true, 00877 $filename = false, $subdirectory = false, 00878 $parameters = false ) 00879 { 00880 $installEntry = $parameters; 00881 $installEntry['type'] = $type; 00882 $installEntry['name'] = $name; 00883 $installEntry['os'] = $os; 00884 $installEntry['filename'] = $filename; 00885 $installEntry['sub-directory'] = $subdirectory; 00886 if ( $installEntry['filename'] ) 00887 { 00888 $content = false; 00889 if ( isset( $installEntry['content'] ) ) 00890 $content = $installEntry['content']; 00891 if ( $content instanceof DOMElement ) 00892 { 00893 $path = $this->path(); 00894 if ( $installEntry['sub-directory'] ) 00895 { 00896 $path .= '/' . $installEntry['sub-directory']; 00897 } 00898 $filePath = $path . '/' . $installEntry['filename'] . '.xml'; 00899 if ( !file_exists( $path ) ) 00900 { 00901 eZDir::mkdir( $path, false, true ); 00902 } 00903 $partDOM = new DOMDocument( '1.0', 'utf-8' ); 00904 $partDOM->formatOutput = true; 00905 $contentImport = $partDOM->importNode( $content, true ); 00906 $partDOM->appendChild( $contentImport ); 00907 $this->storeDOM( $filePath, $partDOM ); 00908 $installEntry['content'] = false; 00909 } 00910 } 00911 $installName = 'install'; 00912 if ( !$isInstall ) 00913 $installName = 'uninstall'; 00914 $this->Parameters[$installName][] = $installEntry; 00915 } 00916 00917 /*! 00918 Sets the packager of this release. 00919 */ 00920 function setPackager( $timestamp = false, $host = false, $packager = false ) 00921 { 00922 if ( $timestamp ) 00923 $this->Parameters['packaging']['timestamp'] = $timestamp; 00924 if ( $host ) 00925 $this->Parameters['packaging']['host'] = $host; 00926 if ( $packager ) 00927 $this->Parameters['packaging']['packager'] = $packager; 00928 } 00929 00930 /*! 00931 Sets various release information. If the value is set to \c false it is not updated. 00932 \param $version The version number, eg. 1.0, 2.3.5 00933 \param $release The release number, usually starts at 1 and increments for updates on the same version 00934 \param $timestamp The timestamp of the release 00935 \param $licence The licence of the package, eg. GPL, LGPL etc. 00936 \param $state The sate of the release, e.g alpha, beta, stable etc. 00937 */ 00938 function setRelease( $version = false, $release = false, $timestamp = false, 00939 $licence = false, $state = false ) 00940 { 00941 if ( $version !== false ) 00942 { 00943 $this->Parameters['version-number'] = $version; 00944 } 00945 if ( $release !== false ) 00946 { 00947 $this->Parameters['release-number'] = $release; 00948 } 00949 if ( $timestamp !== false ) 00950 { 00951 $this->Parameters['release-timestamp'] = $timestamp; 00952 } 00953 if ( $licence !== false ) 00954 { 00955 $this->Parameters['licence'] = $licence; 00956 } 00957 if ( $state !== false ) 00958 { 00959 $this->Parameters['state'] = $state; 00960 } 00961 } 00962 00963 /*! 00964 \private 00965 \return the package as a string, the string is in xml format. 00966 */ 00967 function toString() 00968 { 00969 $dom = $this->domStructure(); 00970 $string = $dom->saveXML(); 00971 return $string; 00972 } 00973 00974 /*! 00975 \private 00976 Stores a cached version of the package in the cache directory 00977 under the repository for the package. 00978 */ 00979 function storeCache( $directory = false ) 00980 { 00981 if ( !file_exists( $directory ) ) 00982 eZDir::mkdir( $directory, false, true ); 00983 $php = new eZPHPCreator( $directory, 'package.php' ); 00984 $php->addComment( "Automatically created cache file for the package format\n" . 00985 "Do not modify this file" ); 00986 $php->addSpace(); 00987 $php->addVariable( 'CacheCodeDate', eZPackage::CACHE_CODE_DATE ); 00988 $php->addSpace(); 00989 $php->addVariable( 'Parameters', $this->Parameters, eZPHPCreator::VARIABLE_ASSIGNMENT, 00990 array( 'full-tree' => true ) ); 00991 $php->addVariable( 'InstallData', $this->InstallData, eZPHPCreator::VARIABLE_ASSIGNMENT, 00992 array( 'full-tree' => true ) ); 00993 $php->addVariable( 'RepositoryPath', $this->RepositoryPath ); 00994 $php->store(); 00995 } 00996 00997 /*! 00998 Stores the current package in the repository. 00999 */ 01000 function store() 01001 { 01002 $path = $this->path(); 01003 return $this->storePackageFile( $path ); 01004 } 01005 01006 /*! 01007 Stores the current package definition file to the directory \a $path. 01008 */ 01009 function storePackageFile( $path, $storeCache = true ) 01010 { 01011 if ( !file_exists( $path ) ) 01012 { 01013 eZDir::mkdir( $path, false, true ); 01014 } 01015 $filePath = $path . '/' . eZPackage::definitionFilename(); 01016 01017 $packageFileString = $this->toString(); 01018 $result = $this->storeString( $filePath, $packageFileString ); 01019 01020 if ( $storeCache ) 01021 $this->storeCache( $path . '/' . $this->cacheDirectory() ); 01022 return $result; 01023 } 01024 01025 /*! 01026 Recursively deletes \a $path 01027 */ 01028 static function removeFiles( $path ) 01029 { 01030 if ( file_exists( $path ) ) 01031 { 01032 eZDir::recursiveDelete( $path ); 01033 } 01034 } 01035 01036 /*! 01037 Exports the package as a gzip compressed tarball to the directory \a $archivePath 01038 */ 01039 function exportToArchive( $archivePath ) 01040 { 01041 $temporaryExportPath = eZPackage::temporaryExportPath(); 01042 $tempPath = $temporaryExportPath . '/' . $this->attribute( 'name' ); 01043 $this->removeFiles( $tempPath ); 01044 01045 // Create package temp dir and copy package's XML file there 01046 $this->storePackageFile( $tempPath, false ); 01047 01048 // Copy package's directories 01049 $directoryList = array( $this->documentDirectory(), 01050 $this->filesDirectory(), 01051 $this->simpleFilesDirectory(), 01052 $this->settingsDirectory() ); 01053 $installItems = $this->Parameters['install']; 01054 foreach( $installItems as $installItem ) 01055 { 01056 if ( !in_array( $installItem['sub-directory'], $directoryList ) ) 01057 $directoryList[] = $installItem['sub-directory']; 01058 } 01059 01060 $path = $this->path(); 01061 foreach( $directoryList as $dirName ) 01062 { 01063 $destDir = $tempPath; 01064 $dir = $path . '/' . $dirName; 01065 if ( file_exists( $dir ) ) 01066 eZDir::copy( $dir, $destDir ); 01067 } 01068 01069 $tarArchivePath = $temporaryExportPath . '/archive.tmp'; 01070 $tarArchive = ezcArchive::open( $tarArchivePath, ezcArchive::TAR_USTAR ); 01071 $tarArchive->truncate(); 01072 01073 $prefix = $tempPath . '/'; 01074 $fileList = array(); 01075 eZDir::recursiveList( $tempPath, $tempPath, $fileList ); 01076 01077 foreach ( $fileList as $fileInfo ) 01078 { 01079 $path = $fileInfo['type'] === 'dir' ? 01080 $fileInfo['path'] . '/' . $fileInfo['name'] . '/' : 01081 $fileInfo['path'] . '/' . $fileInfo['name']; 01082 $tarArchive->append( array( $path ), $prefix ); 01083 } 01084 01085 $tarArchive->close(); 01086 01087 copy( $tarArchivePath, "compress.zlib://$archivePath" ); 01088 01089 unlink( $tarArchivePath ); 01090 01091 $this->removeFiles( $tempPath ); 01092 return $archivePath; 01093 } 01094 01095 /** 01096 * Imports a package from a gzip compressed tarball file 01097 * 01098 * @param string $archiveName Path to the archive file 01099 * @param string $packageName Package name 01100 * @param bool $dbAvailable 01101 * @param bool $repositoryID 01102 * 01103 * @return eZPackage The eZPackage object if successfull, or one of the 01104 * STATUS_* class constants if an error occurs 01105 */ 01106 static function import( $archiveName, &$packageName, $dbAvailable = true, $repositoryID = false ) 01107 { 01108 if ( is_dir( $archiveName ) ) 01109 { 01110 eZDebug::writeError( "Importing from directory is not supported." ); 01111 $retValue = false; 01112 return $retValue; 01113 } 01114 else 01115 { 01116 $tempDirPath = eZPackage::temporaryImportPath(); 01117 // make a temporary directory to extract the package file to 01118 do 01119 { 01120 $archivePath = eZDir::path( array( $tempDirPath, mt_rand() ) ); 01121 } while ( file_exists( $archivePath ) ); 01122 01123 eZDir::mkdir( $archivePath, false, true ); 01124 01125 $archiveOptions = new ezcArchiveOptions( array( 'readOnly' => true ) ); 01126 01127 // Fix for issue #15891: ezjscore - file names are cutted 01128 // Force the type of the archive as ezcArchive::TAR_GNU so that long file names are supported on Windows 01129 // The previous value for the second parameter was null which meant the type was guessed from the 01130 // archive, but on Windows it was detected as TAR_USTAR and this lead to filenames being limited 01131 // to 100 characters 01132 $archive = ezcArchive::open( "compress.zlib://$archiveName", ezcArchive::TAR_GNU, $archiveOptions ); 01133 01134 $fileList = array(); 01135 $fileList[] = eZPackage::definitionFilename(); 01136 01137 // Search for the files we want to extract 01138 foreach( $archive as $entry ) 01139 { 01140 if ( in_array( $entry->getPath(), $fileList ) ) 01141 { 01142 if ( !$archive->extractCurrent( $archivePath ) ) 01143 { 01144 eZDebug::writeError( "Failed extracting package definition file from $archivePath" ); 01145 return false; 01146 } 01147 } 01148 } 01149 01150 $definitionFileName = eZDir::path( array( $archivePath, self::definitionFilename() ) ); 01151 01152 $package = eZPackage::fetchFromFile( $definitionFileName ); 01153 01154 eZPackage::removeFiles( $archivePath ); 01155 01156 if ( $package ) 01157 { 01158 $packageName = $package->attribute( 'name' ); 01159 01160 if ( !self::isValidName( $packageName ) ) 01161 { 01162 return eZPackage::STATUS_INVALID_NAME; 01163 } 01164 01165 if ( !$repositoryID ) 01166 { 01167 $repositoryID = $package->attribute( 'vendor-dir' ); 01168 } 01169 01170 $existingPackage = eZPackage::fetch( $packageName, false, false, $dbAvailable ); 01171 if ( $existingPackage ) 01172 { 01173 return eZPackage::STATUS_ALREADY_EXISTS; 01174 } 01175 01176 unset( $package ); 01177 01178 $fullRepositoryPath = eZPackage::repositoryPath() . '/' . $repositoryID; 01179 $packagePath = $fullRepositoryPath . '/' . $packageName; 01180 if ( !file_exists( $packagePath ) ) 01181 { 01182 eZDir::mkdir( $packagePath, false, true ); 01183 } 01184 $archive->extract( $packagePath ); 01185 01186 $package = eZPackage::fetch( $packageName, $fullRepositoryPath, false, $dbAvailable ); 01187 if ( !$package ) 01188 { 01189 eZDebug::writeError( "Failed loading imported package $packageName from $fullRepositoryPath" ); 01190 } 01191 } 01192 else 01193 { 01194 eZDebug::writeError( "Failed loading temporary package $packageName" ); 01195 } 01196 01197 return $package; 01198 } 01199 } 01200 01201 /*! 01202 \static 01203 \return the suffix for all package files. 01204 */ 01205 static function suffix() 01206 { 01207 return 'ezpkg'; 01208 } 01209 01210 /*! 01211 \return the file name for an exported archive of the current package 01212 */ 01213 function exportName() 01214 { 01215 return $this->attribute( 'name' ) . '-' . $this->attribute( 'version-number' ) . '-' . $this->attribute( 'release-number' ) . '.' . eZPackage::suffix(); 01216 } 01217 01218 /*! 01219 Stores the current package to the file \a $filename. 01220 */ 01221 function storeToFile( $filename ) 01222 { 01223 $dom = $this->domStructure(); 01224 return eZPackage::storeDOM( $filename, $dom ); 01225 } 01226 01227 /*! 01228 Applies the storage file permissions specified in site.ini to the file \a $filename 01229 */ 01230 static function applyStorageFilePermissions( $filename ) 01231 { 01232 $siteConfig = eZINI::instance( 'site.ini' ); 01233 $filePermissions = $siteConfig->variable( 'FileSettings', 'StorageFilePermissions'); 01234 chmod( $filename, octdec( $filePermissions ) ); 01235 } 01236 01237 /*! 01238 Stores the DOM tree \a $dom to the file \a $filename. 01239 */ 01240 static function storeDOM( $filename, $dom ) 01241 { 01242 $bytes = $dom->save( $filename ); 01243 01244 if ( $bytes !== false ) 01245 { 01246 eZPackage::applyStorageFilePermissions( $filename ); 01247 01248 eZDebugSetting::writeNotice( 'kernel-ezpackage-store', 01249 "Stored file $filename", 01250 'eZPackage::storeDOM' ); 01251 return true; 01252 } 01253 else 01254 { 01255 eZDebug::writeError( "Saving DOM tree to $filename failed", __METHOD__ ); 01256 } 01257 01258 return false; 01259 } 01260 01261 /*! 01262 \private 01263 \static 01264 Stores the string data \a $data into the file \a $filename. 01265 \return \c true if successful. 01266 */ 01267 static function storeString( $filename, $data ) 01268 { 01269 $file = @fopen( $filename, 'w' ); 01270 if ( $file ) 01271 { 01272 fwrite( $file, $data ); 01273 fclose( $file ); 01274 01275 eZPackage::applyStorageFilePermissions( $filename ); 01276 01277 eZDebugSetting::writeNotice( 'kernel-ezpackage-store', 01278 "Stored file $filename", 01279 'eZPackage::storeString' ); 01280 return true; 01281 } 01282 else 01283 { 01284 eZDebug::writeError( "Failed to write package '$filename'" ); 01285 } 01286 return false; 01287 } 01288 01289 01290 /*! 01291 \private 01292 Loads the contents of the file \a $filename and parses it into a DOM tree. 01293 The DOM tree is returned. 01294 */ 01295 static function fetchDOMFromFile( $filename ) 01296 { 01297 if ( file_exists( $filename ) ) 01298 { 01299 $dom = new DOMDocument( '1.0', 'utf-8' ); 01300 $dom->preserveWhiteSpace = false; 01301 $success = $dom->load( $filename ); 01302 01303 if ( !$success ) 01304 { 01305 return false; 01306 } 01307 else 01308 { 01309 return $dom; 01310 } 01311 } 01312 return false; 01313 } 01314 01315 /*! 01316 \static 01317 Tries to load the package definition from file \a $filename 01318 and create a package object from it. 01319 \return \c false if it could be fetched. 01320 */ 01321 static function fetchFromFile( $filename ) 01322 { 01323 $dom = eZPackage::fetchDOMFromFile( $filename ); 01324 01325 if ( $dom === false ) 01326 { 01327 return false; 01328 } 01329 01330 $package = new eZPackage(); 01331 $parameters = $package->parseDOMTree( $dom ); 01332 if ( !$parameters ) 01333 { 01334 return false; 01335 } 01336 01337 return $package; 01338 } 01339 01340 /*! 01341 \static 01342 Tries to load the package named \a $packageName from the repository 01343 and returns the package object. 01344 \param $repositoryID Determines in which repositories the package should be searched for, 01345 if set to \c true it means only look in local packages, \c false means 01346 look in all repositories. 01347 \param $dbAvailable Do we have a database to fetch additional package info, like installed state. 01348 (false in setup wizard) 01349 \return \c false if no package could be found. 01350 */ 01351 static function fetch( $packageName, $packagePath = false, $repositoryID = false, $dbAvailable = true ) 01352 { 01353 $packageRepositories = eZPackage::packageRepositories( array( 'path' => $packagePath ) ); 01354 01355 if ( $repositoryID === true ) 01356 $repositoryID = 'local'; 01357 01358 foreach ( $packageRepositories as $packageRepository ) 01359 { 01360 if ( $repositoryID !== false and 01361 $packageRepository['id'] != $repositoryID ) 01362 continue; 01363 $path = $packageRepository['path']; 01364 01365 $path .= '/' . $packageName; 01366 $filePath = $path . '/' . eZPackage::definitionFilename(); 01367 01368 if ( file_exists( $filePath ) ) 01369 { 01370 $fileModification = filemtime( $filePath ); 01371 $package = false; 01372 $cacheExpired = false; 01373 01374 if ( eZPackage::useCache() ) 01375 { 01376 $package = eZPackage::fetchFromCache( $path, $fileModification, $cacheExpired ); 01377 } 01378 01379 if ( $package ) 01380 { 01381 $package->setCurrentRepositoryInformation( $packageRepository ); 01382 } 01383 else 01384 { 01385 $package = eZPackage::fetchFromFile( $filePath ); 01386 01387 if ( $package ) 01388 { 01389 $package->setCurrentRepositoryInformation( $packageRepository ); 01390 if ( $packagePath ) 01391 $package->RepositoryPath = $packagePath; 01392 if ( $cacheExpired and 01393 eZPackage::useCache() ) 01394 { 01395 $package->storeCache( $path . '/' . eZPackage::cacheDirectory() ); 01396 } 01397 } 01398 } 01399 if ( $dbAvailable ) 01400 $package->getInstallState(); 01401 01402 return $package; 01403 } 01404 } 01405 return false; 01406 } 01407 01408 static function useCache() 01409 { 01410 return eZPackage::USE_CACHE; 01411 } 01412 01413 /*! 01414 \private 01415 */ 01416 static function fetchFromCache( $packagePath, $packageModification, &$cacheExpired ) 01417 { 01418 $packageCachePath = $packagePath . '/' . eZPackage::cacheDirectory() . '/package.php'; 01419 01420 if ( file_exists( $packageCachePath ) ) 01421 { 01422 $cacheModification = filemtime( $packageCachePath ); 01423 if ( $cacheModification >= $packageModification ) 01424 { 01425 include( $packageCachePath ); 01426 if ( !isset( $CacheCodeDate ) or 01427 $CacheCodeDate != eZPackage::CACHE_CODE_DATE ) 01428 { 01429 $cacheExpired = true; 01430 return false; 01431 } 01432 if ( isset( $Parameters ) and 01433 isset( $InstallData ) ) 01434 { 01435 $cacheExpired = false; 01436 $package = new eZPackage( $Parameters, $RepositoryPath ); 01437 $package->InstallData = $InstallData; 01438 return $package; 01439 } 01440 } 01441 else 01442 $cacheExpired = true; 01443 } 01444 $cacheExpired = true; 01445 return false; 01446 } 01447 01448 /*! 01449 \return the full path to this package. 01450 */ 01451 function path() 01452 { 01453 $path = $this->currentRepositoryPath(); 01454 $path .= '/' . $this->attribute( 'name' ); 01455 return $path; 01456 } 01457 01458 /*! 01459 \return the path to the current repository. 01460 */ 01461 function currentRepositoryPath() 01462 { 01463 $repositoryInformation = $this->currentRepositoryInformation(); 01464 if ( $repositoryInformation ) 01465 return $repositoryInformation['path']; 01466 return $this->RepositoryPath; 01467 } 01468 01469 /*! 01470 \static 01471 \return the directory name for temporary export packages, used in conjunction with eZSys::cacheDirectory(). 01472 */ 01473 static function temporaryExportPath() 01474 { 01475 $path = eZDir::path( array( eZSys::cacheDirectory(), 01476 'packages', 01477 'export' . eZUser::currentUserID() ) ); 01478 return $path; 01479 } 01480 01481 /*! 01482 \static 01483 \return the directory name for temporary import packages, used in conjunction with eZSys::cacheDirectory(). 01484 */ 01485 static function temporaryImportPath() 01486 { 01487 $path = eZDir::path( array( eZSys::cacheDirectory(), 01488 'packages', 01489 'import' ) ); 01490 return $path; 01491 } 01492 01493 /*! 01494 \static 01495 \return the path to the package repository. 01496 */ 01497 static function repositoryPath() 01498 { 01499 $ini = eZINI::instance(); 01500 $packageIni = eZINI::instance( 'package.ini' ); 01501 01502 return eZDir::path( array( 'var', 01503 $ini->variable( 'FileSettings', 'StorageDir' ), 01504 $packageIni->variable( 'RepositorySettings', 'RepositoryDirectory' ) ) ); 01505 } 01506 01507 /*! 01508 \static 01509 \return the name of the cache directory for cached package data. 01510 */ 01511 static function cacheDirectory() 01512 { 01513 return '.cache'; 01514 } 01515 01516 /*! 01517 \static 01518 \return the name of the package definition file. 01519 */ 01520 static function definitionFilename() 01521 { 01522 return 'package.xml'; 01523 } 01524 01525 /*! 01526 \static 01527 \return the name of the documents directory for cached package data. 01528 */ 01529 static function documentDirectory() 01530 { 01531 return 'documents'; 01532 } 01533 01534 /*! 01535 \static 01536 \return the name of the documents directory for cached package data. 01537 */ 01538 static function filesDirectory() 01539 { 01540 return 'files'; 01541 } 01542 01543 /*! 01544 \private 01545 Get local simple file path 01546 */ 01547 static function simpleFilesDirectory() 01548 { 01549 return 'simplefiles'; 01550 } 01551 01552 static function settingsDirectory() 01553 { 01554 return 'settings'; 01555 } 01556 01557 /*! 01558 Locates all dependent packages in the repository and returns an array with eZPackage objects. 01559 \param $dependencyType is the name of a dependency sub-node. (ie. 'provides', 'requires' etc...) 01560 */ 01561 function fetchDependentPackages( $dependencyType, &$failedList ) 01562 { 01563 $packages = array(); 01564 $provides = $this->Parameters['dependencies'][$dependencyType]; 01565 01566 if ( $provides != null ) 01567 { 01568 foreach ( $provides as $provide ) 01569 { 01570 // fetch only dependent packages, not package items. 01571 if ( $provide['type'] == 'ezpackage' ) 01572 { 01573 // TODO: Add fetching from URL (not here ?) 01574 $package = $this->fetch( $provide['name'] ); 01575 01576 if ( !$package ) 01577 { 01578 $failedList[] = $provide['name']; 01579 continue; 01580 } 01581 $packages[] =& $package; 01582 } 01583 } 01584 } 01585 return $packages; 01586 } 01587 01588 /*! 01589 \static 01590 \return an array with repositories which can contain packages. 01591 01592 Each repository entry is an array with the following keys. 01593 - path The path to the repository relative from the eZ Publish installation 01594 - id Unique identifier for this repository 01595 - name Human readable string identifying this repository, the name is translatable 01596 - type What kind of repository, currently supports local or global. 01597 */ 01598 static function packageRepositories( $parameters = array() ) 01599 { 01600 if ( isset( $parameters['path'] ) and $parameters['path'] ) 01601 { 01602 $path = $parameters['path']; 01603 $packageRepositories = array( array( 'path' => $path, 01604 'id' => 'local', 01605 'name' => ezpI18n::tr( 'kernel/package', 'Local' ), 01606 'type' => 'local' ) ); 01607 } 01608 else 01609 { 01610 $repositoryPath = eZPackage::repositoryPath(); 01611 $packageRepositories = array( array( 'path' => $repositoryPath . '/local', 01612 'id' => 'local', 01613 'name' => ezpI18n::tr( 'kernel/package', 'Local' ), 01614 'type' => 'local' ) ); 01615 01616 $subdirs = eZDir::findSubitems( $repositoryPath, 'd' ); 01617 foreach( $subdirs as $dir ) 01618 { 01619 if ( $dir == 'local' ) 01620 continue; 01621 01622 $packageRepositories[] = array( 'path' => $repositoryPath . '/' . $dir, 01623 'id' => $dir, 01624 'name' => $dir, 01625 'type' => 'global' ); 01626 } 01627 } 01628 return $packageRepositories; 01629 } 01630 01631 /*! 01632 \static 01633 \return information on the repository with ID $repositoryID or \c false if does not exist. 01634 */ 01635 static function repositoryInformation( $repositoryID ) 01636 { 01637 $packageRepositories = eZPackage::packageRepositories(); 01638 foreach ( $packageRepositories as $packageRepository ) 01639 { 01640 if ( $packageRepository['id'] == $repositoryID ) 01641 return $packageRepository; 01642 } 01643 return false; 01644 } 01645 01646 /*! 01647 \static 01648 \return information on the eZ system repository or \c false if does not exist. 01649 */ 01650 static function systemRepositoryInformation() 01651 { 01652 $ini = eZINI::instance( 'package.ini' ); 01653 $vendor = $ini->variable( 'RepositorySettings', 'Vendor' ); 01654 return eZPackage::repositoryInformation( $vendor ); 01655 } 01656 01657 /*! 01658 Sets the current repository information for the package. 01659 \sa currentRepositoryInformation, packageRepositories 01660 */ 01661 function setCurrentRepositoryInformation( $information ) 01662 { 01663 $this->RepositoryInformation = $information; 01664 } 01665 01666 /*! 01667 \return the current repository information for the package, this 01668 will contain information of where the package was found. 01669 See packageRepositories too see what the information will contain. 01670 \note The return information can be \c null in some cases when the package is not properly initialized. 01671 */ 01672 function currentRepositoryInformation() 01673 { 01674 return $this->RepositoryInformation; 01675 } 01676 01677 /*! 01678 Locates all packages in the repository and returns an array with eZPackage objects. 01679 01680 \param parameters 01681 \param filterArray 01682 */ 01683 static function fetchPackages( $parameters = array(), $filterArray = array() ) 01684 { 01685 $packageRepositories = eZPackage::packageRepositories( $parameters ); 01686 01687 $packages = array(); 01688 01689 $requiredType = null; 01690 $requiredPriority = null; 01691 $requiredVendor = null; 01692 $requiredExtension = null; 01693 if ( isset( $filterArray['type'] ) ) 01694 $requiredType = $filterArray['type']; 01695 if ( isset( $filterArray['priority'] ) ) 01696 $requiredPriority = $filterArray['priority']; 01697 if ( isset( $filterArray['vendor'] ) ) 01698 $requiredVendor = $filterArray['vendor']; 01699 if ( isset( $filterArray['extension'] ) ) 01700 $requiredExtension = $filterArray['extension']; 01701 $repositoryID = false; 01702 if ( isset( $parameters['repository_id'] ) ) 01703 $repositoryID = $parameters['repository_id']; 01704 $dbAvailable = true; 01705 if ( isset( $parameters['db_available'] ) ) 01706 $dbAvailable = $parameters['db_available']; 01707 01708 foreach ( $packageRepositories as $packageRepository ) 01709 { 01710 if ( strlen( $repositoryID ) == 0 or 01711 $repositoryID == $packageRepository['id'] ) 01712 { 01713 $path = $packageRepository['path']; 01714 if ( file_exists( $path ) ) 01715 { 01716 $fileList = array(); 01717 $dir = opendir( $path ); 01718 while( ( $file = readdir( $dir ) ) !== false ) 01719 { 01720 if ( $file == '.' or 01721 $file == '..' ) 01722 continue; 01723 $fileList[] = $file; 01724 } 01725 closedir( $dir ); 01726 sort( $fileList ); 01727 foreach ( $fileList as $file ) 01728 { 01729 $dirPath = $path . '/' . $file; 01730 if ( !is_dir( $dirPath ) ) 01731 continue; 01732 $filePath = $dirPath . '/' . eZPackage::definitionFilename(); 01733 if ( file_exists( $filePath ) ) 01734 { 01735 $fileModification = filemtime( $filePath ); 01736 $name = $file; 01737 $packageCachePath = $dirPath . '/' . eZPackage::cacheDirectory() . '/package.php'; 01738 unset( $package ); 01739 $package = false; 01740 $cacheExpired = false; 01741 if ( eZPackage::useCache() ) 01742 { 01743 $package = eZPackage::fetchFromCache( $dirPath, $fileModification, $cacheExpired ); 01744 } 01745 if ( !$package ) 01746 { 01747 $package = eZPackage::fetchFromFile( $filePath ); 01748 if ( $package and 01749 $cacheExpired and 01750 eZPackage::useCache() ) 01751 { 01752 $package->storeCache( $dirPath . '/' . eZPackage::cacheDirectory() ); 01753 } 01754 } 01755 if ( !$package ) 01756 continue; 01757 01758 if ( $dbAvailable ) 01759 $package->getInstallState(); 01760 01761 if ( $requiredType !== null ) 01762 { 01763 $type = $package->attribute( 'type' ); 01764 if ( $type != $requiredType ) 01765 continue; 01766 } 01767 01768 if ( $requiredPriority !== null ) 01769 { 01770 $priority = $package->attribute( 'priority' ); 01771 if ( $priority != $requiredPriority ) 01772 continue; 01773 } 01774 01775 if ( $requiredExtension !== null ) 01776 { 01777 $extension = $package->attribute( 'extension' ); 01778 if ( $extension != $requiredExtension ) 01779 continue; 01780 } 01781 01782 if ( $requiredVendor !== null ) 01783 { 01784 $vendor = $package->attribute( 'vendor' ); 01785 if ( $vendor != $requiredVendor ) 01786 continue; 01787 } 01788 01789 $package->setCurrentRepositoryInformation( $packageRepository ); 01790 01791 $packages[] =& $package; 01792 } 01793 } 01794 } 01795 } 01796 } 01797 return $packages; 01798 } 01799 01800 /*! 01801 Install specified install item in package 01802 01803 \param Item index 01804 \param parameters 01805 */ 01806 function installItem( $item, &$installParameters ) 01807 { 01808 $type = $item['type']; 01809 $name = $item['name']; 01810 $os = $item['os']; 01811 $filename = $item['filename']; 01812 $subdirectory = $item['sub-directory']; 01813 $content = false; 01814 if ( isset( $item['content'] ) ) 01815 $content = $item['content']; 01816 $handler = $this->packageHandler( $type ); 01817 $installResult = false; 01818 if ( $handler ) 01819 { 01820 if ( $handler->extractInstallContent() ) 01821 { 01822 if ( !$content and 01823 $filename ) 01824 { 01825 if ( $subdirectory ) 01826 $filepath = $subdirectory . '/' . $filename . '.xml'; 01827 else 01828 $filepath = $filename . '.xml'; 01829 01830 $filepath = $this->path() . '/' . $filepath; 01831 01832 $dom = eZPackage::fetchDOMFromFile( $filepath ); 01833 if ( $dom ) 01834 { 01835 $content = $dom->documentElement; 01836 } 01837 else 01838 { 01839 eZDebug::writeError( "Failed fetching dom from file $filepath", __METHOD__ ); 01840 } 01841 } 01842 } 01843 $installData =& $this->InstallData[$type]; 01844 if ( !isset( $installData ) ) 01845 $installData = array(); 01846 $installResult = $handler->install( $this, $type, $item, 01847 $name, $os, $filename, $subdirectory, 01848 $content, $installParameters, 01849 $installData ); 01850 } 01851 return $installResult; 01852 } 01853 01854 /** 01855 * Installs all items in the package 01856 * 01857 * @param array $installParameters 01858 * 01859 * @return bool true if all items installed correctly, false otherwise 01860 */ 01861 function install( &$installParameters ) 01862 { 01863 if ( $this->Parameters['install_type'] != 'install' ) 01864 return; 01865 $installItems = $this->Parameters['install']; 01866 if ( !isset( $installParameters['path'] ) ) 01867 $installParameters['path'] = false; 01868 $installResult = true; 01869 foreach ( $installItems as $item ) 01870 { 01871 if ( !$this->installItem( $item, $installParameters ) ) 01872 { 01873 eZDebug::writeDebug( $item, 'item which failed installing' ); 01874 $installResult = false; 01875 } 01876 } 01877 $this->setInstalled(); 01878 return $installResult; 01879 } 01880 01881 function uninstallItem( $item, &$uninstallParameters ) 01882 { 01883 $type = $item['type']; 01884 $name = $item['name']; 01885 $os = $item['os']; 01886 $filename = $item['filename']; 01887 $subdirectory = $item['sub-directory']; 01888 $content = false; 01889 if ( isset( $item['content'] ) ) 01890 $content = $item['content']; 01891 01892 $handler = $this->packageHandler( $type ); 01893 if ( $handler ) 01894 { 01895 if ( $handler->extractInstallContent() ) 01896 { 01897 if ( !$content and 01898 $filename ) 01899 { 01900 if ( $subdirectory ) 01901 $filepath = $subdirectory . '/' . $filename . '.xml'; 01902 else 01903 $filepath = $filename . '.xml'; 01904 01905 $filepath = $this->path() . '/' . $filepath; 01906 01907 $dom = eZPackage::fetchDOMFromFile( $filepath ); 01908 if ( $dom ) 01909 { 01910 $content = $dom->documentElement; 01911 } 01912 else 01913 { 01914 eZDebug::writeError( "Failed fetching dom from file $filepath", __METHOD__ ); 01915 } 01916 } 01917 } 01918 01919 if ( isset( $this->InstallData[$type] ) ) 01920 { 01921 $installData =& $this->InstallData[$type]; 01922 } 01923 else 01924 { 01925 unset( $installData ); 01926 $installData = array(); 01927 } 01928 $uninstallResult = $handler->uninstall( $this, $type, $item, 01929 $name, $os, $filename, $subdirectory, 01930 $content, $uninstallParameters, 01931 $installData ); 01932 } 01933 return $uninstallResult; 01934 } 01935 01936 /*! 01937 Install all install items in package 01938 */ 01939 function uninstall( $uninstallParameters = array() ) 01940 { 01941 if ( $this->Parameters['install_type'] != 'install' ) 01942 return; 01943 if ( !$this->isInstalled() ) 01944 return; 01945 $uninstallItems = $this->installItemsList(); 01946 if ( !isset( $installParameters['path'] ) ) 01947 $installParameters['path'] = false; 01948 01949 $uninstallResult = true; 01950 foreach ( $uninstallItems as $item ) 01951 { 01952 if ( !$this->uninstallItem( $item, $uninstallParameters ) ) 01953 { 01954 $uninstallResult = false; 01955 } 01956 } 01957 01958 $this->InstallData = array(); 01959 $this->setInstalled( false ); 01960 return $uninstallResult; 01961 } 01962 01963 /*! 01964 \private 01965 */ 01966 function parseDOMTree( DOMDocument $dom ) 01967 { 01968 $root = $dom->documentElement; 01969 01970 // Read basic info 01971 $parameters = array(); 01972 $parameters['name'] = $root->getElementsByTagName( 'name' )->item( 0 )->textContent; 01973 $vendorNode = $root->getElementsByTagName( 'vendor' )->item( 0 ); 01974 $parameters['vendor'] = is_object( $vendorNode ) ? $vendorNode->textContent : false; 01975 $parameters['summary'] = $root->getElementsByTagName( 'summary' )->item( 0 )->textContent; 01976 $parameters['description'] = $root->getElementsByTagName( 'description' )->item( 0 )->textContent; 01977 $priorities = $root->getElementsByTagName( 'priority' ); 01978 if ( $priorities->length > 0 ) 01979 { 01980 $parameters['priority'] = $priorities->item( 0 )->getAttribute( 'value' ); 01981 } 01982 $parameters['type'] = $root->getElementsByTagName( 'type' )->item( 0 )->getAttribute( 'value' ); 01983 01984 if ( $parameters['vendor'] ) 01985 { 01986 // Creating nice vendor directory name 01987 $trans = eZCharTransform::instance(); 01988 $parameters['vendor-dir'] = $trans->transformByGroup( $parameters['vendor'], 'urlalias' ); 01989 } 01990 else 01991 { 01992 $parameters['vendor-dir'] = 'local'; 01993 } 01994 01995 $parameters['install_type'] = 'install'; 01996 $installType = $root->getAttribute( 'install_type' ); 01997 if ( $installType ) 01998 $parameters['install_type'] = $installType; 01999 $sourceNodes = $root->getElementsByTagName( 'source' ); 02000 if ( $sourceNodes->length > 0 ) 02001 { 02002 $parameters['source'] = $sourceNodes->item( 0 )->textContent; 02003 } 02004 $parameters['development'] = $root->getAttribute( 'development' ) == 'true'; 02005 $extensionNode = $root->getElementsByTagName( 'extension' )->item( 0 ); 02006 if ( $extensionNode ) 02007 $parameters['extension'] = $extensionNode->getAttribute( 'name' ); 02008 $ezpublishNode = $root->getElementsByTagName( 'ezpublish' )->item( 0 ); 02009 $parameters['ezpublish']['version'] = $ezpublishNode->getElementsByTagName( 'version' )->item( 0 )->textContent; 02010 $parameters['ezpublish']['named-version'] = $ezpublishNode->getElementsByTagName( 'named-version' )->item( 0 )->textContent; 02011 $this->setParameters( $parameters ); 02012 02013 // Read maintainers 02014 $maintainersNode = $root->getElementsByTagName( 'maintainers' )->item( 0 ); 02015 if ( $maintainersNode ) 02016 { 02017 $maintainerNodes = $maintainersNode->getElementsByTagName( 'maintainer' ); 02018 foreach ( $maintainerNodes as $maintainerNode ) 02019 { 02020 $maintainerName = $maintainerNode->getElementsByTagName( 'name' )->item( 0 )->textContent; 02021 $maintainerEmail = $maintainerNode->getElementsByTagName( 'email' )->item( 0 )->textContent; 02022 $maintainerRole = $maintainerNode->getElementsByTagName( 'role' )->item( 0 )->textContent; 02023 $this->appendMaintainer( $maintainerName, $maintainerEmail, $maintainerRole ); 02024 } 02025 } 02026 02027 // Read packaging info 02028 $packagingNode = $root->getElementsByTagName( 'packaging' )->item( 0 ); 02029 $packagingTimestamp = $packagingNode->getElementsByTagName( 'timestamp' )->item( 0 )->textContent; 02030 $packagingHost = $packagingNode->getElementsByTagName( 'host' )->item( 0 )->textContent; 02031 $packagerNodes = $packagingNode->getElementsByTagName( 'packager' ); 02032 if ( $packagerNodes->length > 0 ) 02033 { 02034 $packagingPackager = $packagerNodes->item( 0 )->textContent; 02035 } 02036 else 02037 { 02038 $packagingPackager = false; 02039 } 02040 $this->setPackager( $packagingTimestamp, $packagingHost, $packagingPackager ); 02041 02042 // Read documents 02043 $documentsNode = $root->getElementsByTagName( 'documents' )->item( 0 ); 02044 $documentNodes = $documentsNode->getElementsByTagName( 'document' ); 02045 02046 foreach ( $documentNodes as $documentNode ) 02047 { 02048 $documentName = $documentNode->getAttribute( 'name' ); 02049 $documentMimeType = $documentNode->getAttribute( 'mime-type' ); 02050 $documentOS = $documentNode->getAttribute( 'os' ); 02051 $documentAudience = $documentNode->getAttribute( 'audience' ); 02052 $this->appendDocument( $documentName, $documentMimeType, 02053 $documentOS, $documentAudience, 02054 false, false ); 02055 } 02056 02057 // Read changelog 02058 $changelogNode = $root->getElementsByTagName( 'changelog' )->item( 0 ); 02059 if ( $changelogNode ) 02060 { 02061 $changelogEntryNodes = $changelogNode->getElementsByTagName( 'entry' ); 02062 foreach ( $changelogEntryNodes as $changelogEntryNode ) 02063 { 02064 $changelogTimestamp = $changelogEntryNode->getAttribute( 'timestamp' ); 02065 $changelogPerson = $changelogEntryNode->getAttribute( 'person' ); 02066 $changelogEmail = $changelogEntryNode->getAttribute( 'email' ); 02067 $changelogRelease = $changelogEntryNode->getAttribute( 'release' ); 02068 $changelogChangeList = $changelogEntryNode->getElementsByTagName( 'change' )->item( 0 )->textContent; 02069 $this->appendChange( $changelogPerson, $changelogEmail, $changelogChangeList, 02070 $changelogRelease, $changelogTimestamp ); 02071 } 02072 } 02073 02074 // Read simple files 02075 $this->Parameters['simple-file-list'] = array(); 02076 $simpleFilesNode = $root->getElementsByTagName( 'simple-files' )->item( 0 ); 02077 if ( $simpleFilesNode && $simpleFilesNode->hasChildNodes() ) 02078 { 02079 $simpleFileNodes = $simpleFilesNode->getElementsByTagName( 'simple-file' ); 02080 foreach ( $simpleFileNodes as $simpleFileNode ) 02081 { 02082 $key = $simpleFileNode->getAttribute( 'key' ); 02083 $originalPath = $simpleFileNode->getAttribute( 'original-path' ); 02084 $packagePath = $simpleFileNode->getAttribute( 'package-path' ); 02085 $this->Parameters['simple-file-list'][$key] = array( 'original-path' => $originalPath, 02086 'package-path' => $packagePath ); 02087 } 02088 } 02089 02090 // Read files 02091 $filesList = $root->getElementsByTagName( 'files' ); 02092 if ( $filesList ) 02093 { 02094 foreach ( $filesList as $fileCollectionNode ) 02095 { 02096 $fileCollectionName = $fileCollectionNode->getAttribute( 'name' ); 02097 $fileLists = $fileCollectionNode->getElementsByTagName( 'file-list' ); 02098 foreach ( $fileLists as $fileListNode ) 02099 { 02100 $fileType = $fileListNode->getAttribute( 'type' ); 02101 $fileDesign = $fileListNode->getAttribute( 'design' ); 02102 $fileRole = $fileListNode->getAttribute( 'role' ); 02103 $fileVariableName = $fileListNode->getAttribute( 'variable-name' ); 02104 $fileRoleValue = $fileListNode->getAttribute( 'role-value' ); 02105 $files = $fileListNode->getElementsByTagName( 'file' ); 02106 if ( count( $files ) > 0 ) 02107 { 02108 foreach ( $files as $fileNode ) 02109 { 02110 $fileFileType = $fileNode->getAttribute( 'type' ); 02111 $fileName = $fileNode->getAttribute( 'name' ); 02112 if ( $fileNode->getAttribute( 'variable-name' ) ) 02113 $fileVariableName = $fileNode->getAttribute( 'variable-name' ); 02114 $fileSubDirectory = $fileNode->getAttribute( 'sub-directory' ); 02115 $filePath = $fileNode->getAttribute( 'path' ); 02116 $fileMD5 = $fileNode->getAttribute( 'md5sum' ); 02117 $this->appendFile( $fileName, $fileType, $fileRole, 02118 $fileDesign, $filePath, $fileCollectionName, 02119 $fileSubDirectory, $fileMD5, false, null, 02120 $fileFileType, 02121 $fileRoleValue, $fileVariableName ); 02122 } 02123 } 02124 else 02125 { 02126 $this->appendFile( false, $fileType, $fileRole, 02127 $fileDesign, false, $fileCollectionName, 02128 false, false, false, null ); 02129 } 02130 unset( $files ); 02131 } 02132 } 02133 } 02134 // Read release info 02135 $xpath = new DOMXPath( $dom ); 02136 $versionNode = $xpath->query( 'version' )->item( 0 ); 02137 $versionNumber = false; 02138 $versionRelease = false; 02139 if ( $versionNode ) 02140 { 02141 $versionNumber = $versionNode->getElementsByTagName( 'number' )->item( 0 )->textContent; 02142 $versionRelease = $versionNode->getElementsByTagName( 'release' )->item( 0 )->textContent; 02143 } 02144 $licence = $root->getElementsByTagName( 'licence' )->item( 0 )->textContent; 02145 $state = $root->getElementsByTagName( 'state' )->item( 0 )->textContent; 02146 $this->setRelease( $versionNumber, $versionRelease, false, 02147 $licence, $state ); 02148 02149 $dependenciesNode = $root->getElementsByTagName( 'dependencies' )->item( 0 ); 02150 if ( $dependenciesNode ) 02151 { 02152 $providesNode = $dependenciesNode->getElementsByTagName( 'provides' )->item( 0 ); 02153 $providesList = $providesNode->getElementsByTagName( 'provide' ); 02154 $requiresNode = $dependenciesNode->getElementsByTagName( 'requires' )->item( 0 ); 02155 $requiresList = $requiresNode->getElementsByTagName( 'require' ); 02156 $obsoletesNode = $dependenciesNode->getElementsByTagName( 'obsoletes' )->item( 0 ); 02157 $obsoletesList = $obsoletesNode->getElementsByTagName( 'obsolete' ); 02158 $conflictsNode = $dependenciesNode->getElementsByTagName( 'conflicts' )->item( 0 ); 02159 $conflictsList = $conflictsNode->getElementsByTagName( 'conflict' ); 02160 $this->parseDependencyTree( $providesList, 'provides' ); 02161 $this->parseDependencyTree( $requiresList, 'requires' ); 02162 $this->parseDependencyTree( $obsoletesList, 'obsoletes' ); 02163 $this->parseDependencyTree( $conflictsList, 'conflicts' ); 02164 } 02165 02166 $settingsNode = $root->getElementsByTagName( 'settings' )->item( 0 ); 02167 02168 if ( $settingsNode ) 02169 { 02170 $settingsFileNodes = $settingsNode->getElementsByTagName( 'settings-file' ); 02171 $this->Parameters['settings-files'] = array(); 02172 02173 foreach( $settingsFileNodes as $settingsFileNode ) 02174 { 02175 $this->Parameters['settings-files'][] = $settingsFileNode->getAttribute( 'filename' ); 02176 } 02177 } 02178 02179 $installNode = $root->getElementsByTagName( 'install' )->item( 0 ); 02180 $installList = $installNode->getElementsByTagName( 'item' ); 02181 $uninstallNode = $root->getElementsByTagName( 'uninstall' )->item( 0 ); 02182 $uninstallList = $uninstallNode->getElementsByTagName( 'item' ); 02183 $this->parseInstallTree( $installList, true ); 02184 $this->parseInstallTree( $uninstallList, false ); 02185 02186 $installDataList = $root->getElementsByTagName( 'install-data' ); 02187 if ( $installDataList ) 02188 { 02189 $this->InstallData = array(); 02190 foreach( $installDataList as $installDataNode ) 02191 { 02192 if ( is_object( $installDataNode ) && 02193 $installDataNode->getAttribute( 'name' ) == 'data' ) 02194 { 02195 $installDataType = $installDataNode->getAttribute( 'type' ); 02196 $installDataElements = $installDataNode->getElementsByTagName( 'data' ); 02197 $installData = array(); 02198 foreach ( $installDataElements as $installDataElement ) 02199 { 02200 if ( $installDataElement->attribute( 'name' ) == 'element' ) 02201 { 02202 $name = $installDataElement->getAttribute( 'name' ); 02203 $value = $installDataElement->getAttribute( 'value' ); 02204 $installData[$name] = $value; 02205 } 02206 else if ( $installDataElement->attribute( 'name' ) == 'array' ) 02207 { 02208 $arrayName = $installDataElement->getAttribute( 'name' ); 02209 $installDataElementArray = $installDataElement->childNodes; 02210 $array = array(); 02211 foreach ( $installDataElementArray as $installDataElementArrayElement ) 02212 { 02213 $name = $installDataElementArrayElement->getAttribute( 'name' ); 02214 $value = $installDataElementArrayElement->getAttribute( 'value' ); 02215 $array[$name] = $value; 02216 } 02217 $installData[$arrayName] = $array; 02218 } 02219 } 02220 if ( count( $installData ) > 0 ) 02221 $this->InstallData[$installDataType] = $installData; 02222 } 02223 } 02224 } 02225 02226 $retValue = true; 02227 return $retValue; 02228 } 02229 02230 /*! 02231 \private 02232 */ 02233 function parseDependencyTree( $dependenciesList, $dependencySection ) 02234 { 02235 foreach ( $dependenciesList as $dependencyNode ) 02236 { 02237 $dependencyType = $dependencyNode->getAttribute( 'type' ); 02238 $dependencyAttributes = $dependencyNode->attributes; 02239 $dependencyParameters = array(); 02240 for ( $i = 0; $i < $dependencyAttributes->length; $i++ ) 02241 { 02242 $dependencyAttribute = $dependencyAttributes->item( $i ); 02243 $dependencyParameters[$dependencyAttribute->name] = $dependencyAttribute->value; 02244 } 02245 02246 $additionalDependencyParameters = array(); 02247 $handler = $this->packageHandler( $dependencyType ); 02248 if ( $handler ) 02249 { 02250 $handler->parseDependencyNode( $this, $dependencyNode, $additionalDependencyParameters, $dependencySection ); 02251 } 02252 02253 if ( count( $additionalDependencyParameters ) > 0 ) 02254 $dependencyParameters = array_merge( $dependencyParameters, $additionalDependencyParameters ); 02255 02256 $this->appendDependency( $dependencySection, $dependencyParameters ); 02257 } 02258 } 02259 02260 /*! 02261 \private 02262 */ 02263 function parseInstallTree( $installList, $isInstall ) 02264 { 02265 foreach( $installList as $installNode ) 02266 { 02267 $installType = $installNode->getAttribute( 'type' ); 02268 $installName = $installNode->getAttribute( 'name' ); 02269 $installFilename = $installNode->getAttribute( 'filename' ); 02270 $installSubdirectory = $installNode->getAttribute( 'sub-directory' ); 02271 $installOS = $installNode->getAttribute( 'os' ); 02272 02273 $handler = $this->packageHandler( $installType ); 02274 $installParameters = array(); 02275 if ( $handler ) 02276 { 02277 $handler->parseInstallNode( $this, $installNode, $installParameters, $isInstall ); 02278 } 02279 if ( count( $installParameters ) == 0 ) 02280 $installParameters = false; 02281 02282 $this->appendInstall( $installType, $installName, $installOS, $isInstall, 02283 $installFilename, $installSubdirectory, 02284 $installParameters ); 02285 } 02286 } 02287 02288 /*! 02289 \return the dom document of the package. 02290 */ 02291 function &domStructure() 02292 { 02293 $dom = new DOMDocument( '1.0', 'utf-8' ); 02294 $dom->formatOutput = true; 02295 $root = $dom->createElement( 'package' ); 02296 $root->setAttribute( 'version', eZPackage::VERSION ); 02297 $root->setAttribute( 'development', ( eZPackage::DEVELOPMENT ? 'true' : 'false' ) ); 02298 $dom->appendChild( $root ); 02299 02300 if ( eZPackage::DEVELOPMENT ) 02301 { 02302 $warningText = "This format was made with a development version and will not work with any release versions.\n" . 02303 "The format of this file is also subject to change until the release version.\n" . 02304 "Upgrades to the development format will not be supported."; 02305 02306 $warningNode = $dom->createElement( 'warning' ); 02307 $warningNode->appendChild( $dom->createTextNode( $warningText ) ); 02308 $root->appendChild( $warningNode ); 02309 } 02310 02311 $name = $this->attribute( 'name' ); 02312 $summary = $this->attribute( 'summary' ); 02313 $description = $this->attribute( 'description' ); 02314 $priority = $this->attribute( 'priority' ); 02315 $type = $this->attribute( 'type' ); 02316 $extension = $this->attribute( 'extension' ); 02317 $installType = $this->attribute( 'install_type' ); 02318 $vendorName = $this->attribute( 'vendor' ); 02319 $source = $this->attribute( 'source' ); 02320 02321 $ezpublishVersion = $this->attribute( 'ezpublish-version' ); 02322 $ezpublishNamedVersion = $this->attribute( 'ezpublish-named-version' ); 02323 02324 $packagingTimestamp = $this->attribute( 'packaging-timestamp' ); 02325 $packagingHost = $this->attribute( 'packaging-host' ); 02326 $packagingPackager = $this->attribute( 'packaging-packager' ); 02327 02328 $maintainers = $this->attribute( 'maintainers' ); 02329 $documents = $this->attribute( 'documents' ); 02330 $groups = $this->attribute( 'groups' ); 02331 02332 $versionNumber = $this->attribute( 'version-number' ); 02333 $releaseNumber = $this->attribute( 'release-number' ); 02334 $releaseTimestamp = $this->attribute( 'release-timestamp' ); 02335 02336 $licence = $this->attribute( 'licence' ); 02337 $state = $this->attribute( 'state' ); 02338 02339 $simpleFileList = $this->attribute( 'simple-file-list' ); 02340 $fileList = $this->attribute( 'file-list' ); 02341 $dependencies = $this->attribute( 'dependencies' ); 02342 $install = $this->attribute( 'install' ); 02343 $uninstall = $this->attribute( 'uninstall' ); 02344 $changelog = $this->attribute( 'changelog' ); 02345 02346 $rootNameTextNode = $dom->createElement( 'name' ); 02347 $rootNameTextNode->appendChild( $dom->createTextNode( $name ) ); 02348 $root->appendChild( $rootNameTextNode ); 02349 02350 if ( $summary ) 02351 { 02352 $rootSummaryTextNode = $dom->createElement( 'summary' ); 02353 $rootSummaryTextNode->appendChild( $dom->createTextNode( $summary ) ); 02354 $root->appendChild( $rootSummaryTextNode ); 02355 } 02356 02357 if ( $description ) 02358 { 02359 $rootDescriptionTextNode = $dom->createElement( 'description' ); 02360 $rootDescriptionTextNode->appendChild( $dom->createTextNode( $description ) ); 02361 $root->appendChild( $rootDescriptionTextNode ); 02362 } 02363 02364 if ( $vendorName ) 02365 { 02366 $rootVendorTextNode = $dom->createElement( 'vendor' ); 02367 $rootVendorTextNode->appendChild( $dom->createTextNode( $vendorName ) ); 02368 $root->appendChild( $rootVendorTextNode ); 02369 } 02370 02371 if ( $priority ) 02372 { 02373 $rootPriorityTextNode = $dom->createElement( 'priority' ); 02374 $rootPriorityTextNode->setAttribute( 'value', $priority ); 02375 $root->appendChild( $rootPriorityTextNode ); 02376 } 02377 02378 if ( $type ) 02379 { 02380 $rootTypeTextNode = $dom->createElement( 'type' ); 02381 $rootTypeTextNode->setAttribute( 'value', $type ); 02382 $root->appendChild( $rootTypeTextNode ); 02383 } 02384 02385 if ( $extension ) 02386 { 02387 $rootExtensionTextNode = $dom->createElement( 'extension' ); 02388 $rootExtensionTextNode->setAttribute( 'name', $extension ); 02389 $root->appendChild( $rootExtensionTextNode ); 02390 } 02391 02392 if ( $source ) 02393 { 02394 $rootSourceTextNode = $dom->createElement( 'source' ); 02395 $rootSourceTextNode->appendChild( $dom->createTextNode( $source ) ); 02396 $root->appendChild( $rootSourceTextNode ); 02397 } 02398 02399 $root->setAttribute( 'install_type', $installType ); 02400 02401 $ezpublishNode = $dom->createElement( 'ezpublish' ); 02402 02403 $ezpublishVersionTextNode = $dom->createElement( 'version' ); 02404 $ezpublishVersionTextNode->appendChild( $dom->createTextNode( $ezpublishVersion ) ); 02405 $ezpublishNode->appendChild( $ezpublishVersionTextNode ); 02406 02407 $ezpublishNamedVersionTextNode = $dom->createElement( 'named-version' ); 02408 $ezpublishNamedVersionTextNode->appendChild( $dom->createTextNode( $ezpublishNamedVersion ) ); 02409 $ezpublishNode->appendChild( $ezpublishNamedVersionTextNode ); 02410 02411 $root->appendChild( $ezpublishNode ); 02412 02413 if ( count( $maintainers ) > 0 ) 02414 { 02415 $maintainersNode = $dom->createElement( 'maintainers' ); 02416 foreach ( $maintainers as $maintainer ) 02417 { 02418 unset( $maintainerNode ); 02419 $maintainerNode = $dom->createElement( 'maintainer' ); 02420 02421 unset( $maintainerName ); 02422 $maintainerName = $dom->createElement( 'name' ); 02423 $maintainerName->appendChild( $dom->createTextNode( $maintainer['name'] ) ); 02424 $maintainerNode->appendChild( $maintainerName ); 02425 02426 unset( $maintainerEmail ); 02427 $maintainerEmail = $dom->createElement( 'email' ); 02428 $maintainerEmail->appendChild( $dom->createTextNode( $maintainer['email'] ) ); 02429 $maintainerNode->appendChild( $maintainerEmail ); 02430 if ( $maintainer['role'] ) 02431 { 02432 unset( $maintainerRole ); 02433 $maintainerRole = $dom->createElement( 'role' ); 02434 $maintainerRole->appendChild( $dom->createTextNode( $maintainer['role'] ) ); 02435 $maintainerNode->appendChild( $maintainerRole ); 02436 } 02437 02438 $maintainersNode->appendChild( $maintainerNode ); 02439 } 02440 $root->appendChild( $maintainersNode ); 02441 } 02442 02443 $packagingNode = $dom->createElement( 'packaging' ); 02444 02445 $packagingTimestampNode = $dom->createElement( 'timestamp' ); 02446 $packagingTimestampNode->appendChild( $dom->createTextNode( $packagingTimestamp ) ); 02447 $packagingNode->appendChild( $packagingTimestampNode ); 02448 02449 $packagingHostNode = $dom->createElement( 'host' ); 02450 $packagingHostNode->appendChild( $dom->createTextNode( $packagingHost ) ); 02451 $packagingNode->appendChild( $packagingHostNode ); 02452 if ( $packagingPackager ) 02453 { 02454 $packagingPackagerNode = $dom->createElement( 'packager' ); 02455 $packagingPackagerNode->appendChild( $dom->createTextNode( $packagingPackager ) ); 02456 $packagingNode->appendChild( $packagingPackagerNode ); 02457 } 02458 02459 $root->appendChild( $packagingNode ); 02460 02461 if ( count( $documents ) > 0 ) 02462 { 02463 $documentsNode = $dom->createElement( 'documents' ); 02464 foreach ( $documents as $document ) 02465 { 02466 unset( $documentNode ); 02467 $documentNode = $dom->createElement( 'document' ); 02468 $documentNode->setAttribute( 'mime-type', $document['mime-type'] ); 02469 $documentNode->setAttribute( 'name', $document['name'] ); 02470 if ( $document['os'] ) 02471 $documentNode->setAttribute( 'os', $document['os'] ); 02472 02473 if ( $document['audience'] ) 02474 $documentNode->setAttribute( 'audience', $document['audience'] ); 02475 02476 $documentsNode->appendChild( $documentNode ); 02477 } 02478 $root->appendChild( $documentsNode ); 02479 } 02480 02481 if ( count( $groups ) > 0 ) 02482 { 02483 $groupsNode = $dom->createElement( 'groups' ); 02484 foreach ( $groups as $group ) 02485 { 02486 unset( $groupNode ); 02487 $groupNode = $dom->createElement( 'group' ); 02488 $groupNode->setAttribute( 'name', $group['name'] ); 02489 $groupsNode->appendChild( $groupNode ); 02490 } 02491 $root->appendChild( $groupsNode ); 02492 } 02493 02494 if ( count( $changelog ) > 0 ) 02495 { 02496 $changelogNode = $dom->createElement( 'changelog' ); 02497 foreach ( $changelog as $changeEntry ) 02498 { 02499 unset( $changeEntryNode ); 02500 $changeEntryNode = $dom->createElement( 'entry' ); 02501 $changeEntryNode->setAttribute( 'timestamp', $changeEntry['timestamp'] ); 02502 $changeEntryNode->setAttribute( 'person', $changeEntry['person'] ); 02503 $changeEntryNode->setAttribute( 'email', $changeEntry['email'] ); 02504 $changeEntryNode->setAttribute( 'release', $changeEntry['release'] ); 02505 02506 foreach ( $changeEntry['changes'] as $change ) 02507 { 02508 unset( $changeEntryChange ); 02509 $changeEntryChange = $dom->createElement( 'change' ); 02510 $changeEntryChange->appendChild( $dom->createTextNode( $change ) ); 02511 $changeEntryNode->appendChild( $changeEntryChange ); 02512 } 02513 $changelogNode->appendChild( $changeEntryNode ); 02514 } 02515 $root->appendChild( $changelogNode ); 02516 } 02517 02518 // Avoid a PHP warning if 'simple-file-list' is not an array 02519 if ( is_array( $this->Parameters['simple-file-list'] ) ) 02520 { 02521 $rootSimpleFiles = $dom->createElement( 'simple-files' ); 02522 foreach( $this->Parameters['simple-file-list'] as $key => $value ) 02523 { 02524 $simpleFileNode = $dom->createElement( 'simple-file' ); 02525 $simpleFileNode->setAttribute( 'key', $key ); 02526 $simpleFileNode->setAttribute( 'original-path', $value['original-path'] ); 02527 $simpleFileNode->setAttribute( 'package-path', $value['package-path'] ); 02528 $rootSimpleFiles->appendChild( $simpleFileNode ); 02529 unset( $simpleFileNode ); 02530 } 02531 $root->appendChild( $rootSimpleFiles ); 02532 } 02533 else 02534 { 02535 $rootSimpleFiles = $dom->createElement( 'simple-files' ); 02536 $root->appendChild( $rootSimpleFiles ); 02537 } 02538 02539 // Handle files 02540 $filesNode = $dom->createElement( 'files' ); 02541 02542 $hasFileItems = false; 02543 foreach ( $fileList as $fileCollectionName => $fileCollection ) 02544 { 02545 if ( count( $fileCollection ) > 0 ) 02546 { 02547 $hasFileItems = true; 02548 02549 unset( $fileCollectionNode ); 02550 $fileCollectionNode = $dom->createElement( 'collection' ); 02551 $fileCollectionNode->setAttribute( 'name', $fileCollectionName ); 02552 02553 unset( $fileLists ); 02554 unset( $fileDesignLists ); 02555 unset( $fileThumbnailLists ); 02556 $fileList = array(); 02557 $fileDesignList = array(); 02558 $fileINIList = array(); 02559 $fileThumbnailList = array(); 02560 $fileListNode = null; 02561 foreach ( $fileCollection as $fileItem ) 02562 { 02563 if ( $fileItem['type'] == 'design' ) 02564 $fileListNode =& $fileDesignLists[$fileItem['design']][$fileItem['role']][$fileItem['role-value']][$fileItem['variable-name']]; 02565 else if ( $fileItem['type'] == 'ini' ) 02566 $fileListNode =& $fileINILists[$fileItem['role']][$fileItem['role-value']][$fileItem['variable-name']]; 02567 else if ( $fileItem['type'] == 'thumbnail' ) 02568 $fileListNode =& $fileThumbnailLists[$fileItem['role']]; 02569 else 02570 $fileListNode =& $fileLists[$fileItem['type']][$fileItem['role']][$fileItem['role-value']][$fileItem['variable-name']]; 02571 02572 if ( !$fileListNode || 02573 $fileListNode->getAttribute( 'type' ) != $fileItem['type'] || 02574 $fileListNode->getAttribute( 'role' ) != $fileItem['role'] || 02575 $fileListNode->getAttribute( 'role-value' ) != $fileItem['role-value'] || 02576 $fileListNode->getAttribute( 'variable-name' ) != $fileItem['variable-name'] ) 02577 { 02578 unset( $fileListNode ); 02579 $fileListNode = $dom->createElement( 'file-list' ); 02580 $fileListNode->setAttribute( 'type', $fileItem['type'] ); 02581 02582 if ( $fileItem['type'] == 'design' ) 02583 $fileListNode->setAttribute( 'design', $fileItem['design'] ); 02584 if ( $fileItem['role'] ) 02585 $fileListNode->setAttribute( 'role', $fileItem['role'] ); 02586 if ( $fileItem['role-value'] ) 02587 $fileListNode->setAttribute( 'role-value', $fileItem['role-value'] ); 02588 if ( $fileItem['variable-name'] ) 02589 $fileListNode->setAttribute( 'variable-name', $fileItem['variable-name'] ); 02590 02591 $fileCollectionNode->appendChild( $fileListNode ); 02592 } 02593 02594 if ( $fileItem['name'] ) 02595 { 02596 unset( $fileListFile ); 02597 $fileListFile = $dom->createElement( 'file' ); 02598 $fileListFile->setAttribute( 'path', $fileItem['path'] ); 02599 $fileListFile->setAttribute( 'name', $fileItem['name'] ); 02600 02601 if ( $fileItem['md5'] ) 02602 $fileListFile->setAttribute( 'md5sum', $fileItem['md5'] ); 02603 02604 if ( $fileItem['subdirectory'] ) 02605 $fileListFile->setAttribute( 'sub-directory', $fileItem['subdirectory'] ); 02606 02607 $fileListNode->appendChild( $fileListFile ); 02608 } 02609 } 02610 $filesNode->appendChild( $fileCollectionNode ); 02611 } 02612 } 02613 if ( $hasFileItems ) 02614 $root->appendChild( $filesNode ); 02615 02616 $versionNode = $dom->createElement( 'version' ); 02617 $versionNumberTextNode = $dom->createElement( 'number' ); 02618 $versionNumberTextNode->appendChild( $dom->createTextNode( $versionNumber ) ); 02619 $versionNode->appendChild( $versionNumberTextNode ); 02620 $versionReleaseNumberTextNode = $dom->createElement( 'release' ); 02621 $versionReleaseNumberTextNode->appendChild( $dom->createTextNode( $releaseNumber ) ); 02622 $versionNode->appendChild( $versionReleaseNumberTextNode ); 02623 $root->appendChild( $versionNode ); 02624 02625 if ( $releaseTimestamp ) 02626 { 02627 $rootTimestampTextNode = $dom->createElement( 'timestamp' ); 02628 $rootTimestampTextNode->appendChild( $dom->createTextNode( $releaseTimestamp ) ); 02629 $root->appendChild( $rootTimestampTextNode ); 02630 } 02631 02632 if ( $licence ) 02633 { 02634 $rootLicenceTextNode = $dom->createElement( 'licence' ); 02635 $rootLicenceTextNode->appendChild( $dom->createTextNode( $licence ) ); 02636 $root->appendChild( $rootLicenceTextNode ); 02637 } 02638 02639 if ( $state ) 02640 { 02641 $rootStateTextNode = $dom->createElement( 'state' ); 02642 $rootStateTextNode->appendChild( $dom->createTextNode( $state ) ); 02643 $root->appendChild( $rootStateTextNode ); 02644 } 02645 02646 $dependencyNode = $dom->createElement( 'dependencies' ); 02647 02648 $providesNode = $dom->createElement( 'provides' ); 02649 $dependencyNode->appendChild( $providesNode ); 02650 $requiresNode = $dom->createElement( 'requires' ); 02651 $dependencyNode->appendChild( $requiresNode ); 02652 $obsoletesNode = $dom->createElement( 'obsoletes' ); 02653 $dependencyNode->appendChild( $obsoletesNode ); 02654 $conflictsNode = $dom->createElement( 'conflicts' ); 02655 $dependencyNode->appendChild( $conflictsNode ); 02656 02657 $this->createDependencyTree( $providesNode, 'provide', $dependencies['provides'] ); 02658 $this->createDependencyTree( $requiresNode, 'require', $dependencies['requires'] ); 02659 $this->createDependencyTree( $obsoletesNode, 'obsolete', $dependencies['obsoletes'] ); 02660 $this->createDependencyTree( $conflictsNode, 'conflict', $dependencies['conflicts'] ); 02661 02662 $root->appendChild( $dependencyNode ); 02663 02664 $installNode = $dom->createElement( 'install' ); 02665 02666 $uninstallNode = $dom->createElement( 'uninstall' ); 02667 02668 $this->createInstallTree( $installNode, $dom, $install, 'install' ); 02669 $this->createInstallTree( $uninstallNode, $dom, $uninstall, 'uninstall' ); 02670 02671 $root->appendChild( $installNode ); 02672 $root->appendChild( $uninstallNode ); 02673 02674 if ( count( $this->InstallData ) > 0 ) 02675 { 02676 $installDataNode = $dom->createElement( 'install-data' ); 02677 foreach ( $this->InstallData as $installDataType => $installData ) 02678 { 02679 if ( count( $installData ) > 0 ) 02680 { 02681 unset( $dataNode ); 02682 $dataNode = $dom->createElement( 'data' ); 02683 $dataNode->setAttribute( 'type', $installDataType ); 02684 $installDataNode->appendChild( $dataNode ); 02685 foreach ( $installData as $installDataName => $installDataValue ) 02686 { 02687 if ( is_array( $installDataValue ) ) 02688 { 02689 unset( $dataArrayNode ); 02690 $dataArrayNode = $dom->createElement( 'array' ); 02691 $dataArrayNode->setAttribute( 'name', $installDataName ); 02692 $dataNode->appendChild( $dataArrayNode ); 02693 foreach ( $installDataValue as $installDataValueName => $installDataValueValue ) 02694 { 02695 unset( $dataArrayElement ); 02696 $dataArrayElement = $dom->createElement( 'element' ); 02697 $dataArrayElement->setAttribute( 'name', $installDataValueName ); 02698 $dataArrayElement->setAttribute( 'value', $installDataValueValue ); 02699 $dataArrayNode->appendChild( $dataArrayElement ); 02700 } 02701 } 02702 else 02703 { 02704 unset( $dataArrayElement ); 02705 $dataArrayElement = $dom->createElement( 'element' ); 02706 $dataArrayElement->setAttribute( 'name', $installDataName ); 02707 $dataArrayElement->setAttribute( 'value', $installDataValue ); 02708 $dataNode->appendChild( $dataArrayElement ); 02709 } 02710 } 02711 } 02712 } 02713 $root->appendChild( $installDataNode ); 02714 } 02715 02716 return $dom; 02717 } 02718 02719 /*! 02720 \private 02721 Creates xml elements as children of the main node \a $installNode. 02722 The install elements are taken from \a $list. 02723 \param $installType Is either \c 'install' or \c 'uninstall' 02724 */ 02725 function createInstallTree( $installNode, $dom, $list, $installType ) 02726 { 02727 foreach ( $list as $installItem ) 02728 { 02729 $type = $installItem['type']; 02730 unset( $installItemNode ); 02731 $installItemNode = $dom->createElement( 'item' ); 02732 $installItemNode->setAttribute( 'type', $type ); 02733 $installNode->appendChild( $installItemNode ); 02734 02735 if ( $installItem['os'] ) 02736 $installItemNode->setAttribute( 'os', $installItem['os'] ); 02737 02738 if ( $installItem['name'] ) 02739 $installItemNode->setAttribute( 'name', $installItem['name'] ); 02740 02741 if ( $installItem['filename'] ) 02742 { 02743 $installItemNode->setAttribute( 'filename', $installItem['filename'] ); 02744 02745 if ( $installItem['sub-directory'] ) 02746 $installItemNode->setAttribute( 'sub-directory', $installItem['sub-directory'] ); 02747 } 02748 else if ( isset( $installItem['content'] ) && $installItem['content'] instanceof DOMElement ) 02749 { 02750 $importedContentNode = $installItemNode->ownerDocument->importNode( $installItem['content'], true ); 02751 $installItemNode->appendChild( $importedContentNode ); 02752 } 02753 02754 $handler = $this->packageHandler( $type ); 02755 if ( $handler ) 02756 { 02757 $handler->createInstallNode( $this, $installItemNode, $installItem, $installType ); 02758 } 02759 } 02760 } 02761 02762 /*! 02763 Creates dependency xml elements as child of $dependenciesNode. 02764 The dependency elements are take from \a $list. 02765 \param $dependencyType Is either \c 'provide', \c 'require', \c 'obsolete' or \c 'conflict' 02766 */ 02767 function createDependencyTree( &$dependenciesNode, $dependencyType, $list ) 02768 { 02769 $dom = $dependenciesNode->ownerDocument; 02770 02771 foreach ( $list as $dependencyItem ) 02772 { 02773 unset( $dependencyNode ); 02774 $dependencyNode = $dom->createElement( $dependencyType ); 02775 $dependencyNode->setAttribute( 'type', $dependencyItem['type'] ); 02776 $dependencyNode->setAttribute( 'name', $dependencyItem['name'] ); 02777 if ( $dependencyItem['value'] ) 02778 $dependencyNode->setAttribute( 'value', $dependencyItem['value'] ); 02779 $dependenciesNode->appendChild( $dependencyNode ); 02780 $handler = $this->packageHandler( $dependencyItem['name'] ); 02781 if ( $handler ) 02782 { 02783 $handler->createDependencyNode( $this, $dependencyNode, $dependencyItem, $dependencyType ); 02784 } 02785 } 02786 } 02787 02788 /*! 02789 \return the package handler object for the handler named \a $handlerName. 02790 */ 02791 static function packageHandler( $handlerName ) 02792 { 02793 if ( !isset( $GLOBALS['eZPackageHandlers'] ) ) 02794 { 02795 $handlers = array(); 02796 } 02797 else 02798 { 02799 $handlers = $GLOBALS['eZPackageHandlers']; 02800 } 02801 $handler = false; 02802 02803 if( isset( $handlers[$handlerName] ) ) 02804 { 02805 $handler = $handlers[$handlerName]; 02806 $handler->reset(); 02807 } 02808 else 02809 { 02810 $optionArray = array( 'iniFile' => 'package.ini', 02811 'iniSection' => 'PackageSettings', 02812 'iniVariable' => 'HandlerAlias', 02813 'handlerIndex' => $handlerName ); 02814 02815 $options = new ezpExtensionOptions( $optionArray ); 02816 02817 $handler = eZExtension::getHandlerClass( $options ); 02818 $handlers[$handlerName] = $handler; 02819 } 02820 02821 $GLOBALS['eZPackageHandlers'] = $handlers; 02822 return $handler; 02823 } 02824 02825 /*! 02826 Append File to package assosiated with key. The file will be available during installation using the same key. 02827 02828 \param key 02829 \param file path 02830 */ 02831 function appendSimpleFile( $key, $filepath ) 02832 { 02833 if ( !isset( $this->Parameters['simple-file-list'] ) ) 02834 { 02835 $this->Parameters['simple-file-list'] = array(); 02836 } 02837 02838 $suffix = eZFile::suffix( $filepath ); 02839 //$sourcePath = $fileInfo['original-path']; 02840 $packagePath = eZPackage::simpleFilesDirectory() . '/' . substr( md5( mt_rand() ), 0, 8 ) . '.' . $suffix; 02841 $destinationPath = $this->path() . '/' . $packagePath; 02842 eZDir::mkdir( eZDir::dirpath( $destinationPath ), false, true ); 02843 02844 //SP DBfile 02845 $fileHandler = eZClusterFileHandler::instance(); 02846 $fileHandler->fileFetch( $filepath ); 02847 02848 eZFileHandler::copy( $filepath, $destinationPath ); 02849 02850 $this->Parameters['simple-file-list'][$key] = array( 'original-path' => $filepath, 02851 'package-path' => $packagePath ); 02852 } 02853 02854 /*! 02855 Get complete path to file by file key 02856 02857 \param file key 02858 02859 \return complete file path 02860 */ 02861 function simpleFilePath( $fileKey ) 02862 { 02863 if ( !isset( $this->Parameters['simple-file-list'] ) ) 02864 { 02865 return false; 02866 } 02867 if ( !isset( $this->Parameters['simple-file-list'][$fileKey] ) ) 02868 { 02869 return false; 02870 } 02871 02872 return $this->path() . '/' . $this->Parameters['simple-file-list'][$fileKey]['package-path']; 02873 } 02874 02875 /** 02876 * Returns package version. 02877 * 02878 * Combines package version number and release number. 02879 * 02880 * \static 02881 * \return Package version (string). 02882 */ 02883 function getVersion() 02884 { 02885 return $this->Parameters['version-number'] . '-' . $this->Parameters['release-number']; 02886 } 02887 02888 /*! 02889 Sets installed/uninstalled state of the package 02890 \param installed 02891 */ 02892 function setInstalled( $installed = true ) 02893 { 02894 if ( $this->Parameters['install_type'] != 'install' ) 02895 return; 02896 02897 $name = $this->Parameters['name']; 02898 $version = $this->getVersion(); 02899 $db = eZDB::instance(); 02900 if ( $installed ) 02901 { 02902 if ( !$this->getInstallState() ) 02903 { 02904 $timestamp = time(); 02905 $db->query( "INSERT INTO ezpackage ( name, version, install_date ) VALUES ( '$name', '$version', '$timestamp' )" ); 02906 $this->isInstalled = true; 02907 } 02908 } 02909 else 02910 { 02911 $db->query( "DELETE FROM ezpackage WHERE name='$name' AND version='$version'" ); 02912 $this->isInstalled = false; 02913 } 02914 } 02915 02916 function isInstalled() 02917 { 02918 return $this->isInstalled; 02919 } 02920 02921 function getInstallState() 02922 { 02923 // TODO installation date 02924 02925 if ( $this->Parameters['install_type'] != 'install' ) 02926 return; 02927 02928 $name = $this->Parameters['name']; 02929 $version = $this->getVersion(); 02930 02931 $db = eZDB::instance(); 02932 $result = $db->arrayQuery( "SELECT count(*) AS count FROM ezpackage WHERE name='$name' AND version='$version'" ); 02933 02934 if ( !count( $result ) ) 02935 return false; 02936 $installed = $result[0]['count'] == '0' ? false : true; 02937 $this->isInstalled = $installed; 02938 return $installed; 02939 } 02940 02941 /*! 02942 \static 02943 Fetch info about languages for packages specified in $packageNameList. 02944 Return ex: array( 'eng-GB', 'rus-RU', ... ); 02945 if $withLanguageNames == true 02946 array( 'eng-GB' => "English", 02947 'rus-RU' => "Russian", 02948 ... ); 02949 */ 02950 static function languageInfoFromPackageList( $packageNameList, $withLanguageNames = false ) 02951 { 02952 $languageInfo = array(); 02953 foreach( $packageNameList as $packageName ) 02954 { 02955 $package = eZPackage::fetch( $packageName, false, false, false ); 02956 if( is_object( $package ) ) 02957 { 02958 $packageLanguageInfo = $package->languageInfo( $withLanguageNames ); 02959 // merge arrays 02960 if( $withLanguageNames ) 02961 { 02962 // we have array like 'locale' => 'name'. can use array_merge 02963 $languageInfo = array_merge( $languageInfo, $packageLanguageInfo ); 02964 } 02965 else 02966 { 02967 foreach( $packageLanguageInfo as $languageLocale ) 02968 { 02969 if( !in_array( $languageLocale, $languageInfo ) ) 02970 { 02971 $languageInfo[] = $languageLocale; 02972 } 02973 } 02974 } 02975 } 02976 else 02977 { 02978 eZDebug::writeWarning( "Unable to fetch package '$packageName'", __METHOD__ ); 02979 } 02980 } 02981 02982 return $languageInfo; 02983 } 02984 02985 /*! 02986 Fetch info about languages for package. 02987 */ 02988 function languageInfo( $withLanguageNames = false ) 02989 { 02990 $langaugeInfo = array(); 02991 02992 $classHandler = eZPackage::packageHandler( 'ezcontentclass' ); 02993 $objectHandler = eZPackage::packageHandler( 'ezcontentobject' ); 02994 02995 $explainClassInfo = array( 'language_info' ); 02996 02997 $packageItems = $this->installItemsList(); 02998 foreach( $packageItems as $item ) 02999 { 03000 $itemLanguageInfo = array(); 03001 03002 if( $item['type'] == 'ezcontentclass' ) 03003 { 03004 $classInfo = $classHandler->explainInstallItem( $this, $item, $explainClassInfo ); 03005 $itemLanguageInfo = isset( $classInfo['language_info'] ) ? $classInfo['language_info'] : array(); 03006 } 03007 else if( $item['type'] == 'ezcontentobject' ) 03008 { 03009 $objectsInfo = $objectHandler->explainInstallItem( $this, $item ); 03010 03011 // merge objects info 03012 foreach( $objectsInfo as $objectInfo ) 03013 { 03014 $objectLanguages = isset( $objectInfo['language_info'] ) ? $objectInfo['language_info'] : array(); 03015 foreach( $objectLanguages as $objectLanguage ) 03016 { 03017 if( !in_array( $objectLanguage, $itemLanguageInfo ) ) 03018 { 03019 $itemLanguageInfo[] = $objectLanguage; 03020 } 03021 } 03022 } 03023 } 03024 03025 // merge class and objects infos 03026 foreach( $itemLanguageInfo as $languageLocale ) 03027 { 03028 if( !in_array( $languageLocale, $langaugeInfo ) ) 03029 { 03030 $langaugeInfo[] = $languageLocale; 03031 } 03032 } 03033 } 03034 03035 if( $withLanguageNames ) 03036 { 03037 $langaugeInfoWithNames = array(); 03038 foreach( $langaugeInfo as $languageLocale ) 03039 { 03040 $language = eZContentLanguage::fetchByLocale( $languageLocale ); 03041 $languageName = $language->attribute( 'name' ); 03042 $langaugeInfoWithNames[$languageLocale] = $languageName; 03043 } 03044 03045 $langaugeInfo = $langaugeInfoWithNames; 03046 } 03047 03048 return $langaugeInfo; 03049 } 03050 03051 function defaultLanguageMap() 03052 { 03053 $languageMap = array(); 03054 $packageLanguages = $this->languageInfo(); 03055 foreach( $packageLanguages as $language ) 03056 { 03057 $languageMap[$language] = $language; 03058 } 03059 03060 return $languageMap; 03061 } 03062 03063 /** 03064 * Checks if a package name is valid 03065 * 03066 * @param string $packageName the package name 03067 * @param string $transformedPackageName the package name, transformed to be valid 03068 * @return boolean true if the package name is valid, false if not 03069 */ 03070 03071 static function isValidName( $packageName, &$transformedPackageName = null ) 03072 { 03073 $trans = eZCharTransform::instance(); 03074 $transformedPackageName = $trans->transformByGroup( $packageName, 'identifier' ); 03075 03076 return $transformedPackageName === $packageName; 03077 } 03078 03079 03080 public $isInstalled = false; 03081 /// \privatesection 03082 /// All interal data 03083 public $Parameters; 03084 /// Controls which data has been modified 03085 } 03086 03087 ?>