diff --git a/README.md b/README.md index 9536591..baf9f2d 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,39 @@ ### Unicalendar -## Модуль Unicalendar - календарь событий +## Модуль Unicalendar - календарь событий v3.32 -#### адаптирован для AVE.CMS v3.26 +### для AVE.CMS ALT ≥ v3.31 + +### Модуль позволяет создавать календари, событиями которых являются все документы из заданной рубрики либо определенные документы из заданной рубрики. + +* Пример работы с модулем Календарь: + * Создайте рубрику "Календарь" которая будет содержать в себе следующие поля: + * Название события + * Место проведения события + * Описание события + * Изображение (тип поля Изображение (Одиночное)) + * Дата начала события (тип поля Дата (Unix Timestamp)) + * Дата завершения события (тип поля Дата (Unix Timestamp)) + * Создайте документ в рубрике "Календарь" и заполните в нем эти поля. + * Скачайте архив с модулем unicalendar-main.zip и положите его в папку modules, разархивируйте, после чего у вас появится папка unicalendar, ее оставляем архив unicalendar-main.zip удаляем. + * Перейдите в раздел управления модулями вкладка Неустановленные модули, установите модуль Универсальный календарь событий. + * Перейдите к управлению модулем вкладка Создать календарь, выберите тип событий календаря, далее выберите рубрику и вам станет доступным выбор полей для создания тизера события. + * Выбор полей для создания тизера события: + * Название события - по умолчанию используется содержимое тега `````` но вы можете использовать поле из документа. + * Изображение - выберите поле Изображение (Одиночное). Если оставить это поле пустым - календарь просто проигнорирует его. + * Описание события - используйте нужное вам поле из документа. Важно - все HTML теги, если они имеются, будут очищены, выведется только текст. + * Место события - используйте нужное вам поле из документа. Если оставить это поле пустым - календарь просто проигнорирует его. + * Дата начала - по умолчанию используется дата и время создания документа. Однако, если вам понадобится указать более позднюю дату, например документ создан 20 апреля , а вы хотите в календаре установить дату события 1 мая - используйте для этого в документе поле Дата (Unix Timestamp), это позволит выбрать дату и время в правильном формате. Если использовать текстовое поле, запишите дату и время в таком формате: 01-05-2026 19:00 + * Дата завершения - полностью аналогична Дате начала. + * Кликните кнопку "Создать". Ваш календарь будет готов к использованию после размещения системного тега [mod_unicalendar:XXX] в документе или Основном шаблоне или в шаблоне Рубрики. +* Календарь в публичной части сайта не делает запросов к базе данных. Создавая календарь вы создаете js файл с данными с которыми он работает. Поэтому, если вы, создав и сохранив календарь решили сделать в документе какие либо изменения - правки в полях, датах документа или меняете название документа - ``````, обязательно после сохранения документа или удаления документа, пересохраните для актуальности календарь использующий данные из этого документа. Таким образом вы обновите js файл с данными и календарь будет актуальным. +* Используйте файл eventCalendar.css, подключается программно при использовании модуля и расположен в каталоге ```modules/unicalendar/css/```, для редактирования некоторых стилей календаря. Непосредственно разметка вывода находится в файле jquery.eventCalendar.js -### Модуль позволяет создавать календари, событиями которых являются документы из заданной рубрики либо определенные документы из заданной рубрики. ##### Changelog: +##### 27.03.2026 - обновление модуля - версия 3.32 - рефакторинг кода для работы в ave.cms ALT v3.31. Добавлен выбор полей для Названия событий и даты начала и завершения события, обновлен дизайн календаря. + ##### 05.09.2019 - обновление модуля - версия 1.26.8 - адаптация для версии ave.cms 3.26, замена устаревшего size() на length ##### 08.09.2017 - обновление модуля - версия 1.2.8 - Fix регулярного выражения для сохранения в файл (dataX.js) в кодировке UTF-8 diff --git a/class/unicalendar.php b/class/unicalendar.php index 37d3f3a..79a607e 100644 --- a/class/unicalendar.php +++ b/class/unicalendar.php @@ -14,619 +14,595 @@ class Unicalendar * ФУНКЦИИ ПУБЛИЧНОЙ ЧАСТИ */ - /** - * Вывод календаря событий +/** + * Вывод календаря событий * @param string $tpl_dir - путь к папке с шаблонами модуля - * @param int $id - идентификатор календаря - */ - function unicalendarShow($tpl_dir, $id) - { - require(BASE_DIR . '/modules/unicalendar/lang/'.$_SESSION['user_language'].'.php'); // загружаем файл ленгов для php переменных - // подключаем JS скрипты и CSS файлы календаря в секцию head + * @param int $id - идентификатор календаря + */ + function unicalendarShow($tpl_dir, $id) + { + $id = (int)$id; + + $user_lang = preg_replace('/[^a-zA-Z0-9_-]/', '', $_SESSION['user_language'] ?? 'ru'); + $lang_path = BASE_DIR . '/modules/unicalendar/lang/' . $user_lang . '.php'; + + if (file_exists($lang_path)) { + require($lang_path); + } else { + $default_lang = BASE_DIR . '/modules/unicalendar/lang/ru.php'; + if (file_exists($default_lang)) require($default_lang); + } + $eventCalendar_css = ''; $eventCalendar_theme_responsive_css = ''; $moment_js = ''; $jquery_eventCalendar_js = ''; + $GLOBALS['user_header']['module_unicalendar_'] = $eventCalendar_css."\n".$eventCalendar_theme_responsive_css."\n".$moment_js."\n".$jquery_eventCalendar_js; - // подключаем в секции js файл с данным , согласно Id календаря + $data_dir = "/modules/unicalendar/js/data-files"; - $filename = BASE_DIR .$data_dir."/data".$id.".js"; - if (file_exists($filename)) - { + $filename = BASE_DIR . $data_dir . "/data" . $id . ".js"; + + if (file_exists($filename)) { $GLOBALS['user_header']['module_unicalendar_' . $id] = ''; + } else { + echo $uca_file_not_found.$id.".js"; // если не смогли подключить файл -выводим сообщение-подсказку; } - else { - echo $uca_file_not_found.$id.".js"; // если не смогли подключить файл -выводим сообщение-подсказку - }; - global $AVE_Template; - $AVE_Template->assign('id', $id); - $AVE_Template->display($tpl_dir . 'unicalendar.tpl'); - } + + global $AVE_Template; + $AVE_Template->assign('id', $id); + $AVE_Template->display($tpl_dir . 'unicalendar.tpl'); + } /** * ФУНКЦИИ АДМИНИСТРАТИВНОЙ ЧАСТИ */ - /** - * Вывод списка календарей - * - * @param string $tpl_dir - путь к папке с шаблонами модуля - */ - function unicalendarList($tpl_dir) - { - global $AVE_DB, $AVE_Template; + /** + * Вывод списка календарей + * + * @param string $tpl_dir - путь к папке с шаблонами модуля + */ + function unicalendarList($tpl_dir) + { + global $AVE_DB, $AVE_Template; - $unicalendars = array(); + $unicalendars = array(); - $limit = 20; - $start = get_current_page() * $limit - $limit; - - $sql = $AVE_DB->Query(" - SELECT SQL_CALC_FOUND_ROWS - u.*, - COUNT(u.id) AS uca_count - FROM - " . PREFIX . "_module_unicalendar AS u - GROUP BY u.id - ORDER BY u.id ASC - LIMIT " . $start . "," . $limit . " - "); + $limit = 20; + $current_page = (int)get_current_page(); + if ($current_page < 1) $current_page = 1; + $start = ($current_page * $limit) - $limit; + + $sql = $AVE_DB->Query(" + SELECT SQL_CALC_FOUND_ROWS + u.*, + COUNT(u.id) AS uca_count + FROM + " . PREFIX . "_module_unicalendar AS u + GROUP BY u.id + ORDER BY u.id ASC + LIMIT " . (int)$start . "," . (int)$limit . " + "); - $sql_num = $AVE_DB->Query("SELECT FOUND_ROWS()"); - $num = $sql_num->GetCell(); + $sql_num = $AVE_DB->Query("SELECT FOUND_ROWS()"); + $num = (int)$sql_num->GetCell(); - while($row = $sql->FetchAssocArray()) - { - array_push($unicalendars, $row); - } - - if ($num > $limit) - { - $page_nav = "
  • {t}
  • "; - $page_nav = get_pagination(ceil($num / $limit), 'page', $page_nav); - } - else - { - $page_nav = ''; - } - - $AVE_Template->assign('page_nav', $page_nav); + while($row = $sql->FetchAssocArray()) + { + $unicalendars[] = $row; + } + + if ($num > $limit) + { + $page_nav_tpl = "
  • {t}
  • "; + $page_nav = get_pagination(ceil($num / $limit), 'page', $page_nav_tpl); + } + else + { + $page_nav = ''; + } + + $AVE_Template->assign('page_nav', $page_nav); - if (!empty($_REQUEST['alert'])) - { - $AVE_Template->assign('alert', htmlspecialchars(stripslashes($_REQUEST['alert']))); - } + // 4. Безопасный вывод алертов + if (!empty($_REQUEST['alert'])) + { + $alert = htmlspecialchars(stripslashes((string)$_REQUEST['alert']), ENT_QUOTES, 'UTF-8'); + $AVE_Template->assign('alert', $alert); + } $AVE_Template->assign('unicalendars', $unicalendars); - $AVE_Template->assign('formaction', 'index.php?do=modules&action=modedit&mod=unicalendar&moduleaction=new&sub=save&cp=' . SESSION); - $AVE_Template->assign('content', $AVE_Template->fetch($tpl_dir . 'admin_unicalendar_list.tpl')); - } - - /** - * Создание календаря - * - */ - function unicalendarNew() - { - if (isset($_REQUEST['sub']) && $_REQUEST['sub'] == 'save') - { - global $AVE_DB; - $cont = true; - $alert = ''; - if (empty($_POST['uca_title'])) - { - $alert = '&alert=empty_uca_title'; - $cont = false; - } - if ($cont) - { - $AVE_DB->Query(" - INSERT - INTO " . PREFIX . "_module_unicalendar - SET - id = '', - uca_title = '" . $_POST['uca_title'] . "', - uca_date_format = '" . $_POST['uca_date_format'] . "', - uca_events = '" . $_POST['uca_events'] . "', - uca_rubric_id = '" . $_POST['uca_rubric_id'] . "', - uca_rubric_title = '" . $_POST['uca_rubric_title'] . "', - uca_doc_id = '" . $_POST['uca_doc_id'] . "', - uca_link = '" . $_POST['uca_link'] . "', - uca_day = '" . $_POST['uca_day'] . "', - uca_scroll = '" . $_POST['uca_scroll'] . "', - uca_descript = '" . $_POST['uca_descript'] . "', - uca_events_limit = '" . $_POST['uca_events_limit'] . "', - uca_img_field = '" . $_POST['i_uca_img_field'] . "', - uca_dsc_field = '" . $_POST['i_uca_dsc_field'] . "', - uca_place_field = '" . $_POST['i_uca_place_field'] . "' - "); - - // Получаем обновленные данные календаря - require(BASE_DIR . '/modules/unicalendar/lang/'.$_SESSION['admin_language'].'.php'); // загружаем файл ленгов для php переменных - $sql = $AVE_DB->Query(" - SELECT * - FROM " . PREFIX . "_module_unicalendar - WHERE id = '".$AVE_DB->InsertId()."' - "); - $unicalendars = array(); - while ($row = $sql->FetchAssocArray()) - { - array_push($unicalendars, $row); - } - foreach ( $unicalendars as $k=>$v ) - { - $uca_id = $v['id']; - $uca_dfrm = $v['uca_date_format']; - $uevents = $v['uca_events']; - $urubric_id = $v['uca_rubric_id']; - $udoc_id = $v['uca_doc_id']; - $uca_day = $v['uca_day']; - $uca_scroll = $v['uca_scroll']; - $uca_link = $v['uca_link']; - $uca_descript = $v['uca_descript']; - $uca_events_limit = $v['uca_events_limit']; - $uca_img_field = $v['uca_img_field']; - $uca_dsc_field = $v['uca_dsc_field']; - $uca_place_field = $v['uca_place_field']; - } - if ($uca_dsc_field != 0) {$ellipsis = '… ';} else {$ellipsis = '';};// если описания нет не добавляем многоточие при выводе description - // Если выбрали вывести все документы из заданной рубрики - документы с Id=1 (Главная) и 404 страница - выводиться не будут! - if ($uevents !='' && $uevents == '1'){ - $sql = $AVE_DB->Query(" - SELECT Id, document_alias, document_title, document_published, document_expire, document_meta_description - FROM " . PREFIX . "_documents - WHERE rubric_id = '" . $urubric_id . "' AND Id !=1 && Id != '".PAGE_NOT_FOUND_ID."' - "); - $results = array(); - while ($row = $sql->FetchAssocArray()) - { - array_push($results, $row); - } - //получаем данные всех документов из заданной рубрики циклом, формируем строку JSON - foreach ( $results as $k=>$v ) - { - $uni_data .= "{ \"date\": \"".pretty_date(strftime('%Y-%m-%d %H:%M:%S', $v['document_published']))."\", \"expire_date\": \"".pretty_date(strftime('%Y-%m-%d %H:%M:%S', $v['document_expire']))."\", \"title\": \"".$v['document_title']."\", \"image\": \"".strstr(get_document_field($v['Id'], $uca_img_field), '|', true)."\", \"description\": \"".rtrim(mb_substr(preg_replace('|[\s]+|su', ' ', strip_tags(get_document_field($v['Id'], $uca_dsc_field))), 0, 255, 'UTF-8'), "!,.-").$ellipsis."\", \"location\": \"".mb_substr(preg_replace('|[\s]+|su', ' ', strip_tags(get_document_field($v['Id'], $uca_place_field))), 0, 300, 'UTF-8')."\", \"url\": \"".$v['document_alias']."\" },"; - $rubric_count .= $v['Id']." OR Id="; - } - $js_data_files = "$(function(){"."var data".$uca_id." = [".$uni_data."]; $(\"#eventCalendar".$uca_id."\").eventCalendar({jsonData: data".$uca_id.", jsonDateFormat: \"human\", startWeekOnMonday: ".$uca_day.", eventsScrollable: ".$uca_scroll.", openEventInNewWindow: ".$uca_link.", dateFormat: \"".$uca_dfrm."\", showDescription: ".$uca_descript.", eventsLimit: ".$uca_events_limit.", locales: {locale: \"".$uca_locale."\", txt_noEvents: \"".$uca_no_events."\", txt_SpecificEvents_prev: \"\", txt_SpecificEvents_after: \"".$uca_real_events."\", txt_NextEvents: \"".$uca_next_events."\", txt_GoToEventUrl: \"".$uca_look_events."\", moment: {\"months\" : ".$uca_months_events.", \"monthsShort\" : ".$uca_monshort_events.", \"weekdays\" : ".$uca_weekdays_events.", \"weekdaysShort\" : ".$uca_wdayshort_events.", \"weekdaysMin\" : ".$uca_wdaymin_events."}}});});"; + $AVE_Template->assign('formaction', 'index.php?do=modules&action=modedit&mod=unicalendar&moduleaction=new&sub=save&cp=' . SESSION); - // Получаем Id документов в категории на момент создания календаря и записываем значение в БД - $rubric_count ='Id='.$rubric_count; - $rubric_count = chop($rubric_count, ' OR Id='); + $AVE_Template->assign('content', $AVE_Template->fetch($tpl_dir . 'admin_unicalendar_list.tpl')); + } + +/** + * Создание календаря + */ +function unicalendarNew() +{ + if (isset($_REQUEST['sub']) && $_REQUEST['sub'] == 'save') + { + global $AVE_DB; + $alert = ''; + + if (empty($_POST['uca_title'])) + { + header('Location:index.php?do=modules&action=modedit&mod=unicalendar&moduleaction=1&alert=empty_uca_title'); + exit; + } + + $uca_ttl_field = (int)($_POST['i_uca_ttl_field'] ?? 0); + $uca_str_field = (int)($_POST['i_uca_str_field'] ?? 0); + $uca_end_field = (int)($_POST['i_uca_end_field'] ?? 0); $AVE_DB->Query(" - UPDATE - " . PREFIX . "_module_unicalendar - SET - uca_doc_id = '" . $rubric_count . "' - WHERE id = '" . $uca_id . "' - "); + INSERT INTO " . PREFIX . "_module_unicalendar + SET + uca_title = '" . addslashes($_POST['uca_title']) . "', + uca_date_format = '" . addslashes($_POST['uca_date_format']) . "', + uca_events = '" . addslashes($_POST['uca_events']) . "', + uca_rubric_id = '" . (int)$_POST['uca_rubric_id'] . "', + uca_rubric_title = '" . addslashes($_POST['uca_rubric_title']) . "', + uca_doc_id = '" . addslashes($_POST['uca_doc_id'] ?? '') . "', + uca_link = '" . ($_POST['uca_link'] == 'true' ? 'true' : 'false') . "', + uca_day = '" . ($_POST['uca_day'] == 'true' ? 'true' : 'false') . "', + uca_scroll = '" . ($_POST['uca_scroll'] == 'true' ? 'true' : 'false') . "', + uca_descript = '" . ($_POST['uca_descript'] == 'true' ? 'true' : 'false') . "', + uca_events_limit = '" . (int)$_POST['uca_events_limit'] . "', + uca_ttl_field = '" . $uca_ttl_field . "', + uca_img_field = '" . (int)$_POST['i_uca_img_field'] . "', + uca_dsc_field = '" . (int)$_POST['i_uca_dsc_field'] . "', + uca_place_field = '" . (int)$_POST['i_uca_place_field'] . "', + uca_str_field = '" . $uca_str_field . "', + uca_end_field = '" . $uca_end_field . "' + "); - // Создаем js файл для календаря с названием dataXXX.js - где XXX = Id календаря - $fdir = "/modules/unicalendar/js/data-files/"; - mkdir(BASE_DIR . $fdir, 0777, true); - chmod(BASE_DIR . $fdir, 0777); - $df = fopen(BASE_DIR . "/modules/unicalendar/js/data-files/data".$uca_id.".js", "w") - or die($uca_not_write_file);// ругаемся если нет прав на запись в директорию data-files ! - flock($df,2); - fwrite($df, $js_data_files); - flock($df,3); - fclose($df); - } + $uca_id = $AVE_DB->InsertId(); - // Если выбрали вывести выбранные документы из заданной рубрики - документы с Id=1 (Главная) и 404 страница - выводиться не будут! - if ($uevents !='' && $uevents == '2'){ - $sql = $AVE_DB->Query(" - SELECT Id, document_alias, document_title, document_published, document_expire, document_meta_description + require(BASE_DIR . '/modules/unicalendar/lang/'.($_SESSION['admin_language'] ?? 'ru').'.php'); + + $sql = $AVE_DB->Query("SELECT * FROM " . PREFIX . "_module_unicalendar WHERE id = '" . $uca_id . "'"); + $v = $sql->FetchAssocArray(); + + if ($v) + { + $uni_data = ""; + $rubric_count_ids = []; + + $where = "rubric_id = '" . (int)$v['uca_rubric_id'] . "' AND Id != 1 AND Id != '" . PAGE_NOT_FOUND_ID . "'"; + + if ($v['uca_events'] == '2' && !empty($v['uca_doc_id'])) { + $where .= " AND (" . $v['uca_doc_id'] . ")"; + } + + $sql_docs = $AVE_DB->Query(" + SELECT Id, document_alias, document_title, document_published, document_expire + FROM " . PREFIX . "_documents + WHERE " . $where + ); + + while ($res = $sql_docs->FetchAssocArray()) + { + // --- ЗАГОЛОВОК (Очистка + Лимит 100) --- + $raw_title = ($v['uca_ttl_field'] > 0) + ? get_document_field($res['Id'], $v['uca_ttl_field']) + : $res['document_title']; + if (empty($raw_title)) $raw_title = $res['document_title']; + + $clean_title = preg_replace('|[\s]+|su', ' ', strip_tags($raw_title)); + $event_title = mb_substr($clean_title, 0, 100, 'UTF-8'); + if (mb_strlen($clean_title, 'UTF-8') > 100) $event_title .= '...'; + + // --- ДАТЫ --- + $date_start = ($v['uca_str_field'] > 0) + ? get_document_field($res['Id'], $v['uca_str_field']) + : $res['document_published']; + + $date_end = ($v['uca_end_field'] > 0) + ? get_document_field($res['Id'], $v['uca_end_field']) + : $res['document_expire']; + + // --- ИЗОБРАЖЕНИЕ --- + $img_raw = get_document_field($res['Id'], $v['uca_img_field']); + $img = strstr($img_raw, '|', true) ?: $img_raw; + + // --- ОПИСАНИЕ (Очистка + Лимит 250) --- + $raw_desc = get_document_field($res['Id'], $v['uca_dsc_field']); + $clean_desc = preg_replace('|[\s]+|su', ' ', strip_tags($raw_desc)); + $desc = rtrim(mb_substr($clean_desc, 0, 250, 'UTF-8'), "!,.-"); + if (mb_strlen($clean_desc, 'UTF-8') > 250) $desc .= '...'; + + // --- МЕСТО (Очистка + Лимит 250) --- + $raw_place = get_document_field($res['Id'], $v['uca_place_field']); + $clean_place = preg_replace('|[\s]+|su', ' ', strip_tags($raw_place)); + $place = mb_substr($clean_place, 0, 250, 'UTF-8'); + if (mb_strlen($clean_place, 'UTF-8') > 250) $place .= '...'; + + // Формируем JSON + $uni_data .= "{ + \"date\": \"" . pretty_date(ave_date_format('%Y-%m-%d %H:%M:%S', $date_start)) . "\", + \"expire_date\": \"" . pretty_date(ave_date_format('%Y-%m-%d %H:%M:%S', $date_end)) . "\", + \"title\": " . json_encode($event_title, JSON_UNESCAPED_UNICODE) . ", + \"image\": " . json_encode($img, JSON_UNESCAPED_UNICODE) . ", + \"description\": " . json_encode($desc, JSON_UNESCAPED_UNICODE) . ", + \"location\": " . json_encode($place, JSON_UNESCAPED_UNICODE) . ", + \"url\": " . json_encode($res['document_alias'], JSON_UNESCAPED_UNICODE) . " + },"; + + $rubric_count_ids[] = $res['Id']; + } + + // Формирование JS файла + $js_data_files = "(function(){function initUcaData(){if(window.jQuery&&jQuery.fn.eventCalendar){jQuery(function($){var data".$uca_id."=[".rtrim($uni_data, ',')."];$('#eventCalendar".$uca_id."').eventCalendar({jsonData:data".$uca_id.",jsonDateFormat:'human',startWeekOnMonday:".($v['uca_day'] == 'true' ? 'true' : 'false').",eventsScrollable:".($v['uca_scroll'] == 'true' ? 'true' : 'false').",openEventInNewWindow:".($v['uca_link'] == 'true' ? 'true' : 'false').",dateFormat:'".addslashes($v['uca_date_format'])."',showDescription:".($v['uca_descript'] == 'true' ? 'true' : 'false').",eventsLimit:".(int)$v['uca_events_limit'].",locales:{locale:'".($uca_locale ?? 'ru')."',txt_noEvents:".json_encode($uca_no_events ?? '').",txt_SpecificEvents_prev:'',txt_SpecificEvents_after:".json_encode($uca_real_events ?? '').",txt_NextEvents:".json_encode($uca_next_events ?? '').",txt_GoToEventUrl:".json_encode($uca_look_events ?? '').",moment:{'months':".($uca_months_events ?? '[]').",'monthsShort':".($uca_monshort_events ?? '[]').",'weekdays':".($uca_weekdays_events ?? '[]').",'weekdaysShort':".($uca_wdayshort_events ?? '[]').",'weekdaysMin':".($uca_wdaymin_events ?? '[]')."}}});});}else{setTimeout(initUcaData,50);}}initUcaData();})();"; + + if ($v['uca_events'] == '1' && !empty($rubric_count_ids)) { + $doc_ids_str = 'Id=' . implode(' OR Id=', $rubric_count_ids); + $AVE_DB->Query("UPDATE " . PREFIX . "_module_unicalendar SET uca_doc_id = '" . addslashes($doc_ids_str) . "' WHERE id = '" . $uca_id . "'"); + } + + $fdir = BASE_DIR . "/modules/unicalendar/js/data-files/"; + if (!is_dir($fdir)) mkdir($fdir, 0755, true); + + $file_path = $fdir . "data" . $uca_id . ".js"; + if ($df = fopen($file_path, "w")) { + flock($df, LOCK_EX); + fwrite($df, $js_data_files); + flock($df, LOCK_UN); + fclose($df); + chmod($file_path, 0644); + } + } + + header('Location:index.php?do=modules&action=modedit&mod=unicalendar&moduleaction=1' . $alert); + exit; + } +} + +/** + * Редактирование календаря + * @param string $tpl_dir - путь к шаблонам модуля + * @param int $unicalendar_id - идентификатор календаря + */ +function unicalendarEdit($tpl_dir, $unicalendar_id) +{ + global $AVE_DB, $AVE_Template; + + $sql = $AVE_DB->Query(" + SELECT * + FROM " . PREFIX . "_module_unicalendar + WHERE id = '" . (int)$unicalendar_id . "' + LIMIT 1 + "); + + $unicalendars = $sql->FetchAssocArray(); + + if (!$unicalendars) { + return; + } + + $uevents = $unicalendars['uca_events']; + $urubric_id = (int)$unicalendars['uca_rubric_id']; + $udoc_id = $unicalendars['uca_doc_id']; + + $unidocs = []; + $check_docs = []; + + if ($uevents == 2) + { + // Получаем все документы рубрики + $sql_docs = $AVE_DB->Query(" + SELECT Id, document_alias, document_title, document_published, document_expire, document_meta_description FROM " . PREFIX . "_documents - WHERE rubric_id = '" . $urubric_id . "' AND Id !=1 && Id != '".PAGE_NOT_FOUND_ID."' AND ".$udoc_id." + WHERE rubric_id = '" . $urubric_id . "' + AND Id != 1 + AND Id != '" . PAGE_NOT_FOUND_ID . "' "); - $results = array(); - while ($row = $sql->FetchAssocArray()) - { - array_push($results, $row); - } - //получаем данные выбранных документов из заданной рубрики циклом, формируем строку JSON - foreach ( $results as $k=>$v ) - { - $uni_data .= "{ \"date\": \"".pretty_date(strftime('%Y-%m-%d %H:%M:%S', $v['document_published']))."\", \"expire_date\": \"".pretty_date(strftime('%Y-%m-%d %H:%M:%S', $v['document_expire']))."\", \"title\": \"".$v['document_title']."\", \"image\": \"".strstr(get_document_field($v['Id'], $uca_img_field), '|', true)."\", \"description\": \"".rtrim(mb_substr(preg_replace('|[\s]+|su', ' ', strip_tags(get_document_field($v['Id'], $uca_dsc_field))), 0, 255, 'UTF-8'), "!,.-").$ellipsis."\", \"location\": \"".mb_substr(preg_replace('|[\s]+|su', ' ', strip_tags(get_document_field($v['Id'], $uca_place_field))), 0, 300, 'UTF-8')."\", \"url\": \"".$v['document_alias']."\" },"; - $rubric_count .= $v['Id'].","; - } - $js_data_files = "$(function(){"."var data".$uca_id." = [".$uni_data."]; $(\"#eventCalendar".$uca_id."\").eventCalendar({jsonData: data".$uca_id.", jsonDateFormat: \"human\", startWeekOnMonday: ".$uca_day.", eventsScrollable: ".$uca_scroll.", openEventInNewWindow: ".$uca_link.", dateFormat: \"".$uca_dfrm."\", showDescription: ".$uca_descript.", eventsLimit: ".$uca_events_limit.", locales: {locale: \"".$uca_locale."\", txt_noEvents: \"".$uca_no_events."\", txt_SpecificEvents_prev: \"\", txt_SpecificEvents_after: \"".$uca_real_events."\", txt_NextEvents: \"".$uca_next_events."\", txt_GoToEventUrl: \"".$uca_look_events."\", moment: {\"months\" : ".$uca_months_events.", \"monthsShort\" : ".$uca_monshort_events.", \"weekdays\" : ".$uca_weekdays_events.", \"weekdaysShort\" : ".$uca_wdayshort_events.", \"weekdaysMin\" : ".$uca_wdaymin_events."}}});});"; + + while ($row = $sql_docs->FetchAssocArray()) { + $unidocs[] = $row; + } - // Создаем js файл для календаря с названием dataXXX.js - где XXX = Id календаря - $fdir = "/modules/unicalendar/js/data-files/"; - mkdir(BASE_DIR . $fdir, 0777, true); - chmod(BASE_DIR . $fdir, 0777); - $df = fopen(BASE_DIR . "/modules/unicalendar/js/data-files/data".$uca_id.".js", "w") - or die($uca_not_write_file);// ругаемся если нет прав на запись в директорию data-files ! - flock($df,2); - fwrite($df, $js_data_files); - flock($df,3); - fclose($df); - } - } - header('Location:index.php?do=modules&action=modedit&mod=unicalendar&moduleaction=1'. $alert); - exit; - } - } + if (!empty($udoc_id) && trim($udoc_id) != '') { + $sql_check = $AVE_DB->Query(" + SELECT Id + FROM " . PREFIX . "_documents + WHERE rubric_id = '" . $urubric_id . "' + AND Id != 1 + AND Id != '" . PAGE_NOT_FOUND_ID . "' + AND (" . $udoc_id . ") + "); + + if ($sql_check) { + while ($row = $sql_check->FetchAssocArray()) { + $check_docs[] = $row; + } + } + } + } + + $AVE_Template->assign([ + 'unidocs' => $unidocs, + 'check_docs' => $check_docs, + 'unicalendars' => $unicalendars + ]); - /** - * Редактирование календаря - * @param int $unicalendar_id - идентификатор календаря - */ - function unicalendarEdit($tpl_dir, $unicalendar_id) - { - global $AVE_DB, $AVE_Template; - $sql = $AVE_DB->Query(" - SELECT * - FROM " . PREFIX . "_module_unicalendar - WHERE id = '" . $unicalendar_id . "' - "); - $unicalendars = array(); - while ($row = $sql->FetchAssocArray()) - { - array_push($unicalendars, $row); - } - foreach ( $unicalendars as $k=>$v ) - { - $uevents = $v['uca_events']; - $urubric_id = $v['uca_rubric_id']; - $udoc_id = $v['uca_doc_id']; - } + $AVE_Template->assign('content', $AVE_Template->fetch($tpl_dir . 'admin_unicalendar_edit.tpl')); +} - if($uevents == 2) - { - $sql = $AVE_DB->Query(" - SELECT Id, document_alias, document_title, document_published, document_expire, document_meta_description - FROM " . PREFIX . "_documents - WHERE rubric_id = '" . $urubric_id . "' AND Id !=1 && Id != '".PAGE_NOT_FOUND_ID."' - "); - $unidocs = array(); - while ($row = $sql->FetchAssocArray()) - { - array_push($unidocs, $row); - } - $AVE_Template->assign('unidocs', $unidocs); - - $sql = $AVE_DB->Query(" - SELECT Id - FROM " . PREFIX . "_documents - WHERE rubric_id = '" . $urubric_id . "' AND Id !=1 && Id != '".PAGE_NOT_FOUND_ID."' AND ".$udoc_id." - "); - $check_docs = array(); - while ($row = $sql->FetchAssocArray()) - { - array_push($check_docs, $row); - } - $AVE_Template->assign('check_docs', $check_docs); - } - - //$AVE_Template->assign('uca_rub_fields', $uca_rub_fields); - $AVE_Template->assign('unicalendars', $unicalendars); - $AVE_Template->assign('content', $AVE_Template->fetch($tpl_dir . 'admin_unicalendar_edit.tpl')); - - } - - /** - * Сохранение календаря после редактирования - * @param int $unicalendar_id - идентификатор календаря - */ + /** + * Сохранение календаря после редактирования + * @param int $unicalendar_id - идентификатор календаря + */ function unicalendarEditSave($unicalendar_id) { - global $AVE_DB; - $AVE_DB->Query(" - UPDATE - " . PREFIX . "_module_unicalendar - SET - uca_title = '" . $_POST['uca_title'] . "', - uca_date_format = '" . $_POST['uca_date_format'] . "', - uca_doc_id = '" . $_POST['uca_doc_id'] . "', - uca_events = '" . $_POST['uca_events'] . "', - uca_rubric_id = '" . $_POST['uca_rubric_id'] . "', - uca_rubric_title = '" . $_POST['uca_rubric_title'] . "', - uca_link = '" . $_POST['uca_link'] . "', - uca_day = '" . $_POST['uca_day'] . "', - uca_scroll = '" . $_POST['uca_scroll'] . "', - uca_descript = '" . $_POST['uca_descript'] . "', - uca_events_limit = '" . $_POST['uca_events_limit'] . "', - uca_img_field = '" . $_POST['send_uca_img_field'] . "', - uca_dsc_field = '" . $_POST['send_uca_dsc_field'] . "', - uca_place_field = '" . $_POST['send_uca_place_field'] . "' - WHERE id = '" . $unicalendar_id . "' - "); - $as = array(); - $as->$_POST['uca_title']; - $as->$_POST['uca_rubric_title']; - echo json_encode($as); - // Получаем обновленные данные календаря - require(BASE_DIR . '/modules/unicalendar/lang/'.$_SESSION['admin_language'].'.php'); // загружаем файл ленгов для php переменных - $sql = $AVE_DB->Query(" - SELECT * - FROM " . PREFIX . "_module_unicalendar - WHERE id = '" . $unicalendar_id . "' - "); - $unicalendars = array(); - while ($row = $sql->FetchAssocArray()) - { - array_push($unicalendars, $row); - } - foreach ( $unicalendars as $k=>$v ) - { - $uevents = $v['uca_events']; - $uca_dfrm = $v['uca_date_format']; - $urubric_id = $v['uca_rubric_id']; - $udoc_id = $v['uca_doc_id']; - $uca_day = $v['uca_day']; - $uca_scroll = $v['uca_scroll']; - $uca_link = $v['uca_link']; - $uca_descript = $v['uca_descript']; - $uca_events_limit = $v['uca_events_limit']; - $uca_img_field = $v['uca_img_field']; - $uca_dsc_field = $v['uca_dsc_field']; - $uca_place_field = $v['uca_place_field']; - } - if ($uca_dsc_field != 0) {$ellipsis = '… ';} else {$ellipsis = '';};// если описания нет не добавляем многоточие при выводе description - // Если выбрали вывести все документы из заданной рубрики - документы с Id=1 (Главная) и 404 страница - выводиться не будут! - if ($uevents !='' && $uevents == '1'){ - $sql = $AVE_DB->Query(" - SELECT Id, document_alias, document_title, document_published, document_expire, document_meta_description - FROM " . PREFIX . "_documents - WHERE rubric_id = '" . $urubric_id . "' AND Id !=1 && Id != '".PAGE_NOT_FOUND_ID."' - "); - $results = array(); - while ($row = $sql->FetchAssocArray()) - { - array_push($results, $row); - } - //получаем данные всех документов из заданной рубрики циклом, формируем строку JSON - foreach ( $results as $k=>$v ) - { - $uni_data .= "{ \"date\": \"".pretty_date(strftime('%Y-%m-%d %H:%M:%S', $v['document_published']))."\", \"expire_date\": \"".pretty_date(strftime('%Y-%m-%d %H:%M:%S', $v['document_expire']))."\", \"title\": \"".$v['document_title']."\", \"image\": \"".strstr(get_document_field($v['Id'], $uca_img_field), '|', true)."\", \"description\": \"".rtrim(mb_substr(preg_replace('|[\s]+|su', ' ', strip_tags(get_document_field($v['Id'], $uca_dsc_field))), 0, 255, 'UTF-8'), "!,.-").$ellipsis."\", \"location\": \"".mb_substr(preg_replace('|[\s]+|su', ' ', strip_tags(get_document_field($v['Id'], $uca_place_field))), 0, 300, 'UTF-8')."\", \"url\": \"".$v['document_alias']."\" },"; - $rubric_count .= $v['Id']." OR Id="; - } - $js_data_files = "$(function(){"."var data".$unicalendar_id." = [".$uni_data."]; $(\"#eventCalendar".$unicalendar_id."\").eventCalendar({jsonData: data".$unicalendar_id.", jsonDateFormat: \"human\", startWeekOnMonday: ".$uca_day.", eventsScrollable: ".$uca_scroll.", openEventInNewWindow: ".$uca_link.", dateFormat: \"".$uca_dfrm."\", showDescription: ".$uca_descript.", eventsLimit: ".$uca_events_limit.", locales: {locale: \"".$uca_locale."\", txt_noEvents: \"".$uca_no_events."\", txt_SpecificEvents_prev: \"\", txt_SpecificEvents_after: \"".$uca_real_events."\", txt_NextEvents: \"".$uca_next_events."\", txt_GoToEventUrl: \"".$uca_look_events."\", moment: {\"months\" : ".$uca_months_events.", \"monthsShort\" : ".$uca_monshort_events.", \"weekdays\" : ".$uca_weekdays_events.", \"weekdaysShort\" : ".$uca_wdayshort_events.", \"weekdaysMin\" : ".$uca_wdaymin_events."}}});});"; - - // Получаем Id документов в категории на момент создания календаря и записываем значение в БД - $rubric_count ='Id='.$rubric_count; - $rubric_count = chop($rubric_count, ' OR Id='); + global $AVE_DB; + $unicalendar_id = (int)$unicalendar_id; $AVE_DB->Query(" - UPDATE - " . PREFIX . "_module_unicalendar - SET - uca_doc_id = '" . $rubric_count . "' - WHERE id = '" . $unicalendar_id . "' - "); - - // Создаем js файл для календаря с названием dataXXX.js - где XXX = Id календаря - $fdir = "/modules/unicalendar/js/data-files/"; - mkdir(BASE_DIR . $fdir, 0777, true); - chmod(BASE_DIR . $fdir, 0777); - $df = fopen(BASE_DIR . "/modules/unicalendar/js/data-files/data".$unicalendar_id.".js", "w") - or die($uca_not_write_file);// ругаемся если нет прав на запись в директорию data-files ! - flock($df,2); - fwrite($df, $js_data_files); - flock($df,3); - fclose($df); - } - - // Если выбрали вывести выбранные документы из заданной рубрики - документы с Id=1 (Главная) и 404 страница - выводиться не будут! - if ($uevents !='' && $uevents == '2'){ - $sql = $AVE_DB->Query(" - SELECT Id, document_alias, document_title, document_published, document_expire, document_meta_description - FROM " . PREFIX . "_documents - WHERE rubric_id = '" . $urubric_id . "' AND Id !=1 && Id != '".PAGE_NOT_FOUND_ID."' AND ".$udoc_id." + UPDATE " . PREFIX . "_module_unicalendar + SET + uca_title = '" . addslashes($_POST['uca_title']) . "', + uca_date_format = '" . addslashes($_POST['uca_date_format']) . "', + uca_doc_id = '" . addslashes($_POST['uca_doc_id'] ?? '') . "', + uca_events = '" . addslashes($_POST['uca_events']) . "', + uca_rubric_id = '" . (int)$_POST['uca_rubric_id'] . "', + uca_rubric_title = '" . addslashes($_POST['uca_rubric_title']) . "', + uca_link = '" . ($_POST['uca_link'] == 'true' ? 'true' : 'false') . "', + uca_day = '" . ($_POST['uca_day'] == 'true' ? 'true' : 'false') . "', + uca_scroll = '" . ($_POST['uca_scroll'] == 'true' ? 'true' : 'false') . "', + uca_descript = '" . ($_POST['uca_descript'] == 'true' ? 'true' : 'false') . "', + uca_events_limit = '" . (int)$_POST['uca_events_limit'] . "', + uca_ttl_field = '" . (int)$_POST['send_uca_ttl_field'] . "', + uca_img_field = '" . (int)$_POST['send_uca_img_field'] . "', + uca_dsc_field = '" . (int)$_POST['send_uca_dsc_field'] . "', + uca_place_field = '" . (int)$_POST['send_uca_place_field'] . "', + uca_str_field = '" . (int)$_POST['send_uca_str_field'] . "', + uca_end_field = '" . (int)$_POST['send_uca_end_field'] . "' + WHERE id = '" . $unicalendar_id . "' "); - $results = array(); - while ($row = $sql->FetchAssocArray()) - { - array_push($results, $row); - } - //получаем данные выбранных документов из заданной рубрики циклом, формируем строку JSON - foreach ( $results as $k=>$v ) - { - $uni_data .= "{ \"date\": \"".pretty_date(strftime('%Y-%m-%d %H:%M:%S', $v['document_published']))."\", \"expire_date\": \"".pretty_date(strftime('%Y-%m-%d %H:%M:%S', $v['document_expire']))."\", \"title\": \"".$v['document_title']."\", \"image\": \"".strstr(get_document_field($v['Id'], $uca_img_field), '|', true)."\", \"description\": \"".rtrim(mb_substr(preg_replace('|[\s]+|su', ' ', strip_tags(get_document_field($v['Id'], $uca_dsc_field))), 0, 255, 'UTF-8'), "!,.-").$ellipsis."\", \"location\": \"".mb_substr(preg_replace('|[\s]+|su', ' ', strip_tags(get_document_field($v['Id'], $uca_place_field))), 0, 300, 'UTF-8')."\", \"url\": \"".$v['document_alias']."\" },"; - $rubric_count .= $v['Id'].","; - } - $js_data_files = "$(function(){"."var data".$unicalendar_id." = [".$uni_data."]; $(\"#eventCalendar".$unicalendar_id."\").eventCalendar({jsonData: data".$unicalendar_id.", jsonDateFormat: \"human\", startWeekOnMonday: ".$uca_day.", eventsScrollable: ".$uca_scroll.", openEventInNewWindow: ".$uca_link.", dateFormat: \"".$uca_dfrm."\", showDescription: ".$uca_descript.", eventsLimit: ".$uca_events_limit.", locales: {locale: \"".$uca_locale."\", txt_noEvents: \"".$uca_no_events."\", txt_SpecificEvents_prev: \"\", txt_SpecificEvents_after: \"".$uca_real_events."\", txt_NextEvents: \"".$uca_next_events."\", txt_GoToEventUrl: \"".$uca_look_events."\", moment: {\"months\" : ".$uca_months_events.", \"monthsShort\" : ".$uca_monshort_events.", \"weekdays\" : ".$uca_weekdays_events.", \"weekdaysShort\" : ".$uca_wdayshort_events.", \"weekdaysMin\" : ".$uca_wdaymin_events."}}});});"; - // Создаем js файл для календаря с названием dataXXX.js - где XXX = Id календаря - $fdir = "/modules/unicalendar/js/data-files/"; - mkdir(BASE_DIR . $fdir, 0777, true); - chmod(BASE_DIR . $fdir, 0777); - $df = fopen(BASE_DIR . "/modules/unicalendar/js/data-files/data".$unicalendar_id.".js", "w") - or die($uca_not_write_file);// ругаемся если нет прав на запись в директорию data-files ! - flock($df,2); - fwrite($df, $js_data_files); - flock($df,3); - fclose($df); - } + $as = [ + 'title' => is_array($_POST['uca_title']) ? ($_POST['uca_title'][0] ?? '') : $_POST['uca_title'], + 'rubric_title' => is_array($_POST['uca_rubric_title']) ? ($_POST['uca_rubric_title'][0] ?? '') : $_POST['uca_rubric_title'] + ]; - exit; + require(BASE_DIR . '/modules/unicalendar/lang/' . ($_SESSION['admin_language'] ?? 'ru') . '.php'); + + $sql = $AVE_DB->Query("SELECT * FROM " . PREFIX . "_module_unicalendar WHERE id = '" . $unicalendar_id . "' LIMIT 1"); + $v = $sql->FetchAssocArray(); + + if ($v) { + $uni_data = ''; + $rubric_count_ids = []; + + $where = "rubric_id = '" . (int)$v['uca_rubric_id'] . "' AND Id != 1 AND Id != '" . PAGE_NOT_FOUND_ID . "'"; + + if ($v['uca_events'] == '2' && !empty($v['uca_doc_id'])) { + $where .= " AND (" . $v['uca_doc_id'] . ")"; + } + + $sql_docs = $AVE_DB->Query("SELECT Id, document_alias, document_title, document_published, document_expire FROM " . PREFIX . "_documents WHERE $where"); + + while ($res = $sql_docs->FetchAssocArray()) { + // --- ЗАГОЛОВОК (Очистка + Лимит 100) --- + $custom_title = get_document_field($res['Id'], $v['uca_ttl_field']); + $raw_title = (!empty($custom_title)) ? $custom_title : $res['document_title']; + + $clean_title = preg_replace('|[\s]+|su', ' ', strip_tags($raw_title)); + $event_title = mb_substr($clean_title, 0, 100, 'UTF-8'); + if (mb_strlen($clean_title, 'UTF-8') > 100) $event_title .= '...'; + + // --- ДАТЫ --- + $custom_start = get_document_field($res['Id'], $v['uca_str_field']); + $custom_end = get_document_field($res['Id'], $v['uca_end_field']); + $date_start = (!empty($custom_start)) ? $custom_start : $res['document_published']; + $date_end = (!empty($custom_end)) ? $custom_end : $res['document_expire']; + + // --- ИЗОБРАЖЕНИЕ --- + $img_raw = get_document_field($res['Id'], $v['uca_img_field']); + $img = strstr($img_raw, '|', true) ?: $img_raw; + + // --- ОПИСАНИЕ (Очистка + Лимит 250) --- + $raw_desc = get_document_field($res['Id'], $v['uca_dsc_field']); + $clean_desc = preg_replace('|[\s]+|su', ' ', strip_tags($raw_desc)); + $desc = rtrim(mb_substr($clean_desc, 0, 250, 'UTF-8'), "!,.-"); + if (mb_strlen($clean_desc, 'UTF-8') > 250) $desc .= '...'; + + // --- МЕСТО (Очистка + Лимит 250) --- + $raw_place = get_document_field($res['Id'], $v['uca_place_field']); + $clean_place = preg_replace('|[\s]+|su', ' ', strip_tags($raw_place)); + $place = mb_substr($clean_place, 0, 250, 'UTF-8'); + if (mb_strlen($clean_place, 'UTF-8') > 250) $place .= '...'; + + $uni_data .= "{ + \"date\": \"" . pretty_date(ave_date_format('%Y-%m-%d %H:%M:%S', $date_start)) . "\", + \"expire_date\": \"" . pretty_date(ave_date_format('%Y-%m-%d %H:%M:%S', $date_end)) . "\", + \"title\": " . json_encode($event_title, JSON_UNESCAPED_UNICODE) . ", + \"image\": " . json_encode($img, JSON_UNESCAPED_UNICODE) . ", + \"description\": " . json_encode($desc, JSON_UNESCAPED_UNICODE) . ", + \"location\": " . json_encode($place, JSON_UNESCAPED_UNICODE) . ", + \"url\": " . json_encode($res['document_alias'], JSON_UNESCAPED_UNICODE) . " + },"; + + $rubric_count_ids[] = $res['Id']; + } + + // Формирование JS файла + $js_data_files = "(function(){function initUcaData(){if(window.jQuery&&jQuery.fn.eventCalendar){jQuery(function($){var data".$unicalendar_id."=[".rtrim($uni_data, ',')."];$('#eventCalendar".$unicalendar_id."').eventCalendar({jsonData:data".$unicalendar_id.",jsonDateFormat:'human',startWeekOnMonday:".($v['uca_day'] == 'true' ? 'true' : 'false').",eventsScrollable:".($v['uca_scroll'] == 'true' ? 'true' : 'false').",openEventInNewWindow:".($v['uca_link'] == 'true' ? 'true' : 'false').",dateFormat:'".addslashes($v['uca_date_format'])."',showDescription:".($v['uca_descript'] == 'true' ? 'true' : 'false').",eventsLimit:".(int)$v['uca_events_limit'].",locales:{locale:'".($uca_locale??'ru')."',txt_noEvents:".json_encode($uca_no_events??'').",txt_SpecificEvents_prev:'',txt_SpecificEvents_after:".json_encode($uca_real_events??'').",txt_NextEvents:".json_encode($uca_next_events??'').",txt_GoToEventUrl:".json_encode($uca_look_events??'').",moment:{'months':".($uca_months_events?? '[]').",'monthsShort':".($uca_monshort_events?? '[]').",'weekdays':".($uca_weekdays_events?? '[]').",'weekdaysShort':".($uca_wdayshort_events?? '[]').",'weekdaysMin':".($uca_wdaymin_events?? '[]')."}}});});}else{setTimeout(initUcaData,50);}}initUcaData();})();"; + + if ($v['uca_events'] == '1' && !empty($rubric_count_ids)) { + $ids_str = 'Id=' . implode(' OR Id=', $rubric_count_ids); + $AVE_DB->Query("UPDATE " . PREFIX . "_module_unicalendar SET uca_doc_id = '" . addslashes($ids_str) . "' WHERE id = '$unicalendar_id'"); + } + + $fdir = BASE_DIR . "/modules/unicalendar/js/data-files/"; + if (!is_dir($fdir)) { + mkdir($fdir, 0755, true); + } + + $file_path = $fdir . "data" . $unicalendar_id . ".js"; + if ($df = fopen($file_path, "w")) { + flock($df, LOCK_EX); + fwrite($df, $js_data_files); + flock($df, LOCK_UN); + fclose($df); + chmod($file_path, 0644); + } else { + die($uca_not_write_file ?? 'Error writing JS file'); + } + } + + header('Content-Type: application/json'); + echo json_encode($as); + exit; } - /** - * Выбор событий календаря - * - */ - + /** + * Выбор событий календаря (AJAX-обработчик) + */ function unicalendarEventsNew() { - require_once(BASE_DIR . '/modules/unicalendar/lang/'.$_SESSION['admin_language'].'.php'); // загружаем файл ленгов для php переменных + // Защита от прямого вызова файла (вне ядра системы) + if (!defined('BASE_DIR')) exit; - if (isset($_POST['c'])) // если пришел запрос вывести все категории, получаем данные и отдаем их в шаблон (выпадающий список) - { - global $AVE_DB; - $sql = $AVE_DB->Query(" - SELECT Id, rubric_title - FROM " . PREFIX . "_rubrics - "); - echo ""; - while($result = $sql->FetchRow()) - { - echo ""; - }; - } - - if (isset($_POST['a'])) // если пришел запрос вывести все документы (не будет выведен документ с Id=1 это Главная страница и документ Ошибка 404), получаем и выводим чекбоксами - { - global $AVE_DB; - $sql = $AVE_DB->Query(" - SELECT Id, document_alias, document_title, document_published, document_expire, document_meta_description - FROM " . PREFIX . "_documents - WHERE rubric_id = '" . $_POST['b'] . "' AND Id !=1 && Id != '".PAGE_NOT_FOUND_ID."' - "); - $u_sel_doc = array(); - while ($row = $sql->FetchAssocArray()) - { - array_push($u_sel_doc, $row); - } - foreach ( $u_sel_doc as $k=>$v ) - { - echo ""."".$v['Id'].""."".$v['document_title'].""."".$v['document_published'] = pretty_date(strftime(TIME_FORMAT, $v['document_published'])).""."".$v['document_expire'] = pretty_date(strftime(TIME_FORMAT, $v['document_expire'])).""; - } - } - - - if (isset($_POST['uca_rub_field'])) // если пришел запрос вывести поля категории, получаем данные и отдаем их в шаблон (выпадающий список) - { - global $AVE_DB; - $sql = $AVE_DB->Query(" - SELECT Id, rubric_field_title - FROM " . PREFIX . "_rubric_fields - WHERE rubric_id = '" . $_POST['uca_frub_id'] . "' - "); - while($result = $sql->FetchRow()) - { - echo ""; - }; - } + // Проверяем либо право на модули, либо полные права (alles) + if (!check_permission_acp('modules_admin') && !check_permission_acp('alles')) { + header('HTTP/1.1 403 Forbidden'); + exit('Access Denied'); + } global $AVE_DB; - $sql = $AVE_DB->Query(" - SELECT * - FROM " . PREFIX . "_module_unicalendar - WHERE id = '".intval($_REQUEST['id'])."' - "); - $unica = array(); - while ($row = $sql->FetchAssocArray()) - { - array_push($unica, $row); - } - foreach ( $unica as $k=>$v ) - { - $uca_img_field = $v['uca_img_field']; - $uca_dsc_field = $v['uca_dsc_field']; - $uca_place_field = $v['uca_place_field']; - } + + $lang = $_SESSION['admin_language'] ?? 'ru'; + require_once(BASE_DIR . '/modules/unicalendar/lang/' . $lang . '.php'); - if (isset($_POST['uca_edit_rub_field_img'])) // если пришел запрос вывести поля изображение при редактировании, получаем данные и отдаем их в шаблон (выпадающий список) - { - global $AVE_DB; - $sql = $AVE_DB->Query(" - SELECT Id, rubric_field_title - FROM " . PREFIX . "_rubric_fields - WHERE rubric_id = '" . $_POST['uca_frub_id'] . "' - "); - while($result = $sql->FetchRow()) - { - if($result->Id == $uca_img_field) {$sel = 'selected=\'selected\'';} else {$sel = '';}; - echo ""; - }; - } - - if (isset($_POST['uca_edit_rub_field_dsc'])) // если пришел запрос вывести поля описание при редактировании, получаем данные и отдаем их в шаблон (выпадающий список) - { - global $AVE_DB; - $sql = $AVE_DB->Query(" - SELECT Id, rubric_field_title - FROM " . PREFIX . "_rubric_fields - WHERE rubric_id = '" . $_POST['uca_frub_id'] . "' - "); - while($result = $sql->FetchRow()) - { - if($result->Id == $uca_dsc_field) {$sel = 'selected=\'selected\'';} else {$sel = '';}; - echo ""; - }; - } - - if (isset($_POST['uca_edit_rub_field_plc'])) // если пришел запрос вывести поля место при редактировании, получаем данные и отдаем их в шаблон (выпадающий список) - { - global $AVE_DB; - $sql = $AVE_DB->Query(" - SELECT Id, rubric_field_title - FROM " . PREFIX . "_rubric_fields - WHERE rubric_id = '" . $_POST['uca_frub_id'] . "' - "); - while($result = $sql->FetchRow()) - { - if($result->Id == $uca_place_field) {$sel = 'selected=\'selected\'';} else {$sel = '';}; - echo ""; - }; - } - - - if (isset($_POST['check_rel'])) // если пришел запрос-проверка актуальности календаря (не будет выведен документ с Id=1 это Главная страница и документ Ошибка 404) + // --- Выбор рубрик --- + if (isset($_POST['c'])) { - global $AVE_DB; - $sql = $AVE_DB->Query(" - SELECT Id - FROM " . PREFIX . "_documents - WHERE rubric_id = '" . $_POST['r_id'] . "' AND Id !=1 && Id != '".PAGE_NOT_FOUND_ID."' - "); - $all_doc_rub = array(); - while ($row = $sql->FetchAssocArray()) - { - array_push($all_doc_rub, $row); - } - foreach ( $all_doc_rub as $k=>$v ) - { - $doc_count .= $v['Id'].","; - } - echo $doc_count = chop($doc_count, ' ,'); - } - if (isset($_POST['allowed_rub'])) //если пришел запрос "проверяем и запрещаем создавать календарь, если рубрика содержит только один или два документа, Id которых равны либо главной странице либо странице 404 , либо и то и другое" - { - global $AVE_DB; - $sql = $AVE_DB->Query(" - SELECT Id - FROM " . PREFIX . "_documents - WHERE rubric_id = '" . $_POST['allowed_rub_id'] . "' - "); - $all_doc_rub = array(); - while ($row = $sql->FetchAssocArray()) - { - array_push($all_doc_rub, $row); - } - foreach ( $all_doc_rub as $k=>$v ) - { - $doc_count .= $v['Id'].","; - } - echo $doc_count = chop($doc_count, ' ,'); - } - exit; + $sql = $AVE_DB->Query("SELECT Id, rubric_title FROM " . PREFIX . "_rubrics"); + echo ""; + while ($row = $sql->FetchRow()) { + echo ""; + } + } + + // --- Выбор документов рубрики --- + if (isset($_POST['a']) && isset($_POST['b'])) + { + $rubric_id = (int)$_POST['b']; + $sql = $AVE_DB->Query(" + SELECT Id, document_alias, document_title, document_published, document_expire + FROM " . PREFIX . "_documents + WHERE rubric_id = '$rubric_id' AND Id != 1 AND Id != '" . (int)PAGE_NOT_FOUND_ID . "' + "); + + while ($v = $sql->FetchAssocArray()) { + $pub = pretty_date(ave_date_format(TIME_FORMAT, $v['document_published'])); + $exp = pretty_date(ave_date_format(TIME_FORMAT, $v['document_expire'])); + + echo " + + " . (int)$v['Id'] . " + " . htmlspecialchars($v['document_title']) . " + " . $pub . " + " . $exp . " + "; + } + } + + // --- Получаем текущие настройки полей из базы --- + $id = (int)($_POST['id'] ?? $_GET['id'] ?? 0); + $saved = ['ttl' => 0, 'img' => 0, 'dsc' => 0, 'plc' => 0, 'str' => 0, 'end' => 0]; + + if ($id > 0) { + $sql = $AVE_DB->Query("SELECT uca_ttl_field, uca_img_field, uca_dsc_field, uca_place_field, uca_str_field, uca_end_field + FROM " . PREFIX . "_module_unicalendar WHERE id = '$id' LIMIT 1"); + $v = $sql->FetchAssocArray(); + if ($v) { + $saved['ttl'] = (int)$v['uca_ttl_field']; + $saved['img'] = (int)$v['uca_img_field']; + $saved['dsc'] = (int)$v['uca_dsc_field']; + $saved['plc'] = (int)$v['uca_place_field']; + $saved['str'] = (int)$v['uca_str_field']; + $saved['end'] = (int)$v['uca_end_field']; + } + } + + // --- Определяем, какое именно поле запрашивает JS --- + $field_request = null; + if (isset($_POST['uca_rub_field'])) $field_request = 'all'; + if (isset($_POST['uca_edit_rub_field_ttl'])) $field_request = 'ttl'; + if (isset($_POST['uca_edit_rub_field_img'])) $field_request = 'img'; + if (isset($_POST['uca_edit_rub_field_dsc'])) $field_request = 'dsc'; + if (isset($_POST['uca_edit_rub_field_plc'])) $field_request = 'plc'; + if (isset($_POST['uca_edit_rub_field_str'])) $field_request = 'str'; + if (isset($_POST['uca_edit_rub_field_end'])) $field_request = 'end'; + + if ($field_request && isset($_POST['uca_frub_id'])) + { + $frub_id = (int)$_POST['uca_frub_id']; + $sql = $AVE_DB->Query("SELECT Id, rubric_field_title FROM " . PREFIX . "_rubric_fields WHERE rubric_id = '$frub_id'"); + + while ($res = $sql->FetchRow()) { + $sel = ''; + $current_id = (int)$res->Id; + if ($field_request == 'ttl' && $current_id == $saved['ttl']) $sel = 'selected="selected"'; + if ($field_request == 'img' && $current_id == $saved['img']) $sel = 'selected="selected"'; + if ($field_request == 'dsc' && $current_id == $saved['dsc']) $sel = 'selected="selected"'; + if ($field_request == 'plc' && $current_id == $saved['plc']) $sel = 'selected="selected"'; + if ($field_request == 'str' && $current_id == $saved['str']) $sel = 'selected="selected"'; + if ($field_request == 'end' && $current_id == $saved['end']) $sel = 'selected="selected"'; + + echo ""; + } + } + + // --- Вспомогательные запросы для зависимостей --- + if (isset($_POST['check_rel']) || isset($_POST['allowed_rub'])) + { + $r_id = (int)($_POST['r_id'] ?? $_POST['allowed_rub_id'] ?? 0); + $filter_sql = ""; + if (isset($_POST['check_rel'])) { + $filter_sql = " AND Id != 1 AND Id != '" . (int)PAGE_NOT_FOUND_ID . "'"; + } + + $sql = $AVE_DB->Query("SELECT Id FROM " . PREFIX . "_documents WHERE rubric_id = '$r_id' $filter_sql"); + $ids = []; + while ($row = $sql->FetchAssocArray()) { + $ids[] = (int)$row['Id']; + } + echo implode(',', $ids); + } + + exit; } - /** - * Удаление календаря - * - * @param int $unicalendar_id - идентификатор календаря - */ - function unicalendarDelete($unicalendar_id) - { - global $AVE_DB; - $AVE_DB->Query("DELETE FROM " . PREFIX . "_module_unicalendar WHERE id = '" . $unicalendar_id . "'"); - // Удаляем js файл с данными из директории /modules/unicalendar/js/data-files/ - $data_dir = "/modules/unicalendar/js/data-files"; - $filename = BASE_DIR .$data_dir."/data".$unicalendar_id.".js"; - if (file_exists($filename)) - { - unlink($filename); + /** + * Удаление календаря + * + * @param int $unicalendar_id - идентификатор календаря + */ + function unicalendarDelete($unicalendar_id) + { + global $AVE_DB; + + $unicalendar_id = (int)$unicalendar_id; + + $AVE_DB->Query("DELETE FROM " . PREFIX . "_module_unicalendar WHERE id = '$unicalendar_id'"); + + $data_dir = "/modules/unicalendar/js/data-files/"; + $filename = BASE_DIR . $data_dir . "data" . $unicalendar_id . ".js"; + + if (is_file($filename)) { + @unlink($filename); } - header('Location:index.php?do=modules&action=modedit&mod=unicalendar&moduleaction=1&cp=' . SESSION); - exit; - } + + header('Location: index.php?do=modules&action=modedit&mod=unicalendar&moduleaction=1&cp=' . SESSION); + exit; + } } ?> \ No newline at end of file diff --git a/css/eventCalendar.css b/css/eventCalendar.css index a24865f..75a7c28 100644 --- a/css/eventCalendar.css +++ b/css/eventCalendar.css @@ -1,99 +1,343 @@ -/*= CORE CSS */ +/* CORE CSS */ .eventCalendar-hidden { - display: none; + display: none; } .eventCalendar-wrap { - position: relative; - overflow: hidden; + position: relative; + overflow: hidden; + border: 1px solid #ddd !important; + box-shadow: none !important; + border-radius: 4px !important; + font-family: inherit; } .eventCalendar-arrow { - position: absolute; - z-index: 5; - top: 3px; -} - -.eventCalendar-prev { - left: 3px; -} - -.eventCalendar-next { - right: 3px; -} - -.eventCalendar-monthTitle { - display: block; - text-align: center; + position: absolute; + z-index: 5; + top: 3px; } .eventCalendar-monthWrap { - position: absolute; - top: 0; - left: 0; - z-index: 2; + position: absolute; + top: 0; + left: 0; + z-index: 2; } .eventCalendar-currentMonth { - z-index: 1; + z-index: 1; } .eventCalendar-daysList { - display: table; - width: 100%; + display: table; + width: 100%; + background: #fff !important; + border: none !important; } .eventCalendar-showAsWeek { - display: block; + display: block; } .eventCalendar-daysList li { - display: table-cell; + display: table-cell; } .eventCalendar-dayWithEvents { - background: rgba(0, 0, 0, 0.15); + background: rgba(0, 0, 0, 0.15); } .eventCalendar-current { - background: rgba(0, 0, 0, 0.35); + background: rgba(0, 0, 0, 0.35); } .eventCalendar-showAsWeek li { - display: block; - float: left; - width: 14.28%; - height: 20px; + display: block; + float: left; + width: 14.28%; + height: 20px; } .eventCalendar-daysList a { - padding: 0; - display: block; - text-align: center; - font-size: 8px; - min-width: 7px; + padding: 0; + display: block; + text-align: center; + font-size: 8px; + min-width: 7px; } .eventCalendar-loading { - display: block; - min-width: 100px; - height: 40px; - line-height: 40px; + display: block; + min-width: 100px; + height: 40px; + line-height: 40px; } .eventCalendar-list { - position: relative; - z-index: 1; + position: relative; + z-index: 1; } .eventCalendar-oldEventList { - z-index: 2; + z-index: 2; } .eventCalendar-subtitle { - padding-left: 5px; - font-weight: bold; - font-size: 120%; + padding-left: 5px; + font-weight: bold; + font-size: 120%; } -/* end of core CSS */ \ No newline at end of file + +/* заголовок */ +.eventCalendar-currentTitle { + background-color: #138DA5 !important; + border: none !important; + padding: 10px 0 !important; + margin: 0 6px; + padding-top: 5px; +} + +.eventCalendar-monthTitle { + display: block; + text-align: center; + width: 100%; + margin: 0 auto; + font-size: 1.1rem !important; + text-transform: uppercase; + letter-spacing: 1px; +} + +.eventCalendar-day-header { + background: #f4f4f4 !important; + border-bottom: 1px solid #eee !important; + color: #666 !important; + text-transform: uppercase !important; + font-size: 10px; + padding: 10px 0 !important; +} + +/* Список событий */ +.eventCalendar-list li { + border-bottom: 1px solid #f0f0f0 !important; + padding: 15px !important; +} + +.eventCalendar-eventTitle { + color: #007bff !important; + font-size: 16px !important; + font-weight: 500 !important; +} + +/* Скрытый блок описания */ +.eventCalendar-eventDesc { + padding: 15px !important; + background-color: #f9f9f9 !important; + border-left: 4px solid #138DA5 !important; + margin-top: 10px !important; +} + +/* Кнопка */ +.bt { + background: #138DA5 !important; + border: none !important; + border-radius: 2px !important; + box-shadow: none !important; + padding: 8px 20px !important; + text-transform: uppercase; + font-size: 12px !important; +} + +/* Стрелки навигации */ +.eventCalendar-prev { + left: 20px !important; + margin-top: 10px !important; +} + +.eventCalendar-next { + right: 20px !important; + margin-top: 10px !important; +} + +/* Сообщение об отсутствии событий */ +.eventCalendar-list .eventCalendar-noEvents { + display: flex; + align-items: center; + justify-content: center; + min-height: 80px; + padding: 20px !important; + text-align: center; + background-color: #ccc !important; + color: #fff !important; + border-radius: 4px; + margin: 10px !important; +} + +.eventCalendar-noEvents p { + margin: 0 !important; + font-size: 1.1rem; +} + +/* Выравнивание иконок и текста */ +.uca-date-icon { + display: flex !important; + align-items: center !important; + gap: 10px; + margin-bottom: 8px; +} + +.bg-blue_calendar, .bg-blue_clock, .bg-blue_map { + float: none !important; + display: flex !important; +} + +.uca-date-icon::before { + content: ""; + display: inline-block; + width: 20px; + height: 20px; + background-repeat: no-repeat; + background-size: contain; + flex-shrink: 0; +} + +.uca-date-txt { + line-height: 1 !important; + display: inline-block !important; + vertical-align: middle !important; +} + +/* Логика для текущего числа */ +.eventCalendar-wrap .eventCalendar-daysList li.today { + background: #1a94a6 !important; + color: #fff !important; +} +.eventCalendar-wrap .eventCalendar-daysList li.today a { + color: #fff !important; +} + +.eventCalendar-wrap .eventCalendar-daysList li.eventCalendar-day-header.today-header { + color: #1a94a6 !important; + font-weight: bold; +} + +.eventCalendar-wrap .eventCalendar-daysList li.eventCalendar-day.today { + background: #1a94a6 !important; + background-color: #1a94a6 !important; + background-image: none !important; +} + +.eventCalendar-wrap .eventCalendar-daysList li.eventCalendar-day.today a { + background: #1a94a6 !important; + background-color: #1a94a6 !important; + color: #ffffff !important; + display: block; +} + +.eventCalendar-wrap .eventCalendar-daysList li.today:before, +.eventCalendar-wrap .eventCalendar-daysList li.today:after { + display: none !important; +} + +/* Прошедшие события */ +html body .eventCalendar-wrap .eventCalendar-daysList li.eventCalendar-day.eventCalendar-dayWithEvents.past-event { + background: #d1d1d1 !important; + background-color: #d1d1d1 !important; + background-image: none !important; + border-color: #bcbcbc !important; +} + +html body .eventCalendar-wrap .eventCalendar-daysList li.eventCalendar-day.eventCalendar-dayWithEvents.past-event a { + background: #d1d1d1 !important; + background-color: #d1d1d1 !important; + color: #777 !important; +} + +.eventCalendar-wrap .eventCalendar-daysList li.past-event:before, +.eventCalendar-wrap .eventCalendar-daysList li.past-event:after { + display: none !important; +} + +/* Будущие события */ +div.eventCalendar-wrap ul.eventCalendar-daysList li.eventCalendar-day.eventCalendar-dayWithEvents.future-event, +div.eventCalendar-wrap ul.eventCalendar-daysList li.eventCalendar-day.eventCalendar-dayWithEvents.future-event a { + background: #48c9b0 !important; + background-color: #48c9b0 !important; + background-image: none !important; + color: #ffffff !important; +} + +/* Cегодняшние события */ +div.eventCalendar-wrap ul.eventCalendar-daysList li.eventCalendar-day.eventCalendar-dayWithEvents.today-event, +div.eventCalendar-wrap ul.eventCalendar-daysList li.eventCalendar-day.eventCalendar-dayWithEvents.today-event a { + background: #138DA5 !important; + background-color: #138DA5 !important; + background-image: none !important; + color: #ffffff !important; +} + +/* Дополнительные отступы и навигация */ +.eventCalendar-wrap .eventCalendar-arrow { + margin: 0 10px; +} + +/* Оформление иконок в описании */ +.eventCalendar-eventDesc .uca-date-row { + display: flex; + align-items: center; + margin-bottom: 8px; + font-size: 14px; + color: #444; +} + +.eventCalendar-eventDesc .uca-date-row i { + color: #1a94a6 !important; + margin-right: 10px; + font-size: 16px; + display: flex; +} + +.eventCalendar-eventDesc .uca-date-row span { + line-height: 1.2; +} + +/* Дата и бейдж */ +.eventCalendar-wrap time { + display: flex; + align-items: center; + flex-wrap: wrap; + margin-bottom: 8px; + gap: 10px; +} + +.eventCalendar-wrap time em { + font-size: 0.95rem !important; + color: #666 !important; + font-style: normal; + line-height: 1; +} + +.eventCalendar-wrap time small { + background-color: #48c9b0 !important; + color: #fff !important; + font-size: 0.85rem !important; + padding: 3px 10px !important; + border-radius: 4px !important; + font-weight: 500; + line-height: 1; + margin: 0 !important; +} + +/* Заголовок в списке */ +.eventCalendar-wrap .eventCalendar-eventTitle { + font-size: 1.25rem !important; + color: #191919 !important; + font-weight: 600; + margin-top: 5px; +} + +.eventCalendar-wrap .eventCalendar-eventTitle:hover { + color: #1a94a6 !important; + text-decoration: none !important; +} \ No newline at end of file diff --git a/info.php b/info.php index d6ca988..3af4531 100644 --- a/info.php +++ b/info.php @@ -4,9 +4,9 @@ $module = array( 'ModuleSysName' => 'unicalendar', - 'ModuleVersion' => '1.26.8', + 'ModuleVersion' => '3.32', 'ModuleAutor' => 'Repellent', - 'ModuleCopyright' => '© 2007-' . date('Y') . ' AVE.cms', + 'ModuleCopyright' => '© 2007-' . date('Y') . ' Ave4cms.ru', 'ModuleStatus' => 1, 'ModuleIsFunction' => 1, 'ModuleTemplate' => 0, diff --git a/js/jquery.eventCalendar.js b/js/jquery.eventCalendar.js index e0a5058..1f84252 100644 --- a/js/jquery.eventCalendar.js +++ b/js/jquery.eventCalendar.js @@ -1,15 +1,22 @@ /* = jquery.eventCalendar.js - version: 0.7 - date: 13-08-2015 - author: - Jaime Fernandez (@vissit) - company: - Paradigma Tecnologico (@paradigmate) - url: - http://www.vissit.com/projects/eventCalendar/ + version: 0.7.1 (Customized) + original date: 13-08-2015 + last update: 19-03-2026 + + original author: Jaime Fernandez (@vissit) + company: Paradigma Tecnologico (@paradigmate) + url: http://www.vissit.com/projects/eventCalendar/ + + Changes (2026) by Alexander Salnikov (aka Repellent): + - Added past/today/future event status logic + - Integrated Bootstrap Icons (bi-calendar3, bi-clock, bi-geo-alt) + - Improved layout and CSS specificity for modern browsers (PHP 8.4 compatibility) + - Fixed image placement within event descriptions */ ;(function( $ ) { + var initEventCalendarPlugin = function( $ ) { + $.fn.eventCalendar = function(options){ var calendar = this; @@ -226,26 +233,33 @@ if (eventsOpts.showDayAsWeeks) { $eventsCalendarDaysList.addClass('eventCalendar-showAsWeek'); - // show day name in top of calendar - if (eventsOpts.showDayNameInCalendar) { - $eventsCalendarDaysList.addClass('eventCalendar-showDayNames'); + // show day name in top of calendar + if (eventsOpts.showDayNameInCalendar) { + $eventsCalendarDaysList.addClass('eventCalendar-showDayNames'); - i = 0; - // if week start on monday - if (eventsOpts.startWeekOnMonday) { - i = 1; - } + // --- НОВЫЙ КОД ТУТ --- + var todayDate = new Date(); + var currentDayNum = todayDate.getDay(); // 0 (вс) - 6 (сб) + // --- КОНЕЦ НОВОГО КОДА --- - for (; i < 7; i++) { - daysList.push('
  • '+moment()._locale._weekdaysShort[i]+'
  • '); + i = 0; + if (eventsOpts.startWeekOnMonday) { + i = 1; + } - if (i === 6 && eventsOpts.startWeekOnMonday) { - // print sunday header - daysList.push('
  • '+moment()._locale._weekdaysShort[0]+'
  • '); - } + for (; i < 7; i++) { + // Проверяем, совпадает ли индекс цикла с текущим днем недели + var activeHeaderClass = (i === currentDayNum) ? 'today-header' : ''; + + daysList.push('
  • '+moment()._locale._weekdaysShort[i]+'
  • '); - } - } + if (i === 6 && eventsOpts.startWeekOnMonday) { + // Для воскресенья отдельная проверка, так как оно в конце + var sunActive = (currentDayNum === 0) ? 'today-header' : ''; + daysList.push('
  • '+moment()._locale._weekdaysShort[0]+'
  • '); + } + } + } dt=new Date(year, month, 01); var weekDay = dt.getDay(); // day of the week where month starts @@ -399,6 +413,23 @@ } + // --- НАЧАЛО ВСТАВКИ: ЛОГИКА ПРОШЕДШИХ СОБЫТИЙ --- + var today = new Date(); + today.setHours(0,0,0,0); + + var checkDate = new Date(eventYear, eventMonth, eventDay); + checkDate.setHours(0,0,0,0); + + var statusClass = ''; + if (checkDate < today) { + statusClass = 'past-event'; // Прошедшее + } else if (checkDate.getTime() === today.getTime()) { + statusClass = 'today-event'; // Сегодня + } else { + statusClass = 'future-event'; // Будущее + } + // --- КОНЕЦ ВСТАВКИ --- + if (parseInt(eventMinute) <= 9) { eventMinute = "0" + parseInt(eventMinute); } @@ -431,9 +462,8 @@ if ((month === false || month == eventMonth) && (day === '' || day == eventDay) && (year === '' || year == eventYear) ) { // if initial load then load only future events if (month === false && eventDate < new Date()) { - } else { + } else { moment.locale(eventsOpts.locales.locale); - //eventStringDate = eventDay + "/" + eventMonthToShow + "/" + eventYear; eventStringDate = moment(eventDate).format(eventsOpts.dateFormat); var eventTitle; @@ -442,7 +472,33 @@ } else { eventTitle = ''+event.title+''; } - events.push('
  • '+ eventImage + eventTitle +'
    ' + '
    ' + eventStringDate + '
    '+eventHour+':'+eventMinute+'
    '+eventLocation + eventDescription + '
  • '); + + // Формируем новые блоки с Bootstrap иконками + var dateRow = '
    ' + eventStringDate + '
    '; + var timeRow = '
    ' + eventHour + ':' + eventMinute + '
    '; + + // Локация (если она есть) + var locRow = (event.location != '') ? '
    ' + event.location + '
    ' : ''; + + // Собираем всё в итоговый список (здесь можно править дизайн вывода собтий) + var eventLink = ''; + if (event.url) { + eventLink = '' + eventsOpts.locales.txt_GoToEventUrl + ''; + } + + events.push('
  • ' + + '' + + eventTitle + + '
    ' + + eventImage + + dateRow + + timeRow + + locRow + + eventDescription + + eventLink + // кнопка с классом "bt" "ПОДРОБНЕЕ" + '
    ' + + '
  • '); + i++; } } @@ -450,7 +506,7 @@ // add mark in the dayList to the days with events if (eventYear == flags.wrap.attr('data-current-year') && eventMonth == flags.wrap.attr('data-current-month')) { - flags.wrap.find('.eventCalendar-currentMonth .eventCalendar-daysList #dayList_' + parseInt(eventDay)).addClass('eventCalendar-dayWithEvents'); + flags.wrap.find('.eventCalendar-currentMonth .eventCalendar-daysList #dayList_' + parseInt(eventDay)).addClass('eventCalendar-dayWithEvents ' + statusClass); } }); @@ -510,7 +566,17 @@ flags.wrap.find('.eventCalendar-list-wrap').width(flags.wrap.width() + 'px'); } + }; -})( jQuery ); + function checkAndInit() { + if (window.jQuery) { + initEventCalendarPlugin(window.jQuery); + } else { + setTimeout(checkAndInit, 50); // Ждем 50мс, если jQuery еще нет + } + } + checkAndInit(); + +})(); diff --git a/lang/ru.txt b/lang/ru.txt index dd3c9d3..893f443 100644 --- a/lang/ru.txt +++ b/lang/ru.txt @@ -69,7 +69,7 @@ UCA_ALERT_RELEV_BAD_SE = ",
    доку UCA_ALERT_RELEV_BAD_SF = "  не найден(ы) !" UCA_SEL_FIELD_BTN = "Выбрать" UCA_SEL_FIELD_DATA_INF = "Выбор полей для создания тизера события" -UCA_SEL_FIELD_DATA_TTL = "Название события" +UCA_SEL_FIELD_DATA_TTL = "Название события или выберите текстовое поле\'> " UCA_SEL_FIELD_TTL = "Аналогично названию документа (тег < title >)" UCA_SEL_FIELD_H_IMG = "Изображение Изображение (Одиночное)\'> " UCA_SEL_FIELD_IMG = "Выбрать поле" @@ -77,6 +77,9 @@ UCA_SEL_FIELD_DATA_DSC = "Опи UCA_SEL_FIELD_DSC = "Выбрать поле" UCA_SEL_FIELD_DATA_PLW = "Место события Все HTML теги (если они присутствуют в поле) будут вырезаны (естественно только в календаре).
    Eсли вы не планируете указывать место, оставьте это значение пустым (не выбирайте никакого поля).\'> 
    " UCA_SEL_FIELD_PLC = "Выбрать поле" -UCA_SEL_FIELD_DATA_STR = "Начало события" -UCA_SEL_FIELD_DATA_END = "Завершение события" + +UCA_SEL_FIELD_DATA_STR = "Начало события Дата (Unix Timestamp)\'> " + +UCA_SEL_FIELD_DATA_END = "Завершение события Дата (Unix Timestamp)\'> " UCA_SEL_FIELD_SDOC = "Задано документом" +UCA_SEL_FIELD_TTL_DEFAULT = "Аналогично названию документа (тег < title >)" \ No newline at end of file diff --git a/sql.php b/sql.php index facd4c6..2da8009 100644 --- a/sql.php +++ b/sql.php @@ -1,90 +1,67 @@ \ No newline at end of file diff --git a/templates/admin_unicalendar_edit.tpl b/templates/admin_unicalendar_edit.tpl index e932024..da5b115 100644 --- a/templates/admin_unicalendar_edit.tpl +++ b/templates/admin_unicalendar_edit.tpl @@ -2,45 +2,45 @@
      -
    • {#UCA_EDIT_INFO#}
    • -
    +
  • {#UCA_EDIT_INFO#}
  • +
    -{foreach from=$unicalendars item=unicalendars} +
    {#UCA_EDIT_CALEND#} - {$unicalendars.uca_title|escape}
      -
    • {#UCA_SET_CALENDAR#}
    • -
    • {#UCA_ID#}  {$unicalendars.id}      {#UCA_EVENTS#} =   {if $unicalendars.uca_events == 1}{#UCA_LIST_ALLDOC_RUB#}   {$unicalendars.uca_rubric_title|escape}{elseif $unicalendars.uca_events == 2}{#UCA_LIST_SELDOC_RUB#}   {$unicalendars.uca_rubric_title|escape}{/if}
    • -
    +
  • {#UCA_SET_CALENDAR#}
  • +
  • {#UCA_ID#}  {$unicalendars.id}      {#UCA_EVENTS#} =   {if $unicalendars.uca_events == 1}{#UCA_LIST_ALLDOC_RUB#}   {$unicalendars.uca_rubric_title|escape}{elseif $unicalendars.uca_events == 2}{#UCA_LIST_SELDOC_RUB#}   {$unicalendars.uca_rubric_title|escape}{/if}
  • +
    {if $unicalendars.uca_events == 1} - - - - - - - - - +
    {#UCA_TITLE#} - -
    + + + + + + + + - - - + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - + + - -
    {#UCA_TITLE#} + +
    {#UCA_PUBLIC_DATE#} @@ -59,74 +59,74 @@
    {#UCA_OPEN_LIKS#} - +
    {#UCA_OPEN_LIKS#} + - + - -
    {#UCA_WEEK_START#} - - - - - -
    {#UCA_SCROLL_BAR#} - - - - - -
    {#UCA_DESCRIPTION#} - - - - - -
    {#UCA_WEEK_START#} + + + + + +
    {#UCA_SCROLL_BAR#} + + + + + +
    {#UCA_DESCRIPTION#} + + + + + +
    {#UCA_EVENTS_LIMIT#}
    {#UCA_EVENTS#}
    - - +
    {#UCA_EVENTS#}
    + + {#UCA_LIST_ALLDOC_RUB#} {$unicalendars.uca_rubric_title|escape}      {#UCA_CHANGE_RUBRIC#} -
    + + +
    - - + - + +
    -
    - {#UCA_SAVE_EDIT#}     +
    + -
    {/if} @@ -272,10 +272,10 @@ {/if} -{/foreach} +