%thread_id% * * @data_type Array * @access private */ //private $parameters = []; /** * Name of the php file which will be loaded * for the permalink. * example: news.php, articles.php * * @data_type String * @access private */ private $pathtofile = ""; /** * Array of Parameters with their * actual values. * example: thread_id => 1, rowstart => 20 * * @data_type Array * @access private */ private $get_parameters = []; public function __construct() { // Pretty URL $this->requesturi = rtrim(urldecode($this->removeParam(PERMALINK_CURRENT_PATH)), '/'); } private function removeParam($urlValue) { $urlArray = explode('?', $urlValue); if (isset($urlArray)) { return $urlArray[0]; } return $urlValue; } public static function getRouterInstance() { if (self::$router_instance === NULL) { self::$router_instance = new static(); } return self::$router_instance; } public function get_FileParams() { return $this->get_parameters; } /** * @param mixed $pathtofile */ public function setPathtofile($pathtofile) { $this->pathtofile = $pathtofile; } /** * @param mixed $get_parameters */ public function setGetParameters($get_parameters) { $this->get_parameters = $get_parameters; } /** * Call all the functions to process rewrite detection and further actions. * This will call all the other functions after all the included files have been included * and all the patterns have been made. * * @access public */ public function rewritePage() { // Import the required Handlers $this->loadSQLDrivers(); // Include the Rewrites $this->includeRewrite(); // Import Patterns from DB $this->importPatterns(); // Prepare Search Strings $this->prepare_searchRegex(); // Check if there is any Alias matching with current URL if (!$this->checkAlias()) { // Check if any Alias Pattern is matching with current URL if (!$this->checkAliasPatterns()) { // Check if any Pattern is matching with current URL $this->checkPattern(); } } // If path to File is empty, set a warning if ($this->pathtofile == "") { $this->setWarning(6); } if (fusion_get_settings('debug_seo') && iSUPERADMIN && iADMIN) { $this->displayWarnings(); } } /** * Import the Available Patterns from Database * This will Import all the available Patterns for the Handlers * from the Database and put it into $pattern_search and * $pattern_replace array. * * @access private */ private function importPatterns() { if (!empty($this->handlers)) { $types = []; foreach ($this->handlers as $key => $value) { $types[] = "'".$value."'"; // When working on string, the values should be inside single quotes. } $types_str = implode(",", $types); $query = "SELECT r.rewrite_name, p.pattern_type, p.pattern_source, p.pattern_target, p.pattern_cat FROM ".DB_PERMALINK_METHOD." p INNER JOIN ".DB_PERMALINK_REWRITE." r WHERE r.rewrite_id=p.pattern_type AND r.rewrite_name IN(".$types_str.") ORDER BY p.pattern_type"; $this->queries[] = $query; $result = dbquery($query); if (dbrows($result)) { while ($data = dbarray($result)) { if ($data['pattern_cat'] == "normal") { $this->pattern_search[$data['rewrite_name']][] = $data['pattern_source']; $this->pattern_replace[$data['rewrite_name']][] = $data['pattern_target']; } else if ($data['pattern_cat'] == "alias") { $this->alias_pattern[$data['rewrite_name']][$data['pattern_source']] = $data['pattern_target']; } } } } } /** * Checks if there is any matching Alias or not * This function will check if there is any matching Alias for the URI or not. * * @access private */ private function checkAlias() { // Check if there is any Alias matching the current URI $query = "SELECT * FROM ".DB_PERMALINK_ALIAS." WHERE alias_url=:url LIMIT 1"; $result = dbquery($query, [':url' => stripinput($this->requesturi)]); $this->queries[] = $query; if (dbrows($result)) { $aliasdata = dbarray($result); // If Yes, then Exploded the corresponding php_url and render the page if ($aliasdata['alias_php_url'] != "") { $alias_url = $this->getAliasURL($aliasdata['alias_url'], $aliasdata['alias_php_url'], $aliasdata['alias_type']); $url_info = $this->explodeURL($alias_url, "&"); // File Path (Example: news.php) $this->pathtofile = $url_info[0]; if (isset($url_info[1])) { foreach ($url_info[1] as $paramkey => $paramval) { $this->get_parameters[$paramkey] = $paramval; // $this->get_parameters['thread_id'] = 1 } } // Call the function to set server variables $this->setVariables(); $this->setWarning(7, $this->requesturi); // Alias Found return TRUE; } } else { $this->setWarning(1, $this->requesturi); // Alias not found return FALSE; } } /** * Get Alias URL for Router * This function will return an Array of 2 elements for a specific Alias: * 1. The Permalink URL of Alias * 2. PHP URL of the Alias * * @param string $url The Permalink URL (incomplete) * @param string $php_url The PHP URL (incomplete) * @param string $type Type of Alias * * @access private * @return mixed|string */ private function getAliasURL($url, $php_url, $type) { if (isset($this->alias_pattern) && isset($this->alias_pattern[$type]) && is_array($this->alias_pattern[$type])) { foreach ($this->alias_pattern[$type] as $search => $replace) { $search = str_replace("%alias%", $url, $search); $replace = str_replace("%alias_target%", $php_url, $replace); if ($search == $this->requesturi) { return $replace; } } } return $php_url; } /** * Explodes a URL into Filename and Get Parameters * This function will explode the URL into its Filename and Get Parameters * Example: viewthread.php?thread_id=1&rowstart=20 * then : * array[0] => viewthread.php * array[1] => array( * [thread_id] => 1 * [rowstart] => 20 * ) * * @param string $url The URL * @param string $param_delimiter The Parameters to explode by * * @access private * @return array */ private function explodeURL($url, $param_delimiter = "&") { $url_info = []; // Explode URL $pathinfo = explode("?", $url); // Save the File path in 1st position of array $url_info[0] = $pathinfo[0]; if (isset($pathinfo[1])) { // Now calculate the query parameters $params = explode($param_delimiter, $pathinfo[1]); // 0=>thread_id=1, 1=>pid=25 // Now again explode it with '=' foreach ($params as $paramkey => $paramval) { // 0=>thread_id=1, 1=>pid=25 // bug fix. sometimes is just ?create. if (strpos($paramval, '=')) { $get_params = explode("=", $paramval); // thread_id => 1, pid => 25 $url_info[1][$get_params[0]] = $get_params[1]; } else { $url_info[1][$paramval] = ''; // void all values since there is no value. } } } return $url_info; } /** * Call the Functions to Set GET Parameters and Query String * This function will call the functions to set Server GET parameters * and the QUERY_STRING. * * @access private */ private function setVariables() { $this->setservervars(); $this->setquerystring(); } /** * Set the PHP_SELF and SCRIPT_NAME to the suitable filepath. * This function will set the values of PHP_SELF and SCRIPT_NAME to the suitable * file name. The filename will be searched in the $pattern_replace array. * The php filename is found before '?' in the pattern. * * @access private */ public function setservervars() { if (!empty($this->pathtofile)) { $_SERVER['PHP_SELF'] = preg_replace("/index\.php/", $this->pathtofile, $_SERVER['PHP_SELF'], 1); $_SERVER['SCRIPT_NAME'] = preg_replace("/index\.php/", $this->pathtofile, $_SERVER['SCRIPT_NAME'], 1); } } /** * Set the new QUERY_STRING * This function will set the values of QUERY_STRING to new value * which is calculated in buildParams(). * * @access private */ public function setquerystring() { if (!empty($_SERVER['QUERY_STRING'])) { $_SERVER['QUERY_STRING'] = $_SERVER['QUERY_STRING']."&".$this->buildParams(); } else { $_SERVER['QUERY_STRING'] = $this->buildParams(); } } /** * Builds the $_GET parameters * This function will build the GET parameters and also the Query String. * * @access private */ private function buildParams() { $total = count($this->get_parameters); $i = 1; $query_str = ""; foreach ($this->get_parameters as $key => $val) { $_GET[$key] = $val; // This is where $_GET is produced. $query_str .= $key."=".$val; if ($i < $total) { $query_str .= "&"; } $i++; } return $query_str; } /** * Checks if there is any matching Alias Pattern or not * This function will check if there is any matching Alias Pattern for the URI or not. * Example: If a Thread request is like: "post-your-site-rowstart-20", then it will * try to find any pattern like: "post-your-site-rowstart-%thread_rowstart%" * * @access private */ private function checkAliasPatterns() { if (is_array($this->alias_pattern)) { $match_found = FALSE; $alias = ""; foreach ($this->alias_pattern as $type => $alias_patterns) { foreach ($alias_patterns as $search => $replace) { $search_pattern = $search; $search = $this->makeSearchRegex($search, $type); $search = str_replace("%alias%", "(.*?)", $search); if (preg_match($search, $this->requesturi, $matches)) { $alias_pos = $this->getTagPosition($search_pattern, "%alias%"); if ($alias_pos != 0) { // The Alias is Detected ! $alias = $matches[$alias_pos]; // Now search for this Alias in Database $query = "SELECT * FROM ".DB_PERMALINK_ALIAS." WHERE alias_url=:url LIMIT 1"; $result = dbquery($query, [':url' => $alias]); $this->queries[] = $query; if (dbrows($result)) { $aliasdata = dbarray($result); // Replace the %alias_target% in the Replacement pattern $replace = str_replace("%alias_target%", $aliasdata['alias_php_url'], $replace); //$replace_with = $replace; // Replacing Tags with their suitable matches $replace = $this->replaceOtherTags($type, $search_pattern, $replace, $matches, -1); $url_info = $this->explodeURL($replace, "&"); // File Path (Example: news.php) $this->pathtofile = $url_info[0]; if (isset($url_info[1])) { foreach ($url_info[1] as $paramkey => $paramval) { $this->get_parameters[$paramkey] = $paramval; // $this->get_parameters['thread_id'] = 1 } } // Call the function to set server variables $this->setVariables(); $match_found = TRUE; break; } } } } } if ($match_found == TRUE) { $this->setWarning(8, $alias); // Alias Pattern Found return TRUE; } else { $this->setWarning(2, $this->requesturi); // Alias Pattern Not Found return FALSE; } } return FALSE; } /** * Builds the Regex pattern for a specific Type string * This function will build the Regex pattern for a specific string, which is * passed to the function. * * @param string $pattern * @param string $type * * @return mixed|string */ protected function makeSearchRegex($pattern, $type) { $regex = $pattern; if (isset($this->rewrite_code[$type]) && isset($this->rewrite_replace[$type])) { $regex = str_replace($this->rewrite_code[$type], $this->rewrite_replace[$type], $regex); } $regex = $this->cleanRegex($regex); $regex = "/^".$regex."$/"; return $regex; } /** * Builds the Regular Expressions Patterns * This function will create the Regex patterns and will put the built patterns * in $patterns_regex array. This array will then used in preg_match function * to match against current request. * Note: Using ^ and $ made us to match exact string so that it doesn't match sub-patterns * * @access private */ private function checkPattern() { $match_found = FALSE; if (is_array($this->pattern_search)) { foreach ($this->pattern_search as $type => $RawSearchPatterns) { if (!empty($RawSearchPatterns) && is_array($RawSearchPatterns)) { foreach ($RawSearchPatterns as $key => $search) { if ($match_found == FALSE) { if (isset($this->pattern_replace[$type][$key]) && isset($this->pattern_search[$type][$key])) { $search_pattern = $this->pattern_search[$type][$key]; $replace_pattern = $this->pattern_replace[$type][$key]; if (isset($this->rewrite_code[$type]) && isset($this->rewrite_replace[$type])) { $search = str_replace($this->rewrite_code[$type], $this->rewrite_replace[$type], $search); } $search = "~".$this->cleanRegex($search)."$~i"; if (preg_match($search, $this->requesturi, $matches)) { $url_info = $this->explodeURL($replace_pattern, "&"); $this->pathtofile = str_replace("../", "", $url_info[0]); preg_match_all($search, $this->requesturi, $url_matches, PREG_SET_ORDER); if (isset($url_info[1])) { // indicate has $_GET request /** * File path is in search pattern */ preg_match_all("~%(.*?)%~i", $search_pattern, $tag_matches); $tag_values = []; if (!empty($tag_matches[0])) { $tagData = array_combine(range(1, count($tag_matches[0])), array_values($tag_matches[0])); $tagRequests = array_combine(range(1, count($tag_matches[0])), array_values($tag_matches[1])); foreach ($tagData as $tagKey => $tagVal) { $tag_values[$tagRequests[$tagKey]] = $matches[$tagKey]; } $this->dataStatements[$type][] = $tag_values; $urlParams = array_combine(array_values($tagData), array_values($tag_values)); } /** * Read the Request URL pattern */ if (isset($url_info[1]) && !empty($urlParams)) { $parameters = []; foreach ($url_info[1] as $paramKey => $paramVal) { if (!$paramVal) { $paramVal = TRUE; } $value = (isset($tag_values[$paramKey])) ? $tag_values[$paramKey] : $paramVal; // If key is not val, (i.e. such as post_id=%thread_id%) the below will find and insert value if (stristr($value, "%")) { $value = (isset($urlParams[$value])) ? $urlParams[$value] : $paramVal; } $parameters[$paramKey] = $value; } $this->get_parameters = $parameters; } $this->setVariables(); $this->setWarning(9, $this->requesturi); // Regex pattern found break; } } } else { die("You do not have correct Permalink rules Driver. See that your driver is properly set!"); } } else { $this->setWarning(3, $this->requesturi); // Regex pattern not found } } } } } } /** * Show Warnings or Debugging Information * This function will show the Warnings or Debugging Information * if Warnings are enabled or if Debug Mode is enabled. * * @access private */ private function displayWarnings() { echo "
\n"; echo "Queries which were made for Rewriting:

\n"; foreach ($this->queries as $key => $query) { echo $query.";
\n"; } add_to_footer(""); echo "\n
"; echo "Path to File: ".$this->pathtofile."
"; echo "Request URI: ".$this->requesturi."
"; echo "
\n"; foreach ($this->warnings as $key => $val) { echo (intval($key) + 1).". ".$val."
\n"; } echo "
\n"; echo "Handlers Stack = Array (
"; foreach ($this->handlers as $key => $name) { echo "    [".$key."] => ".$name."
"; echo "    )
\n"; } echo ");
\n"; echo "
\n"; echo "Alias Patterns = Array (
"; foreach ($this->alias_pattern as $type => $tag) { echo "    [".$type."] => Array (
"; foreach ($tag as $key => $val) { echo "        [".$key."] => ".$val."
"; } echo "    )
\n"; } echo ");
\n"; echo "
\n"; echo "Rewrite Codes = Array (
"; foreach ($this->rewrite_code as $type => $tag) { echo "    [".$type."] => Array (
"; foreach ($tag as $key => $val) { echo "        [".$key."] => ".$val."
"; } echo "    )
\n"; } echo ");
\n"; echo "
\n"; echo "Rewrite Replace = Array (
"; foreach ($this->rewrite_replace as $type => $tag) { echo "    [".$type."] => Array (
"; foreach ($tag as $key => $val) { echo "        [".$key."] => ".$val."
"; } echo "    )
\n"; } echo ");
\n"; echo "
\n"; echo "Pattern Search = Array (
"; foreach ($this->pattern_search as $type => $tag) { echo "    [".$type."] => Array (
"; foreach ($tag as $key => $val) { echo "        [".$key."] => ".$val."
"; } echo "    )
\n"; } echo ");
\n"; echo "
\n"; echo "Pattern Replace = Array (
"; foreach ($this->pattern_replace as $type => $tag) { echo "    [".$type."] => Array (
"; foreach ($tag as $key => $val) { echo "        [".$key."] => ".$val."
"; } echo "    )
\n"; } echo ");
\n"; echo "
\n"; echo "Pattern Regex = Array (
"; foreach ($this->patterns_regex as $type => $tag) { echo "    [".$type."] => Array (
"; foreach ($tag as $key => $val) { echo "        [".$key."] => ".$val."
"; } echo "    )
\n"; } echo ");
\n"; echo "
\n"; echo "Module Property Information:
"; foreach ($this->pattern_tables as $type => $val) { $propHTML = ''; foreach ($val as $val_pattern => $arrayProp) { $propHTML .= "      - {$val_pattern} will be translated on ".$arrayProp['table']." WHERE ".$arrayProp['primary_key']." is equals to $val_pattern
\n"; } echo "    ".$type." rewrite module
".$propHTML."
"; } echo ");
\n"; echo "
\n"; echo "Data Cache = Array (
"; foreach ($this->dataStatements as $type => $info) { echo "    [".$type."] => Array (
"; foreach ($info as $id => $dbinfo) { echo "        [".$id."] => Array (
"; foreach ($dbinfo as $colname => $colvalue) { echo "                [".$colname."] => ".$colvalue."
"; } echo "        )
\n"; } echo "    )
\n"; } echo ");
\n"; echo "
\n"; echo "\$_GET Parameters = Array (
"; foreach ($this->get_parameters as $key => $val) { echo "    [".$key."] => ".$val."
"; } echo ");
\n"; echo "
\n"; echo "
\n"; } /** * Index Include File * Returns the filename of the php file which will be included. * If this file is blank, index.php will redirect to 404 error page * * @access public */ public function getFilePath() { return $this->pathtofile; } /** * Get the Current URL * * @return string */ public function getCurrentURL() { return $this->pathtofile.(!empty($this->get_parameters) ? '?'.http_build_query($this->get_parameters, '', '&') : ''); } }