Найти в Дзене
Программист - турист

Как создать файл календаря (ics) средствами PHP

Довольно нестандартная задача возникла впервые за 5 лет разработки. Обычно подобное решается внедрением google календаря или аналогичными средствами. Но тут другое дело, заказчик пожелал возможность создания мероприятий на сайте, с последующим выводом и генерацию ICS файла, чтобы пользователи могли скачать его. Подобную задачу можно решить как минимум двумя способами: генерация и загрузка файла после создания мероприятия или динамическая генерация без создания файла. Я расскажу про второй вариант. Всё будет делаться на примере создания мероприятия Готовим список значений Представим, что у нас реализован динамический вывод необходимых нам значений: дата начала, дата окончания, название, описание, место, ссылка на сайт с информацией о мероприятии. Готовим файл генерации ics Создаем в корне сайта файл ics.php
Создадим обертку для php кода: <?php ?>
Поместим внутрь код для вывода приходящих данных request: var_dump($_REQUEST); Передаем список значений На странице просмотра мероприятия д
Оглавление

Довольно нестандартная задача возникла впервые за 5 лет разработки. Обычно подобное решается внедрением google календаря или аналогичными средствами. Но тут другое дело, заказчик пожелал возможность создания мероприятий на сайте, с последующим выводом и генерацию ICS файла, чтобы пользователи могли скачать его.
Подобную задачу можно решить как минимум двумя способами: генерация и загрузка файла после создания мероприятия или динамическая генерация без создания файла. Я расскажу про второй вариант.
Всё будет делаться на примере создания мероприятия

Готовим список значений

Представим, что у нас реализован динамический вывод необходимых нам значений: дата начала, дата окончания, название, описание, место, ссылка на сайт с информацией о мероприятии.

Готовим файл генерации ics

Создаем в корне сайта файл ics.php
Создадим обертку для php кода:
<?php ?>
Поместим внутрь код для вывода приходящих данных request: var_dump($_REQUEST);

Передаем список значений

На странице просмотра мероприятия добавляем ссылку, следующего вида: <a href=""></a>
Представим, что нужные нам значения хранятся в переменной $arr (тип массив). В href помещаем следующий url:
/ics.php?START=$arr['dtstart']&END=$arr['dtstart']&TITLE=$arr['title']&DESCRIPTION=$arr['desc']&LOC=$arr['place']&URL=$arr['url']
Кликаем по ссылке и видим, что значения передаются, если нет, то проверяем переменную со значениями и правильность ссылки в href.

Возвращаемся к ics файлу

Теперь у нас есть значения для генерации файла.
Очищаем файл от var_dump т.к мы убедились в успешности передачи данных. Вставляем код, что ниже.

Если статья наберет 50 лайков, то напишу пояснение по каждой строчке, как и почему я это сделал

Исходный код ics.php

<?php

class ICS {
const
DT_FORMAT = 'Ymd\THis\Z';
protected $properties = array();
private $available_properties = array(
'description',
'dtend',
'dtstart',
'location',
'summary',
'url',
'SUMMARY;LANGUAGE=ru'
);
public function __construct($props) {
$this->set($props);
}
public function set($key, $val = false) {
if (is_array($key)) {
foreach ($key as $k => $v) {
$this->set($k, $v);
}
} else {
if (in_array($key, $this->available_properties)) {
$this->properties[$key] = $this->sanitize_val($val, $key);
}
}
}
public function to_string() {
$rows = $this->build_props();
return implode("\r\n", $rows);
}
private function build_props() {
// Build ICS properties - add header
$ics_props = array(
'BEGIN:VCALENDAR',
'VERSION:2.0',
'X-WR-CALNAME:'.$_GET['TITLE'],
'PRODID:-//hacksw/handcal//NONSGML v1.0//EN',
'CALSCALE:GREGORIAN',
'BEGIN:VEVENT'
);
// Build ICS properties - add header
$props = array();
foreach($this->properties as $k => $v) {
$props[strtoupper($k . ($k === 'url' ? ';VALUE=URI' : ''))] = $v;
}
// Set some default values
$props['DTSTAMP'] = $this->format_timestamp('now');
$props['UID'] = uniqid();
// Append properties
foreach ($props as $k => $v) {
$ics_props[] = "$k:$v";
}
// Build ICS properties - add footer
$ics_props[] = 'END:VEVENT';
$ics_props[] = 'END:VCALENDAR';
return $ics_props;
}
private function sanitize_val($val, $key = false) {
switch($key) {
case 'dtend':
case 'dtstamp':
case 'dtstart':
$val = $this->format_timestamp($val);
break;
default:
$val = $this->escape_string($val);
}
return $val;
}
private function format_timestamp($timestamp) {
$dt = new DateTime($timestamp);
return $dt->format(self::
DT_FORMAT);
}
private function escape_string($str) {
return preg_replace('/([\,;])/','\\\$1', $str);
}
}


header('Content-Type: text/calendar; charset=utf-8');
header('Content-Disposition: attachment; filename=invite.ics');

$ics = new ICS(array(
'dtstart' => $_GET['START'],
'dtend' => $_GET['END'],
'location' => $_GET['LOC'],
'description' => $_GET['DESCRIPTION'],
'url' => $_GET['URL'],
'SUMMARY;LANGUAGE=ru' => $_GET['TITLE']
));

echo $ics->to_string();

?>