Добрый день!
С отображением вкладок календаря, экспортом в 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