<?
/**
 * Класс, включающий все свойства и методы для управления документами
 *
 * @package AVE.cms
 * @subpackage module_DocManager
 * @filesource
 */

class ModuleImport
{

/**
 *	Свойства класса
 */

	/**
	 * Путь к директории с шаблонами модуля
	 */
	var $tpl_dir;

	/**
	 * Основные поля документа, предлагаемые для импорта
	 */
	var $fields_main = array(
		'Id',
		'document_title',
		'document_alias',
		'document_meta_keywords',
		'document_meta_description',
		'document_meta_robots',
		'document_published',
		'document_expire',
		'document_in_search',
		'document_status',
		'document_deleted',
		'document_linked_navi_id',
		'document_breadcrum_title',
		'document_parent',
		'document_count_view',
		'document_lang'
	);

/**
 *	Внутренние методы
 */

	/**
	 *	Метод получения импорта
	 * $small - для сохранения памяти при импорте
	 */
	function _import($import_id, $type='row', $small = false)
	{
		global $AVE_DB;

		// забираем импорт
		$import = $AVE_DB->Query("
			SELECT " . ($small
				? "i.rub_id,i.name,i.parser,i.docs_disable,i.docs_create,i.fields,i.file	FROM " . PREFIX . "_module_import AS i"
				: "i.*, r.rubric_title AS rub_title
			FROM
				" . PREFIX . "_module_import AS i
			LEFT JOIN
				" . PREFIX . "_rubrics AS r ON r.Id = i.rub_id"
			) . "
			WHERE
				i.id=" . (int)$import_id
		)->FetchRow();

		// поля
		$import->fields = $import->fields ? unserialize($import->fields) : array();

		// теги
		if (isset($import->tags))
			$import->tags = $import->tags
				? unserialize($import->tags)
				: array();

		// возвращаем массив, если попросили
		if ($type != 'row' && $type != 'r')
			$import = (array)$import;

		return $import;
	}

	/**
	 * Метод рекурсивно создаёт массив замен
	 */
	function _replace($mixed, $key = '', $new = true)
	{
		static $arr = array();

		if ($new)
			$arr = array();

		if (! is_array($mixed))
			return $arr['[row' . $key . ']'] = $mixed;

		$res = $key;

		foreach ($mixed as $k => $v)
		{
			if(is_array($v))
			{
				$arr['[row:' . $k . ']'] = serialize($v);
			}
			$this->_replace($v, $res . ':' . $k, false);
		}

		return $arr;
	}

	/**
	 * Метод рекурсивно создаёт массив замен
	 */
	function _maketag($key)
	{
		return '[row:' . $key . ']';
	}

	/**
	 * Метод заменяет в шаблонах полей теги и выполняет код php
	 */
	function _parse_tpl(&$item, &$key, $replace)
	{
		$code = stripslashes(strtr($item,$replace));

		$item = trim(eval2var('?>' . $code . '<?'));

		if ($unser = unserialize($item))
			$item = $unser;
	}

	/**
	 * Проверка наличия документа по ключевым полям
	 *
	 * @param array $array - массив ID_поля_в_рубрике=>Ключевое_значение
	 * @param int $rub - id рубрики
	 *
	 * @return int/false - возвращает Id документа или false
	 */
	function _docs_find(&$fields_key, $fields_comp, $item_fields, $rub_id)
	{
		global $AVE_DB;

		if (! $fields_key)
			return 0;

		foreach($fields_key['main'] as $field_id => &$val)
		{
			$val = $item_fields['main'][$field_id];

			if ($fields_comp['main'][$field_id] == 'LIKE')
				$main[] = 'a.' . $field_id . " LIKE '%" . (string)addslashes($item_fields['main'][$field_id]) . "%'";
			else
				$main[] = 'a.' . $field_id . " = '" . (string)addslashes($item_fields['main'][$field_id]) . "'";
		}

		if ($main)
			$main = ' AND ' . implode(' AND ', $main);

		$x = 0;

		foreach($fields_key['body'] as $field_id => &$val)
		{
			$val = $item_fields['body'][$field_id];

			$tables[] = PREFIX . "_document_fields AS t" . $x;

			if ($fields_comp['body'][$field_id] == 'LIKE')
				$body[] = "(a.Id=t" . $x . ".document_id AND (t" . $x . ".rubric_field_id = " . $field_id . " AND t" . $x . ".field_value LIKE '%" . (string)addslashes($item_fields['body'][$field_id]) . "%'))";
			else
				$body[] = "(a.Id=t" . $x . ".document_id AND (t" . $x . ".rubric_field_id = " . $field_id . " AND t" . $x . ".field_value = '" . (string)addslashes($item_fields['body'][$field_id]) . "'))";

			$x++;
		}

		if ($tables)
			$tables = ', ' . implode(', ', $tables);

		if ($body)
			$body = ' AND ' . implode(' AND ', $body);

		$docids = array();

		$sql = $AVE_DB->Real_Query("
			SELECT
				a.Id AS id
			FROM
				" . PREFIX . "_documents AS a " . $tables . "
			WHERE
				a.rubric_id = " . $rub_id .
				$main .
				$body
		);

		while ($docid = $sql->FetchRow()->id)
			$docids[] = $docid;

		return $docids;
	}

/**
 *	Внешние методы
 */

	/**
	 *	Метод вывода импортов
	 */
	function importsList ()
	{
		global $AVE_DB, $AVE_Template;

		// Забираем все импорты
		$limit = 20;

		$start = get_current_page() * $limit - $limit;

		$sql = $AVE_DB->Query("
			SELECT SQL_CALC_FOUND_ROWS
				*
			FROM
				" . PREFIX . "_module_import
			ORDER BY
				id ASC
			LIMIT
				" . $start . "," . $limit
		);

		while ($import = $sql->FetchAssocArray())
		{
			$import['rub_title'] = $AVE_DB->Query("
				SELECT
					rubric_title
				FROM
					" . PREFIX . "_rubrics
				WHERE
					id=" . (int)$import['rub_id']
			)->GetCell();

			$imports[] = $import;
		}

		$num = $AVE_DB->NumAllRows;

		if ($num > $limit)
		{
			$page_nav = '<a class="pnav" href="index.php?do=modules&amp;action=modedit&amp;mod=import&amp;moduleaction=1&amp;page={s}&amp;cp=' . SESSION . '">{t}</a>';
			$page_nav = get_pagination($pages, 'page', $page_nav);
			$AVE_Template->assign('page_nav', $page_nav);
		}

		$AVE_Template->assign('imports',$imports);
		$AVE_Template->assign('content', $AVE_Template->fetch($this->tpl_dir . 'admin_list.tpl'));
	}

	/**
	 *	Метод создания и редактирования импорта
	 */
	function importEdit ($import_id=null)
	{
		global $AVE_DB, $AVE_Template;

		if ($import_id)
		{
			$import = $this->_import($import_id, 'array');

			$import_fields = array();

			// основные поля
			foreach ($this->fields_main as $field_id)
			{
				$import_fields['main'][$field_id] = isset($import['fields']['main'][$field_id]) ? $import['fields']['main'][$field_id] : array();
				$import_fields['main'][$field_id]['title'] = $AVE_Template->get_config_vars('field_' . $field_id);
			}

			// поля рубрики
			$sql = $AVE_DB->Query("
				SELECT
					Id AS id,
					rubric_field_title AS title
				FROM
					" . PREFIX . "_rubric_fields
				WHERE
					rubric_id = '" . (int)$import['rub_id'] . "'
				ORDER BY
					rubric_field_position
			");

			while ($field = $sql->FetchRow())
			{
				$field_id = $field->id;

				$import_fields['body'][$field_id] = isset($import['fields']['body'][$field_id])
					? $import['fields']['body'][$field_id]
					: array();

				$import_fields['body'][$field_id]['title'] = $field->title;
			}

			$import['fields'] = $import_fields;
		}
		else
		{
			// рубрики
			$sql = $AVE_DB->Query("
				SELECT
					Id AS id,
					rubric_title AS title
				FROM
					" . PREFIX . "_rubrics
			");

			while ($row = $sql->FetchAssocArray())
			{
				$rubs[] = $row;
			}

			$AVE_Template->assign('rubs',$rubs);
		}

		// парсеры
		require_once (BASE_DIR . '/modules/import/class.import.parsers.php');

		$parsers = get_class_methods('ModuleImportParsers');

		$AVE_Template->assign('parsers',$parsers);
		$AVE_Template->assign('import_id',$import_id);
		$AVE_Template->assign('import',$import);
		$AVE_Template->assign('content', $AVE_Template->fetch($this->tpl_dir . 'admin_edit.tpl'));
	}

	/**
	 *	Метод сохранения профиля обмена
	 */
	function importSave ($import_id=null)
	{
		global $AVE_DB, $AVE_Template;

		// если новый
		if (! $import_id)
		{
			$AVE_DB->Query("
				INSERT INTO
					" . PREFIX . "_module_import
				SET
					name			= '" . addslashes($_POST['name']) . "',
					rub_id			= '" . (int)$_POST['rub_id'] . "',
					parser			= '" . $_POST['parser'] . "',
					docs_disable	= '" . (int)$_POST['docs_disable'] . "',
					docs_create		= '" . (int)$_POST['docs_create'] . "',
					file			= '" . trim(trim($_POST['file']),'/') . "',
					monitor			= '" . (int)$_POST['monitor'] . "',
					time_edited		= '" . time() . "'
			");
			$import_id = $AVE_DB->InsertId();
		}
		else // если редактирование
		{
			$import_fields = array(
				'main' => array(),
				'body' => array()
			);

			// чистим массив от пустых шаблонов
			foreach ($_POST['fields']['main'] as $field_id => $field)
			{
				$field['tpl'] = trim((string)$field['tpl']);

				if ($field['tpl'] === '')
					unset($field['tpl']);

				if (!$field['comp'])
					unset($field['comp']);
				elseif ($field['comp'] === 'LIKE' && isset($field['active']))
					unset($field['active']);

				if (! empty($field))
					$import_fields['main'][$field_id] = $field;
			}

			foreach ($_POST['fields']['body'] as $field_id => $field)
			{
				$field['tpl'] = trim((string)$field['tpl']);

				if ($field['tpl'] === '')
					unset($field['tpl']);

				if (!$field['comp'])
					unset($field['comp']);
				elseif ($field['comp'] === 'LIKE' && isset($field['active']))
					unset($field['active']);

				if (! empty($field)) $import_fields['body'][$field_id] = $field;
			}

			// записываем изменения в бд
			$AVE_DB->Query("
				UPDATE
					" . PREFIX . "_module_import
				SET
					name				= '" . addslashes($_POST['name']) . "',
					parser				= '" . $_POST['parser'] . "',
					docs_disable		= '" . (int)$_POST['docs_disable'] . "',
					docs_create			= '" . (int)$_POST['docs_create'] . "',
					file				= '" . trim(trim($_POST['file']),'/') . "',
					monitor				= '" . (int)$_POST['monitor'] . "',
					fields				= '" . addslashes(serialize($import_fields)) . "',
					time_edited			= '" . time() . "'
				WHERE
					id					= '" . $import_id . "'
			");
		}
		if (isAjax())
		{
			$message = $AVE_Template->get_config_vars('saved');
			$header = $AVE_Template->get_config_vars('success');
			$theme = 'accept';

			echo json_encode(array('message' => $message, 'header' => $header, 'theme' => $theme));
			exit;
		}
		else
			{
				return $import_id;
			}
	}

	/**
	 *	Метод удаления импорта
	 */
	function importDelete ($import_id)
	{
		global $AVE_DB;

		$AVE_DB->Query("
			DELETE FROM
				" . PREFIX . "_module_import
			WHERE
				id = " . $import_id
		);
	}

	/**
	 *	Метод копирования импорта
	 */
	function importCopy ($import_id)
	{
		global $AVE_DB;

		$_POST = $this->_import($import_id,'array');

		// сначала создаём и получаем id
		$import_id = $this->importSave();

		// теперь сохраняем всё остальное
		return $this->importSave($import_id);
	}

	/**
	 * Импорт
	 */
	function importRun ($import_id, $tags_only = false, $file = null, $write_log = false)
	{
		global $AVE_DB;

		require_once(BASE_DIR . '/class/class.docs.php');
		$AVE_Document = new AVE_Document();

		// задаём переменные
		$fields_active = array();
		$fields_key = array();
		$fields_oblig = array();
		$fields_comp = array();
		$fields = array();

		// Получаем параметры импорта и создаём переменные с параметрами полей
		$import = $this->_import($import_id, 'row', true);

		foreach ($import->fields['main'] as $field_id => &$field)
		{
			if (!isset($field['tpl']))
				$field['tpl'] = '';

			if ($field['active'] && $field['comp'] != 'LIKE')
				$fields_active['main'][$field_id] = true;

			if ($field['key'])
			{
				$fields_key['main'][$field_id] = '';
				$fields_comp['main'][$field_id] = (isset($field['comp']) && $field['comp'] == 'LIKE') ? 'LIKE' : '';
			}

			if ($field['oblig'])
				$fields_oblig['main'][] = $field_id;

			if ($field['active'] || $field['tpl'] > '')
				$fields['main'][$field_id] = $field['tpl'];
		}

		foreach ($import->fields['body'] as $field_id => &$field)
		{
			if (! isset($field['tpl']))
				$field['tpl'] = '';

			if ($field['active'] && $field['comp'] != 'LIKE')
				$fields_active['body'][$field_id] = true;

			if ($field['key'])
			{
				$fields_key['body'][$field_id] = '';
				$fields_comp['body'][$field_id] = (isset($field['comp']) && $field['comp'] == 'LIKE') ? 'LIKE' : '';
			}

			if ($field['oblig'])
				$fields_oblig['body'][] = $field_id;

			if ($field['active'] || $field['tpl'] > '')
				$fields['body'][$field_id] = $field['tpl'];
		}

		// определяем файл
		// если файл не передан как аргумент функции, то берём из настроек
		if (! isset($file))
			$file = BASE_DIR . '/' . $import->file;

		// если файл существует, парсим его
		if (file_exists($file) && is_file($file))
		{
			require_once (BASE_DIR . '/modules/import/class.import.parsers.php');

			$ModuleImportParsers = new ModuleImportParsers;

			$parser = $import->parser;

			$import_data = $ModuleImportParsers->$parser($file);
		}

		// если в итоге (из файла или из кода) был
		// сформирован массив $import_data, то продолжаем
		// иначе, выходим
		if (! isset($import_data))
			exit('Отсутствует файл! В ходе выполнения кода массив $import_data также не был передан!');

		// Если просили узнать только теги, проходим весь массив $import_data и собираем теги
		/* !tags_only */
		if ($tags_only)
		{
			$tags = array();

			foreach ($import_data['tags'] as $item)
			{
				$tags[] = $this->_maketag($item);
			}

			$tags = array_unique($tags);

			$AVE_DB->Query("
				UPDATE
					" . PREFIX . "_module_import
				SET
					tags = '" . serialize($tags) . "'
				WHERE
					id = " . $import_id
			);

			return $tags;
		}

		// Помечаем документы как неактивные в указанной рубрике, если нужно
		if($import->docs_disable && !$tags_only)
		{
			$AVE_DB->Query("
				UPDATE
					" . PREFIX . "_documents
				SET
					document_status = '0'
				WHERE
					rubric_id=" . $import->rub_id
			);
		}

		// чистим память
		unset ($import->fields, $import->code_start, $parser, $ModuleImportParsers, $file);

		$i = 0;

		$log = array(
			'updated'	=> array(),
			'created'	=> array(),
			'notfound'	=> array()
		);

		// Обрабатываем по очереди каждый объект
		foreach($import_data['rows'] as $item)
		{
			// создаем массив замен
			$replace = array();
			$replace = $this->_replace($item);
			$replace['[Y-m-d]'] = date('d.m.Y H:i');

			// парсим шаблоны
			$item_fields = $fields;

			array_walk_recursive($item_fields, array($this, '_parse_tpl'), $replace);

			// чистим память
			unset ($replace,$item);

			$pass = true;

			// проверяем обязательные поля в параметрах документа
			foreach ($fields_oblig['main'] as $field_id)
			{
				if (trim($item_fields['main'][$field_id]) === '')
				{
					$pass = false;
					break;
				}
			}

			if (! $pass)
				continue;

			// проверяем обязательные поля в теле документа
			foreach ($fields_oblig['body'] as $field_id)
			{
				if (trim($item_fields['body'][$field_id]) === '')
				{
					$pass = false;
					break;
				}
			}

			if (! $pass)
				continue;

			// находим документ по ключевым полям
			$docids = $this->_docs_find($fields_key, $fields_comp, $item_fields, $import->rub_id);

			// если не совпал и не создаём новые
			if (! $docids && !$import->docs_create && $write_log)
			{
				$log['notfound'][] = array('fields_key' => $fields_key, 'fields_values' => $item_fields);
				continue;
			}
			// если указано создавать документы при несовпадении, добавляем нулевой id
			elseif (! $docids && $import->docs_create)
				$docids[] = 0;

			// проходим каждый документ
			foreach ($docids as $doc_id)
			{
				if ($doc_id)
				{
					$doc = $AVE_DB->Real_Query("
						SELECT
							*
						FROM
							" . PREFIX . "_documents
						WHERE
							Id = '" . $doc_id . "'
					")->FetchAssocArray();

					// прописываем текущие значения в поля main, которые не надо импортировать
					foreach($this->fields_main as $field_id)
					{
						if(! $fields_active['main'][$field_id])
						{
							$item_fields['main'][$field_id] = $doc[$field_id];
						}
					}

					unset ($doc);
				}

				// меняем время, если в UNIX-е
				if (strlen((string)$item_fields['main']['document_published']) == 10)
					$item_fields['main']['document_published'] = date('d.m.Y H:i', $item_fields['main']['document_published']);

				if (strlen((string)$item_fields['main']['document_expire']) == 10)
					$item_fields['main']['document_expire'] = date('d.m.Y H:i', $item_fields['main']['document_expire']);

				// удаляем ненужные поля из полей рубрики
				foreach($item_fields['body'] as $field_id => $field)
				{
					if (! $fields_active['body'][$field_id])
						unset($item_fields['body'][$field_id]);
					else
					// если поле оказалось пустым, убираем значение из формы
					$item_fields['body'][$field_id] = preg_replace('/\[row:(.+?)\]/', '', $item_fields['body'][$field_id]);
				}

				// удаляем Id документа
				unset ($item_fields['main']['Id']);

				// сохраняем документ
				$data = array();
				$data = $item_fields['main'];
				$data['doc_title'] = $data['document_title'];
				$data['document_expire'] = date("d.m.Y H:i", strtotime('+20 year'));
				$data['feld'] = $item_fields['body'];
				$data['import'] = 1;

				$response = $AVE_Document->documentSave($import->rub_id, $doc_id, $data);

				// записываем лог
				if ($write_log)
				{
					// если совпал и обновлён
					if ($doc_id)
						$log['updated'][$doc_id] = array('fields_key' => $fields_key);

					// если не совпал и создан
					else
						$log['created'][$response] = array('fields_key' => $fields_key);
				}
			}
		}

		$AVE_DB->Query("
			UPDATE
				" . PREFIX . "_module_import
			SET
				time_run = '" . time() . "'
			WHERE
				id = " . $import_id
		);

		return $log;
	}
}