Source of file PackagemanagerPackagemanagerModule.php
Size: 13,417 Bytes - Last Modified: 2016-05-18T03:08:26+02:00
buildproject/core/module_packagemanager/system/PackagemanagerPackagemanagerModule.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404 | <?php /*"****************************************************************************************************** * (c) 2007-2016 by Kajona, www.kajona.de * * Published under the GNU LGPL v2.1, see /system/licence_lgpl.txt * *-------------------------------------------------------------------------------------------------------* * $Id$ * ********************************************************************************************************/ namespace Kajona\Packagemanager\System; use Kajona\System\System\CacheManager; use Kajona\System\System\Carrier; use Kajona\System\System\Classloader; use Kajona\System\System\Exception; use Kajona\System\System\Filesystem; use Kajona\System\System\InstallerInterface; use Kajona\System\System\InstallerRemovableInterface; use Kajona\System\System\Logger; use Kajona\System\System\SystemModule; use Kajona\System\System\SystemSetting; /** * Implementation to handle module-packages. List all installed module-packages and starts the installation / update. * * @package module_packagemanager * @author sidler@mulchprod.de * @since 4.0 */ class PackagemanagerPackagemanagerModule implements PackagemanagerPackagemanagerInterface { /** * @var PackagemanagerMetadata */ protected $objMetadata; /** * Returns a list of installed packages, so a single metadata-entry * for each package. * * @return PackagemanagerMetadata[] */ public function getInstalledPackages() { $arrReturn = array(); //loop all modules $arrModules = Classloader::getInstance()->getArrModules(); foreach ($arrModules as $strPath => $strOneModule) { try { $objMetadata = new PackagemanagerMetadata(); $objMetadata->autoInit("/".$strPath); $arrReturn[] = $objMetadata; } catch (Exception $objEx) { } } return $arrReturn; } /** * Copies the extracted(!) package from the temp-folder * to the target-folder. * In most cases, this is either located at /core or at /templates. * The original should be deleted afterwards. * * @throws Exception * @return void */ public function move2Filesystem() { $strSource = $this->objMetadata->getStrPath(); if (!is_dir(_realpath_.$strSource)) { throw new Exception("current package ".$strSource." is not a folder.", Exception::$level_ERROR); } Logger::getInstance(Logger::PACKAGEMANAGEMENT)->addLogRow("moving ".$strSource." to ".$this->getStrTargetPath(), Logger::$levelInfo); $objFilesystem = new Filesystem(); //set a chmod before copying the files - at least try to $objFilesystem->chmod($this->getStrTargetPath(), 0777); $objFilesystem->folderCopyRecursive($strSource, $this->getStrTargetPath(), true); $this->objMetadata->setStrPath($this->getStrTargetPath()); //reset chmod after copying the files $objFilesystem->chmod($this->getStrTargetPath()); $objFilesystem->folderDeleteRecursive($strSource); //shift the cache buster $objSetting = SystemSetting::getConfigByName("_system_browser_cachebuster_"); if ($objSetting != null) { $objSetting->setStrValue((int)$objSetting->getStrValue() + 1); $objSetting->updateObjectToDb(); } } /** * Invokes the installer, if given. * The installer itself is capable of detecting whether an update or a plain installation is required. * * @throws Exception * @return string */ public function installOrUpdate() { $strReturn = ""; if (uniStrpos($this->getObjMetadata()->getStrPath(), "core") === false) { throw new Exception("Current module not located in a core directory.", Exception::$level_ERROR); } if (!$this->isInstallable()) { throw new Exception("Current module isn't installable, not all requirements are given", Exception::$level_ERROR); } //search for an existing installer $arrInstaller = $this->getInstaller($this->getObjMetadata()); //start with modules foreach ($arrInstaller as $objInstance) { if (!$objInstance instanceof \Kajona\System\System\InstallerBase) { continue; } //skip element installers at first run Logger::getInstance(Logger::PACKAGEMANAGEMENT)->addLogRow("triggering updateOrInstall() on installer ".get_class($objInstance).", all requirements given", Logger::$levelInfo); //trigger update or install $strReturn .= $objInstance->installOrUpdate(); $this->updateDefaultTemplate(); } /** @var CacheManager $objCache */ $objCache = Carrier::getInstance()->getContainer()->offsetGet(\Kajona\System\System\ServiceProvider::STR_CACHE_MANAGER); $objCache->flushCache(); return $strReturn; } /** * @return bool */ public function updateDefaultTemplate() { $objFilesystem = new Filesystem(); Logger::getInstance(Logger::PACKAGEMANAGEMENT)->addLogRow("updating default template from /".$this->objMetadata->getStrPath(), Logger::$levelInfo); if (is_dir(_realpath_."/".$this->objMetadata->getStrPath()."/templates/default/js")) { $objFilesystem->folderCopyRecursive($this->objMetadata->getStrPath()."/templates/default/js", "/templates/default/js", true); } if (is_dir(_realpath_."/".$this->objMetadata->getStrPath()."/templates/default/css")) { $objFilesystem->folderCopyRecursive($this->objMetadata->getStrPath()."/templates/default/css", "/templates/default/css", true); } if (is_dir(_realpath_."/".$this->objMetadata->getStrPath()."/templates/default/pics")) { $objFilesystem->folderCopyRecursive($this->objMetadata->getStrPath()."/templates/default/pics", "/templates/default/pics", true); } return true; } /** * @param PackagemanagerMetadata $objMetadata * * @return void */ public function setObjMetadata($objMetadata) { $this->objMetadata = $objMetadata; } /** * @return PackagemanagerMetadata */ public function getObjMetadata() { return $this->objMetadata; } /** * Validates, whether the current package is installable or not. * In nearly all cases * * @return bool */ public function isInstallable() { if (!$this->getObjMetadata()->getBitProvidesInstaller()) { return false; } //check if required modules are given in matching versions $arrRequiredModules = $this->objMetadata->getArrRequiredModules(); foreach ($arrRequiredModules as $strOneModule => $strMinVersion) { if (trim($strOneModule) != "") { $objModule = SystemModule::getModuleByName(trim($strOneModule)); if ($objModule === null) { $arrModules = Classloader::getInstance()->getArrModules(); $objMetadata = null; foreach ($arrModules as $strPath => $strOneFolder) { if (uniStrpos($strOneFolder, $strOneModule) !== false) { $objMetadata = new PackagemanagerMetadata(); $objMetadata->autoInit("/".$strPath); //but: if the package provides an installer and was not resolved by the previous calls, //we shouldn't include it here if ($objMetadata->getBitProvidesInstaller()) { $objMetadata = null; } } } //no package found if ($objMetadata === null) { return false; } //package found, but wrong version if (version_compare($strMinVersion, $objMetadata->getStrVersion(), ">")) { return false; } } //module found, but wrong version elseif (version_compare($strMinVersion, $objModule->getStrVersion(), ">")) { return false; } } } //compare versions of installed elements $objModule = SystemModule::getModuleByName($this->getObjMetadata()->getStrTitle()); if ($objModule !== null) { if (version_compare($this->objMetadata->getStrVersion(), $objModule->getStrVersion(), ">")) { return true; } else { return false; } } else { return true; } } /** * Gets the version of the package currently installed. * If not installed, null should be returned instead. * * @return string|null */ public function getVersionInstalled() { //version compare - depending on module or element $objModule = SystemModule::getModuleByName($this->getObjMetadata()->getStrTitle()); if ($objModule !== null) { return $objModule->getStrVersion(); } else { return null; } } /** * Queries the packagemanager for the resolved target path, so the folder to package will be located at * after installation (or is already located at since it's already installed. * * @return mixed */ public function getStrTargetPath() { $strTarget = $this->objMetadata->getStrTarget(); if ($strTarget == "") { $strTarget = uniStrtolower($this->objMetadata->getStrType()."_".createFilename($this->objMetadata->getStrTitle(), true)).""; } $arrModules = array_flip(Classloader::getInstance()->getArrModules()); if (isset($arrModules[$strTarget])) { return "/".$arrModules[$strTarget]; } return "/core/".$strTarget; } /** * Validates if the current package is removable or not. * * @return bool */ public function isRemovable() { $objManager = new PackagemanagerManager(); if (count($objManager->getArrRequiredBy($this->getObjMetadata())) > 0) { return false; } if (!$this->getObjMetadata()->getBitProvidesInstaller()) { return true; } //scan installers in order to query them on their removable status $bitIsRemovable = true; foreach ($this->getInstaller($this->getObjMetadata()) as $objOneInstaller) { if (!$objOneInstaller instanceof InstallerRemovableInterface) { $bitIsRemovable = false; break; } if (!$objOneInstaller->isRemovable()) { $bitIsRemovable = false; break; } } return $bitIsRemovable; } /** * Removes the current package, if possible, from the system * * @param string &$strLog * * @return bool */ public function remove(&$strLog) { if (!$this->isRemovable()) { return false; } $bitReturn = true; //if we reach up until here, each installer should be an instance of InstallerRemovableInterface foreach ($this->getInstaller($this->getObjMetadata()) as $objOneInstaller) { if ($objOneInstaller instanceof InstallerRemovableInterface) { $bitReturn = $bitReturn && $objOneInstaller->remove($strLog); } } //finally: delete the the module on file-system level if ($bitReturn) { $strLog .= "Deleting file-system parts...\n"; $objFilesystem = new Filesystem(); $bitReturn = $objFilesystem->folderDeleteRecursive($this->getObjMetadata()->getStrPath()); if (!$bitReturn) { $strLog .= "Error deleting file-system parts!. Please remove manually: ".$this->getObjMetadata()->getStrPath().""; } } $strLog .= "\n\nRemoval finished ".($bitReturn ? "successfully" : " with errors")."\n"; return $bitReturn; } /** * Internal helper, fetches all installers located within the passed package * * @param PackagemanagerMetadata $objMetadata * * @return InstallerInterface[] */ protected function getInstaller(PackagemanagerMetadata $objMetadata) { $objFilesystem = new Filesystem(); $arrInstaller = $objFilesystem->getFilelist($objMetadata->getStrPath()."/installer/", array(".php")); $arrReturn = array(); //start with modules foreach ($arrInstaller as $strOneInstaller) { /** @var $objInstaller InstallerInterface */ $objInstaller = Classloader::getInstance()->getInstanceFromFilename(_realpath_.$objMetadata->getStrPath()."/installer/".$strOneInstaller); $arrReturn[] = $objInstaller; } return $arrReturn; } } |