module-import/import/class.import.php
2017-04-13 23:07:40 +03:00

733 lines
18 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?
/**
* Класс, включающий все свойства и методы для управления документами
*
* @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;
}
}