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