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