<?php /*

 ocPortal
 Copyright (c) ocProducts, 2004-2012

 See text/EN/licence.txt for full licencing information.


 NOTE TO PROGRAMMERS:
   Do not edit this file. If you need to make changes, save your changed file to the appropriate *_custom folder
   **** If you ignore this advice, then your website upgrades (e.g. for bug fixes) will likely kill your changes ****

*/

/**
 * @license		http://opensource.org/licenses/cpal_1.0 Common Public Attribution License
 * @copyright	ocProducts Ltd
 * @package		catalogues
 */

require_code('aed_module');

/**
 * Module page class.
 */
class Module_cms_catalogues extends standard_aed_module
{
	var $lang_type='CATALOGUE_ENTRY';
	var $select_name='ENTRY';
	var $permissions_require='mid';
	var $permissions_cat_require='catalogues_catalogue';
	var $permissions_cat_name='catalogue_name';
	var $permissions_cat_require_b='catalogues_category';
	var $permissions_cat_name_b='category_id';
	var $user_facing=true;
	var $seo_type='catalogue_entry';
	var $catalogue=true;
	var $award_type='catalogue_entry';
	var $possibly_some_kind_of_upload=true;
	var $do_preview=NULL;
	var $menu_label='CATALOGUES';
	var $orderer='ce_add_date';
	var $table='catalogue_entries';
	var $title_is_multi_lang=false;

	var $donext_category_id;
	var $donext_catalogue_name;

	/**
	 * Standard modular entry-point finder function.
	 *
	 * @return ?array	A map of entry points (type-code=>language-code) (NULL: disabled).
	 */
	function get_entry_points()
	{
		return array_merge(array('misc'=>'MANAGE_CATALOGUES','import'=>'IMPORT_CATALOGUE_ENTRIES','export'=>'CATALOGUE_EXPORT'),parent::get_entry_points());
	}

	/**
	 * Standard modular privilege-overide finder function.
	 *
	 * @return array	A map of privileges that are overridable; sp to 0 or 1. 0 means "not category overridable". 1 means "category overridable".
	 */
	function get_sp_overrides()
	{
		require_lang('catalogues');
		return array('mass_import'=>0,'high_catalogue_entry_timeout'=>1,'submit_cat_highrange_content'=>array(0,'ADD_CATALOGUE'),'edit_cat_highrange_content'=>array(0,'EDIT_CATALOGUE'),'delete_cat_highrange_content'=>array(0,'DELETE_CATALOGUE'),'submit_cat_midrange_content'=>array(0,'ADD_CATALOGUE_CATEGORY'),'edit_cat_midrange_content'=>array(0,'EDIT_CATALOGUE_CATEGORY'),'delete_cat_midrange_content'=>array(0,'DELETE_CATALOGUE_CATEGORY'),'submit_midrange_content'=>array(1,'ADD_CATALOGUE_ENTRY'),'bypass_validation_midrange_content'=>array(1,'BYPASS_VALIDATION_CATALOGUE_ENTRY'),'edit_own_midrange_content'=>array(1,'EDIT_OWN_CATALOGUE_ENTRY'),'edit_midrange_content'=>array(1,'EDIT_CATALOGUE_ENTRY'),'delete_own_midrange_content'=>array(1,'DELETE_OWN_CATALOGUE_ENTRY'),'delete_midrange_content'=>array(1,'DELETE_CATALOGUE_ENTRY'));
	}

	/**
	 * Standard aed_module run_start.
	 *
	 * @param  ID_TEXT		The type of module execution
	 * @return tempcode		The output of the run
	 */
	function run_start($type)
	{
		$this->cat_aed_module=new Module_cms_catalogues_cat();
		$this->alt_aed_module=new Module_cms_catalogues_alt();
		$GLOBALS['MODULE_CMS_CATALOGUES']=$this;

		if (get_value('disable_cat_cat_perms')==='1')
		{
			$this->permissions_cat_require_b=NULL;
			$this->permissions_cat_name_b=NULL;
			$this->cat_aed_module->permissions_cat_require=NULL;
			$this->cat_aed_module->permissions_cat_name=NULL;
		}

		$GLOBALS['HELPER_PANEL_TUTORIAL']='tut_catalogues';
		$GLOBALS['HELPER_PANEL_PIC']='pagepics/catalogues';

		require_lang('catalogues');
		require_lang('fields');
		require_code('catalogues');

		if ($type=='add_catalogue')
		{
			require_javascript('javascript_ajax');
			$script=find_script('snippet');
			$this->alt_aed_module->javascript.="
				var form=document.getElementById('new_field_0_name').form;
				form.old_submit=form.onsubmit;
				form.onsubmit=function()
					{
						document.getElementById('submit_button').disabled=true;
						var url='".addslashes($script)."?snippet=exists_catalogue&name='+window.encodeURIComponent(form.elements['name'].value);
						if (!do_ajax_field_test(url))
						{
							document.getElementById('submit_button').disabled=false;
							return false;
						}
						document.getElementById('submit_button').disabled=false;
						if (typeof form.old_submit!='undefined' && form.old_submit) return form.old_submit();
						return true;
					};
			";
		}

		// Decide what to do
		if ($type=='misc') return $this->misc();
		if ($type=='import') return $this->import_catalogue();
		if ($type=='_import') return $this->_import_catalogue();
		if ($type=='export') return $this->export_catalogue();

		return new ocp_tempcode();
	}

	/**
	 * The do-next manager for before content management.
	 *
	 * @return tempcode		The UI
	 */
	function misc()
	{
		require_code('templates_donext');
		$catalogue_name=get_param('catalogue_name','');
		if ($catalogue_name=='')
		{
			$extra_map=array();
			$extra_map_2=array();
		} else
		{
			require_lang('do_next');
			$extra_map=array('catalogue_name'=>$catalogue_name);
			$extra_map_2=array('id'=>$catalogue_name);
			$cat_rows=$GLOBALS['SITE_DB']->query_select('catalogues',array('c_title','c_description'),array('c_name'=>$catalogue_name),'',1);
			if (!array_key_exists(0,$cat_rows)) warn_exit(do_lang_tempcode('MISSING_RESOURCE'));
			$cat_title=$cat_rows[0]['c_title'];
			$cat_description=$cat_rows[0]['c_description'];
		}

		if ((!is_null($catalogue_name)) && ($catalogue_name!=''))
		{
			$cat_count=$GLOBALS['SITE_DB']->query_value('catalogue_categories','COUNT(*)',array('c_name'=>$catalogue_name));
			$has_categories=($cat_count!=0);
		} else $has_categories=true;

		require_code('fields');

		return do_next_manager(($catalogue_name!='')?get_page_title(escape_html(get_translated_text($cat_title)),false):get_page_title('MANAGE_CATALOGUES'),($catalogue_name!='')?get_translated_tempcode($cat_description):comcode_lang_string('DOC_CATALOGUES'),
					array_merge(array(
						/*	 type							  page	 params													 zone	  */
						(has_specific_permission(get_member(),'submit_cat_highrange_content','cms_catalogues') && ($catalogue_name==''))?array('add_one_catalogue',array('_SELF',array_merge($extra_map,array('type'=>'add_catalogue')),'_SELF'),do_lang('ADD_CATALOGUE')):NULL,
						has_specific_permission(get_member(),'edit_cat_highrange_content','cms_catalogues')?array('edit_one_catalogue',array('_SELF',array_merge($extra_map_2,array('type'=>($catalogue_name=='')?'edit_catalogue':'_edit_catalogue')),'_SELF'),do_lang('EDIT_CATALOGUE')):NULL,
						has_specific_permission(get_member(),'submit_cat_midrange_content','cms_catalogues')?array('add_one_category',array('_SELF',array_merge($extra_map,array('type'=>'add_category')),'_SELF'),($catalogue_name!='')?do_lang('NEXT_ITEM_add_one_category'):do_lang('ADD_CATALOGUE_CATEGORY')):NULL,
						has_specific_permission(get_member(),'edit_cat_midrange_content','cms_catalogues')?array('edit_one_category',array('_SELF',array_merge($extra_map,array('type'=>'edit_category')),'_SELF'),($catalogue_name!='')?do_lang('NEXT_ITEM_edit_one_category'):do_lang('EDIT_CATALOGUE_CATEGORY')):NULL,
						(!$has_categories)?NULL:(has_specific_permission(get_member(),'submit_midrange_content','cms_catalogues')?array('add_one',array('_SELF',array_merge($extra_map,array('type'=>'add_entry')),'_SELF'),($catalogue_name!='')?do_lang('NEXT_ITEM_add_one'):do_lang('ADD_CATALOGUE_ENTRY')):NULL),
						(!$has_categories)?NULL:(has_specific_permission(get_member(),'edit_midrange_content','cms_catalogues')?array('edit_one',array('_SELF',array_merge($extra_map,array('type'=>'edit_entry')),'_SELF'),($catalogue_name!='')?do_lang('NEXT_ITEM_edit_one'):do_lang('EDIT_CATALOGUE_ENTRY')):NULL),
						(!$has_categories)?NULL:(has_specific_permission(get_member(),'mass_import','cms_catalogues')?array('import',array('_SELF',array_merge($extra_map,array('type'=>'import')),'_SELF'),do_lang('IMPORT_CATALOGUE_ENTRIES')):NULL),
						(!$has_categories)?NULL:($GLOBALS['FORUM_DRIVER']->is_super_admin(get_member())?array('export',array('_SELF',array_merge($extra_map,array('type'=>'export')),'_SELF'),do_lang('EXPORT_CATALOGUE_ENTRIES')):NULL),
					),manage_custom_fields_donext_link('catalogue'),manage_custom_fields_donext_link('catalogue_category')),
					($catalogue_name!='')?escape_html(get_translated_text($cat_title)):do_lang('MANAGE_CATALOGUES')
		);
	}

	/**
	 * Standard aed_module table function.
	 *
	 * @param  array			Details to go to build_url for link to the next screen.
	 * @return array			A quartet: The choose table, Whether re-ordering is supported from this screen, Search URL, Archive URL.
	 */
	function nice_get_choose_table($url_map)
	{
		require_code('templates_results_table');

		$current_ordering=get_param('sort','title ASC');
		if (strpos($current_ordering,' ')===false) warn_exit(do_lang_tempcode('INTERNAL_ERROR'));
		list($sortable,$sort_order)=explode(' ',$current_ordering,2);
		$sortables=array(
			'title'=>do_lang_tempcode('TITLE'),
			'cc_id'=>do_lang_tempcode('CATEGORY'),
			'ce_add_date'=>do_lang_tempcode('_ADDED'),
			'ce_views'=>do_lang_tempcode('_VIEWS'),
			'ce_submitter'=>do_lang_tempcode('OWNER'),
		);
		if (addon_installed('unvalidated'))
			$sortables['ce_validated']=do_lang_tempcode('VALIDATED');
		if (((strtoupper($sort_order)!='ASC') && (strtoupper($sort_order)!='DESC')) || (!array_key_exists($sortable,$sortables)))
			log_hack_attack_and_exit('ORDERBY_HACK');
		global $NON_CANONICAL_PARAMS;
		$NON_CANONICAL_PARAMS[]='sort';

		$fh=array();
		$fh[]=do_lang_tempcode('TITLE');
		$fh[]=do_lang_tempcode('CATEGORY');
		$fh[]=do_lang_tempcode('_ADDED');
		$fh[]=do_lang_tempcode('_VIEWS');
		$fh[]=do_lang_tempcode('OWNER');
		if (addon_installed('unvalidated'))
			$fh[]=do_lang_tempcode('VALIDATED');
		$fh[]=do_lang_tempcode('ACTIONS');
		$header_row=results_field_title($fh,$sortables,'sort',$sortable.' '.$sort_order);

		$fields=new ocp_tempcode();

		require_code('form_templates');
		$only_owned=has_specific_permission(get_member(),'edit_midrange_content','cms_catalogues')?NULL:get_member();
		list($rows,$max_rows)=$this->get_entry_rows(false,($current_ordering=='title ASC' || $current_ordering=='title DESC')?'ce_add_date ASC':$current_ordering,is_null($only_owned)?array('c_name'=>get_param('catalogue_name')):array('c_name'=>get_param('catalogue_name'),'ce_submitter'=>$only_owned));
		$_fields=array();
		$cat_titles=array();
		foreach ($rows as $row)
		{
			$edit_link=build_url($url_map+array('id'=>$row['id']),'_SELF');

			$catalogue_name=$row['c_name'];

			$entry_fields=get_catalogue_entry_field_values($catalogue_name,$row['id'],array(0));
			$name=$entry_fields[0]['effective_value']; // 'Name' is value of first field

			$fr=array();
			$fr[]=protect_from_escaping(hyperlink(build_url(array('page'=>'catalogues','type'=>'entry','id'=>$row['id']),get_module_zone('catalogues')),$name));
			if (array_key_exists($row['cc_id'],$cat_titles))
			{
				$cc_title=$cat_titles[$row['cc_id']];
			} else
			{
				$cc_title=$GLOBALS['SITE_DB']->query_value_null_ok('catalogue_categories','cc_title',array('id'=>$row['cc_id']));
				$cat_titles[$row['cc_id']]=$cc_title;
			}
			if (!is_null($cc_title))
			{
				$fr[]=protect_from_escaping(hyperlink(build_url(array('page'=>'catalogues','type'=>'category','id'=>$row['cc_id']),get_module_zone('catalogues')),get_translated_text($cc_title),false,true));
			} else
			{
				$fr[]=do_lang('UNKNOWN');
			}
			$fr[]=get_timezoned_date($row['ce_add_date']);
			$fr[]=integer_format($row['ce_views']);
			$username=protect_from_escaping($GLOBALS['FORUM_DRIVER']->member_profile_hyperlink($row['ce_submitter']));
			$fr[]=$username;
			if (addon_installed('unvalidated'))
				$fr[]=$row['ce_validated']?do_lang_tempcode('YES'):do_lang_tempcode('NO');
			$fr[]=protect_from_escaping(hyperlink($edit_link,do_lang_tempcode('EDIT'),false,true,'#'.strval($row['id'])));

			$_fields[]=array('row'=>$fr,'title'=>$name);
		}
		if ($current_ordering=='title ASC' || $current_ordering=='title DESC')
		{
			global $M_SORT_KEY;
			$M_SORT_KEY='title';
			usort($_fields,'multi_sort');
			if ($current_ordering=='title DESC') $_fields=array_reverse($_fields);
		}
		foreach ($_fields as $_fr)
		{
			$fields->attach(results_entry($_fr['row'],true));
		}

		$search_url=build_url(array('page'=>'search','id'=>'catalogue_entries','catalogue_name'=>$catalogue_name),get_module_zone('search'));
		$archive_url=build_url(array('page'=>'catalogues','type'=>'index','id'=>$catalogue_name),get_module_zone('news'));

		return array(results_table(do_lang($this->menu_label),get_param_integer('start',0),'start',get_param_integer('max',20),'max',$max_rows,$header_row,$fields,$sortables,$sortable,$sort_order),false,$search_url,$archive_url);
	}

	/**
	 * Standard aed_module list function.
	 *
	 * @return ?array				A triple: The tree field (tempcode), Search URL, Archive URL (NULL: nothing here)
	 */
	function nice_get_ajax_tree()
	{
		$catalogue_name=get_param('catalogue_name');

		if ($GLOBALS['SITE_DB']->query_value('catalogue_entries','COUNT(*)',array('c_name'=>$catalogue_name))==0) warn_exit(do_lang_tempcode('NO_ENTRIES'));

		$is_tree=$GLOBALS['SITE_DB']->query_value('catalogues','c_is_tree',array('c_name'=>$catalogue_name));
		if ($is_tree==0) return NULL;

		$search_url=build_url(array('page'=>'search','id'=>'catalogue_entries','catalogue_name'=>$catalogue_name),get_module_zone('search'));
		$archive_url=build_url(array('page'=>'catalogues','type'=>'index','id'=>$catalogue_name),get_module_zone('catalogues'));

		$only_owned=has_specific_permission(get_member(),'edit_midrange_content','cms_catalogues')?NULL:get_member();
		$tree=form_input_tree_list(do_lang_tempcode('ENTRY'),'','id',NULL,'choose_catalogue_entry',array('catalogue_name'=>$catalogue_name,'only_owned'=>$only_owned,'editable_filter'=>true),true);
		return array($tree,$search_url,$archive_url);
	}

	/**
	 * Get tempcode for a catalogue entry adding/editing form.
	 *
	 * @param  ?ID_TEXT			The catalogue for the entry (NULL: detect)
	 * @param  ?AUTO_LINK		The category for the entry (NULL: first)
	 * @param  BINARY				Whether the entry is validated
	 * @param  LONG_TEXT			Staff notes
	 * @param  ?BINARY			Whether rating is allowed (NULL: decide statistically, based on existing choices)
	 * @param  ?SHORT_INTEGER	Whether comments are allowed (0=no, 1=yes, 2=review style) (NULL: decide statistically, based on existing choices)
	 * @param  ?BINARY			Whether trackbacks are allowed (NULL: decide statistically, based on existing choices)
	 * @param  ?AUTO_LINK		The ID of the entry (NULL: not yet added)
	 * @return array				A pair: the tempcode for the visible fields, and the tempcode for the hidden fields
	 */
	function get_form_fields($catalogue_name=NULL,$category_id=NULL,$validated=1,$notes='',$allow_rating=NULL,$allow_comments=NULL,$allow_trackbacks=NULL,$id=NULL)
	{
		list($allow_rating,$allow_comments,$allow_trackbacks)=$this->choose_feedback_fields_statistically($allow_rating,$allow_comments,$allow_trackbacks);

		if (is_null($catalogue_name)) $catalogue_name=get_param('catalogue_name');

		require_code('feedback');
		require_code('form_templates');

		$fields=new ocp_tempcode();

		$hidden=form_input_hidden('catalogue_name',$catalogue_name);

		global $NON_CANONICAL_PARAMS;
		$NON_CANONICAL_PARAMS[]='validated';

		if ((is_null($id)) && (is_null($category_id)))
		{
			$category_id=get_param_integer('category_id',NULL);

			$NON_CANONICAL_PARAMS[]='category_id';
			$NON_CANONICAL_PARAMS[]='category_id_suggest';
		}

		$this->add_text=do_lang('CATALOGUE_'.$catalogue_name.'_ADD_TEXT',escape_html(get_base_url()),NULL,NULL,NULL,false);
		$this->edit_text=do_lang('CATALOGUE_'.$catalogue_name.'_EDIT_TEXT',escape_html(get_base_url()),NULL,NULL,NULL,false);

		// Standard fields
		// ===============

		// Category
		if ((is_null($id)) && (is_null($category_id)) && (get_value('no_confirm_url_spec_cats')!=='1'))
		{
			$category_id=$GLOBALS['SITE_DB']->query_value_null_ok('catalogue_categories','MIN(id)',array('c_name'=>$catalogue_name));
		}
		if ((!is_null($category_id)) && ((is_null($id)) && (get_value('no_confirm_url_spec_cats')==='1') || (get_value('no_spec_cat__'.$catalogue_name)==='1'))) // Adding, but defined category ID in URL, and set option saying not to ask for passed categories
		{
			$hidden->attach(form_input_hidden('category_id',strval($category_id)));
		} else
		{
			if ((is_null($id)) && (is_null($category_id)))
			{
				$category_id=get_param_integer('category_id_suggest',NULL); // Less forceful than 'category_id', as may be changed even with 'no_confirm_url_spec_cats' on
			}

			$fields->attach(form_input_tree_list(do_lang_tempcode('CATEGORY'),do_lang_tempcode('DESCRIPTION_CATEGORY_TREE'),'category_id',NULL,'choose_catalogue_category',array('catalogue_name'=>$catalogue_name,'addable_filter'=>true),true,is_null($category_id)?'':strval($category_id)));
		}

		// Special fields
		// ==============

		if (!is_null($id))
		{
			$special_fields=get_catalogue_entry_field_values($catalogue_name,$id);
		} else
		{
			$special_fields=$GLOBALS['SITE_DB']->query_select('catalogue_fields',array('*'),array('c_name'=>$catalogue_name),'ORDER BY cf_order');
		}

		$field_groups=array();

		require_code('fields');
		foreach ($special_fields as $field_num=>$field)
		{
			$NON_CANONICAL_PARAMS[]='field_'.strval($field['id']);

			$ob=get_fields_hook($field['cf_type']);
			$default=get_param('field_'.strval($field['id']),$field['cf_default']);
			if (array_key_exists('effective_value_pure',$field)) $default=$field['effective_value_pure'];
			elseif (array_key_exists('effective_value',$field)) $default=$field['effective_value'];

			$_cf_name=get_translated_text($field['cf_name']);
			$field_cat='';
			if (strpos($_cf_name,': ')!==false)
			{
				$field_cat=substr($_cf_name,0,strpos($_cf_name,': '));
				if ($field_cat.': '==$_cf_name)
				{
					$_cf_name=$field_cat; // Just been pulled out as heading, nothing after ": "
				} else
				{
					$_cf_name=substr($_cf_name,strpos($_cf_name,': ')+2);
				}
			}
			if (!array_key_exists($field_cat,$field_groups)) $field_groups[$field_cat]=new ocp_tempcode();

			$_cf_description=escape_html(get_translated_text($field['cf_description']));

			$GLOBALS['NO_DEBUG_MODE_FULLSTOP_CHECK']=true;
			$result=$ob->get_field_inputter($_cf_name,$_cf_description,$field,$default,is_null($id),!array_key_exists($field_num+1,$special_fields));
			$GLOBALS['NO_DEBUG_MODE_FULLSTOP_CHECK']=false;

			if (is_null($result)) continue;

			if (is_array($result))
			{
				$field_groups[$field_cat]->attach($result[0]);
				$hidden->attach($result[1]);
			} else
			{
				$field_groups[$field_cat]->attach($result);
			}

			if (strpos($field['cf_type'],'_trans')!==false) $this->do_preview=true;

			unset($result);
			unset($ob);
		}

		if (array_key_exists('',$field_groups)) // Blank prefix must go first
		{
			$field_groups_blank=$field_groups[''];
			unset($field_groups['']);
			$field_groups=array_merge(array($field_groups_blank),$field_groups);
		}
		foreach ($field_groups as $field_group_title=>$extra_fields)
		{
			if (is_integer($field_group_title)) $field_group_title=($field_group_title==0)?'':strval($field_group_title);

			if ($field_group_title!='')
				$fields->attach(do_template('FORM_SCREEN_FIELD_SPACER',array('TITLE'=>$field_group_title)));
			$fields->attach($extra_fields);
		}

		if ($validated==0)
		{
			$validated=get_param_integer('validated',0);
			if ($validated==1) attach_message(do_lang_tempcode('WILL_BE_VALIDATED_WHEN_SAVING'));
		}
		if ((has_some_cat_specific_permission(get_member(),'bypass_validation_'.$this->permissions_require.'range_content',NULL,$this->permissions_cat_require_b)) || (has_some_cat_specific_permission(get_member(),'bypass_validation_'.$this->permissions_require.'range_content',NULL,$this->permissions_cat_require)))
		{
			if (addon_installed('unvalidated'))
			{
				if (count($field_groups)!=1)
					$fields->attach(do_template('FORM_SCREEN_FIELD_SPACER',array('TITLE'=>do_lang_tempcode('SETTINGS'))));
				$fields->attach(form_input_tick(do_lang_tempcode('VALIDATED'),do_lang_tempcode('DESCRIPTION_VALIDATED'),'validated',$validated==1));
			}
		}

		require_code('feedback2');
		$fields->attach(feedback_fields($allow_rating==1,$allow_comments==1,$allow_trackbacks==1,false,$notes,$allow_comments==2));

		return array($fields,$hidden);
	}

	/**
	 * Standard aed_module submitter getter.
	 *
	 * @param  ID_TEXT		The entry for which the submitter is sought
	 * @return array			The submitter, and the time of submission (null submission time implies no known submission time)
	 */
	function get_submitter($id)
	{
		$rows=$GLOBALS['SITE_DB']->query_select('catalogue_entries',array('ce_submitter','ce_add_date'),array('id'=>intval($id)),'',1);
		if (!array_key_exists(0,$rows)) return array(NULL,NULL);
		return array($rows[0]['ce_submitter'],$rows[0]['ce_add_date']);
	}

	/**
	 * Standard aed_module cat getter.
	 *
	 * @param  AUTO_LINK		The entry for which the cat is sought
	 * @return string			The cat
	 */
	function get_cat_b($id)
	{
		$temp=$GLOBALS['SITE_DB']->query_value_null_ok('catalogue_entries','cc_id',array('id'=>$id));
		if (is_null($temp)) warn_exit(do_lang_tempcode('MISSING_RESOURCE'));
		return strval($temp);
	}

	/**
	 * Standard aed_module cat getter.
	 *
	 * @param  AUTO_LINK		The entry for which the cat is sought
	 * @return string			The cat
	 */
	function get_cat($id)
	{
		$cat=$this->get_cat_b($id);
		return $GLOBALS['SITE_DB']->query_value('catalogue_categories','c_name',array('id'=>intval($cat)));
	}

	/**
	 * Standard aed_module edit form filler.
	 *
	 * @param  ID_TEXT		The entry being edited
	 * @return array			A tuple of lots of info
	 */
	function fill_in_edit_form($_id)
	{
		$id=intval($_id);

		$myrows=$GLOBALS['SITE_DB']->query_select('catalogue_entries',array('*'),array('id'=>$id),'',1);
		if (!array_key_exists(0,$myrows))
		{
			warn_exit(do_lang_tempcode('MISSING_RESOURCE'));
		}
		$myrow=$myrows[0];

		$catalogue_name=$myrow['c_name'];
		if (is_null($catalogue_name)) warn_exit(do_lang_tempcode('MISSING_RESOURCE'));
		//$this->edit_text=paragraph(do_lang_tempcode('FOR_CATALOGUE',escape_html($catalogue_name)));

		return $this->get_form_fields($catalogue_name,$myrow['cc_id'],$myrow['ce_validated'],$myrow['notes'],$myrow['allow_rating'],$myrow['allow_comments'],$myrow['allow_trackbacks'],$id);
	}

	/**
	 * Get a entry-id=>value map of what a submitted catalogue entry form has set
	 *
	 * @param  ID_TEXT		The name of the catalogue that was used
	 * @param  ?AUTO_LINK	ID of entry being edited (NULL: not being edited)
	 * @return array			The map
	 */
	function get_set_field_map($catalogue_name,$editing_id=NULL)
	{
		// Get field values
		$fields=$GLOBALS['SITE_DB']->query_select('catalogue_fields',array('*'),array('c_name'=>$catalogue_name),'ORDER BY cf_order');
		$map=array();
		require_code('fields');
		require_code('catalogues');
		foreach ($fields as $field)
		{
			$object=get_fields_hook($field['cf_type']);

			list(,,$storage_type)=$object->get_field_value_row_bits($field);

			$value=$object->inputted_to_field_value(!is_null($editing_id),$field,'uploads/catalogues',is_null($editing_id)?NULL:_get_catalogue_entry_field($field['id'],$editing_id,$storage_type));

			$map[$field['id']]=$value;
		}

		return $map;
	}

	/**
	 * Standard aed_module add actualiser.
	 *
	 * @return ID_TEXT		The ID of the entry added
	 */
	function add_actualisation()
	{
		require_code('catalogues2');

		$category_id=post_param_integer('category_id');
		$validated=post_param_integer('validated',0);
		$notes=post_param('notes','');
		$allow_rating=post_param_integer('allow_rating',0);
		$allow_comments=post_param_integer('allow_comments',0);
		$allow_trackbacks=post_param_integer('allow_trackbacks',0);

		$catalogue_name=$GLOBALS['SITE_DB']->query_value_null_ok('catalogue_categories','c_name',array('id'=>$category_id));
		if (is_null($catalogue_name)) warn_exit(do_lang_tempcode('MISSING_RESOURCE'));

		$map=$this->get_set_field_map($catalogue_name);

		if ((!is_guest()) && (addon_installed('points')))
		{
			$points=$GLOBALS['SITE_DB']->query_value('catalogues','c_submit_points',array('c_name'=>$catalogue_name));
			require_code('points2');
			system_gift_transfer(do_lang('ADD_CATALOGUE_ENTRY'),intval($points),get_member());
		}

		$id=actual_add_catalogue_entry($category_id,$validated,$notes,$allow_rating,$allow_comments,$allow_trackbacks,$map);

		if ($validated==1)
		{
			if ((has_actual_page_access($GLOBALS['FORUM_DRIVER']->get_guest_id(),'catalogues')) && (has_category_access($GLOBALS['FORUM_DRIVER']->get_guest_id(),'catalogues_catalogue',$catalogue_name)) && (has_category_access($GLOBALS['FORUM_DRIVER']->get_guest_id(),'catalogues_category',strval($category_id))))
			{
				$map_copy=$map;
				$title=array_shift($map_copy);
				$catalogue_title=get_translated_text($GLOBALS['SITE_DB']->query_value('catalogues','c_title',array('c_name'=>$catalogue_name)));
				syndicate_described_activity('catalogues:ACTIVITY_CATALOGUE_GENERIC_ADD',$catalogue_title,$title,'','_SEARCH:catalogues:entry:'.strval($id),'','','catalogues');
			}
		}

		$this->donext_category_id=$category_id;
		$this->donext_catalogue_name=$catalogue_name;

		return strval($id);
	}

	/**
	 * Standard aed_module edit actualiser.
	 *
	 * @param  ID_TEXT		The entry being edited
	 */
	function edit_actualisation($_id)
	{
		require_code('catalogues2');

		$id=intval($_id);

		$category_id=post_param_integer('category_id',INTEGER_MAGIC_NULL);
		$validated=post_param_integer('validated',fractional_edit()?INTEGER_MAGIC_NULL:0);
		$notes=post_param('notes',STRING_MAGIC_NULL);
		$allow_rating=post_param_integer('allow_rating',fractional_edit()?INTEGER_MAGIC_NULL:0);
		$allow_comments=post_param_integer('allow_comments',fractional_edit()?INTEGER_MAGIC_NULL:0);
		$allow_trackbacks=post_param_integer('allow_trackbacks',fractional_edit()?INTEGER_MAGIC_NULL:0);

		$catalogue_name=$GLOBALS['SITE_DB']->query_value_null_ok('catalogue_categories','c_name',array('id'=>$category_id));
		if (is_null($catalogue_name)) warn_exit(do_lang_tempcode('MISSING_RESOURCE'));
		$map=$this->get_set_field_map($catalogue_name,$id);

		if (($validated==1) && ($GLOBALS['SITE_DB']->query_value('catalogue_entries','ce_validated',array('id'=>$id))==0)) // Just became validated, syndicate as just added
		{
			if ((has_actual_page_access($GLOBALS['FORUM_DRIVER']->get_guest_id(),'catalogues')) && (has_category_access($GLOBALS['FORUM_DRIVER']->get_guest_id(),'catalogues_catalogue',$catalogue_name)) && (has_category_access($GLOBALS['FORUM_DRIVER']->get_guest_id(),'catalogues_category',strval($category_id))))
			{
				$map_copy=$map;
				$title=array_shift($map_copy);
				$catalogue_title=get_translated_text($GLOBALS['SITE_DB']->query_value('catalogues','c_title',array('c_name'=>$catalogue_name)));
				syndicate_described_activity('catalogues:ACTIVITY_CATALOGUE_GENERIC_ADD',$catalogue_title,$title,'','_SEARCH:catalogues:entry:'.strval($id),'','','catalogues',1,$GLOBALS['SITE_DB']->query_value('catalogue_entries','ce_submitter',array('id'=>$id)));
			}
		}

		actual_edit_catalogue_entry($id,$category_id,$validated,$notes,$allow_rating,$allow_comments,$allow_trackbacks,$map,post_param('meta_keywords',STRING_MAGIC_NULL),post_param('meta_description',STRING_MAGIC_NULL));

		$this->donext_category_id=$category_id;
		$this->donext_catalogue_name=$catalogue_name;
	}

	/**
	 * Standard aed_module delete actualiser.
	 *
	 * @param  ID_TEXT		The entry being deleted
	 */
	function delete_actualisation($_id)
	{
		require_code('catalogues2');

		$id=intval($_id);

		$category_id=$GLOBALS['SITE_DB']->query_value_null_ok('catalogue_entries','cc_id',array('id'=>$id));
		if (is_null($category_id)) warn_exit(do_lang_tempcode('MISSING_RESOURCE'));

		actual_delete_catalogue_entry($id);

		$catalogue_name=$GLOBALS['SITE_DB']->query_value('catalogue_categories','c_name',array('id'=>$category_id));
		$this->donext_category_id=$category_id;
		$this->donext_catalogue_name=$catalogue_name;
	}

	/**
	 * Standard aed_module delete possibility checker.
	 *
	 * @param  ID_TEXT		The entry being potentially deleted
	 * @return boolean		Whether it may be deleted
	 */
	function may_delete_this($id)
	{		
		if (!is_ecommerce_catalogue_entry(intval($id))) return true;
		return
			is_null($GLOBALS['SITE_DB']->query_value_null_ok('shopping_order_details','id',array('p_id'=>intval($id),'p_type'=>'catalogue_items')))
			&&
			is_null($GLOBALS['SITE_DB']->query_value_null_ok('shopping_cart','product_id',array('product_id'=>intval($id),'product_type'=>'catalogue_items')))
			;
	}

	/**
	 * The do-next manager for after content management.
	 *
	 * @param  tempcode		The title (output of get_page_title)
	 * @param  tempcode		Some description to show, saying what happened
	 * @param  ?AUTO_LINK	The ID of whatever was just handled (NULL: N/A)
	 * @return tempcode		The UI
	 */
	function do_next_manager($title,$description,$id)
	{
		breadcrumb_set_self(do_lang_tempcode('DONE'));

		$c_name=$this->donext_catalogue_name;
		$category_id=$this->donext_category_id;

		require_code('templates_donext');
		return do_next_manager($title,$description,
					NULL,
					NULL,
					/*		TYPED-ORDERED LIST OF 'LINKS'		*/
					/*	 page	 params				  zone	  */
					array('_SELF',array('type'=>'add_entry','catalogue_name'=>$c_name,'category_id'=>$category_id),'_SELF'),								  // Add one
					(is_null($id) || (!has_specific_permission(get_member(),'edit_own_midrange_content','cms_catalogues',array('catalogues_category',$category_id))))?NULL:array('_SELF',array('type'=>'_edit_entry','id'=>$id,'catalogue_name'=>$c_name),'_SELF'),				 // Edit this
					has_specific_permission(get_member(),'edit_own_midrange_content','cms_catalogues')?array('_SELF',array('type'=>'edit_entry','catalogue_name'=>$c_name),'_SELF'):NULL, // Edit one
					is_null($id)?NULL:array('catalogues',array('type'=>'entry','id'=>$id),get_module_zone('catalogues')),						  // View this
					NULL,																						// View archive
					NULL,																						// Add to category
					has_specific_permission(get_member(),'submit_cat_midrange_content','cms_catalogues')?array('_SELF',array('type'=>'add_category','catalogue_name'=>$c_name),'_SELF'):NULL,			  // Add one category
					has_specific_permission(get_member(),'edit_own_cat_midrange_content','cms_catalogues')?array('_SELF',array('type'=>'edit_category','catalogue_name'=>$c_name),'_SELF'):NULL,			  // Edit one category

					NULL,																						// Edit this category
					NULL,																						// View this category
					/*	  SPECIALLY TYPED 'LINKS'				  */
					array(),
					array(),
					array(
						/*	 type							  page	 params													 zone	  */
						has_specific_permission(get_member(),'submit_cat_highrange_content','cms_catalogues')?array('add_one_catalogue',array('_SELF',array('type'=>'add_catalogue'),'_SELF')):NULL,
						has_specific_permission(get_member(),'edit_own_cat_highrange_content','cms_catalogues')?array('edit_this_catalogue',array('_SELF',array('type'=>'_edit_catalogue','id'=>$c_name),'_SELF')):NULL,
						has_specific_permission(get_member(),'edit_own_cat_highrange_content','cms_catalogues')?array('edit_one_catalogue',array('_SELF',array('type'=>'edit_catalogue'),'_SELF')):NULL,
						array('view_this',array('catalogues',array('type'=>'index','id'=>$c_name),get_module_zone('catalogues')),do_lang('VIEW_CATALOGUE'))
					),
					do_lang('MANAGE_CATALOGUES')
		);
	}

	/**
	 * The UI to choose a catalogue to import catalogue entries
	 *
	 * @return tempcode		The UI
	 */
	function import_catalogue()
	{
		check_specific_permission('mass_import');

		$title=get_page_title('CATALOGUE_IMPORT');

		$catalogue_select=$this->choose_catalogue($title);

		if (!is_null($catalogue_select)) return $catalogue_select;

		$catalogue_name=get_param('catalogue_name');

		$post_url=build_url(array('page'=>'_SELF','type'=>'_import','old_type'=>get_param('type',''),'catalogue_name'=>$catalogue_name),'_SELF');

		$submit_name=do_lang_tempcode('CATALOGUE_IMPORT');

		// Build up form
		$fields=new ocp_tempcode();

		require_code('form_templates');

		$fields->attach(form_input_upload(do_lang_tempcode('UPLOAD'),do_lang_tempcode('UPLOAD_DESC'),'file_novalidate',true,NULL,NULL,true,'csv,txt'));
		$hidden=new ocp_tempcode();
		handle_max_file_size($hidden);

		return do_template('FORM_SCREEN',array('TITLE'=>$title,'TEXT'=>do_lang_tempcode('CATALOGUE_IMPORT_TEXT'),'HIDDEN'=>$hidden,'FIELDS'=>$fields,'SUBMIT_NAME'=>$submit_name,'URL'=>$post_url));
	}

	/**
	 * Standard actualiser to import catalogue entries
	 *
	 * @return tempcode		The UI
	 */
	function _import_catalogue()
	{	
		require_code('catalogues2');

		check_specific_permission('mass_import');

		$catalog_root=NULL;

		$title=get_page_title('CATALOGUE_IMPORT');

		$catalogue_name=get_param('catalogue_name');

		$categories=array();

		$fields=$GLOBALS['SITE_DB']->query_select('catalogue_fields',array('*'),array('c_name'=>$catalogue_name));

		$catsrow=$GLOBALS['SITE_DB']->query("SELECT t1.id,t2.text_original,t1.cc_parent_id FROM ".$GLOBALS['SITE_DB']->get_table_prefix()."catalogue_categories t1,".$GLOBALS['SITE_DB']->get_table_prefix()."translate t2 WHERE t1.cc_title=t2.id AND t1.c_name='".db_escape_string($catalogue_name)."'");

		foreach($catsrow as $values)
		{
			$categories[$values['text_original']]=$values['id'];

			// Root category is 'default' category for catalogue importing (category with same name as catalogue)
			if ((!array_key_exists($catalogue_name,$categories)) && (is_null($values['cc_parent_id'])))
				$categories[$catalogue_name]=$values['id'];
		}

		require_code('uploads');
		$csv_name=NULL;
		if (((is_swf_upload(true)) && (array_key_exists('file_novalidate',$_FILES))) || ((array_key_exists('file_novalidate',$_FILES)) && (is_uploaded_file($_FILES['file_novalidate']['tmp_name']))))
			$csv_name=$_FILES['file_novalidate']['tmp_name'];

		if (is_null($csv_name))
			warn_exit(do_lang_tempcode('IMPROPERLY_FILLED_IN'));

		$fixed_contents=unixify_line_format(file_get_contents($csv_name));
		$myfile=@fopen($csv_name,'wb');
		if ($myfile!==false)
		{
			fwrite($myfile,$fixed_contents);
			fclose($myfile);
		}

		$handle=fopen($csv_name,'rb');

		$del=',';
		$csv_field_titles=fgetcsv($handle,1000,$del);
		if ((count($csv_field_titles)==1) && (strpos($csv_field_titles[0],';')!==false))
		{
			$del=';';
			rewind($handle);
			$csv_field_titles=fgetcsv($handle,1000,$del);
		}

		$csv_field_titles=array_flip($csv_field_titles);

		//if(!array_key_exists('CATEGORY',$csv_field_titles)) //Checking the fields title contains 'CATEGORY'.
		//	warn_exit(do_lang_tempcode('FIELDS_UNMATCH'));

		global $LAX_COMCODE;
		$temp2=$LAX_COMCODE;
		$LAX_COMCODE=true;

		if (function_exists('set_time_limit')) @set_time_limit(0);

		//$count=0;
		$root_cat=$GLOBALS['SITE_DB']->query_value_null_ok('catalogue_categories','id',array('cc_parent_id'=>NULL));
		while (($data=fgetcsv($handle,100000,$del))!==false)
		{
			if ($data===array(NULL)) continue; // blank line
			$this->import_csv_lines($catalogue_name,$data,$root_cat,$fields,$categories,$csv_field_titles);
			//$count++;
		}

		$LAX_COMCODE=$temp2;

		$description=is_null($this->do_next_description)?do_lang_tempcode('SUCCESS'):$this->do_next_description;

		$this->donext_catalogue_name=$catalogue_name;

		return $this->do_next_manager($title,$description,NULL);		
	}

	/**
	 * Create an entry-id=>value map of uploaded csv data and it's importing
	 *
	 * @param  ID_TEXT		The name of the catalogue that was used
	 * @param  array			Data array of CSV imported file's lines
	 * @param  ?AUTO_LINK	Catalogue root ID (NULL: Not a tree catalogue)
	 * @param  array			Array of catalogue fields
 	 * @param  array			Array of categories
 	 * @param  array			Array of csv field titles
	 */
	function import_csv_lines($catalogue_name,$csv_data,$catalog_root,$fields,&$categories,$csv_field_titles)
	{
		$map=array();	
		$match_flag=false;

		check_specific_permission('mass_import');

		$curr_cat=array_key_exists('CATEGORY',$csv_field_titles)?$csv_data[$csv_field_titles['CATEGORY']]:'';

		if($curr_cat=='')
		{
			//Checks the general category exists or not
			if(array_key_exists($catalogue_name,$categories))
				$catid=$categories[$catalogue_name];
			else	//If category field is null, record adds to a general category named catalogue name.
			{
				$catalog_title=$GLOBALS['SITE_DB']->query_value_null_ok('catalogues','c_title',array('c_name'=>$catalogue_name));

				$catid=actual_add_catalogue_category($catalogue_name,$catalog_title,$catalog_title,$catalog_title,$catalog_root,'');

				$categories=array_merge(array($catalogue_name=>$catid),$categories);
			}
		}
		elseif(array_key_exists($curr_cat,$categories))
		{	
			$catid=$categories[$curr_cat];
		}
		else
		{	
			$catid=actual_add_catalogue_category($catalogue_name,$curr_cat,$curr_cat,$curr_cat,$catalog_root,'');

			$categories=array_merge(array($curr_cat=>$catid),$categories);

			if (get_value('disable_cat_cat_perms')!=='1')
				$this->set_permissions(strval($catid));					
		}

		foreach ($fields as $field)
		{
			$field_name=get_translated_text($field['cf_name']);

			if(array_key_exists($field_name,$csv_field_titles))
			{
				if (!array_key_exists($csv_field_titles[$field_name],$csv_data)) $csv_data[$csv_field_titles[$field_name]]=''; // Not set for this particular row, even though column exists in the CSV

				$value=trim($csv_data[$csv_field_titles[$field_name]]);

				if (($field['cf_type']=='picture') || ($field['cf_type']=='video'))
				{
					if (preg_replace('#\..*$#','',$value)=='Noimage') $value='';

					if ($value!='')
					{
						if ((strpos($value,'\\')===false) && (strpos($value,'/')===false))
						{
							$value='uploads/catalogues/'.rawurlencode($value);
						}
					}
				} else
				{
					if ((strip_tags($value)!=$value) && (strpos($value,'[html')===false) && (strpos($value,'[semihtml')===false))
						$value='[html]'.$value.'[/html]';
				}

				$map[$field['id']]=$value;
				$match_flag=true; // to check matching of csv and db fields	
			}
			else
			{
				$map[$field['id']]=$field['cf_default'];
			}			
		}

		if ($match_flag)
			$id=actual_add_catalogue_entry($catid,1,'',1,1,1,$map);
		else
			warn_exit(do_lang_tempcode('FIELDS_UNMATCH'));
	}

	/**
	 * The UI to choose a catalogue to export catalogue entries
	 *
	 * @return tempcode		The UI
	 */
	function export_catalogue()
	{
		if (!$GLOBALS['FORUM_DRIVER']->is_super_admin(get_member())) access_denied('I_ERROR');

		$title=get_page_title('CATALOGUE_EXPORT');

		$catalogue_select=$this->choose_catalogue($title);

		if (!is_null($catalogue_select)) return $catalogue_select;

		$catalogue_name=get_param('catalogue_name');
		$this->_export_catalogue($catalogue_name);
		return new ocp_tempcode();
	}

	/**
	 * The actualiser to download a CSV of catalogues.
	 *
	 * @param ID_TEXT			The name of the catalogue
	 */
	function _export_catalogue($catalogue_name)
	{
		$filename=$catalogue_name.'-'.date('Y-m-d').'.csv';

		if (function_exists('set_time_limit')) @set_time_limit(0);

		header('Content-type: text/csv');
		if (strstr(ocp_srv('HTTP_USER_AGENT'),'MSIE')!==false)
			header('Content-Disposition: filename="'.str_replace(chr(13),'',str_replace(chr(10),'',addslashes($filename))).'"');
		else
			header('Content-Disposition: attachment; filename="'.str_replace(chr(13),'',str_replace(chr(10),'',addslashes($filename))).'"');

		@ini_set('ocproducts.xss_detect','0');

		$catalogue_row=$GLOBALS['SITE_DB']->query_select('catalogues',array('*'),array('c_name'=>$catalogue_name),'',NULL,NULL,true);
		if (is_null($catalogue_row)) $catalogue_row=array();
		if (isset($catalogue_row[0])) $catalogue_row=$catalogue_row[0];

		$category_names=array();

		$start=0;
		do
		{
			$entry_rows=$GLOBALS['SITE_DB']->query_select('catalogue_entries',array('*'),array('c_name'=>$catalogue_name),'ORDER BY ce_add_date ASC',4000,$start);

			foreach($entry_rows as $k=>$entry_row)
			{
				if (is_null($entry_row)) $entry_row=array();
				if(isset($entry_row[0])) $entry_row=$entry_row[0];

				$details=get_catalogue_entry_map($entry_row,$catalogue_row,'PAGE','DEFAULT',NULL);

				$better_results=array();
				foreach ($details as $key=>$val)
				{
					if (substr($key,0,10)=='FIELDNAME_')
					{
						$value=$details['FIELD_'.substr($key,10).'_PLAIN'];
						if(is_object($value))
							$value=$value->evaluate();
						$better_results[$val]=$value;
					}
				}

				if ($k==0)
				{
					echo 'CATEGORY';
					foreach (array_keys($better_results) as $k2)
					{
						echo ',';
						echo '"'.str_replace('"','""',$k2).'"';
					}
					echo chr(10);
				}
				if (!isset($category_names[$entry_row['cc_id']]))
				{
					if (!array_key_exists($entry_row['cc_id'],$category_names))
						$category_names[$entry_row['cc_id']]=get_translated_text($GLOBALS['SITE_DB']->query_value('catalogue_categories','cc_title',array('id'=>$entry_row['cc_id'])));
				}
				echo '"'.str_replace('"','""',$category_names[$entry_row['cc_id']]).'"';
				foreach ($better_results as $v)
				{
					echo ',';
					echo '"'.str_replace('"','""',$v).'"';
				}
				echo chr(10);
			}

			$start+=4000;
		}
		while (count($entry_rows)!=0);
		$GLOBALS['SCREEN_TEMPLATE_CALLED']='';
		exit();
	}
}

/**
 * Module page class.
 */
class Module_cms_catalogues_cat extends standard_aed_module
{
	var $lang_type='CATALOGUE_CATEGORY';
	var $select_name='NAME';
	var $permissions_require='cat_mid';
	var $permission_module='catalogues_category';
	var $permissions_cat_require='catalogues_catalogue';
	var $permissions_cat_name='catalogue_name';
	var $seo_type='catalogue_category';
	var $catalogue=true;
	var $award_type='catalogue_category';
	var $upload='image';
	var $javascript='if (document.getElementById(\'move_days_lower\')) { var mt=document.getElementById(\'move_target\'); var form=mt.form; var crf=function() { var s=mt.selectedIndex==0; form.elements[\'move_days_lower\'].disabled=s; form.elements[\'move_days_higher\'].disabled=s; }; crf(); mt.onclick=crf; }';
	var $menu_label='CATALOGUES';
	var $table='catalogue_categories';
	var $title_is_multi_lang=false;
	var $orderer='cc_title';

	var $donext_catalogue_name;

	/**
	 * Standard aed_module table function.
	 *
	 * @param  array			Details to go to build_url for link to the next screen.
	 * @return array			A quartet: The choose table, Whether re-ordering is supported from this screen, Search URL, Archive URL.
	 */
	function nice_get_choose_table($url_map)
	{
		require_code('templates_results_table');

		$current_ordering=get_param('sort','cc_title ASC');
		if (strpos($current_ordering,' ')===false) warn_exit(do_lang_tempcode('INTERNAL_ERROR'));
		list($sortable,$sort_order)=explode(' ',$current_ordering,2);
		$sortables=array(
			'cc_title'=>do_lang_tempcode('TITLE'),
			'cc_add_date'=>do_lang_tempcode('_ADDED'),
		);
		if (((strtoupper($sort_order)!='ASC') && (strtoupper($sort_order)!='DESC')) || (!array_key_exists($sortable,$sortables)))
			log_hack_attack_and_exit('ORDERBY_HACK');
		global $NON_CANONICAL_PARAMS;
		$NON_CANONICAL_PARAMS[]='sort';

		$fh=array(do_lang_tempcode('TITLE'),do_lang_tempcode('_ADDED'));
		$fh[]=do_lang_tempcode('ACTIONS');
		$header_row=results_field_title($fh,$sortables,'sort',$sortable.' '.$sort_order);

		$fields=new ocp_tempcode();

		$catalogue_name=get_param('catalogue_name');

		require_code('form_templates');
		list($rows,$max_rows)=$this->get_entry_rows(false,$current_ordering,array('c_name'=>$catalogue_name));
		$news_cat_titles=array();
		foreach ($rows as $row)
		{
			$edit_link=build_url($url_map+array('id'=>$row['id']),'_SELF');

			$fr=array();
			$fr[]=protect_from_escaping(hyperlink(build_url(array('page'=>'catalogues','type'=>'category','id'=>$row['id']),get_module_zone('catalogues')),get_translated_text($row['cc_title'])));
			$fr[]=get_timezoned_date($row['cc_add_date']);
			$fr[]=protect_from_escaping(hyperlink($edit_link,do_lang_tempcode('EDIT'),false,true,'#'.strval($row['id'])));

			$fields->attach(results_entry($fr,true));
		}

		$search_url=build_url(array('page'=>'search','id'=>'catalogue_categories'),get_module_zone('search'));
		$archive_url=build_url(array('page'=>'catalogues','type'=>'index','id'=>$catalogue_name),get_module_zone('catalogues'));

		return array(results_table(do_lang($this->menu_label),get_param_integer('start',0),'start',get_param_integer('max',20),'max',$max_rows,$header_row,$fields,$sortables,$sortable,$sort_order),false,$search_url,$archive_url);
	}

	/**
	 * Standard aed_module list function.
	 *
	 * @return ?array				A triple: The tree field (tempcode), Search URL, Archive URL (NULL: nothing here)
	 */
	function nice_get_ajax_tree()
	{
		$catalogue_name=get_param('catalogue_name');

		$is_tree=$GLOBALS['SITE_DB']->query_value('catalogues','c_is_tree',array('c_name'=>$catalogue_name));
		if ($is_tree==0) return NULL;

		$search_url=build_url(array('page'=>'search','id'=>'catalogue_categories','catalogue_name'=>$catalogue_name),get_module_zone('search'));
		$archive_url=build_url(array('page'=>'catalogues','type'=>'index','id'=>$catalogue_name),get_module_zone('catalogues'));

		$tree=form_input_tree_list(do_lang_tempcode('CODENAME'),'','id',NULL,'choose_catalogue_category',array('catalogue_name'=>$catalogue_name),true);
		return array($tree,$search_url,$archive_url);
	}

	/**
	 * Get tempcode for a catalogue category adding/editing form.
	 *
	 * @param  ?ID_TEXT		The name of the catalogue the category is in (NULL: detect)
	 * @param  SHORT_TEXT	The title of the category
	 * @param  LONG_TEXT		Description for the category
	 * @param  LONG_TEXT		Admin notes
	 * @param  ?AUTO_LINK	The ID of the parent category (NULL: no parent) (-1: arbitrary default)
	 * @param  ?AUTO_LINK	The ID of this category (NULL: we're adding, not editing)
	 * @param  URLPATH		The rep-image for the catalogue category
	 * @param  integer		The number of days before expiry (lower limit)
	 * @param  integer		The number of days before expiry (higher limit)
	 * @param  ?AUTO_LINK	The expiry category (NULL: do not expire)
	 * @return array			A pair: the tempcode for the visible fields, and the tempcode for the hidden fields
	 */
	function get_form_fields($catalogue_name=NULL,$title='',$description='',$notes='',$parent_id=-1,$id=NULL,$rep_image='',$move_days_lower=30,$move_days_higher=60,$move_target=NULL) // Not the fields in a category (no such thing: fields are in catalogues) - the HTML form fields to input the details for a category
	{
		if (is_null($catalogue_name)) $catalogue_name=get_param('catalogue_name',is_null($id)?false:$GLOBALS['SITE_DB']->query_value('catalogues_categories','c_name',array('id'=>$id)));

		if ($parent_id==-1)
		{
			global $NON_CANONICAL_PARAMS;
			$NON_CANONICAL_PARAMS[]='parent_id';
			$NON_CANONICAL_PARAMS[]='title';
			$NON_CANONICAL_PARAMS[]='notes';

			$parent_id=get_param_integer('parent_id',-1);

			$title=get_param('title',$title);
			$notes=get_param('notes',$notes);
		}

		$fields=new ocp_tempcode();
		require_code('form_templates');
		$hidden=new ocp_tempcode();
		$hidden->attach(form_input_hidden('catalogue_name',$catalogue_name));
		$fields->attach(form_input_line(do_lang_tempcode('TITLE'),do_lang_tempcode('DESCRIPTION_TITLE'),'title',$title,true));
		$fields->attach(form_input_text_comcode(do_lang_tempcode('DESCRIPTION'),do_lang_tempcode('DESCRIPTION_DESCRIPTION'),'description',$description,false));
		if (get_value('disable_staff_notes')!=='1')
			$fields->attach(form_input_text(do_lang_tempcode('NOTES'),do_lang_tempcode('DESCRIPTION_NOTES'),'notes',$notes,false));
		handle_max_file_size($hidden,'image');
		$fields->attach(form_input_upload(do_lang_tempcode('REPRESENTATIVE_IMAGE'),do_lang_tempcode('DESCRIPTION_REPRESENTATIVE_IMAGE'),'rep_image',false,$rep_image,NULL,true,str_replace(' ','',get_option('valid_images'))));

		// Is the catalogue a tree?
		$is_tree=$GLOBALS['SITE_DB']->query_value_null_ok('catalogues','c_is_tree',array('c_name'=>$catalogue_name));
		if (is_null($is_tree)) warn_exit(do_lang_tempcode('MISSING_RESOURCE'));
		if (($is_tree==1) && (!is_null($parent_id)))
		{
			$fields->attach(form_input_tree_list(do_lang_tempcode('PARENT'),do_lang_tempcode('DESCRIPTION_PARENT'),'parent_id',NULL,'choose_catalogue_category',array('catalogue_name'=>$catalogue_name),true,((is_null($parent_id)) || ($parent_id==-1))?'':strval($parent_id)));
		}

		$fields->attach(do_template('FORM_SCREEN_FIELD_SPACER',array('SECTION_HIDDEN'=>is_null($move_target),'TITLE'=>do_lang_tempcode('CLASSIFIED_ADS'))));
		$list=new ocp_tempcode();
		$fields->attach(form_input_tree_list(do_lang_tempcode('EXPIRY_MOVE_TARGET'),do_lang_tempcode('DESCRIPTION_EXPIRY_MOVE_TARGET'),'move_target',NULL,'choose_catalogue_category',array('catalogue_name'=>$catalogue_name),false,is_null($move_target)?NULL:strval($move_target)));
		if (cron_installed())
		{
			$fields->attach(form_input_integer(do_lang_tempcode('EXPIRY_MOVE_DAYS_LOWER'),do_lang_tempcode('DESCRIPTION_EXPIRY_MOVE_DAYS_LOWER'),'move_days_lower',$move_days_lower,true));
			$fields->attach(form_input_integer(do_lang_tempcode('EXPIRY_MOVE_DAYS_HIGHER'),do_lang_tempcode('DESCRIPTION_EXPIRY_MOVE_DAYS_HIGHER'),'move_days_higher',$move_days_higher,true));
		}

		// Permissions
		if (get_value('disable_cat_cat_perms')!=='1')
			$fields->attach($this->get_permission_fields(is_null($id)?'':strval($id),NULL,is_null($id)));

		return array($fields,$hidden);
	}

	/**
	 * Standard aed_module cat getter.
	 *
	 * @param  AUTO_LINK		The entry for which the cat is sought
	 * @return string			The cat
	 */
	function get_cat($id)
	{
		return $GLOBALS['SITE_DB']->query_value('catalogue_categories','c_name',array('id'=>$id));
	}

	/**
	 * Standard aed_module edit form filler.
	 *
	 * @param  ID_TEXT		The entry being edited
	 * @return array			A tuple of lots of info
	 */
	function fill_in_edit_form($_id)
	{
		$category_id=intval($_id);

		$catalogue_name=get_param('catalogue_name',$GLOBALS['SITE_DB']->query_value('catalogue_categories','c_name',array('id'=>$category_id)));
		//$this->edit_text=paragraph(do_lang_tempcode('FOR_CATALOGUE',escape_html($catalogue_name)));

		$rows=$GLOBALS['SITE_DB']->query_select('catalogue_categories',array('*'),array('id'=>$category_id),'',1);
		if (!array_key_exists(0,$rows))
		{
			warn_exit(do_lang_tempcode('MISSING_RESOURCE'));
		}
		$myrow=$rows[0];

		return $this->get_form_fields($catalogue_name,get_translated_text($myrow['cc_title']),get_translated_text($myrow['cc_description']),$myrow['cc_notes'],$myrow['cc_parent_id'],$category_id,$myrow['rep_image'],$myrow['cc_move_days_lower'],$myrow['cc_move_days_higher'],$myrow['cc_move_target']);
	}

	/**
	 * Standard aed_module delete possibility checker.
	 *
	 * @param  ID_TEXT		The entry being potentially deleted
	 * @return boolean		Whether it may be deleted
	 */
	function may_delete_this($id)
	{
		$cat=$GLOBALS['SITE_DB']->query_select('catalogue_categories cc LEFT JOIN '.get_table_prefix().'catalogues c ON c.c_name=cc.c_name',array('cc_parent_id','c_is_tree'),array('id'=>intval($id)),'',1);
		if (!array_key_exists(0,$cat)) return true;
		return ($cat[0]['c_is_tree']==0) || (!is_null($cat[0]['cc_parent_id']));
	}

	/**
	 * Standard aed_module add actualiser.
	 *
	 * @return AUTO_LINK		The ID of what was added
	 */
	function add_actualisation()
	{
		require_code('catalogues2');

		$catalogue_name=post_param('catalogue_name');

		$title=post_param('title');
		$description=post_param('description');
		$notes=post_param('notes','');
		$parent_id=post_param_integer('parent_id',-1);
		if ($parent_id==-1) $parent_id=NULL;
		$urls=get_url('image_url','rep_image','uploads/grepimages',0,OCP_UPLOAD_IMAGE);
		$rep_image=$urls[0];

		$move_days_lower=post_param_integer('move_days_lower',30);
		$move_days_higher=post_param_integer('move_days_higher',60);
		$move_target=post_param_integer('move_target',-1);
		if ($move_target==-1) $move_target=NULL;
		if (!is_null($move_target))
		{
			if (!has_submit_permission('mid',get_member(),get_ip_address(),'cms_catalogues',array('catalogues_catalogue',$catalogue_name,'catalogues_category',$move_target)))
				access_denied('CATEGORY_ACCESS');
		}

		$category_id=actual_add_catalogue_category($catalogue_name,$title,$description,$notes,$parent_id,$rep_image,$move_days_lower,$move_days_higher,$move_target);
		if (get_value('disable_cat_cat_perms')!=='1')
			$this->set_permissions(strval($category_id));

		$this->donext_category_id=$category_id;
		$this->donext_catalogue_name=$catalogue_name;

		return $category_id;
	}

	/**
	 * Standard aed_module edit actualiser.
	 *
	 * @param  ID_TEXT		The entry being edited
	 */
	function edit_actualisation($_id)
	{
		require_code('catalogues2');

		$category_id=intval($_id);

		$catalogue_name=$GLOBALS['SITE_DB']->query_value_null_ok('catalogue_categories','c_name',array('id'=>$category_id));
		if (is_null($catalogue_name)) warn_exit(do_lang_tempcode('MISSING_RESOURCE'));

		$title=post_param('title');
		$description=post_param('description',STRING_MAGIC_NULL);
		$notes=post_param('notes',STRING_MAGIC_NULL);
		$parent_id=post_param_integer('parent_id',INTEGER_MAGIC_NULL);

		$move_days_lower=post_param_integer('move_days_lower',INTEGER_MAGIC_NULL);
		$move_days_higher=post_param_integer('move_days_higher',INTEGER_MAGIC_NULL);
		$move_target=post_param_integer('move_target',INTEGER_MAGIC_NULL);
		if ($move_target==-1) $move_target=NULL;
		if (!is_null($move_target))
		{
			if (!has_submit_permission('mid',get_member(),get_ip_address(),'cms_catalogues',array('catalogues_catalogue',$catalogue_name,'catalogues_category',$move_target)))
				access_denied('CATEGORY_ACCESS');
		}

		if (!fractional_edit())
		{
			$urls=get_url('image_url','rep_image','uploads/grepimages',0,OCP_UPLOAD_IMAGE);
			$rep_image=$urls[0];
			if (($rep_image=='') && (post_param_integer('rep_image_unlink',0)!=1)) $rep_image=NULL;
		} else $rep_image=STRING_MAGIC_NULL;

		actual_edit_catalogue_category($category_id,$title,$description,$notes,$parent_id,post_param('meta_keywords',STRING_MAGIC_NULL),post_param('meta_description',STRING_MAGIC_NULL),$rep_image,$move_days_lower,$move_days_higher,$move_target);
		if (!fractional_edit())
		{
			if (get_value('disable_cat_cat_perms')!=='1')
				$this->set_permissions(strval($category_id));
		}

		$this->donext_category_id=$category_id;
		$this->donext_catalogue_name=$catalogue_name;
	}

	/**
	 * Standard aed_module delete actualiser.
	 *
	 * @param  ID_TEXT		The entry being deleted
	 */
	function delete_actualisation($id)
	{
		require_code('catalogues2');

		actual_delete_catalogue_category(intval($id));

		$catalogue_name=$GLOBALS['SITE_DB']->query_value_null_ok('catalogue_categories','c_name',array('id'=>$id));
		if (is_null($catalogue_name)) warn_exit(do_lang_tempcode('MISSING_RESOURCE'));

		$this->donext_catalogue_name=$catalogue_name;
	}

	/**
	 * The do-next manager for after catalogue content management.
	 *
	 * @param  tempcode		The title (output of get_page_title)
	 * @param  tempcode		Some description to show, saying what happened
	 * @param  ?AUTO_LINK	The ID of whatever catalogue category was just handled (NULL: deleted)
	 * @return tempcode		The UI
	 */
	function do_next_manager($title,$description,$id)
	{
		$catalogue_name=$this->donext_catalogue_name;

		breadcrumb_set_self(do_lang_tempcode('DONE'));

		require_code('templates_donext');
		return do_next_manager($title,$description,
					NULL,
					NULL,
					/*		TYPED-ORDERED LIST OF 'LINKS'		*/
					/*	 page	 params				  zone	  */
					(!is_null($id))?NULL:array('_SELF',array('type'=>'add_entry','catalogue_name'=>$catalogue_name),'_SELF'),// Add one
					NULL,																						// Edit this
					has_specific_permission(get_member(),'edit_own_midrange_content','cms_catalogues')?array('_SELF',array('type'=>'edit_entry','catalogue_name'=>$catalogue_name),'_SELF'):NULL,  // Edit one
					NULL,																						// View this
					NULL,																						// View archive
					is_null($id)?NULL:array('_SELF',array('type'=>'add_entry','category_id'=>$id,'catalogue_name'=>$catalogue_name),'_SELF'),// Add to category
					has_specific_permission(get_member(),'submit_cat_midrange_content','cms_catalogues')?array('_SELF',array('type'=>'add_category','catalogue_name'=>$catalogue_name),'_SELF'):NULL, // Add one category
					has_specific_permission(get_member(),'edit_own_cat_midrange_content','cms_catalogues')?array('_SELF',array('type'=>'edit_category','catalogue_name'=>$catalogue_name),'_SELF'):NULL, // Edit one category
					(is_null($id) || (!has_specific_permission(get_member(),'edit_own_cat_midrange_content','cms_catalogues')))?NULL:array('_SELF',array('type'=>'_edit_category','id'=>$id,'catalogue_name'=>$catalogue_name),'_SELF'), // Edit this category
					is_null($id)?NULL:array('catalogues',array('type'=>'category','id'=>$id),get_module_zone('catalogues')),// View this category

					/*	  SPECIALLY TYPED 'LINKS'				  */
					array(),array(),
					array(
						/*	 type							  page	 params													 zone	  */
						has_specific_permission(get_member(),'submit_cat_highrange_content','cms_catalogues')?array('add_one_catalogue',array('_SELF',array('type'=>'add_catalogue'),'_SELF')):NULL,
						has_specific_permission(get_member(),'edit_own_cat_highrange_content','cms_catalogues')?array('edit_this_catalogue',array('_SELF',array('type'=>'_edit_catalogue','id'=>$catalogue_name),'_SELF')):NULL,
						has_specific_permission(get_member(),'edit_own_cat_highrange_content','cms_catalogues')?array('edit_one_catalogue',array('_SELF',array('type'=>'edit_catalogue'),'_SELF')):NULL,
						array('view_this',array('catalogues',array('type'=>'index','id'=>$catalogue_name),get_module_zone('catalogues')),do_lang('INDEX'))
					),
					do_lang('MANAGE_CATALOGUES')
		);
	}

}

/**
 * Module page class.
 */
class Module_cms_catalogues_alt extends standard_aed_module
{
	var $lang_type='CATALOGUE';
	var $select_name='CATALOGUE';
	var $select_name_description='DESCRIPTION_CATALOGUE';
	var $permissions_require='cat_high';
	var $permission_module='catalogues_catalogue';
	var $non_integer_id=true;
	var $award_type='catalogue';
	var $is_tree_catalogue=false; // Set for usage by do-next-manager
	var $menu_label='CATALOGUES';
	var $table='catalogue_entries';
	var $javascript="var fn=document.getElementById('title'); if (fn) { var form=fn.form; fn.onchange=function() { if ((form.elements['name']) && (form.elements['name'].value=='')) form.elements['name'].value=fn.value.toLowerCase().replace(/[^\w\d\.\-]/g,'_').replace(/\_+\$/,''); }; }";

	/**
	 * Standard aed_module list function.
	 *
	 * @return tempcode		The selection list
	 */
	function nice_get_entries()
	{
		return nice_get_catalogues();
	}

	/**
	 * Get tempcode for a catalogue adding/editing form.
	 *
	 * @param  ID_TEXT			The name of the catalogue
	 * @param  SHORT_TEXT		The human readable name/title of the catalogue
	 * @param  LONG_TEXT			The description
	 * @param  SHORT_INTEGER	The display type
	 * @param  BINARY				Whether the catalogue uses a hierarchy
	 * @param  LONG_TEXT			Admin notes
	 * @param  integer			How many points are given to a member that submits to the catalogue
	 * @param  BINARY				Whether the catalogue is an eCommerce catalogue
	 * @param  ID_TEXT			How to send view reports
	 * @set    never daily weekly monthly quarterly
	 * @return array				A tuple: the tempcode for the visible fields, and the tempcode for the hidden fields, ..., and action fields
	 */
	function get_form_fields($name='',$title='',$description='',$display_type=0,$is_tree=1,$notes='',$submit_points=0,$ecommerce=0,$send_view_reports='never')
	{
		$fields=new ocp_tempcode();
		$hidden=new ocp_tempcode();
		require_code('form_templates');

		if ($name=='') $name=get_param('id','');
		$tied_to_content_type=(substr($name,0,1)=='_') && ((file_exists(get_file_base().'/sources_custom/hooks/systems/awards/'.substr($name,1).'.php')) || (file_exists(get_file_base().'/sources/hooks/systems/awards/'.substr($name,1).'.php')));
		if ($tied_to_content_type)
		{
			$content_type=substr($name,1);

			require_code('hooks/systems/awards/'.$content_type);
			$ob=object_factory('Hook_awards_'.$content_type);
			$info=$ob->info();

			$title=do_lang('CUSTOM_FIELDS_FOR',$info['title']->evaluate());

			$hidden->attach(form_input_hidden('title',$title));
			$hidden->attach(form_input_hidden('name',$name));
			$hidden->attach(form_input_hidden('description',''));
			$hidden->attach(form_input_hidden('notes',''));
			$hidden->attach(form_input_hidden('auto_fill',''));
			$hidden->attach(form_input_hidden('display_type','0'));
			$hidden->attach(form_input_hidden('submit_points','0'));
			$hidden->attach(form_input_hidden('send_view_reports','never'));

			attach_message(do_lang_tempcode('EDITING_CUSTOM_FIELDS_HELP',$info['title']));

			$actions=new ocp_tempcode();
		} else
		{
			$fields->attach(form_input_line(do_lang_tempcode('TITLE'),do_lang_tempcode('DESCRIPTION_TITLE'),'title',$title,true));
			$fields->attach(form_input_codename(do_lang_tempcode('CODENAME'),do_lang_tempcode('DESCRIPTION_CODENAME'),'name',$name,true));
			$fields->attach(form_input_text_comcode(do_lang_tempcode('DESCRIPTION'),do_lang_tempcode('DESCRIPTION_CATALOGUE_DESCRIPTION'),'description',$description,false));

			$display_types=new ocp_tempcode();
			$display_types->attach(form_input_list_entry(strval(0),$display_type==0,do_lang_tempcode('DT_MAPS')));
			$display_types->attach(form_input_list_entry(strval(1),$display_type==1,do_lang_tempcode('DT_LIST')));
			$display_types->attach(form_input_list_entry(strval(2),$display_type==2,do_lang_tempcode('DT_MATRIX')));
			$fields->attach(form_input_list(do_lang_tempcode('DISPLAY_TYPE'),do_lang_tempcode('DESCRIPTION_DISPLAY_TYPE'),'display_type',$display_types));

			if (addon_installed('shopping'))
			{
				if ($ecommerce==1)
				{
					if (get_forum_type()!='ocf') warn_exit(do_lang_tempcode('NO_OCF'));
				}

				$fields->attach(form_input_tick(do_lang_tempcode('CAT_ECOMMERCE'),do_lang_tempcode('DESCRIPTION_CAT_ECOMMERCE'),'ecommerce',$ecommerce==1));
			}
			$fields->attach(form_input_tick(do_lang_tempcode('IS_TREE'),do_lang_tempcode('DESCRIPTION_IS_TREE'),'is_tree',$is_tree==1));
			if ($name=='') $fields->attach(form_input_line(do_lang_tempcode('AUTO_FILL'),do_lang_tempcode('DESCRIPTION_AUTO_FILL'),'auto_fill','',false,NULL,10000));

			$fields->attach(do_template('FORM_SCREEN_FIELD_SPACER',array('SECTION_HIDDEN'=>$notes=='' && $submit_points==0 && $send_view_reports=='never','TITLE'=>do_lang_tempcode('ADVANCED'))));

			if (get_value('disable_staff_notes')!=='1')
				$fields->attach(form_input_text(do_lang_tempcode('NOTES'),do_lang_tempcode('DESCRIPTION_NOTES'),'notes',$notes,false));
			if (addon_installed('points'))
			{
				$fields->attach(form_input_integer(do_lang_tempcode('SUBMIT_POINTS'),do_lang_tempcode('DESCRIPTION_SUBMIT_POINTS'),'submit_points',$submit_points,false));
			}

			$view_report_types=new ocp_tempcode();
			$view_report_types->attach(form_input_list_entry('never',$send_view_reports=='never',do_lang_tempcode('VR_NEVER')));
			$view_report_types->attach(form_input_list_entry('daily',$send_view_reports=='daily',do_lang_tempcode('VR_DAILY')));
			$view_report_types->attach(form_input_list_entry('weekly',$send_view_reports=='weekly',do_lang_tempcode('VR_WEEKLY')));
			$view_report_types->attach(form_input_list_entry('monthly',$send_view_reports=='monthly',do_lang_tempcode('VR_MONTHLY')));
			$view_report_types->attach(form_input_list_entry('quarterly',$send_view_reports=='quarterly',do_lang_tempcode('VR_QUARTERLY')));
			$fields->attach(form_input_list(do_lang_tempcode('VIEW_REPORTS'),do_lang_tempcode('DESCRIPTION_VIEW_REPORTS'),'send_view_reports',$view_report_types));

			// Permissions
			$fields->attach($this->get_permission_fields($name,NULL,($name=='')));

			$actions=new ocp_tempcode();
			if (($name!='') && (get_value('disable_cat_cat_perms')!=='1'))
				$actions->attach(form_input_tick(do_lang_tempcode('RESET_CATEGORY_PERMISSIONS'),do_lang_tempcode('DESCRIPTION_RESET_CATEGORY_PERMISSIONS'),'reset_category_permissions',false));
			if ($name=='')
				$actions->attach(form_input_tick(do_lang_tempcode('ADD_TO_MENU'),do_lang_tempcode('DESCRIPTION_ADD_TO_MENU'),'add_to_menu',true));
		}

		return array($fields,$hidden,NULL,NULL,false,NULL,$actions);
	}

	/**
	 * Get tempcode for a catalogue field adding/editing form (many of these are put together to add/edit a single catalogue!).
	 *
	 * @param  boolean		Whether this is the first field of the entry fields
	 * @param  integer		The number of fields that will be on the screen
	 * @param  string			The prefix the field input fields are given (e.g. new1_)
	 * @param  integer		The order of the field relative to the other fields
	 * @param  SHORT_TEXT	The name of the field
	 * @param  LONG_TEXT		Description for the field
	 * @param  ID_TEXT		The field type
	 * @param  BINARY			Whether the field defines entry ordering
	 * @param  BINARY			Whether the field is searchable
	 * @param  BINARY			Whether the field is visible when an entry is viewed
	 * @param  SHORT_TEXT	Default value for the field
	 * @param  BINARY			Whether the field is required
	 * @param  BINARY			Whether the field is to be shown in category views (not applicable for the list display type)
	 * @param  BINARY			Whether the field is to be shown in search views (not applicable for the list display type)
	 * @return array			A pair: the tempcode for the visible fields, and the tempcode for the hidden fields
	 */
	function get_field_fields($first_field,$num_fields_to_show,$prefix,$order,$name='',$description='',$type='short_text',$defines_order=0,$visible=1,$searchable=1,$default='',$required=0,$put_in_category=1,$put_in_search=1)
	{
		$fields=new ocp_tempcode();
		$hidden=new ocp_tempcode();

		require_code('form_templates');
		$fields->attach(form_input_line(do_lang_tempcode('NAME'),do_lang_tempcode('DESCRIPTION_FIELD_NAME'),$prefix.'name',$name,($name!='') || $first_field)); // If this is gonna be a new field that might not be filled in, don't make them fill it in
		$fields->attach(form_input_line(do_lang_tempcode('DESCRIPTION'),do_lang_tempcode('DESCRIPTION_FIELD_DESCRIPTION'),$prefix.'description',$description,false));
		$fields->attach(form_input_line(do_lang_tempcode('DEFAULT_VALUE'),do_lang_tempcode('DESCRIPTION_FIELD_DEFAULT'),$prefix.'default',$default,false,NULL,10000));

		require_code('fields');
		require_lang('fields');

		$type_list=nice_get_field_type($type,$name!='');

		$fields->attach(form_input_list(do_lang_tempcode('TYPE'),do_lang_tempcode(($name=='')?'DESCRIPTION_FIELD_TYPE_FIRST_TIME':'DESCRIPTION_FIELD_TYPE'),$prefix.'type',$type_list));
		$order_list=new ocp_tempcode();
		for ($i=0;$i<$num_fields_to_show;$i++)
		{
			$order_list->attach(form_input_list_entry(strval($i),$i==$order,integer_format($i+1).(($i==0 && substr(get_param('id',''),0,1)!='_')?do_lang('NEW_FIELD_TITLE'):'')));
		}
		$fields->attach(form_input_list(do_lang_tempcode('ORDER'),do_lang_tempcode('DESCRIPTION_FIELD_ORDER_CLEVER'),$prefix.'order',$order_list));

		// Defines order?
		$radios=form_input_radio_entry($prefix.'defines_order','0',$defines_order==0,do_lang_tempcode('NO'));
		$radios->attach(form_input_radio_entry($prefix.'defines_order','1',$defines_order==1,do_lang_tempcode('ASCENDING')));
		$radios->attach(form_input_radio_entry($prefix.'defines_order','2',$defines_order==2,do_lang_tempcode('DESCENDING')));
		$fields->attach(form_input_radio(do_lang_tempcode('DEFINES_ORDER'),do_lang_tempcode('DESCRIPTION_DEFINES_ORDER'),$prefix.'defines_order',$radios));

		if ($first_field)
		{
			$hidden->attach(form_input_hidden($prefix.'visible','1'));
			$hidden->attach(form_input_hidden($prefix.'required','1'));
		} else
		{
			$fields->attach(form_input_tick(do_lang_tempcode('VISIBLE'),do_lang_tempcode('DESCRIPTION_VISIBLE'),$prefix.'visible',$visible==1));
			$fields->attach(form_input_tick(do_lang_tempcode('REQUIRED'),do_lang_tempcode('DESCRIPTION_REQUIRED'),$prefix.'required',$required==1));
		}
		$fields->attach(form_input_tick(do_lang_tempcode('SEARCHABLE'),do_lang_tempcode('DESCRIPTION_SEARCHABLE'),$prefix.'searchable',$searchable==1));
		$fields->attach(form_input_tick(do_lang_tempcode('PUT_IN_CATEGORY'),do_lang_tempcode('DESCRIPTION_PUT_IN_CATEGORY'),$prefix.'put_in_category',$put_in_category==1));
		$fields->attach(form_input_tick(do_lang_tempcode('PUT_IN_SEARCH'),do_lang_tempcode('DESCRIPTION_PUT_IN_SEARCH'),$prefix.'put_in_search',$put_in_search==1));

		return array($fields,$hidden);
	}

	/**
	 * Standard aed_module edit form filler.
	 *
	 * @param  ID_TEXT		The entry being edited
	 * @return tempcode		The edit form
	 */
	function fill_in_edit_form($catalogue_name)
	{
		$rows=$GLOBALS['SITE_DB']->query_select('catalogues',array('*'),array('c_name'=>$catalogue_name),'',1);
		if (!array_key_exists(0,$rows))
		{
			warn_exit(do_lang_tempcode('MISSING_RESOURCE'));
		}
		$myrow=$rows[0];

		$title=get_translated_text($myrow['c_title']);
		$description=get_translated_text($myrow['c_description']);

		return $this->get_form_fields($catalogue_name,$title,$description,$myrow['c_display_type'],$myrow['c_is_tree'],$myrow['c_notes'],$myrow['c_submit_points'],$myrow['c_ecommerce'],$myrow['c_send_view_reports']);
	}

	/**
	 * Standard aed_module add actualiser.
	 *
	 * @return ID_TEXT		The entry added
	 */
	function add_actualisation()
	{
		require_code('catalogues2');
		$name=post_param('name');
		$title=post_param('title');
		$description=post_param('description');
		$display_type=post_param_integer('display_type');
		$is_tree=post_param_integer('is_tree',0);
		$this->is_tree_catalogue=($is_tree==1);
		$notes=post_param('notes','');
		$submit_points=post_param_integer('submit_points',0);
		$cat_tab=post_param_integer('cat_tab',0);
		$ecommerce=post_param_integer('ecommerce',0);
		$send_view_reports=post_param('send_view_reports');

		// What fields do we have?
		$new=array();
		foreach ($_POST as $key=>$val)
		{
			if ((!is_string($val)) && (!is_integer($val))) continue;

			if (get_magic_quotes_gpc()) $val=stripslashes($val);

			$matches=array();
			if (preg_match('#new_field_(\d*)_(.*)#A',$key,$matches)!=0)
			{
				$new[$matches[1]][$matches[2]]=$val;
			}
		}

		$num_fields=0;
		foreach ($new as $field)
		{
			if ($field['name']!='') $num_fields++;
		}
		if ($num_fields==0) warn_exit(do_lang_tempcode('NO_FIELDS'));

		$category_id=actual_add_catalogue($name,$title,$description,$display_type,$is_tree,$notes,$submit_points,$ecommerce,$send_view_reports);
		$this->set_permissions($name);
		if (!is_null($category_id)) $GLOBALS['MODULE_CMS_CATALOGUES']->cat_aed_module->set_permissions(strval($category_id));

		// Now onto the fields
		foreach ($new as $field)
		{
			if (!array_key_exists('default',$field)) warn_exit(do_lang_tempcode('IMPROPERLY_FILLED_IN'));
			if (!array_key_exists('description',$field)) warn_exit(do_lang_tempcode('IMPROPERLY_FILLED_IN'));
			if (!array_key_exists('name',$field)) warn_exit(do_lang_tempcode('IMPROPERLY_FILLED_IN'));
			if (!array_key_exists('order',$field)) warn_exit(do_lang_tempcode('IMPROPERLY_FILLED_IN'));
			if ((!array_key_exists('type',$field)) || ($field['type']=='')) warn_exit(do_lang_tempcode('IMPROPERLY_FILLED_IN'));

			if ($field['order']=='') $field['order']=0; else $field['order']=intval($field['order']);
			$defines_order=array_key_exists('defines_order',$field)?intval($field['defines_order']):0;
			$visible=array_key_exists('visible',$field)?intval($field['visible']):0;
			$searchable=array_key_exists('searchable',$field)?intval($field['searchable']):0;
			$required=array_key_exists('required',$field)?intval($field['required']):0;
			$put_in_category=array_key_exists('put_in_category',$field)?intval($field['put_in_category']):0;
			$put_in_search=array_key_exists('put_in_search',$field)?intval($field['put_in_search']):0;
			if ($field['name']!='') actual_add_catalogue_field($name,$field['name'],$field['description'],$field['type'],$field['order'],$defines_order,$visible,$searchable,$field['default'],$required,$put_in_category,$put_in_search);
		}

		$add_to_menu=post_param_integer('add_to_menu',0);
		if ($add_to_menu==1)
		{
			require_code('menus2');
			if ($is_tree==1)
			{
				add_menu_item_simple('main_content',NULL,$title,'_SEARCH:catalogues:type=category:catalogue_name='.$name);
			} else
			{
				add_menu_item_simple('main_content',NULL,$title,'_SEARCH:catalogues:type=index:'.$name);
			}
		}

		// Auto-fill feature
		$auto_fill=post_param('auto_fill');
		if ($auto_fill!='')
		{
			$categories=array();
			if (strpos($auto_fill,'|')===false)
			{
				$to_do=explode(',',$auto_fill);
			} else
			{
				$to_do=explode('|',$auto_fill);
			}
			foreach ($to_do as $doing)
			{
				if (trim($doing)=='') continue;

				$bits=explode('\\',$doing);
				$parent_id=$category_id;
				foreach ($bits as $bit)
				{
					$bit=trim($bit);

					if (array_key_exists($bit,$categories))
					{
						if (!is_null($parent_id)) $parent_id=$categories[$bit];
					} else
					{
						$_parent_id=actual_add_catalogue_category($name,$bit,'','',$parent_id,'');
						if (!is_null($parent_id)) $parent_id=$_parent_id;
						require_code('permissions2');
						if (get_value('disable_cat_cat_perms')!=='1')
							set_category_permissions_from_environment('catalogues_category',strval($parent_id),$this->permission_page);
						$categories[$bit]=$parent_id;
					}
				}
			}
		}

		if (($is_tree==0) && (substr($name,0,1)!='_')) $this->do_next_description=paragraph(do_lang_tempcode('SUGGEST_ADD_CATEGORY_NEXT'));

		return $name;
	}

	/**
	 * Standard aed_module edit actualiser.
	 *
	 * @param  ID_TEXT		The entry being edited
	 */
	function edit_actualisation($old_name)
	{
		require_code('catalogues2');

		$name=post_param('name',$old_name);
		$title=post_param('title',STRING_MAGIC_NULL);
		$description=post_param('description',STRING_MAGIC_NULL);
		$display_type=post_param_integer('display_type',fractional_edit()?INTEGER_MAGIC_NULL:0);
		$notes=post_param('notes',STRING_MAGIC_NULL);
		$submit_points=post_param_integer('submit_points',fractional_edit()?INTEGER_MAGIC_NULL:0);
		$ecommerce=post_param_integer('ecommerce',fractional_edit()?INTEGER_MAGIC_NULL:0);
		$send_view_reports=post_param('send_view_reports');
		if (!fractional_edit())
		{
			if (post_param_integer('reset_category_permissions',0)==1)
			{
				if (function_exists('set_time_limit')) @set_time_limit(0);

				$start=0;
				do
				{
					$rows=$GLOBALS['SITE_DB']->query_select('catalogue_categories',array('id'),array('c_name'=>$name),'',300,$start);
					foreach ($rows as $row)
					{
						$this->set_permissions(strval($row['id']));
					}

					$start+=300;
				}
				while (array_key_exists(0,$rows));
			}
		}

		$was_tree=$GLOBALS['SITE_DB']->query_value_null_ok('catalogues','c_is_tree',array('c_name'=>$old_name));
		if (is_null($was_tree)) warn_exit(do_lang_tempcode('MISSING_RESOURCE'));
		$is_tree=post_param_integer('is_tree',0);

		if (!fractional_edit())
		{
			// What fields do we have?
			$old=array();
			$new=array();
			foreach ($_POST as $key=>$val)
			{
				if (!is_string($val)) continue;

				if (get_magic_quotes_gpc()) $val=stripslashes($val);

				$matches=array();
				if (preg_match('#new\_field\_(\d+)\_(.*)#A',$key,$matches)!=0)
				{
					$new[$matches[1]][$matches[2]]=$val;
				}
				elseif (preg_match('#existing\_field\_(\d+)\_(.*)#A',$key,$matches)!=0)
				{
					$old[$matches[1]][$matches[2]]=$val;
				}
			}
			$num_fields=0;
			foreach ($new as $field)
			{
				if ($field['name']!='') $num_fields++;
			}
			foreach ($old as $field)
			{
				if (!((array_key_exists('delete',$field)) && ($field['delete']=='1'))) $num_fields++;
			}
			if ($num_fields==0) warn_exit(do_lang_tempcode('NO_FIELDS'));
		}

		if (($is_tree==1) && ($was_tree==0))
		{
			catalogue_to_tree($name);
		}
		if (($is_tree==0) && ($was_tree==1))
		{
			catalogue_from_tree($name);
		}
		$this->is_tree_catalogue=($is_tree==1);

		actual_edit_catalogue($old_name,$name,$title,$description,$display_type,$notes,$submit_points,$ecommerce,$send_view_reports);

		$this->new_id=$name;

		if (!fractional_edit())
		{
			// Now onto the fields
			//  First we must rationalise the ordering
			$o=0;
			$orderings=array();
			foreach ($new as $current)
			{
				if (!array_key_exists('default',$current)) warn_exit(do_lang_tempcode('IMPROPERLY_FILLED_IN'));
				if (!array_key_exists('description',$current)) warn_exit(do_lang_tempcode('IMPROPERLY_FILLED_IN'));
				if (!array_key_exists('name',$current)) warn_exit(do_lang_tempcode('IMPROPERLY_FILLED_IN'));
				if (!array_key_exists('order',$current)) warn_exit(do_lang_tempcode('IMPROPERLY_FILLED_IN'));
				if ((!array_key_exists('type',$current)) || ($current['type']=='')) warn_exit(do_lang_tempcode('IMPROPERLY_FILLED_IN'));

				if ($current['name']!='')
				{
					if ((!array_key_exists('order',$current)) || ($current['order']=='')) $current['order']=strval(count($new)+count($old));
					$orderings['new_'.strval($o)]=$current['order'];
				}
				$o++;
			}
			$o=0;
			foreach ($old as $current)
			{
				if (!((array_key_exists('delete',$current)) && ($current['delete']=='1'))) // If not deleting
				{
					if ((!array_key_exists('order',$current)) || ($current['order']=='')) $current['order']=strval(count($new)+count($old));
					$orderings['old_'.strval($o)]=$current['order'];
				}
				$o++;
			}
			asort($orderings);
			//  Now add/edit them
			$o=0;
			foreach ($new as $field)
			{
				$p=0;
				foreach (array_keys($orderings) as $key)
				{
					if ($key=='new_'.strval($o)) $order=$p;
					$p++;
				}
				$defines_order=array_key_exists('defines_order',$field)?intval($field['defines_order']):0;
				$visible=array_key_exists('visible',$field)?intval($field['visible']):0;
				$searchable=array_key_exists('searchable',$field)?intval($field['searchable']):0;
				$required=array_key_exists('required',$field)?intval($field['required']):0;
				$put_in_category=array_key_exists('put_in_category',$field)?intval($field['put_in_category']):0;
				$put_in_search=array_key_exists('put_in_search',$field)?intval($field['put_in_search']):0;
				if ($field['name']!='') actual_add_catalogue_field($name,$field['name'],$field['description'],$field['type'],$order,$defines_order,$visible,$searchable,$field['default'],$required,$put_in_category,$put_in_search);
				$o++;
			}
			$o=0;
			foreach ($old as $id=>$field)
			{
				if ((array_key_exists('delete',$field)) && ($field['delete']=='1'))
				{
					actual_delete_catalogue_field($id);
				} else
				{
					$p=0;
					foreach (array_keys($orderings) as $key)
					{
						if ($key=='old_'.strval($o)) $order=$p;
						$p++;
					}
					$defines_order=array_key_exists('defines_order',$field)?intval($field['defines_order']):0;
					$visible=array_key_exists('visible',$field)?intval($field['visible']):0;
					$searchable=array_key_exists('searchable',$field)?intval($field['searchable']):0;
					$required=array_key_exists('required',$field)?intval($field['required']):0;
					$put_in_category=array_key_exists('put_in_category',$field)?intval($field['put_in_category']):0;
					$put_in_search=array_key_exists('put_in_search',$field)?intval($field['put_in_search']):0;
					$field_type=array_key_exists('type',$field)?$field['type']:NULL;
					actual_edit_catalogue_field($id,$name,$field['name'],$field['description'],$order,$defines_order,$visible,$searchable,$field['default'],$required,$put_in_category,$put_in_search,$field_type);
				}
				$o++;
			}
		}

		// Do this last as it causes a main_sitemap decache which can cause memory errors if we do a warn_exit (i.e. we want the warn_exit's before this)
		if (!fractional_edit())
		{
			$this->set_permissions($name);
		}
	}

	/**
	 * Standard aed_module delete actualiser.
	 *
	 * @param  ID_TEXT		The entry being deleted
	 */
	function delete_actualisation($id)
	{
		require_code('catalogues2');

		actual_delete_catalogue($id);
	}

	/**
	 * The do-next manager for after catalogue content management.
	 *
	 * @param  tempcode		The title (output of get_page_title)
	 * @param  tempcode		Some description to show, saying what happened
	 * @param  ?ID_TEXT		The catalogue name we were working with (NULL: deleted)
	 * @return tempcode		The UI
	 */
	function do_next_manager($title,$description,$name)
	{
		breadcrumb_set_self(do_lang_tempcode('DONE'));

		if (!is_null($name))
		{
			$cat_count=$GLOBALS['SITE_DB']->query_value('catalogue_categories','COUNT(*)',array('c_name'=>$name));
			$has_categories=($cat_count!=0);
		} else $has_categories=false;

		require_code('templates_donext');
		return do_next_manager($title,$description,
					NULL,
					NULL,
					/*		TYPED-ORDERED LIST OF 'LINKS'		*/
					/*	 page	 params				  zone	  */
					(is_null($name)||(!$has_categories))?NULL:array('_SELF',array('type'=>'add_entry','catalogue_name'=>$name),'_SELF'),								  // Add one
					NULL,				 // Edit this
					(is_null($name)||(!$has_categories))?NULL:(has_specific_permission(get_member(),'edit_own_midrange_content','cms_catalogues')?array('_SELF',array('type'=>'edit_entry','catalogue_name'=>$name),'_SELF'):NULL), // Edit one
					NULL,																						// View this
					NULL,																						// View archive
					NULL,																						// Add to category
					is_null($name)?NULL:array('_SELF',array('type'=>'add_category','catalogue_name'=>$name),'_SELF'), // Add one category
					(is_null($name)||(!$has_categories))?NULL:array('_SELF',array('type'=>'edit_category','catalogue_name'=>$name),'_SELF'),// Edit one category
					NULL,																						// Edit this category
					NULL,																						// View this category
					/*	  SPECIALLY TYPED 'LINKS'				  */
					array(),
					array(),
					array(
						/*	 type							  page	 params													 zone	  */
						array('add_one_catalogue',array('_SELF',array('type'=>'add_catalogue'),'_SELF')),
						is_null($name)?NULL:array('edit_this_catalogue',array('_SELF',array('type'=>'_edit_catalogue','id'=>$name),'_SELF')),
						array('edit_one_catalogue',array('_SELF',array('type'=>'edit_catalogue'),'_SELF')),
						is_null($name)?NULL:array('view_this',array('catalogues',$this->is_tree_catalogue?array('type'=>'category','catalogue_name'=>$name):array('type'=>'index','id'=>$name),get_module_zone('catalogues')))
					),
					do_lang('MANAGE_CATALOGUES')
		);
	}
}


