Добрый день!
С отображением вкладок календаря, экспортом в ICal—вроде проблем не было.
Настал момент натягивать дизайн. Тут задался задачей: «Как сделать так, чтобы название события вело на страницу детального просмотра?»
Вернулся в код компонента и понял, что никакой догмой разработки на компонентах и их шаблонах — тут и не пахнет.
Весь рендеринг кода зашит в CCalendar, а именно в CCalendarSceleton::Build(array(“Куча недокументированных параметров…”));
Кому интересно — /bitrix/modules/calendar/classes/general/calendar_sceleton.php:5
Пришлось наследовать и переопределять методы под решение данной задачи...
А ведь, с одной стороны для решения задачи не хватало то:
Стояла задача создать страничку с календарём мероприятий*,правда с функциональностью почти как у GoogleCalendar.
Примечание*1 мероприятие – элемент ИБ, имеющий конкретную дату/время проведения.
Что требовалось от функционала:
- Загрузка событий в календарь из ИБ.
- Отображение двух вкладок: Неделя, Месяц, с возможностью перехода по неделям/месяцам вперед и назад во времени.
- В один календарный день может проводиться несколько мероприятий. Если мероприятие длится более 1го дня, то оно протягивается по календарной сетке на к-во дней, равное своей длительности.
- Экспорт в ICal, MSOutLook.
- Название мероприятия должно являться ссылкой и вести на страницу детального просмотра.
Выбрал для решения этой задачи календарь событий 2.0. Создал в модуле календарь тип событий, бросил на страницу компонент bitrix: calendar.grid. Залез в код компонента и понял, что для решения моей задачи придется долго и нудно ковыряться в ядре модуля календарь. Начал распиливать этот недокументированный «чёрный ящик», а он же работает только с событиями.
Написал метод для превращения элементов ИБ в события календаря.
Выглядит он примерно так:| Код |
|---|
public static function LoadCalendarEventsFromIB($iblockID, $calendarType, $calendarSectionID = false, $arAddFilter = false, $arDecoration = false) {
//если не задан календарь, то создаем новый
if (intval($calendarSectionID) > 0) {
$bAutoCreateSection = false;
} else {
$bAutoCreateSection = true;
}
if (CModule::IncludeModule("iblock" && CModule::IncludeModule("calendar") {
$arFilter = array("IBLOCK_ID" = > $iblockID, "ACTIVE" = > "Y", "ACTIVE_DATE" = > "Y", ">DATE_ACTIVE_TO" = > date("Y-m-d");
//если есть дополнительный фильтр, объединим его с уже сформированным
if (is_array($arAddFilter) && (count($arAddFilter) > 1)) {
$arFilter = array_merge($arFilter, $arAddFilter);
}
$arSelect = array("ID", "NAME", "DATE_ACTIVE_FROM", "ACTIVE_DATE", "DATE_ACTIVE_TO";
//массив для записи в b_calendar_...
$arEventsToDb = array();
//выбираем мероприятия
$dbRes = CIBlockElement::GetList(array(), $arFilter, false, false, $arSelect);
if (intval($dbRes - > SelectedRowsCount()) > 0) {
global $USER;
//массив для успешно записанных в БД событий
$arSuccessfullyAdded = array();
//если необходимо записывать в уже существующий календарь
//проверим — нет ли в нем ещё этих мероприятий
if (!$bAutoCreateSection) {
//выберем уже существующие события в данном календаре, из b_calendar..
$arExistEvents = CCalendarEvent::GetList(
array('arFilter' = > array("SECTIONS" = > array($calendarSectionID)), 'parseRecursion' = > false));
if (count($arExistEvents) > 0) {
$arExistEventsID = array();
foreach($arExistEvents as $oneExistEvent) {
$arExistEventsID[] = intval($oneExistEvent['LOCATION']
}
}
}
while ($arRes = $dbRes - > GetNext(true, false)) {
//если в b_calendar_... еще нет такого мероприятия
if (!in_array(intval($arRes['ID'], $arExistEventsID)) {
$arEventsToDb[$arRes['ID']]['DT_FROM'] = $arRes['DATE_ACTIVE_FROM'];
$arEventsToDb[$arRes['ID']]['DT_TO'] = $arRes['DATE_ACTIVE_TO'];
$arEventsToDb[$arRes['ID']]['NAME'] = $arRes['NAME'];
$arEventsToDb[$arRes['ID']]['OWNER_ID'] = $USER - > GetID();
$arEventsToDb[$arRes['ID']]['DESCRIPTION'] = $arRes['NAME'];
$arEventsToDb[$arRes['ID']]['COLOR'] = ($arDecoration['COLOR'] ? $arDecoration['COLOR'] : "#FFFFFF";
$arEventsToDb[$arRes['ID']]['TEXT_COLOR'] = ($arDecoration['TEXT_COLOR'] ? $arDecoration['TEXT_COLOR'] : "#00679A";
$arEventsToDb[$arRes['ID']]['SECTIONS'] = array($calendarSectionID);
$arEventsToDb[$arRes['ID']]['LOCATION'] = $arRes['ID']; //пишем ID мероприятия
}
}
//если есть что записывать в b_calendar_...
if (count($arEventsToDb) > 0) {
//создаем экземпляр объекта
$obCalendar = new CCalenar();
foreach($arEventsToDb as $elID = > $oneEvent) {
$toDB = array("arFields" = > array_merge(array("CAL_TYPE" = > $calendarType), $oneEvent), "autoDetectSection" = > true, "autoCreateSection" = > $bAutoCreateSection);
//пишем событие в БД
$eventID = $obCalendar - > SaveEvent($toDB);
if ($eventID > 0) {
$arSuccessfullyAdded[$elID] = $eventID;
} else {
//произошла ошибка при записи события в БД
return false;
}
}
} else {
//записывать нечего
return false;
}
} else {
//выборка не содержит мероприятий по заданному фильтру
return false;
}
}
return true;
}
//end of LoadCalendarEventsFromIB
|
С отображением вкладок календаря, экспортом в ICal—вроде проблем не было.
Настал момент натягивать дизайн. Тут задался задачей: «Как сделать так, чтобы название события вело на страницу детального просмотра?»
Вернулся в код компонента и понял, что никакой догмой разработки на компонентах и их шаблонах — тут и не пахнет.
Весь рендеринг кода зашит в CCalendar, а именно в CCalendarSceleton::Build(array(“Куча недокументированных параметров…”));Кому интересно — /bitrix/modules/calendar/classes/general/calendar_sceleton.php:5
Пришлось наследовать и переопределять методы под решение данной задачи...
А ведь, с одной стороны для решения задачи не хватало то:
- Компонента «Календарь событий» с возможностью загрузки событиями из ИБ и функциональностью «Календарь событий 2.0».
- Шаблона компонента(с CSS и JS-ом как раньше, а не зашитым в ядро).
- Это новый стиль разработки фреймворка? Когда представление зашивается в ядро и интегратору приходится наследовать методы.
- Имхо стоит подружить календарь с ИБ, как основным хранилищем структурированных данных. Т.к. там уже есть ряд полей вроде даты-начала, даты окончания, на которых в 90% случаев интеграторы делают подобные вещи.
- Не полетит ли функционал, написанный на ООП после обновления модуля календарь, на 12й версии БУС?
Изменено: Месилов Максим - 20.08.2012 17:19:43
