oxmodulelist.php

Go to the documentation of this file.
00001 <?php
00002 
00009 class oxModuleList extends oxSuperCfg
00010 {
00011 
00018     protected $_aModules = array();
00019 
00025     protected $_aModuleExtensions = null;
00026 
00032     protected $_aSkipFiles = array('functions.php', 'vendormetadata.php');
00033 
00039     public function getList()
00040     {
00041         return $this->_aModules;
00042     }
00043 
00049     public function getModulesWithExtendedClass()
00050     {
00051         return $this->getConfig()->getModulesWithExtendedClass();
00052     }
00053 
00059     public function getActiveModuleInfo()
00060     {
00061         $aModulePaths = $this->getModulePaths();
00062 
00063         // Extract module paths from extended classes
00064         if (!is_array($aModulePaths) || count($aModulePaths) < 1) {
00065             $aModulePaths = $this->extractModulePaths();
00066         }
00067 
00068         $aDisabledModules = $this->getDisabledModules();
00069         if (is_array($aDisabledModules) && count($aDisabledModules) > 0 && count($aModulePaths) > 0) {
00070             $aModulePaths = array_diff_key($aModulePaths, array_flip($aDisabledModules));
00071         }
00072 
00073         return $aModulePaths;
00074     }
00075 
00081     public function getDisabledModuleInfo()
00082     {
00083         $aDisabledModules = $this->getDisabledModules();
00084         $aModulePaths = array();
00085 
00086         if (is_array($aDisabledModules) && count($aDisabledModules) > 0) {
00087             $aModulePaths = $this->getModulePaths();
00088 
00089             // Extract module paths from extended classes
00090             if (!is_array($aModulePaths) || count($aModulePaths) < 1) {
00091                 $aModulePaths = $this->extractModulePaths();
00092             }
00093 
00094             if (is_array($aModulePaths) || count($aModulePaths) > 0) {
00095                 $aModulePaths = array_intersect_key($aModulePaths, array_flip($aDisabledModules));
00096             }
00097         }
00098 
00099         return $aModulePaths;
00100     }
00101 
00107     public function getModuleVersions()
00108     {
00109         return $this->getConfig()->getConfigParam('aModuleVersions');
00110     }
00111 
00117     public function getModules()
00118     {
00119         return $this->getConfig()->getConfigParam('aModules');
00120     }
00121 
00127     public function getDisabledModules()
00128     {
00129         return (array) $this->getConfig()->getConfigParam('aDisabledModules');
00130     }
00131 
00137     public function getModulePaths()
00138     {
00139         return $this->getConfig()->getConfigParam('aModulePaths');
00140     }
00141 
00147     public function getModuleEvents()
00148     {
00149         return (array) $this->getConfig()->getConfigParam('aModuleEvents');
00150     }
00151 
00157     public function extractModulePaths()
00158     {
00159         $aModules = $this->getModulesWithExtendedClass();
00160         $aModulePaths = array();
00161 
00162         if (is_array($aModules) && count($aModules) > 0) {
00163             foreach ($aModules as $aModuleClasses) {
00164                 foreach ($aModuleClasses as $sModule) {
00165                     $sModuleId = substr($sModule, 0, strpos($sModule, "/"));
00166                     $aModulePaths[$sModuleId] = $sModuleId;
00167                 }
00168             }
00169         }
00170 
00171         return $aModulePaths;
00172     }
00173 
00179     public function getModuleFiles()
00180     {
00181         return (array) $this->getConfig()->getConfigParam('aModuleFiles');
00182     }
00183 
00189     public function getModuleTemplates()
00190     {
00191         return $this->getConfig()->getConfigParam('aModuleTemplates');
00192     }
00193 
00202     public function getDisabledModuleClasses()
00203     {
00204         $aDisabledModules = $this->getDisabledModules();
00205         $aModules = $this->getModulesWithExtendedClass();
00206         $aModulePaths = $this->getModulePaths();
00207 
00208         $aDisabledModuleClasses = array();
00209         if (isset($aDisabledModules) && is_array($aDisabledModules)) {
00210             //get all disabled module paths
00211             foreach ($aDisabledModules as $sId) {
00212                 $sPath = $aModulePaths[$sId];
00213                 if (!isset($sPath)) {
00214                     $sPath = $sId;
00215                 }
00216                 foreach ($aModules as $aModuleClasses) {
00217                     foreach ($aModuleClasses as $sModuleClass) {
00218                         if (strpos($sModuleClass, $sPath . "/") === 0) {
00219                             $aDisabledModuleClasses[] = $sModuleClass;
00220                         }
00221                     }
00222                 }
00223             }
00224         }
00225 
00226         return $aDisabledModuleClasses;
00227     }
00228 
00232     public function cleanup()
00233     {
00234         $aDeletedModules = $this->getDeletedExtensions();
00235 
00236         //collecting deleted extension IDs
00237         $aDeletedModuleIds = array_keys($aDeletedModules);
00238 
00239         // removing from aModules config array
00240         $this->_removeExtensions($aDeletedModuleIds);
00241 
00242         // removing from aDisabledModules array
00243         $this->_removeFromDisabledModulesArray($aDeletedModuleIds);
00244 
00245         // removing from aModulePaths array
00246         $this->_removeFromModulesPathsArray($aDeletedModuleIds);
00247 
00248         // removing from aModuleEvents array
00249         $this->_removeFromModulesEventsArray($aDeletedModuleIds);
00250 
00251         // removing from aModuleVersions array
00252         $this->_removeFromModulesVersionsArray($aDeletedModuleIds);
00253 
00254         // removing from aModuleFiles array
00255         $this->_removeFromModulesFilesArray($aDeletedModuleIds);
00256 
00257         // removing from aModuleTemplates array
00258         $this->_removeFromModulesTemplatesArray($aDeletedModuleIds);
00259 
00260         //removing from config tables and templates blocks table
00261         $this->_removeFromDatabase($aDeletedModuleIds);
00262     }
00263 
00269     public function getDeletedExtensions()
00270     {
00271         $oModuleValidatorFactory = $this->getModuleValidatorFactory();
00272         $oModuleMetadataValidator = $oModuleValidatorFactory->getModuleMetadataValidator();
00273         $aModulesIds = $this->getModuleIds();
00274         $oModule = $this->getModule();
00275         $aDeletedExt = array();
00276 
00277         foreach ($aModulesIds as $sModuleId) {
00278             $oModule->setModuleData(array('id' => $sModuleId));
00279             if (!$oModuleMetadataValidator->validate($oModule)) {
00280                 $aDeletedExt[$sModuleId]['files'] = array($sModuleId . '/metadata.php');
00281             } else {
00282                 $aInvalidExtensions = $this->_getInvalidExtensions($sModuleId);
00283                 if ($aInvalidExtensions) {
00284                     $aDeletedExt[$sModuleId]['extensions'] = $aInvalidExtensions;
00285                 }
00286             }
00287         }
00288 
00289         return $aDeletedExt;
00290     }
00291 
00301     public function diffModuleArrays($aAllModuleArray, $aRemModuleArray)
00302     {
00303         if (is_array($aAllModuleArray) && is_array($aRemModuleArray)) {
00304             foreach ($aAllModuleArray as $sClass => $aModuleChain) {
00305                 if (!is_array($aModuleChain)) {
00306                     $aModuleChain = array($aModuleChain);
00307                 }
00308                 if (isset($aRemModuleArray[$sClass])) {
00309                     if (!is_array($aRemModuleArray[$sClass])) {
00310                         $aRemModuleArray[$sClass] = array($aRemModuleArray[$sClass]);
00311                     }
00312                     $aAllModuleArray[$sClass] = array();
00313                     foreach ($aModuleChain as $sModule) {
00314                         if (!in_array($sModule, $aRemModuleArray[$sClass])) {
00315                             $aAllModuleArray[$sClass][] = $sModule;
00316                         }
00317                     }
00318                     if (!count($aAllModuleArray[$sClass])) {
00319                         unset ($aAllModuleArray[$sClass]);
00320                     }
00321                 } else {
00322                     $aAllModuleArray[$sClass] = $aModuleChain;
00323                 }
00324             }
00325         }
00326 
00327         return $aAllModuleArray;
00328     }
00329 
00337     public function buildModuleChains($aModuleArray)
00338     {
00339         $aModules = array();
00340         if (is_array($aModuleArray)) {
00341             foreach ($aModuleArray as $sClass => $aModuleChain) {
00342                 $aModules[$sClass] = implode('&', $aModuleChain);
00343             }
00344         }
00345 
00346         return $aModules;
00347     }
00348 
00354     public function getModule()
00355     {
00356         return oxNew('oxModule');
00357     }
00358 
00364     protected function _removeExtensions($aModuleIds)
00365     {
00366         $aModuleExtensions = $this->getModulesWithExtendedClass();
00367         $aExtensionsToDelete = array();
00368         foreach ($aModuleIds as $sModuleId) {
00369             $aExtensionsToDelete = array_merge_recursive($aExtensionsToDelete, $this->getModuleExtensions($sModuleId));
00370         }
00371 
00372         $aUpdatedExtensions = $this->diffModuleArrays($aModuleExtensions, $aExtensionsToDelete);
00373         $aUpdatedExtensionsChains = $this->buildModuleChains($aUpdatedExtensions);
00374 
00375         $this->getConfig()->saveShopConfVar('aarr', 'aModules', $aUpdatedExtensionsChains);
00376     }
00377 
00383     protected function _removeFromDisabledModulesArray($aDeletedExtIds)
00384     {
00385         $oConfig = $this->getConfig();
00386         $aDisabledExtensionIds = $this->getDisabledModules();
00387         $aDisabledExtensionIds = array_diff($aDisabledExtensionIds, $aDeletedExtIds);
00388         $oConfig->saveShopConfVar('arr', 'aDisabledModules', $aDisabledExtensionIds);
00389     }
00390 
00396     protected function _removeFromModulesPathsArray($aDeletedModule)
00397     {
00398         $aModulePaths = $this->getModulePaths();
00399 
00400         foreach ($aDeletedModule as $sDeletedModuleId) {
00401             if (isset($aModulePaths[$sDeletedModuleId])) {
00402                 unset($aModulePaths[$sDeletedModuleId]);
00403             }
00404         }
00405 
00406         $this->getConfig()->saveShopConfVar('aarr', 'aModulePaths', $aModulePaths);
00407     }
00408 
00414     protected function _removeFromModulesVersionsArray($aDeletedModule)
00415     {
00416         $aModuleVersions = $this->getModuleVersions();
00417 
00418         foreach ($aDeletedModule as $sDeletedModuleId) {
00419             if (isset($aModuleVersions[$sDeletedModuleId])) {
00420                 unset($aModuleVersions[$sDeletedModuleId]);
00421             }
00422         }
00423 
00424         $this->getConfig()->saveShopConfVar('aarr', 'aModuleVersions', $aModuleVersions);
00425     }
00426 
00432     protected function _removeFromModulesEventsArray($aDeletedModule)
00433     {
00434         $aModuleEvents = $this->getModuleEvents();
00435 
00436         foreach ($aDeletedModule as $sDeletedModuleId) {
00437             if (isset($aModuleEvents[$sDeletedModuleId])) {
00438                 unset($aModuleEvents[$sDeletedModuleId]);
00439             }
00440         }
00441 
00442         $this->getConfig()->saveShopConfVar('aarr', 'aModuleEvents', $aModuleEvents);
00443     }
00444 
00450     protected function _removeFromModulesFilesArray($aDeletedModule)
00451     {
00452         $aModuleFiles = $this->getModuleFiles();
00453 
00454         foreach ($aDeletedModule as $sDeletedModuleId) {
00455             if (isset($aModuleFiles[$sDeletedModuleId])) {
00456                 unset($aModuleFiles[$sDeletedModuleId]);
00457             }
00458         }
00459 
00460         $this->getConfig()->saveShopConfVar('aarr', 'aModuleFiles', $aModuleFiles);
00461     }
00462 
00468     protected function _removeFromModulesTemplatesArray($aDeletedModule)
00469     {
00470         $aModuleTemplates = $this->getModuleTemplates();
00471 
00472         foreach ($aDeletedModule as $sDeletedModuleId) {
00473             if (isset($aModuleTemplates[$sDeletedModuleId])) {
00474                 unset($aModuleTemplates[$sDeletedModuleId]);
00475             }
00476         }
00477 
00478         $this->getConfig()->saveShopConfVar('aarr', 'aModuleTemplates', $aModuleTemplates);
00479     }
00480 
00488     protected function _removeFromDatabase($aDeletedExtIds)
00489     {
00490         if (!is_array($aDeletedExtIds) || !count($aDeletedExtIds)) {
00491             return;
00492         }
00493 
00494         $oDb = oxDb::getDb();
00495 
00496         $aConfigIds = $sDelExtIds = array();
00497         foreach ($aDeletedExtIds as $sDeletedExtId) {
00498             $aConfigIds[] = $oDb->quote('module:' . $sDeletedExtId);
00499             $sDelExtIds[] = $oDb->quote($sDeletedExtId);
00500         }
00501 
00502         $sConfigIds = implode(', ', $aConfigIds);
00503         $sDelExtIds = implode(', ', $sDelExtIds);
00504 
00505         $aSql[] = "DELETE FROM oxconfig where oxmodule IN ($sConfigIds)";
00506         $aSql[] = "DELETE FROM oxconfigdisplay where oxcfgmodule IN ($sConfigIds)";
00507         $aSql[] = "DELETE FROM oxtplblocks where oxmodule IN ($sDelExtIds)";
00508 
00509         foreach ($aSql as $sQuery) {
00510             $oDb->execute($sQuery);
00511         }
00512     }
00513 
00523     public function getModulesFromDir($sModulesDir, $sVendorDir = null)
00524     {
00525         $sModulesDir = oxRegistry::get('oxUtilsFile')->normalizeDir($sModulesDir);
00526 
00527         foreach (glob($sModulesDir . '*') as $sModuleDirPath) {
00528 
00529             $sModuleDirPath .= (is_dir($sModuleDirPath)) ? '/' : '';
00530             $sModuleDirName = basename($sModuleDirPath);
00531 
00532             // skipping some file
00533             if (in_array($sModuleDirName, $this->_aSkipFiles) || (!is_dir($sModuleDirPath) && substr($sModuleDirName, -4) != ".php")) {
00534                 continue;
00535             }
00536 
00537             if ($this->_isVendorDir($sModuleDirPath)) {
00538                 // scanning modules vendor directory
00539                 $this->getModulesFromDir($sModuleDirPath, basename($sModuleDirPath));
00540             } else {
00541                 // loading module info
00542                 $oModule = $this->getModule();
00543                 $sModuleDirName = (!empty($sVendorDir)) ? $sVendorDir . '/' . $sModuleDirName : $sModuleDirName;
00544                 if ($oModule->loadByDir($sModuleDirName)) {
00545                     $sModuleId = $oModule->getId();
00546                     $this->_aModules[$sModuleId] = $oModule;
00547 
00548                     $aModulePaths = $this->getModulePaths();
00549 
00550                     if (!is_array($aModulePaths) || !array_key_exists($sModuleId, $aModulePaths)) {
00551                         // saving module path info
00552                         $this->_saveModulePath($sModuleId, $sModuleDirName);
00553 
00554                         //checking if this is new module and if it extends any eshop class
00555                         if (!$this->_extendsClasses($sModuleDirName)) {
00556                             // if not - marking it as disabled by default
00557 
00559                             $oModuleCache = oxNew('oxModuleCache', $oModule);
00561                             $oModuleInstaller = oxNew('oxModuleInstaller', $oModuleCache);
00562 
00563                             $oModuleInstaller->deactivate($oModule);
00564                         }
00565                     }
00566                 }
00567             }
00568         }
00569         // sorting by name
00570         if ($this->_aModules !== null) {
00571             uasort($this->_aModules, array($this, '_sortModules'));
00572         }
00573 
00574         return $this->_aModules;
00575     }
00576 
00582     public function getModuleValidatorFactory()
00583     {
00584         return oxNew('oxModuleValidatorFactory');
00585     }
00586 
00592     public function getModuleIds()
00593     {
00594         $aModuleIdsFromExtensions = $this->_getModuleIdsFromExtensions($this->getModulesWithExtendedClass());
00595         $aModuleIdsFromFiles = array_keys($this->getModuleFiles());
00596 
00597         return array_unique(array_merge($aModuleIdsFromExtensions, $aModuleIdsFromFiles));
00598     }
00599 
00607     public function getModuleExtensions($sModuleId)
00608     {
00609         if (!isset($this->_aModuleExtensions)) {
00610             $aModuleExtension = $this->getConfig()->getModulesWithExtendedClass();
00611             $oModule = $this->getModule();
00612             $aExtension = array();
00613             foreach ($aModuleExtension as $sOxClass => $aFiles) {
00614                 foreach ($aFiles as $sFilePath) {
00615                     $sId = $oModule->getIdByPath($sFilePath);
00616                     $aExtension[$sId][$sOxClass][] = $sFilePath;
00617                 }
00618             }
00619 
00620             $this->_aModuleExtensions = $aExtension;
00621         }
00622 
00623         return $this->_aModuleExtensions[$sModuleId] ? $this->_aModuleExtensions[$sModuleId] : array();
00624     }
00625 
00634     protected function _sortModules($oModule1, $oModule2)
00635     {
00636         return strcasecmp($oModule1->getTitle(), $oModule2->getTitle());
00637     }
00638 
00646     protected function _isVendorDir($sModuleDir)
00647     {
00648         if (is_dir($sModuleDir) && file_exists($sModuleDir . 'vendormetadata.php')) {
00649             return true;
00650         }
00651 
00652         return false;
00653     }
00654 
00662     protected function _extendsClasses($sModuleDir)
00663     {
00664         $aModules = $this->getConfig()->getConfigParam('aModules');
00665         if (is_array($aModules)) {
00666             $sModules = implode('&', $aModules);
00667 
00668             if (preg_match("@(^|&+)" . $sModuleDir . "\b@", $sModules)) {
00669                 return true;
00670             }
00671         }
00672 
00673         return false;
00674     }
00675 
00682     protected function _saveModulePath($sModuleId, $sModulePath)
00683     {
00684         $aModulePaths = $this->getModulePaths();
00685 
00686         $aModulePaths[$sModuleId] = $sModulePath;
00687         $this->getConfig()->saveShopConfVar('aarr', 'aModulePaths', $aModulePaths);
00688     }
00689 
00697     private function _getModuleIdsFromExtensions($aData)
00698     {
00699         $aModuleIds = array();
00700         $oModule = $this->getModule();
00701         foreach ($aData as $aModule) {
00702             foreach ($aModule as $sFilePath) {
00703                 $sModuleId = $oModule->getIdByPath($sFilePath);
00704                 $aModuleIds[] = $sModuleId;
00705             }
00706         }
00707 
00708         return $aModuleIds;
00709     }
00710 
00718     private function _getInvalidExtensions($sModuleId)
00719     {
00720         $aModules = $this->getModuleExtensions($sModuleId);
00721         $aDeletedExt = array();
00722 
00723         foreach ($aModules as $sOxClass => $aModulesList) {
00724             foreach ($aModulesList as $sModulePath) {
00725                 $sExtPath = $this->getConfig()->getModulesDir() . $sModulePath . '.php';
00726                 if (!file_exists($sExtPath)) {
00727                     $aDeletedExt[$sOxClass][] = $sModulePath;
00728                 }
00729             }
00730         }
00731 
00732         return $aDeletedExt;
00733     }
00734 }