Overview

Packages

  • CONTENIDO
  • Core
    • Authentication
    • Backend
    • Cache
    • CEC
    • Chain
    • ContentType
    • Database
    • Debug
    • Exception
    • Frontend
      • Search
      • URI
      • Util
    • GenericDB
      • Model
    • GUI
      • HTML
    • I18N
    • LayoutHandler
    • Log
    • Security
    • Session
    • Util
    • Validation
    • Versioning
    • XML
  • Module
    • ContentSitemapHtml
    • ContentSitemapXml
    • ContentUserForum
    • NavigationTop
    • ScriptCookieDirective
  • mpAutoloaderClassMap
  • None
  • PHP
  • Plugin
    • ContentAllocation
    • CronjobOverview
    • FormAssistant
    • FrontendLogic
    • FrontendUsers
    • Linkchecker
    • ModRewrite
    • Newsletter
    • Repository
      • FrontendNavigation
      • KeywordDensity
    • SmartyWrapper
    • UrlShortener
    • UserForum
    • Workflow
  • PluginManager
  • Setup
    • Form
    • GUI
    • Helper
      • Environment
      • Filesystem
      • MySQL
      • PHP
    • UpgradeJob

Classes

  • cUriBuilderMR
  • ModRewrite
  • ModRewrite_ContentController
  • ModRewrite_ContentExpertController
  • ModRewrite_ContentTestController
  • ModRewrite_ControllerAbstract
  • ModRewriteBase
  • ModRewriteController
  • ModRewriteDebugger
  • ModRewriteTest
  • ModRewriteUrlStack
  • ModRewriteUrlUtil

Functions

  • mr_arrayValue
  • mr_buildGeneratedCode
  • mr_buildNewUrl
  • mr_conCopyArtLang
  • mr_conMoveArticles
  • mr_conSaveArticle
  • mr_conSyncArticle
  • mr_debugOutput
  • mr_getConfiguration
  • mr_getConfigurationFilePath
  • mr_getRequest
  • mr_header
  • mr_i18n
  • mr_loadConfiguration
  • mr_queryAndNextRecord
  • mr_removeMultipleChars
  • mr_requestCleanup
  • mr_runFrontendController
  • mr_setClientLanguageId
  • mr_setConfiguration
  • mr_strCopyCategory
  • mr_strMovedownCategory
  • mr_strMoveSubtree
  • mr_strMoveUpCategory
  • mr_strNewCategory
  • mr_strNewTree
  • mr_strRenameCategory
  • mr_strSyncCategory
  • Overview
  • Package
  • Class
  • Tree
  • Deprecated
  • Todo
   1: <?php
   2: /**
   3:  * AMR Mod Rewrite helper class
   4:  *
   5:  * @package     Plugin
   6:  * @subpackage  ModRewrite
   7:  * @id          $Id$:
   8:  * @author      Stefan Seifarth / stese
   9:  * @author      Murat Purc <murat@purc.de>
  10:  * @copyright   www.polycoder.de
  11:  * @copyright   four for business AG <www.4fb.de>
  12:  * @license     http://www.contenido.org/license/LIZENZ.txt
  13:  * @link        http://www.4fb.de
  14:  * @link        http://www.contenido.org
  15:  */
  16: 
  17: defined('CON_FRAMEWORK') || die('Illegal call: Missing framework initialization - request aborted.');
  18: 
  19: /**
  20:  * Class to create websafe names, it also provides several helper functions
  21:  *
  22:  * @author      Stefan Seifarth / stese
  23:  * @author      Murat Purc <murat@purc.de>
  24:  * @package     Plugin
  25:  * @subpackage  ModRewrite
  26:  */
  27: class ModRewrite extends ModRewriteBase {
  28: 
  29:     /**
  30:      * Database instance
  31:      *
  32:      * @var  cDb
  33:      */
  34:     private static $_db;
  35: 
  36:     /**
  37:      * Lookup table to cache some internal data such as db query results
  38:      *
  39:      * @var  array
  40:      */
  41:     protected static $_lookupTable;
  42: 
  43:     /**
  44:      * Initialization, is to call at least once, also possible to call multible
  45:      * times, if different client configuration is to load.
  46:      *
  47:      * Loads configuration of passed client and sets some properties.
  48:      *
  49:      * @param  int  $clientId  Client id
  50:      */
  51:     public static function initialize($clientId) {
  52:         mr_loadConfiguration($clientId, true);
  53:         self::$_db = cRegistry::getDb();
  54:         self::$_lookupTable = [];
  55:     }
  56: 
  57:     /**
  58:      * Check categories on websafe name
  59:      *
  60:      * Check all categories in the main parent category on existing same websafe name
  61:      *
  62:      * @param   string  $sName    Websafe name to check
  63:      * @param   int     $iCatId   Current category id
  64:      * @param   int     $iLangId  Current language id
  65:      * @return  bool    True if websafename already exists, false if not
  66:      */
  67:     public static function isInCategories($sName = '', $iCatId = 0, $iLangId = 0) {
  68:         $cfg = cRegistry::getConfig();
  69:         $iCatId = cSecurity::toInteger($iCatId);
  70:         $iLangId = cSecurity::toInteger($iLangId);
  71: 
  72:         // get parentid
  73:         $iParentId = 0;
  74:         $sql = "SELECT parentid FROM " . $cfg['tab']['cat'] . " WHERE idcat = " . $iCatId;
  75:         if ($aData = mr_queryAndNextRecord($sql)) {
  76:             $iParentId = ($aData['parentid'] > 0) ? cSecurity::toInteger($aData['parentid']) : 0;
  77:         }
  78: 
  79:         // check if websafe name is in this category
  80:         $sql = "SELECT count(cl.idcat) as numcats FROM " . $cfg['tab']['cat_lang'] . " cl "
  81:                 . "LEFT JOIN " . $cfg['tab']['cat'] . " c ON cl.idcat = c.idcat WHERE "
  82:                 . "c.parentid = '$iParentId' AND cl.idlang = " . $iLangId . " AND "
  83:                 . "LOWER(cl.urlname) = LOWER('" . self::$_db->escape($sName) . "') AND cl.idcat <> " . $iCatId;
  84:         ModRewriteDebugger::log($sql, 'ModRewrite::isInCategories $sql');
  85: 
  86:         if ($aData = mr_queryAndNextRecord($sql)) {
  87:             return ($aData['numcats'] > 0) ? true : false;
  88:         }
  89: 
  90:         return false;
  91:     }
  92: 
  93:     /**
  94:      * Check articles on websafe name.
  95:      *
  96:      * Check all articles in the current category on existing same websafe name.
  97:      *
  98:      * @internal This method only considers the case that articles are related to a single category.
  99:      *           The function conIsArticleUrlnameUnique also considers multiple categories.
 100:      *
 101:      * @param    string  $sName    Websafe name to check
 102:      * @param    int     $iArtId   Current article id
 103:      * @param    int     $iLangId  Current language id
 104:      * @param    int     $iCatId   Category id
 105:      * @return   bool    True if websafename already exists, false if not
 106:      */
 107:     public static function isInCatArticles($sName = '', $iArtId = 0, $iLangId = 0, $iCatId = 0) {
 108:         $cfg = cRegistry::getConfig();
 109:         $iArtId = cSecurity::toInteger($iArtId);
 110:         $iLangId = cSecurity::toInteger($iLangId);
 111:         $iCatId = cSecurity::toInteger($iCatId);
 112: 
 113:         // handle multipages
 114:         if ($iCatId == 0) {
 115:             // get category id if not set
 116:             $sql = "SELECT idcat FROM " . $cfg['tab']['cat_art'] . " WHERE idart = " . $iArtId;
 117:             if ($aData = mr_queryAndNextRecord($sql)) {
 118:                 $iCatId = ($aData['idcat'] > 0) ? cSecurity::toInteger($aData['idcat']) : 0;
 119:             }
 120:         }
 121: 
 122:         // check if websafe name is in this category
 123:         $sql = "SELECT count(al.idart) as numcats FROM " . $cfg['tab']['art_lang'] . " al "
 124:                 . "LEFT JOIN " . $cfg['tab']['cat_art'] . " ca ON al.idart = ca.idart WHERE "
 125:                 . " ca.idcat='$iCatId' AND al.idlang=" . $iLangId . " AND "
 126:                 . "LOWER(al.urlname) = LOWER('" . self::$_db->escape($sName) . "') AND al.idart <> " . $iArtId;
 127:         if ($aData = mr_queryAndNextRecord($sql)) {
 128:             return ($aData['numcats'] > 0) ? true : false;
 129:         }
 130: 
 131:         return false;
 132:     }
 133: 
 134:     /**
 135:      * Set websafe name in article list.
 136:      *
 137:      * Insert new websafe name in article list
 138:      *
 139:      * @param   string  $sName    Original name (will be converted)
 140:      * @param   int     $iArtId   Current article id
 141:      * @param   int     $iLangId  Current language id
 142:      * @param   int     $iCatId   Category id
 143:      * @return  bool    True if insert was successfully
 144:      * @throws  cInvalidArgumentException
 145:      * @throws  cDbException
 146:      */
 147:     public static function setArtWebsafeName($sName = '', $iArtId = 0, $iLangId = 0, $iCatId = 0) {
 148:         $cfg = cRegistry::getConfig();
 149:         $iArtId = cSecurity::toInteger($iArtId);
 150:         $iLangId = cSecurity::toInteger($iLangId);
 151:         $iCatId = cSecurity::toInteger($iCatId);
 152: 
 153:         // get websafe name
 154:         $sNewName = cString::cleanURLCharacters(conHtmlEntityDecode($sName));
 155: 
 156:         // remove double or more separators
 157:         $sNewName = mr_removeMultipleChars('-', $sNewName);
 158: 
 159:         // check if websafe name already exists
 160:         if (self::isInCatArticles($sNewName, $iArtId, $iLangId, $iCatId)) {
 161:             // create new websafe name if exists
 162:             $sNewName = $sNewName . $iArtId;
 163:         }
 164: 
 165:         // check again - and set name
 166:         if (!self::isInCatArticles($sNewName, $iArtId, $iLangId, $iCatId)) {
 167:             // insert websafe name in article list
 168:             $sql = "UPDATE " . $cfg['tab']['art_lang'] . " SET urlname = '" . self::$_db->escape($sNewName) . "' "
 169:                 . "WHERE idart = " . $iArtId . " AND idlang = " . $iLangId;
 170:             return self::$_db->query($sql);
 171:         } else {
 172:             return false;
 173:         }
 174:     }
 175: 
 176:     /**
 177:      * Set websafe name in category list.
 178:      *
 179:      * Insert new websafe name in category list.
 180:      *
 181:      * @param   string  $sName    Original name (will be converted) or alias
 182:      * @param   int     $iCatId   Category id
 183:      * @param   int     $iLangId  Language id
 184:      * @return  bool    True if insert was successfully
 185:      * @throws  cInvalidArgumentException
 186:      * @throws  cDbException
 187:      */
 188:     public static function setCatWebsafeName($sName = '', $iCatId = 0, $iLangId = 0) {
 189:         $cfg = cRegistry::getConfig();
 190:         $iCatId = cSecurity::toInteger($iCatId);
 191:         $iLangId = cSecurity::toInteger($iLangId);
 192: 
 193:         // create websafe name
 194:         $sNewName = cString::cleanURLCharacters(conHtmlEntityDecode($sName));
 195: 
 196:         // remove double or more separators
 197:         $sNewName = mr_removeMultipleChars('-', $sNewName);
 198: 
 199:         // check if websafe name already exists
 200:         if (self::isInCategories($sNewName, $iCatId, $iLangId)) {
 201:             // create new websafe name if exists
 202:             $sNewName = $sNewName . $iCatId;
 203:         }
 204: 
 205:         // check again - and set name
 206:         if (!self::isInCategories($sNewName, $iCatId, $iLangId)) {
 207:             // update urlname
 208:             $sql = "UPDATE " . $cfg['tab']['cat_lang'] . " SET urlname = '" . self::$_db->escape($sNewName) . "' "
 209:                 . "WHERE idcat = " . $iCatId . " AND idlang = " . $iLangId;
 210: 
 211:             ModRewriteDebugger::log([
 212:                 'sName' => $sName,
 213:                 'iCatId' => $iCatId,
 214:                 'iLangId' => $iLangId,
 215:                 'sNewName' => $sNewName
 216:             ], 'ModRewrite::setCatWebsafeName $data');
 217: 
 218:             return self::$_db->query($sql);
 219:         } else {
 220:             return false;
 221:         }
 222:     }
 223: 
 224:     /**
 225:      * Set urlpath of category
 226:      *
 227:      * @param   int     $iCatId   Category id
 228:      * @param   int     $iLangId  Language id
 229:      * @return  bool    True if insert was successfully
 230:      * @throws  cDbException
 231:      */
 232:     public static function setCatUrlPath($iCatId = 0, $iLangId = 0) {
 233:         $cfg = cRegistry::getConfig();
 234:         $sPath = self::buildRecursivPath($iCatId, $iLangId);
 235:         $iCatId = cSecurity::toInteger($iCatId);
 236:         $iLangId = cSecurity::toInteger($iLangId);
 237: 
 238:         // update urlpath
 239:         $sql = "UPDATE " . $cfg['tab']['cat_lang'] . " SET urlpath = '" . self::$_db->escape($sPath) . "' "
 240:             . "WHERE idcat = " . $iCatId . " AND idlang = " . $iLangId;
 241: 
 242:         ModRewriteDebugger::log([
 243:             'iCatId' => $iCatId,
 244:             'iLangId' => $iLangId,
 245:             'sPath' => $sPath
 246:         ], 'ModRewrite::setCatUrlPath $data');
 247: 
 248:         return self::$_db->query($sql);
 249:     }
 250: 
 251:     /**
 252:      * Get article id and language id from article language id
 253:      *
 254:      * @param   int    $iArtlangId  Current article id
 255:      * @return  array  Array with idart and idlang of current article
 256:      */
 257:     public static function getArtIdByArtlangId($iArtlangId = 0) {
 258:         $cfg = cRegistry::getConfig();
 259:         $iArtlangId = cSecurity::toInteger($iArtlangId);
 260:         $sql = "SELECT idart, idlang FROM " . $cfg['tab']['art_lang'] . " WHERE idartlang = " . $iArtlangId;
 261:         if ($aData = mr_queryAndNextRecord($sql)) {
 262:             return $aData;
 263:         }
 264:         return [];
 265:     }
 266: 
 267:     /**
 268:      * Get article id by article websafe name
 269:      *
 270:      * @param   string    $sArtName  Websafe name
 271:      * @param   int       $iCatId    Category id
 272:      * @param   int       $iLangId   Language id
 273:      * @return  int|NULL  Recent article id or NULL
 274:      * @throws  cDbException
 275:      */
 276:     public static function getArtIdByWebsafeName($sArtName = '', $iCatId = 0, $iLangId = 0) {
 277:         $cfg = cRegistry::getConfig();
 278:         $lang = cRegistry::getLanguageId();
 279:         $iCatId = cSecurity::toInteger($iCatId);
 280:         $iLangId = cSecurity::toInteger($iLangId);
 281:         if (0 === $iLangId && is_int($lang)) {
 282:             $iLangId = $lang;
 283:         }
 284: 
 285:         $sWhere = '';
 286:         if ($iLangId !== 0) {
 287:             $sWhere = ' AND al.idlang = ' . $iLangId;
 288:         }
 289:         // only article name were given
 290:         if ($iCatId == 0) {
 291:             // get all basic category ids with parentid=0
 292:             $aCatIds = [];
 293:             $sql = "SELECT idcat FROM " . $cfg['tab']['cat'] . " WHERE parentid = 0";
 294:             self::$_db->query($sql);
 295:             while (self::$_db->nextRecord()) {
 296:                 $aCatIds[] = "idcat = " . cSecurity::toInteger(self::$_db->f('idcat'));
 297:             }
 298:             $sWhere .= " AND (" . join(" OR ", $aCatIds) . ")";
 299:         } else {
 300:             $sWhere .= " AND ca.idcat = " . $iCatId;
 301:         }
 302: 
 303:         $sql = "SELECT al.idart FROM " . $cfg['tab']['art_lang'] . " al "
 304:             . "LEFT JOIN " . $cfg['tab']['cat_art'] . " ca ON al.idart = ca.idart "
 305:             . "WHERE LOWER(al.urlname) = LOWER('" . self::$_db->escape($sArtName) . "')" . $sWhere;
 306: 
 307:         if ($aData = mr_queryAndNextRecord($sql)) {
 308:             return $aData['idart'];
 309:         } else {
 310:             return NULL;
 311:         }
 312:     }
 313: 
 314:     /**
 315:      * Get category name from category id and language id.
 316:      *
 317:      * @param   int     $iCatId   Category id
 318:      * @param   int     $iLangId  Language id
 319:      * @return  string  Category name
 320:      */
 321:     public static function getCatName($iCatId = 0, $iLangId = 0) {
 322:         $cfg = cRegistry::getConfig();
 323:         $iCatId = cSecurity::toInteger($iCatId);
 324:         $iLangId = cSecurity::toInteger($iLangId);
 325:         $key = 'catname_by_catid_idlang_' . $iCatId . '_' . $iLangId;
 326: 
 327:         if (isset(self::$_lookupTable[$key])) {
 328:             return self::$_lookupTable[$key];
 329:         }
 330: 
 331:         $sql = "SELECT name FROM " . $cfg['tab']['cat_lang']
 332:             . " WHERE idcat = " . $iCatId . " AND idlang = " . $iLangId;
 333:         if ($aData = mr_queryAndNextRecord($sql)) {
 334:             $catName = $aData['name'];
 335:         } else {
 336:             $catName = '';
 337:         }
 338: 
 339:         self::$_lookupTable[$key] = $catName;
 340:         return $catName;
 341:     }
 342: 
 343:     /**
 344:      * Funcion to return cat id by path.
 345:      *
 346:      * Caches the paths at first call to provode faster processing at further calls.
 347:      *
 348:      * @param   string  $path  Category path
 349:      * @return  int  Category id
 350:      * @throws  cDbException
 351:      */
 352:     public static function getCatIdByUrlPath($path) {
 353:         $cfg = cRegistry::getConfig();
 354:         $lang = cRegistry::getLanguageId();
 355:         $client = cRegistry::getClientId();
 356: 
 357:         if (cString::findFirstPos($path, '/') === 0) {
 358:             $path = cString::getPartOfString($path, 1);
 359:         }
 360:         if (cString::findLastPos($path, '/') === cString::getStringLength($path) - 1) {
 361:             $path = cString::getPartOfString($path, 0, -1);
 362:         }
 363: 
 364:         $catSeperator = '/';
 365:         $startFromRoot = parent::getConfig('startfromroot');
 366:         $urls2lowercase = parent::getConfig('use_lowercase_uri');
 367: 
 368:         $path = str_replace('/', parent::getConfig('category_seperator'), $path);
 369: 
 370:         $key = 'cat_ids_and_urlpath_' . $client . '_' . $lang;
 371: 
 372:         if (isset(self::$_lookupTable[$key])) {
 373:             $aPathsCache = self::$_lookupTable[$key];
 374:         } else {
 375:             $aPathsCache = [];
 376:         }
 377: 
 378:         if (count($aPathsCache) == 0) {
 379:             $sql = "SELECT cl.idcat, cl.urlpath FROM " . $cfg['tab']['cat_lang']
 380:                 . " AS cl, " . $cfg['tab']['cat'] . " AS c WHERE c.idclient = " . cSecurity::toInteger($client)
 381:                 . " AND c.idcat = cl.idcat AND cl.idlang = " . cSecurity::toInteger($lang);
 382: 
 383:             self::$_db->query($sql);
 384:             while (self::$_db->nextRecord()) {
 385:                 $urlPath = self::$_db->f('urlpath');
 386:                 if ($startFromRoot == 0 && cString::findFirstPos($urlPath, $catSeperator) > 0) {
 387:                     // paths are stored with prefixed main category, but created
 388:                     // urls doesn't contain the main cat, remove it...
 389:                     $urlPath = cString::getPartOfString($urlPath, cString::findFirstPos($urlPath, $catSeperator) + 1);
 390:                 }
 391:                 if ($urls2lowercase) {
 392:                     $urlPath = cString::toLowerCase($urlPath);
 393:                 }
 394: 
 395:                 // store path
 396:                 $aPathsCache[self::$_db->f('idcat')] = $urlPath;
 397:             }
 398:         }
 399:         self::$_lookupTable[$key] = $aPathsCache;
 400: 
 401:         // compare paths using the similar_text algorithm
 402:         $fPercent = 0;
 403:         $aResults = [];
 404:         foreach ($aPathsCache as $id => $pathItem) {
 405:             similar_text($path, $pathItem, $fPercent);
 406:             $aResults[$id] = $fPercent;
 407:         }
 408: 
 409:         arsort($aResults, SORT_NUMERIC);
 410:         reset($aResults);
 411: 
 412:         ModRewriteDebugger::add($path, 'ModRewrite::getCatIdByUrlPath() $path');
 413:         ModRewriteDebugger::add($aPathsCache, 'ModRewrite::getCatIdByUrlPath() $aPathsCache');
 414:         ModRewriteDebugger::add($aResults, 'ModRewrite::getCatIdByUrlPath() $aResults');
 415: 
 416:         $iMinPercentage = cSecurity::toInteger(parent::getConfig('category_resolve_min_percentage', 0));
 417:         $catId = key($aResults);
 418:         if ($iMinPercentage > 0 && $aResults[$catId] < $iMinPercentage) {
 419:             return 0;
 420:         } else {
 421:             return $catId;
 422:         }
 423:     }
 424: 
 425:     /**
 426:      * Get article name from article id and language id
 427:      *
 428:      * @NOTE: seems to be not used???
 429:      *
 430:      * @param   int     $iArtId   Article id
 431:      * @param   int     $iLangId  Language id
 432:      * @return  string  Article name
 433:      */
 434:     public static function getArtTitle($iArtId = 0, $iLangId = 0) {
 435:         $cfg = cRegistry::getConfig();
 436:         $iArtId = cSecurity::toInteger($iArtId);
 437:         $iLangId = cSecurity::toInteger($iLangId);
 438: 
 439:         $sql = "SELECT title FROM " . $cfg['tab']['art_lang']
 440:             . " WHERE idart = " . $iArtId . " AND idlang = " . $iLangId;
 441:         if ($aData = mr_queryAndNextRecord($sql)) {
 442:             return $aData['title'];
 443:         }
 444:         return '';
 445:     }
 446: 
 447:     /**
 448:      * Get language ids from category id
 449:      *
 450:      * @param   int    $iCatId  Category id
 451:      * @return  array  Used language ids
 452:      * @throws  cDbException
 453:      */
 454:     public static function getCatLanguages($iCatId = 0) {
 455:         $cfg = cRegistry::getConfig();
 456:         $iCatId = cSecurity::toInteger($iCatId);
 457:         $key = 'cat_idlang_by_catid_' . $iCatId;
 458: 
 459:         if (isset(self::$_lookupTable[$key])) {
 460:             return self::$_lookupTable[$key];
 461:         }
 462: 
 463:         $aLanguages = [];
 464: 
 465:         $sql = "SELECT idlang FROM " . $cfg['tab']['cat_lang'] . " WHERE idcat = " . $iCatId;
 466:         self::$_db->query($sql);
 467:         while (self::$_db->nextRecord()) {
 468:             $aLanguages[] = self::$_db->f('idlang');
 469:         }
 470: 
 471:         self::$_lookupTable[$key] = $aLanguages;
 472:         return $aLanguages;
 473:     }
 474: 
 475:     /**
 476:      * Get article urlname and language id
 477:      *
 478:      * @param   int    $iArtlangId  idartlang
 479:      * @return  array  Urlname, idlang of empty array
 480:      */
 481:     public static function getArtIds($iArtlangId = 0) {
 482:         $cfg = cRegistry::getConfig();
 483:         $iArtlangId = cSecurity::toInteger($iArtlangId);
 484:         $sql = "SELECT urlname, idlang FROM " . $cfg['tab']['art_lang']
 485:             . " WHERE idartlang = " . $iArtlangId;
 486:         if ($aData = mr_queryAndNextRecord($sql)) {
 487:             return $aData;
 488:         }
 489:         return [];
 490:     }
 491: 
 492:     /**
 493:      * Build a recursiv path for mod_rewrite rule like server directories
 494:      * (dir1/dir2/dir3)
 495:      *
 496:      * @param   int     $iCatId   Latest category id
 497:      * @param   int     $iLangId  Language id
 498:      * @param   int     $iLastId  Last category id
 499:      * @return  string    linkpath with correct uri
 500:      */
 501:     public static function buildRecursivPath($iCatId = 0, $iLangId = 0, $iLastId = 0) {
 502:         $cfg = cRegistry::getConfig();
 503:         $aDirectories = [];
 504:         $bFinish = false;
 505:         $iTmpCatId = cSecurity::toInteger($iCatId);
 506:         $iLangId = cSecurity::toInteger($iLangId);
 507:         $iLastId = cSecurity::toInteger($iLastId);
 508: 
 509:         while ($bFinish == false) {
 510:             $sql = "SELECT cl.urlname, c.parentid FROM " . $cfg['tab']['cat_lang'] . " cl "
 511:                 . "LEFT JOIN " . $cfg['tab']['cat'] . " c ON cl.idcat = c.idcat "
 512:                 . "WHERE cl.idcat = " . $iTmpCatId . " AND cl.idlang = " . $iLangId;
 513:             if ($aData = mr_queryAndNextRecord($sql)) {
 514:                 $aDirectories[] = $aData['urlname'];
 515:                 $iTmpCatId = cSecurity::toInteger($aData['parentid']);
 516: 
 517:                 if ($aData['parentid'] == 0 || $aData['parentid'] == $iLastId) {
 518:                     $bFinish = true;
 519:                 }
 520:             } else {
 521:                 $bFinish = true;
 522:             }
 523:         }
 524: 
 525:         // reverse array entries and create directory string
 526:         $sPath = join('/', array_reverse($aDirectories));
 527: 
 528:         return $sPath;
 529:     }
 530: 
 531:     /**
 532:      * Return full CONTENIDO url from single anchor
 533:      *
 534:      * @param   array   $aMatches [0] = complete anchor, [1] = pre arguments, [2] = anchor name, [3] = post arguments
 535:      * @return  string  New anchor
 536:      */
 537:     public static function rewriteHtmlAnchor(array $aMatches = []) {
 538:         global $artname;
 539: 
 540:         $lang = cRegistry::getLanguageId();
 541:         $client = cRegistry::getClientId();
 542:         $idcat = cRegistry::getCategoryId();
 543:         $idart = cRegistry::getArticleId();
 544:         $sess = cRegistry::getSession();
 545: 
 546:         // set article name
 547:         $sArtParam = '';
 548:         if (isset($artname) && cString::getStringLength($artname) > 0) {
 549:             $sArtParam = '&idart=' . cSecurity::toInteger($idart);
 550:         }
 551: 
 552:         // check for additional parameter in url
 553:         $aParamsToIgnore = [
 554:             'idcat', 'idart', 'lang', 'client', 'idcatart', 'changelang', 'changeclient', 'idartlang', 'parts', 'artname'
 555:         ];
 556:         $sOtherParams = '';
 557: 
 558:         if (!empty($_GET)) {
 559:             foreach ($_GET as $key => $value) {
 560:                 if (!in_array($key, $aParamsToIgnore) && cString::getStringLength(trim($value)) > 0) {
 561:                     #$aNoAnchor = explode('#', $value);
 562:                     $sOtherParams .= '&' . urlencode(urldecode($key)) . '=' . urlencode(urldecode($value));
 563:                 }
 564:             }
 565:         }
 566: 
 567:         $url = $sess->url(
 568:             'front_content.php?' . 'idcat=' . cSecurity::toInteger($idcat) . '&client=' . cSecurity::toInteger($client)
 569:             . '&changelang=' . cSecurity::toInteger($lang) . $sArtParam . $sOtherParams . '#' . $aMatches[2]
 570:         );
 571: 
 572:         $sNewUrl = '<a' . $aMatches[1] . 'href="' . $url . '"' . $aMatches[3] . '>';
 573: 
 574:         return $sNewUrl;
 575:     }
 576: 
 577:     /**
 578:      * Return full CONTENIDO url from single anchor
 579:      *
 580:      * @param   array   $aMatches [0] = complete anchor, [1] = pre arguments, [2] = anchor name, [3] = post arguments
 581:      * @param   bool    $bXHTML  Flag to return XHTML valid url
 582:      * @return  string  New anchor
 583:      */
 584:     public static function contenidoHtmlAnchor(array $aMatches = [], $bXHTML = true) {
 585:         $sess = cRegistry::getSession();
 586:         $aParams = [];
 587:         $sAmpersand = $bXHTML ? '&amp;' : '&';
 588: 
 589:         foreach ($_GET as $key => $value) {
 590:             $aNoAnchor = explode('#', $value);
 591:             $aParams[] = urlencode(urldecode($key)) . '=' . urlencode(urldecode($aNoAnchor[0]));
 592:         }
 593: 
 594:         $url = $sess->url('front_content.php?' . implode($sAmpersand, $aParams) . '#' . $aMatches[2]);
 595:         $sNewUrl = '<a' . $aMatches[1] . 'href="' . $url . '"' . $aMatches[3] . '>';
 596: 
 597:         return $sNewUrl;
 598:     }
 599: 
 600:     /**
 601:      * Get article websafe name from article id and language id.
 602:      *
 603:      * @param    int     $iArtId   Article id
 604:      * @param    int     $iLangId  Language id
 605:      * @return   string    Article websafe name
 606:      */
 607:     public static function getArtWebsafeName($iArtId = 0, $iLangId = 0) {
 608:         $cfg = cRegistry::getConfig();
 609:         $iArtId = cSecurity::toInteger($iArtId);
 610:         $iLangId = cSecurity::toInteger($iLangId);
 611:         $sql = "SELECT urlname FROM " . $cfg['tab']['art_lang']
 612:             . " WHERE idart = " . $iArtId . " AND idlang = " . $iLangId;
 613:         if ($aData = mr_queryAndNextRecord($sql)) {
 614:             return $aData['urlname'];
 615:         }
 616:         return NULL;
 617:     }
 618: 
 619:     /**
 620:      * Get article websafe name from idartlang.
 621:      *
 622:      * @param    int     $iArtLangId  idartlang
 623:      * @return   string    Article websafe name
 624:      */
 625:     public static function getArtLangWebsafeName($iArtLangId = 0) {
 626:         $cfg = cRegistry::getConfig();
 627:         $iArtLangId = cSecurity::toInteger($iArtLangId);
 628:         $sql = "SELECT urlname FROM " . $cfg['tab']['art_lang'] . " WHERE idartlang = " . $iArtLangId;
 629:         if ($aData = mr_queryAndNextRecord($sql)) {
 630:             return $aData['urlname'];
 631:         }
 632:         return NULL;
 633:     }
 634: 
 635:     /**
 636:      * Get name of client by id.
 637:      *
 638:      * @param   int     $clientId  Client id
 639:      * @return  string  Client name
 640:      */
 641:     public static function getClientName($clientId = 0) {
 642:         $cfg = cRegistry::getConfig();
 643:         $clientId = cSecurity::toInteger($clientId);
 644:         $key = 'clientname_by_clientid_' . $clientId;
 645: 
 646:         if (isset(self::$_lookupTable[$key])) {
 647:             return self::$_lookupTable[$key];
 648:         }
 649: 
 650:         $sql = "SELECT name FROM " . $cfg['tab']['clients'] . " WHERE idclient = " . $clientId;
 651:         if ($aData = mr_queryAndNextRecord($sql)) {
 652:             $clientName = $aData['name'];
 653:         } else {
 654:             $clientName = '';
 655:         }
 656: 
 657:         self::$_lookupTable[$key] = $clientName;
 658:         return $clientName;
 659:     }
 660: 
 661:     /**
 662:      * Get client id from client name
 663:      *
 664:      * @param   string   $sClientName  Client name
 665:      * @return  int  Client id
 666:      */
 667:     public static function getClientId($sClientName = '') {
 668:         $cfg = cRegistry::getConfig();
 669:         $sClientName = cString::toLowerCase($sClientName);
 670:         $key = 'clientid_by_name_' . $sClientName;
 671: 
 672:         if (isset(self::$_lookupTable[$key])) {
 673:             return self::$_lookupTable[$key];
 674:         }
 675: 
 676:         $sql = "SELECT idclient FROM " . $cfg['tab']['clients']
 677:             . " WHERE LOWER(name) = '" . self::$_db->escape($sClientName) . "'"
 678:             . " OR LOWER(name) = '" . self::$_db->escape(urldecode($sClientName)) . "'";
 679:         if ($aData = mr_queryAndNextRecord($sql)) {
 680:             $clientId = $aData['idclient'];
 681:         } else {
 682:             $clientId = false;
 683:         }
 684: 
 685:         self::$_lookupTable[$key] = $clientId;
 686:         return $clientId;
 687:     }
 688: 
 689:     /**
 690:      * Checks if client id exists
 691:      *
 692:      * @param   int  $clientId
 693:      * @return  bool
 694:      */
 695:     public static function clientIdExists($clientId) {
 696:         $cfg = cRegistry::getConfig();
 697:         $clientId = cSecurity::toInteger($clientId);
 698:         $key = 'clientid_exists_' . $clientId;
 699: 
 700:         if (isset(self::$_lookupTable[$key])) {
 701:             return self::$_lookupTable[$key];
 702:         }
 703: 
 704:         $sql = "SELECT idclient FROM " . $cfg['tab']['clients'] . " WHERE idclient = " . $clientId;
 705:         if ($aData = mr_queryAndNextRecord($sql)) {
 706:             $exists = true;
 707:         } else {
 708:             $exists = false;
 709:         }
 710: 
 711:         self::$_lookupTable[$key] = $exists;
 712:         return $exists;
 713:     }
 714: 
 715:     /**
 716:      * Returns name of language by id.
 717:      *
 718:      * @param   int     $languageId  Language id
 719:      * @return  string  Lanuage name
 720:      */
 721:     public static function getLanguageName($languageId = 0) {
 722:         $cfg = cRegistry::getConfig();
 723:         $languageId = cSecurity::toInteger($languageId);
 724:         $key = 'languagename_by_id_' . $languageId;
 725: 
 726:         if (isset(self::$_lookupTable[$key])) {
 727:             return self::$_lookupTable[$key];
 728:         }
 729: 
 730:         $sql = "SELECT name FROM " . $cfg['tab']['lang'] . " WHERE idlang = " . $languageId;
 731:         if ($aData = mr_queryAndNextRecord($sql)) {
 732:             $languageName = $aData['name'];
 733:         } else {
 734:             $languageName = '';
 735:         }
 736: 
 737:         self::$_lookupTable[$key] = $languageName;
 738:         return $languageName;
 739:     }
 740: 
 741:     /**
 742:      * Checks if language id exists
 743:      *
 744:      * @param   int     $languageId  Language id
 745:      * @return  bool
 746:      */
 747:     public static function languageIdExists($languageId) {
 748:         $cfg = cRegistry::getConfig();
 749:         $languageId = cSecurity::toInteger($languageId);
 750:         $key = 'languageid_exists_' . $languageId;
 751: 
 752:         if (isset(self::$_lookupTable[$key])) {
 753:             return self::$_lookupTable[$key];
 754:         }
 755: 
 756:         $sql = "SELECT idlang FROM " . $cfg['tab']['lang'] . " WHERE idlang = " . $languageId;
 757:         if ($aData = mr_queryAndNextRecord($sql)) {
 758:             $exists = true;
 759:         } else {
 760:             $exists = false;
 761:         }
 762: 
 763:         self::$_lookupTable[$key] = $exists;
 764:         return $exists;
 765:     }
 766: 
 767:     /**
 768:      * Get language id from language name thanks to Nicolas Dickinson for multi
 769:      * Client/Language BugFix
 770:      *
 771:      * @param  string   $sLanguageName  Language name
 772:      * @param  int      $iClientId      Client id
 773:      * @return int  Language id
 774:      */
 775:     public static function getLanguageId($sLanguageName = '', $iClientId = 1) {
 776:         $cfg = cRegistry::getConfig();
 777:         $sLanguageName = cString::toLowerCase($sLanguageName);
 778:         $iClientId = cSecurity::toInteger($iClientId);
 779:         $key = 'langid_by_langname_clientid_' . $sLanguageName . '_' . $iClientId;
 780: 
 781:         if (isset(self::$_lookupTable[$key])) {
 782:             return self::$_lookupTable[$key];
 783:         }
 784: 
 785:         $sql = "SELECT l.idlang FROM " . $cfg['tab']['lang'] . " as l "
 786:             . "LEFT JOIN " . $cfg['tab']['clients_lang'] . " AS cl ON l.idlang = cl.idlang "
 787:             . "WHERE cl.idclient = " . $iClientId . " AND (LOWER(l.name) = '" . self::$_db->escape($sLanguageName) . "' "
 788:             . "OR LOWER(l.name) = '" . self::$_db->escape(urldecode($sLanguageName)) . "')";
 789:         if ($aData = mr_queryAndNextRecord($sql)) {
 790:             $languageId = $aData['idlang'];
 791:         } else {
 792:             $languageId = 0;
 793:         }
 794: 
 795:         self::$_lookupTable[$key] = $languageId;
 796:         return $languageId;
 797:     }
 798: 
 799:     /**
 800:      * Splits passed argument into scheme://host and path/query.
 801:      *
 802:      * Example:
 803:      * input  = http://host/front_content.php?idcat=123
 804:      * return = ['htmlpath' => 'http://host', 'url' => 'front_content.php?idcat=123']
 805:      *
 806:      * @param  string  $url  URL to split
 807:      * @return array   Assoziative array including the two parts:
 808:      *                 - ['htmlpath' => $path, 'url' => $url]
 809:      */
 810:     public static function getClientFullUrlParts($url) {
 811:         $clientPath = cRegistry::getFrontendUrl();
 812: 
 813:         if (cString::findFirstOccurrenceCI($url, $clientPath) !== false) {
 814:             // url includes full html path (scheme host path, etc.)
 815:             $url = str_replace($clientPath, '', $url);
 816:             $htmlPath = $clientPath;
 817:             $aComp = parse_url($htmlPath);
 818: 
 819:             // check if path matches to defined rootdir from mod_rewrite conf
 820:             if (isset($aComp['path']) && $aComp['path'] !== parent::getConfig('rootdir')) {
 821:                 // replace not matching path agaings configured one
 822:                 // this will replace e. g. "http://host/cms/" against "http://host/"
 823:                 $htmlPath = str_replace($aComp['path'], parent::getConfig('rootdir'), $htmlPath);
 824:                 if (cString::getPartOfString($htmlPath, cString::getStringLength($htmlPath) - 1) == '/') {
 825:                     // remove last slash
 826:                     $htmlPath = cString::getPartOfString($htmlPath, 0, cString::getStringLength($htmlPath) - 1);
 827:                 }
 828:             }
 829:         } else {
 830:             $htmlPath = '';
 831:         }
 832:         return ['htmlpath' => $htmlPath, 'url' => $url];
 833:     }
 834: 
 835:     /**
 836:      * Function to preclean a url.
 837:      *
 838:      * Removes absolute path declaration '/front_content.php' or relative path
 839:      * definition to actual dir './front_content.php', ampersand entities '&amp;'
 840:      * and returns a url like 'front_content.php?idart=12&idlang=1'
 841:      *
 842:      * @param   string  $url  Url to clean
 843:      * @return  string  Cleaned Url
 844:      */
 845:     public static function urlPreClean($url) {
 846:         // some preparation of different front_content.php occurence
 847:         if (cString::findFirstPos($url, './front_content.php') === 0) {
 848:             $url = str_replace('./front_content.php', 'front_content.php', $url);
 849:         } elseif (cString::findFirstPos($url, '/front_content.php') === 0) {
 850:             $url = str_replace('/front_content.php', 'front_content.php', $url);
 851:         }
 852:         $url = str_replace('&amp;', '&', $url);
 853:         return $url;
 854:     }
 855: 
 856:     /**
 857:      * Recreates all or only empty aliases in categories table.
 858:      *
 859:      * @param  bool  $bOnlyEmpty  Flag to reset only empty items
 860:      * @throws  cDbException
 861:      * @throws Exception
 862:      */
 863:     public static function recreateCategoriesAliases($bOnlyEmpty = false) {
 864:         $cfg = cRegistry::getConfig();
 865:         $db = cRegistry::getDb();
 866:         $aCats = [];
 867: 
 868:         // get all or only empty categories
 869:         $sql = "SELECT name, idcat, idlang FROM " . $cfg['tab']['cat_lang'];
 870:         if ($bOnlyEmpty === true) {
 871:             $sql .= " WHERE urlname IS NULL OR urlname = '' OR urlpath IS NULL OR urlpath = ''";
 872:         }
 873: 
 874:         $db->query($sql);
 875:         while ($db->nextRecord()) {
 876:             //set new alias
 877:             self::setCatWebsafeName($db->f('name'), $db->f('idcat'), $db->f('idlang'));
 878:             $aCats[] = ['idcat' => $db->f('idcat'), 'idlang' => $db->f('idlang')];
 879:         }
 880: 
 881:         foreach ($aCats as $p => $item) {
 882:             self::setCatUrlPath($item['idcat'], $item['idlang']);
 883:         }
 884:     }
 885: 
 886:     /**
 887:      * Returns list of all empty category aliases
 888:      *
 889:      * @param   bool  $bOnlyNumber
 890:      * @return  array|int
 891:      * @throws  cDbException
 892:      */
 893:     public static function getEmptyCategoriesAliases($bOnlyNumber = true) {
 894:         $cfg = cRegistry::getConfig();
 895:         $db = cRegistry::getDb();
 896:         $return = ($bOnlyNumber) ? 0 : [];
 897: 
 898:         // get all empty categories
 899:         $sql = "SELECT name, idcat, idlang FROM " . $cfg['tab']['cat_lang']
 900:             . " WHERE urlname IS NULL OR urlname = '' OR urlpath IS NULL OR urlpath = ''";
 901: 
 902:         $db->query($sql);
 903: 
 904:         if ($bOnlyNumber) {
 905:             $return = cSecurity::toInteger($db->numRows());
 906:         } else {
 907:             while ($db->nextRecord()) {
 908:                 $return[] = [$db->f('name'), $db->f('idcat'), $db->f('idlang')];
 909:             }
 910:         }
 911: 
 912:         return $return;
 913:     }
 914: 
 915:     /**
 916:      * Recreates all or only empty urlname entries in art_lang table.
 917:      *
 918:      * @param  bool  $bOnlyEmpty  Flag to reset only empty items
 919:      * @throws cDbException
 920:      * @throws Exception
 921:      */
 922:     public static function recreateArticlesAliases($bOnlyEmpty = false) {
 923:         $cfg = cRegistry::getConfig();
 924:         $db = cRegistry::getDb();
 925: 
 926:         // get all or only empty articles
 927:         $sql = "SELECT title, idart, idlang FROM " . $cfg['tab']['art_lang'];
 928:         if ($bOnlyEmpty === true) {
 929:             $sql .= " WHERE urlname IS NULL OR urlname = ''";
 930:         }
 931:         $db->query($sql);
 932: 
 933:         while ($db->nextRecord()) {
 934:             //set new alias
 935:             self::setArtWebsafeName($db->f('title'), $db->f('idart'), $db->f('idlang'));
 936:         }
 937:     }
 938: 
 939:     /**
 940:      * Returns list of all empty article aliases
 941:      *
 942:      * @param   bool  $bOnlyNumber
 943:      * @return  array|int
 944:      * @throws  cDbException
 945:      */
 946:     public static function getEmptyArticlesAliases($bOnlyNumber = true) {
 947:         $cfg = cRegistry::getConfig();
 948:         $db = cRegistry::getDb();
 949:         $return = ($bOnlyNumber) ? 0 : [];
 950: 
 951:         // get all empty articles
 952:         $sql  = "SELECT title, idart, idlang FROM " . $cfg['tab']['art_lang']
 953:             . " WHERE urlname IS NULL OR urlname = ''";
 954: 
 955:         $db->query($sql);
 956:         if ($bOnlyNumber) {
 957:             $return = cSecurity::toInteger($db->numRows());
 958:         } else {
 959:             while ($db->nextRecord()) {
 960:                 $return[] = [$db->f('title'), $db->f('idart'), $db->f('idlang')];
 961:             }
 962:         }
 963: 
 964:         return $return;
 965:     }
 966: 
 967:     /**
 968:      * Method to reset all aliases (categories and articles).
 969:      *
 970:      * Shortcut to recreateCategoriesAliases() and recreateArticlesAliases()
 971:      */
 972:     public static function resetAliases() {
 973:         self::recreateCategoriesAliases();
 974:         self::recreateArticlesAliases();
 975:     }
 976: 
 977:     /**
 978:      * Recreate all or only empty aliases (categories and articles).
 979:      *
 980:      * Shortcut to recreateCategoriesAliases() and recreateArticlesAliases()
 981:      *
 982:      * @param  bool  $bOnlyEmpty  Flag to reset only empty items
 983:      * @throws  cDbException
 984:      */
 985:     public static function recreateAliases($bOnlyEmpty = false) {
 986:         self::recreateCategoriesAliases($bOnlyEmpty);
 987:         self::recreateArticlesAliases($bOnlyEmpty);
 988:     }
 989: 
 990:     /**
 991:      * Returns .htaccess related assoziative info array
 992:      *
 993:      * @return  array
 994:      */
 995:     public static function getHtaccessInfo() {
 996:         $arr = [
 997:             'contenido_full_path' => str_replace('\\', '/', realpath(cRegistry::getBackendPath() . '../') . '/'),
 998:             'client_full_path' => cRegistry::getFrontendPath(),
 999:         ];
1000:         $arr['in_contenido_path'] = is_file($arr['contenido_full_path'] . '.htaccess');
1001:         $arr['in_client_path'] = is_file($arr['client_full_path'] . '.htaccess');
1002:         $arr['has_htaccess'] = ($arr['in_contenido_path'] || $arr['in_client_path']);
1003: 
1004:         return $arr;
1005:     }
1006: 
1007: }
1008: 
CMS CONTENIDO 4.10.0 API documentation generated by ApiGen 2.8.0