calendar 25.200.0: таймзона пользователя переехала в b_user.TIME_ZONE — и это ломающий релиз
Ломающее обновление
Удалены или изменены публичные API — прикладной код может перестать работать.
Самый «ломающий» календарный релиз батча. Часовой пояс пользователя перестал быть настройкой календаря и стал полем пользователя, из-за чего у AJAX-экшена сохранения настроек изменилась сигнатура. Плюс вырезаны два метода SynchronizationFeature. Обновление стоит смотреть внимательно, если вы что-то дописывали вокруг настроек календаря.
Таймзона: один источник правды вместо двух
Раньше имя часового пояса лежало в CUserOptions (категория calendar, ключ вида timezone{offset}), а в b_user было поле TIME_ZONE. Два хранилища одного факта — классический источник расхождений: пользователь меняет пояс в профиле, календарь продолжает считать по своему.
Теперь CCalendar::GetUserTimezoneName() берёт имя из $user['TIME_ZONE'], а чтение из CUserOptions оставлено только как fallback и помечено как deprecated compatibility. Метод CCalendar::SaveUserTimezoneName($user, $tzName = '') тоже помечен @deprecated с прямым указанием причины: «now using TIME_ZONE field in b_user». Он остался и по-прежнему пишет в CUserOptions, но опираться на него не надо.
Второе изменение того же круга: GetCurrentOffsetUTC() считает смещение через (new DateTime())->getOffset(), а не через date('Z'). Разница проявляется на переходах на летнее время и в зонах с нецелым смещением — date('Z') отдаёт смещение по текущей таймзоне PHP, а не по таймзоне вычисляемой даты.
Что сломается
CalendarAjax::saveSettingsAction()— удалён аргументstring $user_timezone_name = ''. Сигнатура стала(string $type, array $user_settings = [], array $settings = []). ВызовCCalendar::SaveUserTimezoneName()из экшена убран. Если у вас есть свой JS, который дёргает этот экшен и передаёт имя таймзоны, — параметр просто перестанет доезжать, молча.SynchronizationFeature::isOnForUser(int $userId)иsetUserId(?int $userId)удалены. ОсталсяisOn(): bool, который возвращаетtrue. Признак того, что синхронизация перестала быть пофичефлажной настройкой на пользователя — вызовыsetUserIdсняты в нескольких точках синхронизации. Наследники и вызовы этих методов упадут с фаталом.CCalendarпри пустом$typeсразу отдаётaccess_denied: проверка сталаempty($type) || !…check(ACTION_TYPE_VIEW…). Раньше пустой тип уходил дальше и мог трактоваться по умолчанию. Код, который вызывал календарные методы без явного типа, начнёт получать отказ — это не баг, а закрытая дыра в проверке прав.
Ужесточение прав на групповые календари
Тема релиза продолжается и в правах:
CreateEventHandlerдополнительно проверяетCCalendar::GetPermissionsс ключомedit, если секция групповая ($section->isGroup()).CalendarAjaxприtype=groupи заданном$ownerIdтоже требуетpermission['edit'], иначе access denied.
Для этого в Section появились isGroup() и isCompany() — сравнение type со значениями Dictionary::CALENDAR_TYPE. Мелочь, но она убирает из кода россыпь сравнений со строками.
Прочее
ICal\MailInvitation\Helper::getAttendee(?int $userId, …)—$userIdстал nullable и приnullметод сразу возвращаетnull. Меньше проверок на стороне вызывающего.Sync\Icloud\Helper::getImportLockName(int $connectionId)— имя лока импорта вынесено в метод.Section::isVirtual()читает ролиreader/freeBusyOrderизGoogle\Dictionary::ACCESS_ROLE_TO_EXTERNAL_TYPE, а не из общегоDictionary.
Схема БД не менялась: b_user.TIME_ZONE — существующее поле пользователя, новой колонки в календаре не появилось.
Что делать
- Найдите вызовы
SynchronizationFeature::isOnForUserиsetUserId— их больше нет. - Проверьте свой JS/PHP, который зовёт
calendar.api.calendarajax.saveSettingsс именем таймзоны. - Читаете таймзону пользователя — берите
b_user.TIME_ZONE, а неCUserOptions. - Проверьте места, где календарные методы вызывались без явного
$type.