<?php
/**
* @version	$Id: filenames_helper.php 14628 2011-10-04 09:36:30Z alex $
* @package	In-Portal
* @copyright	Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license      GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/

defined('FULL_PATH') or die('restricted access!');

class kFilenamesHelper extends kHelper {

	/**
	 * Character, that should replace disallowed symbols in filename
	 *
	 * @var string
	 */
	var $_escapeChar = '_';

	/**
	 * Sequences, that should be replaced with mathing sequences from _filenameReplaceTo property
	 *
	 * @var Array
	 */
	var $_filenameReplaceFrom = Array ();

	/**
	 * Sequences, that will replace matching sequences from _filenameReplaceFrom property
	 *
	 * @var Array
	 */
	var $_filenameReplaceTo = Array ();


	public function __construct()
	{
		parent::__construct();

		$this->_escapeChar = $this->Application->ConfigValue('FilenameSpecialCharReplacement');

		$language =& $this->Application->recallObject('lang.primary');
		/* @var $language kDBItem */

		$replacements = $language->GetDBField('FilenameReplacements');
		if ($replacements) {
			$replacements = explode("\r\n", $replacements);
			foreach ($replacements as $replacement) {
				list ($replace_from, $replace_to) = explode('=', $replacement);
				$this->_filenameReplaceFrom[] = trim($replace_from);
				$this->_filenameReplaceTo[] = trim($replace_to);
			}
		}
	}

	function replaceSequences($filename)
	{
		$not_allowed = Array (
			' ', '\\', '/', ':', '*', '?', '"', '<', '>', '|', '`',
			'~', '!', '@', '#', '$', '%', '^', '&', '(', ')', '~',
			'+', '=', '-', '{', '}', ']', '[', "'", ';', '.', ',', "\r", "\n"
		);

		if ($this->_filenameReplaceFrom) {
			// replace predefined sequences
			$filename = str_replace($this->_filenameReplaceFrom, $this->_filenameReplaceTo, $filename);
		}

		$filename = str_replace($not_allowed, $this->_escapeChar, $filename);
		$filename = preg_replace('/(' . $this->_escapeChar . '+)/', $this->_escapeChar, $filename);
		return trim($filename, $this->_escapeChar); // remove trailing escape chars
	}

	/**
	 * Replace not allowed symbols with "_" chars + remove duplicate "_" chars in result
	 *
	 * @param string $table
	 * @param string $id_field
	 * @param int $item_id
	 * @param string $filename
	 * @return string
	 */
	function stripDisallowed($table, $id_field, $item_id, $filename)
	{
		$filename = $this->replaceSequences($filename);

		return $this->checkAutoFilename($table, $id_field, $item_id, $filename);
	}

	function checkAutoFilename($table, $id_field, $item_id, $filename)
	{
		if (!$filename) {
			return $filename;
		}

		$item_id = !$item_id ? 0 : $item_id;

		if ( $this->Application->GetLiveName($table) == TABLE_PREFIX.'CategoryItems' ) {
			$sql_mask = '	SELECT CategoryId
							FROM %1$s
							WHERE ItemResourceId = %2$s';

			$item_categories_cur = $this->Conn->GetCol( sprintf($sql_mask, $table, $item_id) );

			if ( $this->Application->IsTempTable($table) ) {
				$item_categories_live = $this->Conn->GetCol( sprintf($sql_mask, $this->Application->GetLiveName($table), $item_id) );
			}
			else {
				$item_categories_live = Array ();
			}

			$item_categories = array_unique(array_merge($item_categories_cur, $item_categories_live));

			if (!$item_categories) {
				$item_categories = Array( $this->Application->GetVar('m_cat_id') ); // this may happen when creating new item
			}

			$cat_filter = ' AND CategoryId IN (' . implode(',', $item_categories) . ')';
		}
		else {
			$cat_filter = '';
		}

		// check current table (temp or live)
		$sql_mask = '	SELECT ' . $id_field . '
						FROM %1$s
						WHERE Filename = ' . $this->Conn->qstr($filename) . $cat_filter;
		$found_temp_ids = $this->Conn->GetCol( sprintf($sql_mask, $table) );

		// check live table if current is temp
		if ( $this->Application->IsTempTable($table) ) {
			$found_live_ids = $this->Conn->GetCol( sprintf($sql_mask, $this->Application->GetLiveName($table)) );
		}
		else {
			$found_live_ids = Array ();
		}

		$found_item_ids = array_unique( array_merge($found_temp_ids, $found_live_ids) );

		$has_page = preg_match('/(.*)_([\d]+)([a-z]*)$/', $filename, $rets);

		$duplicates_found = (count($found_item_ids) > 1) || ($found_item_ids && $found_item_ids[0] != $item_id);
		if ($duplicates_found || $has_page) {// other category has same filename as ours OR we have filename, that ends with _number
			$append = $duplicates_found ? $this->_escapeChar . 'a' : '';

			if ($has_page) {
				$filename = $rets[1].'_'.$rets[2];
				$append = $rets[3] ? $rets[3] : $this->_escapeChar . 'a';
			}

			// check live & temp table
			$sql_cur = 'SELECT ' . $id_field . '
						FROM ' . $table . '
						WHERE (Filename = %s) AND (' . $id_field . ' != ' . $item_id . ')' . $cat_filter;

			if ( $this->Application->IsTempTable($table) ) {
				$sql_live = '	SELECT ' . $id_field . '
								FROM ' . $this->Application->GetLiveName($table) . '
								WHERE (Filename = %s) AND (' . $id_field . ' != ' . $item_id . ')' . $cat_filter;
			}
			else {
				$sql_live = false;
			}

			while ( $this->Conn->GetOne( sprintf($sql_cur, $this->Conn->qstr($filename.$append)) ) > 0 ||
							(	$sql_live
								&&
								( $this->Conn->GetOne( sprintf($sql_live, $this->Conn->qstr($filename.$append)) ) > 0 )
							)
						)
			{
				if (mb_substr($append, -1) == 'z') $append .= 'a';
				$append = mb_substr($append, 0, mb_strlen($append) - 1) . chr( ord( mb_substr($append, -1) ) + 1 );
			}

			return $filename.$append;
		}

		return $filename;
	}
}