eZ Publish  [trunk]
ezsiteinstaller.php
Go to the documentation of this file.
00001 <?php
00002 /**
00003  * File containing the eZSiteInstaller class.
00004  *
00005  * @copyright Copyright (C) 1999-2012 eZ Systems AS. All rights reserved.
00006  * @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License v2
00007  * @version //autogentag//
00008  * @package kernel
00009  */
00010 
00011 /*!
00012   \class eZSiteInstaller ezsiteinstaller.php
00013   \ingroup eZUtils
00014   \brief A set of functions to do web-site installation from command-line.
00015 
00016   Helps simplify installation process by providing a set of steps
00017   which will be executed sequentially. This class contains a common functions
00018   which can be reused in particular installations.
00019 
00020 */
00021 
00022 class eZSiteInstaller
00023 {
00024     const ERR_OK = 0;
00025     const ERR_ABORT = 1;
00026     const ERR_CONTINUE = 2;
00027 
00028     function eZSiteInstaller( $parameters = false )
00029     {
00030         $this->initSettings( $parameters );
00031         $this->initSteps();
00032 
00033         $this->LastErrorCode = eZSiteInstaller::ERR_OK;
00034     }
00035 
00036     function &instance( $params )
00037     {
00038         eZDebug::writeWarning( "Your installer doesn't implement 'instance' function", __METHOD__ );
00039         return false;
00040     }
00041 
00042     /*!
00043      Initialize $Settings member with custom values which can be used
00044      in install steps.
00045     */
00046     function initSettings( $parameters )
00047     {
00048         eZDebug::writeWarning( "Your installer doesn't implement 'initSettings' function", __METHOD__ );
00049     }
00050 
00051     /*!
00052      Define install steps
00053      Step definition:
00054          array( '_function' => <function_name>,
00055                 '_params' => array( <param_list> ) )
00056          where '_function' defines function name(which should be implemented within installer class) which will be called,
00057                '_params' is an array of parameters which will be passed to function <function_name>. Note that items of <param_list>
00058                can be defined in the form as <step definition> and this rule can be applied recursively.
00059 
00060      Each function used in step definition should be defined as:
00061      function someFunction( $params )
00062      {
00063         ...
00064         // you code goes here
00065         ...
00066 
00067         // optionally you can set $LastErrorCode to 'eZSiteInstaller::ERR_ABORT' if you want to break installation if some step is failed.
00068         // $this->setLastErrorCode( eZSiteInstaller::ERR_ABORT );
00069      }
00070 
00071      Example:
00072          array( '_function' => 'step_1',
00073                 '_params' => array( 'param_a' => 'foo',
00074                                     'param_b' => array( '_function' => 'helper_function_for_b',
00075                                                         '_params' => array( 'param_b_a' => 'goo',
00076                                                                             'param_b_b' => array( '_function' => 'helper_functin_for_b_b',
00077                                                                                                   '_params' => array( 'param_b_b_a' => 'b_b_a' ) ) ) ) ) );
00078          Execution flow:
00079          - $b_b = helper_function_b_b( array( 'param_b_b_a' => 'b_b_a' ) );
00080          - $b = helper_function_for_b( array( 'param_b_a' => 'goo',
00081                                               'param_b_b' => $b_b ) );
00082          - $result = step_1( array( 'param_a' => 'foo',
00083                                     'param_b' => $b ) );
00084     */
00085     function initSteps()
00086     {
00087         eZDebug::writeWarning( "Your installer doesn't implement 'initSteps' function", __METHOD__ );
00088     }
00089 
00090     /*!
00091      Add setting with $name and $value.
00092     */
00093     function addSetting( $name, $value )
00094     {
00095         $this->Settings[$name] = $value;
00096     }
00097 
00098     /*!
00099      Return value for setting $name.
00100     */
00101     function setting( $name )
00102     {
00103         $value = false;
00104         if( $this->hasSetting( $name ) )
00105         {
00106             $value = $this->Settings[$name];
00107         }
00108         else
00109         {
00110             eZDebug::writeWarning( "Setting '$name' doesn't exist", __METHOD__ );
00111         }
00112 
00113         return $value;
00114     }
00115 
00116     /*!
00117      Return TRUE if setting exist, otherwise FALSE.
00118     */
00119     function hasSetting( $name )
00120     {
00121         $hasSetting = false;
00122         if( isset( $this->Settings[$name] ) )
00123             $hasSetting = true;
00124 
00125         return $hasSetting;
00126     }
00127 
00128     /*!
00129      Return 'post_install' steps
00130     */
00131     function postInstallSteps()
00132     {
00133         return $this->Steps['post_install'];
00134     }
00135 
00136     /*!
00137      Execute 'post_install' steps
00138     */
00139     function postInstall()
00140     {
00141         $steps = $this->postInstallSteps();
00142         $this->executeSteps( $steps );
00143     }
00144 
00145     /*!
00146      Execute $steps
00147     */
00148     function executeSteps( $steps )
00149     {
00150         $stepNum = 1;
00151         foreach( $steps as $step )
00152         {
00153             $this->execFunction( $step );
00154 
00155             if( $this->lastErrorCode() !== eZSiteInstaller::ERR_OK )
00156             {
00157                 $res = $this->handleError();
00158                 if( $res === false )
00159                     $res = $this->defaultErrorHandler();
00160 
00161                 if( $res === eZSiteInstaller::ERR_ABORT )
00162                 {
00163                     $this->reportError( "Aborting execution on step number $stepNum: '". $step['_function'] ."'", 'eZSiteInstaller::postInstall' );
00164                     break;
00165                 }
00166             }
00167 
00168             ++$stepNum;
00169         }
00170     }
00171 
00172     /*!
00173      Execute $function defined in step
00174     */
00175     function execFunction( $function )
00176     {
00177         $functionName = $function['_function'];
00178 
00179         $this->buildFunctionParams( $function['_params'] );
00180 
00181         $result = $this->$functionName( $function['_params'] );
00182 
00183         return $result;
00184     }
00185 
00186     /*!
00187      Prepare parameters for function executed in step definition.
00188     */
00189     function buildFunctionParams( &$params )
00190     {
00191         foreach( array_keys( $params ) as $paramKey )
00192         {
00193             if( $this->isFunctionParam( $params[$paramKey] ) )
00194             {
00195                 $params[$paramKey] = $this->execFunction( $params[$paramKey] );
00196             }
00197             else if( is_array( $params[$paramKey] ) )
00198             {
00199                 $this->buildFunctionParams( $params[$paramKey] );
00200             }
00201         }
00202     }
00203 
00204     /*!
00205      Return TRUE is custom function should be called to prepare params, otherwise FALSE( $param is constant).
00206     */
00207     function isFunctionParam( $param )
00208     {
00209         $isFunction = false;
00210         if( is_array( $param) && isset( $param['_function'] ) )
00211             $isFunction = true;
00212 
00213         return $isFunction;
00214     }
00215 
00216     /*!
00217      Set last error code.
00218     */
00219     function setLastErrorCode( $errCode )
00220     {
00221         $this->LastErrorCode = $errCode;
00222     }
00223 
00224     /*!
00225      Get last error code.
00226     */
00227     function lastErrorCode()
00228     {
00229         return $this->LastErrorCode;
00230     }
00231 
00232     /*!
00233      Set last error code and write error message to debug output
00234      Params:
00235         $text    - error message text;
00236         $caption - error message caption;
00237         $errCode - error code to set;
00238     */
00239     function reportError( $text, $caption, $errCode = eZSiteInstaller::ERR_ABORT )
00240     {
00241         eZDebug::writeError( $text, $caption );
00242 
00243         $this->setLastErrorCode( $errCode );
00244     }
00245 
00246 
00247     //
00248     // Function groups for common use in install steps.
00249     //
00250 
00251     ///////////////////////////////////////////////////////////////////////////
00252     // DB:
00253     //     dbBegin
00254     //     dbCommit
00255     ///////////////////////////////////////////////////////////////////////////
00256 
00257     /*!
00258      Start transaction.
00259     Params:
00260         no params
00261     */
00262     function dbBegin( $params )
00263     {
00264         $db = eZDB::instance();
00265         $db->begin();
00266     }
00267 
00268     /*!
00269      Commit transaction.
00270      Params:
00271         no params
00272     */
00273     function dbCommit( $params )
00274     {
00275         $db = eZDB::instance();
00276         $db->commit();
00277     }
00278 
00279 
00280     ///////////////////////////////////////////////////////////////////////////
00281     // Content class:
00282     //      classIDbyIdentifier
00283     //      classByIdentifier
00284     ///////////////////////////////////////////////////////////////////////////
00285 
00286     /*!
00287      Return ID of the content class.
00288      Params:
00289         'identifier'  - identifier of the class.
00290     */
00291     function classIDbyIdentifier( $params )
00292     {
00293         $classID = false;
00294 
00295         $contentClass = $this->classByIdentifier( $params );
00296 
00297         if( is_object( $contentClass ) )
00298         {
00299             $classID = $contentClass->attribute( 'id' );
00300         }
00301 
00302         return $classID;
00303     }
00304 
00305     /*!
00306      Return content class.
00307      Params:
00308         'identifier'  - identifier of the class.
00309     */
00310     function classByIdentifier( $params )
00311     {
00312         $classIdentifier = $params['identifier'];
00313 
00314         $contentClass = eZContentClass::fetchByIdentifier( $classIdentifier );
00315         if( !is_object( $contentClass ) )
00316         {
00317             eZDebug::writeWarning( "Content class with identifier '$classIdentifier' doesn't exist.", __METHOD__ );
00318         }
00319 
00320         return $contentClass;
00321     }
00322 
00323 
00324     ///////////////////////////////////////////////////////////////////////////
00325     // Content class attributes:
00326     //      removeClassAttribute
00327     //      addClassAttributes
00328     //      updateClassAttributes
00329     ///////////////////////////////////////////////////////////////////////////
00330 
00331     /*!
00332      Remove attribute from the content class
00333      Params:
00334         'class_id'              - ID of content class to remove attribute from;
00335         'attribute_identifier'  - attibute identifier to remove;
00336     */
00337     function removeClassAttribute( $params )
00338     {
00339         $contentClassID = $params['class_id'];
00340         $classAttributeIdentifier = $params['attribute_identifier'];
00341 
00342         // get attributes of 'temporary' version as well
00343         $classAttributeList = eZContentClassAttribute::fetchFilteredList( array( 'contentclass_id' => $contentClassID,
00344                                                                                   'identifier' => $classAttributeIdentifier ),
00345                                                                            true );
00346 
00347         $validation = array();
00348         foreach( $classAttributeList as $classAttribute )
00349         {
00350             $dataType = $classAttribute->dataType();
00351             if( $dataType->isClassAttributeRemovable( $classAttribute ) )
00352             {
00353                 $objectAttributes = eZContentObjectAttribute::fetchSameClassAttributeIDList( $classAttribute->attribute( 'id' ) );
00354                 foreach( $objectAttributes as $objectAttribute )
00355                 {
00356                     $objectAttributeID = $objectAttribute->attribute( 'id' );
00357                     $objectAttribute->removeThis( $objectAttributeID );
00358                 }
00359 
00360                 $classAttribute->removeThis();
00361             }
00362             else
00363             {
00364                 $removeInfo = $dataType->classAttributeRemovableInformation( $classAttribute );
00365                 if( $removeInfo === false )
00366                     $removeInfo = "Unknow reason";
00367 
00368                 $validation[] = array( 'id' => $classAttribute->attribute( 'id' ),
00369                                        'identifier' => $classAttribute->attribute( 'identifier' ),
00370                                        'reason' => $removeInfo );
00371             }
00372         }
00373 
00374         if( count( $validation ) > 0 )
00375         {
00376             $this->reportError( $validation, 'eZSiteInstaller::removeClassAttribute: Unable to remove eZClassAttribute(s)' );
00377         }
00378 
00379     }
00380 
00381     /*!
00382      Add attribute to the content class
00383      Params:
00384         array( 'class' => array( 'identifier' => optional, string: identifire of content class; see 'id';
00385                                  'id' => optional, ID of content class. if set it's used instead of 'class_identifier' to speed up things.
00386                                          you must supply either 'class_identifier' or 'class_id'; ),
00387                'attributes' => array( array( 'identifier' => attibute identifier,
00388                                              'name' => attribute name,
00389                                              'data_type_string' => attribute datatype,
00390                                              'default_value' => optional, attribute default value, default is 'false'
00391                                              'can_translate' => optional, default '1'
00392                                              'is_required' => optional, default '0'
00393                                              'is_searchable' => optional, default '0'
00394                                              'content' => optional, attribute content ),
00395                                       ...
00396                                     );
00397     */
00398     function addClassAttributes( $params )
00399     {
00400         $classInfo = $params['class'];
00401         $attributesInfo = $params['attributes'];
00402 
00403         $classID = isset( $classInfo['id'] ) ? $classInfo['id'] : false;
00404         if( $classID )
00405         {
00406             $class = eZContentClass::fetch( $classID );
00407         }
00408         else
00409         {
00410             if( isset( $classInfo['identifier'] ) )
00411             {
00412                 $class = eZSiteInstaller::classByIdentifier( $classInfo );
00413             }
00414             else
00415             {
00416                 $this->reportError( "neither 'id' nor 'identifier' is set for content class" ,
00417                                     'eZSiteInstaller::addClassAttribute' );
00418             }
00419         }
00420 
00421         if( !is_object( $class ) )
00422         {
00423             $this->reportError( "Can't fetch content class" ,
00424                                 'eZSiteInstaller::addClassAttribute' );
00425             return;
00426         }
00427 
00428         $classID = $class->attribute( 'id' );
00429 
00430         foreach( $attributesInfo as $attributeInfo )
00431         {
00432             $classAttributeIdentifier = $attributeInfo['identifier'];
00433             $classAttributeName = $attributeInfo['name'];
00434             $datatype = $attributeInfo['data_type_string'];
00435             $defaultValue = isset( $attributeInfo['default_value'] ) ? $attributeInfo['default_value'] : false;
00436             $canTranslate = isset( $attributeInfo['can_translate'] ) ? $attributeInfo['can_translate'] : 1;
00437             $isRequired   = isset( $attributeInfo['is_required']   ) ? $attributeInfo['is_required'] : 0;
00438             $isSearchable = isset( $attributeInfo['is_searchable'] ) ? $attributeInfo['is_searchable'] : 0;
00439             $attrContent  = isset( $attributeInfo['content'] ) ? $attributeInfo['content'] : false;
00440 
00441             $attrCreateInfo = array( 'identifier' => $classAttributeIdentifier,
00442                                      'name' => $classAttributeName,
00443                                      'can_translate' => $canTranslate,
00444                                      'is_required' => $isRequired,
00445                                      'is_searchable' => $isSearchable );
00446             $newAttribute = eZContentClassAttribute::create( $classID, $datatype, $attrCreateInfo  );
00447 
00448             $dataType = $newAttribute->dataType();
00449             $dataType->initializeClassAttribute( $newAttribute );
00450 
00451             // not all datatype can have 'default_value'. do check here.
00452             if( $defaultValue !== false  )
00453             {
00454                 switch( $datatype )
00455                 {
00456                     case 'ezboolean':
00457                     {
00458                         $newAttribute->setAttribute( 'data_int3', $defaultValue );
00459                     }
00460                     break;
00461 
00462                     default:
00463                         break;
00464                 }
00465             }
00466 
00467             if( $attrContent )
00468                 $newAttribute->setContent( $attrContent );
00469 
00470             // store attribute, update placement, etc...
00471             $attributes = $class->fetchAttributes();
00472             $attributes[] = $newAttribute;
00473 
00474             // remove temporary version
00475             if ( $newAttribute->attribute( 'id' ) !== null )
00476             {
00477                 $newAttribute->remove();
00478             }
00479 
00480             $newAttribute->setAttribute( 'version', eZContentClass::VERSION_STATUS_DEFINED );
00481             $newAttribute->setAttribute( 'placement', count( $attributes ) );
00482 
00483             $class->adjustAttributePlacements( $attributes );
00484             foreach( $attributes as $attribute )
00485             {
00486                 $attribute->storeDefined();
00487             }
00488 
00489             // update objects
00490             $classAttributeID = $newAttribute->attribute( 'id' );
00491             $objects = eZContentObject::fetchSameClassList( $classID );
00492             foreach( $objects as $object )
00493             {
00494                 $contentobjectID = $object->attribute( 'id' );
00495                 $objectVersions = $object->versions();
00496                 foreach( $objectVersions as $objectVersion )
00497                 {
00498                     $translations = $objectVersion->translations( false );
00499                     $version = $objectVersion->attribute( 'version' );
00500                     foreach( $translations as $translation )
00501                     {
00502                         $objectAttribute = eZContentObjectAttribute::create( $classAttributeID, $contentobjectID, $version );
00503                         $objectAttribute->setAttribute( 'language_code', $translation );
00504                         $objectAttribute->initialize();
00505                         $objectAttribute->store();
00506                         $objectAttribute->postInitialize();
00507                     }
00508                 }
00509             }
00510         }
00511     }
00512 
00513     /*!
00514      Update class attribute data. Currently only attribute 'name' is supported.
00515      Params:
00516         'class'      - array( 'identifier' - identifire of content class );
00517         'attributes  - array( array( 'identifier'  - attibute identifier to update;
00518                                      'new_name'    - new attribute name ),
00519                               ...
00520                             );
00521     */
00522     function updateClassAttributes( $params )
00523     {
00524         $classInfo = $params['class'];
00525         $attributesInfo = $params['attributes'];
00526 
00527         $contentClassID = eZSiteInstaller::classIDbyIdentifier( $classInfo );
00528         if( $contentClassID )
00529         {
00530             foreach( $attributesInfo as $attributeInfo )
00531             {
00532                 $attributeIdentifier = $attributeInfo['identifier'];
00533                 $name = isset( $attributeInfo['new_name'] ) ? $attributeInfo['new_name'] : false;
00534 
00535                 $classAttributeList = eZContentClassAttribute::fetchFilteredList( array( 'contentclass_id' => $contentClassID,
00536                                                                                          'identifier' => $attributeIdentifier ),
00537                                                                                   true );
00538                 foreach( $classAttributeList as $attribute )
00539                 {
00540                     if( $name !== false )
00541                     {
00542                         $attribute->setName( $name );
00543                     }
00544 
00545                     $attribute->store();
00546                 }
00547             }
00548         }
00549     }
00550 
00551 
00552     ///////////////////////////////////////////////////////////////////////////
00553     // Content object:
00554     //      contentObjectByUrl
00555     //      contentObjectByName
00556     //      createContentObject
00557     //      removeContentObject
00558     //      renameContentObject
00559     ///////////////////////////////////////////////////////////////////////////
00560 
00561     /*!
00562      Return content object by path identification string of its node.
00563      Params:
00564         'location'  - path_identification_string of the node.
00565     */
00566     function contentObjectByUrl( $params )
00567     {
00568         $object = false;
00569 
00570         $node = $this->nodeByUrl( $params );
00571         if( is_object( $node ) )
00572         {
00573             $object = $node->object();
00574         }
00575 
00576         return $object;
00577     }
00578 
00579     /*!
00580      Create content object.
00581      Params:
00582         class_identifier    - identifier of class;
00583         location            - path identification string of parent node;
00584         attributes          - array with object attributes;
00585     */
00586     function createContentObject( $params )
00587     {
00588         $objectID = false;
00589 
00590         $classIdentifier = $params['class_identifier'];
00591         $location = $params['location'];
00592         $attributesData = $params['attributes'];
00593 
00594         $parentNode = $this->nodeByUrl( $params );
00595         if( is_object( $parentNode ) )
00596         {
00597             $parentNodeID = $parentNode->attribute( 'node_id' );
00598             $object = eZContentFunctions::createAndPublishObject( array( 'parent_node_id' => $parentNodeID,
00599                                                                          'class_identifier' => $classIdentifier,
00600                                                                          'attributes' => $attributesData ) );
00601 
00602             if( is_object( $object ) )
00603             {
00604                 $objectID = $object->attribute( 'id' );
00605             }
00606         }
00607 
00608         return $objectID;
00609     }
00610 
00611     /*!
00612      Change name of content object.
00613      Params:
00614         contentobject_id        - ID of object;
00615         name                    - new object name;
00616     */
00617     function renameContentObject( $params )
00618     {
00619         $contentObjectID = $params['contentobject_id'];
00620         $newName = $params['name'];
00621         $object = eZContentObject::fetch( $contentObjectID );
00622         if( !is_object( $object ) )
00623             return false;
00624         $object->rename( $newName );
00625     }
00626 
00627     /*!
00628      Return content object. The first object is returned in case if several objects have the same name.
00629      Params:
00630         'name'      - object's name to look up;
00631         'class_id'  - optional, ID of content class;
00632     */
00633     function contentObjectByName( $params )
00634     {
00635         $objectName = $params['name'];
00636         $classID = isset( $params['class_id'] ) ? $params['class_id'] : false;
00637 
00638         //build up the conditions
00639         $conditions = array( 'name' => $objectName );
00640 
00641         if( $classID )
00642             array_merge( $conditions, array( 'contentclass_id' => $classID ) );
00643 
00644         $objectList = eZContentObject::fetchList( true, $conditions, 0, 1 );
00645 
00646         $object = false;
00647         if( count( $objectList ) > 0 )
00648             $object = $objectList[0];
00649 
00650         return $object;
00651     }
00652 
00653     /*!
00654      Remove content object.
00655         Params: see 'contentObjectByName'
00656     */
00657     function removeContentObject( $params )
00658     {
00659         $object = $this->contentObjectByName( $params );
00660         if( is_object( $object ) )
00661         {
00662             $object->purge();
00663         }
00664         else
00665         {
00666             eZDebug::writeWarning( "Object with name '" . $params['name'] . "' doesn't exist", __METHOD__ );
00667         }
00668     }
00669 
00670 
00671 
00672     ///////////////////////////////////////////////////////////////////////////
00673     // Content object attributes:
00674     //      updateObjectAttributeFromString
00675     //      updateContentObjectAttributes
00676     ///////////////////////////////////////////////////////////////////////////
00677 
00678     /*!
00679      Update contentObjectAttribute with value specified in string.
00680      The object can be specified either by ID or by path identification string
00681      of its node.
00682      Params:
00683         object_id                   - optional, ID of object to update;
00684         location                    - optional, path to node with object;
00685         class_attribute_identifier  - an identifier of attribute to update;
00686         string                      - new attribute value;
00687     */
00688     function updateObjectAttributeFromString( $params )
00689     {
00690         $objectID = isset( $params['object_id'] ) ? $params['object_id'] : false;
00691         $location = isset( $params['location'] ) ? $params['location'] : false;
00692         $classAttrIdentifier = $params['class_attribute_identifier'];
00693         $stringParam = $params['string'];
00694 
00695         $contentObject = false;
00696         if( $objectID )
00697         {
00698             $contentObject = eZContentObject::fetch( $objectID );
00699             if( !is_object( $contentObject ) )
00700             {
00701                 $this->reportError( "Content object with id '$objectID' doesn't exist." , 'eZSiteInstaller::updateObjectAttributeFromString' );
00702             }
00703         }
00704         else if( $location )
00705         {
00706             $contentObject = $this->contentObjectByUrl( array( 'location' => $location ) );
00707         }
00708 
00709         if( is_object( $contentObject ) )
00710         {
00711             $attributes = $contentObject->contentObjectAttributes();
00712             if( count( $attributes ) > 0 )
00713             {
00714                 $objectAttribute = false;
00715                 foreach( $attributes as $attribute )
00716                 {
00717                     if( $attribute->attribute( 'contentclass_attribute_identifier' ) == $classAttrIdentifier )
00718                     {
00719                         $objectAttribute = $attribute;
00720                         break;
00721                     }
00722                 }
00723 
00724                 if( is_object( $objectAttribute ) )
00725                 {
00726                     $objectAttribute->fromString( $stringParam );
00727                     $objectAttribute->store();
00728                 }
00729                 else
00730                 {
00731                     $this->reportError( "Content object with id '$objectID' doesn't have attribute with contentClassAttribute identifier '$classAttrIdentifier'." , 'eZSiteInstaller::updateObjectAttributeFromString' );
00732                 }
00733             }
00734             else
00735             {
00736                 $this->reportError( "Content object with id '$objectID' doesn't have attributes." , 'eZSiteInstaller::updateObjectAttributeFromString' );
00737             }
00738         }
00739     }
00740 
00741 
00742     function updateContentObjectAttributes( $params )
00743     {
00744         $objectID = $params['object_id'];
00745         $attributesData = $params['attributes_data'];
00746 
00747         $contentObject = eZContentObject::fetch( $objectID );
00748         if( !is_object( $contentObject ) )
00749         {
00750             $this->reportError( "Content object with id '$objectID' doesn't exist." , 'eZSiteInstaller::updateContentObjectAttributes' );
00751             return;
00752         }
00753 
00754         $dataMap = $contentObject->dataMap();
00755         foreach( $attributesData as $attrIdentifier => $attrData )
00756         {
00757             $attribute = $dataMap[$attrIdentifier];
00758             if( !is_object( $attribute ) )
00759             {
00760                 $this->reportError( "Warning: could not acquire attribute with identifier '$attrIdentifier'.",
00761                                     'eZSiteInstaller::updateContentObjectAttributes',
00762                                     eZSiteInstaller::ERR_CONTINUE );
00763                 continue;
00764             }
00765 
00766             //get datatype name
00767             $datatypeString = $attribute->attribute( 'data_type_string' );
00768 
00769             switch( $datatypeString )
00770             {
00771                 case 'ezstring':
00772                 {
00773                     $attribute->setAttribute( "data_text", $attrData['DataText']);
00774                 } break;
00775 
00776                 case 'ezxmltext':
00777                 {
00778                     $xml = '<?xml version="1.0" encoding="utf-8"?>'."\n".
00779                            '<section xmlns:image="http://ez.no/namespaces/ezpublish3/image/"'."\n".
00780                            '         xmlns:xhtml="http://ez.no/namespaces/ezpublish3/xhtml/"'."\n".
00781                            '         xmlns:custom="http://ez.no/namespaces/ezpublish3/custom/">'."\n".
00782                            '  <section>'."\n";
00783                     {
00784                         $xml .= '    <paragraph>';
00785                         $numSentences = mt_rand( ( int ) $attributeParameters['min_sentences'], ( int ) $attributeParameters['max_sentences'] );
00786                         for( $sentence = 0; $sentence < $numSentences; $sentence++ )
00787                         {
00788                             if( $sentence != 0 )
00789                             {
00790                                 $xml .= ' ';
00791                             }
00792                         }
00793                         $xml .= "</paragraph>\n";
00794                     }
00795                     $xml .= "  </section>\n</section>\n";
00796 
00797                     $attribute->setAttribute( 'data_text', $xml );
00798                 } break;
00799 
00800                 case 'eztext':
00801                 {
00802                     $attribute->setAttribute( 'data_text', $attrData['DataText'] );
00803                 } break;
00804 
00805                 case 'ezmatrix':
00806                 {
00807                     $columnsCount = count( $attrData["MatrixDefinition"]->attribute( 'columns' ) );
00808                     if( $columnsCount > 0 )
00809                     {
00810                         $rowsCount = count( $attrData["MatrixCells"] ) / $columnsCount;
00811 
00812                         $tempMatrix = new eZMatrix( $attrData["MatrixTitle"], $rowsCount, $attrData["MatrixDefinition"] );
00813                         $tempMatrix->Cells = $attrData["MatrixCells"];
00814 
00815                         $attribute->setAttribute( 'data_text', $tempMatrix->xmlString() );
00816                         $tempMatrix->decodeXML( $attribute->attribute( 'data_text' ) );
00817 
00818                         $attribute->setContent( $tempMatrix );
00819                     }
00820                     else
00821                     {
00822                         $this->reportError( "Number of columns in 'ezmatrix' should be greater then zero",
00823                                             'eZSiteInstaller::updateContentObjectAttributes',
00824                                             eZSiteInstaller::ERR_CONTINUE );
00825                     }
00826 
00827                 } break;
00828 
00829                 case 'ezboolean':
00830                 {
00831                     $attribute->setAttribute( 'data_int', $attrData['DataInt'] );
00832                 } break;
00833 
00834                 case 'ezinteger':
00835                 {
00836                     $attribute->setAttribute( 'data_int', $attrData['DataInt'] );
00837                 } break;
00838 
00839                 case 'ezfloat':
00840                 {
00841                     $power = 100;
00842                     $float = mt_rand( $power * ( int ) $attrData['Min'], $power * ( int ) $attrData['Max'] );
00843                     $float = $float / $power;
00844                     $attribute->setAttribute( 'data_float', $float );
00845                 } break;
00846 
00847                 case 'ezprice':
00848                 {
00849                     $power = 10;
00850                     $price = mt_rand( $power * ( int ) $attrData['Min'], $power * ( int ) $attrData['Max'] );
00851                     $price = $price / $power;
00852                     $attribute->setAttribute( 'data_float', $price );
00853                 } break;
00854 
00855                 case 'ezurl':
00856                 {
00857                     $attribute->setContent( $attrData['Content'] );
00858                     $attribute->setAttribute( "data_text", $attrData['DataText']);
00859                 } break;
00860 
00861                 case 'ezuser':
00862                 {
00863                     $user = $attribute->content();
00864                     if( $user === null )
00865                     {
00866                         $user = eZUser::create( $objectID );
00867                     }
00868 
00869                     $user->setInformation( $objectID,
00870                                            md5( time() . '-' . mt_rand() ),
00871                                            md5( time() . '-' . mt_rand() ) . '@ez.no',
00872                                            'publish',
00873                                            'publish' );
00874                     $user->store();
00875                 } break;
00876             }
00877             $attribute->store();
00878         }
00879 
00880         $contentObject->store();
00881     }
00882 
00883 
00884     ///////////////////////////////////////////////////////////////////////////
00885     // Content object tree node:
00886     //      nodeByUrl
00887     //      nodeByName
00888     //      nodeIdByName
00889     //      nodePathStringByURL
00890     //      moveTreeNode
00891     //      swapNodes
00892     ///////////////////////////////////////////////////////////////////////////
00893 
00894     /*!
00895      Return 'path_string' attribute of the node.
00896      Params:
00897         'location'  - path_identification_string of the node.
00898     */
00899     function nodePathStringByURL( $params )
00900     {
00901         $pathString = '';
00902 
00903         $node = $this->nodeByUrl( $params );
00904 
00905         if( is_object( $node ) )
00906         {
00907             $pathString = $node->attribute( 'path_string' );
00908         }
00909 
00910         return $pathString;
00911     }
00912 
00913     /*!
00914      Return node.
00915      Params:
00916         'location'  - path_identification_string of the node.
00917     */
00918     function nodeByUrl( $params )
00919     {
00920         $path_identification_string = $params['location'];
00921 
00922         $node = eZContentObjectTreeNode::fetchByURLPath( $path_identification_string );
00923 
00924         if( !is_object( $node ) )
00925         {
00926             $this->reportError( "The node '$path_identification_string' doesn't exist", 'eZSiteInstaller::nodeByUrl' );
00927         }
00928 
00929         return $node;
00930     }
00931 
00932     /*
00933      Return 'main' node ID of object which has specifued name. For more info see 'contentObjectByName'
00934      Params:
00935         See 'contentObjectByName'
00936     */
00937     function nodeIdByName( $params )
00938     {
00939         $node = $this->nodeByName( $params );
00940 
00941         $id = false;
00942         if( is_object( $node ) )
00943             $id = $node->attribute( 'node_id' );
00944 
00945         return $id;
00946     }
00947 
00948     /*
00949      Return 'main' node of object which has specifued name. For more info see 'contentObjectByName'
00950      Params:
00951         See 'contentObjectByName'
00952     */
00953     function nodeByName( $params )
00954     {
00955         $node = false;
00956 
00957         $contentObject = $this->contentObjectByName( $params );
00958         if( is_object( $contentObject ) )
00959             $node = $contentObject->attribute( 'main_node' );
00960 
00961         return $node;
00962     }
00963 
00964     /*!
00965      Move node.
00966         Params:
00967             'node'          -   array( 'name'       => object's name to move,
00968                                        'class_id'   => optional, object's content class ID );
00969 
00970             'parent_node'   -   array( 'name'       => parent object's name to move;
00971                                        'class_id'   => optional, parent object's content class ID );
00972     */
00973     function moveTreeNode( $params )
00974     {
00975         $nodeID = $this->nodeIdByName( $params['node'] );
00976         $parentNodeID = $this->nodeIdByName( $params['parent_node'] );
00977 
00978         $result = eZContentObjectTreeNodeOperations::move( $nodeID, $parentNodeID );
00979 
00980         return $result;
00981     }
00982 
00983     /*!
00984      Swap two nodes.
00985      It's a copy/paste from kernel/content/action.php
00986     */
00987     function swapNodes( $params )
00988     {
00989         $nodeInfo1 = $params['src_node'];
00990         $nodeInfo2 = $params['dst_node'];
00991 
00992         //init vars
00993         $node1 = $this->nodeIdByName( $nodeInfo1 );
00994         $node2 = $this->nodeIdByName( $nodeInfo2 );
00995 
00996         $nodeID = $node1;
00997         $node = eZContentObjectTreeNode::fetch( $nodeID );
00998 
00999         if( !is_object( $node ) )
01000         {
01001             $this->reportError( "Can't fetch node '$nodeID'", 'eZSiteInstaller::swapNodes' );
01002             return false;
01003         }
01004 
01005         if( !$node->canSwap() )
01006         {
01007             $this->reportError( "Cannot swap node '$nodeID' (no edit permission)", 'eZSiteInstaller::swapNodes' );
01008             return false;
01009         }
01010 
01011         $nodeParentNodeID = $node->attribute( 'parent_node_id' );
01012 
01013         $object = $node->object();
01014         if( !is_object( $object ) )
01015         {
01016             $this->reportError( "Cannot fetch object for node '$nodeID'", 'eZSiteInstaller::swapNodes' );
01017             return false;
01018         }
01019 
01020         $objectID = $object->attribute( 'id' );
01021         $objectVersion = $object->attribute( 'current_version' );
01022         $class = $object->contentClass();
01023         $classID = $class->attribute( 'id' );
01024 
01025         $selectedNodeID = $node2;
01026 
01027         $selectedNode = eZContentObjectTreeNode::fetch( $selectedNodeID );
01028 
01029         if( !is_object( $selectedNode ) )
01030         {
01031             $this->reportError( "Cannot fetch node '$selectedNodeID'", 'eZSiteInstaller::swapNodes' );
01032             return false;
01033         }
01034 
01035         if( !$selectedNode->canSwap() )
01036         {
01037             $this->reportError( "Cannot use node $selectedNodeID as the exchanging node for $nodeID, the current user does not have edit permission for it",
01038                                 'eZSiteInstaller::swapNodes' );
01039             return false;
01040         }
01041 
01042         // clear cache.
01043         eZContentCacheManager::clearContentCacheIfNeeded( $objectID );
01044 
01045         $selectedObject = $selectedNode->object();
01046         $selectedObjectID = $selectedObject->attribute( 'id' );
01047         $selectedObjectVersion = $selectedObject->attribute( 'current_version' );
01048         $selectedNodeParentNodeID = $selectedNode->attribute( 'parent_node_id' );
01049 
01050 
01051         /* In order to swap node1 and node2 a user should have the following permissions:
01052          * 1. move_from: move node1
01053          * 2. move_from: move node2
01054          * 3. move_to: move an object of the same class as node2 under parent of node1
01055          * 4. move_to: move an object of the same class as node1 under parent of node2
01056          *
01057          * The First two has already been checked. Let's check the rest.
01058          */
01059         $nodeParent            = $node->attribute( 'parent' );
01060         $selectedNodeParent    = $selectedNode->attribute( 'parent' );
01061         $objectClassID         = $object->attribute( 'contentclass_id' );
01062         $selectedObjectClassID = $selectedObject->attribute( 'contentclass_id' );
01063 
01064         if( !$nodeParent || !$selectedNodeParent )
01065         {
01066             $this->reportError( "No $nodeParent or no !$selectedNodeParent received.",
01067                                 'eZSiteInstaller::swapNodes' );
01068             return false;
01069         }
01070 
01071         if( !$nodeParent->canMoveTo( $selectedObjectClassID ) )
01072         {
01073             $this->reportError( "Cannot move an object of class $selectedObjectClassID to node $nodeParentNodeID (no create permission)",
01074                                 'eZSiteInstaller::swapNodes' );
01075             return false;
01076         }
01077 
01078         if( !$selectedNodeParent->canMoveTo( $objectClassID ) )
01079         {
01080             $this->reportError( "Cannot move an object of class $objectClassID to node $selectedNodeParentNodeID (no create permission)",
01081                                 'eZSiteInstaller::swapNodes' );
01082             return false;
01083         }
01084 
01085         // exchange contentobject ids and versions.
01086         $node->setAttribute( 'contentobject_id', $selectedObjectID );
01087         $node->setAttribute( 'contentobject_version', $selectedObjectVersion );
01088 
01089         $db = eZDB::instance();
01090         $db->begin();
01091         $node->store();
01092         $selectedNode->setAttribute( 'contentobject_id', $objectID );
01093         $selectedNode->setAttribute( 'contentobject_version', $objectVersion );
01094         $selectedNode->store();
01095 
01096         // modify path string
01097         $changedOriginalNode = eZContentObjectTreeNode::fetch( $nodeID );
01098         $changedOriginalNode->updateSubTreePath();
01099         $changedTargetNode = eZContentObjectTreeNode::fetch( $selectedNodeID );
01100         $changedTargetNode->updateSubTreePath();
01101 
01102         // modify section
01103         if( $changedOriginalNode->attribute( 'main_node_id' ) == $changedOriginalNode->attribute( 'node_id' ) )
01104         {
01105             $changedOriginalObject = $changedOriginalNode->object();
01106             $parentObject = $nodeParent->object();
01107             if( $changedOriginalObject->attribute( 'section_id' ) != $parentObject->attribute( 'section_id' ) )
01108             {
01109 
01110                 eZContentObjectTreeNode::assignSectionToSubTree( $changedOriginalNode->attribute( 'main_node_id' ),
01111                                                                  $parentObject->attribute( 'section_id' ),
01112                                                                  $changedOriginalObject->attribute( 'section_id' ) );
01113             }
01114         }
01115         if( $changedTargetNode->attribute( 'main_node_id' ) == $changedTargetNode->attribute( 'node_id' ) )
01116         {
01117             $changedTargetObject = $changedTargetNode->object();
01118             $selectedParentObject = $selectedNodeParent->object();
01119             if( $changedTargetObject->attribute( 'section_id' ) != $selectedParentObject->attribute( 'section_id' ) )
01120             {
01121 
01122                 eZContentObjectTreeNode::assignSectionToSubTree( $changedTargetNode->attribute( 'main_node_id' ),
01123                                                                  $selectedParentObject->attribute( 'section_id' ),
01124                                                                  $changedTargetObject->attribute( 'section_id' ) );
01125             }
01126         }
01127 
01128         $db->commit();
01129 
01130         // clear cache for new placement.
01131         eZContentCacheManager::clearContentCacheIfNeeded( $objectID );
01132 
01133         return true;
01134     }
01135 
01136     ///////////////////////////////////////////////////////////////////////////
01137     // Roles and policies:
01138     //      assignUserToRole
01139     //      addPoliciesForRole
01140     //      removePoliciesForRole
01141     ///////////////////////////////////////////////////////////////////////////
01142 
01143     /*!
01144      Assign user to role.
01145      Params:
01146         location    - path to user node where user object is located;
01147         role_name   - name of role to assign;
01148     */
01149     function assignUserToRole( $params )
01150     {
01151         $location = $params['location'];
01152         $roleName = $params['role_name'];
01153 
01154         $node = $this->nodeByUrl( $params );
01155         if( is_object( $node ) )
01156         {
01157             $role = eZRole::fetchByName( $roleName );
01158             if( is_object( $role ) )
01159                 $role->assignToUser( $node->attribute( 'contentobject_id' ) );
01160         }
01161     }
01162 
01163     /*!
01164      Add policies from role
01165      Params:
01166         role_name       - name of role;
01167         policies        - array of policies to remove. Each item is an
01168                           array of policy definition: array( 'module' =>
01169                                                              'function' =>
01170                                                              ['limitation'] => );
01171        create_role      - boolean, optional. If TRUE - will create new role if it doesn't exist.
01172                           Default is TRUE.
01173     */
01174     function addPoliciesForRole( $params )
01175     {
01176         $roleName = $params['role_name'];
01177         $policiesDefinition = $params['policies'];
01178         $createRoleIfNotExists = isset( $params['create_role'] ) ? $params['create_role'] : true;
01179 
01180         $role = eZRole::fetchByName( $roleName );
01181         if( is_object( $role ) || $createRoleIfNotExists )
01182         {
01183             if( !is_object( $role ) )
01184             {
01185                 $role = eZRole::create( $roleName );
01186                 $role->store();
01187             }
01188 
01189             $roleID = $role->attribute( 'id' );
01190             if( count( $policiesDefinition ) > 0 )
01191             {
01192                 foreach( $policiesDefinition as $policyDefinition )
01193                 {
01194                     if( isset( $policyDefinition['limitation'] ) )
01195                     {
01196                         $role->appendPolicy( $policyDefinition['module'], $policyDefinition['function'], $policyDefinition['limitation'] );
01197                     }
01198                     else
01199                     {
01200                         $role->appendPolicy( $policyDefinition['module'], $policyDefinition['function'] );
01201                     }
01202                 }
01203             }
01204         }
01205         else
01206         {
01207             $this->reportError( "Role '$roleName' doesn't exist." , 'eZSiteInstaller::addPoliciesToRole' );
01208         }
01209     }
01210 
01211     /*!
01212      Remove policies from role
01213      Params:
01214         role_name       - name of role;
01215         policies        - array of policies to remove. Each item is an
01216                           array of policy definition: array( 'module' => ,
01217                                                              'function' => );
01218        remove_role      - boolean, optional. If TRUE - empty(without policies) role will be removed.
01219                           Default is TRUE.
01220     */
01221     function removePoliciesForRole( $params )
01222     {
01223         $roleName = $params['role_name'];
01224         $policiesDefinition = $params['policies'];
01225         $removeRoleIfEmpty = isset( $params['remove_role'] ) ? $params['remove_role'] : true;
01226 
01227         $role = eZRole::fetchByName( $roleName );
01228         if( is_object( $role ) )
01229         {
01230             foreach( $policiesDefinition as $policyDefinition )
01231             {
01232                 $role->removePolicy( $policyDefinition['module'], $policyDefinition['function'] );
01233             }
01234 
01235             if( $removeRoleIfEmpty && count( $role->policyList() ) == 0 )
01236             {
01237                 $role->removeThis();
01238             }
01239         }
01240         else
01241         {
01242             $this->reportError( "Role '$roleName' doesn't exist." , 'eZSiteInstaller::removePoliciesForRole' );
01243         }
01244     }
01245 
01246 
01247     ///////////////////////////////////////////////////////////////////////////
01248     // Section:
01249     //      sectionIDbyName
01250     //      createContentSection
01251     //      setSection
01252     ///////////////////////////////////////////////////////////////////////////
01253 
01254     /*!
01255      Return ID of the section.
01256      Params:
01257         'section_name'  - name of the section
01258     */
01259     function sectionIDbyName( $params )
01260     {
01261         $sectionID = false;
01262         $sectionName = $params['section_name'];
01263 
01264         $sectionList = eZSection::fetchFilteredList( array( 'name' => $sectionName ), false, false, true );
01265 
01266         if( is_array( $sectionList ) && count( $sectionList ) > 0 )
01267         {
01268             $section = $sectionList[0];
01269             if( is_object( $section ) )
01270             {
01271                 $sectionID = $section->attribute( 'id' );
01272             }
01273         }
01274 
01275         return $sectionID;
01276     }
01277 
01278     /*!
01279      Create new content section.
01280      Params:
01281         'name'                          - string: section name;
01282         'navigation_part_identifier'    - string: identifier of navigation part;
01283     */
01284     function createContentSection( $params )
01285     {
01286         $section = false;
01287 
01288         $sectionName = $params['name'];
01289         $navigationPart = $params['navigation_part_identifier'];
01290 
01291         $section = new eZSection( array() );
01292         $section->setAttribute( 'name', $sectionName );
01293         $section->setAttribute( 'navigation_part_identifier', $navigationPart );
01294         $section->store();
01295 
01296         return $section;
01297     }
01298 
01299     /*!
01300      Assign section to subtree.
01301      Params:
01302         'section_name'    - string: section name;
01303         'location'        - string: path_identification_string of the node(root node of subtree);
01304     */
01305     function setSection( $params )
01306     {
01307         $location = $params['location'];
01308         $sectionName = $params['section_name'];
01309 
01310         $sectionID = $this->sectionIDbyName( $params );
01311         if( $sectionID )
01312         {
01313             $rootNode = $this->nodeByUrl( $params );
01314             if( is_object( $rootNode ) )
01315             {
01316                 eZContentObjectTreeNode::assignSectionToSubTree( $rootNode->attribute( 'node_id' ), $sectionID );
01317             }
01318         }
01319 
01320     }
01321 
01322 
01323     ///////////////////////////////////////////////////////////////////////////
01324     // RSS:
01325     //      setRSSExport
01326     ///////////////////////////////////////////////////////////////////////////
01327 
01328     /*!
01329      Create rss export.
01330     */
01331     function setRSSExport( $params )
01332     {
01333 
01334 
01335         // Create default rssExport object to use
01336         $rssExport = eZRSSExport::create( $params['creator'] );
01337         $rssExport->setAttribute( 'access_url', $params['access_url'] );
01338         $rssExport->setAttribute( 'main_node_only', $params['main_node_only'] );
01339         $rssExport->setAttribute( 'number_of_objects', $params['number_of_objects'] );
01340         $rssExport->setAttribute( 'rss_version', $params['rss_version'] );
01341         $rssExport->setAttribute( 'status', $params['status'] );
01342         $rssExport->setAttribute( 'title', $params['title'] );
01343         $rssExport->store();
01344 
01345         $rssExportID = $rssExport->attribute( 'id' );
01346 
01347         foreach( $params['rss_export_itmes'] as $item )
01348         {
01349             // Create One empty export item
01350             $rssExportItem = eZRSSExportItem::create( $rssExportID );
01351             $rssExportItem->setAttribute( 'class_id', $item['class_id'] );
01352             $rssExportItem->setAttribute( 'description', $item['description'] );
01353             $rssExportItem->setAttribute( 'source_node_id', $item['source_node_id'] );
01354             $rssExportItem->setAttribute( 'status', $item['status'] );
01355             $rssExportItem->setAttribute( 'title', $item['title'] );
01356             if ( isset( $item['enclosure'] ) )
01357             {
01358                 $rssExportItem->setAttribute( 'enclosure', $item['enclosure'] );
01359             }
01360             $rssExportItem->store();
01361         }
01362     }
01363 
01364 
01365     ///////////////////////////////////////////////////////////////////////////
01366     // Package:
01367     //      packageFileItemPath
01368     ///////////////////////////////////////////////////////////////////////////
01369 
01370     /*!
01371      Return path for package item.
01372     */
01373     function packageFileItemPath( $params )
01374     {
01375         $collection = $params['collection'];
01376         $fileItem = $params['file_item'];
01377 
01378         $filePath = $fileItem['name'];
01379 
01380         $package = $this->setting( 'package_object' );
01381         if( is_object( $package ) )
01382         {
01383             $filePath = $package->fileItemPath( $fileItem, $collection );
01384         }
01385         else
01386         {
01387             eZDebug::writeWarning( "'Package' object is not set", __METHOD__ );
01388         }
01389 
01390         return $filePath;
01391     }
01392 
01393     ///////////////////////////////////////////////////////////////////////////
01394     // Languages and Locales:
01395     //      languageNameListFromLocaleList
01396     //      languageNameFromLocale
01397     ///////////////////////////////////////////////////////////////////////////
01398 
01399     /*!
01400      Build array of language names from locale list.
01401      Example: array( 'eng-GB', 'rus-RU' ) => array( 'eng', 'rus' )
01402     */
01403     function languageNameListFromLocaleList( $localeList )
01404     {
01405         $languageList = array();
01406         foreach( $localeList as $locale )
01407             $languageList[] = $this->languageNameFromLocale( $locale );
01408 
01409         return $languageList;
01410     }
01411 
01412     /*!
01413      Return language name from locale string.
01414      Example: 'rus' from 'rus-RU'
01415     */
01416     function languageNameFromLocale( $locale )
01417     {
01418          $pos = strpos( $locale , "-");
01419          $languageName = substr( $locale , 0, $pos );
01420          return $languageName;
01421     }
01422 
01423     /*!
01424      Helper function used for extracting hostname from the given \param $uri
01425     */
01426     public function extractHostname( $uri )
01427     {
01428         $hostname = false;
01429 
01430         $parts = parse_url( $uri );
01431 
01432         if ( isset( $parts['host'] ) )
01433             $hostname = $parts['host'];
01434 
01435         return $hostname;
01436     }
01437 
01438     /*!
01439      Create siteaccess urls for additional user siteacceses using info about access type(host, post, uri)
01440      Params:
01441         'siteaccess_list'         - list of siteaccess names to build urls;
01442         'access_type'             - access type: port, hostname, url;
01443         'access_type_value'       - access type value provided by setup wizard
01444         'exclude_port_list'       - optional, ports to skip. used if 'access_type' is 'port';
01445         'host'                    - host name
01446         'host_prepend_siteaccess' - optional, boolean which instructs to prepend the site access name or not to the value of 'host', by default true
01447     */
01448     function createSiteaccessUrls( $params )
01449     {
01450         $urlList = array();
01451 
01452         $siteaccessList = $params['siteaccess_list'];
01453         $accessType = $params['access_type'];
01454         $accessTypeValue = $params['access_type_value'];
01455 
01456         $excludePortList = isset( $params['exclude_port_list'] ) ? $params['exclude_port_list'] : array();
01457 
01458         $hostname = false;
01459 
01460         if ( isset( $params['host'] ) && $params['host'] !== '' )
01461             $hostname = $this->extractHostname( $params['host'] );
01462 
01463         if ( !$hostname )
01464             $hostname = eZSys::hostname();
01465 
01466         $indexFile = eZSys::wwwDir() . eZSys::indexFileName();
01467 
01468         switch( $accessType )
01469         {
01470             case 'port':
01471                 {
01472                     $port = $accessTypeValue;
01473 
01474                     // build urls
01475                     foreach( $siteaccessList as $siteaccess )
01476                     {
01477                         // skip ports which are already in use
01478                         while( in_array( $port, $excludePortList ) )
01479                             ++$port;
01480 
01481                         $urlList[$siteaccess]['url'] = "$hostname:$port" . $indexFile;
01482                         $urlList[$siteaccess]['port'] = $port;
01483                         ++$port;
01484                     }
01485                 }
01486                 break;
01487             case 'host':
01488             case 'hostname':
01489                 {
01490                     $prependSiteAccess = isset( $params['host_prepend_siteaccess'] ) && is_bool( $params['host_prepend_siteaccess'] ) ? $params['host_prepend_siteaccess'] : true;
01491 
01492                     $hostname = $this->extractHostname( $accessTypeValue );
01493 
01494                     if ( !$hostname )
01495                         $hostname = $accessTypeValue;
01496 
01497                     foreach( $siteaccessList as $siteaccess )
01498                     {
01499                         if ( $prependSiteAccess )
01500                         {
01501                             // replace undescores with dashes( '_' -> '-' );
01502                             $hostPrefix = preg_replace( '/(_)/', '-', $siteaccess);
01503 
01504                             // create url and host
01505                             $urlList[$siteaccess]['url'] = $hostPrefix . '.' . $hostname . $indexFile;
01506                             $urlList[$siteaccess]['host'] = $hostPrefix . '.' . $hostname;
01507                         }
01508                         else
01509                         {
01510                             // create url and host
01511                             $urlList[$siteaccess]['url'] = $hostname . $indexFile;
01512                             $urlList[$siteaccess]['host'] = $hostname;
01513                         }
01514                     }
01515                 }
01516                 break;
01517             case 'url':
01518             case 'uri':
01519                 {
01520                     foreach( $siteaccessList as $siteaccess )
01521                     {
01522                         $urlList[$siteaccess]['url'] = $hostname . $indexFile . '/' . $siteaccess;
01523                     }
01524                 }
01525                 break;
01526 
01527             default:
01528                 break;
01529         }
01530 
01531         return $urlList;
01532     }
01533 
01534     /*!
01535      Create localized siteaccess: copy general setting form 'source' siteaccess, apply new custom settings(locale, others...).
01536     */
01537     function createSiteAccess( $params )
01538     {
01539         $srcSiteaccess = $params['src']['siteaccess'];
01540         $dstSiteaccess = $params['dst']['siteaccess'];
01541         $dstSettings   = isset( $params['dst']['settings'] ) ? $params['dst']['settings'] : array();
01542 
01543         // Create the siteaccess directory
01544         $srcSiteaccessDir = "settings/siteaccess/" . $srcSiteaccess;
01545         $dstSiteaccessDir = "settings/siteaccess/" . $dstSiteaccess;
01546         eZDir::mkdir( $dstSiteaccessDir, false, true );
01547         eZDir::copy( $srcSiteaccessDir, $dstSiteaccessDir, false, true );
01548 
01549         // Update settings
01550         foreach ( $dstSettings as $iniFile => $settingGroups )
01551         {
01552             $ini = eZINI::instance( $iniFile . ".append.php", $dstSiteaccessDir, null, false, null, true );
01553 
01554             foreach ( $settingGroups as $settingGroup => $settings )
01555             {
01556                 foreach ( $settings as $name => $value )
01557                 {
01558                     $ini->setVariable( $settingGroup, $name, $value );
01559                 }
01560             }
01561 
01562             $ini->save(  false, false, false, false, true, true );
01563             unset( $ini );
01564         }
01565 
01566         // Create roles
01567         $role = eZRole::fetchByName( "Anonymous" );
01568         $role->appendPolicy( "user", "login", array( "SiteAccess" => array( eZSys::ezcrc32( $dstSiteaccess ) ) ) );
01569         $role->store();
01570     }
01571 
01572     function solutionVersion()
01573     {
01574         eZDebug::writeWarning( "Your installer doesn't implement 'solutionVersion' function", __METHOD__ );
01575         return false;
01576     }
01577 
01578     function solutionName()
01579     {
01580         eZDebug::writeWarning( "Your installer doesn't implement 'solutionName' function", __METHOD__ );
01581         return false;
01582     }
01583 
01584     /*!
01585      Set solution name and version into db.
01586      Params:
01587         not used
01588     */
01589     function setVersion( $params = false )
01590     {
01591         $db = eZDB::instance();
01592 
01593         $name = strtolower( $this->solutionName() );
01594         $version = $this->solutionVersion();
01595 
01596         $result = $db->query( "INSERT INTO ezsite_data VALUES( '$name', '$version' )" );
01597 
01598         return $result;
01599     }
01600 
01601     function updateINIFiles( $params )
01602     {
01603         foreach( $params['groups'] as $settingsData )
01604         {
01605             $iniFilename = $settingsData['name'] . '.append.php';
01606             $ini = eZINI::instance( $iniFilename, $params['settings_dir'] );
01607             if( isset( $settingsData['discard_old_values'] ) && $settingsData['discard_old_values'] )
01608                 $ini->reset();
01609 
01610             // Ignore site.ini[eZINISettings].ReadonlySettingList[] settings when saving ini variables.
01611             $ini->setReadOnlySettingsCheck( false );
01612             $ini->setVariables( $settingsData['settings'] );
01613             $ini->save();
01614         }
01615     }
01616 
01617     function updateRoles( $params )
01618     {
01619         foreach( $params['roles'] as $roleData )
01620         {
01621             $roleName = $roleData['name'];
01622             $role = eZRole::fetchByName( $roleName );
01623             if( !is_object( $role ) )
01624             {
01625                 $role = eZRole::create( $roleName );
01626                 $role->store();
01627             }
01628 
01629             $roleID = $role->attribute( 'id' );
01630             if( isset( $roleData['policies'] ) )
01631             {
01632                 $policies = $roleData['policies'];
01633                 foreach( $policies as $policy )
01634                 {
01635                     $role->appendPolicy( $policy['module'], $policy['function'], isset( $policy['limitation'] ) ? $policy['limitation'] : array() );
01636                 }
01637             }
01638 
01639             if( isset( $roleData['assignments'] ) )
01640             {
01641                 $roleAssignments = $roleData['assignments'];
01642                 foreach( $roleAssignments as $roleAssignment )
01643                 {
01644                     $assignmentIdentifier = false;
01645                     $assignmentValue = false;
01646                     if( isset( $roleAssignment['limitation'] ) )
01647                     {
01648                         $assignmentIdentifier = $roleAssignment['limitation']['identifier'];
01649                         $assignmentValue = $roleAssignment['limitation']['value'];
01650                     }
01651                     $role->assignToUser( $roleAssignment['user_id'], $assignmentIdentifier, $assignmentValue );
01652                 }
01653             }
01654         }
01655     }
01656 
01657     function updatePreferences( $params )
01658     {
01659         foreach( $params['prefs'] as $prefEntry )
01660         {
01661             $prefUserID = $prefEntry['user_id'];
01662             foreach( $prefEntry['preferences'] as $pref )
01663             {
01664                 $prefName = $pref['name'];
01665                 $prefValue = $pref['value'];
01666                 eZPreferences::setValue( $prefName, $prefValue, $prefUserID );
01667             }
01668         }
01669     }
01670 
01671     /*!
01672      \static
01673      Return a value from $params hash.
01674      Return $defaultValue is value is not set.
01675      $name - a key in $params hash. $name can point to 2-dimensional array.
01676      example: $name = 'foo' will return $params['foo'];
01677               $name = 'foo/boo' will return  $params['foo']['boo']
01678 
01679     */
01680     function getParam( $params, $name, $defaultValue = false )
01681     {
01682         $value = $defaultValue;
01683 
01684         $pos = strpos( $name, '/' );
01685         if( $pos !== false )
01686         {
01687             $dim1 = substr( $name, 0, $pos );
01688             $dim2 = substr( $name, $pos + 1 );
01689             if( isset( $params[$dim1][$dim2] ) )
01690             {
01691                 $value = $params[$dim1][$dim2];
01692             }
01693         }
01694         else if( isset( $params[$name] ) )
01695         {
01696             $value = $params[$name];
01697         }
01698 
01699         return $value;
01700     }
01701 
01702     /*!
01703      Default error handler
01704     */
01705     function defaultErrorHandler()
01706     {
01707         return $this->lastErrorCode();
01708     }
01709 
01710     /*!
01711      Virtual function to re-implement in derived classes to handle error.
01712      Default error handler will be called if returns FALSE.
01713     */
01714     function handleError()
01715     {
01716         // call default error handler
01717         return false;
01718     }
01719 
01720     // store data to use in your steps.
01721     public $Settings;
01722     // define an order of functions to execute.
01723     public $Steps;
01724     // hold an error code of last executed step.
01725     public $LastErrorCode;
01726 }
01727 
01728 ?>