* @license http://www.contenido.org/license/LIZENZ.txt * @link http://www.4fb.de * @link http://www.contenido.org * @since file available since contenido release <= 4.6 * * {@internal * created unknown * modified 2006-12-14, init array $results in fct prResolvePathViaURLNames, prResolvePathViaCategoryNames, return type is now integer * modified 2008-06-26, Frederic Schneider, add security fix * modified 2008-08-11, Bilal Arslan, Change prResolvePathViaCategoryNames function for take current path language id! * modified 2008-11-11, Andreas Lindner, Change prResolvePathViaCategoryNames, suppress change of current language if an url path * is found in current and at least one more language * modified 2009-10-23, Murat Purc, removed deprecated function (PHP 5.3 ready) and formatting * * $Id$: * }} * */ if(!defined('CON_FRAMEWORK')) { die('Illegal call'); } /** * prResolvePathViaURLNames: Resolves a path using some fuzzy logic. * * Warning: If you use this function, try to pass a "good" path. This * function doesn't guarantee that the matches are logically * best-matches. * * This function operates on the category aliases. It compares the given path with the urlpaths generated by function * prCreateURLNameLocationString() based on category aliases. * * @param $path string Path to resolve * @return integer Closest matching category ID (idcat) */ function prResolvePathViaURLNames($path) { $handle = startTiming("prResolvePathViaURLNames", array ($path)); global $cfg, $lang, $client; /* Initialize variables */ $db = new DB_ConLite; $categories = array(); $results = array(); /* Pre-process path */ $path = strtolower(str_replace(" ", "", $path)); if ($cfg["pathresolve_heapcache"] == true) { $pathresolve_tablename = $cfg["sql"]["sqlprefix"]."_pathresolve_cache"; $sql = "SHOW TABLES LIKE '".Contenido_Security::escapeDB($pathresolve_tablename, $db)."'"; $db->query($sql); if (!$db->next_record()) { /** * @TODO: Externalize table creation * * Important: This is really a hack! Don't use pathresolve_heapcache if you are * not sure what it does. */ $sql = 'CREATE TABLE `'.Contenido_Security::escapeDB($pathresolve_tablename, $db).'` ( `idpathresolvecache` INT( 10 ) NOT NULL PRIMARY KEY , `path` VARCHAR( 255 ) NOT NULL , `idcat` INT( 10 ) NOT NULL , `idlang` INT( 10 ) NOT NULL , `lastcached` INT(10) NOT NULL ) TYPE = HEAP;'; $db->query($sql); } $sql = "SELECT idpathresolvecache, idcat, lastcached FROM %s WHERE path LIKE '%s' AND idlang='%s' ORDER BY lastcached DESC LIMIT 1"; $db->query(sprintf($sql, Contenido_Security::escapeDB($pathresolve_tablename, $db), Contenido_Security::escapeDB($path, $db), Contenido_Security::toInteger($lang))); if ($db->next_record()) { if (isset ($cfg["pathresolve_heapcache_time"])) { $iCacheTime = $cfg["pathresolve_heapcache_time"]; } else { $iCacheTime = 60 * 60 * 24; } $tmp_idcat = $db->f("idcat"); if ($db->f("lastcached") + $iCacheTime < time()) { $sql = "DELETE FROM %s WHERE idpathresolvecache = '%s'"; $db->query(sprintf($sql, Contenido_Security::escapeDB($pathresolve_tablename, $db), Contenido_Security::toInteger($db->f("idpathresolvecache")))); } else { return $db->f("idcat"); } } } /* Fetch all category names, build path strings */ // change the where statement for get all languages $sql = "SELECT * FROM ".$cfg["tab"]["cat_tree"]." AS A, ".$cfg["tab"]["cat"]." AS B, ".$cfg["tab"]["cat_lang"]." AS C WHERE A.idcat=B.idcat AND B.idcat=C.idcat AND C.idlang='".Contenido_Security::toInteger($lang)."' AND C.visible = 1 AND B.idclient='".Contenido_Security::toInteger($client)."' ORDER BY A.idtree"; $db->query($sql); $catpath = array (); while ($db->next_record()) { $cat_str = ""; prCreateURLNameLocationString($db->f("idcat"), "/", $cat_str, false, "", 0, 0, true, true); /* Store path */ $catpath[$db->f("idcat")] = $cat_str; $catnames[$db->f("idcat")] = $db->f("name"); $catlevels[$db->f("idcat")] = $db->f("level"); } /* Compare strings using the similar_text algorythm */ $percent = 0; foreach ($catpath as $key => $value) { $value = strtolower(str_replace(" ", "", $value)); similar_text($value, $path, $percent); $firstpath = strpos($value, "/"); if ($firstpath !== 0) { $xpath = substr($value, $firstpath); $ypath = substr($path, 0, strlen($path) - 1); if ($xpath == $ypath) { $results[$key] = 100; } else { $results[$key] = $percent; } } else { $results[$key] = $percent; } } arsort($results, SORT_NUMERIC); reset($results); endAndLogTiming($handle); if ($cfg["pathresolve_heapcache"] == true) { $nid = $db->nextid($pathresolve_tablename); $sql = "INSERT INTO %s SET idpathresolvecache='%s', path='%s', idcat='%s', idlang='%s', lastcached=%s"; $db->query(sprintf($sql, Contenido_Security::toInteger($pathresolve_tablename), Contenido_Security::toInteger($nid), Contenido_Security::escapeDB($path, $db), Contenido_Security::toInteger(key($results)), Contenido_Security::toInteger($lang), time())); } return (int) key($results); } /** * prResolvePathViaCategoryNames: Resolves a path using some fuzzy logic. * * Warning: If you use this function, try to pass a "good" path. This * function doesn't guarantee that the matches are logically * best-matches. * * This function operates on the actual category names. * * @param $path string Path to resolve * @return integer Closest matching category ID (idcat) */ function prResolvePathViaCategoryNames($path, &$iLangCheck) { $handle = startTiming("prResolvePathViaCategoryNames", array ($path)); global $cfg, $lang, $client; /* Initialize variables */ $db = new DB_ConLite; $categories = array (); $results = array(); $iLangCheckOrg = $iLangCheck; /* Added since 2008-08 from Bilal Arslan */ // To take only path body if (preg_match('/^\/(.*)\/$/', $path, $aResults)) { $aResult = explode("/", $aResults[1]); } elseif (preg_match('/^\/(.*)$/', $path, $aResults)) { $aResult = explode("/", $aResults[1]); } else { $aResults[1] = $path; } $aResults[1] = strtolower(preg_replace('/-/', ' ', $aResults[1])); // Init to Compare, save path in array $aPathsToCompare = explode("/", $aResults[1]); $iCountPath = count($aPathsToCompare); // init lang id $iLangCheck=0; /* Pre-process path */ $path = strtolower(str_replace(" ", "", $path)); /* Fetch all category names, build path strings */ // change the where statement for get all languages $sql = "SELECT * FROM ".$cfg["tab"]["cat_tree"]." AS A, ".$cfg["tab"]["cat"]." AS B, ".$cfg["tab"]["cat_lang"]." AS C WHERE A.idcat=B.idcat AND B.idcat=C.idcat AND C.visible = 1 AND B.idclient='".Contenido_Security::toInteger($client)."' ORDER BY A.idtree"; $db->query($sql); $catpath = array (); $arrLangMatches = array(); while ($db->next_record()) { $cat_str = ""; $aTemp = ""; $iFor = 0; $bLang = false; // $level is changeless 0!!! conCreateLocationString($db->f("idcat"), "/", $cat_str, false, '', 0, $db->f("idlang")); /* Store path */ $catpath[$db->f("idcat")] = $cat_str; $catnames[$db->f("idcat")] = $db->f("name"); $catlevels[$db->f("idcat")] = $db->f("level"); // Init variables for take a language id $aTemp = strtolower($cat_str); $aDBToCompare = explode("/", $aTemp); $iCountDB = count($aDBToCompare); $iCountDBFor = $iCountDB - 1; // take min. count of two arrays ($iCountDB > $iCountPath) ? $iFor = $iCountPath : $iFor = $iCountDB; $iCountM = $iFor-1; for ($i=0; $i<$iFor; $i++) { if ($aPathsToCompare[$iCountM] == $aDBToCompare[$iCountDBFor]) { $bLang = true; } else { $bLang = false; } $iCountM--; $iCountDBFor--; // compare, only if current element is lastone and we are in true path if($i == $iFor-1 && $bLang) { $iLangCheck = $db->f("idlang"); $arrLangMatches[] = $iLangCheck; } } } #Suppress wrongly language change if url name can be found in current language if ($iLangCheckOrg == 0) { if (in_array($lang, $arrLangMatches)) { $iLangCheck = $lang; } } /* Compare strings using the similar_text algorythm */ $percent = 0; foreach ($catpath as $key => $value) { $value = strtolower(str_replace(" ", "", $value)); similar_text($value, $path, $percent); $results[$key] = $percent; } foreach ($catnames as $key => $value) { $value = strtolower(str_replace(" ", "", $value)); similar_text($value, $path, $percent); /* Apply weight */ $percent = $percent * $catlevels[$key]; if ($results[$key] > $percent) { $results[$key] = $percent; } } arsort($results, SORT_NUMERIC); reset($results); endAndLogTiming($handle); return (int) key($results); } /** * Recursive function to create an URL name location string * * @param int $idcat ID of the starting category * @param string $seperator Seperation string * @param string $cat_str Category location string (by reference) * @param boolean $makeLink create location string with links * @param string $linkClass stylesheet class for the links * @param integer first navigation level location string should be printed out (first level = 0!!) * * @return string location string * * @author Jan Lengowski * @author Marco Jahn * * @copyright four for business AG */ function prCreateURLNameLocationString($idcat, $seperator, & $cat_str, $makeLink = false, $linkClass = "", $firstTreeElementToUse = 0, $uselang = 0, $final = true, $usecache = false) { global $cfg, $client, $cfgClient, $lang, $sess, $_URLlocationStringCache; if ($final == true) { $cat_str = ""; } if ($idcat == 0) { $cat_str = "Lost and Found"; return; } if ($uselang == 0) { $uselang = $lang; } if ($final == true && $usecache == true) { if (!is_array($_URLlocationStringCache)) { if (file_exists($cfgClient[$client]["path"]["frontend"]."cache/locationstring-url-cache-$uselang.txt")) { $_URLlocationStringCache = unserialize(file_get_contents($cfgClient[$client]["path"]["frontend"]."cache/locationstring-url-cache-$uselang.txt")); } else { $_URLlocationStringCache = array (); } } if (array_key_exists($idcat, $_URLlocationStringCache)) { if ($_URLlocationStringCache[$idcat]["expires"] > time()) { $cat_str = $_URLlocationStringCache[$idcat]["name"]; return; } } } $db = new DB_ConLite; $sql = "SELECT a.urlname AS urlname, a.name AS name, a.idcat AS idcat, b.parentid AS parentid, c.level as level FROM ".$cfg["tab"]["cat_lang"]." AS a, ".$cfg["tab"]["cat"]." AS b, ".$cfg["tab"]["cat_tree"]." AS c WHERE a.idlang = '".Contenido_Security::toInteger($uselang)."' AND b.idclient = '".Contenido_Security::toInteger($client)."' AND b.idcat = '".Contenido_Security::toInteger($idcat)."' AND a.idcat = b.idcat AND c.idcat = b.idcat"; $db->query($sql); $db->next_record(); if ($db->f("level") >= $firstTreeElementToUse) { $name = $db->f("urlname"); if (trim($name) == "") { $name = $db->f("name"); } $parentid = $db->f("parentid"); //create link if ($makeLink == true) { $linkUrl = $sess->url("front_content.php?idcat=$idcat"); $name = ''.$name.''; } $tmp_cat_str = $name.$seperator.$cat_str; $cat_str = $tmp_cat_str; } if ($parentid != 0) { prCreateURLNameLocationString($parentid, $seperator, $cat_str, $makeLink, $linkClass, $firstTreeElementToUse, $uselang, false, $usecache); } else { $sep_length = strlen($seperator); $str_length = strlen($cat_str); $tmp_length = $str_length - $sep_length; $cat_str = substr($cat_str, 0, $tmp_length); } if ($final == true && $usecache == true) { $_URLlocationStringCache[$idcat]["name"] = $cat_str; $_URLlocationStringCache[$idcat]["expires"] = time() + 3600; if (is_writable($cfgClient[$client]["path"]["frontend"]."cache/") || (strtolower(substr(PHP_OS, 0, 3)) == "win")) { file_put_contents($cfgClient[$client]["path"]["frontend"]."cache/locationstring-url-cache-$uselang.txt", serialize($_URLlocationStringCache)); } } } ?>