In my coworking space we are using ownCloud calendar to keep track of the availability of our conference room which we are also renting. However, we want also to be able to show publicly the room availability without disclosing personal information to the public. Even more limiting, since we use Jimdo to host our website we can’t execute any server-side code.

Currently we have a calendar shared using a service account to all administrative users which is used to track availability. Basically looking as following:

Reservations in ownCloud calendar

Unfortunately, the default ownCloud calendar is not able to share calendar publicly, there is since a longer time a Pull Request to add this functionality but unfortunately it is unlikely that this one is going to be merged anytime soon. Also we need to be able to embed the calendar easily on other web pages.

The first solution that came to my mind is Google Calendar since it allows easily embedding calendars within web pages. However, we wanted to keep the data under our own control and also leverage our existing tools.

Luckily ownCloud is providing CalDAV access to calendars and also iCal export due to the super awesome sabre libraries that we use. Sabre offers also classes to read objects such as iCal files. This means that to remove sensitive information from an calendar and get a new iCal file only a few lines of code are required:

<?php
// Use "composer require sabre/vobject" to get the required libraries
require_once('./vendor/autoload.php');

use Sabre\VObject;

// Configure your data
$remoteHost = 'https://cloud.smartworksg.ch';
$calendarName = 'sitzungszimmer';
$username = 'service';
$password = 'XXXXXX';

// Get ownCloud calendar
$curl = curl_init($remoteHost . '/remote.php/caldav/calendars/'.$username.'/'.$calendarName.'?export');
curl_setopt($curl, CURLOPT_USERPWD, $username . ":" . $password);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_VERBOSE, true);
$ics = curl_exec($curl);
curl_close($curl);

// Parse calendar file
$calendar = VObject\Reader::read($ics);

// Replace all SUMMARY fields with a value of "Reserved"
foreach($calendar->children() as $children) {
    if($children instanceof VObject\Component\VEvent) {
        $children->SUMMARY = 'Reserved';
    }
}

// Put the resulting ICS to /var/www/public.ics
file_put_contents('/var/www/public.ics', $calendar->serialize());

This file can then get easily added to a cronjob and using Google’s calendar “Subscribe to public calendars” functionality the sanitized calendar can get shared to the public and embedded in web pages:

Reservations displayed publicly in Google Calendar