<?php

/**
 * <pre>
 * Invision Power Services
 * IP.CCS front end database interface
 * Last Updated: $Date: 2009-09-22 19:34:19 -0400 (Tue, 22 Sep 2009) $
 * </pre>
 *
 * @author 		$Author: bfarber $
 * @copyright	(c) 2001 - 2009 Invision Power Services, Inc.
 * @license		http://www.invisionpower.com/community/board/license.html
 * @package		IP.Content
 * @link		http://www.invisionpower.com
 * @since		1st March 2009
 * @version		$Revision: 93 $
 */

if ( ! defined( 'IN_ACP' ) )
{
	print "<h1>Incorrect access</h1>You cannot access this file directly.";
	exit();
}

class databaseBuilder
{
	/**
	 * Page builder library
	 *
	 * @access	protected
	 * @var		object
	 */
	protected $pages;
	
	/**#@+
	 * Registry objects
	 *
	 * @access	protected
	 * @var		object
	 */	
	protected $registry;
	protected $DB;
	protected $settings;
	protected $request;
	protected $lang;
	protected $member;
	protected $memberData;
	protected $caches;
	protected $cache;
	/**#@-*/
	
	/**
	 * Custom fields class
	 *
	 * @access	public
	 * @var		obj
	 */
	public $fieldsClass;
	
	/**
	 * Categories handler
	 *
	 * @access	public
	 * @var		obj
	 */
	public $categories;
	
	/**
	 * Plugin class
	 *
	 * @access	public
	 * @var		obj
	 */
	public $plugin;
	
	/**
	 * Array of information about the database
	 *
	 * @access	public
	 * @var		array
	 */
	public $database		= array();
	
	/**
	 * Array of information about the fields in this database
	 *
	 * @access	public
	 * @var		array
	 */
	public $fields			= array();
	
	/**
	 * Cached record data, if pulled for FURL parsing
	 *
	 * @access	private
	 * @var		array
	 */
	private $_record		= array();

	/**
	 * Constructor
	 *
	 * @access	public
	 * @param	object	ipsRegistry
	 * @param	mixed	pageBuilder object, or null (i.e. if using a utility function such as checkModerator())
	 * @return	void
	 */
	public function __construct( ipsRegistry $registry, $pages=null )
	{
		/* Make object */
		$this->registry		=  $registry;
		$this->DB			=  $this->registry->DB();
		$this->settings		=& $this->registry->fetchSettings();
		$this->request		=& $this->registry->fetchRequest();
		$this->lang			=  $this->registry->getClass('class_localization');
		$this->member		=  $this->registry->member();
		$this->memberData	=& $this->registry->member()->fetchMemberData();
		$this->cache		=  $this->registry->cache();
		$this->caches		=& $this->registry->cache()->fetchCaches();
		$this->pages		=  $pages;
	}

	/**
	 * Get and return database HTML
	 *
	 * @access	public
	 * @param	string		Database key
	 * @param	array 		Page data
	 * @return	string		Database HTML
	 */
	public function getDatabase( $key, $page )
	{
		//-----------------------------------------
		// Load skin file if it hasn't been loaded yet
		//-----------------------------------------
		
		$this->pages->loadSkinFile();
		
		//-----------------------------------------
		// Get the database info
		//-----------------------------------------
		
		$this->database	= $this->_loadDatabase( $key );

		if( !$this->database['database_id'] OR !$this->database['database_database'] )
		{
			return '';
		}
		
		if ( $this->registry->permissions->check( 'view', $this->database ) != TRUE )
		{
			return '';
		}
		
		//-----------------------------------------
		// Fix language strings
		//-----------------------------------------
		
		$this->registry->ccsFunctions->fixStrings( $this->database['database_id'] );
		
		//-----------------------------------------
		// Get plugin functionality
		//-----------------------------------------
		
		$this->_loadPlugin();

		//-----------------------------------------
		// Basic perm checking and init
		//-----------------------------------------
		
		if( !$this->_initDatabase( $page ) )
		{
			return '';
		}

		//-----------------------------------------
		// Get possible field types
		//-----------------------------------------
		
		$this->fieldsClass	= $this->registry->ccsFunctions->getFieldsClass();

		$this->fields	= array();

		if( is_array($this->caches['ccs_fields'][ $this->database['database_id'] ]) AND count($this->caches['ccs_fields'][ $this->database['database_id'] ]) )
		{
			foreach( $this->caches['ccs_fields'][ $this->database['database_id'] ] as $_field )
			{
				$this->fields[ $_field['field_id'] ]	= $_field;
			}
		}

		//-----------------------------------------
		// Get category handler
		//-----------------------------------------
		
		$this->categories	= $this->registry->ccsFunctions->getCategoriesClass( $this->database );
		
		//-----------------------------------------
		// Fix database furls... sigh :(
		//-----------------------------------------
		
		$this->fixDatabaseFurls();

		//-----------------------------------------
		// What action to take
		//-----------------------------------------
		
		switch( $this->request['do'] )
		{
			case 'add':
				return $this->_actionAdd();
			break;
			
			case 'save':
				return $this->_actionSaveAdd();
			break;
			
			case 'edit':
				return $this->_actionEdit();
			break;
			
			case 'save_edit':
				return $this->_actionSaveEdit();
			break;
			
			case 'comment':
				return $this->_actionComment();
			break;
			
			case 'delete':
				return $this->_actionDelete();
			break;
			
			case 'deleteComment':
				return $this->_actionDeleteComment();
			break;
			
			case 'toggleComment':
				return $this->_actionToggleComment();
			break;
			
			case 'lock':
			case 'unlock':
				return $this->_actionToggleLock();
			break;
			
			case 'pin':
			case 'unpin':
				return $this->_actionPin();
			break;
			
			case 'approve':
			case 'unapprove':
				return $this->_actionApprove();
			break;
			
			case 'search':
				$this->_loadTemplates( 'category' );

				return $this->_getDatabaseListing();
			break;
			
			case 'watch':
			case 'unwatch':
				return $this->_actionWatch();
			break;
		}
		
		//-----------------------------------------
		// Get templates
		//-----------------------------------------
		
		$this->_loadTemplates();

		//-----------------------------------------
		// If none of the above, view cats, listing or record?
		//-----------------------------------------

		$_content	= '';
		
		if( $this->request['record'] )
		{
			$_content	.= $this->_getRecordDisplay();
		}
		else if( $this->request['category'] )
		{
			$_content	.= $this->_getDatabaseListing();
		}
		else
		{
			$_content	.= $this->_getDatabaseCategories();
		}

		return $_content;
	}
	
	/**
	 * Get listing of categories
	 *
	 * @access	protected
	 * @return	string		HTML
	 */
	protected function _getDatabaseCategories()
	{
		$this->checkPermalink( $this->database['base_link'] );
		
		//-----------------------------------------
		// Get all categories
		//-----------------------------------------
		
		$categories	= $this->categories->catcache[0];
		
		if( !count($categories) )
		{
			//-----------------------------------------
			// We have categories, but none we can view
			//-----------------------------------------
			
			if( $this->categories->hasCategories )
			{
				$this->registry->output->showError( $this->lang->words['no_cats_can_view'], '10CCS26' );
			}

			$this->_loadTemplates( 'category' );
			
			$_content	.= $this->_getDatabaseListing();
		}
		else
		{
			foreach( $categories as $id => $data )
			{
				$categories[ $id ]				= $this->categories->getCategory( $id );
				$_children						= $this->categories->getChildren( $id );
				$categories[ $id ]['children']	= array();
				
				if( count($_children) )
				{
					foreach( $_children as $_child )
					{
						$categories[ $id ]['children'][ $_child ]					= $this->categories->getCategory( $_child );
						$categories[ $id ]['children'][ $_child ]['category_link']	= $this->categories->getCategoryUrl( $this->database['base_link'], $_child );
					}
				}
				
				//-----------------------------------------
				// Latest record display
				//-----------------------------------------

				if( in_array( $this->database['database_field_title'], array( 'primary_id_field', 'member_id', 'record_saved', 'record_updated', 'rating_real' ) ) )
				{
					$categories[ $id ][ $this->database['database_field_title'] . '_value' ]	= ( $this->database['database_field_title'] == 'record_saved' OR $this->database['database_field_title'] == 'record_updated' ) ? $this->registry->class_localization->getDate( $categories[ $id ][ $this->database['database_field_title'] ], 'LONG' ) : $categories[ $id ][ $this->database['database_field_title'] ];
				}
				else
				{
					$categories[ $id ][ $this->database['database_field_title'] . '_value' ]	= $this->fieldsClass->getFieldValue( $this->fields[ str_replace( 'field_', '', $this->database['database_field_title'] ) ], $categories[ $id ], $this->fields[ str_replace( 'field_', '', $this->database['database_field_title'] ) ]['field_truncate'] );
				}
				
				$categories[ $id ]['record_link']	= $this->getRecordUrl( array( 'primary_id_field' => $categories[ $id ]['category_last_record_id'], 'category_id' => $categories[ $id ]['category_last_record_cat'] ? $categories[ $id ]['category_last_record_cat'] : $id, $this->database['database_field_title'] . '_value' => $categories[ $id ][ $this->database['database_field_title'] . '_value' ], '_skipUpdateDynamic' => true ) );
				$categories[ $id ]['category_link']	= $this->categories->getCategoryUrl( $this->database['base_link'], $id );
			}
			
			$this->pages->setMetaKeywords( $this->database['database_meta_keywords'] );
			$this->pages->setMetaDescription( $this->database['database_meta_description'] );
			$this->pages->setCanonical( rtrim( $this->database['base_link'], '?' ) );

			$template	= 'template_' . $this->database['template_key'];
			$_content	.= $this->registry->output->getTemplate('ccs')->$template( array( 'database' => $this->database, 'categories' => $categories ) );
		}
		
		return $_content;
	}
	
	/**
	 * Get listing of records in a database
	 *
	 * @access	protected
	 * @return	string		HTML
	 */
	protected function _getDatabaseListing()
	{
		//-----------------------------------------
		// Do we have children?
		//-----------------------------------------
		
		$category					= $this->categories->getCategory( $this->request['category'] );
		$category['category_link']	= $this->categories->getCategoryUrl( $this->database['base_link'], $category['category_id'] );
		
		$this->checkPermalink( $category['category_link'] );
		
		$this->pages->setMetaKeywords( $category['category_meta_keywords'] );
		$this->pages->setMetaDescription( $category['category_meta_description'] );
		$this->pages->setCanonical( $category['category_link'] );

		if( $this->request['category'] AND !$category['category_id'] )
		{
			$this->registry->output->showError( $this->lang->words['no_view_perm_cat'], '10CCS27' );
		}
		else if( $this->request['category'] )
		{
			if ( $category['category_has_perms'] AND $this->registry->permissions->check( 'add', $category ) != TRUE )
			{
				$this->database['_can_add']	= false;
			}
		}
		
		$categories	= $this->categories->catcache[ $this->request['category'] ];
		
		if( count($categories) )
		{
			foreach( $categories as $id => $data )
			{
				$categories[ $id ]					= $this->categories->getCategory( $id );
				$categories[ $id ]['category_link']	= $this->categories->getCategoryUrl( $this->database['base_link'], $id );
				$_children							= $this->categories->getChildren( $id );
				$categories[ $id ]['children']		= array();
				
				if( count($_children) )
				{
					foreach( $_children as $_child )
					{
						$categories[ $id ]['children'][]							= $this->categories->getCategory( $_child );
						$categories[ $id ]['children'][ $_child ]['category_link']	= $this->categories->getCategoryUrl( $this->database['base_link'], $_child );
					}
				}
				
				//-----------------------------------------
				// Latest record display
				//-----------------------------------------

				if( in_array( $this->database['database_field_title'], array( 'primary_id_field', 'member_id', 'record_saved', 'record_updated', 'rating_real' ) ) )
				{
					$categories[ $id ][ $this->database['database_field_title'] . '_value' ]	= ( $this->database['database_field_title'] == 'record_saved' OR $this->database['database_field_title'] == 'record_updated' ) ? $this->registry->class_localization->getDate( $categories[ $id ][ $this->database['database_field_title'] ], 'LONG' ) : $categories[ $id ][ $this->database['database_field_title'] ];
				}
				else
				{
					$categories[ $id ][ $this->database['database_field_title'] . '_value' ]	= $this->fieldsClass->getFieldValue( $this->fields[ str_replace( 'field_', '', $this->database['database_field_title'] ) ], $categories[ $id ], $this->fields[ str_replace( 'field_', '', $this->database['database_field_title'] ) ]['field_truncate'] );
				}
				
				if( in_array( $this->database['database_field_content'], array( 'primary_id_field', 'member_id', 'record_saved', 'record_updated', 'rating_real' ) ) )
				{
					$categories[ $id ][ $this->database['database_field_content'] . '_value' ]	= ( $this->database['database_field_content'] == 'record_saved' OR $this->database['database_field_content'] == 'record_updated' ) ? $this->registry->class_localization->getDate( $categories[ $id ][ $this->database['database_field_content'] ], 'LONG' ) : $categories[ $id ][ $this->database['database_field_content'] ];
				}
				else
				{
					$categories[ $id ][ $this->database['database_field_content'] . '_value' ]	= $this->fieldsClass->getFieldValue( $this->fields[ str_replace( 'field_', '', $this->database['database_field_content'] ) ], $categories[ $id ], $this->fields[ str_replace( 'field_', '', $this->database['database_field_content'] ) ]['field_truncate'] );
				}
				
				$categories[ $id ]['record_link']	= $this->getRecordUrl( array( 'primary_id_field' => $categories[ $id ]['category_last_record_id'], 'category_id' => $categories[ $id ]['category_last_record_cat'] ? $categories[ $id ]['category_last_record_cat'] : $id, $this->database['database_field_title'] . '_value' => $categories[ $id ][ $this->database['database_field_title'] . '_value' ], '_skipUpdateDynamic' => true ) );
			}
		}

		//-----------------------------------------
		// Breadcrumbs
		//-----------------------------------------

		if( count($categories) OR $this->request['category'] )
		{
			$crumbies	= $this->categories->getBreadcrumbs( $this->request['category'], $this->database['base_link'] );
	
			if( !$this->settings['use_friendly_urls'] AND !$this->settings['ccs_root_url'] )
			{
				array_unshift( $crumbies, array( 0 => $this->database['database_name'], 1 => substr( $this->database['base_link'], 0, -5 ) ) );
			}
			else
			{
				array_unshift( $crumbies, array( 0 => $this->database['database_name'], 1 => substr( $this->database['base_link'], 0, -1 ) ) );
			}
		}
		else if( !$this->request['category'] )
		{
			if( !$this->settings['use_friendly_urls'] AND !$this->settings['ccs_root_url'] )
			{
				$crumbies	= array( array( 0 => $this->database['database_name'], 1 => substr( $this->database['base_link'], 0, -5 ) ) );
			}
			else
			{
				$crumbies	= array( array( 0 => $this->database['database_name'], 1 => substr( $this->database['base_link'], 0, -1 ) ) );
			}
		}

		$this->pages->addNavigation( $this->registry->output->getTemplate('ccs_global')->databaseNavigation( $crumbies ) );
		
		define( 'CCS_NAV_DONE', true );
		
		if( $category['category_name'] )
		{
			$this->registry->output->setTitle( $category['category_name'] );
		}
		
		//-----------------------------------------
		// Showing records?
		//-----------------------------------------
		
		$_show	= true;
		
		if( $category['category_id'] )
		{
			if( !$category['category_show_records'] )
			{
				$_show	= false;
			}
		}

		$records	= array();
		$pages		= '';
		
		if( $_show )
		{
			//-----------------------------------------
			// Sorting and limiting
			//-----------------------------------------
			
			$perPage	= intval($this->request['per_page']) ? intval($this->request['per_page']) : $this->database['database_field_perpage'];
			$perPage	= intval($perPage) > 0 ? $perPage : 25;
			$start		= intval($this->request['st']) ? intval($this->request['st']) : 0;
			
			$_col		= $this->request['sort_col'];
			$_useCol	= $this->database['database_field_sort'];
			$_numeric	= false;
	
			foreach( $this->fields as $_field )
			{
				if( $_col == 'field_' . $_field['field_id'] )
				{
					$_useCol	= $_col;
				}
			}
			
			if( in_array( $_col, array( 'rating_real', 'record_views', 'primary_id_field', 'member_id', 'record_saved', 'record_updated' ) ) )
			{
				$_useCol	= $_col;
			}
			
			//-----------------------------------------
			// Need to loop a second time to set numeric
			//-----------------------------------------
			
			foreach( $this->fields as $_field )
			{
				if( $_useCol == 'field_' . $_field['field_id'] )
				{
					$_numeric	= $_field['field_is_numeric'];
				}
			}
	
			$_dir		= ( $this->request['sort_order'] && in_array( $this->request['sort_order'], array( 'asc', 'desc' ) ) ) ? $this->request['sort_order'] : $this->database['database_field_direction'];
			
			$this->request['sort_col']		= $_useCol;
			$this->request['sort_order']	= $_dir;
			$this->request['per_page']		= $perPage;
		
			//-----------------------------------------
			// Search
			//-----------------------------------------
	
			$_where	= '';
			
			if( $this->request['search_value'] )
			{
				$_where	= $this->fieldsClass->getSearchWhere( $this->fields, $this->request['search_value'] );
			}
			
			if( $category['category_id'] )
			{
				$_where		= $_where ? "category_id=" . intval($this->request['category']) . " AND (" . $_where . ")" : "category_id=" . intval($this->request['category']);
			}
			else
			{
				if( count($this->categories->categories) )
				{
					$_catIds	= array();
					
					foreach( $this->categories->categories as $_catId => $_cat )
					{
						$_catIds[]	= $_catId;
					}
					
					$_where		= $_where ? "category_id IN(" . implode( ',', $_catIds ) . ") AND (" . $_where . ")" : "category_id IN(" . implode( ',', $_catIds ) . ")";
				}
			}
			
			//-----------------------------------------
			// Only show approved records if we can't mod
			//-----------------------------------------
			
			if( !$this->database['moderate_approve'] )
			{
				if( $_where )
				{
					$_where	= "record_approved=1 AND " . $_where;
				}
				else
				{
					$_where	= "record_approved=1";
				}
			}
			
			$count		= $this->DB->buildAndFetch( array( 'select' => 'COUNT(*) as total', 'from' => $this->database['database_database'], 'where' => $_where ) );
			
			//-----------------------------------------
			// Query string
			//-----------------------------------------
			
			$baseUrl	= $this->request['category'] ? $this->categories->getCategoryUrl( $this->database['base_link'], $this->request['category'], true ) : $this->database['base_link'];
			$_qs		= 'search_value=' . urlencode($this->request['search_value']) . '&amp;sort_col=' . $_useCol . '&amp;sort_order=' . $_dir . '&amp;per_page=' . $perPage;
			
			if( $this->request['do'] == 'search' )
			{
				$_qs	= "do=search&amp;" . $_qs;
			}
			
			//-----------------------------------------
			// Page links
			//-----------------------------------------
			
			$pages		= $this->registry->output->generatePagination( array( 
																	'totalItems'		=> $count['total'],
																	'itemsPerPage'		=> $perPage,
																	'currentStartValue'	=> $start,
																	'baseUrl'			=> $baseUrl . $_qs,
																	'base'				=> 'none',
											 				)	);

			//-----------------------------------------
			// Count for search results
			//-----------------------------------------
			
			if( $this->request['search_value'] )
			{
				$this->database['keyword']		= $this->request['search_value'];
				$this->database['result_cnt']	= $count['total'];
			}

			//-----------------------------------------
			// Records
			//-----------------------------------------
			
			$_memberIds	= array();
			
			$this->DB->build( array( 'select' => '*', 'from' => $this->database['database_database'], 'order' => 'record_pinned DESC, ' . ( $_numeric ? $_useCol . '+0' : $_useCol ) . ' ' . $_dir, 'where' => $_where, 'limit' => array( $start, $perPage ) ) );
			$outer	= $this->DB->execute();
			
			while( $r = $this->DB->fetch($outer) )
			{
				foreach( $r as $k => $v )
				{
					if( preg_match( "/^field_(\d+)$/", $k, $matches ) )
					{
						$r[ $k . '_value' ]	= $this->fieldsClass->getFieldValue( $this->fields[ $matches[1] ], $r, $this->fields[ $matches[1] ]['field_truncate'] );
					}
				}
				
				$r['_isRead']		= $this->registry->classItemMarking->isRead( array( 'catID' => $r['category_id'], 'itemID' => $r['primary_id_field'], 'itemLastUpdate' => $r['record_updated'] ), 'ccs' );
				$r['record_link']	= $this->getRecordUrl( $r );
	
				$records[]						= $r;
				$memberIds[ $r['member_id'] ]	= $r['member_id'];
			}
			
			if( count($memberIds) )
			{
				$_members	= IPSMember::load( $memberIds );
				$_mems		= array();
				
				foreach( $_members as $k => $v )
				{
					foreach( $v as $_k => $_v )
					{
						if( strpos( $_k, 'field_' ) === 0 )
						{
							$_k	= str_replace( 'field_', 'user_field_', $_k );
						}
						
						$_mems[ $k ][ $_k ]	= $_v;
					}
				}
				
				$_members	= $_mems;
				
				foreach( $records as $key => $record )
				{
					$records[ $key ]	= array_merge( $record, IPSMember::buildDisplayData( $_members[ $record['member_id'] ] ) );
				}
			}
		}
		
		//-----------------------------------------
		// Hide fields
		//-----------------------------------------
		
		$showFields	= array();
		
		foreach( $this->fields as $field )
		{
			if( $field['field_display_listing'] )
			{
				$showFields[]	= $field;
			}
		}

		$template	= 'template_' . $this->database['template_key'];
		$_content	.= $this->registry->output->getTemplate('ccs')->$template( array( 'database' => $this->database, 'fields' => $showFields, 'records' => $records, 'pages' => $pages, 'categories' => $categories, 'parent' => $category, 'show' => $_show ) );
		
		return $_content;
	}
	
	/**
	 * Load the database
	 *
	 * @access	protected
	 * @param	string		Key
	 * @return	array 		Database info
	 */
	protected function _loadDatabase( $key )
	{
		if( !$key )
		{
			return array();
		}
		
		$database	= array();
		
		if( count($this->caches['ccs_databases']) AND is_array($this->caches['ccs_databases']) )
		{
			foreach( $this->caches['ccs_databases'] as $dbid => $_database )
			{
				if( $key == $_database['database_key'] )
				{
					$database	= $_database;
				}
			}
		}
		
		//-----------------------------------------
		// Store globally for item marking lib
		//-----------------------------------------
		
		if( $database['database_id'] )
		{
			$this->settings['_currentDatabaseId']	= $database['database_id'];
		}
		
		return $database;
	}
	
	/**
	 * Load the appropriate template data
	 *
	 * @access	protected
	 * @param	string		Override to a specific template type
	 * @return	void
	 */
	protected function _loadTemplates( $override='' )
	{
		//-----------------------------------------
		// Which template we loading?
		//-----------------------------------------
		
		$templateType	= $override;
		
		if( $this->request['record'] )
		{
			$templateType	= 'record';
		}
		else if( $this->request['category'] )
		{
			$templateType	= 'category';
		}
		else if( !$override )
		{
			$templateType	= 'index';
		}
		
		//-----------------------------------------
		// Get it
		//-----------------------------------------
		
		if( $templateType == 'record' )
		{
			$template	= $this->DB->buildAndFetch( array( 'select' => '*', 'from' => 'ccs_page_templates', 'where' => "template_id=" . $this->database['database_template_display'] ) );
		}
		else if( $templateType == 'category' )
		{
			$template	= $this->DB->buildAndFetch( array( 'select' => '*', 'from' => 'ccs_page_templates', 'where' => "template_id=" . $this->database['database_template_listing'] ) );
		}
		else
		{
			$template	= $this->DB->buildAndFetch( array( 'select' => '*', 'from' => 'ccs_page_templates', 'where' => "template_id=" . $this->database['database_template_categories'] ) );
		}
		
		//-----------------------------------------
		// Merge into database data and return
		//-----------------------------------------
		
		$this->database	= array_merge( $this->database, $template );
	}
	
	
	/**
	 * Get the plugin handler
	 *
	 * @access	protected
	 * @return	void
	 */
	protected function _loadPlugin()
	{
		if( !$this->database['database_id'] )
		{
			return null;
		}

		$this->plugin	= null;
		
		if( file_exists( DOC_IPS_ROOT_PATH . '/hooks/database_callback_' . $this->database['database_id'] . '.php' ) )
		{
			require_once( DOC_IPS_ROOT_PATH . '/hooks/database_callback_' . $this->database['database_id'] . '.php' );
			
			$className	= 'database_callback_' . $this->database['database_id'];
			
			if( class_exists( $className ) )
			{
				$this->plugin	= new $className( $this->registry );
				$this->plugin->startUp();
			}
		}
	}

	/**
	 * Checks permissions for request, and sets some basic parameters
	 *
	 * @access	protected
	 * @param	array 		Page info
	 * @return	bool		Successfully init
	 */	
	protected function _initDatabase( $page )
	{
		//-----------------------------------------
		// Check show and view permissions
		//-----------------------------------------
		
		if( $this->request['record'] )
		{
			if( $this->database['perm_view'] != '*' )
			{ 
				if ( $this->registry->permissions->check( 'view', $this->database ) != TRUE )
				{
					$this->registry->output->showError( $this->lang->words['noperm_list_database'], '10CCS28' );
				}
			}
			
			if( $this->database['perm_2'] != '*' )
			{ 
				if ( $this->registry->permissions->check( 'show', $this->database ) != TRUE )
				{
					$this->registry->output->showError( $this->lang->words['noperm_view_database'], '10CCS29' );
				}
			}
		}
		else
		{
			if( $this->database['perm_view'] != '*' )
			{ 
				if ( $this->registry->permissions->check( 'view', $this->database ) != TRUE )
				{
					//$this->registry->output->showError( $this->lang->words['noperm_list_database'] );
					return false;
				}
			}
		}
		
		//-----------------------------------------
		// Need to set base link for this DB page
		//-----------------------------------------
		
		$this->database['base_link']		= $this->registry->ccsFunctions->returnPageUrl( $page );
		
		if( !$this->settings['use_friendly_urls'] AND !$this->settings['ccs_root_url'] )
		{
			$this->database['base_link']	.= '&amp;';
		}
		else
		{
			$this->database['base_link']	.= '?';
		}

		$this->settings['post_key']	= md5( uniqid( microtime() ) );
		
		//-----------------------------------------
		// Permissions
		//-----------------------------------------
		
		$this->database['_can_add']		= false;
		$this->database['_can_edit']		= false;
		$this->database['_can_rate']		= false;
		$this->database['_can_comment']	= false;
		
		if( $this->database['database_user_editable'] )
		{
			if ( $this->registry->permissions->check( 'add', $this->database ) == TRUE )
			{
				$this->database['_can_add']		= true;
			}
		}
		
		if( $this->database['database_rate'] )
		{
			if ( $this->registry->permissions->check( 'rate', $this->database ) == TRUE )
			{
				$this->database['_can_rate']		= true;
			}
		}
		
		if( $this->database['database_comments'] )
		{
			if ( $this->registry->permissions->check( 'comment', $this->database ) == TRUE )
			{
				$this->database['_can_comment']	= true;
			}
		}
		
		//-----------------------------------------
		// Moderator permissions
		//-----------------------------------------
		
		$this->database	= $this->checkModerator( $this->database );
		
		return true;
	}
	
	/**
	 * Delete a record
	 *
	 * @access	protected
	 * @return	mixed		void (output an error) or HTML to print
	 */
	protected function _actionDelete()
	{
		//-----------------------------------------
		// Can we add?
		//-----------------------------------------
		
		if( !$this->database['moderate_delete'] )
		{
			$this->registry->output->showError( $this->lang->words['noperm_del_record'], '10CCS30' );
		}
		
		//-----------------------------------------
		// Get the data
		//-----------------------------------------
		
		$record	= $this->DB->buildAndFetch( array( 'select' => '*', 'from' => $this->database['database_database'], 'where' => 'primary_id_field=' . intval($this->request['record']) ) );

		if( !$record['primary_id_field'] )
		{
			$this->registry->output->showError( $this->lang->words['nofind_del_record'], '10CCS31' );
		}
		
		if( $record['category_id'] )
		{
			$category	= $this->categories->categories[ $record['category_id'] ];
			
			if( !$category['category_id'] )
			{
				$this->registry->output->showError( $this->lang->words['nofind_del_record'], '10CCS32' );
			}
			
			if ( $category['category_has_perms'] AND $this->registry->permissions->check( 'show', $category ) != TRUE )
			{
				$this->registry->output->showError( $this->lang->words['nofind_del_record'], '10CCS33' );
			}
		}
		
		//-----------------------------------------
		// Have we confirmed?
		//-----------------------------------------
		
		if( !$this->request['confirm'] )
		{
			return $this->registry->output->getTemplate('ccs_global')->confirmDeleteRecord( $this->database, $record );
		}
		
		//-----------------------------------------
		// Plugin
		//-----------------------------------------
		
		if( $this->plugin )
		{
			if( method_exists( $this->plugin, 'preDelete' ) )
			{
				$this->plugin->preDelete();
			}
		}

		//-----------------------------------------
		// Delete record
		//-----------------------------------------
		
		$this->DB->delete( $this->database['database_database'], 'primary_id_field=' . $record['primary_id_field'] );
		
		//-----------------------------------------
		// Delete revisions
		//-----------------------------------------

		$this->DB->delete( 'ccs_database_revisions', 'revision_database_id=' . $this->database['database_id'] . ' AND revision_record_id=' . $record['primary_id_field'] );
		
		//-----------------------------------------
		// Delete comments
		//-----------------------------------------
		
		$this->DB->delete( 'ccs_database_comments', 'comment_database_id=' . $this->database['database_id'] . ' AND comment_record_id=' . $record['primary_id_field'] );

		//-----------------------------------------
		// Ratings
		//-----------------------------------------
		
		$this->DB->delete( 'ccs_database_ratings', 'rating_database_id=' . $this->database['database_id'] . ' AND rating_record_id=' . $record['primary_id_field'] );
		
		//-----------------------------------------
		// Post process delete
		//-----------------------------------------

		foreach( $this->fields as $field )
		{
			$this->fieldsClass->postProcessDelete( $field, $record );
		}
		
		//-----------------------------------------
		// Topic
		//-----------------------------------------
		
		require_once( IPSLib::getAppDir( 'ccs' ) . '/sources/databases/topics.php' );
		$_topics	= new topicsLibrary( $this->registry, $this->fieldsClass, $this->categories, $this->fields );
		$_topics->removeTopic( $record, $this->categories->categories[ $record['category_id'] ], $this->database );

		//-----------------------------------------
		// Update database
		//-----------------------------------------
		
		if( $record['record_approved'] )
		{
			$this->DB->update( 'ccs_databases', array( 'database_record_count' => ($this->database['database_record_count'] - 1) ), 'database_id=' . $this->database['database_id'] );
		}

		//-----------------------------------------
		// Recache category
		//-----------------------------------------

		$this->categories->recache( $record['category_id'] );

		$this->registry->output->redirectScreen( $this->lang->words['record_deleted_success'], $record['category_id'] ? $this->categories->getCategoryUrl( $this->database['base_link'], $record['category_id'] ) : $this->database['base_link'] );
	}

	/**
	 * Delete a comment
	 *
	 * @access	protected
	 * @return	mixed		void (output an error) or HTML to print
	 */
	protected function _actionDeleteComment()
	{
		//-----------------------------------------
		// Can we add?
		//-----------------------------------------
		
		if( !$this->database['moderate_deletec'] )
		{
			$this->registry->output->showError( $this->lang->words['noperm_del_comment'], '10CCS34' );
		}
		
		//-----------------------------------------
		// Is this a topic comment?
		//-----------------------------------------
		
		if( $this->request['pid'] )
		{
			$comment	= $this->DB->buildAndFetch( array(
														'select'	=> 'p.pid',
														'from'		=> array( 'posts' => 'p' ),
														'where'		=> 'p.pid=' . intval($this->request['pid']),
														'add_join'	=> array(
																			array(
																				'select'	=> 'r.*',
																				'from'		=> array( $this->database['database_database'] => 'r' ),
																				'where'		=> 'r.record_topicid=p.topic_id',
																				'type'		=> 'left',
																				)
																			)
												)		);

			if( !$comment['pid'] )
			{
				$this->registry->output->showError( $this->lang->words['nofind_del_comment'], '10CCS35' );
			}
		}
		else
		{
			//-----------------------------------------
			// Get the data
			//-----------------------------------------
			
			$comment	= $this->DB->buildAndFetch( array(
														'select'	=> 'c.*',
														'from'		=> array( 'ccs_database_comments' => 'c' ),
														'where'		=> 'c.comment_id=' . intval($this->request['comment']),
														'add_join'	=> array(
																			array(
																				'select'	=> 'r.*',
																				'from'		=> array( $this->database['database_database'] => 'r' ),
																				'where'		=> 'r.primary_id_field=c.comment_record_id',
																				'type'		=> 'left',
																				)
																			)
												)		);

			if( !$comment['comment_id'] )
			{
				$this->registry->output->showError( $this->lang->words['nofind_del_comment'], '10CCS36' );
			}
		}
		
		if( $comment['category_id'] )
		{
			$category	= $this->categories->categories[ $comment['category_id'] ];
			
			if( !$category['category_id'] )
			{
				$this->registry->output->showError( $this->lang->words['nofind_del_comment'], '10CCS37' );
			}
			
			if ( $category['category_has_perms'] AND $this->registry->permissions->check( 'show', $category ) != TRUE )
			{
				$this->registry->output->showError( $this->lang->words['nofind_del_comment'], '10CCS38' );
			}
		}
		
		//-----------------------------------------
		// Plugin
		//-----------------------------------------
		
		if( $this->plugin )
		{
			if( method_exists( $this->plugin, 'preDeleteComment' ) )
			{
				$this->plugin->preDeleteComment();
			}
		}

		if( $this->request['pid'] )
		{
			require_once( IPSLib::getAppDir( 'ccs' ) . '/sources/databases/topics.php' );
			$_topics	= new topicsLibrary( $this->registry, $this->fieldsClass, $this->categories, $this->fields );
			$_topics->removeComment( $comment, $this->categories->categories[ $record['category_id'] ], $this->database, $this->request['pid'] );
		}
		else
		{
			//-----------------------------------------
			// Delete comment
			//-----------------------------------------
			
			$this->DB->delete( 'ccs_database_comments', 'comment_id=' . $comment['comment_id'] );
		}
		
		//-----------------------------------------
		// Update database
		//-----------------------------------------
		
		if( !$this->request['pid'] AND $comment['comment_approved'] )
		{
			$this->DB->update( $this->database['database_database'], "record_comments=record_comments-1", 'primary_id_field=' . $comment['primary_id_field'], false, true );
		}
		
		//-----------------------------------------
		// Update category
		//-----------------------------------------

		$this->registry->output->redirectScreen( $this->lang->words['comment_deleted_success'], $this->getRecordUrl( $comment ) );
	}
	
	/**
	 * Lock or unlock record
	 *
	 * @access	protected
	 * @return	mixed		void (output an error) or HTML to print
	 */
	protected function _actionToggleLock()
	{
		//-----------------------------------------
		// Get the data
		//-----------------------------------------
		
		$record	= $this->DB->buildAndFetch( array( 'select' => '*', 'from' => $this->database['database_database'], 'where' => 'primary_id_field=' . intval($this->request['record']) ) );

		if( !$record['primary_id_field'] )
		{
			$this->registry->output->showError( $this->lang->words['nofind_lock_record'], '10CCS39' );
		}
		
		if( $record['category_id'] )
		{
			$category	= $this->categories->categories[ $record['category_id'] ];
			
			if( !$category['category_id'] )
			{
				$this->registry->output->showError( $this->lang->words['nofind_lock_record'], '10CCS40' );
			}
			
			if ( $category['category_has_perms'] AND $this->registry->permissions->check( 'show', $category ) != TRUE )
			{
				$this->registry->output->showError( $this->lang->words['nofind_lock_record'], '10CCS41' );
			}
		}
		
		//-----------------------------------------
		// Update record
		//-----------------------------------------
		
		if( $record['record_locked'] )
		{
			//-----------------------------------------
			// Permission
			//-----------------------------------------
			
			if( !$this->database['moderate_unlock'] )
			{
				$this->registry->output->showError( $this->lang->words['noperm_lock_record'], '10CCS42' );
			}
			
			//-----------------------------------------
			// Plugin
			//-----------------------------------------
			
			if( $this->plugin )
			{
				if( method_exists( $this->plugin, 'preLock' ) )
				{
					$this->plugin->preLock();
				}
			}
			
			$this->DB->update( $this->database['database_database'], array( 'record_locked' => 0 ), 'primary_id_field=' . $record['primary_id_field'] );
			
			$this->registry->output->redirectScreen( $this->lang->words['record_unlocked_success'], $this->getRecordUrl( $record ) );
		}
		else
		{
			//-----------------------------------------
			// Permission
			//-----------------------------------------
			
			if( !$this->database['moderate_lock'] )
			{
				$this->registry->output->showError( $this->lang->words['noperm_lock_record'], '10CCS43' );
			}
			
			//-----------------------------------------
			// Plugin
			//-----------------------------------------
			
			if( $this->plugin )
			{
				if( method_exists( $this->plugin, 'preLock' ) )
				{
					$this->plugin->preLock();
				}
			}
			
			$this->DB->update( $this->database['database_database'], array( 'record_locked' => 1 ), 'primary_id_field=' . $record['primary_id_field'] );
			
			$this->registry->output->redirectScreen( $this->lang->words['record_locked_success'], $this->getRecordUrl( $record ) );
		}
	}
	
	/**
	 * Approve or unapprove record
	 *
	 * @access	protected
	 * @return	mixed		void (output an error) or HTML to print
	 */
	protected function _actionApprove( )
	{
		//-----------------------------------------
		// Permission
		//-----------------------------------------
		
		if( !$this->database['moderate_approve'] )
		{
			$this->registry->output->showError( $this->lang->words['noperm_app_record'], '10CCS44' );
		}
		
		//-----------------------------------------
		// Get the data
		//-----------------------------------------
		
		$record	= $this->DB->buildAndFetch( array( 'select' => '*', 'from' => $this->database['database_database'], 'where' => 'primary_id_field=' . intval($this->request['record']) ) );

		if( !$record['primary_id_field'] )
		{
			$this->registry->output->showError( $this->lang->words['nofind_app_record'], '10CCS45' );
		}
		
		if( $record['category_id'] )
		{
			$category	= $this->categories->categories[ $record['category_id'] ];
			
			if( !$category['category_id'] )
			{
				$this->registry->output->showError( $this->lang->words['nofind_app_record'], '10CCS46' );
			}
			
			if ( $category['category_has_perms'] AND $this->registry->permissions->check( 'show', $category ) != TRUE )
			{
				$this->registry->output->showError( $this->lang->words['nofind_app_record'], '10CCS47' );
			}
		}
		
		//-----------------------------------------
		// Update record
		//-----------------------------------------
		
		if( $record['record_approved'] )
		{
			//-----------------------------------------
			// Plugin
			//-----------------------------------------
			
			if( $this->plugin )
			{
				if( method_exists( $this->plugin, 'preUnapprove' ) )
				{
					$this->plugin->preUnapprove();
				}
			}
			
			$this->DB->update( $this->database['database_database'], array( 'record_approved' => 0 ), 'primary_id_field=' . $record['primary_id_field'] );
			
			$this->DB->update( 'ccs_databases', "database_record_count=database_record_count-1", 'database_id=' . $this->database['database_id'], false, true );
			
			if( $record['category_id'] )
			{
				$this->categories->recache( $record['category_id'] );
			}
			
			$this->registry->output->redirectScreen( $this->lang->words['record_unapprove_success'], $this->getRecordUrl( $record ) );
		}
		else
		{
			//-----------------------------------------
			// Plugin
			//-----------------------------------------
			
			if( $this->plugin )
			{
				if( method_exists( $this->plugin, 'preApprove' ) )
				{
					$this->plugin->preApprove();
				}
			}
			
			$this->DB->update( $this->database['database_database'], array( 'record_approved' => 1 ), 'primary_id_field=' . $record['primary_id_field'] );
			
			$this->DB->update( 'ccs_databases', "database_record_count=database_record_count+1", 'database_id=' . $this->database['database_id'], false, true );
			
			if( $record['category_id'] )
			{
				$this->categories->recache( $record['category_id'] );
			}
			
			//-----------------------------------------
			// If this is first time approval, send notifications
			//-----------------------------------------
			
			$_modQueue	= $this->DB->buildAndFetch( array( 'select' => '*', 'from' => 'ccs_database_modqueue', 'where' => "mod_database={$this->database['database_id']} AND mod_record={$record['primary_id_field']} AND mod_comment=0" ) );
			
			if( $_modQueue['mod_id'] )
			{
		    	//-----------------------------------------
		    	// Post topic if configured to do so
		    	//-----------------------------------------
		    	
		    	require_once( IPSLib::getAppDir( 'ccs' ) . '/sources/databases/topics.php' );
		    	$_topics	= new topicsLibrary( $this->registry, $this->fieldsClass, $this->categories, $this->fields );
		    	$_topics->postTopic( $record, $this->categories->categories[ $record['category_id'] ], $this->database );
	    	
				$_member				= IPSMember::load( $record['member_id'], 'core' );
		    	$record					= array_merge( $_member, $record );
		    	$record['poster_name']	= $record['members_display_name'];
		    	
			    $this->sendRecordNotification( $this->database, $this->categories->categories[ $record['category_id'] ], $record );
			    
			    $this->DB->delete( 'ccs_database_modqueue', "mod_database={$this->database['database_id']} AND mod_record={$record['primary_id_field']} AND mod_comment=0" );
			}
			
			$this->registry->output->redirectScreen( $this->lang->words['record_approve_success'], $this->getRecordUrl( $record ) );
		}
	}
	
	/**
	 * Watch or stop watching a category or record
	 *
	 * @access	protected
	 * @return	mixed		void (output an error) or HTML to print
	 */
	protected function _actionWatch()
	{
		//-----------------------------------------
		// Members only
		//-----------------------------------------
		
		if( !$this->memberData['member_id'] )
		{
			$this->registry->output->showError( $this->lang->words['members_only_watch'], '10CCS48' );
		}
		
		//-----------------------------------------
		// Subscribe to category?
		//-----------------------------------------
		
		if( $this->request['category'] )
		{
			$category	= $this->categories->categories[ $this->request['category'] ];
			
			if( !$category['category_id'] )
			{
				$this->registry->output->showError( $this->lang->words['cannot_find_to_watch'], '10CCS49' );
			}
			
			//-----------------------------------------
			// Already subscribed?
			//-----------------------------------------
			
			$_check	= $this->DB->buildAndFetch( array( 'select' => '*', 'from' => 'ccs_database_notifications', 'where' => "notify_member={$this->memberData['member_id']} AND notify_category=" . $category['category_id'] ) );
			
			//-----------------------------------------
			// Unsubscribe
			//-----------------------------------------
			
			if( $_check['notify_id'] )
			{
				$this->DB->delete( "ccs_database_notifications", "notify_member={$this->memberData['member_id']} AND notify_category=" . $category['category_id'] );

				//-----------------------------------------
				// Redirect info
				//-----------------------------------------
				
				$text	= $this->lang->words['end_watch_c_success'];
				$url	= $this->categories->getCategoryUrl( $this->database['base_link'], $category['category_id'] );
				
				//-----------------------------------------
				// Update member cache
				//-----------------------------------------
				
				$_cache	= $this->memberData['_cache']['watchedContentCats'];
				$_new	= array();
				
				if( is_array($_cache) AND count($_cache) )
				{
					foreach( $_cache as $_idx => $catId )
					{
						if( $catId != $category['category_id'] )
						{
							$_new[ $_idx ]	= $catId;
						}
					}
				}
				
				IPSMember::packMemberCache( $this->memberData['member_id'], array( 'watchedContentCats' => $_new ), $this->memberData['_cache'] );
			}
			else
			{
				//-----------------------------------------
				// New subscription
				//-----------------------------------------
				
				$insert	= array(
								'notify_member'		=> $this->memberData['member_id'],
								'notify_database'	=> $this->database['database_id'],
								'notify_category'	=> $category['category_id'],
								'notify_start'		=> time(),
								);

				$this->DB->insert( "ccs_database_notifications", $insert );

				//-----------------------------------------
				// Redirect info
				//-----------------------------------------
				
				$text	= $this->lang->words['start_watch_c_success'];
				$url	= $this->categories->getCategoryUrl( $this->database['base_link'], $category['category_id'] );
				
				//-----------------------------------------
				// Update member cache
				//-----------------------------------------
				
				$_cache	= $this->memberData['_cache']['watchedContentCats'];
				
				if( is_array($_cache) AND count($_cache) )
				{
					$_exist	= false;
					
					foreach( $_cache as $_idx => $catId )
					{
						if( $catId == $category['category_id'] )
						{
							$_exist	= true;
							break;
						}
					}
					
					if( !$_exist )
					{
						$_cache[]	= $category['category_id'];
					}
				}
				else
				{
					$_cache	= array( $category['category_id'] );
				}
				
				IPSMember::packMemberCache( $this->memberData['member_id'], array( 'watchedContentCats' => $_cache ), $this->memberData['_cache'] );
			}
		}
		
		//-----------------------------------------
		// Or record?
		//-----------------------------------------
		
		else
		{
			//-----------------------------------------
			// Error/permission checking
			//-----------------------------------------
			
			$record	= $this->DB->buildAndFetch( array( 'select' => '*', 'from' => $this->database['database_database'], 'where' => 'primary_id_field=' . intval($this->request['record']) ) );
	
			if( !$record['primary_id_field'] )
			{
				$this->registry->output->showError( $this->lang->words['cannot_find_to_watch'], '10CCS50' );
			}
			
			if( $record['category_id'] )
			{
				$category	= $this->categories->categories[ $record['category_id'] ];
				
				if( !$category['category_id'] )
				{
					$this->registry->output->showError( $this->lang->words['cannot_find_to_watch'], '10CCS51' );
				}
				
				if ( $category['category_has_perms'] AND $this->registry->permissions->check( 'view', $category ) != TRUE )
				{
					$this->registry->output->showError( $this->lang->words['cannot_find_to_watch'], '10CCS52' );
				}
			}
			
			//-----------------------------------------
			// Already subscribed?
			//-----------------------------------------
			
			$_check	= $this->DB->buildAndFetch( array( 'select' => '*', 'from' => 'ccs_database_notifications', 'where' => "notify_member={$this->memberData['member_id']} AND notify_record=" . $record['primary_id_field'] . " AND notify_database=" . $this->database['database_id'] ) );
			
			//-----------------------------------------
			// Unsubscribe
			//-----------------------------------------
			
			if( $_check['notify_id'] )
			{
				$this->DB->delete( "ccs_database_notifications", "notify_member={$this->memberData['member_id']} AND notify_record=" . $record['primary_id_field'] . " AND notify_database=" . $this->database['database_id'] );
				
				//-----------------------------------------
				// Redirect info
				//-----------------------------------------
				
				$text	= $this->lang->words['end_watch_r_success'];
				$url	= $this->getRecordUrl( $record );
				
				//-----------------------------------------
				// Update member cache
				//-----------------------------------------
				
				$_cache	= $this->memberData['_cache']['watchedContentRecords'];
				
				if( is_array($_cache) AND count($_cache) )
				{
					foreach( $_cache as $_idx => $watchId )
					{
						if( $watchId == $this->database['database_id'] . ';' . $record['primary_id_field'] )
						{
							unset($_cache[ $idx ]);
						}
					}
				}
				
				IPSMember::packMemberCache( $this->memberData['member_id'], array( 'watchedContentRecords' => $_cache ), $this->memberData['_cache'] );
			}
			else
			{
				//-----------------------------------------
				// New subscription
				//-----------------------------------------
				
				$insert	= array(
								'notify_member'		=> $this->memberData['member_id'],
								'notify_database'	=> $this->database['database_id'],
								'notify_record'		=> $record['primary_id_field'],
								'notify_start'		=> time(),
								);

				$this->DB->insert( "ccs_database_notifications", $insert );
				
				//-----------------------------------------
				// Redirect info
				//-----------------------------------------
				
				$text	= $this->lang->words['start_watch_r_success'];
				$url	= $this->getRecordUrl( $record );
				
				//-----------------------------------------
				// Update member cache
				//-----------------------------------------
				
				$_cache	= $this->memberData['_cache']['watchedContentRecords'];
				
				if( is_array($_cache) AND count($_cache) )
				{
					$_exist	= false;
					
					foreach( $_cache as $_idx => $watchId )
					{
						if( $watchId == $this->database['database_id'] . ';' . $record['primary_id_field'] )
						{
							$_exist	= true;
							break;
						}
					}
					
					if( !$_exist )
					{
						$_cache[]	= $this->database['database_id'] . ';' . $record['primary_id_field'];
					}
				}
				else
				{
					$_cache	= array( $this->database['database_id'] . ';' . $record['primary_id_field'] );
				}
				
				IPSMember::packMemberCache( $this->memberData['member_id'], array( 'watchedContentRecords' => $_cache ), $this->memberData['_cache'] );
			}
		}

		$this->registry->output->redirectScreen( $text, $url );
	}
	
	/**
	 * Pin or unpin record
	 *
	 * @access	protected
	 * @return	mixed		void (output an error) or HTML to print
	 */
	protected function _actionPin()
	{
		//-----------------------------------------
		// Get the data
		//-----------------------------------------
		
		$record	= $this->DB->buildAndFetch( array( 'select' => '*', 'from' => $this->database['database_database'], 'where' => 'primary_id_field=' . intval($this->request['record']) ) );

		if( !$record['primary_id_field'] )
		{
			$this->registry->output->showError( $this->lang->words['nofind_pin_record'], '10CCS53' );
		}
		
		if( $record['category_id'] )
		{
			$category	= $this->categories->categories[ $record['category_id'] ];
			
			if( !$category['category_id'] )
			{
				$this->registry->output->showError( $this->lang->words['nofind_pin_record'], '10CCS54' );
			}
			
			if ( $category['category_has_perms'] AND $this->registry->permissions->check( 'show', $category ) != TRUE )
			{
				$this->registry->output->showError( $this->lang->words['nofind_pin_record'], '10CCS55' );
			}
		}
		
		//-----------------------------------------
		// Permission
		//-----------------------------------------
		
		if( !$this->database['moderate_pin'] )
		{
			$this->registry->output->showError( $this->lang->words['noperm_pin_record'], '10CCS56' );
		}
		
		//-----------------------------------------
		// Update record
		//-----------------------------------------
		
		if( $record['record_pinned'] )
		{
			//-----------------------------------------
			// Plugin
			//-----------------------------------------
			
			if( $this->plugin )
			{
				if( method_exists( $this->plugin, 'preUnpin' ) )
				{
					$this->plugin->preUnpin();
				}
			}
			
			$this->DB->update( $this->database['database_database'], array( 'record_pinned' => 0 ), 'primary_id_field=' . $record['primary_id_field'] );
			
			$this->registry->output->redirectScreen( $this->lang->words['record_unpinned_success'], $this->getRecordUrl( $record ) );
		}
		else
		{
			//-----------------------------------------
			// Plugin
			//-----------------------------------------
			
			if( $this->plugin )
			{
				if( method_exists( $this->plugin, 'prePin' ) )
				{
					$this->plugin->prePin();
				}
			}
			
			$this->DB->update( $this->database['database_database'], array( 'record_pinned' => 1 ), 'primary_id_field=' . $record['primary_id_field'] );
			
			$this->registry->output->redirectScreen( $this->lang->words['record_pinned_success'], $this->getRecordUrl( $record ) );
		}
	}
	
	/**
	 * Show form to add record
	 *
	 * @access	protected
	 * @return	mixed		void (output an error) or HTML to print
	 */
	protected function _actionAdd()
	{
		//-----------------------------------------
		// Can we add?
		//-----------------------------------------
		
		if( !$this->database['_can_add'] )
		{
			$this->registry->output->showError( $this->lang->words['noperm_add_database'], '10CCS57' );
		}
		
		if( $this->request['category'] )
		{
			$_cat	= $this->categories->categories[ $this->request['category'] ];
			
			if ( $_cat['category_has_perms'] AND $this->registry->permissions->check( 'add', $_cat ) != TRUE )
			{
				$this->registry->output->showError( $this->lang->words['noperm_add_category'], '10CCS58' );
			}
		}
		
		//-----------------------------------------
		// Plugin
		//-----------------------------------------
		
		if( $this->plugin )
		{
			if( method_exists( $this->plugin, 'preAdd' ) )
			{
				$this->plugin->preAdd();
			}
		}
		
		//-----------------------------------------
		// Remove non-user-editable fields
		// Also sort form defaults
		//-----------------------------------------
		
		$_formDefaults	= array( 'post_key' => $this->settings['post_key'] );
		
		foreach( $this->fields as $_field )
		{
			if( !$_field['field_user_editable'] )
			{
				unset($this->fields[$_field['field_id']]);
			}
			else if( $_field['field_default_value'] )
			{
				$_formDefaults['field_' . $_field['field_id'] ]	= $_field['field_default_value'];
			}
		}

		//-----------------------------------------
		// Get category select list
		//-----------------------------------------

		$categories	= $this->categories->getSelectMenu();
		
		//-----------------------------------------
		// Output
		//-----------------------------------------
		
		return $this->registry->output->getTemplate('ccs_global')->recordForm( 'add', $this->database, $this->fields, $this->fieldsClass, $_formDefaults, $categories, $error );
	}
	
	/**
	 * Save the newly added record
	 *
	 * @access	protected
	 * @return	mixed		void (output an error) or HTML to print
	 */
	protected function _actionSaveAdd()
	{
		//-----------------------------------------
		// Can we add?
		//-----------------------------------------
		
		if( !$this->database['_can_add'] )
		{
			$this->registry->output->showError( $this->lang->words['noperm_add_database'], '10CCS59' );
		}
		
		if( $this->request['category_id'] )
		{
			$_cat	= $this->categories->categories[ $this->request['category_id'] ];
			
			if ( $_cat['category_has_perms'] AND $this->registry->permissions->check( 'add', $_cat ) != TRUE )
			{
				$this->registry->output->showError( $this->lang->words['noperm_add_category'], '10CCS60' );
			}
		}
		
		//-----------------------------------------
		// Plugin
		//-----------------------------------------
		
		if( $this->plugin )
		{
			if( method_exists( $this->plugin, 'preSave' ) )
			{
				$this->plugin->preSave();
			}
		}
		
		$this->settings['post_key']	= $this->request['post_key'];
		
		$_save	= array( 'post_key' => $this->request['post_key'] );
		
		//-----------------------------------------
		// Remove non-user-editable fields
		//-----------------------------------------
		
		foreach( $this->fields as $_field )
		{
			if( !$_field['field_user_editable'] )
			{
				unset($this->fields[$_field['field_id']]);
				continue;
			}
			
			$_save['field_' . $_field['field_id'] ]	= $this->fieldsClass->processInput( $_field );
		}

		//-----------------------------------------
		// Any errors?
		//-----------------------------------------
		
		if( $error = $this->fieldsClass->getError() )
		{
			//-----------------------------------------
			// Cat lib
			//-----------------------------------------
			
			$this->request['category']	= $this->request['category_id'] ? $this->request['category_id'] : 0;

			$categories	= $this->categories->getSelectMenu();
	
			return $this->registry->output->getTemplate('ccs_global')->recordForm( 'add', $this->database, $this->fields, $this->fieldsClass, $_save, $categories, $error );
		}
					
		foreach( $this->fields as $field )
		{
			$this->DB->force_data_type[ 'field_' . $field['field_id'] ]	= 'string';
		}
		
		//-----------------------------------------
		// Some other data for add
		//-----------------------------------------
		
		$_save['member_id']				= $this->memberData['member_id'];
		$_save['record_saved']			= time();
		$_save['record_updated']		= time();
		$_save['category_id']			= intval($this->request['category_id']);
		$_save['record_dynamic_furl']	= IPSText::makeSeoTitle( $this->fieldsClass->getFieldValue( $this->fields[ str_replace( 'field_', '', $this->database['database_field_title'] ) ], $_save, $this->fields[ str_replace( 'field_', '', $this->database['database_field_title'] ) ]['field_truncate'] ) );

		if( $this->database['database_record_approve'] AND !$this->database['moderate_approve'] )
		{
			$_save['record_approved']	= 0;
		}
		else
		{
			$_save['record_approved']	= 1;
		}
		
		//-----------------------------------------
		// Got a category?
		//-----------------------------------------
		
		if( ( !$_save['category_id'] OR !$this->categories->categories[ $_save['category_id'] ] ) AND count($this->categories->catcache) )
		{
			$this->request['category']	= $this->request['category_id'] ? $this->request['category_id'] : 0;

			$categories	= $this->categories->getSelectMenu();
	
			return $this->registry->output->getTemplate('ccs_global')->recordForm( 'add', $this->database, $this->fields, $this->fieldsClass, $_save, $categories, $this->lang->words['must_select_cat'] );
		}
		
		//-----------------------------------------
		// Previewing?
		//-----------------------------------------

		if( $this->request['preview'] )
		{
			$this->request['category']	= $this->request['category_id'] ? $this->request['category_id'] : 0;

			$categories	= $this->categories->getSelectMenu();
	
			return $this->registry->output->getTemplate('ccs_global')->recordForm( 'add', $this->database, $this->fields, $this->fieldsClass, $_save, $categories, '', true );
		}
		
		//-----------------------------------------
		// Insert and recount
		//-----------------------------------------
		
		$this->DB->insert( $this->database['database_database'], $_save );
		
		$id	= $this->DB->getInsertId();
		
		$_save['primary_id_field']	= $id;
		
		if( $_save['record_approved'] )
		{
			$this->DB->update( 'ccs_databases', array( 'database_record_count' => ($this->database['database_record_count'] + 1) ), 'database_id=' . $this->database['database_id'] );
		}
		
		//-----------------------------------------
		// If it's not approved, flag
		//-----------------------------------------
		
		if( !$_save['record_approved'] )
		{
			$modqueue	= array(
								'mod_database'		=> $this->database['database_id'],
								'mod_record'		=> $_save['primary_id_field'],
								'mod_comment'		=> 0,
								'mod_poster'		=> $this->memberData['member_id'],
								);
		
			$this->DB->insert( 'ccs_database_modqueue', $modqueue );
		}

		//-----------------------------------------
		// Post process
		//-----------------------------------------
		
		foreach( $this->fields as $field )
		{
			$this->fieldsClass->postProcessInput( $field, $id );
		}

		//-----------------------------------------
		// Plugin
		//-----------------------------------------
		
		if( $this->plugin )
		{
			if( method_exists( $this->plugin, 'postSave' ) )
			{
				$this->plugin->postSave();
			}
		}

		//-----------------------------------------
		// Update category
		//-----------------------------------------
		
		$this->categories->recache( $_save['category_id'] );
		
	    //-----------------------------------------
	    // Send out appropriate notifications
	    //-----------------------------------------
	    
	    if( $_save['record_approved'] )
	    {
	    	//-----------------------------------------
	    	// Post topic if configured to do so
	    	//-----------------------------------------
	    	
	    	require_once( IPSLib::getAppDir( 'ccs' ) . '/sources/databases/topics.php' );
	    	$_topics	= new topicsLibrary( $this->registry, $this->fieldsClass, $this->categories, $this->fields );
	    	$_topics->postTopic( $_save, $this->categories->categories[ $_save['category_id'] ], $this->database );

			//-----------------------------------------
			// Send notifications
			//-----------------------------------------
			
	    	$_save['poster_name']	= $this->memberData['members_display_name'];
	    	
		    $this->sendRecordNotification( $this->database, $this->categories->categories[ $_save['category_id'] ], $_save );
	    }
		
		//-----------------------------------------
		// Redirect
		//-----------------------------------------
		
		if( $_save['record_approved'] )
		{
			$this->registry->output->redirectScreen( $this->lang->words['record_saved_success'], $this->getRecordUrl( $_save ) );
		}
		else
		{
			if( $_save['category_id'] )
			{
				$this->registry->output->redirectScreen( $this->lang->words['record_saved_success1'], $this->categories->getCategoryUrl( $this->database['base_link'], $_save['category_id'] ) );
			}
			else
			{
				$this->registry->output->redirectScreen( $this->lang->words['record_saved_success1'], $this->database['base_link'] );
			}
		}
	}
	
	/**
	 * Show form to edit a record
	 *
	 * @access	protected
	 * @return	mixed		void (output an error) or HTML to print
	 */
	protected function _actionEdit()
	{
		//-----------------------------------------
		// Got our id?
		//-----------------------------------------
		
		if( $this->request['record'] )
		{
			//-----------------------------------------
			// Get the data
			//-----------------------------------------
			
			$_approved	= !$this->database['moderate_approve'] ? "record_approved=1 AND " : '';
			
			$record	= $this->DB->buildAndFetch( array( 'select' => '*', 'from' => $this->database['database_database'], 'where' => $_approved . 'primary_id_field=' . intval($this->request['record']) ) );

			if( !$record['primary_id_field'] )
			{
				$this->registry->output->showError( $this->lang->words['record_edit_not_found'], '10CCS61' );
			}

			$member	= IPSMember::load( $record['member_id'] );
			$_mem	= array();
			
			if( count($member) AND is_array($member) )
			{
				foreach( $member as $k => $v )
				{
					if( strpos( $k, 'field_' ) === 0 )
					{
						$k	= str_replace( 'field_', 'user_field_', $k );
					}
					
					$_mem[ $k ]	= $v;
				}
			}
			
			$member	= $_mem;

			$record	= array_merge( $member, $record );

			if( $record['category_id'] )
			{
				$category	= $this->categories->categories[ $record['category_id'] ];
				
				if( !$category['category_id'] )
				{
					$this->registry->output->showError( $this->lang->words['record_edit_not_found'], '10CCS62' );
				}
				
				if ( $category['category_has_perms'] AND $this->registry->permissions->check( 'show', $category ) != TRUE )
				{
					$this->registry->output->showError( $this->lang->words['record_edit_not_found'], '10CCS63' );
				}
			}
			
			$this->settings['post_key']	= $record['post_key'];
			
			//-----------------------------------------
			// Can we edit this record?
			//-----------------------------------------
			
			if( $this->database['database_user_editable'] )
			{
				if ( $this->registry->permissions->check( 'edit', $this->database ) == TRUE )
				{
					if( $this->database['database_all_editable'] OR $record['member_id'] == $this->memberData['member_id'] OR $this->database['moderate_edit'] )
					{
						$this->database['_can_edit']		= true;
					}
				}
				
				if( $record['category_id'] )
				{
					if ( $category['category_has_perms'] AND $this->registry->permissions->check( 'edit', $category ) != TRUE )
					{
						$this->database['_can_edit']		= false;
					}
				}
				
				if( $this->database['moderate_edit'] )
				{
					$this->database['_can_edit']		= true;
				}
			}
			
			if( $record['record_locked'] AND !$this->database['moderate_edit'] )
			{
				$this->database['_can_edit']		= false;
			}
			
			//-----------------------------------------
			// Plugin
			//-----------------------------------------
			
			if( $this->plugin )
			{
				if( method_exists( $this->plugin, 'preEdit' ) )
				{
					$this->plugin->preEdit();
				}
			}
			
			//-----------------------------------------
			// Remove non-user-editable fields
			//-----------------------------------------
			
			foreach( $this->fields as $_field )
			{
				if( !$_field['field_user_editable'] )
				{
					unset($this->fields[$_field['field_id']]);
				}
			}
			
			//-----------------------------------------
			// Get cat selector
			//-----------------------------------------
			
			$this->request['category']	= $record['category_id'];

			$categories	= $this->categories->getSelectMenu();
			
			//-----------------------------------------
			// Output or error
			//-----------------------------------------
			
			if( $this->database['_can_edit'] )
			{
				return $this->registry->output->getTemplate('ccs_global')->recordForm( 'edit', $this->database, $this->fields, $this->fieldsClass, $record, $categories );
			}
			
			$this->registry->output->showError( $this->lang->words['record_edit_no_perm'], '10CCS64' );
		}
		else
		{
			$this->registry->output->showError( $this->lang->words['record_edit_not_found'], '10CCS65' );
		}
	}
	
	/**
	 * Save updated record
	 *
	 * @access	protected
	 * @return	mixed		void (output an error) or HTML to print
	 */
	protected function _actionSaveEdit()
	{
		//-----------------------------------------
		// Got our id?
		//-----------------------------------------
		
		if( $this->request['record'] )
		{
			//-----------------------------------------
			// Get record data
			//-----------------------------------------
			
			$_approved	= !$this->database['moderate_approve'] ? "record_approved=1 AND " : '';
			
			$record	= $this->DB->buildAndFetch( array( 'select' => '*', 'from' => $this->database['database_database'], 'where' => $_approved . 'primary_id_field=' . intval($this->request['record']) ) );

			if( !$record['primary_id_field'] )
			{
				$this->registry->output->showError( $this->lang->words['record_edit_not_found'], '10CCS66' );
			}

			// Member data is not used anywhere here.  Leaving this in place, but commented out, for now.
			// $member	= IPSMember::load( $record['member_id'] );
			
			// Merging the data causes problems with revisions
			// $record	= array_merge( $member, $record );
			
			if( $record['category_id'] )
			{
				$category	= $this->categories->categories[ $record['category_id'] ];
				
				if( !$category['category_id'] )
				{
					$this->registry->output->showError( $this->lang->words['record_edit_not_found'], '10CCS67' );
				}
				
				if ( $category['category_has_perms'] AND $this->registry->permissions->check( 'show', $category ) != TRUE )
				{
					$this->registry->output->showError( $this->lang->words['record_edit_not_found'], '10CCS68' );
				}
			}
			
			$this->settings['post_key']	= $record['post_key'];
			
			//-----------------------------------------
			// Can we edit this record?
			//-----------------------------------------
			
			if( $this->database['database_user_editable'] )
			{
				if ( $this->registry->permissions->check( 'edit', $this->database ) == TRUE )
				{
					if( $this->database['database_all_editable'] OR $record['member_id'] == $this->memberData['member_id'] OR $this->database['moderate_edit'] )
					{
						$this->database['_can_edit']		= true;
					}
				}
				
				if( $record['category_id'] )
				{
					if ( $category['category_has_perms'] AND $this->registry->permissions->check( 'edit', $category ) != TRUE )
					{
						$this->database['_can_edit']		= false;
					}
				}
				
				if( $this->database['moderate_edit'] )
				{
					$this->database['_can_edit']		= true;
				}
			}
			
			if( $record['record_locked'] AND !$this->database['moderate_edit'] )
			{
				$this->database['_can_edit']		= false;
			}
			
			//-----------------------------------------
			// Plugin
			//-----------------------------------------
			
			if( $this->plugin )
			{
				if( method_exists( $this->plugin, 'preSaveEdit' ) )
				{
					$this->plugin->preSaveEdit();
				}
			}
			
			if( $this->database['_can_edit'] )
			{
				$_save	= array();
				
				//-----------------------------------------
				// Loop over fields and check input
				//-----------------------------------------

				foreach( $this->fields as $field )
				{
					if( !$field['field_user_editable'] )
					{
						continue;
					}
			
					$_save['field_' . $field['field_id'] ]	= $this->fieldsClass->processInput( $field );

					if( $error = $this->fieldsClass->getError() )
					{
						//-----------------------------------------
						// Cat lib
						//-----------------------------------------
						
						$this->request['category']	= $this->request['category_id'] ? $this->request['category_id'] : $record['category_id'];

						$categories	= $this->categories->getSelectMenu();
				
						return $this->registry->output->getTemplate('ccs_global')->recordForm( 'edit', $this->database, $this->fields, $this->fieldsClass, array_merge( $record, $_save ), $categories, $error );
					}
				}
				
				foreach( $this->fields as $field )
				{
					$this->DB->force_data_type[ 'field_' . $field['field_id'] ]	= 'string';
				}
				
				//-----------------------------------------
				// Some other needed data
				//-----------------------------------------
				
				$_save['record_updated']		= time();
				$_save['category_id']			= intval($this->request['category_id']);
				$_save['record_dynamic_furl']	= IPSText::makeSeoTitle( $this->fieldsClass->getFieldValue( $this->fields[ str_replace( 'field_', '', $this->database['database_field_title'] ) ], $_save, $this->fields[ str_replace( 'field_', '', $this->database['database_field_title'] ) ]['field_truncate'] ) );
				
				//-----------------------------------------
				// Got category?
				//-----------------------------------------
				
				if( ( !$_save['category_id'] OR !$this->categories->categories[ $_save['category_id'] ] ) AND count($this->categories->catcache) )
				{
					$this->request['category']	= $this->request['category_id'] ? $this->request['category_id'] : $record['category_id'];

					$categories	= $this->categories->getSelectMenu();
			
					return $this->registry->output->getTemplate('ccs_global')->recordForm( 'edit', $this->database, $this->fields, $this->fieldsClass, $_save, $categories, $this->lang->words['must_select_cat'] );
				}
				
		
				//-----------------------------------------
				// Previewing?
				//-----------------------------------------
		
				if( $this->request['preview'] )
				{
					$this->request['category']	= $this->request['category_id'] ? $this->request['category_id'] : $record['category_id'];
		
					$categories	= $this->categories->getSelectMenu();
			
					return $this->registry->output->getTemplate('ccs_global')->recordForm( 'edit', $this->database, $this->fields, $this->fieldsClass, array_merge( $record, $_save ), $categories, '', true );
				}
				
				//-----------------------------------------
				// Update db
				//-----------------------------------------
				
				$this->DB->update( $this->database['database_database'], $_save, 'primary_id_field=' . $record['primary_id_field'] );

				//-----------------------------------------
				// Post process input
				//-----------------------------------------

				foreach( $this->fields as $field )
				{
					if( !$field['field_user_editable'] )
					{
						continue;
					}
					
					$this->fieldsClass->postProcessInput( $field, $record['primary_id_field'] );
				}
				
				//-----------------------------------------
				// Plugin
				//-----------------------------------------
				
				if( $this->plugin )
				{
					if( method_exists( $this->plugin, 'postSaveEdit' ) )
					{
						$this->plugin->postSaveEdit();
					}
				}
		
				//-----------------------------------------
				// Revisions?
				//-----------------------------------------
				
				if( $this->database['database_revisions'] )
				{
					require_once( IPSLib::getAppDir('ccs') . '/sources/databases/revisions.php' );
					$revisions	= new ccs_database_revisions( $this->registry );
					$revisions->storeRevision( $this->database, $record );
				}
				
		    	//-----------------------------------------
		    	// Post topic if configured to do so
		    	//-----------------------------------------
		    	
		    	require_once( IPSLib::getAppDir( 'ccs' ) . '/sources/databases/topics.php' );
		    	$_topics	= new topicsLibrary( $this->registry, $this->fieldsClass, $this->categories, $this->fields );
		    	$_topics->postTopic( array_merge( $record, $_save ), $this->categories->categories[ $_save['category_id'] ], $this->database, 'edit' );
				
				//-----------------------------------------
				// Update categor(y|ies)
				//-----------------------------------------
				
				$this->categories->recache( $_save['category_id'] );
				
				if( $record['category_id'] != $_save['category_id'] )
				{
					$this->categories->recache( $record['category_id'] );
				}
				
				//-----------------------------------------
				// Redirect
				//-----------------------------------------
				
				$this->registry->output->redirectScreen( $this->lang->words['record_edited_success'], $this->getRecordUrl( $record ) );
			}
			
			$this->registry->output->showError( $this->lang->words['record_edit_no_perm'], '10CCS69' );
		}
		else
		{
			$this->registry->output->showError( $this->lang->words['record_edit_not_found'], '10CCS70' );
		}
	}
	
	/**
	 * Approve or unapprove comment
	 *
	 * @access	protected
	 * @return	mixed		void (output an error) or HTML to print
	 */
	protected function _actionToggleComment()
	{
		//-----------------------------------------
		// Can we manage comments?
		//-----------------------------------------
		
		if( !$this->database['moderate_approvec'] )
		{
			$this->registry->output->showError( $this->lang->words['noperm_manage_comments'], '10CCS71' );
		}
		
		//-----------------------------------------
		// Get the data
		//-----------------------------------------
		
		if( $this->request['pid'] )
		{
			$_approved	= !$this->database['moderate_approve'] ? "p.queued=0 AND " : '';
			
			$comment	= $this->DB->buildAndFetch( array(
														'select'	=> 'p.pid, p.pid as comment_id, p.post_date as comment_date, p.queued',
														'from'		=> array( 'posts' => 'p' ),
														'where'		=> $_approved . 'p.pid=' . intval($this->request['pid']),
														'add_join'	=> array(
																			array(
																				'select'	=> 'r.*',
																				'from'		=> array( $this->database['database_database'] => 'r' ),
																				'where'		=> 'r.record_topicid=p.topic_id',
																				'type'		=> 'left',
																				),
																			array(
																				'select'	=> 'm.members_display_name as poster_name',
																				'from'		=> array( 'members' => 'm' ),
																				'where'		=> 'm.member_id=p.author_id',
																				'type'		=> 'left',
																				)
																			)
												)		);

			if( !$comment['pid'] )
			{
				$this->registry->output->showError( $this->lang->words['nofind_comment_tog'], '10CCS72' );
			}
			
			$comment['comment_approved']	= $comment['queued'] ? 0 : 1;
		}
		else
		{
			$_approved	= !$this->database['moderate_approve'] ? "r.record_approved=1 AND " : '';
			
			$comment	= $this->DB->buildAndFetch( array(
														'select'	=> 'c.*',
														'from'		=> array( 'ccs_database_comments' => 'c' ),
														'where'		=> $_approved . 'c.comment_id=' . intval($this->request['comment']),
														'add_join'	=> array(
																			array(
																				'select'	=> 'r.*',
																				'from'		=> array( $this->database['database_database'] => 'r' ),
																				'where'		=> 'r.primary_id_field=c.comment_record_id',
																				'type'		=> 'left',
																				),
																			array(
																				'select'	=> 'm.members_display_name as poster_name, m.members_seo_name, m.member_id',
																				'from'		=> array( 'members' => 'm' ),
																				'where'		=> 'm.member_id=c.comment_user',
																				'type'		=> 'left',
																				)
																			)
												)		);

			if( !$comment['comment_id'] )
			{
				$this->registry->output->showError( $this->lang->words['nofind_comment_tog'], '10CCS73' );
			}
		}
		
		if( !$comment['primary_id_field'] )
		{
			$this->registry->output->showError( $this->lang->words['nofind_comment_tog'], '10CCS74' );
		}
		
		if( $comment['category_id'] )
		{
			$category	= $this->categories->categories[ $comment['category_id'] ];
			
			if( !$category['category_id'] )
			{
				$this->registry->output->showError( $this->lang->words['nofind_comment_tog'], '10CCS75' );
			}
			
			if ( $category['category_has_perms'] AND $this->registry->permissions->check( 'show', $category ) != TRUE )
			{
				$this->registry->output->showError( $this->lang->words['nofind_comment_tog'], '10CCS76' );
			}
		}
		
		//-----------------------------------------
		// Update record
		//-----------------------------------------
		
		if( !$comment['comment_approved'] )
		{
			//-----------------------------------------
			// Plugin
			//-----------------------------------------
			
			if( $this->plugin )
			{
				if( method_exists( $this->plugin, 'preApproveComment' ) )
				{
					$this->plugin->preApproveComment();
				}
			}

			if( $this->request['pid'] )
			{
				require_once( IPSLib::getAppDir( 'ccs' ) . '/sources/databases/topics.php' );
				$_topics	= new topicsLibrary( $this->registry, $this->fieldsClass, $this->categories, $this->fields );
				$_topics->toggleComment( $comment, $this->categories->categories[ $record['category_id'] ], $this->database, $this->request['pid'], true );
			}
			else
			{
				$this->DB->update( 'ccs_database_comments', array( 'comment_approved' => 1 ), 'comment_id=' . $comment['comment_id'] );
			}
			
			//-----------------------------------------
			// Update comment count
			//-----------------------------------------
			
			$update	= "record_comments=record_comments+1";
			
			//-----------------------------------------
			// Bump record?
			//-----------------------------------------
			
			if( $this->database['database_comment_bump'] )
			{
				if( $comment['comment_date'] > $comment['record_updated'] )
				{
					$update	.= ", record_updated='{$comment['comment_date']}'";
				}
			}
			
			$this->DB->update( 'ccs_custom_database_' . $this->database['database_id'], $update, 'primary_id_field=' . $comment['primary_id_field'], false, true );
			
			//-----------------------------------------
			// If this is first time approval, send notifications
			//-----------------------------------------
			
			$_modQueue	= $this->DB->buildAndFetch( array( 'select' => '*', 'from' => 'ccs_database_modqueue', 'where' => "mod_database={$this->database['database_id']} AND mod_record={$comment['primary_id_field']} AND mod_comment={$comment['comment_id']}" ) );
			
			if( $_modQueue['mod_id'] )
			{
			    $this->sendCommentNotification( $this->database, $comment, $comment );
			    
			    $this->DB->delete( 'ccs_database_modqueue', "mod_database={$this->database['database_id']} AND mod_record={$comment['primary_id_field']} AND mod_comment={$comment['comment_id']}" );
			}
			
			$this->registry->output->redirectScreen( $this->lang->words['comment_approved_success'], $this->getRecordUrl( $comment ) );
		}
		else
		{
			//-----------------------------------------
			// Permission
			//-----------------------------------------
			
			if( !$this->database['moderate_lock'] )
			{
				$this->registry->output->showError( $this->lang->words['noperm_lock_record'], '10CCS77' );
			}
			
			//-----------------------------------------
			// Plugin
			//-----------------------------------------
			
			if( $this->plugin )
			{
				if( method_exists( $this->plugin, 'preUnapproveComment' ) )
				{
					$this->plugin->preUnapproveComment();
				}
			}

			if( $this->request['pid'] )
			{
				require_once( IPSLib::getAppDir( 'ccs' ) . '/sources/databases/topics.php' );
				$_topics	= new topicsLibrary( $this->registry, $this->fieldsClass, $this->categories, $this->fields );
				$_topics->toggleComment( $comment, $this->categories->categories[ $record['category_id'] ], $this->database, $this->request['pid'], false );
			}
			else
			{
				$this->DB->update( 'ccs_database_comments', array( 'comment_approved' => 0 ), 'comment_id=' . $comment['comment_id'] );
			}
			
			$this->DB->update( 'ccs_custom_database_' . $this->database['database_id'], "record_comments=record_comments-1", 'primary_id_field=' . $comment['primary_id_field'], false, true );

			$this->registry->output->redirectScreen( $this->lang->words['comment_unapp_success'], $this->getRecordUrl( $comment ) );
		}
	}
	
	/**
	 * Save comment to a record
	 *
	 * @access	protected
	 * @return	mixed		void (output an error) or HTML to print
	 */
	protected function _actionComment()
	{
		//-----------------------------------------
		// Can we comment?
		//-----------------------------------------
		
		if( !$this->database['_can_comment'] )
		{
			$this->registry->output->showError( $this->lang->words['noperm_comment_database'], '10CCS78' );
		}
		
		//-----------------------------------------
		// Plugin
		//-----------------------------------------
		
		if( $this->plugin )
		{
			if( method_exists( $this->plugin, 'preComment' ) )
			{
				$this->plugin->preComment();
			}
		}
		
		//-----------------------------------------
		// Do we have a comment
		//-----------------------------------------
		
		if( IPSText::mbstrlen( trim( $_POST['Post'] ) ) < 1)
		{
			$this->registry->output->showError( 'no_comment_submitted', '10CCS79' );
		}
		
		//-----------------------------------------
		// Got a member id?
		//-----------------------------------------
		
		if( !$this->memberData['member_id'] )
		{
			$this->registry->output->showError( 'only_members_comment', '10CCS80' );
		}
		
		//-----------------------------------------
		// Got the record
		//-----------------------------------------
		
		if( !$this->request['record_id'] )
		{
			$this->registry->output->showError( 'couldnot_comment_record', '10CCS81' );
		}
		
		if( $this->_record['primary_id_field'] )
		{
			$record	= $this->_record;
		}
		else
		{
			$_approved	= !$this->database['moderate_approve'] ? "record_approved=1 AND " : '';
			
			$record	= $this->DB->buildAndFetch( array( 'select' => '*', 'from' => $this->database['database_database'], 'where' => $_approved . 'primary_id_field=' . intval($this->request['record_id']) ) );
		}
		
		if( $record['category_id'] )
		{
			$category	= $this->categories->categories[ $record['category_id'] ];
			
			if( !$category['category_id'] )
			{
				$this->registry->output->showError( $this->lang->words['couldnot_comment_record'], '10CCS82' );
			}
			
			if ( $category['category_has_perms'] AND $this->registry->permissions->check( 'show', $category ) != TRUE )
			{
				$this->registry->output->showError( $this->lang->words['couldnot_comment_record'], '10CCS83' );
			}
			
			if ( $category['category_has_perms'] AND $this->registry->permissions->check( 'comment', $category ) != TRUE )
			{
				$this->registry->output->showError( $this->lang->words['couldnot_comment_record'], '10CCS84' );
			}
		}
		
		//-----------------------------------------
		// Check form hash
		//-----------------------------------------
		
		if( $this->request['auth_key'] != $this->member->form_hash )
		{
			$this->registry->output->showError( 'comment_bad_formhash', '10CCS85' );
		}
		
		//-----------------------------------------
		// Process comment
		//-----------------------------------------
		
		$_comment	= IPSText::getTextClass( 'editor' )->processRawPost( 'Post' );

		IPSText::getTextClass( 'bbcode' )->parse_html		= 0;
		IPSText::getTextClass( 'bbcode' )->parse_smilies	= 1;
		IPSText::getTextClass( 'bbcode' )->parse_bbcode		= 1;
		IPSText::getTextClass( 'bbcode' )->parsing_section	= 'ccs_comment';

		//-----------------------------------------
		// Auto approve?
		//-----------------------------------------
		
		if( !$this->database['database_comment_approve'] )
		{
			$approved	= 1;
		}
		else
		{
			if( $this->database['moderate_approvec'] )
			{
				$approved	= 1;
			}
			else
			{
				$approved	= 0;
			}
		}
		
		//-----------------------------------------
		// Build insert array
		//-----------------------------------------
		
		$comment = array(
						'comment_user'			=> $this->memberData['member_id'],
						'comment_database_id'   => $this->database['database_id'],
						'comment_record_id'		=> intval($this->request['record_id']),
						'comment_date'  		=> time(),
						'comment_ip_address'	=> $this->member->ip_address,
						'comment_post'			=> IPSText::getTextClass( 'bbcode' )->preDbParse( $_comment ),
						'comment_approved'		=> $approved,
					 );

		//-----------------------------------------
		// Errors?
		//-----------------------------------------
		
	    if( IPSText::getTextClass('bbcode')->error )
	    {
	    	$this->registry->class_localization->loadLanguageFile( array( 'public_post' ), 'forums' );
	    	
	    	$this->registry->output->showError( IPSText::getTextClass('bbcode')->error, '10CCS86' );
	    }
	    
	    //-----------------------------------------
	    // Comments as topic replies?
	    //-----------------------------------------
	    
	    $forumIntegration	= $this->categories->categories[ $record['category_id'] ]['category_forum_override'] ? $this->categories->categories[ $record['category_id'] ]['category_forum_record'] : $this->database['database_forum_record'];
	    $commentsToo		= $this->categories->categories[ $record['category_id'] ]['category_forum_override'] ? $this->categories->categories[ $record['category_id'] ]['category_forum_comments'] : $this->database['database_forum_comments'];
	    
	    if( $forumIntegration AND $commentsToo )
	    {
			//-----------------------------------------
			// Post topic if configured to do so
			//-----------------------------------------

			require_once( IPSLib::getAppDir( 'ccs' ) . '/sources/databases/topics.php' );
			$_topics	= new topicsLibrary( $this->registry, $this->fieldsClass, $this->categories, $this->fields );
			$comment	= $_topics->postComment( $record, $this->categories->categories[ $record['category_id'] ], $this->database, $comment );
	    }
	    else
	    {
			//-----------------------------------------
			// Insert and redirect
			//-----------------------------------------
			
			$this->DB->insert( 'ccs_database_comments', $comment );
			
			$comment['comment_id']	= $this->DB->getInsertId();
	    }

		//-----------------------------------------
		// If it's not approved, flag
		//-----------------------------------------

		if( !$approved )
		{
			$modqueue	= array(
								'mod_database'		=> $this->database['database_id'],
								'mod_record'		=> intval($this->request['record_id']),
								'mod_comment'		=> $comment['comment_id'] ? $comment['comment_id'] : $comment['pid'],
								'mod_poster'		=> $this->memberData['member_id'],
								);
		
			$this->DB->insert( 'ccs_database_modqueue', $modqueue );
		}
	    
	    //-----------------------------------------
	    // Send out appropriate notifications
	    //-----------------------------------------
	    
	    if( $comment['comment_approved'] )
	    {
		    $comment['poster_name']	= $this->memberData['members_display_name'];
		    
		    $this->sendCommentNotification( $this->database, $record, $comment );

			//-----------------------------------------
			// Update comment count
			//-----------------------------------------
			
			$update	= "record_comments=record_comments+1";

			//-----------------------------------------
			// Bump record?
			//-----------------------------------------
			
			if( $this->database['database_comment_bump'] )
			{
				if( $comment['comment_date'] > $record['record_updated'] )
				{
					$update	.= ", record_updated='{$comment['comment_date']}'";
				}
			}
			
	    	$this->DB->update( 'ccs_custom_database_' . $this->database['database_id'], $update, 'primary_id_field=' . intval($this->request['record_id']), false, true );
    	}
	    
	    $text	= $approved ? $this->lang->words['comment_saved_success'] : $this->lang->words['comment_saved_approval'];
	    
		$this->registry->output->redirectScreen( $text, $this->getRecordUrl( $record ) );
	}
	
	/**
	 * Show a record
	 *
	 * @access	protected
	 * @return	string		HTML output
	 */
	protected function _getRecordDisplay()
	{
		//-----------------------------------------
		// Get record
		//-----------------------------------------
		
		$record	= $this->_getRecord();

		if( !$record['primary_id_field'] )
		{
			$this->registry->output->showError( $this->lang->words['couldnot_find_record'], '10CCS87' );
		}
		
		if( $record['category_id'] )
		{
			$category	= $this->categories->categories[ $record['category_id'] ];
			
			$category['category_link']	= $this->categories->getCategoryUrl( $this->database['base_link'], $category['category_id'] );
			
			if( !$category['category_id'] )
			{
				$this->registry->output->showError( $this->lang->words['couldnot_find_record'], '10CCS88' );
			}

			if ( $category['category_has_perms'] AND $this->registry->permissions->check( 'show', $category ) != TRUE )
			{
				$this->registry->output->showError( $this->lang->words['no_view_perm_rec'], '10CCS89' );
			}
			
			if ( $category['category_has_perms'] AND $this->registry->permissions->check( 'rate', $category ) != TRUE )
			{
				$this->database['_can_rate']	= false;
			}
			
			if ( $category['category_has_perms'] AND $this->registry->permissions->check( 'comment', $category ) != TRUE )
			{
				$this->database['_can_comment']	= false;
			}
		}
		
		//-----------------------------------------
		// Format fields
		//-----------------------------------------
		
		foreach( $record as $k => $v )
		{
			if( preg_match( "/^field_(\d+)$/", $k, $matches ) )
			{
				$record[ $k . '_value' ]	= $this->fieldsClass->getFieldValue( $this->fields[ $matches[1] ], $record );
			}
		}
		
		$record	= $this->parseAttachments( $this->database, $this->fields, $record );
		
		$record['record_link']	= $this->getRecordUrl( $record, true );
		
		$this->checkPermalink( $record['record_link'] );
		
		//-----------------------------------------
		// Get member data
		//-----------------------------------------
		
		$member	= IPSMember::load( $record['member_id'] );

		$_mem	= array();
		
		if( count($member) AND is_array($member) )
		{
			foreach( $member as $k => $v )
			{
				if( strpos( $k, 'field_' ) === 0 )
				{
					$k	= str_replace( 'field_', 'user_field_', $k );
				}
				
				$_mem[ $k ]	= $v;
			}
		}
		
		$member	= $_mem;
		
		$record	= array_merge( $member ? $member : array( 'members_display_name' => $this->lang->words['global_guestname'] ), $record );
		
		//-----------------------------------------
		// User editable
		//-----------------------------------------
		
		if( $this->database['database_user_editable'] )
		{
			if ( $this->registry->permissions->check( 'edit', $this->database ) == TRUE )
			{
				if( $this->database['database_all_editable'] OR $record['member_id'] == $this->memberData['member_id'] OR $this->database['moderate_edit'] )
				{
					$this->database['_can_edit']		= true;
				}
			}
			
			if( $record['category_id'] )
			{
				if ( $category['category_has_perms'] AND $this->registry->permissions->check( 'edit', $category ) != TRUE )
				{
					$this->database['_can_edit']	= false;
				}
			}
			
			if( $this->database['moderate_edit'] )
			{
				$this->database['_can_edit']		= true;
			}
		}
		
		if( $record['record_locked'] AND !$this->database['moderate_edit'] )
		{
			$this->database['_can_edit']		= false;
		}
		
		//-----------------------------------------
		// Breadcrumbs
		//-----------------------------------------

		$crumbies	= $this->categories->getBreadcrumbs( $record['category_id'], $this->database['base_link'] );

		if( !$this->settings['use_friendly_urls'] AND !$this->settings['ccs_root_url'] )
		{
			array_unshift( $crumbies, array( 0 => $this->database['database_name'], 1 => substr( $this->database['base_link'], 0, -5 ) ) );
		}
		else
		{
			array_unshift( $crumbies, array( 0 => $this->database['database_name'], 1 => substr( $this->database['base_link'], 0, -1 ) ) );
		}

		array_push( $crumbies, array( 0 => $this->lang->words['navigation_prefix'] . $record[ $this->database['database_field_title'] . '_value' ], 1 => '' ) );
		
		$this->pages->addNavigation( $this->registry->output->getTemplate('ccs_global')->databaseNavigation( $crumbies ) );
		
		define( 'CCS_NAV_DONE', true );
		
		$this->registry->output->setTitle( $record[ $this->database['database_field_title'] . '_value' ] );
		
		//-----------------------------------------
		// Mark read
		//-----------------------------------------

		$this->registry->classItemMarking->markRead( array( 'catID' => $record['category_id'], 'itemID' => $record['primary_id_field'] ), 'ccs' );
		
		//-----------------------------------------
		// Meta tags
		//-----------------------------------------
		
		if( $record['record_meta_keywords'] )
		{
			$this->pages->setMetaKeywords( $record['record_meta_keywords'] );
		}
		else
		{
			$text	= $record[ $this->database['database_field_title'] . '_value' ];
			$text	.= "\n " . $record[ $this->database['database_field_content'] . '_value' ];
			
			//-----------------------------------------
			// Mostly copied from output class
			//-----------------------------------------
			
			$text = str_replace( array( '.', ',', '!', ':', ';', "'", "'", '@', '%', '*', '(', ')' ), '', preg_replace( "/&([^;]+?);/", "", strip_tags($text) ) );
			$_vals   = preg_split( "/\s+?/", $text, -1, PREG_SPLIT_NO_EMPTY );
			$_sw     = explode( ',', $this->lang->words['_stopwords_'] );
			$_fvals  = array();
			$_limit  = 30;
			$_c      = 0;
			
			if ( is_array( $_vals ) )
			{
				foreach( $_vals as $_v )
				{
					if ( strlen( $_v ) >= 3 AND ! in_array( $_v, array_values( $_fvals ) ) AND ! in_array( $_v, $_sw ) )
					{
						$_fvals[] = $_v;
					}
					
					if ( $_c >= $_limit )
					{
						break;
					}
					
					$_c++;
				}
			}

			$this->pages->setMetaKeywords( implode( ',', $_fvals ) );
		}
		
		if( $record['record_meta_description'] )
		{
			$this->pages->setMetaDescription( $record['record_meta_description'] );
		}
		else
		{
			$text	= $record[ $this->database['database_field_title'] . '_value' ];
			$text	.= "\n " . $record[ $this->database['database_field_content'] . '_value' ];
			
			$this->pages->setMetaDescription( IPSText::truncate( strip_tags($text), 247 ) );
		}
		
		$this->pages->setCanonical( $this->getRecordUrl( $record ) );

		//-----------------------------------------
		// Comments
		//-----------------------------------------
		
		$commentHtml	= '';

	    $forumIntegration	= $this->categories->categories[ $record['category_id'] ]['category_forum_override'] ? $this->categories->categories[ $record['category_id'] ]['category_forum_record'] : $this->database['database_forum_record'];
	    $commentsToo		= $this->categories->categories[ $record['category_id'] ]['category_forum_override'] ? $this->categories->categories[ $record['category_id'] ]['category_forum_comments'] : $this->database['database_forum_comments'];
	    
	    if( $this->database['database_comments'] AND $forumIntegration AND $commentsToo )
	    {
			//-----------------------------------------
			// Post topic if configured to do so
			//-----------------------------------------

			require_once( IPSLib::getAppDir( 'ccs' ) . '/sources/databases/topics.php' );
			$_topics	= new topicsLibrary( $this->registry, $this->fieldsClass, $this->categories, $this->fields );
			$commentHtml	= $_topics->getComments( $record, $this->categories->categories[ $record['category_id'] ], $this->database );
	    }
		else if( $this->database['database_comments'] )
		{
			$comments	= array();
			$perPage	= 30;
			$start		= intval($this->request['st']) > 0 ? intval($this->request['st']) : 0;
			$where		= $this->database['moderate_approvec'] ? '' : "comment_approved=1 AND ";
			$count		= $this->DB->buildAndFetch( array( 'select' => 'count(*) as total', 'from' => 'ccs_database_comments', 'where' => $where . "comment_database_id={$this->database['database_id']} AND comment_record_id={$record['primary_id_field']}" ) );
			
			$pages		= $this->registry->output->generatePagination( array( 
																	'totalItems'		=> $count['total'],
																	'itemsPerPage'		=> $perPage,
																	'currentStartValue'	=> $start,
																	'baseUrl'			=> $this->database['base_link'],
																	'base'				=> 'none',
											 				)	);

			//-----------------------------------------
			// Joins
			//-----------------------------------------
			
			$_post_joins = array(
								array(
										'type'		=> 'left',
										'select'	=> 'm.*',
										'where'		=> 'm.member_id=c.comment_user',
										'from'		=> array( 'members' => 'm' )
									),
								array(
										'type'		=> 'left',
										'select'	=> 'pp.*',
										'where'		=> 'pp.pp_member_id=m.member_id',
										'from'		=> array( 'profile_portal' => 'pp' )
									),
								array(
										'select'	=> 'pd.*',
										'from'		=> array( 'pfields_content' => 'pd' ),
										'where'		=> 'pd.member_id=m.member_id',
										'type'		=> 'left',
									),
								);
			
			//-----------------------------------------
			// Reputation system joins
			//-----------------------------------------
			
			if( $this->settings['reputation_enabled'] )
			{
				require_once( IPS_ROOT_PATH . 'sources/classes/class_reputation_cache.php' );
				$this->registry->setClass( 'repCache', new classReputationCache() );
			
				/* Add the join to figure out if the user has already rated the post */
				$_post_joins[] = $this->registry->repCache->getUserHasRatedJoin( 'comment_id', 'c.comment_id', 'ccs' );
				
				/* Add the join to figure out the total ratings for each post */
				if( $this->settings['reputation_show_content'] )
				{
					$_post_joins[] = $this->registry->repCache->getTotalRatingJoin( 'comment_id', 'c.comment_id', 'ccs' );
				}
			}

			if( $count['total'] )
			{
				$this->DB->build( array(
										'select'	=> 'c.*',
										'from'		=> array( 'ccs_database_comments' => 'c' ),
										'where'		=> ( $where ? "c." . $where : '' ) . "c.comment_database_id={$this->database['database_id']} AND c.comment_record_id={$record['primary_id_field']}",
										'order'		=> 'c.comment_date ASC',
										'limit'		=> array( $start, $perPage ),
										'add_join'	=> $_post_joins
								)		);
				$outer	= $this->DB->execute();
	
				IPSText::getTextClass( 'bbcode' )->parse_html		= 0;
				IPSText::getTextClass( 'bbcode' )->parse_smilies	= 1;
				IPSText::getTextClass( 'bbcode' )->parse_bbcode		= 1;
				IPSText::getTextClass( 'bbcode' )->parsing_section	= 'ccs_comment';
				
				while( $comment = $this->DB->fetch($outer) )
				{
					//-----------------------------------------
					// Basics
					//-----------------------------------------
	
					$comment	= IPSMember::buildDisplayData( $comment );
					
					IPSText::getTextClass( 'bbcode' )->parsing_mgroup			= $comment['member_group_id'];
					IPSText::getTextClass( 'bbcode' )->parsing_mgroup_others	= $comment['mgroup_others'];
					$comment['comment_post']	= IPSText::getTextClass( 'bbcode' )->preDisplayParse( $comment['comment_post'] );
					
					//-----------------------------------------
					// Reputation
					//-----------------------------------------
					
					if( $this->settings['reputation_enabled'] )
					{
						$comment['pp_reputation_points']	= $comment['pp_reputation_points'] ? $comment['pp_reputation_points'] : 0;
						$comment['has_given_rep']			= $comment['has_given_rep'] ? $comment['has_given_rep'] : 0;
						$comment['rep_points']				= $comment['rep_points'] ? $comment['rep_points'] : 0;
					}
					
					$comment['_repignored']	= 0;
	
					$this->memberData['_cache']['rep_filter'] = isset( $this->memberData['_cache']['rep_filter'] ) ? $this->memberData['_cache']['rep_filter'] : '*';
	
					if( $this->settings['reputation_enabled'] )
					{
						if( ! ( $this->settings['reputation_protected_groups'] && 
							    in_array( $comment['member_group_id'], explode( ',', $this->settings['reputation_protected_groups'] ) ) 
							   ) &&
						 	$this->memberData['_members_cache']['rep_filter'] !== '*' 
						)
						{
							if( $this->settings['reputation_show_content'] && $comment['rep_points'] < $this->memberData['_cache']['rep_filter'] )
							{
								$comment['_repignored'] = 1;
							}
						}
					}
					
					$_link	= $this->registry->getClass('output')->formatUrl( $this->registry->getClass('output')->buildUrl( "showuser={$comment['member_id']}", "public" ), $comment['members_seo_name'], "showuser" );
					$_temp	= $this->registry->getClass('output')->getTemplate('global')->user_popup( $comment['member_id'], $comment['members_seo_name'] );
					
					$comment['author_link']	= "<a href='{$_link}'>{$comment['members_display_name']}</a> {$_temp}";
				
					//-----------------------------------------
					// Store
					//-----------------------------------------
					
					$comments[]	= $comment;
				}
			}
			
			$this->lang->loadLanguageFile( array( 'public_editors' ), 'core' );
			
			$commentHtml	= $this->registry->output->getTemplate('ccs_global')->comments( $this->database, $record, $comments, $pages );
		}
		
		//-----------------------------------------
		// Get contributer/revision data
		//-----------------------------------------
		
		$record['contributers']		= array();
		
		if( $this->database['database_revisions'] )
		{
			$contributors	= array();
			$contributions	= array();
			
			$this->DB->build( array( 'select' => 'revision_date, revision_member_id', 'from' => 'ccs_database_revisions', 'where' => 'revision_database_id=' . $this->database['database_id'] . ' AND revision_record_id=' . $record['primary_id_field'] . ' AND revision_member_id <> ' . $record['member_id'] ) );
			$this->DB->execute();
			
			while( $r = $this->DB->fetch() )
			{
				$contributions[ $r['revision_member_id'] ]	= ( isset($contributions[ $r['revision_member_id'] ]) AND $contributions[ $r['revision_member_id'] ] > $r['revision_date'] ) ? $contributions[ $r['revision_member_id'] ] : $r['revision_date'];
				$contributors[ $r['revision_member_id'] ]	= $r['revision_member_id'];
			}
			
			if( count($contributors) )
			{
				$members	= IPSMember::load( $contributors );
				
				foreach( $contributions as $mid => $date )
				{
					$member	= IPSMember::buildDisplayData( $members[ $mid ] );
					
					$contributions[ $mid ]	= array( 'date' => $date, 'member' => $member );
				}
			}
			
			$record['contributers']	= $contributions;
		}

		//-----------------------------------------
		// Update views count
		//-----------------------------------------
		
		$this->DB->update( $this->database['database_database'], "record_views=record_views+1", "primary_id_field={$record['primary_id_field']}", true, true );
		
		//-----------------------------------------
		// Hide fields
		//-----------------------------------------
		
		$showFields	= array();
		
		foreach( $this->fields as $field )
		{
			if( $field['field_display_display'] )
			{
				$showFields[]	= $field;
			}
		}
		
		//-----------------------------------------
		// Output
		//-----------------------------------------

		$template	= 'template_' . $this->database['template_key'];
		$_content	.= $this->registry->output->getTemplate('ccs')->$template( array( 'database' => $this->database, 'fields' => $showFields, 'record' => $record, 'comments' => $commentHtml, 'category' => $category ) );
		
		return $_content;
	}
	
	/**
	 * Parse attachments
	 *
	 * @access	public
	 * @param	array 	Database data
	 * @param	array	Field data (all fields)
	 * @param	array 	Record data
	 * @return	array 	Reparsed records
	 */
	public function parseAttachments( $database, $fields, $record )
	{
		//-----------------------------------------
		// Verify we have an attachments field,
		// otherwise there are no uploads to parse
		//-----------------------------------------
		
		$_hasAttachments	= false;
		
		foreach( $fields as $k => $v )
		{
			if( $v['field_type'] == 'attachments' )
			{
				$_hasAttachments	= true;
				break;
			}
		}
		
		if( !$_hasAttachments )
		{
			return $record;
		}

		//-----------------------------------------
		// Get attachment map ids
		//-----------------------------------------
		
		$mapIds	= array();
		
		if( is_array($this->caches['ccs_attachments_data'][ $record['primary_id_field'] ]) AND count($this->caches['ccs_attachments_data'][ $record['primary_id_field'] ]) )
		{
			$mapIds	= array_keys( $this->caches['ccs_attachments_data'][ $record['primary_id_field'] ] );
		}
		else
		{
			$this->DB->build( array( 'select' => '*', 'from' => 'ccs_attachments_map', 'where' => "map_database_id={$database['database_id']} AND map_record_id={$record['primary_id_field']}" ) );
			$this->DB->execute();
			
			while( $r = $this->DB->fetch() )
			{
				$mapIds[]	= $r['map_id'];
			}
		}
		
		if( !count($mapIds) )
		{
			return $record;
		}
			
		//-----------------------------------------
		// Get attachments library
		//-----------------------------------------
		
		$this->registry->class_localization->loadLanguageFile( array( 'public_topic' ), 'forums' );
		
		if ( ! is_object( $this->class_attach ) )
		{
			require_once( IPSLib::getAppDir( 'core' ) . '/sources/classes/attach/class_attach.php' );
			$class_attach = new class_attach( $this->registry );
		}
	
		$class_attach->type  = 'ccs';
		$class_attach->init();
		
		//-----------------------------------------
		// Loop over each field in the record
		//-----------------------------------------

		foreach( $record as $k => $v )
		{
			//-----------------------------------------
			// If it's a custom field...
			//-----------------------------------------
			
			if( preg_match( "/^field_(\d+)$/", $k, $matches ) )
			{
				//-----------------------------------------
				// If the field type is attachments, just skip
				//-----------------------------------------
				
				if( $fields[ $matches[1] ]['field_type'] == 'attachments' )
				{
					continue;
				}

				$value	= $record[ $k . '_value' ];
				
				//-----------------------------------------
				// Do we have a tag in this field?
				//-----------------------------------------
				
				if( !stristr( $value, "[attachment=" ) )
				{
					continue;
				}

				//-----------------------------------------
				// Get HTML
				//-----------------------------------------

				$attachHTML = $class_attach->renderAttachments( $value, $mapIds );

				/* Now parse back in the rendered posts */
				if( is_array($attachHTML) AND count($attachHTML) )
				{
					foreach( $attachHTML as $id => $data )
					{
						if( !$data['html'] )
						{
							continue;
						}
						
						/* Get rid of any lingering attachment tags */
						if ( stristr( $data['html'], "[attachment=" ) )
						{
							$data['html'] = IPSText::stripAttachTag( $data['html'] );
						}

						$record[ $k . '_value' ]				= $data['html'];
						$record[ $k . '_value_attachmentHtml']	= $data['attachmentHtml'];
					}
				}
			}
		}

		return $record;
	}
	
	/**
	 * Get/check moderator permissions
	 *
	 * @access	public
	 * @param	array 		Database info
	 * @return	array 		Modified database info array
	 */
	public function checkModerator( $database=array() )
	{
		//-----------------------------------------
		// Supermods can moderator
		//-----------------------------------------
		
		if( $this->memberData['g_is_supmod'] )
		{
			$database['_can_add']			= true;
			$database['moderate_edit']		= 1;
			$database['moderate_delete']	= 1;
			$database['moderate_deletec']	= 1;
			$database['moderate_lock']		= 1;
			$database['moderate_pin']		= 1;
			$database['moderate_unlock']	= 1;
			$database['moderate_approve']	= 1;
			$database['moderate_approvec']	= 1;
			
			return $database;
		}
		
		//-----------------------------------------
		// Cache, in case we get called more than once
		//-----------------------------------------
		
		static $moderators	= array();
		static $modChecked	= false;
		
		if( !$modChecked )
		{
			$modChecked	= true;
			
			$this->DB->build( array( 'select' => '*', 'from' => 'ccs_database_moderators', 'where' => 'moderator_database_id=' . $database['database_id'] ) );
			$this->DB->execute();
			
			while( $r = $this->DB->fetch() )
			{
				$moderators[ $r['moderator_type'] ][]	= $r;
			}
		}
		
		//-----------------------------------------
		// Check group perms first
		//-----------------------------------------
		
		if( is_array($moderators['group']) AND count($moderators['group']) )
		{
			$_myGroups	= array( $this->memberData['member_group_id'] );
			
			if( $this->memberData['mgroup_others'] )
			{
				$_others	= explode( ',', IPSText::cleanPermString( $this->memberData['mgroup_others'] ) );
				$_myGroups	= array_merge( $_myGroups, $_others );
			}
			
			foreach( $moderators['group'] as $_moderator )
			{
				if( in_array( $_moderator['moderator_type_id'], $_myGroups ) )
				{
					$database['_can_add']			= $_moderator['moderator_add_record'] ? true : $database['_can_add'];
					$database['moderate_edit']		= $_moderator['moderator_edit_record'];
					$database['moderate_delete']	= $_moderator['moderator_delete_record'];
					$database['moderate_deletec']	= $_moderator['moderator_delete_comment'];
					$database['moderate_lock']		= $_moderator['moderator_lock_record'];
					$database['moderate_unlock']	= $_moderator['moderator_unlock_record'];
					$database['moderate_approve']	= $_moderator['moderator_approve_record'];
					$database['moderate_approvec']	= $_moderator['moderator_approve_comment'];
					$database['moderate_pin']		= $_moderator['moderator_pin_record'];
				}
			}
		}
		
		//-----------------------------------------
		// Then individual member mod perms
		//-----------------------------------------
		
		if( is_array($moderators['member']) AND count($moderators['member']) )
		{
			foreach( $moderators['member'] as $_moderator )
			{
				if( $_moderator['moderator_type_id'] == $this->memberData['member_id'] )
				{
					$database['_can_add']			= $_moderator['moderator_add_record'] ? true : $database['_can_add'];
					$database['moderate_edit']		= $_moderator['moderator_edit_record'];
					$database['moderate_delete']	= $_moderator['moderator_delete_record'];
					$database['moderate_deletec']	= $_moderator['moderator_delete_comment'];
					$database['moderate_lock']		= $_moderator['moderator_lock_record'];
					$database['moderate_unlock']	= $_moderator['moderator_unlock_record'];
					$database['moderate_approve']	= $_moderator['moderator_approve_record'];
					$database['moderate_approvec']	= $_moderator['moderator_approve_comment'];
					$database['moderate_pin']		= $_moderator['moderator_pin_record'];
				}
			}
		}
		
		return $database;
	}
	
	/**
	 * Send a notification to members watching a record
	 *
	 * @access	public
	 * @param	array 		Database data
	 * @param	array 		Record data
	 * @param	array 		New comment data
	 * @return	void
	 */
	public function sendCommentNotification( $database, $record, $comment )
	{
		$this->lang->loadLanguageFile( array( 'public_lang' ), 'ccs' );

		//-----------------------------------------
		// Format title
		//-----------------------------------------
		
		$this->fieldsClass	= $this->registry->ccsFunctions->getFieldsClass();

		$fields	= array();

		if( is_array($this->caches['ccs_fields'][ $database['database_id'] ]) AND count($this->caches['ccs_fields'][ $database['database_id'] ]) )
		{
			foreach( $this->caches['ccs_fields'][ $database['database_id'] ] as $_field )
			{
				$fields[ $_field['field_id'] ]	= $_field;
			}
		}
		
		$_title	= $this->fieldsClass->getFieldValue( $fields[ str_replace( 'field_', '', $database['database_field_title'] ) ], $record, $fields[ str_replace( 'field_', '', $database['database_field_title'] ) ]['field_truncate'] );

		//-----------------------------------------
		// Get subscribed members
		//-----------------------------------------
		
		$this->DB->build( array( 'select'	=> 'c.*', 
								 'from'		=> array( 'ccs_database_notifications' => 'c' ), 
								 'where'	=> "c.notify_database={$database['database_id']} AND c.notify_record={$record['primary_id_field']}",
								 'add_join'	=> array(
								 					array(
								 						'select'	=> 'm.member_id, m.language, m.members_display_name, m.email, m.members_seo_name',
								 						'from'		=> array( 'members' => 'm' ),
								 						'type'		=> 'left',
								 						'where'		=> 'm.member_id=c.notify_member',
								 						)
								 					)
						)		);
		$outer	= $this->DB->execute();
		
		while( $row = $this->DB->fetch($outer) )
		{
			if( $row['notify_member'] == $comment['comment_user'] )
			{
				continue;
			}
			
			//-----------------------------------------
			// Notifications library
			//-----------------------------------------
			
			$classToLoad		= IPSLib::loadLibrary( IPS_ROOT_PATH . '/sources/classes/member/notifications.php', 'notifications' );
			$notifyLibrary		= new $classToLoad( $this->registry );
			
			$row['language'] = !$row['language'] ? IPSLib::getDefaultLanguage() : $row['language'];
			
			IPSText::getTextClass('email')->getTemplate( "ccs_comment_notification", $row['language'] );
		
			IPSText::getTextClass('email')->buildMessage( array(
																'NAME'		=> $row['members_display_name'],
																'POSTER'	=> $comment['poster_name'],
																'LINK'		=> $this->registry->ccsFunctions->returnDatabaseUrl( $database['database_id'], 0, $record, $comment['comment_id'] ),
																'TITLE'		=> $_title,
																'TEXT'		=> $comment['comment_post'] ) );

			IPSText::getTextClass('email')->subject	= sprintf( 
																IPSText::getTextClass('email')->subject, 
																$this->registry->output->buildSEOUrl( 'showuser=' . $comment['member_id'], 'public', $comment['members_seo_name'], 'showuser' ),
																$comment['poster_name'],
																$this->registry->ccsFunctions->returnDatabaseUrl( $database['database_id'], 0, $record, $comment['comment_id'] ), 
																$_title
															);
															
			$notifyLibrary->setMember( $row );
			$notifyLibrary->setFrom( array() );
			$notifyLibrary->setNotificationKey( 'ccs_notifications' );
			$notifyLibrary->setNotificationUrl( $this->registry->ccsFunctions->returnDatabaseUrl( $database['database_id'], 0, $record, $comment['comment_id'] ) );
			$notifyLibrary->setNotificationText( IPSText::getTextClass('email')->message );
			$notifyLibrary->setNotificationTitle( IPSText::getTextClass('email')->subject );
			
			try
			{
				$notifyLibrary->sendNotification();
			}
			catch( Exception $e ){}
		}
	}

	/**
	 * Send a notification to members watching a category
	 *
	 * @access	public
	 * @param	array 		Database data
	 * @param	array 		Category data
	 * @param	array 		Record data
	 * @return	void
	 */
	public function sendRecordNotification( $database, $category, $record )
	{
		if( !$category['category_id'] )
		{
			return;
		}
		
		$this->lang->loadLanguageFile( array( 'public_lang' ), 'ccs' );
		
		//-----------------------------------------
		// Format title
		//-----------------------------------------

		$this->fieldsClass	= $this->registry->ccsFunctions->getFieldsClass();

		$fields	= array();

		if( is_array($this->caches['ccs_fields'][ $database['database_id'] ]) AND count($this->caches['ccs_fields'][ $database['database_id'] ]) )
		{
			foreach( $this->caches['ccs_fields'][ $database['database_id'] ] as $_field )
			{
				$fields[ $_field['field_id'] ]	= $_field;
			}
		}
		
		$_title	= $this->fieldsClass->getFieldValue( $fields[ str_replace( 'field_', '', $database['database_field_title'] ) ], $record, $fields[ str_replace( 'field_', '', $database['database_field_title'] ) ]['field_truncate'] );

		//-----------------------------------------
		// Get subscribed members
		//-----------------------------------------
		
		$this->DB->build( array( 'select'	=> 'c.*', 
								 'from'		=> array( 'ccs_database_notifications' => 'c' ), 
								 'where'	=> "c.notify_database={$database['database_id']} AND c.notify_category={$category['category_id']}",
								 'add_join'	=> array(
								 					array(
								 						'select'	=> 'm.member_id, m.language, m.members_display_name, m.email',
								 						'from'		=> array( 'members' => 'm' ),
								 						'type'		=> 'left',
								 						'where'		=> 'm.member_id=c.notify_member',
								 						)
								 					)
						)		);
		$outer	= $this->DB->execute();
		
		while( $row = $this->DB->fetch($outer) )
		{
			if( $row['notify_member'] == $record['member_id'] )
			{
				continue;
			}
			
			//-----------------------------------------
			// Notifications library
			//-----------------------------------------
			
			$classToLoad		= IPSLib::loadLibrary( IPS_ROOT_PATH . '/sources/classes/member/notifications.php', 'notifications' );
			$notifyLibrary		= new $classToLoad( $this->registry );
			
			$row['language'] = !$row['language'] ? IPSLib::getDefaultLanguage() : $row['language'];
			
			IPSText::getTextClass('email')->getTemplate( "ccs_record_notification", $row['language'] );
		
			IPSText::getTextClass('email')->buildMessage( array(
																'NAME'		=> $row['members_display_name'],
																'POSTER'	=> $record['poster_name'],
																'LINK'		=> $this->registry->ccsFunctions->returnDatabaseUrl( $database['database_id'], 0, $record ),
																'TITLE'		=> $_title,
																'CATEGORY'	=> $category['category_name'] ) );

			IPSText::getTextClass('email')->subject	= sprintf( 
																IPSText::getTextClass('email')->subject, 
																$this->registry->ccsFunctions->returnDatabaseUrl( $database['database_id'], 0, $record ),
																$_title, 
																$this->registry->ccsFunctions->returnDatabaseUrl( $database['database_id'], $category['category_id'] ),
																$category['category_name']
															);
															
			$notifyLibrary->setMember( $row );
			$notifyLibrary->setFrom( array() );
			$notifyLibrary->setNotificationKey( 'ccs_notifications' );
			$notifyLibrary->setNotificationUrl( $this->registry->ccsFunctions->returnDatabaseUrl( $database['database_id'], 0, $record ) );
			$notifyLibrary->setNotificationText( IPSText::getTextClass('email')->message );
			$notifyLibrary->setNotificationTitle( IPSText::getTextClass('email')->subject );

			try
			{
				$notifyLibrary->sendNotification();
			}
			catch( Exception $e ){}
		}
	}
	
	/**
	 * Check permalink
	 *
	 * @access	public
	 * @param	string	Correct URL for page
	 * @return	void	(May redirect to correct URL)
	 */
	public function checkPermalink( $url )
	{
		$databaseString	= $this->registry->ccsFunctions->getDatabaseFurlString();

		if( !$databaseString )
		{
			return;
		}
		
		$requestedUrl	= rtrim( $this->database['base_link'], '?' ) . '/' . DATABASE_FURL_MARKER . '/' . $databaseString;
		$url			= rtrim( $url, '/?' );

		if( $requestedUrl != $url )
		{
			//print $requestedUrl . '<br>';
			//print $url;exit;
			
			if ( isset( $_SERVER['SERVER_PROTOCOL'] ) AND strstr( $_SERVER['SERVER_PROTOCOL'], '/1.0' ) )
			{
				header("HTTP/1.0 301 Moved Permanently" );
			}
			else
			{
				header("HTTP/1.1 301 Moved Permanently" );
			}			

			header( "Location: " . $url );
			exit;
		}
	}
	
	/**
	 * Fix the incoming data into a normalized version for furls
	 *
	 * @access	public
	 * @param	object	Category library
	 * @return	void
	 */
	public function fixDatabaseFurls()
	{
		//-----------------------------------------
		// Got a string to parse?
		//-----------------------------------------
		
		$databaseString	= $this->registry->ccsFunctions->getDatabaseFurlString();

		if( !$databaseString )
		{
			return;
		}
		
		//-----------------------------------------
		// Break string up
		//-----------------------------------------
		
		$_bits			= explode( '/', $databaseString );

		if( count($_bits) )
		{
			$_last	= array_pop($_bits);
			
			//-----------------------------------------
			// Does last element appear to be a record?
			//-----------------------------------------
			
			if( preg_match( "/.+?\-r(\d+)($|#|&|\?)/", $_last, $matches ) )
			{
				$this->request['record']	= $matches[1];

				return;
			}
			
			//-----------------------------------------
			// Not sure?  Check categories first, since they
			//	are cached.
			//-----------------------------------------
			
			foreach( $this->categories->categories as $id => $data )
			{
				if( $_last == $data['category_furl_name'] )
				{
					$this->request['category']	= $id;
					
					return;
				}
			}
			
			//-----------------------------------------
			// No category found, possibly a static record furl
			//-----------------------------------------
			
			$_approved	= !$this->database['moderate_approve'] ? "r.record_approved=1 AND " : '';
			
			$record		= $this->DB->buildAndFetch( array( 
														'select'	=> 'r.*', 
														'from'		=> array( $this->database['database_database'] => 'r' ), 
														'where'		=> $_approved . "r.record_static_furl='" . $this->DB->addSlashes( $_last ) . "'",
														'add_join'	=> array(
																			array(
																				'select'	=> 'c.*',
																				'from'		=> array( 'ccs_database_categories' => 'c' ),
																				'where'		=> 'c.category_id=r.category_id',
																				'type'		=> 'left',
																				)
																			)
												)		);

			if( $record['primary_id_field'] )
			{
				$this->_record	= $record;
				
				$this->request['record']	= $record['primary_id_field'];
			}
		}
	}
	
	/**
	 * Get record url (handles furls)
	 *
	 * @access	public
	 * @param	array 	Record data
	 * @param	bool	Prepare URL to add more params
	 * @return	string	Record url
	 */
	public function getRecordUrl( $record, $more=false )
	{
		if( !$this->settings['use_friendly_urls'] AND !$this->settings['ccs_root_url'] )
		{
			return $this->database['base_link'] . 'record=' . $record['primary_id_field'] . ( $more ? '&amp;' : '' );
		}
		else
		{
			if( $record['category_id'] )
			{
				$_url	= $this->categories->getCategoryUrl( $this->database['base_link'], $record['category_id'] );
			}
			else
			{
				$_url	= substr( $this->database['base_link'], 0, -1 ) . '/' . DATABASE_FURL_MARKER . '/';
			}

			$_value	= '';
			
			if( $record['record_static_furl'] )
			{
				$_url	.= $record['record_static_furl'];
			}
			else
			{
				if( $record['record_dynamic_furl'] )
				{
					$_url	.= $record['record_dynamic_furl'] . '-r' . $record['primary_id_field'];
				}
				else
				{
					if( $record[ $this->database['database_field_title'] . '_value' ] )
					{
						$_value	= $record[ $this->database['database_field_title'] . '_value' ];
					}
					else
					{
						$_value	= $this->fieldsClass->getFieldValue( $this->fields[ str_replace( 'field_', '', $this->database['database_field_title'] ) ], $record, $this->fields[ str_replace( 'field_', '', $this->database['database_field_title'] ) ]['field_truncate'] );
					}
					
					$_seo	= IPSText::makeSeoTitle( $_value );
					$_url	.= $_seo . '-r' . $record['primary_id_field'];
					
					if( !$record['_skipUpdateDynamic'] )
					{
						$this->DB->update( $this->database['database_database'], array( 'record_dynamic_furl' => $_seo ), 'primary_id_field=' . $record['primary_id_field'], true );
					}
				}
			}
			
			return $_url . ( $more ? '?' : '' );
		}
	}
	
	/**
	 * Get the record
	 *
	 * @access	protected
	 * @return	array 		Record data
	 */
	protected function _getRecord()
	{
		if( $this->_record )
		{
			$record		= $this->_record;
		}
		else
		{
			$_approved	= !$this->database['moderate_approve'] ? "r.record_approved=1 AND " : '';
			
			$record		= $this->DB->buildAndFetch( array( 
														'select'	=> 'r.*', 
														'from'		=> array( $this->database['database_database'] => 'r' ), 
														'where'		=> $_approved . 'r.primary_id_field=' . intval($this->request['record']),
														'add_join'	=> array(
																			array(
																				'select'	=> 'c.*',
																				'from'		=> array( 'ccs_database_categories' => 'c' ),
																				'where'		=> 'c.category_id=r.category_id',
																				'type'		=> 'left',
																				)
																			)
												)		);
		}
		
		return $record;
	}
}