File: D:/HostingSpaces/PvdBoogaard/indoorski.nl/backup/oude-site/cms/api/class.urls.php
<?php
/**
* This file contains the iwp_urls class
*
* @version $Id$
*
*
* @package IWP
* @subpackage IWP_API
*/
/**
* IWP URLs Class
* This is the class that handles all the functions related to URLs within the application
*
* @package IWP
* @subpackage IWP_API
*/
class iwp_urls extends iwp_base {
/**
* This is the current matched static page name. It is the 'key' for the matched URL regex in the static_urls.ini file.
* @var string CurrentStaticPage
*/
private $CurrentStaticPage = '';
/**
* This is the current matched module page name. It is the 'key' for the matched URL regex in a module's uriPatterns.ini file.
* @var string CurrentModulePage
*/
private $CurrentModulePage = '';
/**
* This is the name of the current module that has a match for the current page request
* @var string CurrentModule
*/
private $CurrentModule = '';
/**
* This is an array with the matched segments from the URL. These segments are determined by $MatchURI
* @var array CurrentSegmentMatches
* @see $MatchURI
*/
private $CurrentSegmentMatches = array();
/**
* This the the current URL used to access this page. It has had the application path and query string removed.
* @var string CurrentURL
*/
private $CurrentURL = '';
/**
* This is an array that will contain all the static urls from the static_urls.ini file.
* @var array StaticUrls
*/
private $StaticUrls = array();
/**
* This is a multidimensional associative array for all the module's URLs
* @var array ModuleUrls
*/
private $ModuleUrls = array();
/**
* An array of predefined regular expressions to match in URLs. This can be added to via a module for its own urls.
* @var array MatchURI
*/
private $MatchURI = array(
'From' => array(
'{contenttype}',
'{idnumber}',
'{searchterm}',
'{slash}',
'{optionalslash}',
'{name}',
'{catparents}',
'{archive_year}',
'{archive_month}',
'{archive_day}',
),
'To' => array(
'(?P<contenttype>[a-zA-Z0-9\-_]*)', // {contenttype}
'(?P<idnumber>[0-9]*)', // {idnumber}
'(?P<searchterm>[^/]+)', // {searchterm}
'/', // {slash}
'[/]{0,1}',// {optionalslash}
'(?P<name>[^/]*)', // {name}
'(?P<parents>(?P<parent>[^/]*/)*)', // {catparents}
'(?P<archive_year>([0-9][0-9][0-9][0-9])?)', // {archive_year}
'(?P<archive_month>([0-9][0-9])?)', // {archive_month}
'(?P<archive_day>([0-9][0-9])?)', // {archive_day}
),
);
/**
* Instance
* This static variable holds the current instance of this object being loaded.
* So using the getInstance function anywhere will return the very same instance.
*
* @var object Instance
*/
public static $Instance;
/**
* getInstance
* This is a static function that sets up the class instance and stores it to the static variable. It will then return that instantiation in the future.
*
* @return iwp_urls Returns the instantiated object
**/
public static function getInstance(){
if(!isset(self::$Instance)){
self::$Instance = new self();
}
return self::$Instance;
}
/**
* Initializes the class by loading the static_urls.ini file into the $StaticUrls member variable.
* @return void
*/
public function __construct(){
if(file_exists(IWP_BASE_PATH . '/language/static_urls.ini')){
$this->StaticUrls = parse_ini_file(IWP_BASE_PATH . '/language/static_urls.ini');
}
}
public function GetRssPageURL(){
return $this->GetStaticUrl('rsspage');
}
/**
* Loops through all the modules and loads each one's URI Matches (named regular expressions) to add to the $MatchURI member variable
* @return void
*/
public function LoadModuleMatches(){
$modules = iwp_modules::getInstance();
foreach($modules->ModuleList() as $moduleName){
$array = call_user_func(array('iwp_module_' .$moduleName, 'getUriMatches'));
if(!is_array($array) || sizeof($array) < 1){
continue;
}
if(is_array($array['From']) && is_array($array['To']) && sizeof($array['To']) > 0 && sizeof($array['From']) > 0){
foreach($array['From'] as $k=>$val){
if(!in_array($val, $this->MatchURI['From'])){
$this->MatchURI['From'][] = $val;
$this->MatchURI['To'][] = $array['To'][$k];
}
}
}
}
}
/**
* Loops through all the loaded modules and collects their uriPatterns.ini files into a large associative array in $this->ModuleUrls
*
* @param boolean $force If set to true, it will re-read all the files even if they've already been loaded before.
*
* @return void
*/
public function LoadModuleURIs($force = false){
if(is_array($this->ModuleUrls) && sizeof($this->ModuleUrls) > 0 && !$force){
return;
}
$modules = iwp_modules::getInstance();
foreach($modules->ModuleList() as $moduleName){
$iniFile = IWP_MODULES_PATH . '/'.$moduleName.'/uriPatterns.ini';
if(file_exists($iniFile)){
$this->ModuleUrls[$moduleName] = parse_ini_file($iniFile);
}
}
}
/**
* Returns an array of all the module URLs for a specified module
*
* @param string $module The name of the module to get the variables for.
*
* @return array An array of module URLs for a specified module
*/
public function GetModuleUrls($module=null){
if($module !== null && isset($this->ModuleUrls[$module])){
return $this->ModuleUrls[$module];
}
return $this->ModuleUrls;
}
/**
* This function returns the URL for the Error 404 page
*
* @return string The URL to the 404 page.
*/
public function Error404URL(){
return $this->StaticUrls['error404'];
}
/**
* This function takes in the UserID and name and returns the User's profile page.
*
* @return string The URL to a speicified User's profile page
*/
public function ViewAuthorProfileURL($userid=null, $name=null){
if(is_null($name) && is_null($userid)) {
return $this->Error404URL();
}
if(is_null($name) && iwp_IsId($userid)) {
$userData = iwp_user::getInstance()->GetUserDataById($userid);
if(!is_array($userData) || sizeof($userData) < 1){
return $this->Error404URL();
}
$name = trim($userData['firstname'] .' '. $userData['lastname']);
}elseif(!iwp_IsId($userid)){
return $this->Error404URL();
}
$name = $this->CleanURL(trim($name));
$url = $this->StaticUrls['viewauthor'];
$url = str_replace('{name}', $name, $url);
$url = str_replace('{idnumber}', $userid, $url);
$url = $this->ForceSlash($url);
return '/'.$url;
}
public function UpdateCategoryURL($categoryId, $newURL){
if($this->db->FetchOne('select count(urlid) from ' . IWP_TABLE_URLS . ' where `associd`=' . (int)$categoryId . ' AND `assoctype`="categories" AND urlpath="' . $this->db->Quote($newURL) . '"') < 1){
$UpdateData = array();
$UpdateData['assoctype'] = 'redirect';
$UpdateData['redirecttype'] = 'categories';
$this->db->UpdateQuery(IWP_TABLE_URLS, $UpdateData, '`associd`=' . (int)$categoryId . ' AND `assoctype`="categories"');
$InsertData = array();
$InsertData['assoctype'] = 'categories';
$InsertData['associd'] = (int)$categoryId;
$InsertData['urlpath'] = $newURL;
$this->db->InsertQuery(IWP_TABLE_URLS, $InsertData);
}
}
public function CategoryNameForURL($categoryName) {
$categoryName = iwp_strtolower($categoryName);
$categoryName = preg_replace('#["' . preg_quote("~`!@^&*()_+{}|:?><,./;'[]\\", "#") . "]#", "", $categoryName);
$categoryName = str_replace(array('$', '%', '#', '+', '/') , "", $categoryName);
$categoryName = preg_replace("# +#", " ", $categoryName);
$categoryName = str_replace(" ", "-", trim($categoryName));
return $categoryName;
}
public function GetParentCategoriesURL($parentid, $categoryClass=null) {
if(is_null($categoryClass) || !is_object($categoryClass)){
$categoryClass = iwp_admin_categories::getInstance();
}
if ($parentid == 0){
return '';
}else{
$name = $this->CategoryNameForURL($categoryClass->catsById[$parentid]['name']);
return $this->GetParentCategoriesURL($categoryClass->parentsById[$parentid], $categoryClass) . $name . '/';
}
}
public function GenerateCategoryURL($name, $catid, $parentid, $categoryClass=null) {
if(is_null($categoryClass) || !is_object($categoryClass)){
$categoryClass = iwp_admin_categories::getInstance();
}
$categoryClass->getCategoryInformation();
$categoryName = $this->CategoryNameForURL($name);
$parentCategories = '';
if($parentid > 0){
$parentCategories = $this->GetParentCategoriesURL($parentid, $categoryClass);
}
$increment = 0;
$newURL = '/' . $this->lang->Get('urlCategory') . '/' . $parentCategories . $categoryName .'.html';
if($catid > 0){
$sql = "select count(urlid) from " . IWP_TABLE_URLS . ' where `urlpath`="%s" AND NOT(assoctype="categories" AND associd=' . $catid . ')';
}else{
$sql = "select count(urlid) from " . IWP_TABLE_URLS . ' where `urlpath`="%s"';
}
$count = $this->db->FetchOne(sprintf($sql, $newURL));
while($count > 0){
++$increment;
if($increment < 20){
$newURL = '/' . $this->lang->Get('urlCategory') . '/' . $parentCategories . $categoryName . '-' . $increment .'.html';
$count = $this->db->FetchOne(sprintf($sql, $newURL));
}else{
$newURL = '/' . $this->lang->Get('urlCategory') . '/' . $parentCategories . $categoryName . '-' . rand(1000,200000) . '.html';
$count = $this->db->FetchOne(sprintf($sql, $newURL));
}
}
return $newURL;
}
/**
* Takes in a category ID and name and outputs its URL
*
* @return string The URL of the specified URL
*/
public function ViewCategoryURL($catid=null){
if(is_null($catid) || (int)$catid < 1) {
return $this->Error404URL();
}
$catid = intval($catid);
if (isset(iwp_categories::$categoryNameURLCache[$catid])) {
return iwp_categories::$categoryNameURLCache[$catid]['url'];
}
$url = $this->db->FetchOne('select urlpath from ' . IWP_TABLE_URLS . ' where associd=' . $catid . ' AND assoctype="categories"');
return $url;
}
/**
* Cleans a string ready to be entered into a URL by replacing spaces, casting to lowercase and urlencoding.
*
* @param string $str The string to clean for use in a URL
*
* @return string The cleaned string ready for a URL
*/
public function CleanURL($str, $FixSpaces=true){
if($FixSpaces){
$str = $this->ReplaceSpaces($str);
}
$str = iwp_strtolower($str);
$str = urlencode($str);
$str = str_replace(array('%5C', '%2F', '%2B'), array('%255C', '%252F' , '%252B'), $str);
return $str;
}
/**
* This is the reverse of the CleanURL() function, it takes a URL string and returns it to a normal string with spaces and not urlencoded
*
* @param string $str The string to be returned to normal
*/
public function ReverseCleanURL($str){
$str = str_replace("-", " ", $str);
$str = urldecode($str);
$str = str_replace("%2d", "-", $str);
return $str;
}
/**
* This function will create a unique URL for a piece of content. If a URL is already taken, it adds a number to the end of the string.
*
* @param integer $id The ID number of the content item to create the URL for
* @param iwp_content $contentInstance This should be an instance of the content item, if it is null it is created
* @param iwp_contenttype $contentTypeInstance This should be an instance of the content type, if it is null it is created
*
* @return string The unique URL for the piece of content ready to be used and/or saved to the database
*/
public function GetUniqueContentUrl($id, $contentInstance=null, $contentTypeInstance=null){
if(!iwp_IsId($id)) {
return '';
}
if(!is_object($contentTypeInstance)){
$contentTypeInstance = iwp_contenttypes::getInstance();
}
$urlpath = $contentTypeInstance->GetUrlForContentItem($contentInstance,$id);
$count = 1;
$maxOut = 100;
while($this->db->FetchOne('select count(*) from '. IWP_TABLE_URLS .' where urlpath="'.$this->db->Quote($urlpath).'"') > 0){
--$maxOut;
++$count;
if($maxOut < 1){
break;
}
$urlpath = $contentTypeInstance->GetUrlForContentItem($contentInstance,$id,'-'.$count);
if(empty($urlpath)){
return '';
}
}
return $urlpath;
}
/**
* This is a generic function to get a URL for categories, content or users.
*
* @param string $type The type of URL to get; categories, content or users
* @param integer $id The ID for the item to get the URL for
* @param array $data An array with any additional data needed to retrieve the URL
*
* @return string The URL for the requested category, content or user.
*/
public function GetUrl($type, $id, $data){
$url = '';
if($type == 'categories'){
$url = $this->ViewCategoryURL($data['categoryid']);
}elseif($type == 'content'){
if(!iwp_IsId($id)) {
return iwp_config::Get('siteURL') .'/';
}
$query = 'select * from ' . IWP_TABLE_URLS .' where assoctype="'.$this->db->Quote($type).'" AND associd='.$id;
$urlData = $this->db->FetchQuery($query);
if(!is_array($urlData) || sizeof($urlData) < 1 || is_null($urlData['urlpath'])){
// lets try to generate the url
$contentType = iwp_contenttypes::getInstance();
if($contentType->GetId() != $data['typeid']){
$contentType->Load($data['typeid']);
}
$maxOut = 500;
$Insert = array();
$Insert['urlpath'] = $this->GetUniqueContentUrl($id, null, $contentType);
$Insert['assoctype'] = 'content';
$Insert['associd'] = $id;
if(!$this->valid->IsBlank($Insert['urlpath'])){
$this->db->InsertQuery(IWP_TABLE_URLS, $Insert);
}
$url = $Insert['urlpath'];
}else{
$url = $urlData['urlpath'];
}
}elseif($type == 'users'){
$name = trim($data['firstname'] . ' ' . $data['lastname']);
$url = $this->ViewAuthorProfileURL($id, $name);
}
return $url;
}
/**
* Returns a string with the base application path
*
* @param boolean $leadingSlash If set to true (default) it will ensure there is a leading slash on the return string
* @param boolean $trailingSlash If set to true (default) it will ensure there is a trailing slash on the return string
*
* @return string The URL path to the application without the domain
*/
public function GetURLPrepend($leadingSlash=true,$trailingSlash=true){
return $this->ForceSlash(iwp_config::Get('appPath'), $leadingSlash, $trailingSlash);
}
/**
* Takes in a string and prepares it for use in a URL by replacing spaces with dashes
*
* @param string $str The string to have the spaces and single quotes replaced
*
* @return string The cleaned string with spaces replaced
*/
public function ReplaceSpaces($str){
$str = str_replace("-", "%2d", $str);
$str = str_replace(" ", "-", $str);
$str = str_replace("'", "%27",$str);
return $str;
}
/**
* Takes in a string and prepares it for use in a URL by replacing spaces with dashes
*
* @param string $str The string to have the spaces and single quotes replaced
*
* @return string The cleaned string with spaces replaced
*/
public function ReplaceSpacesOnly($str){
$str = str_replace(" ", "-", $str);
return $str;
}
/**
* Takes in a string and prepares it for use in a URL by removing bad characters
*
* @param string $str The string to have the bad characters removed
* @param boolean $removeSpaces Whether or not to replace the spaces in the string as well
*
* @return string The cleaned string with bad characters removed
*/
public function RemoveBadCharacters($str, $removeSpaces=true){
$badChars = array('"', "'", "}", "{", "<", ">", "\\", "=", "+", "*", "^", "&", "$", ".", "/", "%", "#", "@", "!","`", "~", "[", "]", "|", ":", ";", ",", "?");
$str = str_replace($badChars, "", $str);
if($removeSpaces){
$str = $this->ReplaceSpacesOnly($str);
}
return $str;
}
/**
* The getter function for the $CurrentStaticPage member variable
*
* @return string The current static page that matched the current URL
*
* @see $CurrentStaticPage
*/
public function GetCurrentStaticPage(){
return $this->CurrentStaticPage;
}
/**
* The getter function for the $CurrentModulePage member variable
*
* @return string The current module page that matched the current URL
*
* @see $CurrentModulePage
*/
public function GetCurrentModulePage(){
return $this->CurrentModulePage;
}
/**
* The getter function for the $CurrentModule member variable
*
* @return string The current module that had a page match the current URL
*
* @see $CurrentModule
*/
public function GetCurrentModule(){
return $this->CurrentModule;
}
/**
* Checks if a URL passed in matches one of the defined static URLs. If there is a match, it sets the $CurrentStaticPage member variable and returns true.
*
* @param string $url The URL to search for a match. If null, the function will use the member variable $currentURL.
*
* @return boolean True if there was a match, false otherwise
*
* @see $StaticUrls
* @see ForceSlash()
* @see SetCurrentStaticPage()
* @see SetCurrentMatches()
*/
public function IsStaticURL($url=null){
if($url === null){
$url = $this->GetCurrentURL();
}
$appPath = $this->ForceSlash(iwp_config::Get('appPath'), true, false);
$url = CleanPath($url);
// this ensures it has a leading slash but not a trailing one
$url = $this->ForceSlash($url, true, false);
// this is a quicker check for any urls that aren't regexes
if(in_array($url, $this->StaticUrls)){
$key = array_search($url, $this->StaticUrls);
if(in_string('_alias', $key)) {
$key = substr($key, 0, strpos($key, '_alias'));
}
$this->SetCurrentStaticPage($key);
return true;
}
foreach($this->StaticUrls as $key=>$value){
$regexValue = $this->TokensToRegex($value);
if(preg_match('#^'.$regexValue.'[/]{0,1}$#ism', $url, $matches)){
if(in_string('_alias', $key)) {
$key = substr($key, 0, strpos($key, '_alias'));
}
$this->SetCurrentStaticPage($key);
$this->SetCurrentMatches($matches);
return true;
}
}
// nothing was found!
return false;
}
/**
* Checks to see if a passed in URL matches any of the modules defined URLs.
*
* @param string $url The URL to search for a match. If null, the function will use the member variable $currentURL.
*
* @return boolean True if there was a match, false otherwise
*
* @see LoadModuleMatches()
* @see LoadModuleURIs()
* @see ForceSlash()
* @see SetCurrentModulePage()
* @see SetCurrentMatches()
*/
public function IsModuleURL($url=null){
if($url === null){
$url = $this->GetCurrentURL();
}
$url = CleanPath($url);
// this ensures it has a leading slash but not a trailing one
$url = $this->ForceSlash($url, true, false);
$this->LoadModuleMatches();
if(!is_array($this->ModuleUrls) || sizeof($this->ModuleUrls) < 1){
$this->LoadModuleURIs();
}
// this is a quicker check for any urls that aren't regexes
foreach($this->ModuleUrls as $modulename=>$array){
if(in_array($url, $array)){
$this->SetCurrentModulePage(array_search($url, $array), $modulename);
return true;
}
}
foreach($this->ModuleUrls as $modulename=>$uris){
foreach($uris as $key=>$value){
$regexValue = $this->TokensToRegex($value);
if(preg_match('#^'.$regexValue.'[/]{0,1}$#i', $url, $matches)){
$this->SetCurrentModulePage($key, $modulename);
$this->SetCurrentMatches($matches);
return true;
}
}
}
// nothing was found!
return false;
}
/**
* This is the setter for the $CurrentStaticPage member variable
*
* @param string $key The name of the current matched static page
*
* @return void
*/
private function SetCurrentStaticPage($key){
$this->CurrentStaticPage = $key;
}
/**
* This is the setter for the $CurrentModulePage and $CurrentModule member variables
*
* @param string $key The name of the current matched module page
* @param string $module The name of the module that owns the matched page
*
* @return void
*/
private function SetCurrentModulePage($key,$module){
$this->CurrentModulePage = $key;
$this->CurrentModule = $module;
}
/**
* This is the setter for the $CurrentSegmentMatches member variable. It holds all matched segments in the URL.
*
* @param array $matches The array of matched segments
*
* @return void
*/
private function SetCurrentMatches($matches){
$this->CurrentSegmentMatches = $matches;
}
/**
* The getter function for the $CurrentSegmentMatches member variable. It holds all matched segments in the URL.
*
* @return array The array of matched segments
*/
public function GetCurrentMatches(){
return $this->CurrentSegmentMatches;
}
/**
* The setter function for the member variable $CurrentURL
*
* @param string $url The URL to set the CurrentURL to
*
* @return void
*/
public function SetCurrentURL($url){
$this->CurrentURL = $url;
}
/**
* The getter function for the member variable $CurrentURL
*
* @return string The value of the current set URL
*/
public function GetCurrentURL(){
return $this->CurrentURL;
}
/**
* Replaces placeholder tokens in a URL string with their associated regex patterns
*
* @param string $value The string to have the tokens replaced
*
* @return string A regular expression string ready for use in a regular expression function
*/
private function TokensToRegex($value){
$value = str_replace($this->MatchURI['From'], $this->MatchURI['To'], $value);
return $value;
}
/**
* This function takes a key/name of a static URL and retrieves the value from a list. It uses the values passed in to replace the tokens and returns the resulting string.
*
* @param string $name The name/key of the static URL to retrieve
* @param array $values An array of values to replace tokens with
*
* @return string A URL string ready for use with the tokens replaced
*/
public function GetStaticUrl($name, $values=null){
$url = $this->StaticUrls[$name];
if(is_array($values)){
foreach($values as $key=>$value){
$url = str_replace('{preslash}{'.$key.'}', '/' . $this->CleanURL($value), $url);
$url = str_replace('{optionalslash}{'.$key.'}', '/' . $this->CleanURL($value), $url);
$url = str_replace('{'.$key.'}{postslash}', $this->CleanURL($value) . '/', $url);
$url = str_replace('{'.$key.'}', $this->CleanURL($value), $url);
}
}
$url = preg_replace('#\{[a-zA-Z_]*\}#i', '', $url);
$url = str_replace('//', '/', $url);
$url = str_replace('//', '/', $url);
return $this->GetURLPrepend(). $this->RemoveLeadingSlash($url);
}
/**
* This function takes in a string (usually a URL or path) and ensures there is or isn't leading and trailing slashes
*
* @param string $url The URL/path to check the slashes on
* @param boolean $leading True will ensure there IS a leading slash, false will ensure there isn't one.
* @param boolean $trailing True will ensure there IS a trailing slash, false will ensure there isn't one.
*
* @return string The URL/path with the slashes confirmed
*/
public function ForceSlash($url,$leading=false,$trailing=false){
if($leading){
if(substr($url,0,1) != '/'){
$url = '/' . $url;
}
}else{
if(substr($url,0,1) == '/'){
$url = substr($url,1);
}
}
if($trailing){
if(substr($url,-1) != '/'){
$url = $url . '/';
}
}else{
if(substr($url,-1) == '/'){
$url = substr($url,0, -1);
}
}
return $url;
}
/**
* Checks to see if there is a leading slash and removes it if there is
*
* @param string $url The URL or path to ensure there is no leading slash
*
* @return string The URL or path without a leading slash.
*/
function RemoveLeadingSlash($url){
if(substr($url,0,1) == '/'){
$url = substr($url,1);
}
return $url;
}
/**
* Checks to see if there is a leading slash and removes it if there is
*
* @param string $url The URL or path to ensure there is no leading slash
*
* @return string The URL or path without a leading slash.
*/
function ConfirmLeadingSlash($url){
if(substr($url,0,1) != '/'){
$url = '/' . $url;
}
return $url;
}
/**
* TODO: Allow modules to enter URLs into the iwp_urls table
*/
public function RegisterModuleURL($moduleId, $url){
}
}