Plugin Advanced Mod Rewrite für Contenido 4.8.x

malsdgtac
Beiträge: 717
Registriert: Fr 12. Mär 2004, 15:50
Kontaktdaten:

Re: Plugin Advanced Mod Rewrite für Contenido 4.8.x

Beitrag von malsdgtac » Fr 17. Jul 2015, 16:41

Hallo,

ich möchte nachfragen, wie ich es schaffe, dass Artikel die online sind aber in Kategorien liegen die offline sind, angezeigt werden können.

Danke für euren Input

Oldperl
Beiträge: 4250
Registriert: Do 30. Jun 2005, 22:56
Wohnort: Eltmann, Unterfranken, Bayern
Kontaktdaten:

Re: Plugin Advanced Mod Rewrite für Contenido 4.8.x

Beitrag von Oldperl » Fr 17. Jul 2015, 17:14

Hallo smac,

AMR bei Version 4.9 oder bei 4.8???

Gruß aus Franken

Ortwin
ConLite 2.1, alternatives und stabiles Update von Contenido 4.8.x unter PHP 7.x - Download und Repo auf Gitport.de
phpBO Search Advanced - das Suchwort-Plugin für CONTENIDO 4.9
Mein Entwickler-Blog

malsdgtac
Beiträge: 717
Registriert: Fr 12. Mär 2004, 15:50
Kontaktdaten:

Re: Plugin Advanced Mod Rewrite für Contenido 4.8.x

Beitrag von malsdgtac » Fr 17. Jul 2015, 18:18

Ist jetzt 4.9.7 - war voher eine 4.9.3 oder 4.9.4 und ich habe ein Update gemacht.

Ich habe einiges durchgeschaut geschaut und kapier's nicht ganz, denn ich bin mir sicher, dass es vor dem Update funktioniert hat - ich kann aber im Plugin nichts Neues finden.

Oldperl
Beiträge: 4250
Registriert: Do 30. Jun 2005, 22:56
Wohnort: Eltmann, Unterfranken, Bayern
Kontaktdaten:

Re: Plugin Advanced Mod Rewrite für Contenido 4.8.x

Beitrag von Oldperl » Fr 17. Jul 2015, 21:27

Dachte ich mir fast, dann sind wir hier im falschen Forum/Beitrag. Für die 4.9er gibt es dazu bereits einen Beitrag im entsprechenden Forum. Offensichtlich gibt es im dortigen AMR-Plugin einen diesbezüglichen Bug.

:arrow: http://forum.contenido.org/viewtopic.php?f=92&t=36351

Gruß aus Franken

Ortwin
ConLite 2.1, alternatives und stabiles Update von Contenido 4.8.x unter PHP 7.x - Download und Repo auf Gitport.de
phpBO Search Advanced - das Suchwort-Plugin für CONTENIDO 4.9
Mein Entwickler-Blog

Kickbanignore
Beiträge: 37
Registriert: Mi 20. Jan 2010, 11:13
Kontaktdaten:

Re: Plugin Advanced Mod Rewrite für Contenido 4.8.x

Beitrag von Kickbanignore » Fr 23. Okt 2015, 08:50

Hat jemand für 4.8.x eine Anpassung für PHP 5.5? "preg_replace" wird da ja irgendwie abgeändert.

Edit: Falls noch wer diese alten Versionen hat, hier die beiden angepassten Files, bei mir läuft so wieder alles.

contenido/plugins/mod_rewrite/classes/class.modrewritecontroller.php

Code: Alles auswählen

<?php
/**
 * Includes Mod Rewrite controller class.
 *
 * @author      Murat Purc <murat@purc.de>
 * @copyright   © Murat Purc 2008
 * @package     Contenido
 * @subpackage  ModRewrite
 */


defined('CON_FRAMEWORK') or die('Illegal call');


/**
 * Mod Rewrite controller class. Extracts url parts and sets some necessary globals like:
 * - $idart
 * - $idcat
 * - $client
 * - $changeclient
 * - $lang
 * - $changelang
 *
 * @author      Murat Purc <murat@purc.de>
 * @date        16.04.2008
 * @package     Contenido
 * @subpackage  ModRewrite
 */
class ModRewriteController extends ModRewriteBase {

    /**
     * Extracted request uri path parts by path separator '/'
     *
     * @var array
     */
    private $_aParts;

    /**
     * Extracted article name from request uri
     *
     * @var string
     */
    private $_sArtName;

    /**
     * Remaining path for path resolver (see $GLOBALS['path'])
     *
     * @var string
     */
    private $_sPath;

    /**
     * Incomming URL
     *
     * @var string
     */
    private $_sIncommingUrl;

    /**
     * Resolved URL
     *
     * @var string
     */
    private $_sResolvedUrl;

    /**
     * Client id used by this class
     *
     * @var int
     */
    private $_iClientMR;

    /**
     * Flag about occured errors
     *
     * @var bool
     */
    private $_bError = false;

    /**
     * Flag about found routing definition
     *
     * @var bool
     */
    private $_bRoutingFound = false;


    /**
     * Constructor, sets several properties.
     *
     * @param  string  $incommingUrl  Incomming URL
     */
    public function __construct($incommingUrl) {
        parent::initialize();
        $this->_sIncommingUrl = $incommingUrl;
        $this->_aParts        = array();
    }


    /**
     * Getter for overwritten client id (see $GLOBALS['client'])
     *
     * @return  int  Client id
     */
    public function getClient() {
        return parent::$_oGlobals->get('client');
    }


    /**
     * Getter for overwritten change client id (see $GLOBALS['changeclient'])
     *
     * @return  int  Change client id
     */
    public function getChangeClient() {
        return parent::$_oGlobals->get('changeclient');
    }


    /**
     * Getter for article id (see $GLOBALS['idart'])
     *
     * @return  int  Article id
     */
    public function getIdArt() {
        return parent::$_oGlobals->get('idart');
    }


    /**
     * Getter for category id (see $GLOBALS['idcat'])
     *
     * @return  int  Category id
     */
    public function getIdCat() {
        return parent::$_oGlobals->get('idcat');
    }


    /**
     * Getter for language id (see $GLOBALS['lang'])
     *
     * @return  int  Language id
     */
    public function getLang() {
        return parent::$_oGlobals->get('lang');
    }


    /**
     * Getter for change language id (see $GLOBALS['change_lang'])
     *
     * @return  int  Change language id
     */
    public function getChangeLang() {
        return parent::$_oGlobals->get('changelang');
    }


    /**
     * Getter for path (see $GLOBALS['path'])
     *
     * @return  string  Path, used by path resolver
     */
    public function getPath() {
        return $this->_sPath;
    }


    /**
     * Getter for resolved url
     *
     * @return  string  Resolved url
     */
    public function getResolvedUrl() {
        return $this->_sResolvedUrl;
    }


    /**
     * Returns a flag about found routing definition
     *
     * return  bool  Flag about found routing
     */
    public function getRoutingFoundState() {
        return $this->_bRoutingFound;
    }


    /**
     * Getter for occured error state
     *
     * @return  bool  Flag for occured error
     */
    public function errorOccured(){
        return $this->_bError;
    }


    /**
     * Main function to call for mod rewrite related preprocessing jobs.
     *
     * Executes some private functions to extract request URI and to set needed membervariables
     * (client, language, article id, category id, etc.)
     */
    public function execute() {
        if (parent::isEnabled() == false) {
            return;
        }

        $this->_extractRequestUri();

        $this->_initializeClientId();

        $this->_setClientId();

        mr_loadConfiguration($this->_iClientMR);

        $this->_setLanguageId();

        // second call after setting client and language
        $this->_extractRequestUri(true);

        $this->_setPathresolverSetting();

        $this->_setIdart();

        parent::$_oDebug->addDebug($this->_aParts, 'ModRewriteController::execute() _setIdart');

        $this->_postValidation();
    }


    /**
     * Extracts request URI and sets member variables $this->_sArtName and $this->_aParts
     *
     * @param  bool $secondCall  Flag about second call of this function, is needed
     *                           to re extract url if a routing definition was found
     */
    private function _extractRequestUri($secondCall=false) {
        // check for defined rootdir
        if (parent::getConfig('rootdir') !== '/' && strpos($_SERVER['REQUEST_URI'], $this->_sIncommingUrl) === 0) {
            $this->_sIncommingUrl = str_replace(parent::getConfig('rootdir'), '/', $this->_sIncommingUrl);
        }

        $aUrlComponents = $this->_parseUrl($this->_sIncommingUrl);
        if (isset($aUrlComponents['path'])) {
##++##
            if (parent::getConfig('rootdir') !== '/' && strpos($aUrlComponents['path'], parent::getConfig('rootdir')) === 0) {
                $aUrlComponents['path'] = str_replace(parent::getConfig('rootdir'), '/', $aUrlComponents['path']);
            }
##++##

            if ($secondCall == true) {

#        parent::$_oDebug->addDebug($aUrlComponents, 'ModRewriteController::_extractRequestUri() 2. call $aUrlComponents');
                // @todo: implement real redirect of old front_content.php style urls

                // check for routing definition
                $routings = parent::getConfig('routing');
                if (is_array($routings) && isset($routings[$aUrlComponents['path']])) {
                    $aUrlComponents['path'] = $routings[$aUrlComponents['path']];
                    if (strpos($aUrlComponents['path'], 'front_content.php') !== false) {
                        // routing destination contains front_content.php

                        $this->_bRoutingFound = true;

                        // set client language, if not set before
                        mr_setClientLanguageId(parent::$_oGlobals->get('client'));

                        //rebuild URL
                        $url = mr_buildNewUrl($aUrlComponents['path']);

                        $aUrlComponents = $this->_parseUrl($url);

                        $this->_aParts = array();
                    }
                } else {
                    return;
                }
            }

            $aPaths = explode('/', $aUrlComponents['path']);
            foreach ($aPaths as $p => $item) {
                if (!empty($item)) {
                    // pathinfo would also work
                    $arr   = explode('.', $item);
                    $count = count($arr);
                    if ($count > 0 && '.' . strtolower($arr[$count-1]) == parent::getConfig('file_extension')) {
                        array_pop($arr);
                        $this->_sArtName = implode('.', $arr);
                    } else {
                        $this->_aParts[] = $item;
                    }
                }
            }

            if ($secondCall == true) {
                // reprocess extracting client and language
                $this->_setClientId();
                mr_loadConfiguration($this->_iClientMR);
                $this->_setLanguageId();
            }

        }
        parent::$_oDebug->addDebug($this->_aParts, 'ModRewriteController::_extractRequestUri() $this->_aParts');

        // loop parts array and remove existing 'front_content.php'
        if ($this->_hasPartArrayItems()) {
            foreach($this->_aParts as $p => $item) {
                if ($item == 'front_content.php') {
                    unset($this->_aParts[$p]);
                }
            }
        }

        // set parts property top null, if needed
        if ($this->_hasPartArrayItems() == false) {
            $this->_aParts = null;
        }

        // set artname to null if needed
        if (!isset($this->_sArtName) || empty($this->_sArtName) || strlen($this->_sArtName) == 0) {
            $this->_sArtName = null;
        }

    }


    /**
     * Tries to initialize the client id
     */
    private function _initializeClientId() {
        $client       = parent::$_oGlobals->get('client', 0);
        $changeclient = parent::$_oGlobals->get('changeclient', 0);

        $this->_iClientMR = 0;
        if ($client > 0 && $changeclient == 0) {
            $this->_iClientMR = $client;
        } elseif ($changeclient > 0) {
            $this->_iClientMR = $changeclient;
        } else {
            $this->_iClientMR = parent::$_oGlobals->get('load_client');
        }

        if ((int) $this->_iClientMR > 0) {
            // set global client variable
            parent::$_oGlobals->set('client', (int) $this->_iClientMR);
        }
    }


    /**
     * Sets client id
     */
    private function _setClientId() {
        if ($this->_hasPartArrayItems() == false || parent::getConfig('use_client') !== 1) {
            return;
        }

        $client       = parent::$_oGlobals->get('client', 0);
        $changeclient = parent::$_oGlobals->get('changeclient', 0);

        if (parent::getConfig('use_client_name') == 1) {
            $changeclient     = ModRewrite::getClientId(array_shift($this->_aParts));
            $this->_iClientMR = $changeclient;
        } else {
            $changeclient     = (int) array_shift($this->_aParts);
            $this->_iClientMR = $changeclient;
        }

        if (empty($changeclient) || (int) $changeclient == 0) {
            $changeclient = parent::$_oGlobals->get('load_client');
        }
        if ($client > 0 && $changeclient !== $client) {
            // overwrite existing client variable
            $this->_iClientMR = $changeclient;
            parent::$_oGlobals->set('client', $changeclient);
        }

        parent::$_oGlobals->set('changeclient', $changeclient);
    }


    /**
     * Sets language id
     */
    private function _setLanguageId() {
        if ($this->_hasPartArrayItems() == false || parent::getConfig('use_language') !== 1) {
            return;
        }

        if (parent::getConfig('use_language_name') == 1) {
            // thanks to Nicolas Dickinson for multi Client/Language BugFix
            $changelang = ModRewrite::getLanguageId(array_shift($this->_aParts) , $this->_iClientMR);
        } else {
            $changelang = (int) array_shift($this->_aParts);
        }

        if ((int) $changelang > 0) {
            parent::$_oGlobals->set('lang', $changelang);
            parent::$_oGlobals->set('changelang', $changelang);
        }
    }


    /**
     * Sets path resolver and category id
     */
    private function _setPathresolverSetting() {
        if ($this->_hasPartArrayItems() == false) {
            return;
        }

        $this->_sPath = '/' . implode('/', $this->_aParts) . '/';

        $lang = parent::$_oGlobals->get('lang');

        if ($lang == null) {
            if (parent::$_oGlobals->get('load_lang', 0) > 0) {
                // load_client is set in frontend/config.php

                $lang = parent::$_oGlobals->get('load_lang');
            } else {
                // get client id from table
                cInclude('classes', 'contenido/class.clientslang.php');
                $clCol = new cApiClientLanguageCollection();
                $clCol->setWhere('idclient', parent::$_oGlobals->get('client'));
                $clCol->query();
                if ($clItem = $clCol->next()) {
                    $lang = $clItem->get('idlang');
                }
            }
            parent::$_oGlobals->set('lang', $lang);
        }

        $idcat = (int) ModRewrite::getCatIdByUrlPath($this->_sPath);

        if ($idcat == 0) {
            // category couldn't resolved
            $this->_bError = true;
            $idcat = null;
        } else {
            // unset $this->_sPath if $idcat could set, otherwhise it would be resolved again.
            unset($this->_sPath);
        }

        parent::$_oGlobals->set('idcat', $idcat);

        parent::$_oDebug->addDebug($idcat, 'ModRewriteController->_setPathresolverSetting $idcat');
        parent::$_oDebug->addDebug($this->_sPath, 'ModRewriteController->_setPathresolverSetting $this->_sPath');
    }


    /**
     * Sets article id
     */
    private function _setIdart() {
        // startarticle name in url
        if (parent::getConfig('add_startart_name_to_url') && isset($this->_sArtName)) {
            if ($this->_sArtName == parent::getConfig('default_startart_name')) {
                // stored articlename is the default one, remove it ModRewrite::getArtIdByWebsafeName()
                // will find the real article name
                $this->_sArtName = null;
            }
        }

        $idcat = parent::$_oGlobals->get('idcat');
        $idart = parent::$_oGlobals->get('idart');

        if ($idcat !== null && $this->_sArtName && $idart == null) {
            // existing idcat with article name and no idart
			
			$fuckyouphpupdate = new ModRewrite();
			$idart = $fuckyouphpupdate->getArtIdByWebsafeName($this->_sArtName, $idcat, parent::$_oGlobals->get('lang'));
            //$idart = ModRewrite::getArtIdByWebsafeName($this->_sArtName, $idcat, parent::$_oGlobals->get('lang'));
        } elseif ($idcat > 0 && $this->_sArtName == null && $idart == null) {

            if (parent::getConfig('add_startart_name_to_url') && parent::getConfig('default_startart_name') == '') {

                // existing idcat without article name and idart
                cInclude('classes', 'class.article.php');
                $artColl = new ArticleCollection(array('idcat' => $idcat, 'start' => 1));
                if ($artItem = $artColl->startArticle()) {
                    $idart = $artItem->get('idart');
                }

            }

        } elseif ($idcat == null && $idart == null && isset($this->_sArtName)) {
            // no idcat and idart but article name
            $idart = ModRewrite::getArtIdByWebsafeName($this->_sArtName);
        }

        if ($idart !== null && (!$idart || (int) $idart == 0)) {
            if (parent::getConfig('redirect_invalid_article_to_errorsite') == 1) {
                $this->_bError = true;
                $idart = null;
            }
        }

        parent::$_oGlobals->set('idart', $idart);

        parent::$_oDebug->addDebug($idart, 'ModRewriteController->_setIdart $idart');
    }


    /**
     * Does post validation of the extracted data.
     *
     * One main goal of this function is to prevent duplicated content, which could happen, if
     * the configuration 'startfromroot' is activated.
     */
    private function _postValidation() {
        if ($this->_bError || $this->_bRoutingFound || !$this->_hasPartArrayItems()) {
            return;
        }

        if (parent::getConfig('startfromroot') == 1 && parent::getConfig('prevent_duplicated_content') == 1) {

            // prevention of duplicated content if '/firstcat/' is directly requested!

            $idcat = parent::$_oGlobals->get('idcat');
            $idart = parent::$_oGlobals->get('idart');

            // compose new parameter
            $param = '';
            if ($idcat) {
                $param .= 'idcat=' . (int) $idcat;
            }
            if ($idart) {
                $param .= ($param !== '') ? '&idart=' . (int) $idart : 'idart=' . (int) $idart;
            }

            if ($param == '') {
                return;
            }

            // set client language, if not set before
            mr_setClientLanguageId(parent::$_oGlobals->get('client'));

            //rebuild url
            $url = mr_buildNewUrl('front_content.php?' . $param);

            $aUrlComponents = @parse_url($this->_sIncommingUrl);
            $incommingUrl   = (isset($aUrlComponents['path'])) ? $aUrlComponents['path'] : '';

            parent::$_oDebug->addDebug($url, 'ModRewriteController->_postValidation validate url');
            parent::$_oDebug->addDebug($incommingUrl, 'ModRewriteController->_postValidation incommingUrl');

            // now the new generated uri should be identical with the request uri
            if ($incommingUrl !== $url) {
                $this->_bError = true;
                parent::$_oGlobals->set('idcat', null);
            }
        }
    }


    /**
     * Parses the url using defined separators
     *
     * @param   string  $url  Incoming url
     * @return  string  Parsed url
     */
    private function _parseUrl($url) {
        $this->_sResolvedUrl = $url;

        $oMrUrlUtil = ModRewriteUrlUtil::getInstance();
        $url = $oMrUrlUtil->toContenidoUrl($url);

        return @parse_url($url);
    }


    /**
     * Returns state of parts property.
     *
     * @return  bool  True if $this->_aParts propery is an array and contains items
     * @access  private
     */
    function _hasPartArrayItems() {
        if (is_array($this->_aParts) && count($this->_aParts) > 0) {
            return true;
        } else {
            return false;
        }
    }

}
contenido/plugins/mod_rewrite/includes/functions.mod_rewrite.php

Code: Alles auswählen

<?php
/**
 * Defines the 'modrewrite' related helper functions
 *
 * @author      Stefan Seifarth / stese
 * @copyright   © www.polycoder.de
 * @author      Murat Purc <murat@purc.de>
 * @package     Contenido
 * @subpackage  ModRewrite
 */

/******************************************
 * File      :   functions.mod_rewrite.php
 * Project   :   Contenido
 * Descr     :   Defines the 'modrewrite' related
 *               functions
 *
 * Author    :   Stefan Seifarth
 * Created   :   04.12.2004
 * Modified  :   18.12.2005
 *
 * © www.polycoder.de
 ******************************************/


defined('CON_FRAMEWORK') or die('Illegal call');

cInclude('classes', 'contenido/class.articlelanguage.php');


/**
 * Processes mod_rewrite related job for created new tree.
 *
 * Will be called by chain 'Contenido.Action.str_newtree.AfterCall'.
 *
 * @param   array  $data  Assoziative array with some values
 * @return  array  Passed parameter
 */
function mr_strNewTree(array $data){
    // get instance of the mpdebug class
    Contenido_mpDebug::getInstance()->log($data, 'mr_strNewTree $data');

    if ((int) $data['newcategoryid'] > 0) {
        $mrCatAlias = (trim($data['categoryalias']) !== '') ? trim($data['categoryalias']) : trim($data['categoryname']);
        $lang       = mpGlobals::getInstance()->get('lang');
        // set new urlname - because original set urlname isn''t validated for double entries in same parent category
        ModRewrite::setCatWebsafeName($mrCatAlias, $data['newcategoryid'], $lang);
        ModRewrite::setCatUrlPath($data['newcategoryid'], $lang);
    }

    return $data;
}


/**
 * Processes mod_rewrite related job for created new category.
 *
 * Will be called by chain 'Contenido.Action.str_newcat.AfterCall'.
 *
 * @param   array  $data  Assoziative array with some values
 * @return  array  Passed parameter
 */
function mr_strNewCategory(array $data){
    Contenido_mpDebug::getInstance()->log($data, 'mr_strNewCategory $data');

    if ((int) $data['newcategoryid'] > 0) {
        $mrCatAlias = (trim($data['categoryalias']) !== '') ? trim($data['categoryalias']) : trim($data['categoryname']);
        $lang       = mpGlobals::getInstance()->get('lang');
        // set new urlname - because original set urlname isn''t validated for double entries in same parent category
        ModRewrite::setCatWebsafeName($mrCatAlias, $data['newcategoryid'], $lang);
        ModRewrite::setCatUrlPath($data['newcategoryid'], $lang);
    }

    return $data;
}


/**
 * Processes mod_rewrite related job for renamed category.
 *
 * Will be called by chain 'Contenido.Action.str_renamecat.AfterCall'.
 *
 * @param   array  $data  Assoziative array with some values
 * @return  array  Passed parameter
 */
function mr_strRenameCategory(array $data){
    Contenido_mpDebug::getInstance()->log($data, 'mr_strRenameCategory $data');

    $mrCatAlias = (trim($data['newcategoryalias']) !== '') ? trim($data['newcategoryalias']) : trim($data['newcategoryname']);
    if ($mrCatAlias != '') {
        // set new urlname - because original set urlname isn''t validated for double entries in same parent category
        ModRewrite::setCatWebsafeName($mrCatAlias, $data['idcat'], $data['lang']);
        ModRewrite::setCatUrlPath($data['idcat'], $data['lang']);
    }

    return $data;
}


/**
 * Processes mod_rewrite related job after moving a category up.
 *
 * Will be called by chain 'Contenido.Action.str_moveupcat.AfterCall'.
 *
 * @todo  do we really need processing of the category? there is no mr relevant data
 *        changes while moving the category on same level, level and name won't change
 *
 * @param   int  $idcat  Category id
 * @return  int  Category id
 */
function mr_strMoveUpCategory($idcat) {
    Contenido_mpDebug::getInstance()->log($idcat, 'mr_strMoveUpCategory $idcat');

    // category check
    $cat = new cApiCategory((int) $idcat);
    if (!$cat->get('preid')) {
        return;
    }

    // get all cat languages
    $aIdLang = ModRewrite::getCatLanguages($idcat);

    // update ...
    foreach ($aIdLang as $iIdLang) {
        // get urlname
        $str_catname = ModRewrite::getCatName($idcat, $iIdLang);
        // set new urlname - because original set urlname isn't validated for double entries in same parent category
        ModRewrite::setCatWebsafeName($str_catname, $idcat, $iIdLang);
    }

    return $idcat;
}


/**
 * Processes mod_rewrite related job after moving a category down.
 *
 * Will be called by chain 'Contenido.Action.str_movedowncat.AfterCall'.
 *
 * @todo  do we really need processing of the category? there is no mr relevant data
 *        changes while moving the category on same level, level and name won't change
 *
 * @param   int  $idcat  Id of category beeing moved down
 * @return  int  Category id
 */
function mr_strMovedownCategory($idcat) {
    Contenido_mpDebug::getInstance()->log($idcat, 'mr_strMovedownCategory $idcat');

    // category check
    $cat = new cApiCategory((int) $idcat);
    if (!$cat->get('id')) {
        return;
    }

    // get all cat languages
    $aIdLang = ModRewrite::getCatLanguages($idcat);
    // update ...
    foreach ($aIdLang as $iIdLang) {
        // get urlname
        $sCatname = ModRewrite::getCatName($idcat, $iIdLang);
        // set new urlname - because original set urlname isn't validated for double entries in same parent category
        ModRewrite::setCatWebsafeName($sCatname, $idcat, $iIdLang);
    }

    return $idcat;
}


/**
 * Processes mod_rewrite related job after moving a category subtree.
 *
 * Will be called by chain 'Contenido.Action.str_movesubtree.AfterCall'.
 *
 * @param   array  $data  Assoziative array with some values
 * @return  array  Passed parameter
 */
function mr_strMoveSubtree(array $data) {
    Contenido_mpDebug::getInstance()->log($data, 'mr_strMoveSubtree $data');

    // category check
    if ((int) $data['idcat'] <= 0) {
        return;
    }

    // next category check
    $cat = new cApiCategory($data['idcat']);
    if (!$cat->get('idcat')) {
        return;
    }

    // get all cat languages
    $aIdLang = ModRewrite::getCatLanguages($data['idcat']);
    // update all languages
    foreach ($aIdLang as $iIdLang) {
        // get urlname
        $sCatname = ModRewrite::getCatName($data['idcat'], $iIdLang);
        // set new urlname - because original set urlname isn't validated for double entries in same parent category
        ModRewrite::setCatWebsafeName($sCatname, $data['idcat'], $iIdLang);
        ModRewrite::setCatUrlPath($data['idcat'], $iIdLang);
    }

    // now dive into all existing subcategories and modify their paths too...
    $oCatColl = new cApiCategoryCollection('parentid=' . $data['idcat']);
    while ($oCat = $oCatColl->next()) {
        mr_strMoveSubtree(array('idcat' => $oCat->get('idcat')));
    }

    return $data;
}


/**
 * Processes mod_rewrite related job after copying a category subtree.
 *
 * Will be called by chain 'Contenido.Category.strCopyCategory'.
 *
 * @param   array  $data  Assoziative array with some values
 * @return  array  Passed parameter
 */
function mr_strCopyCategory(array $data) {
    Contenido_mpDebug::getInstance()->log($data, 'mr_strCopyCategory $data');

    $idcat = (int) $data['newcat']->get('idcat');
    if ($idcat <= 0) {
        return $data;
    }

    // get all cat languages
    $aIdLang = ModRewrite::getCatLanguages($idcat);
    // update ...
    foreach ($aIdLang as $iIdLang) {
        // get urlname
        $sCatname = ModRewrite::getCatName($idcat, $iIdLang);
        // set new urlname - because original set urlname isn't validated for double entries in same parent category
        ModRewrite::setCatWebsafeName($sCatname, $idcat, $iIdLang);
        ModRewrite::setCatUrlPath($idcat, $iIdLang);
    }
}


/**
 * Processes mod_rewrite related job for saved articles (new or modified article).
 *
 * Will be called by chain 'Contenido.Action.con_saveart.AfterCall'.
 *
 * @param   array  $data  Assoziative array with some article properties
 * @return  array  Passed parameter
 */
function mr_conSaveArticle(array $data) {
    Contenido_mpDebug::getInstance()->log($data, 'mr_conSaveArticle $data');

//    if (!isset($title) || ((int) $idart == 0)) {
    if ((int) $data['idart'] == 0) {
        return $data;
    }

    $oGlob = mpGlobals::getInstance();

    if (strlen(trim($data['urlname'])) == 0) {
        $data['urlname'] = $data['title'];
    }

    if (1 == $oGlob->get('tmp_firstedit'))	{
        // new article
        $aLanguages = getLanguagesByClient($oGlob->get('client'));

        foreach ($aLanguages as $iLang) {
            ModRewrite::setArtWebsafeName($data['urlname'], $data['idart'], $iLang, $data['idcat']);
        }

    } else {
        // modified article
        $aArticle = ModRewrite::getArtIdByArtlangId($data['idartlang']);

        if (isset($aArticle['idart']) && isset($aArticle['idlang'])) {
            ModRewrite::setArtWebsafeName($data['urlname'], $aArticle['idart'], $aArticle['idlang'], $data['idcat']);
        }

    }

    return $data;
}


/**
 * Processes mod_rewrite related job for articles beeing moved.
 *
 * Will be called by chain 'Contenido.Article.conMoveArticles_Loop'.
 *
 * @param   array  $data  Assoziative array with record entries
 * @return  array  Loop through of arguments
 */
function mr_conMoveArticles($data){
    Contenido_mpDebug::getInstance()->log($data, 'mr_conMoveArticles $data');

    // too defensive but secure way
    if (!is_array($data)) {
        return $data;
    } elseif (!isset($data['idartlang'])) {
        return $data;
    } elseif (!isset($data['idart'])) {
        return $data;
    }

    $arr_art = ModRewrite::getArtIds($data['idartlang']);
    if (count($arr_art) == 2) {
        ModRewrite::setArtWebsafeName($arr_art["urlname"], $data['idart'], $arr_art["idlang"]);
    }

    return $data;
}


/**
 * Processes mod_rewrite related job for duplicated articles.
 *
 * Will be called by chain 'Contenido.Article.conCopyArtLang_AfterInsert'.
 *
 * @param   array  $data  Assoziative array with record entries
 * @return  array  Loop through of arguments
 */
function mr_conCopyArtLang($data) {
    Contenido_mpDebug::getInstance()->log($data, 'mr_conCopyArtLang $data');

    // too defensive but secure way
    if (!is_array($data)) {
        return $data;
    } elseif (!isset($data['title'])) {
        return $data;
    } elseif (!isset($data['idart'])) {
        return $data;
    } elseif (!isset($data['idlang'])) {
        return $data;
    }

    ModRewrite::setArtWebsafeName($data['title'], $data['idart'], $data['idlang']);

    return $data;
}


/**
 * Processes mod_rewrite related job for synchronized articles.
 *
 * Will be called by chain 'Contenido.Article.conSyncArticle_AfterInsert'.
 *
 * @param   array  $data  Assoziative array with record entries as follows:
 * <code>
 * array(
 *     'src_art_lang'  => Recordset (assoziative array) of source item from con_art_lang table
 *     'dest_art_lang' => Recordset (assoziative array) of inserted destination item from con_art_lang table
 * );
 * </code>
 *
 * @return  array  Loop through of argument
 */
function mr_conSyncArticle($data){
    Contenido_mpDebug::getInstance()->log($data, 'mr_conSyncArticle $data');

    // too defensive but secure way
    if (!is_array($data)) {
        return $data;
    } elseif (!isset($data['src_art_lang']) || !is_array($data['src_art_lang'])) {
        return $data;
    } elseif (!isset($data['dest_art_lang']) || !is_array($data['dest_art_lang'])) {
        return $data;
    } elseif (!isset($data['dest_art_lang']['idart'])) {
        return $data;
    } elseif (!isset($data['dest_art_lang']['idlang'])) {
        return $data;
    }

    if (!isset($data['src_art_lang']['urlname'])) {
        $artLang = new cApiArticleLanguage($data['src_art_lang']['idartlang']);
        $urlname = $artLang->get('urlname');
    } else {
        $urlname = $data['src_art_lang']['urlname'];
    }

    if ($urlname) {
        ModRewrite::setArtWebsafeName($urlname, $data['dest_art_lang']['idart'], $data['dest_art_lang']['idlang']);
    }

    return $data;
}


/**
 * Works as a wrapper for Contenido_Url.
 *
 * Will also be called by chain 'Contenido.Frontend.CreateURL'.
 *
 * @todo: Still exists bcause of downwards compatibility (some other modules/plugins are using it)
 *
 * @param   string  $url  URL to rebuild
 * @return  string        New URL
 */
function mr_buildNewUrl($url) {
    Contenido_mpDebug::getInstance()->addDebug($url, 'mr_buildNewUrl() in -> $url');

    $oUrl = Contenido_Url::getInstance();
    $aUrl = $oUrl->parse($url);

    // add language, if not exists
    if (!isset($aUrl['params']['lang'])) {
        $aUrl['params']['lang'] = mpGlobals::getInstance()->get('lang');
    }

    // build url
    $newUrl = $oUrl->build($aUrl['params']);

    // add existing fragment
    if (isset($aUrl['fragment'])) {
        $newUrl .= '#' . $aUrl['fragment'];
    }

    $arr['in']  = $url;
    $arr['out'] = $newUrl;
    Contenido_mpDebug::getInstance()->addDebug($arr, 'mr_buildNewUrl() in -> out');

    return $newUrl;
}


/**
 * Replaces existing ancors inside passed code, while rebuilding the urls.
 *
 * Will be called by chain 'Contenido.Content.conGenerateCode' or
 * 'Contenido.Frontend.HTMLCodeOutput' depening on mod_rewrite settings.
 *
 * @param   string  $code   Code to prepare
 * @return  string          New code
 */
function mr_buildGeneratedCode($code) {
    Contenido_mpDebug::getInstance()->addDebug($code, 'mr_buildGeneratedCode() in');

    // mod rewrite is activated
    if (ModRewrite::isEnabled()) {
        $sseStarttime = getmicrotime();

        $oGlob = mpGlobals::getInstance();

        // anchor hack
        $code = preg_replace_callback(
            "/<a([^>]*)href\s*=\s*[\"|\'][\/]#(.?|.+?)[\"|\']([^>]*)>/i",
            create_function('$arr_matches' , 'return ModRewrite::rewriteHtmlAnchor($arr_matches);'),
            $code
        );

        // remove fucking tinymce single quote entities:
        $code = str_replace("'", "'", $code);

        // get base uri
        $client = $oGlob->get('client');
        $sBaseUri = $oGlob->get('cfgClient/' . $client . '/path/htmlpath');
        $sBaseUri = CEC_Hook::execute("Contenido.Frontend.BaseHrefGeneration", $sBaseUri);

        // IE hack with wrong base href interpretation // => weg wegen PHP 5.7 oder so
        //$code = preg_replace("/([\"|\'|=])upload\/(.?|.+?)([\"|\'|>])/ie", "stripslashes('\\1{$sBaseUri}upload/\\2\\3')", $code);
		
        // define some preparations to replace /front_content.php & ./front_content.php
        // against front_content.php, because urls should start with front_content.php
        $aPattern = array(
            '/([\"|\'|=])\/front_content\.php(.?|.+?)([\"|\'|>])/i',
            '/([\"|\'|=])\.\/front_content\.php(.?|.+?)([\"|\'|>])/i'
        );

        $aReplace = array(
            '\1front_content.php\2\3',
            '\1front_content.php\2\3'
        );

        // perform the pre replacements
        $code = preg_replace($aPattern, $aReplace, $code);

        // create url stack object and fill it with found urls...
        $oMRUrlStack = ModRewriteUrlStack::getInstance();
        $oMRUrlStack->add('front_content.php');

        preg_match_all("/([\"|\'|=])front_content\.php(.?|.+?)([\"|\'|>])/i", $code, $matches, PREG_SET_ORDER);
        foreach ($matches as $val) {
            $oMRUrlStack->add('front_content.php' . $val[2]);
        }

        // ok let it beginn, start mod rewrite class
        $code = str_replace('"front_content.php"', '"' . mr_buildNewUrl('front_content.php') . '"', $code);
        $code = str_replace("'front_content.php'", "'" . mr_buildNewUrl('front_content.php') . "'", $code);
        $code = preg_replace_callback(
            "/([\"|\'|=])front_content\.php(.?|.+?)([\"|\'|>])/i",
            create_function('$aMatches' , 'return $aMatches[1] . mr_buildNewUrl("front_content.php" . $aMatches[2]) . $aMatches[3];'),
            $code
        );

        Contenido_mpDebug::getInstance()->addDebug($code, 'mr_buildGeneratedCode() out');

        $sseEndtime = getmicrotime();
    } else {
        // anchor hack for non modrewrite websites
        $code = preg_replace_callback(
                    "/<a([^>]*)href\s*=\s*[\"|\'][\/]#(.?|.+?)[\"|\']([^>]*)>/i",
        create_function('$arr_matches' , 'return ModRewrite::contenidoHtmlAnchor($arr_matches, $GLOBALS["is_XHTML"]);'),
        $code
        );
    }

    Contenido_mpDebug::getInstance()->addDebug(($sseEndtime - $sseStarttime), 'mr_buildGeneratedCode() total spend time');

    if ($debug = mr_debugOutput(false)) {
        $code = str_ireplace_once("</body>", $debug . "\n</body>", $code);
    }

    return $code;
    // print "\n\n<!-- modrewrite generation time: " . ($sseEndtime - $sseStarttime) . " seconds -->";
}


/**
 * Sets language of client, like done in front_content.php
 *
 * @param  int  $client  Client id
 */
function mr_setClientLanguageId($client) {
    $oGlob = mpGlobals::getInstance();

    if ((int) $oGlob->get('lang') > 0) {
        // there is nothing to do
        return;
    }

    // use the first language of this client
    if ($oGlob->get('load_lang')) {
        // load_client is set in frontend/config.php
        $oGlob->set('lang', $oGlob->get('load_lang'));
        return;
    }

    $aTab = $oGlob->get('cfg/tab');

    // try to get clients language from table
    $sql = "SELECT B.idlang FROM "
                . $aTab['clients_lang']." AS A, "
                . $aTab['lang']." AS B "
          . "WHERE "
                . "A.idclient='" . ((int) $client) . "' AND A.idlang=B.idlang"
          . "LIMIT 0,1";

    if ($aData = mr_queryAndNextRecord($sql)) {
        $oGlob->set('lang', $aData['idlang']);
    }
}


/**
 * Loads Advanced Mod Rewrite configuration for passed client using serialized
 * file containing the settings.
 *
 * File is placed in /contenido/mod_rewrite/includes/and is named like
 * config.mod_rewrite_{client_id}.php.
 *
 * @param  int   $clientId     Id of client
 * @param  bool  $forceReload  Flag to force to reload configuration, e. g. after
 *                             done changes on it
 */
function mr_loadConfiguration($clientId, $forceReload=false) {
    static $aLoaded;

    $clientId = (int) $clientId;
    if (!isset($aLoaded)) {
        $aLoaded = array();
    } elseif (isset($aLoaded[$clientId]) && $forceReload == false) {
        return;
    }

    $oGlob = mpGlobals::getInstance();
    $aCfg = $oGlob->get('cfg');

    $options['key'] = $aCfg['path']['contenido'] . $aCfg['path']['plugins'] . 'mod_rewrite/includes/config.mod_rewrite_' . $clientId . '.php';

    $config = ConfigFactory::get('filestorage', $options);
    $mrConfig = $config->get();
    if (is_array($mrConfig)) {

        // merge mod rewrite configuration with global cfg array
        $oGlob->set('cfg', array_merge($aCfg, $mrConfig));

    } else {

        // couldn't load configuration, set defaults
        include_once($aCfg['path']['contenido'] . $aCfg['path']['plugins'] . 'mod_rewrite/includes/config.mod_rewrite_default.php');

    }

    $aLoaded[$clientId] = true;
}


/**
 * Includes the frontend controller script which parses the url and extacts
 * needed data like idcat, idart, lang and client from it.
 *
 * Will be called by chain 'Contenido.Frontend.AfterLoadPlugins' at front_content.php.
 *
 * @return  bool  Just a return value
 */
function mr_runFrontendController() {
    $iStartTime = getmicrotime();

    plugin_include('mod_rewrite', 'includes/config.plugin.php');

    if (ModRewrite::isEnabled() == true) {

        plugin_include('mod_rewrite', 'includes/front_content_controller.php');

        $totalTime = sprintf('%.4f', (getmicrotime() - $iStartTime));
        Contenido_mpDebug::getInstance()->addDebug($totalTime, 'mr_runFrontendController() total time');

    }

    return true;
}


/**
 * Cleanups passed string from characters beeing repeated two or more times
 *
 * @param   string  $char    Character to remove
 * @param   string  $string  String to clean from character
 * @return  string  Cleaned string
 */
function mr_removeMultipleChars($char, $string) {
    while (strpos($string, $char . $char) !== false) {
        $string = str_replace($char . $char, $char, $string);
    }
    return $string;
}


/**
 * Returns amr related translation text
 *
 * @param   string  $key    The message id as string
 * @return  string  Related message
 */
function mr_i18n($key) {
    $aLng = mpGlobals::getInstance()->get('lngAMR');
    var_dump($aLng);
    return (is_array($aLng) && isset($aLng[$key])) ? $aLng[$key] : 'n. a.';
}

################################################################################
### Some helper functions, which are not plugin specific


/**
 * Database query helper. Used to execute a select statement and to return the
 * result of first recordset.
 *
 * Minimizes following code:
 * <code>
 * // default way
 * $db  = new DB_Contenido();
 * $sql = "SELECT * FROM foo WHERE bar='foobar'";
 * $db->query($sql);
 * $db->next_record();
 * $data = $db->Record;
 *
 * // new way
 * $sql  = "SELECT * FROM foo WHERE bar='foobar'";
 * $data = mr_queryAndNextRecord($sql);
 * </code>
 *
 * @param   string  $query  Query to execute
 * @return  mixed   Assoziative array including recordset or null
 */
function mr_queryAndNextRecord($query){
    static $db;
    if (!isset($db)) {
        $db = new DB_Contenido();
    }
    if (!$db->query($query)) {
        return null;
    }
    return ($db->next_record()) ? $db->Record : null;
}


/**
 * Returns value of an array key (assoziative or indexed).
 *
 * Shortcut function for some ways to access to arrays:
 * <code>
 * // old way
 * if (is_array($foo) && isset($foo['bar']) && $foo['bar'] == 'yieeha') {
 *     // do something
 * }
 *
 * // new, more readable way:
 * if (mr_arrayValue($foo, 'bar') == 'yieeha') {
 *     // do something
 * }
 *
 * // old way
 * if (is_array($foo) && isset($foo['bar'])) {
 *     $jep = $foo['bar'];
 * } else {
 *     $jep = 'yummy';
 * }
 *
 * // new way
 * $jep = mr_arrayValue($foo, 'bar', 'yummy');
 * </code>
 *
 * @param   array  $array    The array
 * @param   mixed  $key      Position of an indexed array or key of an assoziative array
 * @param   mixed  $default  Default value to return
 * @return  mixed  Either the found value or the default value
 */
function mr_arrayValue($array, $key, $default=null) {
    if (!is_array($array)) {
        return $default;
    } elseif (!isset($array[$key])) {
        return $default;
    } else {
        return $array[$key];
    }
}


/**
 * Request cleanup function. Request data is allways tainted and must be filtered.
 * Pass the array to cleanup using several options.
 * Emulates array_walk_recursive().
 *
 * @param   mixed  $data     Data to cleanup
 * @param   array  $options  Default options array, provides only 'filter' key with several
 *                           filter functions which are to execute as follows:
 * <code>
 * $options['filter'] = array('trim', 'myFilterFunc');
 * </code>
 *                           If no filter functions are set, 'trim', 'strip_tags' and 'stripslashes'
 *                           will be used by default.
 *                           A userdefined function must accept the value as a parameter and must return
 *                           the filtered parameter, e. g.
 * <code>
 * function myFilter($data) {
 *    // do what you want with the data, e. g. cleanup of xss content
 *    return $data;
 * }
 * </code>
 *
 * @return  mixed  Cleaned data
 */
function mr_requestCleanup(&$data, $options=null) {
    if (!mr_arrayValue($options, 'filter')) {
        $options['filter'] = array('trim', 'strip_tags', 'stripslashes');
    }

    if (is_array($data)) {
        foreach ($data as $p => $v) {
            $data[$p] = mr_requestCleanup($v, $options);
        }
    } else {
        foreach ($options['filter'] as $filter) {
            if ($filter == 'trim') {
                $data = trim($data);
            } elseif ($filter == 'strip_tags') {
                $data = strip_tags($data);
            } elseif ($filter == 'stripslashes') {
                $data = stripslashes($data);
            } elseif (function_exists($filter)) {
                $data = call_user_func($filter, $data);
            }
        }
    }
    return $data;
}



/**
 * Replaces calling of header method for redirects in front_content.php,
 * used during development.
 *
 * @param  $header  Header value for redirect
 */
function mr_header($header) {
    header($header);return;

    $header = str_replace('Location: ', '', $header);
    echo '<html>
        <head></head>
        <body>
        <p><a href="'.$header.'">'.$header.'</a></p>';
    mr_debugOutput();
    echo '</body></html>';
    exit();
}


/**
 * Debug output only during development
 *
 * @param   bool  $print  Flag to echo the debug data
 * @return  mixed  Either the debug data, if parameter $print is set to true, or nothing
 */
function mr_debugOutput($print=true) {
    $oDebug = Contenido_mpDebug::getInstance();

    $queryCache = mpGlobals::getInstance()->get('DB_Contenido_QueryCache');
    if (is_array($queryCache) && count($queryCache) > 0) {
        $oDebug->addDebug($queryCache, 'sql statements');

        // calculate total time consumption of queries
        $timeTotal = 0;
        foreach ($queryCache as $pos => $item) {
            $timeTotal += $item['time'];
        }
        $oDebug->addDebug($timeTotal, 'sql total time');
    }

    if ($print == true) {
        echo $oDebug->getResults();
    } else {
        return $oDebug->getResults(false);
    }
}

Gesperrt