<?php
/*
*	NP_FancierURL2 provides serach engine optimized URLs:
*
*	/item/id	=>	/item/yyyy/mm/title
*	/item/id	=>	/item/title (optional)
*	/member/id	=>	/member/name
*	/category/id/blogid/id	=>	/category/name/blogid/number
*	/blog/id	=>	/blog/name
*	
*	NP_FancierURL2 requirements:
*		- an account with an activated mod_rewrite Module
*		- Nucleus version 3.22 or higher
*		- a .htaccess file in the root of the Nucleus installtion:
*
*				<IfModule mod_rewrite.c>
*				RewriteEngine on
*				RewriteCond %{REQUEST_FILENAME} !-f
*				RewriteCond %{REQUEST_FILENAME} !-d
*				RewriteRule ^(.*)$ index.php?virtualpath=$1 [L]
*				</IfModule>
*
*	History:
*	
*	NP_FancierURL2 is derived from NP_SeoURL v0.1 which is a
*	plugin under development for the Nucleus 3.3 version. 
*	NP_SeoURL is based on NP_ReplaceURL from Wouter Demuynck.
*
*	v0.1 2006-11-08 Kai Greve (http://kgblog.de):
*		- initial release
*		
*	v0.2 2007-01-07 Kai Greve (http://kgblog.de):
*		- table plug_urls is also included in the database backup 
*		- categories are also in the look up table to support
*		  characters from other languages
*		- option added: whether the date is included in item urls or not
*
*	v0.3 2007-06-13 Kai Greve (http://kgblog.de):
*		- compatibility mode added which support old style fancy urls:
*		  item/1234, member/1234, category/1234 and blog/1234
*		- use the global variable $virtualpath for Nucleus version 3.3
*		  and higher
*		  
*	v0.3eh 2007-06-18 Edmond Hui (http://edmondhui.homeip.net/blog)
*		- add utf-8/Chinese (un)friendly url fallback
*		- fix category generateURL handling
*		- subscribe to delete event to cleanup mapping table on item and category delete
*		
*	v0.4 2007-12-02 Kai Greve (http://kgblog.de): 	
*		- change the way in which  encoding is interpreted and add a new option
*		  for the encoding to avoid problems if mb_detect_encoding fails 
*		- Overwerite the clearOptionValueCache function of the parent class
*		  (NucleusPlugin) because it has a bug: doesn't set the variable 
*		  plugin_options to zero (needed to refresh the url table after 
*		  the PostPluginOptionsUpdate event)
*		- Repair the code that counts the entries with the same title
*		  that are published before
*		  
*	v0.5 2008-02-17 wessite and Edmond Hui:
*		fix from wessite (http://www.wessite.com) and code 
*		from Edmond Hui (http://edmondhui.homeip.net/blog):
*		- don't consider titels from drafts when building URLs 
*		  (to avoid problems with the Autosave draft function)
*		  
*	v0.6 2009-03-21 Kai Greve (http://kgblog.de): 	
*		- fixed bug: if an item is updated the category with the same ID isn't changed
*		- changed formatting and more comments
*		
*	Todos:
*		- Category links in a multiblog environment don't be generated
*		  proper in the Template (but they are right in the sidebar)
*		  
*	Notes: 
*		- mname (member name) and bshortname (blog short name) only allows the
*		  characters a-z and 0-9 without spaces => they are url friendly	
*
*/
 
class NP_FancierURL2 extends NucleusPlugin
{
	// SQL table name
	var $table;
 
	// used as cache between Pre/PostAddItem
	var $tmp_title;
	var $tmp_timestamp;
 
	// used as cache between Pre/PostPluginOptionsUpdate
	var $withdate_changed;
	var $encoding_changed;
 
 
	function getName()  { return 'NP_FancierURL2'; }
	function getAuthor() { return 'Wouter Demuynck | Edmond Hui | Kai Greve'; }
	function getURL()     { return 'http://plugins.nucleuscms.org/'; }
	function getVersion() { return '0.6'; }
	function getMinNucleusVersion() { return 322; }
	function getMinNucleusPatchLevel() { return 0; }
	function getDescription() {
		return 'Replaces the /item/1234 URLs by /item/yyyy/mm/urlified_title or /item/urlified_title,  /member/1234 by /member/name, /category/1234 by /category/name and /blog/1234 by /blog/name.';
	}
 
	/**
     * Plugin supports table prefixes (needed since Nucleus CMS 2.0)
	 */
	function supportsFeature($what) {
		switch ($what)
		{
			case 'SqlTablePrefix':
				return 1;
			default:
				return 0;
		}
	}
 
	/**
     * Events used by this plugin 
	 */
	function getEventList() {
		return array('ParseURL', 'GenerateURL', 'PreAddItem', 'PostAddItem', 'PreUpdateItem', 'PostUpdateItem', 'PostAddCategory', 'PostPluginOptionsUpdate', 'PrePluginOptionsUpdate', 'PostDeleteItem', 'PostDeleteCategory');
	}
 
	/**
     * Define table name after the plugin is started 
	 */
	function init() {
		$this->table = sql_table('plug_urls');
	}
 
	/**
     * Returns an array of tables to be additionally included
     * in the backup process
	 */
	function getTableList() {
		return array($this->table);
	}
 
	/**
	 * When installing the plugin, create a table for mapping the rewritten URLs
	 * of items and fill it with initial data
	 */
	function install() {
		// create options
		$this->createOption('withdate','Include the date in URLs for items (/item/yyyy/mm/title) or not (/item/title)','yesno','yes');
		$this->createOption('oldstyle','Compatibility mode: support also old style fancy urls (e.g. item/1234)','yesno','no');
		$this->createOption ('encoding','Choose encoding automatic (AUTO) or manual (ISO-8859-1, UTF-8 or ASCII):', 'select', 'AUTO', 'AUTO|AUTO|ISO-8859-1|ISO-8859-1|UTF-8|UTF-8|ASCII|ASCII');
 
		// create initial mapping
		$this->_createMapping();
	}
 
	/**
	 * When uninstalling the plugin, remove the table with the URL mappings from
	 * the database
	 */
	function uninstall() {
		$this->_deleteMapping();
	}
 
	/**
	 * Create a mapping of all items and categories in the database (Member 
	 * names are not in the table because they are unique identifiers) 
	 */
	function _createMapping() {
		// create mapping table
		sql_query(
			  'CREATE TABLE ' . $this->table
			. ' ('
			. '  type char(1) NOT NULL,'
			. '  id int(11) NOT NULL,'
			. '  urlpart varchar(168) NOT NULL,'
			. '  PRIMARY KEY (type, id)'
			. ' );'
		);
 
		// create mappings for all existing items
		$r = sql_query('SELECT ititle as title, UNIX_TIMESTAMP(itime) as timestamp, inumber as itemid FROM ' . sql_table('item'));
		while ($o = mysql_fetch_object($r)) {
			$this->_addToMapping($o->title, $o->timestamp, $o->itemid);
		}
 
		// create mappings for all existing categories
		$r = sql_query('SELECT cname, catid FROM ' . sql_table('category'));
		while ($o = mysql_fetch_object($r)) {
			$this->_addCategoryToMapping($o->cname, $o->catid);
		}
	}
 
	/**
	 * Delete the mapping by removing the database table
	 */
	function _deleteMapping() {
		sql_query('DROP TABLE ' . $this->table);
	}
 
	/**
	 *  Fetch the title and the timestamp of an item before it is lost during
	 *  the saving procedure
	 */
	function event_PreAddItem(&$data) {
		$this->tmp_title = $data['title'];
		$this->tmp_timestamp = $this->_dateToUnix($data['timestamp']);
	}
 
	/**
	 *  Add the new item to the mapping table
	 */
	function event_PostAddItem(&$data) {
		$this->_addToMapping($this->tmp_title, $this->tmp_timestamp, $data['itemid']);
	}
 
	/**
	 *  Fetch the title of an item before it is lost during the updating
	 *  procedure
	 */
	function event_PreUpdateItem(&$data) {
		$this->tmp_title = $data['title'];
	}
 
	/**
	 * Add the updated item to the mapping table
	 */
	function event_PostUpdateItem(&$data) {
		$timestamp = quickQuery('SELECT UNIX_TIMESTAMP(itime) as result FROM ' . sql_table('item') . ' WHERE inumber=' .  intval($data['itemid']));
		$this->_updateMapping($this->tmp_title, $this->_buildUrlPart($this->tmp_title, $timestamp), $data['itemid']);
	}
 
	/**
	 * After a new category is added retrieve the category name 
	 * and call the mapping function
	 */
	function event_PostAddCategory(&$data) {
 
		$catid = $data['catid'];
		$cname = $data['name'];
 
		if ($cname=='') {
			$q = "SELECT cname as result FROM ". sql_table ('category') . " WHERE catid ='" . $catid . "'";
			$cname = quickQuery ($q);
		}
 
		$this->_addCategoryToMapping($cname, $catid);
	}
 
	/**
	 * Add a category name to the mapping table
	 */
	function _addCategoryToMapping($cname, $catid) {
			$catid = intval($catid);
 
			// Build the URL part for the categroy name
			$urlpart=$this->_makeUrlFriendly($cname);
 
			if (strstr($urlpart, "unfriendly_utf8item") != false) {
				$urlpart = "category".$catid;
			}
 
			// Insert the URL part into the mapping table
			$q = 'INSERT INTO ' . $this->table . ' (type, id, urlpart) values (\'c\', \'' . $catid . '\', \'' . addslashes($urlpart) . '\')';
			sql_query($q);
	}
 
	/**
	 *  Save information if option withdate or encoding was changed 
	 *  for the PostPluginOptionsUpdate event
	 */
	function event_PrePluginOptionsUpdate(&$data) {
		// evaluate if option withdate was changed
		if ($data['optionname']=='withdate') {
			$this->withdate_changed = $this->getOption('withdate')!=$data['value'];		
		}
 
		// evaluate if option encoding was changed
		if ($data['optionname']=='encoding') {
			$this->encoding_changed = $this->getOption('encoding')!=$data['value'];		
		}
	}
 
 
	/**
	* Event PostPluginOptionsUpdate is used for:
	* - Updating the category name in the mapping table after a change
	* - Rebuild the mapping table if the 'withdate' option is changed 		 
	*/	
	function event_PostPluginOptionsUpdate (&$data) {
 
		// Work around for missing PostUpdateCategory event
		if ($data['context']== 'category'){
			$q = "SELECT cname as result FROM ". sql_table ('category') . " WHERE catid ='" . $data['catid'] . "'";
			$cname = quickQuery ($q);
			$this->_updateCategoryMapping ($this->_makeUrlFriendly($cname), $data['catid']);
		}
 
		// Rebuild the mapping table if the option 'withdate' (for the date
		// in item urls) or 'encoding' was changed
		if ($this->withdate_changed || $this->encoding_changed){
			$this->_rebuildMapping();
		}
 
	}
 
	/**
	 *	Rebuild Mapping: delete the old and create a new one
	 */	 	 	
	function _rebuildMapping () {
		// clear the option cache in the NucleusPlugin class
		$this->clearOptionValueCache();
		// rebuild the mapping
		$this->_deleteMapping();
		$this->_createMapping();
	}
 
	/**
	 *	Overwerite original function in the parent class (NucleusPlugin)
	 *	because it has a bug: it doesn't set the variable plugin_options 
	 *	to zero which is used in the getOption function
	 */
	function clearOptionValueCache() {
		$this->_aOptionValues = array();
		$this->plugin_options = 0; 
	}
 
 
	/**
	 * Update an urlpart of a category in the mapping table
	 */
	function _updateCategoryMapping($urlpart, $catid) {
		if (strstr($urlpart, "unfriendly_utf8item") != false) {
			$urlpart = "category".$catid;
		}
 
		$q = 'UPDATE ' . $this->table . ' SET urlpart=\'' . addslashes($urlpart) . '\' WHERE type=\'c\' and id=\'' . $catid . '\'';
		sql_query($q);
	}
 
	/**
	 * Adds a given itemid/urlpart pair to the mapping table
	 */
	function _addToMapping($title, $timestamp, $itemid) {
		$itemid = intval($itemid);
 
		// Count entries with the same title that are published before
		$q = "SELECT count(inumber) as result FROM ". sql_table ('item') . " WHERE ititle ='" .  addslashes($title) . "' AND UNIX_TIMESTAMP(itime) < " . $timestamp." AND inumber !='" . $itemid . "' AND idraft=0";
		$number = intval(quickQuery ($q));
 
		// Build the URL part for the item
		$urlpart=$this->_buildUrlPart($title,$timestamp);
 
		// If urlpart contains "unfriendly_utf8item", it means the title is unfriendly, we will use itemXXX
		if (strstr($urlpart, "unfriendly_utf8item") != false) {
			$urlpart = str_replace("unfriendly_utf8item", "item".$itemid, $urlpart);
		} else {
			// Note: we only add -X if we know the title is friendly and duplicated.
			// Append the number for the item title to the URL part
			if ($number>0) {
				$number++;
				$urlpart .= '-' . $number;
			}
		}
 
		// Insert the URL part into the mapping table
		$q = 'INSERT INTO ' . $this->table . ' (type, id, urlpart) values (\'i\', \'' . $itemid . '\', \'' . addslashes($urlpart) . '\')';
		sql_query($q);
	}
 
	/**
	 * Updates an urlpart of an itemid in the mapping table
	 */
	function _updateMapping($title, $urlpart, $itemid) {
 
		$itemid = intval($itemid);
 
		// Count entries with the same title that are published before
		$q = "SELECT count(inumber) as result FROM ". sql_table ('item') . " WHERE ititle ='" . addslashes($title) . "' AND inumber != " . $itemid . " AND idraft=0";
		$number = intval(quickQuery ($q));
 
		// If urlpart contains "unfriendly_utf8item", it means the title is unfriendly, we will use itemXXX
		if (strstr($urlpart, "unfriendly_utf8item") != false) {
			$urlpart = str_replace("unfriendly_utf8item", "item".$itemid, $urlpart);
		} else {
			// Note: we only add -X if we know the title is friendly and duplicated.
			// Append the number for the item title to the URL part
			if ($number>0) {
				$number++;
				$urlpart .= '-' . $number;
			}
		}
 
		$q = 'UPDATE ' . $this->table . ' SET urlpart=\'' . addslashes($urlpart) . '\' WHERE id=\'' . $itemid . '\'' . 'AND type=\'i\'';
		sql_query($q);
	}
 
	/**
	 * Parse URLs:
	 *		/item/yyyy/mm/title => $itemid
	 *		/member/name => $memberid
	 *		/category/name/blogid/number => $catid and $blogid
	 *		/blog/name => $blogid
	 */
	function event_ParseURL(&$data) {
		global $itemid, $memberid, $catid, $blogid, $CONF, $archivelist, $archive;
 
		// nothing to do if another plugin already parsed the URL
		if ($data['complete'])
			return;
 
		// get the requested URL
		if (getNucleusVersion()>=330) {
			// use global variable from Nucleus
			global $virtualpath;
			$parts = explode("/", addslashes($virtualpath));
		}
		else {
			// resolve the requested URL directly from the GET variable
			$parts = explode("/", addslashes(requestVar('virtualpath')));
		}
 
		if (count($parts) < 1) {
			return;
		}
 
		switch ($parts[0])
		{
			case $CONF['ItemKey']:	// parts: item/YYYY/MM/title = 0/1/2/3
				// support old style fancy urls: item/1234 
				if ($this->getOption('oldstyle')=="yes") {
					$urlstring=$parts[1].$parts[2].$parts[3];
					if (is_numeric($urlstring)) {
						$itemid = (int)$urlstring;
						$data['complete'] = true;
						break;
					}
				}
				// resolve urls: item/YYYY/MM/title and item/title
				$itemid = $this->_findItem($parts[1], $parts[2], $parts[3]);
				if ($itemid != 0)
				{
					$data['complete'] = true;
				}
				break;
			case $CONF['MemberKey']:	// parts: member/name = 0/1
				// support old style fancy urls: member/1234 
				if ($this->getOption('oldstyle')=="yes") {
					$urlstring=$parts[1].$parts[2].$parts[3];
					if (is_numeric($urlstring)) {
						$memberid = (int)$urlstring;
						$data['complete'] = true;
						break;
					}
				}
				// resolve urls: member/name
				$memberid = intval($this->_findMemberID($parts[1]));
				if ($memberid != 0)
				{
					$data['complete'] = true;
				}
				break;
			case $CONF['CategoryKey']:	// parts: category/name/blogid/number = 0/1/2/3
				// support old style fancy urls: category/1234 
				if ($this->getOption('oldstyle')=="yes") {
					$urlstring=$parts[1];
					if (is_numeric($urlstring)) {
						$catid = (int)$urlstring;
						$data['complete'] = true;
						break;
					}
				}
				// resolve urls: category/name/blogid/number
				if ($parts[2] == 'blogid'){
					$blogid = intval($parts[3]);
				}
				else {
					$blogid = $CONF['DefaultBlog'];
				}
				$catid = intval($this->_findCategoryID($parts[1],$blogid));
 
				if ($catid != 0)
				{
					$data['complete'] = true;
				}
				break;
			case $CONF['BlogKey']:	// parts: blog/name = 0/1
				// support old style fancy urls: blog/1234 
				if ($this->getOption('oldstyle')=="yes") {
					$urlstring=$parts[1];
					if (is_numeric($urlstring)) {
						$blogid = (int)$urlstring;
						$data['complete'] = true;
						break;
					}
				}
 
				// resolve urls: blog/name
				$blogid = intval($this->_findBlogID($parts[1]));
				if ($blogid != 0)
				{
					$data['complete'] = true;
				}
				break;
			// added because the default implementation of Nucleus
			// only works if PATH_INFO is enabled on the server
			case $CONF['ArchivesKey']:		// archives/1 (blogid)
				$archivelist = intval($parts[1]);
				break;
			// added because the default implementation of Nucleus
			// only works if PATH_INFO is enabled on the server
			case $CONF['ArchiveKey']:		// two possibilities: archive/yyyy-mm or archive/1/yyyy-mm (with blogid)
			if (isset($parts[1])&&isset($parts[2])&&(!strstr($parts[1],'-'))) {
					$blogid = intval($parts[1]);
					$archive = $parts[2];
				}
				else {
					$archive = $parts[1];
				}
				break;
 
			default: $data['complete'] = false;
		}
	}
 
	/**
	 * Generate URLs:
	 * 		/item/yyyy/mm/title
	 * 		...
	 */
	function event_GenerateURL(&$data) {
		// if another plugin already generated the URL
		if ($data['completed'])
			return;
 
		global $CONF;
 
		$params = $data['params'];
 
		switch ($data['type'])
		{
			case 'item':
				$itemid = $params['itemid'];
				$query = "SELECT urlpart as result FROM " . sql_table('plug_urls') . " WHERE type='i' AND id='" . $itemid . "'";
				$urlpart = quickQuery ($query);
 
				$baseurl = $CONF['Self'] . '/' . $CONF['ItemKey'] . '/' . $urlpart;
				$data['url'] = addLinkParams($baseurl, $params['extra']);
 
				$data['completed'] = true;
				break;
 
			case 'member':
				$memberid = $params['memberid'];
 
				$baseurl = $CONF['Self'] . '/' . $CONF['MemberKey'] . '/' . $this->_findMemberName($memberid);
				$data['url'] = addLinkParams($baseurl, $params['extra']);
 
				$data['completed'] = true;
				break;
 
			case 'category':
				$catid = $params['catid'];
				$query = "SELECT urlpart as result FROM " . sql_table('plug_urls') . " WHERE type='c' AND id='" . $catid . "'";
				$urlpart = quickQuery ($query);
				$baseurl = $CONF['Self'] . '/' . $CONF['CategoryKey'] . '/' . $urlpart;
				// $params['extra'] (e.g. /blog/1) is not always initialized
				if (isset($params['extra'])){
					$data['url'] = addLinkParams($baseurl, $params['extra']);
				}
				else {
					$data['url'] = $baseurl;
				}
 
				$data['completed'] = true;
				break;
 
			case 'blog':
				$blogid = $params['blogid'];
 
				$baseurl = $CONF['Self'] . '/' . $CONF['BlogKey'] . '/' . $this->_findBlogName($blogid);
				$data['url'] = addLinkParams($baseurl, $params['extra']);
 
				$data['completed'] = true;
				break;
 
			default:
				$data['completed'] = false;
				break;
		}
	}
 
	/**
	 * Remove entry in the mapping table after an item is deleted
	 */
	function event_PostDeleteItem($data) {
		sql_query("DELETE FROM ".sql_table('plug_urls')." WHERE type='i' AND id= '".$data['itemid']."'");
	}
 
	/**
	 * Remove entry in the mapping table after a category is deleted
	 */
	function event_PostDeleteCategory($data) {
		sql_query("DELETE FROM ".sql_table('plug_urls')." WHERE type='c' AND id= '".$data['catid']."'");
	}
 
	/**
	 * Creates an URL part out of a title and a timestamp.
	 * The resulting url part looks like "2005/07/item_title_here"
	 */
	function _buildUrlPart($title, $timestamp)
	{
		$ts = getdate($timestamp);
		if ($ts['mon']<10) {
			$lead = '0';
		}
		else {
			$lead = '';
		}
 
		if ($this->getOption('withdate')=='no') {
			$urlpart = $this->_makeUrlFriendly($title);
		}
		else {	// used as default solution
			$urlpart = $ts['year'] . '/' . $lead . $ts['mon'] . '/' . $this->_makeUrlFriendly($title);
		}
 
		return $urlpart;
	}
 
	/**
	 * Finds the item ID corresponding to a given URL part
	 */
	function _findItem($year, $month, $title)
	{
			if ($month=='' || $month==$CONF['CategoryKey'] || $month=='catid'){
				$urlstring = $year;			
			}
			else {
				$urlstring = $year . '/' . $month . '/' . $title;
			}
 
			// Find URL part in mapping table
			$query = "SELECT id as result FROM ". sql_table('plug_urls') ." WHERE type='i' AND urlpart='" . $urlstring . "'";
			$res= quickQuery ($query);
 
			return intval($res);
	}
 
	/**
	 * Finds the member ID corresponding to a given member name
	 */
	function _findMemberID($name)
	{
		$q = "SELECT mnumber as result FROM " . sql_table('member') . " WHERE mname='" . $name . "'";
		return quickQuery($q);
	}
 
	/**
	 * Finds the member name corresponding to a given member id
	 * (to generate the member URL)
	 */
	function _findMemberName($id)
	{
		$q = 'SELECT mname as result FROM ' . sql_table('member') . ' WHERE mnumber=\'' . $id . '\' LIMIT 1';
		return quickQuery($q);
	}
 
	/**
	 * Finds the category ID corresponding to a given category name and blog id
	 */
	function _findCategoryID($name, $blog)
	{
		$query = "SELECT id as result FROM ". sql_table('plug_urls') ." WHERE type='c' AND urlpart='" . $name . "'";
		$res= quickQuery ($query);
 
		return intval($res);
	}
 
	/**
	 * Finds the blog ID corresponding to a given blog short name
	 */
	function _findBlogID($name)
	{
		$q = "SELECT bnumber as result FROM " . sql_table('blog') . " WHERE bshortname='" . $name . "'";
		return quickQuery($q);
	}
 
	/**
	 * Finds the blog short name corresponding to a given blog id
	 */
	function _findBlogName($id)
	{
		$q = "SELECT bshortname as result FROM " . sql_table('blog') . " WHERE bnumber='" . $id . "'";
		return quickQuery($q);
	}
 
	/**
	 * Generates an URL-friendly title.
	 */
	function _makeUrlFriendly($title)
	{
		$title = strtolower(trim($title));
		$title = str_replace(' ', '-', $title);
		$title = str_replace("'", '-', $title);
 
		// use default encoding from option encoding
		// or try to evaluate character encoding
		$encoding = '';
		$encoding_trim = trim($this->getOption ('encoding'));
		if ($encoding_trim!='') {
			$encoding = $encoding_trim;
		} else {
			if (function_exists('mb_detect_encoding')) {
				$encoding = mb_detect_encoding($title);
			}
		}
 
		// translate letters
		switch ($encoding) {
			case "ISO-8859-1": // What is the encoding for German??
				$title = str_replace('ä', 'ae', $title);
				$title = str_replace('ö', 'oe', $title);
				$title = str_replace('ü', 'ue', $title);
				$title = str_replace('ß', 'sz', $title);
				break;
			case "UTF-8":
				break;
			case "ASCII":
				break;
			default:
		}
 
		// remove untranslated letters:
		// only letters, numbers and underscores are allowed
		$title = preg_replace("/[^a-z0-9_-]/", "", $title);
 
		// report the title is unfriendly if we failed to convert it
		if ($title == '') {
			$title = 'unfriendly_utf8item';
		}
		return $title;
	}
 
	/**
	 * Returns the item title and timestamp for a given item id. Only non-draft
	 * and present items are considered, unless the logged in member is an admin
	 * or author of the item.
	 */
	function _getItemDetails($itemid)
	{
		$r = sql_query('SELECT ititle, UNIX_TIMESTAMP(itime) as timestamp FROM ' . sql_table('item') . ' WHERE idraft=0 and inumber=' . intval($itemid));
		$o = mysql_fetch_object($r);
		if ($o)
			return array('title' => $o->ititle, 'timestamp' => $o->timestamp);
		else
			return array('title' => '', 'timestamp' => 0);
	}
 
	/**
	 * Converts a date which is formatted as 'Y-m-d H:i:s' into a unix timestamp
	 */
	function _dateToUnix($strDate) {
		list($date, $time) = explode(' ', $strDate);
		list($y, $m, $d) = explode('-', $date);
		list($h, $min, $s) = explode(':', $time);
		return mktime($h,$min,$s,$m,$d,$y);
	}
 
	/**
	 * Output of the resolved item URL for the feed templates  
	 */
	function doTemplateVar(&$item) {
		$query = "SELECT urlpart as result FROM " . sql_table('plug_urls') . " WHERE type='i' and id='" . $item->itemid . "'";
		$urlpart = quickQuery ($query);
		echo "item/".$urlpart;
	}
 
}
?>
np_fancierurl2_code.txt · Last modified: 2009/03/21 13:18 (external edit)
 
Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution-Noncommercial-Share Alike 3.0 Unported
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki