Source of file ElementPortal.php

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

buildproject/core/module_pages/portal/ElementPortal.php

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
<?php
/*"******************************************************************************************************
*   (c) 2004-2006 by MulchProductions, www.mulchprod.de                                                 *
*   (c) 2007-2016 by Kajona, www.kajona.de                                                              *
*       Published under the GNU LGPL v2.1, see /system/licence_lgpl.txt                                 *
*-------------------------------------------------------------------------------------------------------*
*	$Id$								*
********************************************************************************************************/
namespace Kajona\Pages\Portal;

use Kajona\Navigation\System\NavigationPoint;
use Kajona\Pages\Admin\Elements\ElementBlockAdmin;
use Kajona\Pages\System\PagesElement;
use Kajona\Pages\System\PagesPage;
use Kajona\Pages\System\PagesPageelement;
use Kajona\Pages\System\PagesPortaleditorActionEnum;
use Kajona\Pages\System\PagesPortaleditorPlaceholderAction;
use Kajona\Pages\System\PagesPortaleditorSystemidAction;
use Kajona\System\Portal\PortalController;
use Kajona\System\System\CacheManager;
use Kajona\System\System\Carrier;
use Kajona\System\System\Exception;
use Kajona\System\System\LanguagesLanguage;
use Kajona\System\System\Link;
use Kajona\System\System\Objectfactory;
use Kajona\System\System\OrmBase;
use Kajona\System\System\Reflection;
use Kajona\System\System\ScriptletHelper;
use Kajona\System\System\ScriptletInterface;
use Kajona\System\System\ServiceProvider;
use Kajona\System\System\SystemSetting;

/**
 * Base Class for all portal-elements
 *
 * @author sidler@mulchprod.de
 * @abstract
 *
 * @module elements
 * @moduleId _pages_elemente_modul_id_
 */
abstract class ElementPortal extends PortalController
{

    private $strCacheAddon = "";

    /**
     * @var PagesPageelement
     */
    private $objElementData;

    /**
     * Constructor
     *
     * @param PagesPageelement $objElementData
     */
    public function __construct($objElementData)
    {
        parent::__construct();

        $this->setSystemid($objElementData->getSystemid());
        //merge the attributes of $objElementData to the array
        $this->arrElementData["page_element_ph_placeholder"] = $objElementData->getStrPlaceholder();
        $this->arrElementData["page_element_ph_name"] = $objElementData->getStrName();
        $this->arrElementData["page_element_ph_element"] = $objElementData->getStrElement();
        $this->arrElementData["page_element_ph_title"] = $objElementData->getStrTitle(false);

        $this->objElementData = $objElementData;
    }


    /**
     * returns the table used by the element
     *
     * @return string
     */
    public function getTable()
    {
        $objAnnotations = new Reflection($this);
        $arrTargetTables = $objAnnotations->getAnnotationValuesFromClass(OrmBase::STR_ANNOTATION_TARGETTABLE);
        if (count($arrTargetTables) != 0) {
            $arrTable = explode(".", $arrTargetTables[0]);
            return _dbprefix_.$arrTable[0];
        }

        //legacy code
        return $this->getArrModule("table");
    }


    /**
     * Loads the content out of the elements-table
     *
     * @param string $strSystemid
     *
     * @return mixed
     */
    public function getElementContent($strSystemid)
    {
        //table given?
        if ($this->getTable() != "") {
            $strQuery = "SELECT *
    						FROM ".$this->getTable()."
    						WHERE content_id = ? ";
            return Carrier::getInstance()->getObjDB()->getPRow($strQuery, array($strSystemid));
        }
        else {
            return array();
        }

    }

    /**
     * Invokes the element to do the work
     * If enabled, passes to addPortalEditorCode(). This adds the element-based pe-code.
     * If modules want to create pe code, they have to call the static method addPortalEditorCode
     * on their own!
     *
     * @return string
     */
    private function getElementOutput()
    {
        $strReturn = "";
        //load the data from the database
        $this->arrElementData = array_merge($this->getElementContent($this->objElementData->getSystemid()), $this->arrElementData);

        //wrap all in a try catch block
        try {
            $strReturn = $this->loadData();
        }
        catch (Exception $objEx) {
            //FIXME: error handling is currently disabled
            //An error occurred during content generation. redirect to error page
            //$objEx->processException();
            //if available, show the error-page. on debugging-environments, the exception processing already die()d the process.
//            if ($this->getPagename() != SystemSetting::getConfigValue("_pages_errorpage_")) {
//                $this->portalReload(Link::getLinkPortalHref(SystemSetting::getConfigValue("_pages_errorpage_")));
//            }

            $strReturn = $objEx->getMessage();
        }

        //add an anchor to jump to, but exclude navigation-elements
        $strReturn = $this->getAnchorTag().$strReturn;

        //apply element-based scriptlets
        $objScriptlets = new ScriptletHelper();
        $strReturn = $objScriptlets->processString($strReturn, ScriptletInterface::BIT_CONTEXT_PORTAL_ELEMENT);

        return $strReturn;
    }

    /**
     * Tries to load the content of the element from cache.
     * If a valid entry was found, the cached content is returned.
     * If no valid entry was found, false is returned instead.
     * In this case, use getElementOutput to load the content.
     *
     * @return string false in case of no matching entry
     * @see ElementPortal::getElementOutput()
     */
    private function getElementOutputFromCache()
    {
        /** @var CacheManager $objCache */
        $objCache = Carrier::getInstance()->getContainer()->offsetGet(ServiceProvider::STR_CACHE_MANAGER);
        return $objCache->getValue($this->getCacheHashSum());
    }

    /**
     * Overwrite this method if you'd like to perform special actions if as soon as content
     * was loaded from the cache.
     * Make sure to return a proper boolean value, otherwise the cached entry may get invalid.
     *
     * @return boolean
     * @since 3.3.1
     */
    public function onLoadFromCache()
    {
        return true;
    }


    /**
     * Saves the current element to the cache.
     * If passed, the value of the param $strElementOutput is used as content, otherwise
     * content-generation is triggered again.
     *
     * @param string $strElementOutput
     *
     * @since 3.3.1
     */
    private function saveElementToCache($strElementOutput)
    {
        $intCachetimeInSeconds = $this->getCachetimeInSeconds();
        if($intCachetimeInSeconds <= 0) {
            return;
        }

        //strip the data-editable values - no use case for regular page views
        $strElementOutput = preg_replace('/data-kajona-editable=\"([a-zA-Z0-9#_]*)\"/i', "", $strElementOutput);

        /** @var CacheManager $objCache */
        $objCache = Carrier::getInstance()->getContainer()->offsetGet(ServiceProvider::STR_CACHE_MANAGER);
        $objCache->addValue($this->getCacheHashSum(), $strElementOutput, $intCachetimeInSeconds);

    }


    public function getCacheHashSum()
    {
        $strGuestId = "";
        //when browsing the site as a guest, drop the userid
        if ($this->objSession->isLoggedin()) {
            $strGuestId = $this->objSession->getUserID();
        }

        return sha1(
            __CLASS__.
            $strGuestId.
            $this->getAction().
            $this->getPagename().
            $this->strCacheAddon.
            $this->getParam("pv").
            $this->getSystemid().
            $this->getParam("systemid").
            $this->getParam("highlight")
        );
    }

    /**
     * Returns the number of seconds the current element will be cached in the pagecache.
     * @return int
     */
    public function getCachetimeInSeconds()
    {
        return $this->objElementData->getIntCachetime();
    }


    private function getPageData()
    {
        return PagesPage::getPageByName($this->getPagename());
    }


    /**
     * Forces the rendering of the current portal element.
     * Takes care of loading the element from cache or regenerating the element.
     * If enabled, the portal-editor code is rendered, too.
     *
     * @param bool|false $bitActivePortaleditor
     *
     * @return string
     */
    public function getRenderedElementOutput($bitActivePortaleditor = false)
    {

        if (SystemSetting::getConfigValue("_pages_cacheenabled_") == "true" && $this->getParam("preview") != "1" && $this->getPageData()->getStrName() != SystemSetting::getConfigValue("_pages_errorpage_")) {
            $strElementOutput = "";
            //if the portaleditor is disabled, do the regular cache lookups in storage. otherwise regenerate again and again :)
            if ($bitActivePortaleditor) {
                $strElementOutput = $this->getElementOutput();
            }
            else {
                //pe not to be taken into account --> full support of caching
                $strElementOutput = $this->getElementOutputFromCache();

                if ($strElementOutput === false) {
                    $strElementOutput = $this->getElementOutput();
                    $this->saveElementToCache($strElementOutput);
                }
            }

        }
        else {
            $strElementOutput = $this->getElementOutput();
        }


        if ($bitActivePortaleditor) {
            $strElementOutput = $this->addPortalEditorCode($strElementOutput);
        }
        else {
            $strElementOutput = $this->removePortalEditorTags($strElementOutput);
        }


        return $strElementOutput;
    }

    /**
     * Adds the portal-editor code to the current elements' content
     *
     * @param $strElementOutput
     *
     * @return string
     */
    protected function addPortalEditorCode($strElementOutput)
    {
        $this->getPortalEditorActions();
        return PagesPortaleditor::addPortaleditorContentWrapper($strElementOutput, $this->getSystemid(), $this->arrElementData["page_element_ph_element"]);
    }

    /**
     * Removes the portal-editor editable ids
     *
     * @param $strElementOutput
     *
     * @return mixed
     */
    protected function removePortalEditorTags($strElementOutput)
    {
        return preg_replace('/data-kajona-editable=\"([a-zA-Z0-9#_]*)\"/i', "", $strElementOutput);
    }

    /**
     * Registers the default portaleditor actions for the current element
     */
    public function getPortalEditorActions()
    {

        $objPageelement = new PagesPageelement($this->getSystemid());
        if (!$objPageelement->rightEdit()) {
            return;
        }

        $objParent = Objectfactory::getInstance()->getObject($objPageelement->getPrevId());
        if ($objParent instanceof PagesPageelement) {
            $objParent = $objParent->getConcreteAdminInstance();
        }


        //fetch the language to set the correct admin-lang
        $objLanguages = new LanguagesLanguage();
        $strAdminLangParam = $objLanguages->getPortalLanguage();


        PagesPortaleditor::getInstance()->registerAction(
            new PagesPortaleditorSystemidAction(PagesPortaleditorActionEnum::EDIT(), Link::getLinkAdminHref("pages_content", "edit", "&systemid={$this->getSystemid()}&language={$strAdminLangParam}&pe=1"), $this->getSystemid())
        );

        if (!$objParent instanceof ElementBlockAdmin) {

            PagesPortaleditor::getInstance()->registerAction(
                new PagesPortaleditorSystemidAction(PagesPortaleditorActionEnum::COPY(), Link::getLinkAdminHref("pages_content", "copyElement", "&systemid={$this->getSystemid()}&language={$strAdminLangParam}&pe=1"), $this->getSystemid())
            );
            PagesPortaleditor::getInstance()->registerAction(
                new PagesPortaleditorSystemidAction(PagesPortaleditorActionEnum::DELETE(), Link::getLinkAdminHref("pages_content", "deleteElementFinal", "&systemid={$this->getSystemid()}&language={$strAdminLangParam}&pe=1"), $this->getSystemid())
            );
            PagesPortaleditor::getInstance()->registerAction(
                new PagesPortaleditorSystemidAction(PagesPortaleditorActionEnum::MOVE(), "", $this->getSystemid())
            );


            PagesPortaleditor::getInstance()->registerAction(
                new PagesPortaleditorSystemidAction(PagesPortaleditorActionEnum::SETINACTIVE(), Link::getLinkAdminHref("pages_content", "elementStatus", "&systemid={$this->getSystemid()}&language={$strAdminLangParam}&pe=1"), $this->getSystemid())
            );
            PagesPortaleditor::getInstance()->registerAction(
                new PagesPortaleditorSystemidAction(PagesPortaleditorActionEnum::SETACTIVE(), Link::getLinkAdminHref("pages_content", "elementStatus", "&systemid={$this->getSystemid()}&language={$strAdminLangParam}&pe=1"), $this->getSystemid())
            );

        }
    }

    /**
     * Registers new-entry actions for a given placeholder
     *
     * @param $bitElementIsExistingAtPlaceholder
     * @param PagesElement $objElement
     * @param $strPlaceholder
     * @param PagesPage $objPage
     */
    public function getPortaleditorPlaceholderActions($bitElementIsExistingAtPlaceholder, PagesElement $objElement, $strPlaceholder, PagesPage $objPage)
    {
        //fetch the language to set the correct admin-lang
        $objLanguages = new LanguagesLanguage();
        $strAdminLangParam = $objLanguages->getPortalLanguage();


        if ($objElement->getIntRepeat() == 1 || !$bitElementIsExistingAtPlaceholder) {
            PagesPortaleditor::getInstance()->registerAction(
                new PagesPortaleditorPlaceholderAction(PagesPortaleditorActionEnum::CREATE(), Link::getLinkAdminHref("pages_content", "new", "&systemid={$objPage->getSystemid()}&language={$strAdminLangParam}&placeholder={$strPlaceholder}&element={$objElement->getStrName()}&pe=1"), $strPlaceholder, $objElement->getStrName())
            );
        }
    }


    /**
     * Dummy method, element needs to overwrite it
     *
     * @return string
     */
    protected function loadData()
    {
        return "Element needs to overwrite loadData()!";
    }

    /**
     * Generates an anchor tag enabling navigation-points to jump to specific page-elements.
     * can be overwritten by subclasses
     *
     * @return string
     */
    protected function getAnchorTag()
    {
        return "<a name=\"".$this->getSystemid()."\" class=\"hiddenAnchor\"></a>";
    }

    /**
     * Use this method to set additional cache-key-addons.
     * E.g. if you want to cache depending on your own params like a rating history,
     * this is the place to go.
     *
     * @param string $strCacheAddon
     */
    public function setStrCacheAddon($strCacheAddon)
    {
        $this->strCacheAddon .= $strCacheAddon;
    }


    /**
     * Pre-check to indicate if a portal-element provides possible navigation entries.
     * This method has to be static since it is evaluated before the real object instantiation.
     * You have to overwrite this method in order to have getNavigationEntries() queried, otherwise the methode is ignores completely.
     *
     * @return bool
     */
    public static function providesNavigationEntries()
    {
        return false;
    }


    /**
     * This method may be used, if the current module is able to
     * register own levels in the navigation.
     * See the module mediamanager (gallery, downloads) on how to use
     * this special feature.
     * The array returned by this method should be structured like:
     * array(
     *    node => NavigationPoint ,
     *    subnodes => array(
     *        array( node => NavigationPoint, subnodes => array(...)),
     *        array( node => NavigationPoint, subnodes => array(...))
     *    )
     * )
     * If you don't want to create additional navigation entries, don't overwrite this method.
     * Otherwise you have to override the method providesNavigationEntries() and return true.
     * This method is only queried if the static providesNavigationEntries is true since the number of queries
     * could be reduced drastically due to this pre-check.
     * If you only want to return a flat list of nodes, you can return an array of NavigationPoint instances instead of wrapping them
     * into the way more complex node/subnode structure.
     *
     * @see NavigationTree::getCompleteNaviStructure()
     * @see NavigationPoint::getDynamicNaviLayer()
     * @return array|NavigationPoint[]|bool
     * @since 4.0
     */
    public function getNavigationEntries()
    {
        return false;
    }

    /**
     * @return PagesPageelement
     */
    public function getObjElementData()
    {
        return $this->objElementData;
    }

}