Модуль импорта v2.26.0 (Light версия)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

732 lines
18 KiB

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