<?php
/**
* @version	$Id: col_picker_helper.php 15425 2012-07-03 08:27:15Z 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 kColumnPickerHelper extends kHelper {

	var $PickerData;
	var $GridName;
	var $UseFreezer;

	/**
	 * Default column width in pixels
	 *
	 * @var int
	 */
	var $defaultColumnWidth = 100;

	/**
	 * Columns renamed by formatter in last used grid
	 *
	 * @var Array
	 */
	var $formatterRenamed = Array ();

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

		$this->UseFreezer = $this->Application->ConfigValue('UseColumnFreezer');
	}

	function LoadColumns($prefix)
	{
		$default_value = $this->Application->isAdmin ? ALLOW_DEFAULT_SETTINGS : false;
		$val = $this->Application->RecallPersistentVar($this->_getVarName($prefix, 'get'), $default_value);

		if (!$val) {
			$cols = $this->RebuildColumns($prefix);
		}
		else {
			$cols = unserialize($val);
			$current_cols = $this->GetColumns($prefix);

			if ($cols === false || $cols['crc'] != $current_cols['crc'])
			{
				$cols = $this->RebuildColumns($prefix, $cols);
			}
		}
		return $cols;
	}

	function PreparePicker($prefix, $grid_name)
	{
		$this->SetGridName($grid_name);
		$this->PickerData = $this->LoadColumns($prefix);
	}

	function ApplyPicker($prefix, &$fields, $grid_name)
	{
		$this->PreparePicker($prefix, $grid_name);
		uksort($fields, array($this, 'CmpElems'));
		$this->RemoveHiddenColumns($fields);
	}

	function SetGridName($grid_name)
	{
		$this->GridName = $grid_name;
	}

	function CmpElems($a, $b)
	{
		// remove language prefix from field, because formatter renamed column
		if (in_array($a, $this->formatterRenamed)) {
			$a = preg_replace('/^l[\d]+_/', '', $a);
		}

		if (in_array($b, $this->formatterRenamed)) {
			$b = preg_replace('/^l[\d]+_/', '', $b);
		}

		$a_index = array_search($a, $this->PickerData['order']);
		$b_index = array_search($b, $this->PickerData['order']);

		if ($a_index == $b_index) {
	        return 0;
	    }

	    return ($a_index < $b_index) ? -1 : 1;
	}

	function RebuildColumns($prefix, $current=null)
	{
		// get default columns from unit config
		$cols = $this->GetColumns($prefix);

		if (is_array($current)) {
			// 1. prepare visible columns

			// keep user column order (common columns between user and default grid)
			$common = array_intersect($current['order'], $cols['order']);

			// get new columns (found in default grid, but not found in user's grid)
			$added = array_diff($cols['order'], $current['order']);

			if (in_array('__FREEZER__', $added)) {
				// in case if freezer was added, then make it first column
				array_unshift($common, '__FREEZER__');
				unset($added[array_search('__FREEZER__', $added)]);
			}

			$cols['order'] = array_merge($common, $added);

			// 2. prepare hidden columns
			if ($added) {
				$hidden_added = array_intersect($added, $cols['hidden_fields']);
				$cols['hidden_fields'] = array_intersect($current['order'], $current['hidden_fields']);

				// when some of new columns are hidden, then keep them hidden
				foreach ($hidden_added as $position => $field) {
					$cols['hidden_fields'][$position] = $field;
				}
			}
			else {
				$cols['hidden_fields'] = array_intersect($current['order'], $current['hidden_fields']);
			}

			foreach($common as $col) {
				$cols['widths'][$col] = isset($current['widths'][$col]) ? $current['widths'][$col] : $this->defaultColumnWidth;
			}
			$this->SetCRC($cols);
		}
		$this->StoreCols($prefix, $cols);

		return $cols;
	}

	function StoreCols($prefix, $cols)
	{
		$this->Application->StorePersistentVar($this->_getVarName($prefix, 'set'), serialize($cols));
	}

	/**
	* Gets variable name in persistent session to store column positions in
	*
	* @param string $prefix
	* @param string $mode
	* @return string
	*/
	function _getVarName($prefix, $mode = 'get')
	{
		$view_name = $this->Application->RecallVar($prefix . '_current_view');

		$ret = $prefix . '[' . $this->GridName . ']columns_.' . $view_name;
		if ($mode == 'get') {
			if ($this->Application->RecallPersistentVar($ret) === false) {
				$ret = $prefix . '_columns_.' . $view_name;
			}
		}

		return $ret;
	}

	function GetColumns($prefix)
	{
		$splited = $this->Application->processPrefix($prefix);
		$grids = $this->Application->getUnitOption($splited['prefix'], 'Grids');
		$conf_fields = $this->UseFreezer ? array_merge_recursive(
			array('__FREEZER__' => array('title' => '__FREEZER__')),
			$grids[$this->GridName]['Fields']
		) : $grids[$this->GridName]['Fields'];
//		$conf_fields = $grids[$this->GridName]['Fields'];

		// we NEED to recall dummy here to apply fields changes imposed by formatters,
		// such as replacing multilingual field titles etc.
		$dummy = $this->Application->recallObject($prefix, null, Array ('skip_autoload' => 1));

		$counter = 0;
		$hidden = array();
		$fields = array();
		$titles = array();
		$widths = array();
		foreach ($conf_fields as $name => $options) {
			if (array_key_exists('formatter_renamed', $options) && $options['formatter_renamed']) {
				// remove language prefix from field, because formatter renamed column
				$this->formatterRenamed[] = $name;
				$name = preg_replace('/^l[\d]+_/', '', $name);
			}

			$fields[$counter] = $name;
			$titles[$name] = isset($options['title']) ? $options['title'] : 'column:la_fld_' . $name;
			$widths[$name] = isset($options['width']) ? $options['width'] : $this->defaultColumnWidth; // only once per grid !

			if (isset($options['hidden']) && $options['hidden']) {
				$hidden[$counter] = $name;
			}

			$counter++;
		}
		$sorted_fields = $fields;
		sort($sorted_fields);
		$cols = array(
			'order' => $fields,
			'titles' => $titles,
			'hidden_fields' => $hidden,
			'widths' => $widths,
		);
		$this->SetCRC($cols);
		return $cols;
	}

	function SetCRC(&$cols)
	{
		$sorted_fields = $cols['order'];
		$sorted_titles = $cols['titles'];
		asort($sorted_fields);
		asort($sorted_titles);
		$cols['crc'] = crc32(implode(',', $sorted_fields).implode(',', $sorted_titles));
	}

	function RemoveHiddenColumns(&$fields)
	{
		$to_remove = array();
		foreach ($fields as $name => $options) {
			if (array_key_exists('formatter_renamed', $options) && $options['formatter_renamed']) {
				// remove language prefix from field, because formatter renamed column
				$name_renamed = preg_replace('/^l[\d]+_/', '', $name);
			}
			else {
				$name_renamed = $name;
			}

			if (array_search($name_renamed, $this->PickerData['hidden_fields']) !== false) {
				$to_remove[] = $name;
			}
		}

		foreach ($to_remove as $name) {
			unset($fields[$name]);
		}
	}

	function SaveColumns($prefix, $picked, $hidden)
	{
		$order = $picked ? explode('|', $picked) : array();
		$hidden = $hidden ? explode('|', $hidden) : array();
		$order = array_merge($order, $hidden);

		$cols = $this->LoadColumns($prefix);
		$cols['order'] = $order;
		$cols['hidden_fields'] = $hidden;

		$this->SetCRC($cols);
		$this->StoreCols($prefix, $cols);
	}

	function SaveWidths($prefix, $widths)
	{
		if (!is_array($widths)) {
			$widths = explode(':', $widths);
		}

		$i = 0;
		array_shift($widths); // removing first col (checkbox col) width

		foreach ($this->PickerData['order'] as $ord => $field) {
			if ($field == '__FREEZER__') {
				continue;
			}

			$this->PickerData['widths'][$field] = isset($widths[$i]) ? $widths[$i] : $this->defaultColumnWidth;
			$i++;
		}

		$this->StoreCols($prefix, $this->PickerData);
	}

	function GetWidth($field)
	{
		if (in_array($field, $this->formatterRenamed)) {
			// remove language prefix from field, because formatter renamed column
			$field = preg_replace('/^l[\d]+_/', '', $field);
		}

		return isset($this->PickerData['widths'][$field]) ? $this->PickerData['widths'][$field] : false;
	}
}