<?php

/* ======================================================================*\
  || #################################################################### ||
  || # vBulletin 5.0.0 Beta 10
  || # ---------------------------------------------------------------- # ||
  || # Copyright �2000-2012 vBulletin Solutions Inc. All Rights Reserved. ||
  || # This file may not be redistributed in whole or significant part. # ||
  || # ---------------- VBULLETIN IS NOT FREE SOFTWARE ---------------- # ||
  || # http://www.vbulletin.com | http://www.vbulletin.com/license.html # ||
  || #################################################################### ||
  \*====================================================================== */

/**
 * This class is used for creating redirects of legacy URLs
 * Based on vB_Friendly_Url 
 */
abstract class vB5_Route_Legacy extends vB5_Route
{
	/**
	 * Friendly URL types 
	 */
	const FRIENDLY_URL_OFF		= 0;
	const FRIENDLY_URL_BASIC	= 1;
	const FRIENDLY_URL_ADVANCED	= 2;
	const FRIENDLY_URL_REWRITE	= 3;
	
	/**
	 * Regex to clean fragments.
	 *
	 * @var string
	 */
	const CLEAN_URL_REGEX = '*([\s$+,/:=\?@"\'<>%{}|\\^~[\]`\r\n\t\x00-\x1f\x7f]|(?(?<!&)#|#(?![0-9]+;))|&(?!#[0-9]+;)|(?<!&#\d|&#\d{2}|&#\d{3}|&#\d{4}|&#\d{5});)*s';
	
	/**
	 * Unicode URL options
	 *
	 * @var int
	 */
	const UNI_IGNORE = 0;
	const UNI_CONVERT = 1;
	const UNI_STRIP = 2;
	
	/**
	 * Method that was used for creating friendly URLs
	 * @var int 
	 */
	private $friendlyUrlMethod;
	
	/**
	 * The rewrite segment to identify this friendly url type.
	 *
	 * @var string
	 */
	protected $rewrite_segment;
	
	/**
	 * The name of the script that the URL links to.
	 *
	 * @var string
	 */
	protected $script;
	
	/**
	 * olcontenttypeid used in node table while importing content
	 * @var mixed - int or array 
	 */
	protected $oldcontenttypeid;
	
	/**
	 * The request variable for the resource id.
	 *
	 * @var string
	 */
	protected $idvar;
	
	public function __construct($routeInfo = array(), $matches = array(), $queryString = '')
	{
		if (!empty($routeInfo))
		{
			parent::__construct($routeInfo, $matches, $queryString);
		}
		else
		{
			// We are not parsing the route
			$this->arguments = array('friendlyurl' => $this->getFriendlyUrlMethod());
		}
	}
	
	protected function getFriendlyUrlMethod()
	{
		if (!isset($this->friendlyUrlMethod))
		{
			$this->friendlyUrlMethod = vB::getDatastore()->getOption('friendlyurl');
		}
		
		return $this->friendlyUrlMethod;
	}
	
	public function getRedirect301()
	{
		if (!isset($this->arguments['friendlyurl']))
		{
			return false;
		}
		// Get the appropriate url
		switch ($this->arguments['friendlyurl'])
		{
			case self::FRIENDLY_URL_BASIC:
				$keys = array_keys($this->queryParameters);
				if (!empty($keys) AND preg_match('#^(?P<oldid>[0-9]+)(?P<title>(-[A-Za-z0-9-]*)*)#', $keys[0], $matches))
				{
					$oldid = $matches['oldid'];
					unset($this->queryParameters[$keys[0]]);
				}
				else
				{
					return false;
				}
				break;
				
			case self::FRIENDLY_URL_ADVANCED:
				if (!isset($this->arguments['oldid']))
				{
					return false;
				}
				else
				{
					$oldid = $this->arguments['oldid'];
				}
				break;
				
			case self::FRIENDLY_URL_REWRITE:
				return false;
				break;

			case FRIENDLY_URL_OFF:
			default:
				$oldid = 0;
				if (isset($this->queryParameters[$this->idvar]))
				{
					$oldid = $this->queryParameters[$this->idvar];
					unset($this->queryParameters[$this->idvar]);
				}	
				if (isset($this->queryParameters[$this->pagevar]))
				{
					$this->arguments['pagevar'] = $this->queryParameters[$this->pagevar];
					unset($this->queryParameters[$this->pagevar]);
				}
				break;
		}

		//See if we have a cached version
		$cache = vB_Cache::instance(vB_Cache::CACHE_STD);
		$cacheKey = get_class($this) . $this->getCacheKey($oldid);
		$newRouteInfo = $cache->read($cacheKey);

		if ($newRouteInfo === false)
		{
			$newRouteInfo = $this->getNewRouteInfo($oldid);
			$cache->write($cacheKey, $newRouteInfo, 86400);
		}
		
		return $this->setNewRoute($newRouteInfo);
	}
	
	protected function getCacheKey($oldid)
	{
		return '_' . $this->idvar . '_' . $oldid;
	}
	
	protected function getNewRouteInfo($oldid)
	{
		// this method has different implementation in some subclasses
		$node = vB::getDbAssertor()->getRow('node', array(
			'oldid' => $oldid,
			'oldcontenttypeid' => $this->oldcontenttypeid
		));
		
		if (empty($node))
		{
			return false;
		}
		else
		{
			return $node;
		}
	}
	
	/**
	 * Sets arguments for the new route
	 */
	protected function setNewRoute($routeInfo)
	{
		// this method has different implementation in some subclasses
		if (!empty($routeInfo))
		{
			$this->arguments['nodeid'] = $routeInfo['nodeid'];

			if (isset($this->arguments['pagevar']))
			{
				$this->arguments['pagenum'] = intval($this->arguments['pagevar']);
			}

			return $routeInfo['routeid'];
		}
		else
		{
			return false;
		}
	}

	/**
	 * Replaces url entities with -
	 *
	 * @param string $fragment
	 * @return string
	 */
	/*
	public static function cleanEntities($fragment)
	{
		$fragment = preg_replace(self::CLEAN_URL_REGEX, '-', strip_tags($fragment));
		$fragment = trim(preg_replace('#-+#', '-', $fragment), '-');

		return $fragment;
	}
	*/
	
	/**
	 * Cleans output to be parsed into the uri.
	 * Setting $canonical is useful for creating redirect url's that cannot be
	 * encoded for redirects.
	 *
	 * @param string $fragment
	 * @param bool $canonical							- Whether to encode for output
	 * @return string
	 */
	/*
	public static function cleanFragment($fragment, $canonical = false)
	{
		$friendlyUrlUnicode = vB::getDatastore()->getOption('friendlyurl_unicode');

		// Convert to UTF-8
		if (self::UNI_CONVERT == $friendlyUrlUnicode)
		{
			// convert to UTF-8
			$fragment = vB_String::toUtf8($fragment, vB_String::getCharset());

			// convert NCRs
			$fragment = vB_String::unHtmlSpecialChars($fragment, true);
		}
		else if (self::UNI_STRIP == $friendlyUrlUnicode)
		{
			// strip NCRs
			$fragment = vB_String::stripNcrs($fragment);
		}

		// Remove url entities
		$fragment = self::cleanEntities($fragment);

		// Prepare the URL for output
		if (!$canonical AND (self::UNI_CONVERT == $friendlyUrlUnicode) AND ('UTF-8' != vB_String::getCharset()))
		{
			if (vB::getRequest()->isBrowser('ie'))
			{
				if (vB::getDatastore()->getOption('friendlyurl_ncrencode'))
				{
					$fragment = vB_String::ncrEncode($fragment, true);
				}
			}
			else
			{
				$fragment = urlencode($fragment);
			}
		}
		else if ($canonical AND (self::UNI_IGNORE == $friendlyUrlUnicode))
		{
			// ensure NCRs are converted
			$fragment = vB_String::unHtmlSpecialChars($fragment, true);
		}

		return $fragment;
	}
	 *
	 */
	
	/**
	 * Checks whether to ignore a pageinfo element when building the uri.
	 *
	 * @param string $key						- The key of the var to check
	 * @param bool $skip_pageinfo				- Whether to skip current pageinfo
	 * @return bool								- Whether to skip the argument
	 */
	/*
	protected function skipQueryVar($key, $skip_pageinfo = true)
	{
		if (in_array($key, $this->ignorelist) OR ($skip_pageinfo AND isset($this->pageinfo[$key])))
		{
			return true;
		}

		return false;
	}
	 */
	
	/**
	 * Renders the pageinfo query string.
	 * Vars that are included in the main uri should be defined in $ignorelist so
	 * they can be skipped.
	 *
	 * @return string
	 */
	/*
	protected function getQuery()
	{
		$arguments = array();

		// Add session argument if settings require it
//		if (!($this->urloptions & SEO_NOSESSION) AND isset($this->registry->session) AND $this->registry->session->visible)
//		{
//			$arguments['s'] = vB::getCurrentSession()->get('dbsessionhash');
//		}

		// Add any arguments that are not already displayed as part of friendly url
		if (!empty($this->pageinfo) AND is_array($this->pageinfo))
		{
			foreach ($this->pageinfo AS $var => $value)
			{
				if (!$this->skipQueryVar($var, false))
				{
					$arguments[$var] = $value;
				}
			}
		}

		// Check ampersand to use
//		$amp = ($this->urloptions & SEO_JS) ? '&' : '&amp;';
		$amp = '&';
		$arguments = implode_both('=', $amp, $arguments);

		return $arguments;
	}
	*/
	
	/**
	 * Returns only the uri.
	 * Setting $canonical gets the uri without encoding it for output.
	 * @see vB_Friendly_Url::redirect_canonical_url()
	 *
	 * @param bool $canonical							- If true, don't encode for output
	 * @return string
	 */
	protected function getUriRegex()
	{
		if (FRIENDLY_URL_OFF == vB::getDatastore()->getOption('friendlyurl'))
		{
			return false;
		}

//		return self::cleanFragment($this->id . '-' . $this->title, $canonical);
		$this->arguments['oldid'] = '$oldid';
		return '(?P<oldid>[0-9]+)(?P<title>(-[^?&]*)*)';
	}
	
	public function getPrefix()
	{
		$method = $this->friendlyUrlMethod;
		
		if ($method == self::FRIENDLY_URL_REWRITE)
		{
			// redirect must be handled in rewrite rule
			return false;
		}
		else
		{
			$prefix = $this->script;
		}
		
		//this is a nasty workaround, but we have to do it.  Instead of dealing with the base option
		//and forcing the full url after we construct the url, do it before.  The reason is that 
		//create_full_url can deal poorly with UTF characters encoded as &#xxxx; in the url (because it contains
		//'#'.  This may happen in friendly urls when the title contains UTF characters in this format.  
		if ($this->script_base_option_name AND ($scriptBaseOptionName = vB::getDatastore()->getOption($this->script_base_option_name)))
		{
			$prefix = $scriptBaseOptionName . '/' . $prefix;
		}
		
		return $prefix;
	}
	
	public function getRegex()
	{
		$regex = $this->getPrefix();
		
		$method = $this->friendlyUrlMethod;
		switch($method)
		{
			case self::FRIENDLY_URL_REWRITE:
				return false;
				
			case self::FRIENDLY_URL_ADVANCED:
				if ($uri = $this->getUriRegex())
				{
					$regex .= '/' . $uri;
				}
				break;
		}
		
		return $regex;
	}
	
	protected static function validInput(array &$data)
	{
		// we cannot create nor update these routes
		throw new Exception('Invalid route data');
	}

	/**
	 * 
	 * @throws Exception 
	 */
	protected static function updateContentRoute($oldRouteInfo, $newRouteInfo)
	{
		// we cannot update content for these routes
		throw new Exception('Invalid route data');
	}
}

/*======================================================================*\
|| ####################################################################
|| # 
|| # CVS: $RCSfile$ - $Revision: 40911 $
|| ####################################################################
\*======================================================================*/
