oxutilsobject.php

Go to the documentation of this file.
00001 <?php
00002 
00006 class oxUtilsObject extends oxSuperCfg
00007 {
00013     protected $_aClassNameCache = array();
00014 
00020     protected static $_aLoadedArticles = array();
00021 
00027     protected static $_aInstanceCache = array();
00028 
00034     private static $_instance = null;
00035 
00041     public static function getInstance()
00042     {
00043         // disable caching for test modules
00044         if ( defined( 'OXID_PHP_UNIT' ) ) {
00045             self::$_instance = modInstances::getMod( __CLASS__ );
00046         }
00047 
00048         if ( !self::$_instance instanceof oxUtilsObject ) {
00049 
00050             // allow modules
00051             $oUtilsObject = new oxUtilsObject();
00052             self::$_instance = $oUtilsObject->oxNew( 'oxUtilsObject' );
00053 
00054             if ( defined( 'OXID_PHP_UNIT' ) ) {
00055                 modInstances::addMod( __CLASS__, self::$_instance);
00056             }
00057         }
00058         return self::$_instance;
00059     }
00060 
00072     public function oxNew( $sClassName, $sParams = null )
00073     {
00074         $sClassName = strtolower( $sClassName );
00075         $sCacheKey  = ($sParams !== null )?$sClassName.md5( serialize( $sParams ) ):$sClassName;
00076 
00077         if ( !defined( 'OXID_PHP_UNIT' ) ) {
00078             if ( isset( self::$_aInstanceCache[$sCacheKey] ) ) {
00079                 return clone self::$_aInstanceCache[$sCacheKey];
00080             }
00081         }
00082 
00083         // performance
00084         if ( isset( $this->_aClassNameCache[$sClassName] ) ) {
00085             $sActionClassName = $this->_aClassNameCache[$sClassName];
00086         } else {
00087             $sActionClassName = $this->getClassName( $sClassName );
00088             //expect __autoload() (oxfunctions.php) to do its job when class_exists() is called
00089             if ( !class_exists( $sActionClassName ) ) {
00090                 $oEx = new oxSystemComponentException();
00091                 $oEx->setMessage('EXCEPTION_SYSTEMCOMPONENT_CLASSNOTFOUND');
00092                 $oEx->setComponent($sClassName);
00093                 $oEx->debugOut();
00094                 throw $oEx;
00095             }
00096             // performance
00097             $this->_aClassNameCache[$sClassName] = $sActionClassName;
00098         }
00099 
00100         if ( $sParams ) {
00101             $oActionObject = new $sActionClassName( $sParams );
00102         } else {
00103             $oActionObject = new $sActionClassName();
00104         }
00105 
00106         if ( $oActionObject instanceof oxBase ) {
00107             self::$_aInstanceCache[$sCacheKey] = clone $oActionObject;
00108         }
00109 
00110         return $oActionObject;
00111     }
00112 
00121     public function oxNewArticle( $sOxID, $aProperties = array())
00122     {
00123         if ( $sOxID && isset( self::$_aLoadedArticles[$sOxID] ) ) {
00124             return self::$_aLoadedArticles[$sOxID];
00125         }
00126 
00127         $oActionObject = $this->oxNew( 'oxarticle' );
00128 
00129         // adding object prioperties
00130         foreach ( $aProperties as $sPropertyName => $sPropertyVal ) {
00131             $oActionObject->$sPropertyName = $sPropertyVal;
00132         }
00133 
00134         $oActionObject->load( $sOxID );
00135 
00136         self::$_aLoadedArticles[$sOxID] = $oActionObject;
00137         return $oActionObject;
00138     }
00139 
00147     public function resetInstanceCache($sClassName = null)
00148     {
00149         if ($sClassName && isset(self::$_aInstanceCache[$sClassName])) {
00150             unset(self::$_aInstanceCache[$sClassName]);
00151             return;
00152         }
00153 
00154         //looping due to possible memory "leak".
00155         if (is_array(self::$_aInstanceCache)) {
00156             foreach (self::$_aInstanceCache as $sKey => $oInstance) {
00157                 unset(self::$_aInstanceCache[$sKey]);
00158             }
00159         }
00160 
00161         self::$_aInstanceCache = array();
00162     }
00163 
00169     public function generateUId()
00170     {
00171         return substr( $this->getSession()->getId(), 0, 3 ) . substr( md5( uniqid( '', true ).'|'.microtime() ), 0, 29 );
00172     }
00173 
00174 
00182     public function getClassName( $sClassName )
00183     {
00184 
00185         $aModules = $this->getConfig()->getConfigParam( 'aModules' );
00186         if ( is_array( $aModules ) && array_key_exists( $sClassName, $aModules ) ) {
00187             //multiple inheritance implementation
00188             //in case we have multiple modules:
00189             //like oxoutput => sub/suboutput1&sub/suboutput2&sub/suboutput3
00190             $aClassChain = explode( "&", $aModules[$sClassName] );
00191 
00192             $sParent = $sClassName;
00193 
00194             //security: just preventing string termination
00195             $sParent = str_replace(chr(0), '', $sParent);
00196 
00197             //building middle classes if needed
00198             $sClassName = $this->_makeSafeModuleClassParents( $aClassChain, $sParent );
00199         }
00200 
00201         // check if there is a path, if yes, remove it
00202         $sClassName = basename( $sClassName );
00203 
00204         return $sClassName;
00205     }
00206 
00215     public function isModuleActive( $sClassName, $sModuleName )
00216     {
00217         $aModules = $this->getConfig()->getConfigParam( 'aModules' );
00218         if ( is_array( $aModules ) && array_key_exists( $sClassName, $aModules ) ) {
00219             $aClassChain = explode( "&", $aModules[$sClassName] );
00220             foreach ($aClassChain as $sModule) {
00221                 if ( basename($sModule) == $sModuleName ) {
00222                     return true;
00223                 }
00224             }
00225         }
00226         return false;
00227     }
00228 
00239     private function _makeSafeModuleClassParents( $aClassChain, $sBaseModule )
00240     {
00241         $myConfig = $this->getConfig();
00242         $sParent = $sBaseModule;
00243 
00244         //building middle classes if needed
00245         foreach ($aClassChain as $sModule) {
00246             //creating middle classes
00247             //e.g. class suboutput1_parent extends oxoutput {}
00248             //     class suboutput2_parent extends suboutput1 {}
00249             //$sModuleClass = $this->getClassName($sModule);
00250 
00251             //security: just preventing string termination
00252             $sModule = str_replace(chr(0), '', $sModule);
00253 
00254             //get parent and module class names from sub/suboutput2
00255             $sModuleClass = basename($sModule);
00256 
00257             if ( !class_exists( $sModuleClass, false ) ) {
00258                 $sParentClass = basename($sParent);
00259                 //P
00260                 //$sInitClass = "class ".$sModuleClass."_parent extends $sParentClass { function ".$sModuleClass."_parent(){ return ".$sParentClass."::".$sParentClass."();} }";
00261                 $sInitClass = "class ".$sModuleClass."_parent extends $sParentClass {}";
00262 
00263                 //initializing middle class
00264                 if (!class_exists($sModuleClass."_parent", false)) {
00265                     eval($sInitClass);
00266                 }
00267                 $sParentPath = $myConfig->getConfigParam( 'sShopDir' )."/modules/".$sModule.".php";
00268 
00269                 //including original file
00270                 if ( file_exists( $sParentPath ) ) {
00271                     include $sParentPath;
00272                 } elseif ( !class_exists( $sModuleClass ) ) {
00273                     //to avoid problems with unitest and only throw a exception if class does not exists MAFI
00274                     $oEx = new oxSystemComponentException();
00275                     $oEx->setMessage('EXCEPTION_SYSTEMCOMPONENT_CLASSNOTFOUND');
00276                     $oEx->setComponent($sModule);
00277                 }
00278             }
00279 
00280             $sParent = $sModule;
00281         }
00282 
00283         //returning the last module from the chain
00284         $sClassName = $aClassChain[count($aClassChain) - 1];
00285         return $sClassName;
00286     }
00287 }