939 lines
38 KiB
PHP
939 lines
38 KiB
PHP
<?php
|
||
|
||
/**
|
||
* Класс для обработки тегов шаблона.
|
||
*
|
||
* @package AVE.cms
|
||
* @filesource
|
||
*/
|
||
class TagProcessor
|
||
{
|
||
private int $item_num;
|
||
private bool $is_last;
|
||
private object $row;
|
||
private int $rubric_id;
|
||
private int $items_count;
|
||
|
||
/**
|
||
* Конструктор класса.
|
||
*
|
||
* @param int $item_num Текущий номер элемента во всем списке (начиная с 1).
|
||
* @param bool $is_last Флаг, указывающий, является ли элемент последним.
|
||
* @param object $row Объект с данными документа.
|
||
* @param int $rubric_id ID рубрики.
|
||
* @param int $items_count Количество элементов на текущей странице.
|
||
*/
|
||
public function __construct(int $item_num, bool $is_last, object $row, int $rubric_id, int $items_count)
|
||
{
|
||
$this->item_num = $item_num;
|
||
$this->is_last = $is_last;
|
||
$this->row = $row;
|
||
$this->rubric_id = $rubric_id;
|
||
$this->items_count = $items_count;
|
||
}
|
||
|
||
/**
|
||
* Основной метод для обработки всех условных тегов в строке.
|
||
*
|
||
* @param string $content Строка с тегами, например, '[tag:if_first]...[/tag:if]'
|
||
* @return string Обработанная строка
|
||
*/
|
||
public function process(string $content): string
|
||
{
|
||
// Сначала обрабатываем теги if_notempty и if_empty
|
||
$processed_content = preg_replace_callback(
|
||
'/\\[tag:(if_notempty|if_empty):rfld:([a-zA-Z0-9-_]+)]\\[(more|esc|img|strip|[0-9-]+)](.*?)\\[tag:\\/if]/s',
|
||
function ($matches) {
|
||
$tag_type = $matches[1];
|
||
$field_name = $matches[2];
|
||
$format = $matches[3];
|
||
$inner_content = $matches[4];
|
||
|
||
$parts = explode('[tag:if_else]', $inner_content);
|
||
$true_content = $parts[0];
|
||
$false_content = $parts[1] ?? '';
|
||
|
||
$field_value = '';
|
||
if (defined('USE_GET_FIELDS') && USE_GET_FIELDS) {
|
||
$field_value = htmlspecialchars(get_field($field_name, (int)$this->row->Id), ENT_QUOTES);
|
||
} else {
|
||
$field_value = htmlspecialchars(request_get_document_field($field_name, (int)$this->row->Id, $format, $this->rubric_id), ENT_QUOTES);
|
||
}
|
||
|
||
$condition = ($tag_type === 'if_notempty' && $field_value !== '') || ($tag_type === 'if_empty' && $field_value === '');
|
||
|
||
return $condition ? $true_content : $false_content;
|
||
},
|
||
$content
|
||
);
|
||
|
||
// Затем обрабатываем остальные условные теги
|
||
$processed_content = preg_replace_callback(
|
||
'/\\[tag:(if_first|if_not_first|if_last|if_not_last|if_every:([0-9-]+)|if_not_every:([0-9-]+))](.*?)\\[tag:\\/if]/s',
|
||
function ($matches) {
|
||
$tag = $matches[1];
|
||
$inner_content = $matches[4];
|
||
|
||
$parts = explode('[tag:if_else]', $inner_content);
|
||
$true_content = $parts[0];
|
||
$false_content = $parts[1] ?? '';
|
||
|
||
$condition = false;
|
||
|
||
if ($tag === 'if_first') {
|
||
$condition = ($this->item_num === 1);
|
||
} elseif ($tag === 'if_not_first') {
|
||
$condition = ($this->item_num !== 1);
|
||
} elseif ($tag === 'if_last') {
|
||
$condition = $this->is_last;
|
||
} elseif (strpos($tag, 'if_not_last') === 0) {
|
||
$condition = !$this->is_last;
|
||
} elseif (strpos($tag, 'if_every') === 0) {
|
||
$mod = (int)($matches[2] ?? 0);
|
||
$condition = ($this->item_num > 0 && $mod > 0 && ($this->item_num % $mod) === 0);
|
||
} elseif (strpos($tag, 'if_not_every') === 0) {
|
||
$mod = (int)($matches[3] ?? 0);
|
||
$condition = ($this->item_num > 0 && $mod > 0 && ($this->item_num % $mod) !== 0);
|
||
}
|
||
|
||
return $condition ? $true_content : $false_content;
|
||
},
|
||
$processed_content
|
||
);
|
||
|
||
return $processed_content;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Функция для обработки тегов с использованием TagProcessor.
|
||
*
|
||
* @param string $items Строка с тегами.
|
||
* @param int $item_num Текущий номер элемента.
|
||
* @param bool $is_last Флаг, указывающий, является ли элемент последним.
|
||
* @param object $row Объект с данными документа.
|
||
* @param int $items_count Общее количество элементов на текущей странице.
|
||
* @return string Обработанная строка.
|
||
*/
|
||
function request_process_tags($items, $item_num, $is_last, $row, $items_count)
|
||
{
|
||
// Создаем экземпляр обработчика, передавая общее количество
|
||
$processor = new TagProcessor($item_num, $is_last, $row, (int)$row->rubric_id, $items_count);
|
||
|
||
// Обрабатываем содержимое и возвращаем результат
|
||
return $processor->process($items);
|
||
}
|
||
|
||
/**
|
||
* Достаем настройки запроса
|
||
*
|
||
* @param string|int $id Идентификатор или псевдоним запроса
|
||
* @return object|string Объект с настройками запроса или пустая строка в случае ошибки
|
||
*/
|
||
function request_get_settings ($id)
|
||
{
|
||
global $AVE_DB;
|
||
|
||
// Получаем информацию о запросе
|
||
$sql = "
|
||
SELECT
|
||
#REQUEST SETTINGS = " . $id . "
|
||
*
|
||
FROM
|
||
" . PREFIX . "_request
|
||
WHERE
|
||
" . (is_numeric($id) ? 'Id' : 'request_alias') . " = '" . $id . "'
|
||
";
|
||
|
||
// Выполняем запрос с учетом кеширования
|
||
$reqest_settings = $AVE_DB->Query($sql, -1, 'rqs_' . $id, true, '.settings')->FetchRow();
|
||
|
||
// Выходим, если нет запроса
|
||
if (! is_object($reqest_settings))
|
||
return '';
|
||
else
|
||
return $reqest_settings;
|
||
}
|
||
|
||
/**
|
||
* Обработка условий запроса.
|
||
* Возвращает строку условий в SQL-формате.
|
||
*
|
||
* @param int|string $id ID или алиас запроса.
|
||
*
|
||
* @return string Возвращает строку SQL-условия.
|
||
*/
|
||
function request_get_condition_sql_string($id)
|
||
{
|
||
global $AVE_DB, $AVE_Core;
|
||
|
||
// Используем request_get_settings() для получения ID и настроек запроса.
|
||
$request_settings = request_get_settings($id);
|
||
|
||
// Выходим, если запрос не найден.
|
||
if (!is_object($request_settings)) {
|
||
return '';
|
||
}
|
||
|
||
$from = [];
|
||
$where = [];
|
||
$retval = '';
|
||
$i = 0;
|
||
|
||
if (!defined('ACP'))
|
||
{
|
||
$doc = 'doc_' . $AVE_Core->curentdoc->Id;
|
||
|
||
if (isset($_POST['req_' . $id]))
|
||
{
|
||
$_SESSION[$doc]['req_' . $id] = $_POST['req_' . $id];
|
||
}
|
||
elseif (isset($_SESSION[$doc]['req_' . $id]))
|
||
{
|
||
$_POST['req_' . $id] = $_SESSION[$doc]['req_' . $id];
|
||
}
|
||
}
|
||
|
||
// Теперь мы можем безопасно запросить условия, используя гарантированный ID.
|
||
$sql_ak = $AVE_DB->Query(
|
||
"
|
||
SELECT
|
||
condition_field_id,
|
||
condition_value,
|
||
condition_compare,
|
||
condition_join
|
||
FROM " . PREFIX . "_request_conditions
|
||
WHERE
|
||
request_id = '" . $request_settings->Id . "'
|
||
AND condition_status = '1'
|
||
ORDER BY
|
||
condition_position ASC;
|
||
",
|
||
-1,
|
||
'rqc_' . $request_settings->Id,
|
||
true,
|
||
'.conditions'
|
||
);
|
||
|
||
if (!empty($_POST['req_' . $id]) && is_array($_POST['req_' . $id]))
|
||
{
|
||
foreach ($_POST['req_' . $id] as $fid => $val)
|
||
{
|
||
if (!($val != '' && isset($_SESSION['val_' . $fid]) && in_array($val, $_SESSION['val_' . $fid]))) continue;
|
||
|
||
if ($i) $from[] = "JOIN " . PREFIX . "_document_fields AS t$i ON t$i.document_id = t0.document_id";
|
||
|
||
$where[] = "t$i.rubric_field_id = " . $fid . " AND t$i.field_value = '" . $AVE_DB->Escape($val) . "'";
|
||
|
||
++$i;
|
||
}
|
||
}
|
||
|
||
while ($row_ak = $sql_ak->FetchRow())
|
||
{
|
||
$fid = $row_ak->condition_field_id;
|
||
|
||
if (isset($_POST['req_' . $id]) && isset($_POST['req_' . $id][$fid])) continue;
|
||
|
||
if ($i) $from[] = "JOIN " . PREFIX . "_document_fields AS t$i ON t$i.document_id = t0.document_id";
|
||
|
||
$val = $row_ak->condition_value;
|
||
|
||
switch ($row_ak->condition_compare)
|
||
{
|
||
case ' <': $where[] = "t$i.rubric_field_id = " . $fid . " AND t$i.field_value < '" . $AVE_DB->Escape($val) . "'"; break;
|
||
case ' >': $where[] = "t$i.rubric_field_id = " . $fid . " AND t$i.field_value > '" . $AVE_DB->Escape($val) . "'"; break;
|
||
case '<=': $where[] = "t$i.rubric_field_id = " . $fid . " AND t$i.field_value <= '" . $AVE_DB->Escape($val) . "'"; break;
|
||
case '>=': $where[] = "t$i.rubric_field_id = " . $fid . " AND t$i.field_value >= '" . $AVE_DB->Escape($val) . "'"; break;
|
||
case '==': $where[] = "t$i.rubric_field_id = " . $fid . " AND t$i.field_value = '" . $AVE_DB->Escape($val) . "'"; break;
|
||
case '!=': $where[] = "t$i.rubric_field_id = " . $fid . " AND t$i.field_value != '" . $AVE_DB->Escape($val) . "'"; break;
|
||
case '%%': $where[] = "t$i.rubric_field_id = " . $fid . " AND t$i.field_value LIKE '%" . $AVE_DB->Escape($val) . "%'"; break;
|
||
case '%': $where[] = "t$i.rubric_field_id = " . $fid . " AND t$i.field_value LIKE '" . $AVE_DB->Escape($val) . "%'"; break;
|
||
case '--': $where[] = "t$i.rubric_field_id = " . $fid . " AND t$i.field_value NOT LIKE '%" . $AVE_DB->Escape($val) . "%'"; break;
|
||
case '!-': $where[] = "t$i.rubric_field_id = " . $fid . " AND t$i.field_value NOT LIKE '" . $AVE_DB->Escape($val) . "%'"; break;
|
||
}
|
||
|
||
if ($i || $row_ak->condition_join == 'AND') ++$i;
|
||
}
|
||
|
||
if (!empty($where))
|
||
{
|
||
$from = ' FROM ' . PREFIX . '_document_fields AS t0 ' . implode(' ', $from);
|
||
$where = ' WHERE ' . (($i) ? implode(' AND ', $where) : '(' . implode(') OR(', $where) . ')');
|
||
$retval = 'AND a.Id = ANY(SELECT t0.document_id' . $from . $where . ')';
|
||
}
|
||
|
||
if (defined('ACP'))
|
||
{
|
||
$AVE_DB->Query("
|
||
UPDATE " . PREFIX . "_request
|
||
SET request_where_cond = '" . addslashes($retval) . "'
|
||
WHERE Id = '" . $request_settings->Id . "'
|
||
");
|
||
}
|
||
|
||
return $retval;
|
||
}
|
||
|
||
/**
|
||
* Функция обработки тэгов полей с использованием шаблонов
|
||
* в соответствии с типом поля
|
||
*
|
||
* @param int $rubric_id идентификатор рубрики
|
||
* @param int $document_id идентификатор документа
|
||
* @param int $maxlength максимальное количество символов обрабатываемого поля
|
||
* @return string
|
||
*/
|
||
function request_get_document_field ($field_id, $document_id, $maxlength = null, $rubric_id = 0)
|
||
{
|
||
if (! is_numeric($document_id) || $document_id < 1)
|
||
return '';
|
||
|
||
$_maxlength = $maxlength;
|
||
|
||
$document_fields = get_document_fields($document_id);
|
||
|
||
// ToDo
|
||
if (! is_array($document_fields[$field_id]))
|
||
$field_id = intval($document_fields[$field_id]);
|
||
|
||
if (empty($document_fields[$field_id]))
|
||
return '';
|
||
|
||
$field_value = trim($document_fields[$field_id]['field_value']);
|
||
|
||
if ($field_value == '' && $document_fields[$field_id]['tpl_req_empty'])
|
||
return '';
|
||
|
||
$func = 'get_field_' . $document_fields[$field_id]['rubric_field_type'];
|
||
|
||
if (! is_callable($func))
|
||
$func = 'get_field_default';
|
||
|
||
$field_value = $func($field_value, 'req', $field_id, $document_fields[$field_id]['rubric_field_template_request'], $document_fields[$field_id]['tpl_req_empty'], $_maxlength, $document_fields, $rubric_id, $document_fields[$field_id]['rubric_field_default']);
|
||
|
||
if ($maxlength != '')
|
||
{
|
||
if ($maxlength == 'more' || $maxlength == 'esc'|| $maxlength == 'img' || $maxlength == 'strip')
|
||
{
|
||
if ($maxlength == 'more')
|
||
{
|
||
// ToDo - Вывести в настройки или в настройки самого запроса
|
||
$teaser = explode('<a name="more"></a>', $field_value);
|
||
$field_value = $teaser[0];
|
||
}
|
||
elseif ($maxlength == 'esc')
|
||
{
|
||
$field_value = addslashes($field_value);
|
||
}
|
||
elseif ($maxlength == 'img')
|
||
{
|
||
$field_value = getImgSrc($field_value);
|
||
}
|
||
elseif ($maxlength == 'strip')
|
||
{
|
||
$field_value = str_replace(array("\r\n","\n","\r"), " ", $field_value);
|
||
$field_value = strip_tags($field_value, REQUEST_STRIP_TAGS);
|
||
$field_value = preg_replace('/ +/', ' ', $field_value);
|
||
$field_value = trim($field_value);
|
||
}
|
||
}
|
||
elseif (is_numeric($maxlength))
|
||
{
|
||
if ($maxlength < 0)
|
||
{
|
||
$field_value = str_replace(array("\r\n","\n","\r"), " ", $field_value);
|
||
$field_value = strip_tags($field_value, REQUEST_STRIP_TAGS);
|
||
$field_value = preg_replace('/ +/', ' ', $field_value);
|
||
$field_value = trim($field_value);
|
||
|
||
$maxlength = abs($maxlength);
|
||
}
|
||
// ToDo - сделать настройки окончаний = Уже есть в Доп настройках
|
||
if ($maxlength != 0)
|
||
{
|
||
$field_value = truncate($field_value, $maxlength, REQUEST_ETC, REQUEST_BREAK_WORDS);
|
||
}
|
||
|
||
}
|
||
else
|
||
return false;
|
||
}
|
||
|
||
return $field_value;
|
||
}
|
||
|
||
function showteaser ($id, $tparams = '')
|
||
{
|
||
$item = showrequestelement($id, '', $tparams);
|
||
$item = str_replace('[tag:path]', ABS_PATH, $item);
|
||
$item = str_replace('[tag:mediapath]', ABS_PATH . 'templates/' . ((defined('THEME_FOLDER') === false) ? DEFAULT_THEME_FOLDER : THEME_FOLDER) . '/', $item);
|
||
|
||
return $item;
|
||
}
|
||
|
||
// Функция получения уникальных параметров для каждого тизера
|
||
function f_params_of_teaser ($id_param_array,$num)
|
||
{
|
||
global $params_of_teaser;
|
||
return $params_of_teaser[$id_param_array][$num];
|
||
}
|
||
|
||
// Функция получения элемента запроса
|
||
function showrequestelement ($mixed, $template = '', $tparams = '', $req_item_num = null, $items_count = null, $is_last = null)
|
||
{
|
||
global
|
||
$AVE_DB,
|
||
$params_of_teaser,
|
||
$use_cache,
|
||
$request_id,
|
||
$request_changed,
|
||
$request_changed_elements;
|
||
|
||
if (is_array($mixed)) {
|
||
$row = intval($mixed[1]);
|
||
} else if (is_numeric($mixed)) {
|
||
$row = intval($mixed);
|
||
}
|
||
|
||
$row = (is_object($mixed) ? $mixed : getDocument($row));
|
||
|
||
unset ($mixed);
|
||
|
||
if (! $row) {
|
||
return '';
|
||
}
|
||
|
||
$tparams_id = '';
|
||
if ($tparams != '') {
|
||
$tparams_id = $row->Id . md5($tparams);
|
||
$params_of_teaser[$tparams_id] = [];
|
||
$tparams = trim($tparams,'[]:');
|
||
$params_of_teaser[$tparams_id] = explode('|',$tparams);
|
||
}
|
||
|
||
$sql = "
|
||
SELECT
|
||
rubric_teaser_template
|
||
FROM
|
||
" . PREFIX . "_rubrics
|
||
WHERE
|
||
Id = '" . intval($row->rubric_id) . "'
|
||
";
|
||
|
||
$template = ($template > ''
|
||
? $template
|
||
: $AVE_DB->Query($sql)->GetCell());
|
||
|
||
$hash = 'g-' . UGROUP;
|
||
$hash .= 'r-' . $request_id;
|
||
$hash .= 't-' . $row->Id;
|
||
|
||
if ($req_item_num !== null && $items_count !== null) {
|
||
$hash .= 'num-' . $req_item_num;
|
||
$hash .= 'total-' . $items_count;
|
||
}
|
||
|
||
$hash = md5($hash);
|
||
|
||
$cache_id = 'requests/elements/' . (floor($row->Id / 1000)) . '/' . $row->Id;
|
||
$cachefile_docid = BASE_DIR . '/tmp/cache/sql/' . $cache_id . '/' . $hash . '.element';
|
||
|
||
if (file_exists($cachefile_docid) && isset($use_cache) && $use_cache == 1) {
|
||
$check_file = $request_changed_elements;
|
||
if ($check_file > filemtime($cachefile_docid)) {
|
||
unlink ($cachefile_docid);
|
||
}
|
||
} else {
|
||
if (file_exists($cachefile_docid)) {
|
||
unlink ($cachefile_docid);
|
||
}
|
||
}
|
||
|
||
if (defined('DEV_MODE') AND DEV_MODE) {
|
||
$cachefile_docid = null;
|
||
}
|
||
|
||
if (! file_exists($cachefile_docid)) {
|
||
$link = rewrite_link('index.php?id=' . $row->Id . '&doc=' . (empty($row->document_alias) ? prepare_url($row->document_title) : $row->document_alias));
|
||
$item = $template;
|
||
|
||
// Обработка всех условных тегов через TagProcessor
|
||
if ($req_item_num !== null && $items_count !== null) {
|
||
$tagProcessor = new TagProcessor($req_item_num, $is_last, $row, (int)$row->rubric_id, $items_count);
|
||
$item = $tagProcessor->process($item);
|
||
}
|
||
|
||
// Парсим теги визуальных блоков
|
||
$item = preg_replace_callback('/\[tag:block:([A-Za-z0-9-_]{1,20}+)\]/', 'parse_block', $item);
|
||
|
||
// Парсим теги системных блоков
|
||
$item = preg_replace_callback('/\[tag:sysblock:([A-Za-z0-9-_]{1,20}+)(|:\{(.*?)\})\]/',
|
||
function ($m) {
|
||
return parse_sysblock($m[1], $m[2]);
|
||
},
|
||
$item);
|
||
|
||
// Парсим элементы полей
|
||
$item = preg_replace_callback('/\[tag:rfld:([a-zA-Z0-9-_]+)\]\[([0-9]+)]\[([0-9]+)]/',
|
||
function ($m) use ($row) {
|
||
return get_field_element($m[1], $m[2], $m[3], (int)$row->Id);
|
||
},
|
||
$item);
|
||
|
||
// Парсим теги полей
|
||
$item = preg_replace_callback('/\[tag:rfld:([a-zA-Z0-9-_]+)\]\[(more|esc|img|strip|[0-9-]+)]/',
|
||
function ($match) use ($row) {
|
||
return request_get_document_field($match[1], (int)$row->Id, $match[2], (int)$row->rubric_id);
|
||
},
|
||
$item);
|
||
|
||
// Повторно парсим теги полей
|
||
$item = preg_replace_callback('/\[tag:rfld:([a-zA-Z0-9-_]+)\]\[(more|esc|img|strip|[0-9-]+)]/',
|
||
function ($m) use ($row) {
|
||
return request_get_document_field($m[1], (int)$row->Id, $m[2], (int)$row->rubric_id);
|
||
},
|
||
$item);
|
||
|
||
// Возвращаем поле документа из БД (document_***)
|
||
$item = preg_replace_callback('/\[tag:doc:([a-zA-Z0-9-_]+)\]/u',
|
||
function ($m) use ($row) {
|
||
return isset($row->{$m[1]}) ? $row->{$m[1]} : null;
|
||
},
|
||
$item
|
||
);
|
||
|
||
// Если пришел вызов на активацию языковых файлов
|
||
$item = preg_replace_callback(
|
||
'/\[tag:langfile:([a-zA-Z0-9-_]+)\]/u',
|
||
function ($m) {
|
||
global $AVE_Template;
|
||
return $AVE_Template->get_config_vars($m[1]);
|
||
},
|
||
$item
|
||
);
|
||
|
||
// Абсолютный путь
|
||
$item = str_replace('[tag:path]', ABS_PATH, $item);
|
||
|
||
// Путь к папке шаблона
|
||
$item = str_replace('[tag:mediapath]', ABS_PATH . 'templates/' . ((defined('THEME_FOLDER') === false) ? DEFAULT_THEME_FOLDER : THEME_FOLDER) . '/', $item);
|
||
|
||
// Watermarks
|
||
$item = preg_replace_callback('/\[tag:watermark:(.+?):([a-zA-Z]+):([0-9]+)\]/',
|
||
function ($m) {
|
||
watermarks($m[1], $m[2], $m[3]);
|
||
},
|
||
$item);
|
||
|
||
// Удаляем ошибочные теги полей документа и языковые, в шаблоне рубрики
|
||
$item = preg_replace('/\[tag:doc:\d*\]/', '', $item);
|
||
$item = preg_replace('/\[tag:langfile:\d*\]/', '', $item);
|
||
|
||
// Делаем линки на миниатюры
|
||
$item = preg_replace_callback('/\[tag:([r|c|f|t|s]\d+x\d+r*):(.+?)]/', 'callback_make_thumbnail', $item);
|
||
|
||
// Если был вызов тизера, ищем параметры
|
||
if ($tparams != '') {
|
||
$item = preg_replace_callback('/\[tparam:([0-9]+)\]/',
|
||
function ($m) use ($tparams_id) {
|
||
return f_params_of_teaser($tparams_id, $m[1]);
|
||
},
|
||
$item);
|
||
} else {
|
||
$item = preg_replace('/\[tparam:([0-9]+)\]/', '', $item);
|
||
}
|
||
|
||
$item = str_replace('[tag:domain]', getSiteUrl(), $item);
|
||
$item = str_replace('[tag:link]', $link, $item);
|
||
$item = str_replace('[tag:docid]', $row->Id, $item);
|
||
$item = str_replace('[tag:itemid]', $row->Id, $item);
|
||
$item = str_replace('[tag:docitemnum]', $req_item_num, $item);
|
||
$item = str_replace('[tag:adminlink]', 'index.php?do=docs&action=edit&rubric_id=' . $row->rubric_id . '&Id=' . $row->Id . '&cp=' . session_id() . '', $item);
|
||
$item = str_replace('[tag:doctitle]', stripslashes(htmlspecialchars_decode($row->document_title)), $item);
|
||
$item = str_replace('[tag:docparent]', $row->document_parent, $item);
|
||
$item = str_replace('[tag:doclang]', $row->document_lang, $item);
|
||
$item = str_replace('[tag:docdate]', translate_date(strftime(DATE_FORMAT, $row->document_published)), $item);
|
||
$item = str_replace('[tag:doctime]', translate_date(strftime(TIME_FORMAT, $row->document_published)), $item);
|
||
$item = str_replace('[tag:humandate]', human_date($row->document_published), $item);
|
||
|
||
$item = preg_replace_callback('/\[tag:date:([a-zA-Z0-9-. \/]+)\]/',
|
||
function ($m) use ($row) {
|
||
return translate_date(date($m[1], $row->document_published));
|
||
},
|
||
$item);
|
||
|
||
if (preg_match('/\[tag:docauthor]/u', $item)) {
|
||
$item = str_replace('[tag:docauthor]', get_username_by_id($row->document_author_id), $item);
|
||
}
|
||
|
||
$item = str_replace('[tag:docauthorid]', $row->document_author_id, $item);
|
||
|
||
$item = preg_replace_callback('/\[tag:docauthoravatar:(\d+)\]/',
|
||
function ($m) use ($row) {
|
||
return getAvatar(intval($row->document_author_id), $m[1]);
|
||
},
|
||
$item);
|
||
|
||
if (isset($use_cache) && $use_cache == 1) {
|
||
if (! file_exists(dirname($cachefile_docid))) {
|
||
@mkdir(dirname($cachefile_docid), 0777, true);
|
||
}
|
||
file_put_contents($cachefile_docid, $item);
|
||
}
|
||
} else {
|
||
$item = file_get_contents($cachefile_docid);
|
||
}
|
||
|
||
// Кол-во просмотров
|
||
$item = str_replace('[tag:docviews]', $row->document_count_view, $item);
|
||
|
||
Registry::remove('documents', $row->Id);
|
||
Registry::remove('fields', $row->Id);
|
||
Registry::remove('fields_param', $row->Id);
|
||
|
||
unset($row, $template);
|
||
|
||
return $item;
|
||
}
|
||
|
||
/**
|
||
* Парсинг запроса
|
||
*
|
||
* @param int|string $id Идентификатор или псевдоним запроса
|
||
* @return string
|
||
*/
|
||
function request_parse($id)
|
||
{
|
||
global $AVE_Core, $AVE_DB, $request_documents;
|
||
|
||
// Начальная проверка ID
|
||
if (is_array($id)) {
|
||
$id = $id[1];
|
||
}
|
||
|
||
// Получаем информацию о запросе. Эта функция должна создать .settings файл
|
||
$request = request_get_settings($id);
|
||
|
||
// Выходим, если запрос не найден
|
||
if (!is_object($request)) {
|
||
return '';
|
||
}
|
||
|
||
// Фиксируем время начала генерации запроса
|
||
Debug::startTime('request_' . $id);
|
||
|
||
// Инициализация переменных из настроек запроса
|
||
$limit = ($request->request_items_per_page < 1) ? 1 : $request->request_items_per_page;
|
||
$main_template = $request->request_template_main;
|
||
$item_template = $request->request_template_item;
|
||
$request_order_by = $request->request_order_by;
|
||
$request_order_by_nat = intval($request->request_order_by_nat);
|
||
$request_asc_desc = $request->request_asc_desc;
|
||
|
||
// Генерируем строку условий
|
||
$where_cond = request_get_condition_sql_string($request->Id);
|
||
$where_cond = str_replace('%%PREFIX%%', PREFIX, $where_cond);
|
||
|
||
// Динамическое формирование WHERE-части запросов
|
||
$where_common = "
|
||
a.Id != '1'
|
||
AND a.Id != '" . PAGE_NOT_FOUND_ID . "'
|
||
AND a.rubric_id = '" . (int)$request->rubric_id . "'
|
||
AND a.document_deleted != '1'
|
||
AND a.document_status != '0'
|
||
" . $hide_current_condition . "
|
||
" . $owner_condition . "
|
||
" . $lang_condition . "
|
||
" . $where_cond . "
|
||
" . $doctime . "
|
||
";
|
||
|
||
// Определение частей запроса в зависимости от наличия модуля комментариев и нативной сортировки
|
||
$join_comment = !empty($AVE_Core->install_modules['comment']->Status)
|
||
? "LEFT JOIN " . PREFIX . "_modul_comment_info AS b ON b.document_id = a.Id"
|
||
: "";
|
||
$select_comment_count = !empty($AVE_Core->install_modules['comment']->Status)
|
||
? ", COUNT(b.document_id) AS nums"
|
||
: "";
|
||
$group_by_doc_id = !empty($AVE_Core->install_modules['comment']->Status)
|
||
? "GROUP BY a.Id"
|
||
: "";
|
||
|
||
if ($request_order_by_nat != 0) {
|
||
$join_fields = "LEFT JOIN " . PREFIX . "_document_fields AS d ON a.Id = d.document_id";
|
||
$where_fields = "AND d.rubric_field_id = " . intval($request_order_by_nat);
|
||
$select_fields = ", d.field_value, d.rubric_field_id";
|
||
$order_by = "ORDER BY d.field_value " . ($request_asc_desc === 'DESC' ? 'DESC' : 'ASC');
|
||
} else {
|
||
$join_fields = "";
|
||
$where_fields = "";
|
||
$select_fields = "";
|
||
$order_by = "ORDER BY " . $request_order_by . " " . $request_asc_desc;
|
||
}
|
||
|
||
$num_items = 0;
|
||
$num_pages = 0;
|
||
$start = 0;
|
||
|
||
// Условное выполнение запроса для подсчета общего количества элементов
|
||
if ($request->request_show_pagination == 1 || $request->request_count_items == 1) {
|
||
// Формируем запрос для подсчета количества элементов
|
||
$count_sql = "
|
||
SELECT COUNT(*)
|
||
FROM " . PREFIX . "_documents AS a
|
||
" . $join_fields . "
|
||
WHERE
|
||
" . $where_common . "
|
||
" . $where_fields . "
|
||
";
|
||
|
||
// Получаем общее количество элементов, используя кеширование
|
||
$num_items = $AVE_DB->Query($count_sql, (int)$request->request_cache_lifetime, 'rqs_' . $id, true, '.count')->GetCell();
|
||
}
|
||
|
||
// Если пагинация включена, вычисляем количество страниц и начальную позицию
|
||
if ($request->request_show_pagination == 1) {
|
||
$num_pages = ceil($num_items / $limit);
|
||
$start = get_current_page('page') * $limit - $limit;
|
||
}
|
||
|
||
// Формируем финальный запрос для выборки данных
|
||
$main_sql_query = "
|
||
SELECT
|
||
a.Id,
|
||
a.document_title,
|
||
a.document_alias,
|
||
a.document_parent,
|
||
a.document_author_id,
|
||
a.document_count_view,
|
||
a.document_published,
|
||
a.document_lang
|
||
" . $select_comment_count . "
|
||
" . $select_fields . "
|
||
FROM
|
||
" . PREFIX . "_documents AS a
|
||
" . $join_comment . "
|
||
" . $join_fields . "
|
||
WHERE
|
||
" . $where_common . "
|
||
" . $where_fields . "
|
||
" . $group_by_doc_id . "
|
||
" . $order_by . "
|
||
LIMIT " . $start . "," . $limit . "
|
||
";
|
||
|
||
// Отладочный вывод SQL-запроса, если это необходимо
|
||
if ($request->request_show_sql == 1) {
|
||
$return = Debug::_print($main_sql_query);
|
||
return $return;
|
||
}
|
||
|
||
// Выполняем запрос с кешированием, создавая файл .request
|
||
Debug::startTime('SQL');
|
||
$q = $AVE_DB->Query($main_sql_query, (int)$request->request_cache_lifetime, 'rqs_' . $id, true, '.request');
|
||
$GLOBALS['block_generate']['REQUESTS'][$id]['SQL'] = Debug::endTime('SQL');
|
||
|
||
$rows = array();
|
||
$request_documents = array();
|
||
while ($row = $q->FetchRow()) {
|
||
array_push($request_documents, $row->Id);
|
||
array_push($rows, $row);
|
||
}
|
||
|
||
// Условное отображение контента
|
||
if ($q->NumRows() > 0) {
|
||
$main_template = preg_replace('/\[tag:if_empty](.*?)\[\/tag:if_empty]/si', '', $main_template);
|
||
$main_template = str_replace(array('[tag:if_notempty]','[/tag:if_notempty]'), '', $main_template);
|
||
} else {
|
||
$main_template = preg_replace('/\[tag:if_notempty](.*?)\[\/tag:if_notempty]/si', '', $main_template);
|
||
$main_template = str_replace(array('[tag:if_empty]','[/tag:if_empty]'), '', $main_template);
|
||
}
|
||
|
||
// Формирование пагинации
|
||
$pagination = '';
|
||
if ($request->request_show_pagination == 1 && $num_pages > 1) {
|
||
@$GLOBALS['page_id'][$_REQUEST['id']]['page'] = (isset($GLOBALS['page_id'][$_REQUEST['id']]['page']) && $GLOBALS['page_id'][$_REQUEST['id']]['page'] > $num_pages) ? @$GLOBALS['page_id'][$_REQUEST['id']]['page'] : $num_pages;
|
||
$queries = ($request->request_use_query == 1 || (isset($params['ADD_GET']) && $params['ADD_GET'] == 1)) ? ((isset($_SERVER['QUERY_STRING'])) ? '?' . $_SERVER['QUERY_STRING'] : '') : '';
|
||
$pagination_base = 'index.php?id=' . $AVE_Core->curentdoc->Id . '&doc=' . (empty($AVE_Core->curentdoc->document_alias) ? prepare_url($AVE_Core->curentdoc->document_title) : $AVE_Core->curentdoc->document_alias) . '&page={s}';
|
||
$pagination_params = ((isset($_REQUEST['artpage']) && is_numeric($_REQUEST['artpage'])) ? '&artpage=' . $_REQUEST['artpage'] : '') . ((isset($_REQUEST['apage']) && is_numeric($_REQUEST['apage'])) ? '&apage=' . $_REQUEST['apage'] : '');
|
||
$pagination_full = $pagination_base . $pagination_params . clean_php($queries);
|
||
$pagination_id = (isset($params['PAGINATION']) && $params['PAGINATION'] > 0) ? $params['PAGINATION'] : $request->request_pagination;
|
||
$pagination = AVE_Paginations::getPagination($num_pages, 'page', $pagination_full, $pagination_id);
|
||
|
||
// Костыли для главной страницы
|
||
$pagination = str_ireplace('"//"', '"/"', str_ireplace('///', '/', rewrite_link($pagination)));
|
||
$pagination = str_ireplace('"//' . URL_SUFF . '"', '"/"', $pagination);
|
||
if ($request->request_use_query == 1 || (isset($params['ADD_GET']) && $params['ADD_GET'] == 1)) {
|
||
$pagination = preg_replace('/(?<!:)\/\//', '/', $pagination);
|
||
}
|
||
}
|
||
|
||
// Обработка шаблонов элементов
|
||
$items = '';
|
||
$x = 0;
|
||
$items_count = count($rows);
|
||
|
||
global $req_item_num, $use_cache, $request_id, $request_changed, $request_changed_elements;
|
||
|
||
$use_cache = $request->request_cache_elements;
|
||
|
||
$request_id = $request->Id;
|
||
|
||
$request_changed = $request->request_changed;
|
||
$request_changed_elements = $request->request_changed_elements;
|
||
|
||
Debug::startTime('ELEMENTS_ALL');
|
||
|
||
foreach ($rows as $row) {
|
||
$x++;
|
||
$last_item = ($x == $items_count);
|
||
$req_item_num = $x;
|
||
|
||
// Передаем элемент для обработки и кэширования в showrequestelement.
|
||
$items .= showrequestelement($row, $item_template, '', $req_item_num, $items_count, $last_item);
|
||
}
|
||
|
||
$GLOBALS['block_generate']['REQUESTS'][$id]['ELEMENTS']['ALL'] = Debug::endTime('ELEMENTS_ALL');
|
||
|
||
// Обработка основного шаблона
|
||
$main_template = str_replace('[tag:pages]', $pagination, $main_template);
|
||
$main_template = str_replace('[tag:docid]', $AVE_Core->curentdoc->Id, $main_template);
|
||
$main_template = str_replace('[tag:pagetitle]', stripslashes(htmlspecialchars_decode($AVE_Core->curentdoc->document_title)), $main_template);
|
||
$main_template = str_replace('[tag:pages:curent]', get_current_page('page'), $main_template);
|
||
$main_template = str_replace('[tag:pages:total]', $num_pages, $main_template);
|
||
$main_template = str_replace('[tag:doctotal]', $num_items, $main_template);
|
||
$main_template = str_replace('[tag:doconpage]', $x, $main_template);
|
||
$main_template = str_replace('[tag:docdate]', pretty_date(strftime(DATE_FORMAT, $AVE_Core->curentdoc->document_published)), $main_template);
|
||
$main_template = str_replace('[tag:doctime]', pretty_date(strftime(TIME_FORMAT, $AVE_Core->curentdoc->document_published)), $main_template);
|
||
$main_template = str_replace('[tag:docauthor]', get_username_by_id($AVE_Core->curentdoc->document_author_id), $main_template);
|
||
$main_template = preg_replace_callback('/\[tag:dropdown:([,0-9]+)\]/', function($m) use ($request) {
|
||
return request_get_dropdown($m[1], (int)$request->rubric_id, (int)$request->Id);
|
||
}, $main_template);
|
||
$main_template = preg_replace_callback('/\[tag:date:([a-zA-Z0-9-. \/]+)\]/', function ($match) use ($AVE_Core) {
|
||
return translate_date(date($match[1], $AVE_Core->curentdoc->document_published));
|
||
}, $main_template);
|
||
$main_template = preg_replace_callback('/\[tag:langfile:([a-zA-Z0-9-_]+)\]/u', function ($match) {
|
||
global $AVE_Template;
|
||
return $AVE_Template->get_config_vars($match[1]);
|
||
}, $main_template);
|
||
$main_template = preg_replace_callback('/\[tag:sysblock:([A-Za-z0-9-_]{1,20}+)\]/', 'parse_sysblock', $main_template);
|
||
$main_template = preg_replace_callback('/\[tag:block:([A-Za-z0-9-_]{1,20}+)\]/', 'parse_block', $main_template);
|
||
|
||
$return = str_replace('[tag:content]', $items, $main_template);
|
||
$return = str_replace('[tag:path]', ABS_PATH, $return);
|
||
$return = str_replace('[tag:mediapath]', ABS_PATH . 'templates/' . THEME_FOLDER . '/', $return);
|
||
$return = $AVE_Core->coreModuleTagParse($return);
|
||
|
||
// Фиксируем время генерации запроса
|
||
$GLOBALS['block_generate']['REQUESTS'][$id]['TIME'] = Debug::endTime('request_' . $id);
|
||
|
||
if ($request->request_show_statistic) {
|
||
$return .= "<div class=\"request_statistic\"><br>Найдено: $num_items<br>Показано: $items_count<br>Время генерации: " . Debug::endTime('request_' . $id) . " сек<br>Пиковое значение: " . number_format(memory_get_peak_usage() / 1024, 0, ',', ' ') . ' Kb</div>';
|
||
}
|
||
|
||
return $return;
|
||
}
|
||
|
||
/**
|
||
* Функция получения содержимого поля для обработки в шаблоне запроса
|
||
* <pre>
|
||
* Пример использования в шаблоне:
|
||
* <li>
|
||
* <?php
|
||
* $r = request_get_document_field_value(12, [tag:docid]);
|
||
* echo $r . ' (' . strlen($r) . ')';
|
||
* ?>
|
||
* </li>
|
||
* </pre>
|
||
*
|
||
* @param int $rubric_id идентификатор поля, для [tag:rfld:12][150] $rubric_id = 12
|
||
* @param int $document_id идентификатор документа к которому принадлежит поле.
|
||
* @param int $maxlength необязательный параметр, количество возвращаемых символов.
|
||
* Если данный параметр указать со знаком минус
|
||
* содержимое поля будет очищено от HTML-тэгов.
|
||
* @return string
|
||
*/
|
||
function request_get_document_field_value($rubric_id, $document_id, $maxlength = 0)
|
||
{
|
||
if (!is_numeric($rubric_id) || $rubric_id < 1 || !is_numeric($document_id) || $document_id < 1) return '';
|
||
|
||
$document_fields = get_document_fields($document_id);
|
||
|
||
$field_value = isset($document_fields[$rubric_id]) ? $document_fields[$rubric_id]['field_value'] : '';
|
||
|
||
if (!empty($field_value))
|
||
{
|
||
$field_value = strip_tags($field_value, '<br /><strong><em><p><i>');
|
||
$field_value = str_replace('[tag:mediapath]', ABS_PATH . 'templates/' . THEME_FOLDER . '/', $field_value);
|
||
}
|
||
|
||
if (is_numeric($maxlength) && $maxlength != 0)
|
||
{
|
||
if ($maxlength < 0)
|
||
{
|
||
$field_value = str_replace(array("\r\n", "\n", "\r"), ' ', $field_value);
|
||
$field_value = strip_tags($field_value);
|
||
$field_value = preg_replace('/ +/', ' ', $field_value);
|
||
$maxlength = abs($maxlength);
|
||
}
|
||
$field_value = substr($field_value, 0, $maxlength) . (strlen($field_value) > $maxlength ? '... ' : '');
|
||
}
|
||
|
||
return $field_value;
|
||
}
|
||
|
||
/**
|
||
* Функция формирования выпадающих списков
|
||
* для управления условиями запроса в публичной части
|
||
*
|
||
* @param string $dropdown_ids идентификаторы полей
|
||
* типа выпадающий список указанные через запятую
|
||
* @param int $rubric_id идентификатор рубрики
|
||
* @param int $request_id идентификатор запроса
|
||
* @return string
|
||
*/
|
||
function request_get_dropdown($dropdown_ids, $rubric_id, $request_id)
|
||
{
|
||
global $AVE_Core, $AVE_DB, $AVE_Template;
|
||
|
||
// Получаем настройки запроса
|
||
$request_settings = request_get_settings($request_id);
|
||
|
||
if (!is_object($request_settings)) {
|
||
return '';
|
||
}
|
||
|
||
$dropdown_ids = explode(',', preg_replace('/[^,\\d]/', '', $dropdown_ids));
|
||
$dropdown_ids[] = 0;
|
||
$dropdown_ids = implode(',', $dropdown_ids);
|
||
$doc = 'doc_' . $AVE_Core->curentdoc->Id;
|
||
$control = array();
|
||
|
||
// Для кеширования, используем $request_id в качестве уникального идентификатора.
|
||
$sql = $AVE_DB->Query(
|
||
"
|
||
SELECT
|
||
Id,
|
||
rubric_field_title,
|
||
rubric_field_default
|
||
FROM " . PREFIX . "_rubric_fields
|
||
WHERE Id IN(" . $dropdown_ids . ")
|
||
AND rubric_id = '" . $rubric_id . "'
|
||
AND rubric_field_type = 'drop_down'
|
||
", -1, 'rqs_' . $request_id, true, '.dropdown');
|
||
|
||
while ($row = $sql->FetchRow())
|
||
{
|
||
$dropdown['titel'] = $row->rubric_field_title;
|
||
$dropdown['selected'] = isset($_SESSION[$doc]['req_' . $request_id][$row->Id]) ? $_SESSION[$doc]['req_' . $request_id][$row->Id] : '';
|
||
$dropdown['options'] = $_SESSION['val_' . $row->Id] = explode(',', $row->rubric_field_default);
|
||
$control[$row->Id] = $dropdown;
|
||
}
|
||
|
||
$AVE_Template->assign('request_id', $request_id);
|
||
$AVE_Template->assign('ctrlrequest', $control);
|
||
return $AVE_Template->fetch(BASE_DIR . '/templates/' . THEME_FOLDER . '/tpl/request/public.tpl');
|
||
}
|
||
|
||
?>
|