Source for file functions.mod_rewrite.php
Documentation is available at functions.mod_rewrite.php
* Defines the 'modrewrite' related helper functions
* @author Stefan Seifarth / stese
* @copyright © www.polycoder.de
* @author Murat Purc <murat@purc.de>
/******************************************
* File : functions.mod_rewrite.php
* Descr : Defines the 'modrewrite' related
* Author : Stefan Seifarth
******************************************/
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
// 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
* 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
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
* 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
Contenido_mpDebug::getInstance()->log($data, 'mr_strRenameCategory $data');
$mrCatAlias =
(trim($data['newcategoryalias']) !==
'') ?
trim($data['newcategoryalias']) :
trim($data['newcategoryname']);
// set new urlname - because original set urlname isn''t validated for double entries in same parent category
* 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
Contenido_mpDebug::getInstance()->log($idcat, 'mr_strMoveUpCategory $idcat');
$cat =
new cApiCategory((int)
$idcat);
if (!$cat->get('preid')) {
foreach ($aIdLang as $iIdLang) {
// set new urlname - because original set urlname isn't validated for double entries in same parent category
* 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
Contenido_mpDebug::getInstance()->log($idcat, 'mr_strMovedownCategory $idcat');
$cat =
new cApiCategory((int)
$idcat);
foreach ($aIdLang as $iIdLang) {
// set new urlname - because original set urlname isn't validated for double entries in same parent category
* 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
Contenido_mpDebug::getInstance()->log($data, 'mr_strMoveSubtree $data');
if ((int)
$data['idcat'] <=
0) {
$cat =
new cApiCategory($data['idcat']);
if (!$cat->get('idcat')) {
foreach ($aIdLang as $iIdLang) {
// set new urlname - because original set urlname isn't validated for double entries in same parent category
// now dive into all existing subcategories and modify their paths too...
$oCatColl =
new cApiCategoryCollection('parentid=' .
$data['idcat']);
while ($oCat =
$oCatColl->next()) {
* 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
Contenido_mpDebug::getInstance()->log($data, 'mr_strCopyCategory $data');
$idcat = (int)
$data['newcat']->get('idcat');
foreach ($aIdLang as $iIdLang) {
// set new urlname - because original set urlname isn't validated for double entries in same parent category
* 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
Contenido_mpDebug::getInstance()->log($data, 'mr_conSaveArticle $data');
// if (!isset($title) || ((int) $idart == 0)) {
if ((int)
$data['idart'] ==
0) {
$oGlob =
mpGlobals::getInstance();
$data['urlname'] =
$data['title'];
if (1 ==
$oGlob->get('tmp_firstedit')) {
$aLanguages =
getLanguagesByClient($oGlob->get('client'));
foreach ($aLanguages as $iLang) {
if (isset
($aArticle['idart']) && isset
($aArticle['idlang'])) {
* 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
Contenido_mpDebug::getInstance()->log($data, 'mr_conMoveArticles $data');
// too defensive but secure way
} elseif (!isset
($data['idartlang'])) {
} elseif (!isset
($data['idart'])) {
if (count($arr_art) ==
2) {
* 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
Contenido_mpDebug::getInstance()->log($data, 'mr_conCopyArtLang $data');
// too defensive but secure way
} elseif (!isset
($data['title'])) {
} elseif (!isset
($data['idart'])) {
} elseif (!isset
($data['idlang'])) {
* 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:
* '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
* @return array Loop through of argument
Contenido_mpDebug::getInstance()->log($data, 'mr_conSyncArticle $data');
// too defensive but secure way
} elseif (!isset
($data['src_art_lang']) ||
!is_array($data['src_art_lang'])) {
} elseif (!isset
($data['dest_art_lang']) ||
!is_array($data['dest_art_lang'])) {
} elseif (!isset
($data['dest_art_lang']['idart'])) {
} elseif (!isset
($data['dest_art_lang']['idlang'])) {
if (!isset
($data['src_art_lang']['urlname'])) {
$artLang =
new cApiArticleLanguage($data['src_art_lang']['idartlang']);
$urlname =
$artLang->get('urlname');
$urlname =
$data['src_art_lang']['urlname'];
* Works as a wrapper for creation of urls using Contenido_UrlBuilder_MR.
* Will be called by chain 'Contenido.Frontend.CreateURL'.
* @param string $url URL to rebuild
if (!isset
($mrUrlBuilder)) {
cInclude('classes', 'UrlBuilder/Contenido_UrlBuilder_MR.class.php');
$mrUrlBuilder->buildUrl(array($url));
$newUrl =
$mrUrlBuilder->getUrl();
$urlDebug['out'] =
$newUrl;
Contenido_mpDebug::getInstance()->addDebug($urlDebug, 'mr_buildNewUrl() in -> out');
* 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
Contenido_mpDebug::getInstance()->addDebug($code, 'mr_buildGeneratedCode() in');
// mod rewrite is activated
$sseStarttime =
getmicrotime();
$oGlob =
mpGlobals::getInstance();
"/<a([^>]*)href\s*=\s*[\"|\'][\/]#(.?|.+?)[\"|\']([^>]*)>/i",
create_function('$arr_matches' , 'return ModRewrite::rewriteHtmlAnchor($arr_matches);'),
// remove fucking tinymce single quote entities:
$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
$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
'/([\"|\'|=])\/front_content\.php(.?|.+?)([\"|\'|>])/i',
'/([\"|\'|=])\.\/front_content\.php(.?|.+?)([\"|\'|>])/i'
'\1front_content.php\2\3',
'\1front_content.php\2\3'
// perform the pre replacements
// create url stack object and fill it with found urls...
$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
"/([\"|\'|=])front_content\.php(.?|.+?)([\"|\'|>])/i",
create_function('$aMatches' , 'return $aMatches[1] . mr_buildNewUrl("front_content.php" . $aMatches[2]) . $aMatches[3];'),
Contenido_mpDebug::getInstance()->addDebug($code, 'mr_buildGeneratedCode() out');
$sseEndtime =
getmicrotime();
// anchor hack for non modrewrite websites
"/<a([^>]*)href\s*=\s*[\"|\'][\/]#(.?|.+?)[\"|\']([^>]*)>/i",
create_function('$arr_matches' , 'return ModRewrite::contenidoHtmlAnchor($arr_matches, $GLOBALS["is_XHTML"]);'),
Contenido_mpDebug::getInstance()->addDebug(($sseEndtime -
$sseStarttime), 'mr_buildGeneratedCode() total spend time');
$code =
str_ireplace_once("</body>", $debug .
"\n</body>", $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
$oGlob =
mpGlobals::getInstance();
if ((int)
$oGlob->get('lang') >
0) {
// there is nothing to do
// 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'));
$aTab =
$oGlob->get('cfg/tab');
// try to get clients language from table
$sql =
"SELECT B.idlang FROM "
.
$aTab['clients_lang'].
" AS A, "
.
"A.idclient='" .
((int)
$client) .
"' AND A.idlang=B.idlang"
$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
$clientId = (int)
$clientId;
} elseif (isset
($aLoaded[$clientId]) &&
$forceReload ==
false) {
$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();
// merge mod rewrite configuration with global cfg array
// 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
$iStartTime =
getmicrotime();
plugin_include('mod_rewrite', 'includes/config.plugin.php');
plugin_include('mod_rewrite', 'includes/front_content_controller.php');
$totalTime =
sprintf('%.4f', (getmicrotime() -
$iStartTime));
Contenido_mpDebug::getInstance()->addDebug($totalTime, 'mr_runFrontendController() total time');
* 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
while (strpos($string, $char .
$char) !==
false) {
################################################################################
### Some helper fuctions, 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:
* $db = new DB_Contenido();
* $sql = "SELECT * FROM foo WHERE bar='foobar'";
* $sql = "SELECT * FROM foo WHERE bar='foobar'";
* $data = mr_queryAndNextRecord($sql);
* @param string $query Query to execute
* @return mixed Assoziative array including recordset or null
$db =
new DB_Contenido();
if (!$db->query($query)) {
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:
* if (is_array($foo) && isset($foo['bar']) && $foo['bar'] == 'yieeha') {
* // new, more readable way:
* if (mr_arrayValue($foo, 'bar') == 'yieeha') {
* if (is_array($foo) && isset($foo['bar'])) {
* $jep = mr_arrayValue($foo, 'bar', 'yummy');
* @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
} elseif (!isset
($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:
* $options['filter'] = array('trim', 'myFilterFunc');
* 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.
* function myFilter($data) {
* // do what you want with the data, e. g. cleanup of xss content
* @return mixed Cleaned data
$options['filter'] =
array('trim', 'strip_tags', 'stripslashes');
foreach ($data as $p =>
$v) {
foreach ($options['filter'] as $filter) {
} elseif ($filter ==
'strip_tags') {
} elseif ($filter ==
'stripslashes') {
* Replaces calling of header method for redirects in front_content.php,
* used during development.
* @param $header Header value for redirect
<p><a href="'.
$header.
'">'.
$header.
'</a></p>';
* Debug output only during development
$oDebug =
Contenido_mpDebug::getInstance();
$queryCache =
mpGlobals::getInstance()->get('DB_Contenido_QueryCache');
$oDebug->addDebug($queryCache, 'sql statements');
// calculate total time consumption of queries
foreach ($queryCache as $pos =>
$item) {
$timeTotal +=
$item['time'];
$oDebug->addDebug($timeTotal, 'sql total time');
echo
$oDebug->getResults();
return $oDebug->getResults(false);
Documentation generated on Tue, 25 Nov 2008 22:07:38 +0100 by phpDocumentor 1.4.1