2002-12-15 17:01:06 UTC
Совершенству нет предела, поэтому представляю очередную модификацию календаря с использованием XML. Здесь я не буду расписывать подробно о всех аспектах его работы, — об этом вы можете прочитать в предыдущем примере, а расскажу лишь об отличиях.
Предыдущая версия календаря имела один серьёзный изъян, — в конструкторе определялся хэш $days_of_files
хранящий информацию о днях месяца, за которые были какие либо публикации (новости например). Определение этого хэша привязано к конкретной структуре БД с которой работает сайт и при её изменении придется переделывать конструктор, также при использовании этого кода в другом проекте придется опять переделывать определение хэша, — это плохо. В связи с этим было решено вынести определение данного хэша из класса и передавать его в качестве параметра конструктору — это позволить использовать код без изменения в различных проектах.
Кроме того, я решил оказаться от использования языка по-умолчанию в коде класса и сделал базовый класс календаря абстрактным, т.е. от которого нельзя создавать экземпляры, а для конкретного языка создается класс, производный от базового, в котором определяется один метод, к котором определены специфичные для каждого языка параметры.
Теперь подробнее о параметрах конструктора. Первый из них это $date
— это хэш, в котором передаются параметры дня, месяца и года календаря:
$date[ $.day(2) $.month(10) $.year(2002) ]
Следует отметить, что значение месяца и года, всегда должны быть осмысленными, ненулевыми значениями (например по-умолчанию принять их равными текущим значениям месяца и года), а значение дня может быть нулем (если не нужно показывать новости за какой-либо день).
Второй параметр — это вышеупомянутый хэш $days_of_files
, имеющий следующий вид:
$days_of_files[ $.1[число > 0] $.2[число > 0] $.5[число > 0] ... ]
тут критичны лишь значения ключей хэша, которые должны быть числами, днями месяца, за которые были публикации.
Далее код базового класса:
####### # абстрактный класс для формирования XML кода календаря (метод ^xml[]) # Описание атрибутов: # in - показывает что этот день является сегодняшним днём # f - наличие материалов в этот день # hit - этот день выбран пользователем -> на него не ставить ссылку и выбирать # данные только за этот день @CLASS calendar ####### @init[date;days_of_files] # получение текущей даты $date_now[^date::now[]] # Инициал. хэш показывающий какой период времени передан # при создании экземпляра класса $self.date[$date] # декларация специфических переменных языка # название месяца $month[] # хэш названий всех месяцев и дней недели $calendar_locale[^hash::create[]] # календарь на месяц $calendar_month[^table::create{}] # вызов метода для создания специфических для языка переменных # в классе производном от этого и определить только один # метод @i18n[] ^i18n[] # определение переменных месяца и года для пред. месяца календаря $calendar_month_prev[^date::create($date.year;$date.month)] ^calendar_month_prev.roll[month](-1) $prev_m($calendar_month_prev.month) $prev_y($calendar_month_prev.year) # определение переменных месяца и года для след. месяца календаря $calendar_month_next[^date::create($date.year;$date.month)] ^calendar_month_next.roll[month](+1) $next_m($calendar_month_next.month) $next_y($calendar_month_next.year) # the hash of publications(files) $self.days_of_files[$days_of_files] ####### @xml[] $result[ <month> ^month_year[] ^weekdays[] ^week[] </month> ] ####### # формирование тега для года и месяца @month_year[][hit] ^if( $date.day || ( $date_now.month == $date.month && $date_now.year == $date.year && $date.day ) ){ $hit[] }{ $hit[hit="1"] } <month_year month="$date.month" month_title="$month" next_month="$next_m" prev_month="$prev_m" year="$date.year" next_year="$next_y" prev_year="$prev_y" $hit /> ####### # тег названий дней недели @weekdays[] <weekdays> ^for[i](0;6){ <day title="$calendar_locale.day_names.$i"/> } </weekdays> ####### # формирование тегов для каждой недели месяца # day - день месяца, может быть нулем, если начало/конец # первой/последней недели месяца не приходятся на понедельник/воскресенье @week[][day;in;f;hit] ^calendar_month.menu{ <week> ^for[i](0;6){ $day($calendar_month.$i) # формирование атрибута текущего дня ^if( $date_now.day == $day && $date_now.month == $date.month && $date_now.year == $date.year ){ $in[in="1"] }{ $in[] } # формирование атрибута нахождения в данном дне ^if($day == $date.day){ $hit[hit="1"] }{ $hit[] } # формирование атрибута наличия материалов за день ^if($days_of_files.$day){ $f[f="1"] }{ $f[] } <day d="$day" $in $f $hit/> } </week> }
Код класса для русского языка:
####### # Вызывать так: формировать объект конструктором init # $object[^calendar_ru::init[$date;$days_of_files]] # далее получаем XML календаря ^object.xml[] @CLASS calendar_ru ####### @USE calendar.p ####### @BASE calendar ####### @init[date;days_of_files] ^BASE:init[$date;$days_of_files] ####### # Метод, в котором определяются специфические для разных языков # параметры календаря @i18n[][m;y] # the hash of local calendar (month and day names) $calendar_locale[ $.month_names[ $.1[Январь] $.2[Февраль] $.3[Март] $.4[Апрель] $.5[Май] $.6[Июнь] $.7[Июль] $.8[Август] $.9[Сентябрь] $.10[Октябрь] $.11[Ноябрь] $.12[Декабрь] ] $.day_names[ $.0[Пн] $.1[Вт] $.2[Ср] $.3[Чт] $.4[Пт] $.5[Сб] $.6[Вс] ] ] $m($date.month) $y($date.year) $month[$calendar_locale.month_names.$m] $calendar_month[^date:calendar[rus]($y;$m)]
Код класса для для английского языка:
####### # Вызывать так: формировать объект конструктором init # $object[^calendar_en::init[$date;$days_of_files]] # далее получаем XML календаря ^object.xml[] @CLASS calendar_en ####### @USE calendar.p ####### @BASE calendar ####### @init[date;days_of_files] ^BASE:init[$date;$days_of_files] ####### # Метод, в котором определяются специфические для разных языков # параметры календаря @i18n[][m;y] # the hash of local calendar (month and day names) $calendar_locale[ $.month_names[ $.1[January] $.2[February] $.3[March] $.4[April] $.5[May] $.6[June] $.7[July] $.8[August] $.9[September] $.10[October] $.11[November] $.12[December] ] $.day_names[ $.0[Su] $.1[Mo] $.2[Tu] $.3[We] $.4[Th] $.5[Fr] $.6[Sa] ] ] $m($date.month) $y($date.year) $month[$calendar_locale.month_names.$m] $calendar_month[^date:calendar[eng]($y;$m)]
Пример стилевых таблиц для XSLT преобразований смотрите в предыдущем примере или в архиве с этим примером.