<?php
/**
 * Export File model
 *
 * @package 	CSVIVirtueMart
 * @author 		Roland Dalmulder
 * @link 		http://www.csvimproved.com
 * @copyright 	Copyright (C) 2006 - 2012 RolandD Cyber Produksi
 * @license 	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 * @version 	$Id: exportfile.php 1892 2012-02-11 11:01:09Z RolandD $
 */

defined( '_JEXEC' ) or die( 'Direct Access to this location is not allowed.' );

jimport( 'joomla.application.component.model' );

/**
 * Export File Model
 *
 * @package CSVIVirtueMart
 */
class CsvivirtuemartModelExportfile extends JModel {

	/** @var string Field delimiter */
	private $_field_delim = null;
	/** @var string Text delimiter */
	private $_text_delim = null;
	/** @var string Category separator */
	private $_catsep = null;
	/** @var array Holds the data for combined fields */
	private $_outputfield = array();
	/** @var string Contains the header name to be added */
	private $_headername = null;
	/** @var string Contains the last field to be exported */
	private $_last_field = null;
	/** @var string Contains the last field to be exported */
	private $_contents = array();

	/**
	 * Prepare for export
	 *
	 * @copyright
	 * @author 		RolandD
	 * @todo		Update the output type to include multiple destinations
	 * @todo		Is the setting of the export_type in JRequest necessary?
	 * @see
	 * @access 		public
	 * @param
	 * @return
	 * @since 		3.0
	 */
	public function getPrepareExport() {
		// Load the form handler
		$db = JFactory::getDBO();
		$option = JRequest::getVar('option');
		$data	= JRequest::getVar('jform', array(), 'post', 'array');

		// Re-order the replacement fields
		if (array_key_exists('replacement_export_fields', $data)) {
			if (array_key_exists('_selected_name', $data['replacement_export_fields'])) {
				$fields = array();
				$replacetext = 0;
				$replaceregex = 0;
				foreach ($data['replacement_export_fields']['_selected_name'] as $rkey => $name) {
					if ($data['replacement_export_fields']['_replace_type'][$rkey] == 1) {
						$data['replacement_fields'][$name]['findregex'][$replaceregex] = $data['replacement_export_fields']['_old_value'][$rkey];
						$data['replacement_fields'][$name]['replaceregex'][$replaceregex] = $data['replacement_export_fields']['_new_value'][$rkey];
						$replaceregex++;
					}
					else {
						$data['replacement_fields'][$name]['findtext'][$replacetext] = $data['replacement_export_fields']['_old_value'][$rkey];
						$data['replacement_fields'][$name]['replacetext'][$replacetext] = $data['replacement_export_fields']['_new_value'][$rkey];
						$replacetext++;
					}
				}
			}
		}

		$template = new CsviTemplate($data);
		JRequest::setVar('template', $template);

		// Set the export type
		JRequest::setVar('export_type', $data['export_type']);

		// Initiate the log
		$csvilog = new CsviLog();

		// Create a new Import ID in the logger
		$csvilog->setId();

		// Set to collect debug info
		$csvilog->setDebug($template->getValue('collect_debug_info', 'general'));

		// Set some log info
		$csvilog->SetAction('export');
		$csvilog->SetActionType(JRequest::getCmd('export_type'), JRequest::getVar('template_name'));

		// Add the logger to the registry
		JRequest::setVar('csvilog', $csvilog);

		// Load the fields to export
		$exportfields = $this->getExportFields();
		if (!empty($exportfields)) {
			// Set the last export field
			JRequest::setVar('export.fields', $exportfields);

			// Allow big SQL selects
			$db->setQuery("SET OPTION SQL_BIG_SELECTS=1");
			$db->query();

			// Get the filename for the export file
			JRequest::setVar('export.filename', $this->exportFilename());

			// Check if tab delimiter needs to be used
			if (strtolower($template->getValue('field_delimiter', 'general')) == 't') $template->setValue('field_delimiter', 'general', "\t");

			// See if we need to get an XML/HTML class
			$export_format = $template->getValue('export_file', 'general');
			if ($export_format == 'xml' || $export_format == 'html') {
				$exportclass = $this->getExportClass();
				if ($exportclass) JRequest::setVar('export.class', $exportclass);
				else {
					$csvilog->AddStats('incorrect', JText::_('COM_CSVIVIRTUEMART_NO_EXPORT_CLASS'));
					JRequest::setVar('logcount', array('export' => 0));
					return false;
				}
			}

			// Return all is good
			return true;
		}
		else {
			$csvilog->AddStats('incorrect', JText::_('COM_CSVIVIRTUEMART_NO_EXPORT_FIELDS'));
			JRequest::setVar('logcount', array('export' => 0));
			return false;
		}
	}

	/**
	 * Set the delimiters
	 *
	 * @copyright
	 * @author 		RolandD
	 * @todo
	 * @see
	 * @access 		private
	 * @param
	 * @return
	 * @since 		3.0
	 */
	private function _setDelimiters() {
		if (is_null($this->_field_delim)) {
			$template = JRequest::getVar('template');
			// Set the delimiters
			$this->_field_delim = $template->getValue('field_delimiter', 'general', ',');
			$this->_text_delim = $template->getValue('text_enclosure', 'general', '');
		}
	}

	/**
	 * Process the export data
	 *
	 * @copyright
	 * @author 		RolandD
	 * @todo
	 * @see
	 * @access 		public
	 * @param
	 * @return
	 * @since 		3.0
	 */
	public function getProcessData() {
		$template = JRequest::getVar('template');
		$export_format = $template->getValue('export_file', 'general');
		$export_fields = JRequest::getVar('export.fields');
		$export_class = JRequest::getVar('export.class');

		// Write out some import settings
		$this->_exportDetails();

		// Start the export
		if (!$this->_outputStart()) {
			// Store the log results
			$log_model = $this->_getModel('log');
			$log_model->getStoreLogResults();
			return false;
		}

		// Add signature for Excel
		if ($template->getValue('signature', 'general')) $this->_contents['signature'] = "\xEF\xBB\xBF";

		// Add header for XML
		if ($export_format == 'xml') $this->_contents[] = $export_class->HeaderText();
		// Add header for HTML
		else if ($export_format == 'html') {
			$this->_contents[] = $export_class->HeaderText();
			if ($template->getValue('include_column_headers', 'general')) {
				$this->_contents[] = $export_class->StartTableHeaderText();
				foreach ($export_fields as $column_id => $field) {
					if ($field->process) {
						$header = ($field->column_header) ? $field->column_header : $field->field_name;
						$this->_contents[] = $export_class->TableHeaderText($header);
					}
				}
				$this->_contents[] = $export_class->EndTableHeaderText();
			}
			$this->_contents[] = $export_class->BodyText();
		}
		else {
			// Add the header from the template
			$header = $template->getValue('header', 'layout', false);
			if ($header) {
				$this->_contents[] = $header;
				$this->writeOutput();
			}

			// Get the delimiters
			// See if the user wants column headers
			// Product type names export needs to be excluded here otherwise the column headers are incorrect
			if ($template->getValue('include_column_headers', 'general', true)) {
				$this->_setDelimiters();
				$addheader = true;
				foreach ($export_fields as $column_id => $field) {
					if ($field->process) {
						$header = (empty($field->column_header)) ? $field->field_name : $field->column_header;
						if ($addheader) $this->_contents[] = $this->_text_delim.$header.$this->_text_delim;
						if ($field->combine) $addheader = false;
						else $addheader = true;
					}
				}
			}
		}

		// Output content
		$this->writeOutput();

		// Start the export from the chosen template type
		$exportmodel = $this->_getModel(JRequest::getVar('export_type'));
		$exportmodel->getStart();

		if ($export_format == 'xml' || $export_format == 'html') {
			$footer = $export_class->FooterText();
		}
		else {
			// Add the footer from the template
			$footer = $template->getValue('footer', 'layout');
		}

		// Write the footer
		if ($footer && !empty($footer)) {
			$this->_contents[] = $footer;
			$this->writeOutput();
		}

		// End the export
		$this->_outputEnd();

		// Store the log results
		$log_model = $this->_getModel('log');
		$log_model->getStoreLogResults();

		// Process some settings
		switch ($template->getValue('exportto', 'general')) {
			case 'tofile':
			case 'toemail':
				JToolBarHelper::title(JText::_('COM_CSVIVIRTUEMART_EXPORT'), 'csvivirtuemart_export_48');
				break;
			case 'todownload':
				jexit();
				break;
		}
	}

	/**
	 * Cleanup after export
	 *
	 * @copyright
	 * @author 		RolandD
	 * @todo
	 * @see
	 * @access 		public
	 * @param
	 * @return 		void
	 * @since 		3.0
	 */
	public function getCleanSession() {
		// Store the log results first
		$log = $this->_getModel('log');
		$log->getStoreLogResults();

	}

	/**
	 * Load the export class that handles the file export
	 *
	 * @copyright
	 * @author		RolandD
	 * @todo
	 * @see
	 * @access 		public
	 * @param
	 * @return 		bool true when xml class is found|false when when no site is given
	 * @since 		3.0
	 */
	public function getExportClass() {
		$csvilog = JRequest::getVar('csvilog');
		$template = JRequest::getVar('template');
		$exportclass = false;
		$exporttype = $template->getValue('export_file', 'general');
		$exportsite = $template->getValue('export_site', 'general', 'csvimproved');

		// Construct the file name
		$filename = $exportsite.'.php';

		// Find the export class
		$helper = JPath::find(array(JPATH_COMPONENT_ADMINISTRATOR.'/helpers/file/export/'.$exporttype), $filename);
		if (!$helper) return false;
		else {
			// Load the file and instantite it
			include_once($helper);
			$classname = 'Csvi'.ucfirst($exportsite);
			$exportclass = new $classname;
		}
		return $exportclass;
	}

	/**
	 * Get the export filename
	 *
	 * @copyright
	 * @author 		RolandD
	 * @todo
	 * @see
	 * @access 		public
	 * @param
	 * @return 		string	Returns the filename of the exported file
	 * @since 		3.0
	 */
	public function exportFilename() {
		$csvilog = JRequest::getVar('csvilog');
		$template = JRequest::getVar('template');

		// Check if the export is limited, if so add it to the filename
		// Check if both values are greater than 0
		if (($template->getValue('recordstart', 'general') > 0) && ($template->getValue('recordend', 'general') > 0)) {
			// We have valid limiters, add the limit to the filename
			$filelimit = "_".$template->getValue('recordend', 'general').'_'.($template->getValue('recordend', 'general')-1)+$template->getValue('recordstart', 'general');
		}
		else $filelimit = '';

		// Set the filename to use for export
		$export_filename = trim($template->getValue('export_filename', 'general'));
		$local_path = JPath::clean($template->getValue('localpath', 'general'), '/');
		$export_file = $template->getValue('export_file', 'general');

		// Do some customizing
		// Replace year
		$export_filename = str_replace('[Y]', date('Y', time()), $export_filename);
		$export_filename = str_replace('[y]', date('y', time()), $export_filename);
		// Replace month
		$export_filename = str_replace('[M]', date('M', time()), $export_filename);
		$export_filename = str_replace('[m]', date('m', time()), $export_filename);
		$export_filename = str_replace('[F]', date('F', time()), $export_filename);
		$export_filename = str_replace('[n]', date('n', time()), $export_filename);
		// Replace day
		$export_filename = str_replace('[d]', date('d', time()), $export_filename);
		$export_filename = str_replace('[D]', date('D', time()), $export_filename);
		$export_filename = str_replace('[j]', date('j', time()), $export_filename);
		$export_filename = str_replace('[l]', date('l', time()), $export_filename);
		// Replace hour
		$export_filename = str_replace('[g]', date('g', time()), $export_filename);
		$export_filename = str_replace('[G]', date('G', time()), $export_filename);
		$export_filename = str_replace('[h]', date('h', time()), $export_filename);
		$export_filename = str_replace('[H]', date('H', time()), $export_filename);
		// Replace minute
		$export_filename = str_replace('[i]', date('i', time()), $export_filename);
		// Replace seconds
		$export_filename = str_replace('[s]', date('s', time()), $export_filename);

		// Setup the full path for the filename
		switch ($template->getValue('exportto', 'general')) {
			case 'toemail':
			case 'toftp':
				if (!empty($export_filename)) $localfile = CSVIPATH_TMP.'/'.$export_filename;
				else $localfile = CSVIPATH_TMP.'/CSVI_VM_'.JRequest::getCmd('template_name').'_'.date("j-m-Y_H.i").$filelimit.".".$export_file;
				break;
			case 'tofile':
				if (!empty($local_path) && !empty($export_filename)) $localfile = $local_path.'/'.$export_filename;
				else if (!empty($local_path))  $localfile = $local_path.'/CSVI_VM_'.JRequest::getCmd('template_name').'_'.date("j-m-Y_H.i").$filelimit.".".$export_file;
				else 'CSVI_VM_'.JRequest::getCmd('template_name').'_'.date("j-m-Y_H.i").$filelimit.".".$export_file;
				break;
			case 'tofront':
				$uri = JURI::getInstance();
				$localfile = $uri->toString();
				break;
			default:
				if (!empty($export_filename)) $localfile = $export_filename;
				else $localfile = 'CSVI_VM_'.JRequest::getCmd('template_name').'_'.date("j-m-Y_H.i").$filelimit.".".$export_file;
				break;
		}

		// Clean up
		$localfile = JPath::clean($localfile, '/');

		// Set the filename
		$csvilog->setFilename($localfile);

		// Return the filename
		return $localfile;
	}

	/**
	 * Get the fields to use for the export
	 *
	 * @copyright
	 * @author 		RolandD
	 * @todo
	 * @see
	 * @access 		public
	 * @param
	 * @return 		array 	Returns an array of required fields and default field values
	 * @since 		3.0
	 */
	public function getExportFields() {
		$db = JFactory::getDBO();
		$template = JRequest::getVar('template');

		// Get the field configuration
		$export_fields = $template->getValue('export_fields');

		// Set the field options for export
		if (!empty($export_fields)) {
			foreach ($export_fields['_selected_name'] as $kef => $field_name) {
				$field = new StdClass;
				$field->field_name = $field_name;
				$field->column_header = $export_fields['_column_header'][$kef];
				$field->default_value = $export_fields['_default_value'][$kef];
				$field->process = $export_fields['_process_field'][$kef];
				$field->combine = $export_fields['_combine_field'][$kef];
				$field->sort = $export_fields['_sort_field'][$kef];
				$field->field_id = ($kef+1);
				$fields[($kef+1)] = $field;
			}
		}
		else return array();

		// Return the required and default values
		return $fields;
	}

	/**
	 * Print out export details
	 *
	 * @copyright
	 * @author		RolandD
	 * @todo
	 * @see
	 * @access 		private
	 * @param
	 * @return
	 * @since 		3.0
	 */
	private function _exportDetails() {
		// Get the logger
		$csvilog = JRequest::getVar('csvilog');
		// Get the template settings to see if we need a preview
		$template = JRequest::getVar('template');

		$csvilog->addDebug(JText::_('COM_CSVIVIRTUEMART_CSVI_VERSION_TEXT').JText::_('COM_CSVIVIRTUEMART_CSVI_VERSION'));
		if (function_exists('phpversion')) $csvilog->addDebug(JText::sprintf('COM_CSVIVIRTUEMART_PHP_VERSION', phpversion()));

		// General settings
		$csvilog->addDebug(JText::_('COM_CSVIVIRTUEMART_GENERAL_SETTINGS'));
		// Show which template is used */
		$csvilog->addDebug(JText::sprintf('COM_CSVIVIRTUEMART_TEMPLATE_NAME', JRequest::getVar('template_name')));

		// Destination settings
		$exportto = $template->getValue('exportto', 'general');
		$csvilog->addDebug(JText::sprintf('COM_CSVIVIRTUEMART_DEBUG_CHOSEN_DESTINATION', $exportto));

		switch ($exportto) {
			case 'tofile':
				$csvilog->addDebug(JText::sprintf('COM_CSVIVIRTUEMART_DEBUG_EXPORT_PATH', $template->getValue('localpath', 'general')));
				break;
			case 'toftp':
				$csvilog->addDebug(JText::sprintf('COM_CSVIVIRTUEMART_DEBUG_EXPORT_FTP_HOST', $template->getValue('ftphost', 'general')));
				$csvilog->addDebug(JText::sprintf('COM_CSVIVIRTUEMART_DEBUG_EXPORT_FTP_PORT', $template->getValue('ftpport', 'general')));
				$csvilog->addDebug(JText::sprintf('COM_CSVIVIRTUEMART_DEBUG_EXPORT_FTP_USERNAME', $template->getValue('ftpusername', 'general')));
				$csvilog->addDebug(JText::sprintf('COM_CSVIVIRTUEMART_DEBUG_EXPORT_FTP_ROOT', $template->getValue('ftproot', 'general')));
				break;
		}

		// Export filename
		$csvilog->addDebug(JText::sprintf('COM_CSVIVIRTUEMART_DEBUG_EXPORT_GENERATED_FILENAME', JRequest::getVar('export.filename')));

		// Export type
		$csvilog->addDebug(JText::sprintf('COM_CSVIVIRTUEMART_DEBUG_CHOSEN_EXPORT_TYPE', $template->getValue('export_type')));

		// User given filename
		$csvilog->addDebug(JText::sprintf('COM_CSVIVIRTUEMART_DEBUG_EXPORT_FILENAME', $template->getValue('export_filename')));

		// Export type
		$export_file = $template->getValue('export_file', 'general');
		$csvilog->addDebug(JText::sprintf('COM_CSVIVIRTUEMART_DEBUG_EXPORT_FILE', $export_file));
		if ($export_file == 'xml') {
			$csvilog->addDebug(JText::sprintf('COM_CSVIVIRTUEMART_DEBUG_EXPORT_SITE', $template->getValue('export_site', 'general')));
		}

		// Check delimiter char
		$csvilog->addDebug(JText::sprintf('COM_CSVIVIRTUEMART_USING_DELIMITER', $template->getValue('field_delimiter', 'general')));
		// Check enclosure char
		$csvilog->addDebug(JText::sprintf('COM_CSVIVIRTUEMART_USING_ENCLOSURE', $template->getValue('text_enclosure', 'general')));

		// Include column headers
		$use_header = ($template->getValue('include_column_headers', 'general')) ? JText::_('COM_CSVIVIRTUEMART_YES') : JText::_('COM_CSVIVIRTUEMART_NO');
		$csvilog->addDebug(JText::sprintf('COM_CSVIVIRTUEMART_DEBUG_INCLUDE_HEADER', $use_header));

		// Add signature
		$signature = ($template->getValue('signature', 'general')) ? JText::_('COM_CSVIVIRTUEMART_YES') : JText::_('COM_CSVIVIRTUEMART_NO');
		$csvilog->addDebug(JText::sprintf('COM_CSVIVIRTUEMART_DEBUG_SIGNATURE', $signature));

		// Export frontend
		$export_frontend = ($template->getValue('export_frontend', 'general')) ? JText::_('COM_CSVIVIRTUEMART_YES') : JText::_('COM_CSVIVIRTUEMART_NO');
		$csvilog->addDebug(JText::sprintf('COM_CSVIVIRTUEMART_DEBUG_EXPORT_FRONTEND', $export_frontend));

		// Export state
		switch ($template->getValue('publish_state', 'general')) {
			case 'Y':
				$publish_state = JText::_('COM_CSVIVIRTUEMART_YES');
				break;
			case 'N':
				$publish_state = JText::_('COM_CSVIVIRTUEMART_NO');
				break;
			default:
				$publish_state = JText::_('COM_CSVIVIRTUEMART_ALL_STATES');
				break;
		}
		$csvilog->addDebug(JText::sprintf('COM_CSVIVIRTUEMART_DEBUG_PUBLISH_STATE', $publish_state));

		// Number of records to export
		$csvilog->addDebug(JText::sprintf('COM_CSVIVIRTUEMART_DEBUG_RECORD_START', $template->getValue('recordstart', 'general')));
		$csvilog->addDebug(JText::sprintf('COM_CSVIVIRTUEMART_DEBUG_RECORD_END', $template->getValue('recordend', 'general')));

		// Record grouping
		$groupby = ($template->getValue('groupby', 'general')) ? JText::_('COM_CSVIVIRTUEMART_YES') : JText::_('COM_CSVIVIRTUEMART_NO');
		$csvilog->addDebug(JText::sprintf('COM_CSVIVIRTUEMART_DEBUG_GROUPBY', $groupby));

		// VirtueMart Item ID
		$csvilog->addDebug(JText::sprintf('COM_CSVIVIRTUEMART_DEBUG_VM_ITEMID', $template->getValue('vm_itemid', 'general')));

		// Date format
		$csvilog->addDebug(JText::sprintf('COM_CSVIVIRTUEMART_DEBUG_EXPORT_DATE_FORMAT', $template->getValue('export_date_format', 'general')));

		// Price format
		$csvilog->addDebug(JText::sprintf('COM_CSVIVIRTUEMART_DEBUG_EXPORT_DECIMALS', $template->getValue('export_price_format_decimal', 'general')));
		$csvilog->addDebug(JText::sprintf('COM_CSVIVIRTUEMART_DEBUG_EXPORT_DEC_SEP', $template->getValue('export_price_format_decsep', 'general')));
		$csvilog->addDebug(JText::sprintf('COM_CSVIVIRTUEMART_DEBUG_EXPORT_THOUSAND_SEP', $template->getValue('export_price_format_thousep', 'general')));

		// Record grouping
		$add_currency = ($template->getValue('add_currency_to_price', 'general')) ? JText::_('COM_CSVIVIRTUEMART_YES') : JText::_('COM_CSVIVIRTUEMART_NO');
		$csvilog->addDebug(JText::sprintf('COM_CSVIVIRTUEMART_DEBUG_ADD_CURRENCY_TO_PRICE', $add_currency));

		// Exporting fields
		$export_fields = JRequest::getVar('export.fields');
		$addheader = true;
		foreach ($export_fields as $column_id => $field) {
			if ($addheader) $csvilog->addDebug(JText::sprintf('COM_CSVIVIRTUEMART_DEBUG_EXPORT_FIELD', $field->column_header));
			if ($field->combine) $addheader = false;
			else $addheader = true;
		}

	}

	/**
	 * Output the collected data
	 *
	 * @copyright
	 * @author 		RolandD
	 * @todo
	 * @see
	 * @access 		private
	 * @param
	 * @return 		void
	 * @since		3.0
	 */
	private function _outputStart() {
		$csvilog = JRequest::getVar('csvilog');
		$template = JRequest::getVar('template');
		$exportfilename = JRequest::getVar('export.filename');
		$result = false;
		if ($template->getValue('use_system_limits', 'limit')) {
			$csvilog->addDebug('Setting system limits:');
			// Apply the new memory limits
			$csvilog->addDebug('Setting max_execution_time to '.$template->getValue('max_execution_time', 'limit').' seconds');
			@ini_set('max_execution_time', $template->getValue('max_execution_time', 'limit'));
			$csvilog->addDebug('Setting memory_limit to '.$template->getValue('memory_limit', 'limit').'M');
			if ($template->getValue('memory_limit', 'limit') == '-1') {
				$csvilog->addDebug('Setting memory_limit to '.$template->getValue('memory_limit', 'limit'));
				@ini_set('memory_limit', $template->getValue('memory_limit', 'limit'));
			}
			else {
				$csvilog->addDebug('Setting memory_limit to '.$template->getValue('memory_limit', 'limit').'M');
				@ini_set('memory_limit', $template->getValue('memory_limit', 'limit').'M');
			}
		}
		switch ($template->getValue('exportto', 'general', 'todownload')) {
			case 'todownload':
				if (preg_match('/Opera(\/| )([0-9].[0-9]{1,2})/', $_SERVER['HTTP_USER_AGENT'])) {
					$UserBrowser = "Opera";
				}
				elseif (preg_match('/MSIE ([0-9].[0-9]{1,2})/', $_SERVER['HTTP_USER_AGENT'])) {
					$UserBrowser = "IE";
				} else {
					$UserBrowser = '';
				}
				$mime_type = ($UserBrowser == 'IE' || $UserBrowser == 'Opera') ? 'application/octetstream' : 'application/octet-stream';

				// Clean the buffer
				while( @ob_end_clean() );

				header('Content-Type: ' . $mime_type);
				header('Content-Encoding: UTF-8');
				header('Expires: ' . gmdate('D, d M Y H:i:s') . ' GMT');

				if ($UserBrowser == 'IE') {
					header('Content-Disposition: inline; filename="'.$exportfilename.'"');
					header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
					header('Pragma: public');
				} else {
					header('Content-Disposition: attachment; filename="'.$exportfilename.'"');
					header('Pragma: no-cache');
				}
				$result = true;
				break;
			case 'tofile':
				jimport('joomla.filesystem.folder');

				// Check if the folder exists
				if (!JFolder::exists(dirname($exportfilename))) {
					if (!JFolder::create(dirname($exportfilename))) {
						$csvilog->AddStats('incorrect', JText::sprintf('COM_CSVIVIRTUEMART_CANNOT_CREATE_FOLDER', dirname($exportfilename)));
						$result = false;
					}
				}

				// open the file for writing
				$handle = @fopen($exportfilename, 'w+');
				if (!$handle) {
					$csvilog->AddStats('incorrect', JText::sprintf('COM_CSVIVIRTUEMART_CANNOT_OPEN_FILE', $exportfilename));
					$result = false;
				}
				// Let's make sure the file exists and is writable first.
				if (is_writable($exportfilename)) {
				    JRequest::setVar('handle', $handle);
				    $result = true;
				}
				else {
					$csvilog->AddStats('incorrect', JText::sprintf('COM_CSVIVIRTUEMART_CANNOT_WRITE_FILE', $exportfilename));
					$result = false;
				}
				break;
			case 'toftp':
			case 'toemail':
				// open the file for writing
				$handle = fopen($exportfilename, 'w+');
				if (!$handle) {
					$csvilog->AddStats('incorrect', JText::sprintf('COM_CSVIVIRTUEMART_CANNOT_OPEN_FILE', $exportfilename));
					$result = false;
				}
				// Let's make sure the file exists and is writable first.
				if (is_writable($exportfilename)) {
				    JRequest::setVar('handle', $handle);
				    $result = true;
				}
				else {
					$csvilog->AddStats('incorrect', JText::sprintf('COM_CSVIVIRTUEMART_CANNOT_WRITE_FILE', $exportfilename));
					$result = false;
				}
				break;
			case 'tofront':
				$result = true;
				break;
		}

		return $result;
	}

	/**
	 * Write the output to download or to file
	 *
	 * @copyright
	 * @author		RolandD
	 * @todo
	 * @see
	 * @access 		protected
	 * @param 		string	$contents	the content to output
	 * @return 		bool	true if data is output | false if data is not output
	 * @since 		3.0
	 */
	protected function writeOutput() {
		// Let's take the local contents if nothing is supplied
		$contents = $this->_contents;

		// Clean the local contents
		$this->_contents = array();

		if (!empty($contents)) {
			$csvilog = JRequest::getVar('csvilog');
			$template = JRequest::getVar('template');
			$exportfilename = JRequest::getVar('export.filename');

			if (!is_array($contents)) $contents = (array) $contents;

			switch ($template->getValue('exportto', 'general')) {
				case 'todownload':
				case 'tofront':
					if (isset($contents['signature'])) {
						echo $contents['signature'];
						unset($contents['signature']);
					}
					if ($template->getValue('export_file', 'general') == 'xml' || $template->getValue('export_file', 'general') == 'html') {
						echo implode("", $contents)."\r\n";
					}
					else {
						echo implode($this->_field_delim, $contents)."\r\n";
					}
					break;
				case 'tofile':
				case 'toftp':
				case 'toemail':
					if ($template->getValue('export_file', 'general') == 'xml' || $template->getValue('export_file', 'general') == 'html') {
						$writedata = '';
						if (isset($contents['signature'])) {
							$writedata = $contents['signature'];
							unset($contents['signature']);
						}
						$writedata .= implode('', $contents);
						if (fwrite(JRequest::getVar('handle'), $writedata."\r\n") === FALSE) {
							$csvilog->AddStats('incorrect', JText::sprintf('COM_CSVIVIRTUEMART_CANNOT_WRITE_FILE', $exportfilename));
					   		return false;
						}
					}
					else {
						if (fwrite(JRequest::getVar('handle'), implode($this->_field_delim, $contents)."\r\n") === FALSE) {
							$csvilog->AddStats('incorrect', JText::sprintf('COM_CSVIVIRTUEMART_CANNOT_WRITE_FILE', $exportfilename));
					   		return false;
						}
					}
					break;
			}
		}
		return true;
	}

	/**
	 * Finalize export output
	 *
	 * @copyright
	 * @author 		RolandD
	 * @todo
	 * @see
	 * @access 		private
	 * @param
	 * @return 		void
	 * @since 		3.0
	 */
	private function _outputEnd() {
		$csvilog = JRequest::getVar('csvilog');
		$template = JRequest::getVar('template');
		$exportfilename = JRequest::getVar('export.filename');

		jimport('joomla.filesystem.file');
		switch ($template->getValue('exportto', 'general')) {
			case 'todownload':
				break;
			case 'tofile':
				$csvilog->AddStats('information', "The file ".$exportfilename." has been created");
				fclose(JRequest::getVar('handle'));
				break;
			case 'toftp':
				// Close the file handle
				fclose(JRequest::getVar('handle'));

				// Start the FTP
				jimport('joomla.client.ftp');
				$ftp = JFTP::getInstance($template->getValue('ftphost', 'general'), $template->getValue('ftpport', 'general'), null, $template->getValue('ftpusername', 'general'), $template->getValue('ftppass', 'general'));
				$ftp->chdir($template->getValue('ftproot', 'general', '/'));
				$ftp->store($exportfilename);
				$ftp->quit();

				// Remove the temporary file
				JFile::delete($exportfilename);
				break;
			case 'toemail':
				fclose(JRequest::getVar('handle'));
				$this->_getMailer();
				// Add the email address
				$addresses = explode(',', $template->getValue('export_email_addresses', 'email'));
				foreach ($addresses as $address) {
					if (!empty($address)) $this->mailer->AddAddress($address);
				}
				$addresses_cc = explode(',', $template->getValue('export_email_addresses_cc', 'email'));
				if (!empty($addresses_cc)) {
					foreach ($addresses_cc as $address) {
						if (!empty($address)) $this->mailer->AddCC($address);
					}
				}
				$addresses_bcc = explode(',', $template->getValue('export_email_addresses_bcc', 'email'));
				if (!empty($addresses_bcc)) {
					foreach ($addresses_bcc as $address) {
						if (!empty($address)) $this->mailer->AddBCC($address);
					}
				}

				// Mail submitter
				$htmlmsg = '<html><body>'.$this->_getRelToAbs($template->getValue('export_email_body', 'email')).'</body></html>';
				$this->mailer->setBody($htmlmsg);
				$this->mailer->setSubject($template->getValue('export_email_subject', 'email'));

				// Add the attachemnt
				$this->mailer->AddAttachment($exportfilename);

				// Send the mail
				$sendmail = $this->mailer->Send();
				if (is_a($sendmail, 'JException')) $csvilog->AddStats('incorrect', JText::sprintf('COM_CSVIVIRTUEMART_NO_MAIL_SEND', $sendmail->getMessage()));
				else $csvilog->AddStats('information', JText::_('COM_CSVIVIRTUEMART_MAIL_SEND'));

				// Clear the mail details
				$this->mailer->ClearAddresses();

				// Remove the temporary file
				JFile::delete($exportfilename);
				break;
		}
	}

	/**
	 * Search through the export fields if a certain field is being exported
	 *
	 * @copyright
	 * @author 		RolandD
	 * @todo
	 * @see
	 * @access 		protected
	 * @param 		string	$fieldname	the fieldname to check if it is being exported
	 * @return 		bool	true if field is being exported | false if field is not being exported
	 * @since 		3.0
	 */
	protected function searchExportFields($fieldname) {
		$exportfields = JRequest::getVar('export.fields');
	 	foreach ($exportfields as $column_id => $field) {
	 		if ($field->field_name == $fieldname) return true;
	 	}
	 	return false;
	}

	/**
	 * Constructs a limit for a query
	 *
	 * @copyright
	 * @author 		RolandD
	 * @todo
	 * @see
	 * @access 		protected
	 * @param
	 * @return 		string	the limit to apply to the query
	 * @since 		3.0
	 */
	protected function getExportLimit() {
		$template = JRequest::getVar('template');
		$recordstart = $template->getValue('recordstart', 'general', 0, 'int');
		$recordend = $template->getValue('recordend', 'general', 0, 'int');
		$limit = '';
		// Check if the user only wants to export some products
		if ($recordstart && $recordend) {
			// Check if both values are greater than 0
			if (($recordstart > 0) && ($recordend > 0)) {
				// We have valid limiters, add the limit to the query
				// Recordend needs to have 1 deducted because MySQL starts from 0
				$limit = ' LIMIT '.($recordend-1).','.$recordstart;
			}
		}
		return $limit;
	}

	/**
	 * Create an SQL filter
	 *
	 * @copyright
	 * @author 		RolandD
	 * @todo
	 * @see
	 * @access 		protected
	 * @param 		string	$filter		what kind of SQL type should be created
	 * @param 		array	$ignore		an array of fields not to process
	 * @param		array	$special	an array of special fields not to nameQuote
	 * @return 		string	the SQL part to add to the query
	 * @since 		3.0
	 */
	protected function getFilterBy($filter, $ignore=array(), $special=array()) {
		$db = JFactory::getDBO();
		$export_fields = JRequest::getVar('export.fields');
		$fields = array();

		// Add some basic fields never to be handled
		$ignore[] = 'custom';

		// Collect the fields to process
		foreach ($export_fields as $column_id => $field) {
			switch ($filter) {
				case 'groupby':
					$process = true;
					break;
				case 'sort':
					$process = $field->sort;
					break;
				default:
					$process = false;
			}
			if ($process) {
				// Check if field needs to be skipped
				if (!in_array($field->field_name, $ignore)) {
					// Check if field is special
					if (!array_key_exists($field->field_name, $special)) {
						$fields[] = $db->nameQuote($field->field_name);
					}
					else {
						$fields[] = $special[$field->field_name];
					}
				}
			}
		}

		// Construct the SQL part
		if (!empty($fields)) {
			switch ($filter) {
				case 'groupby':
					$groupby_fields = array_unique($fields);
					$q = " GROUP BY ".implode(',', $groupby_fields);
					break;
				case 'sort':
					$sort_fields = array_unique($fields);
					$q = " ORDER BY ".implode(', ', $sort_fields);
					break;
				default:
					$q = '';
					break;
			}
		}
		else $q = '';

		return $q;
	}

	/**
	* Remove trailing 0
	*
	* @return int returns a product price without trailing 0
	* @todo add user setting for number of decimals
	* @deprecated since version 2.3.13
	*/
	public function ProductPrice($product_price) {
		if ($product_price) {
			if (strstr($product_price, '.')) {
				list($number, $decimals) = explode('.', $product_price);
				if (strlen($decimals) > 2) {
					for ($i=1;$i<4;$i++) {
						if (substr($decimals, -1) == 0) $decimals = substr($decimals, 0, -1);
						else $i = 4;
					}
				}
				$product_price = $number.'.'.$decimals;
			}
		}
		return $product_price;
	}

	/**
	 * Get the flypage for a product
	 *
	 * @copyright
	 * @author		RolandD
	 * @todo
	 * @see
	 * @access 		protected
	 * @param
	 * @return 		string	returns the name of the flypage
	 * @since 		3.0
	 */
	protected function getFlypage($product_id) {
		$db = JFactory::getDBO();
		$q =  "SELECT `#__vm_category`.`category_flypage`
			FROM `#__vm_product`
			LEFT JOIN `#__vm_product_category_xref`
			ON `#__vm_product_category_xref`.`product_id` = `#__vm_product`.`product_id`
			LEFT JOIN `#__vm_category`
			ON `#__vm_product_category_xref`.`category_id` = `#__vm_category`.`category_id`
			WHERE `#__vm_product`.`product_id`='".$product_id."'";
		$db->setQuery($q);
		$flypage = $db->loadResult();
		if (is_null($flypage)) {
			// There is no flypage found let's use the VirtueMart config settings
			$vm_config = new CsviVmConfig();
			$flypage = $vm_config->getSetting('flypage');
			if (!$flypage) return 'shop.flypage.tpl';
			else return $flypage;
		}
		else return $flypage;
	}

	/**
	 * Get the category ID for a product
	 *
	 * @copyright
	 * @author 		RolandD
	 * @todo
	 * @see
	 * @access 		protected
	 * @param 		int	$product_id	the product ID to get the category for
	 * @return 		int	the category ID the product is linked to limited to 1
	 * @since 		3.0
	 */
	protected function getCategoryId($product_id) {
		$db = JFactory::getDBO();
		$q = "SELECT category_id
			FROM #__vm_product_category_xref
			WHERE product_id = '".$product_id."' LIMIT 1";
		$db->setQuery($q);
		return $db->loadResult();
	}

	/**
	 * Add a field to the output
	 *
	 * @copyright
	 * @author 		RolandD
	 * @todo
	 * @see
	 * @access 		protected
	 * @param 		$combine 		boolean	true if the fields need to be combined
	 * @param 		$data 			string	Data to output
	 * @param 		$fieldname 		string	Name of the field currently being processed
	 * @param 		$column_header 	string	Name of the column
	 * @param 		$cdata			boolean true to add cdata tag for XML|false not to add it
	 * @return 		string containing the field for the export file
	 * @since 		3.0
	 */
	protected function addExportField($combine=false, $data, $fieldname, $column_header, $cdata=false) {
		// Data is not going to be combined
		if (!$combine) {
			if (!empty($this->_outputfield)) {
				$this->_outputfield[] = $data;
				$data = implode(' ', $this->_outputfield);
				$this->_outputfield = array();
			}
			$template = JRequest::getVar('template');

			// Load the session
			$exportclass =  JRequest::getVar('export.class');

			// Set the delimiters
			$this->_setDelimiters();

			// Clean up the data by removing linebreaks
			$find = array("\r\n", "\r", "\n");
			$replace = array('','','');
			$data = str_ireplace($find, $replace, $data);

			if ($template->getValue('export_file', 'general') == 'xml' || $template->getValue('export_file', 'general') == 'html') {
				if (!is_null($this->_headername)) {
					$column_header = $this->_headername;
					$this->_headername = null;
				}
				$this->_contents[] = $exportclass->ContentText($data, $column_header, $fieldname, $cdata);
			}
			else {
				$data = str_replace($this->_text_delim, $this->_text_delim.$this->_text_delim, $data);
				$this->_contents[] = $this->_text_delim.$data.$this->_text_delim;
			}
		}
		// Combine with previous field
		else {
			if (is_null($this->_headername)) $this->_headername = $column_header;
			$this->_outputfield[] = $data;
		}
	}

	/**
	 * Add data to the export content
	 *
	 * @copyright
	 * @author 		RolandD
	 * @todo
	 * @see
	 * @access 		protected
	 * @param 		string	$content	the content to export
	 * @return
	 * @since 		3.0
	 */
	protected function addExportContent($content) {
		$this->_contents[] = $content;
	}

	/**
	 * Get the pipe delimited category path of category IDs of a product
	 *
	 * @copyright
	 * @author 		RolandD
	 * @todo
	 * @see
	 * @access 		protected
	 * @param 		int		$product_id	the product ID to create the path for
	 * @return 		string	the category path for the product
	 * @since 		3.0
	 */
	protected function getCategoryPathId($product_id) {
		$db = JFactory::getDBO();
		$q = "SELECT category_id FROM #__vm_product_category_xref WHERE product_id = ".$product_id;
		$db->setQuery($q);
		return implode('|', $db->loadResultArray());
	}

	/**
	 * Create a category path for a product
	 *
	 * @copyright
	 * @author 		RolandD, soeren
	 * @todo
	 * @see
	 * @access 		protected
	 * @param 		int		$product_id	the product ID to create the path for
	 * @return 		string	the category path for the product
	 * @since
	 */
	protected function getCategoryPath($product_id) {
		$db = JFactory::getDBO();

		// Load the category separator
		if (is_null($this->_catsep)) {
			$template = JRequest::getVar('template');
			$this->_catsep = $template->getValue('category_separator', 'general', '/');
		}

		// Build the query to get the category path
		$q = "SELECT #__vm_product.product_id, #__vm_product.product_parent_id, category_name, #__vm_category.category_id, #__vm_category_xref.category_parent_id
			FROM #__vm_category, #__vm_product, #__vm_product_category_xref,#__vm_category_xref
			WHERE #__vm_product.product_id = ".$product_id."
			AND #__vm_category_xref.category_child_id = #__vm_category.category_id
			AND #__vm_category_xref.category_child_id = #__vm_product_category_xref.category_id
			AND #__vm_product.product_id = #__vm_product_category_xref.product_id";
		$db->setQuery($q);
		$rows = $db->loadObjectList();
		$k = 1;
		$category_path = "";

		foreach ($rows as $row) {
			$category_name = array();

			// Check for product or item
			if ($row->category_name) {
				$category_parent_id = $row->category_parent_id;
				$category_name[] = $this->_getJoomFishCategory($row->category_id, $row->category_name);
			}
			else {
				// Find the category path of the parent product
				$q = "SELECT product_parent_id FROM #__vm_product WHERE product_id='".$product_id."'";
				$db->setQuery($q);
				$ppi = $db->loadResult();

				$q  = "SELECT #__vm_product.product_id, #__vm_product.product_parent_id, category_name, #__vm_category.category_id, #__vm_category_xref.category_parent_id "
				."FROM #__vm_category, #__vm_product, #__vm_product_category_xref,#__vm_category_xref "
				."WHERE #__vm_product.product_id='".$ppi."' "
				."AND #__vm_category_xref.category_child_id=#__vm_category.category_id "
				."AND #__vm_category_xref.category_child_id = #__vm_product_category_xref.category_id "
				."AND #__vm_product.product_id = #__vm_product_category_xref.product_id";
				$db->setQuery($q);
				$cat_details = $db->loadObject();
				$category_parent_id = $cat_details->category_parent_id;
				$category_name[] = $this->_getJoomFishCategory($cat_details->category_id, $cat_details->category_name);
			}

			// Check if the parent ID is not empty
			if ($category_parent_id == "") $category_parent_id = "0";

			// Load the individual category details
			while ($category_parent_id != "0") {
				$q = "SELECT category_name, category_parent_id "
				."FROM #__vm_category, #__vm_category_xref "
				."WHERE #__vm_category_xref.category_child_id = #__vm_category.category_id "
				."AND #__vm_category.category_id = ".$category_parent_id;
				$db->setQuery($q);
				$cat_details = $db->loadObject();
				$category_name[] = $this->_getJoomFishCategory($category_parent_id, $cat_details->category_name);

				// Get the new parent ID
				$category_parent_id = $cat_details->category_parent_id;
			}

			// Construct the category path
			if (sizeof($category_name) > 1) {
				for ($i = sizeof($category_name)-1; $i >= 0; $i--) {
					$category_path .= $category_name[$i];
					if( $i >= 1) $category_path .= $this->_catsep;
				}
			}
			else $category_path .= $category_name[0];

			if( $k++ < sizeof($rows) )
			$category_path .= "|";
		}
		return $category_path;
	}

	/**
	 * Creates the category path based on a category ID
	 *
	 * @copyright
	 * @author 		RolandD
	 * @todo
	 * @see
	 * @access 		protected
	 * @param 		int	$category_id the ID to create the category path from
	 * @return 		string	the category path
	 * @since 		3.0
	 */
	protected function createCategoryPath($category_id) {
		$db = JFactory::getDBO();
		$catpaths = array();

		// Load the category separator
		if (is_null($this->_catsep)) {
			$template = JRequest::getVar('template');
			$this->_catsep = $template->getValue('category_separator', 'general', '/');
		}

		// Create the path
		while ($category_id > 0) {
			$q = "SELECT category_parent_id, category_name FROM #__vm_category_xref x, #__vm_category c
				WHERE x.category_child_id = c.category_id
				AND category_child_id = ".$category_id;
			$db->setQuery($q);
			$path = $db->loadObject();
			$catpaths[] = $this->_getJoomFishCategory($category_id, trim($path->category_name));
			$category_id = $path->category_parent_id;
		}
		$catpaths = array_reverse($catpaths);
		return implode($this->_catsep, $catpaths);
	}

	/**
	 * Convert links in a text from relative to absolute
	 *
	 * @copyright
	 * @author
	 * @todo
	 * @see
	 * @access 		private
	 * @param 		string	$text	the text to parse for links
	 * @return 		string	the parsed text
	 * @since 		3.0
	 */
	private function _getRelToAbs($text) {
		$base = JURI::root();
  		$text = preg_replace("/(href|src)=\"(?!http|ftp|https|mailto)([^\"]*)\"/", '$1="$base\$2"', $text);

		return $text;
	}

	/**
	 * Initialise the mailer object to start sending mails
	 *
	 * @copyright
	 * @author		RolandD
	 * @todo
	 * @see
	 * @access 		private
	 * @param
	 * @return
	 * @since 		3.0
	 */
	private function _getMailer() {
		$mainframe = Jfactory::getApplication();
		jimport('joomla.mail.helper');

		// Start the mailer object
		$this->mailer = JFactory::getMailer();
		$this->mailer->isHTML(true);
		$this->mailer->From = $mainframe->getCfg('mailfrom');
		$this->mailer->FromName = $mainframe->getCfg('sitename');
		$this->mailer->AddReplyTo(array($mainframe->getCfg('mailfrom'), $mainframe->getCfg('sitename')));
	}

	/**
	 * Create a proxy for including other models
	 *
	 * @copyright
	 * @author 		RolandD
	 * @todo
	 * @see
	 * @access 		private
	 * @param
	 * @return
	 * @since 		3.0
	 */
	private function _getModel($model) {
		return $this->getInstance($model, 'CsvivirtuemartModel');
	}

	/**
	 * Get the JoomFish translated value for a category name
	 *
	 * @copyright
	 * @author 		RolandD
	 * @todo
	 * @see
	 * @access 		private
	 * @param 		int		$category_id	the category ID to find the translation for
	 * @param		string	$default		the default value to return if nothing found or JoomFish not used
	 * @return 		string	the JoomFish translated value
	 * @since 		3.0
	 */
	private function _getJoomFishCategory($category_id, $default='') {
		$db = JFactory::getDBO();
		$template = JRequest::getVar('template');
		$csvilog = JRequest::getVar('csvilog');

		if ($template->getValue('use_joomfish', 'product', false)) {
			$q = "SELECT value
				FROM #__jf_content
				WHERE reference_table = 'vm_category'
				AND reference_field = 'category_name'
				AND language_id = ".$template->getValue('joomfish_language', 'product')."
				AND reference_id = ".$category_id;
			$db->setQuery($q);
			$csvilog->addDebug(JText::_('COM_CSVIVIRTUEMART_GET_CATEGORY_JF'), true);
			$category_name_jf = $db->loadResult();
			if (empty($category_name_jf)) return $default;
			else return $category_name_jf;
		}
		else return $default;
	}

	/**
	 * Format a date to unix timestamp
	 *
	 * Format of the date is day/month/year or day-month-year.
	 *
	 * @copyright
	 * @author 		RolandD
	 * @todo		use JDate
	 * @see
	 * @access 		protected
	 * @param 		string	$date	the date to convert
	 * @return		integer	UNIX timestamp if date is valid otherwise return 0
	 * @since
	 */
	protected function convertDate($date) {
		$new_date = preg_replace('/-|\./', '/', $date);
		$date_parts = explode('/', $new_date);

		if ((count($date_parts) == 3) && ($date_parts[0] > 0 && $date_parts[0] < 32 && $date_parts[1] > 0 && $date_parts[1] < 13 && (strlen($date_parts[2]) == 4))) {
			$old_date = mktime(0,0,0,$date_parts[1],$date_parts[0],$date_parts[2]);
		}
		else $old_date = 0;
		return $old_date;
	}
}
?>