Source of file PackagemanagerPackagemanagerPharmodule.php

Size: 8,350 Bytes - Last Modified: 2016-05-18T03:08:26+02:00

buildproject/core/module_packagemanager/system/PackagemanagerPackagemanagerPharmodule.php

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
<?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\InstallerBase;
use Kajona\System\System\InstallerInterface;
use Kajona\System\System\InstallerRemovableInterface;
use Kajona\System\System\Logger;
use Kajona\System\System\PharModule;
use Kajona\System\System\StringUtil;
use Kajona\System\System\SystemSetting;
use Phar;
use RecursiveIteratorIterator;


/**
 * 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 PackagemanagerPackagemanagerPharmodule extends PackagemanagerPackagemanagerModule
{


    /**
     * 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)).".phar";
        }

        $arrModules = array_flip(Classloader::getInstance()->getArrModules());

        if (isset($arrModules[$strTarget])) {
            return "/".$arrModules[$strTarget];
        }

        return "/core/".$strTarget;
    }


    /**
     * Copies the phar 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 (!\Kajona\System\System\PharModule::isPhar(_realpath_.$strSource)) {
            throw new Exception("current package ".$strSource." is not a phar.", 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->fileCopy($strSource, $this->getStrTargetPath(), true);
        $this->objMetadata->setStrPath($this->getStrTargetPath());

        //reset chmod after copying the files
        $objFilesystem->chmod($this->getStrTargetPath());
        $objFilesystem->fileDelete($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 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();
        }

        /** @var CacheManager $objCache */
        $objCache = Carrier::getInstance()->getContainer()->offsetGet(\Kajona\System\System\ServiceProvider::STR_CACHE_MANAGER);
        $objCache->flushCache();
        $this->updateDefaultTemplate();

        return $strReturn;
    }


    /**
     * @return bool
     */
    public function updateDefaultTemplate()
    {

        //read the module and extract
        $objPharModule = new PharModule($this->objMetadata->getStrPath());
        $objFilesystem = new Filesystem();
        foreach ($objPharModule->getContentMap() as $strKey => $strFullPath) {

            foreach (array("js", "css", "pics") as $strOneSubfolder) {

                $intStrPos = StringUtil::indexOf($strFullPath, "templates/default/{$strOneSubfolder}", false);
                if ($intStrPos !== false) {
                    $strTargetPath = _realpath_."/templates/default/{$strOneSubfolder}/".StringUtil::substring($strFullPath, $intStrPos + StringUtil::length("templates/default/{$strOneSubfolder}"));
                    $objFilesystem->folderCreate(dirname($strTargetPath), true, true);
                    //copy
                    copy($strFullPath, $strTargetPath);
                }

            }
        }

        return true;
    }


    /**
     * 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->fileDelete($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)
    {

        $objPhar = new Phar(_realpath_.$objMetadata->getStrPath());
        $arrReturn = array();
        foreach (new RecursiveIteratorIterator($objPhar) as $objFile) {
            if (strpos($objFile->getPathname(), "/installer/") !== false && uniSubstr($objFile->getPathname(), -4) === ".php") {
                /** @var $objInstaller InstallerInterface */
                $objInstaller = Classloader::getInstance()->getInstanceFromFilename($objFile->getPathname());
                $arrReturn[] = $objInstaller;
            }
        }

        return $arrReturn;
    }

}