diff --git a/app/SymfonyRequirements.php b/app/SymfonyRequirements.php
index cbcf1c8..28b0dcd 100644
--- a/app/SymfonyRequirements.php
+++ b/app/SymfonyRequirements.php
@@ -77,7 +77,7 @@ class Requirement
}
/**
- * Returns the help text for resolving the problem
+ * Returns the help text for resolving the problem.
*
* @return string The help text
*/
@@ -119,10 +119,10 @@ class PhpIniRequirement extends Requirement
*
* @param string $cfgName The configuration name used for ini_get()
* @param bool|callback $evaluation Either a boolean indicating whether the configuration should evaluate to true or false,
- or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement
+ * or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement
* @param bool $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false.
- This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin.
- Example: You require a config to be true but PHP later removes this config and defaults it to true internally.
+ * This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin.
+ * Example: You require a config to be true but PHP later removes this config and defaults it to true internally.
* @param string|null $testMessage The message for testing the requirement (when null and $evaluation is a boolean a default message is derived)
* @param string|null $helpHtml The help text formatted in HTML for resolving the problem (when null and $evaluation is a boolean a default help is derived)
* @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags)
@@ -221,10 +221,10 @@ class RequirementCollection implements IteratorAggregate
*
* @param string $cfgName The configuration name used for ini_get()
* @param bool|callback $evaluation Either a boolean indicating whether the configuration should evaluate to true or false,
- or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement
+ * or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement
* @param bool $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false.
- This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin.
- Example: You require a config to be true but PHP later removes this config and defaults it to true internally.
+ * This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin.
+ * Example: You require a config to be true but PHP later removes this config and defaults it to true internally.
* @param string $testMessage The message for testing the requirement (when null and $evaluation is a boolean a default message is derived)
* @param string $helpHtml The help text formatted in HTML for resolving the problem (when null and $evaluation is a boolean a default help is derived)
* @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags)
@@ -239,10 +239,10 @@ class RequirementCollection implements IteratorAggregate
*
* @param string $cfgName The configuration name used for ini_get()
* @param bool|callback $evaluation Either a boolean indicating whether the configuration should evaluate to true or false,
- or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement
+ * or a callback function receiving the configuration value as parameter to determine the fulfillment of the requirement
* @param bool $approveCfgAbsence If true the Requirement will be fulfilled even if the configuration option does not exist, i.e. ini_get() returns false.
- This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin.
- Example: You require a config to be true but PHP later removes this config and defaults it to true internally.
+ * This is helpful for abandoned configs in later PHP versions or configs of an optional extension, like Suhosin.
+ * Example: You require a config to be true but PHP later removes this config and defaults it to true internally.
* @param string $testMessage The message for testing the requirement (when null and $evaluation is a boolean a default message is derived)
* @param string $helpHtml The help text formatted in HTML for resolving the problem (when null and $evaluation is a boolean a default help is derived)
* @param string|null $helpText The help text (when null, it will be inferred from $helpHtml, i.e. stripped from HTML tags)
@@ -446,6 +446,12 @@ class SymfonyRequirements extends RequirementCollection
);
}
+ $this->addRequirement(
+ function_exists('iconv'),
+ 'iconv() must be available',
+ 'Install and enable the iconv extension.'
+ );
+
$this->addRequirement(
function_exists('json_encode'),
'json_encode() must be available',
@@ -542,11 +548,22 @@ class SymfonyRequirements extends RequirementCollection
/* optional recommendations follow */
- $this->addRecommendation(
- file_get_contents(__FILE__) === file_get_contents(__DIR__.'/../vendor/sensio/distribution-bundle/Sensio/Bundle/DistributionBundle/Resources/skeleton/app/SymfonyRequirements.php'),
- 'Requirements file should be up-to-date',
- 'Your requirements file is outdated. Run composer install and re-check your configuration.'
- );
+ if (file_exists(__DIR__.'/../vendor/composer')) {
+ require_once __DIR__.'/../vendor/autoload.php';
+
+ try {
+ $r = new ReflectionClass('Sensio\Bundle\DistributionBundle\SensioDistributionBundle');
+
+ $contents = file_get_contents(dirname($r->getFileName()).'/Resources/skeleton/app/SymfonyRequirements.php');
+ } catch (ReflectionException $e) {
+ $contents = '';
+ }
+ $this->addRecommendation(
+ file_get_contents(__FILE__) === $contents,
+ 'Requirements file should be up-to-date',
+ 'Your requirements file is outdated. Run composer install and re-check your configuration.'
+ );
+ }
$this->addRecommendation(
version_compare($installedPhpVersion, '5.3.4', '>='),
@@ -627,20 +644,20 @@ class SymfonyRequirements extends RequirementCollection
}
$this->addRecommendation(
- class_exists('Locale'),
+ extension_loaded('intl'),
'intl extension should be available',
'Install and enable the intl extension (used for validators).'
);
- if (class_exists('Collator')) {
+ if (extension_loaded('intl')) {
+ // in some WAMP server installations, new Collator() returns null
$this->addRecommendation(
null !== new Collator('fr_FR'),
'intl extension should be correctly configured',
'The intl extension does not behave properly. This problem is typical on PHP 5.3.X x64 WIN builds.'
);
- }
- if (class_exists('Locale')) {
+ // check for compatible ICU versions (only done when you have the intl extension)
if (defined('INTL_ICU_VERSION')) {
$version = INTL_ICU_VERSION;
} else {
@@ -659,6 +676,14 @@ class SymfonyRequirements extends RequirementCollection
'intl ICU version should be at least 4+',
'Upgrade your intl extension with a newer ICU version (4+).'
);
+
+ $this->addPhpIniRecommendation(
+ 'intl.error_level',
+ create_function('$cfgValue', 'return (int) $cfgValue === 0;'),
+ true,
+ 'intl.error_level should be 0 in php.ini',
+ 'Set "intl.error_level" to "0" in php.ini* to inhibit the messages when an error occurs in ICU functions.'
+ );
}
$accelerator =
diff --git a/app/check.php b/app/check.php
index 90bad4a..4283cde 100644
--- a/app/check.php
+++ b/app/check.php
@@ -6,7 +6,7 @@ $lineSize = 70;
$symfonyRequirements = new SymfonyRequirements();
$iniPath = $symfonyRequirements->getPhpIniConfigPath();
-echo_title('Symfony2 Requirements Checker');
+echo_title('Symfony Requirements Checker');
echo '> PHP is using the following php.ini file:'.PHP_EOL;
if ($iniPath) {
@@ -42,9 +42,9 @@ foreach ($symfonyRequirements->getRecommendations() as $req) {
}
if ($checkPassed) {
- echo_block('success', 'OK', 'Your system is ready to run Symfony2 projects', true);
+ echo_block('success', 'OK', 'Your system is ready to run Symfony projects');
} else {
- echo_block('error', 'ERROR', 'Your system is not ready to run Symfony2 projects', true);
+ echo_block('error', 'ERROR', 'Your system is not ready to run Symfony projects');
echo_title('Fix the following mandatory requirements', 'red');
diff --git a/composer.json b/composer.json
index f8723ff..64b368a 100755
--- a/composer.json
+++ b/composer.json
@@ -38,7 +38,7 @@
"doctrine/doctrine-migrations-bundle": "dev-master",
"jbroadway/urlify" : "~1.0",
"enko/relativedateparser" : "0.5",
- "sabre/dav" : "~2.0"
+ "sabre/vobject": "^4.1"
},
"require-dev": {
"sensio/generator-bundle": "~2.3"
diff --git a/composer.lock b/composer.lock
index 791ed4b..50245d6 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,8 +4,8 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
- "hash": "929ec448ee4bd9047bda7086b30492ef",
- "content-hash": "855e0330604c2434a4fbbc453c11e2b0",
+ "hash": "b653fb6b6230d43a6048e92f7b208ff8",
+ "content-hash": "3a7c343089ce6886d5fefe973df0b6cc",
"packages": [
{
"name": "doctrine/annotations",
@@ -1583,95 +1583,21 @@
"time": "2012-12-21 11:40:51"
},
{
- "name": "sabre/dav",
- "version": "2.1.10",
+ "name": "sabre/uri",
+ "version": "1.1.0",
"source": {
"type": "git",
- "url": "https://github.com/fruux/sabre-dav.git",
- "reference": "9f8c1939a3f66eb7170489fc48579ffd1461af62"
+ "url": "https://github.com/fruux/sabre-uri.git",
+ "reference": "9012116434d84ef6e5e37a89dfdbfbe2204a8704"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/fruux/sabre-dav/zipball/9f8c1939a3f66eb7170489fc48579ffd1461af62",
- "reference": "9f8c1939a3f66eb7170489fc48579ffd1461af62",
+ "url": "https://api.github.com/repos/fruux/sabre-uri/zipball/9012116434d84ef6e5e37a89dfdbfbe2204a8704",
+ "reference": "9012116434d84ef6e5e37a89dfdbfbe2204a8704",
"shasum": ""
},
"require": {
- "ext-ctype": "*",
- "ext-date": "*",
- "ext-dom": "*",
- "ext-iconv": "*",
- "ext-libxml": "*",
- "ext-mbstring": "*",
- "ext-pcre": "*",
- "ext-simplexml": "*",
- "ext-spl": "*",
- "php": ">=5.4.1",
- "sabre/event": "^2.0.0",
- "sabre/http": "^3.0.0",
- "sabre/vobject": "^3.3.4"
- },
- "require-dev": {
- "evert/phpdoc-md": "~0.1.0",
- "phpunit/phpunit": "~4.2",
- "squizlabs/php_codesniffer": "~1.5.3"
- },
- "suggest": {
- "ext-curl": "*",
- "ext-pdo": "*"
- },
- "bin": [
- "bin/sabredav",
- "bin/naturalselection"
- ],
- "type": "library",
- "autoload": {
- "psr-4": {
- "Sabre\\DAV\\": "lib/DAV/",
- "Sabre\\DAVACL\\": "lib/DAVACL/",
- "Sabre\\CalDAV\\": "lib/CalDAV/",
- "Sabre\\CardDAV\\": "lib/CardDAV/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Evert Pot",
- "email": "me@evertpot.com",
- "homepage": "http://evertpot.com/",
- "role": "Developer"
- }
- ],
- "description": "WebDAV Framework for PHP",
- "homepage": "http://sabre.io/",
- "keywords": [
- "CalDAV",
- "CardDAV",
- "WebDAV",
- "framework",
- "iCalendar"
- ],
- "time": "2016-03-10 20:49:48"
- },
- {
- "name": "sabre/event",
- "version": "2.0.2",
- "source": {
- "type": "git",
- "url": "https://github.com/fruux/sabre-event.git",
- "reference": "337b6f5e10ea6e0b21e22c7e5788dd3883ae73ff"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/fruux/sabre-event/zipball/337b6f5e10ea6e0b21e22c7e5788dd3883ae73ff",
- "reference": "337b6f5e10ea6e0b21e22c7e5788dd3883ae73ff",
- "shasum": ""
- },
- "require": {
- "php": ">=5.4.1"
+ "php": ">=5.4.7"
},
"require-dev": {
"phpunit/phpunit": "*",
@@ -1679,8 +1605,11 @@
},
"type": "library",
"autoload": {
+ "files": [
+ "lib/functions.php"
+ ],
"psr-4": {
- "Sabre\\Event\\": "lib/"
+ "Sabre\\Uri\\": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -1695,90 +1624,40 @@
"role": "Developer"
}
],
- "description": "sabre/event is a library for lightweight event-based programming",
- "homepage": "http://sabre.io/event/",
+ "description": "Functions for making sense out of URIs.",
+ "homepage": "http://sabre.io/uri/",
"keywords": [
- "EventEmitter",
- "events",
- "hooks",
- "plugin",
- "promise",
- "signal"
+ "rfc3986",
+ "uri",
+ "url"
],
- "time": "2015-05-19 10:24:22"
- },
- {
- "name": "sabre/http",
- "version": "3.0.5",
- "source": {
- "type": "git",
- "url": "https://github.com/fruux/sabre-http.git",
- "reference": "6b06c03376219b3d608e1f878514ec105ed1b577"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/fruux/sabre-http/zipball/6b06c03376219b3d608e1f878514ec105ed1b577",
- "reference": "6b06c03376219b3d608e1f878514ec105ed1b577",
- "shasum": ""
- },
- "require": {
- "ext-mbstring": "*",
- "php": ">=5.4",
- "sabre/event": ">=1.0.0,<3.0.0"
- },
- "require-dev": {
- "phpunit/phpunit": "~4.3",
- "squizlabs/php_codesniffer": "~1.5.3"
- },
- "suggest": {
- "ext-curl": " to make http requests with the Client class"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "Sabre\\HTTP\\": "lib/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Evert Pot",
- "email": "me@evertpot.com",
- "homepage": "http://evertpot.com/",
- "role": "Developer"
- }
- ],
- "description": "The sabre/http library provides utilities for dealing with http requests and responses. ",
- "homepage": "https://github.com/fruux/sabre-http",
- "keywords": [
- "http"
- ],
- "time": "2015-05-11 15:25:57"
+ "time": "2016-03-08 02:29:27"
},
{
"name": "sabre/vobject",
- "version": "3.5.2",
+ "version": "4.1.0",
"source": {
"type": "git",
"url": "https://github.com/fruux/sabre-vobject.git",
- "reference": "b7d6005b9f8e18bfe2b953d9847df0b3e4098441"
+ "reference": "8899c0e856b3178b17f4e9a4e85010209f32a2fa"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/fruux/sabre-vobject/zipball/b7d6005b9f8e18bfe2b953d9847df0b3e4098441",
- "reference": "b7d6005b9f8e18bfe2b953d9847df0b3e4098441",
+ "url": "https://api.github.com/repos/fruux/sabre-vobject/zipball/8899c0e856b3178b17f4e9a4e85010209f32a2fa",
+ "reference": "8899c0e856b3178b17f4e9a4e85010209f32a2fa",
"shasum": ""
},
"require": {
"ext-mbstring": "*",
- "php": ">=5.3.1"
+ "php": ">=5.5",
+ "sabre/xml": "~1.1"
},
"require-dev": {
"phpunit/phpunit": "*",
- "squizlabs/php_codesniffer": "*"
+ "sabre/cs": "~0.0.3"
+ },
+ "suggest": {
+ "hoa/bench": "If you would like to run the benchmark scripts"
},
"bin": [
"bin/vobject",
@@ -1787,7 +1666,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.2.x-dev"
+ "dev-master": "4.0.x-dev"
}
},
"autoload": {
@@ -1811,18 +1690,106 @@
"email": "dominik@fruux.com",
"homepage": "http://tobschall.de/",
"role": "Developer"
+ },
+ {
+ "name": "Ivan Enderlin",
+ "email": "ivan.enderlin@hoa-project.net",
+ "homepage": "http://mnt.io/",
+ "role": "Developer"
}
],
"description": "The VObject library for PHP allows you to easily parse and manipulate iCalendar and vCard objects",
"homepage": "http://sabre.io/vobject/",
"keywords": [
- "VObject",
+ "availability",
+ "freebusy",
"iCalendar",
+ "ics",
"jCal",
"jCard",
- "vCard"
+ "recurrence",
+ "rfc2425",
+ "rfc2426",
+ "rfc2739",
+ "rfc4770",
+ "rfc5545",
+ "rfc5546",
+ "rfc6321",
+ "rfc6350",
+ "rfc6351",
+ "rfc6474",
+ "rfc6638",
+ "rfc6715",
+ "rfc6868",
+ "vCard",
+ "vcf",
+ "xCal",
+ "xCard"
],
- "time": "2016-04-24 07:05:24"
+ "time": "2016-04-07 00:48:27"
+ },
+ {
+ "name": "sabre/xml",
+ "version": "1.4.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/fruux/sabre-xml.git",
+ "reference": "f48d98c22a4a4bef76cabb5968ffaddbb2bb593e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/fruux/sabre-xml/zipball/f48d98c22a4a4bef76cabb5968ffaddbb2bb593e",
+ "reference": "f48d98c22a4a4bef76cabb5968ffaddbb2bb593e",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-xmlreader": "*",
+ "ext-xmlwriter": "*",
+ "lib-libxml": ">=2.6.20",
+ "php": ">=5.4.1",
+ "sabre/uri": "~1.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "*",
+ "sabre/cs": "~0.0.2"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Sabre\\Xml\\": "lib/"
+ },
+ "files": [
+ "lib/Deserializer/functions.php",
+ "lib/Serializer/functions.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Evert Pot",
+ "email": "me@evertpot.com",
+ "homepage": "http://evertpot.com/",
+ "role": "Developer"
+ },
+ {
+ "name": "Markus Staab",
+ "email": "markus.staab@redaxo.de",
+ "role": "Developer"
+ }
+ ],
+ "description": "sabre/xml is an XML library that you may not hate.",
+ "homepage": "https://sabre.io/xml/",
+ "keywords": [
+ "XMLReader",
+ "XMLWriter",
+ "dom",
+ "xml"
+ ],
+ "time": "2016-05-19 21:56:49"
},
{
"name": "sensio/distribution-bundle",
diff --git a/src/Hackspace/Bundle/CalciferBundle/Controller/EventController.php b/src/Hackspace/Bundle/CalciferBundle/Controller/EventController.php
index 79ccc0d..9e2af22 100755
--- a/src/Hackspace/Bundle/CalciferBundle/Controller/EventController.php
+++ b/src/Hackspace/Bundle/CalciferBundle/Controller/EventController.php
@@ -15,19 +15,8 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Hackspace\Bundle\CalciferBundle\Entity\Event;
use Hackspace\Bundle\CalciferBundle\Form\EventType;
use Symfony\Component\HttpFoundation\Response;
-use Jsvrcek\ICS\Model\Calendar;
-use Jsvrcek\ICS\Utility\Formatter;
-use Jsvrcek\ICS\CalendarStream;
-use Jsvrcek\ICS\CalendarExport;
-use
- Sabre\VObject,
- Sabre\CalDAV,
- Sabre\DAV,
- Sabre\DAVACL,
- Sabre\DAV\Exception\Forbidden,
- Hackspace\Bundle\CalciferBundle\libs\CalciferCaldavBackend,
- Hackspace\Bundle\CalciferBundle\libs\CalciferPrincipalBackend;
+use Sabre\VObject;
/**
* Event controller.
*
@@ -35,45 +24,6 @@ use
*/
class EventController extends Controller
{
- /**
- * Finds and displays a Event entity.
- *
- * @Route("/{url}", name="events_caldav", requirements={"url" : "caldav(.+)"})
- */
- public function caldavEntry()
- {
- // Backends
- $calendarBackend = new CalciferCaldavBackend($this);
- $principalBackend = new CalciferPrincipalBackend();
- // Directory structure
- $tree = [
- new CalDAV\CalendarRootNode($principalBackend, $calendarBackend),
- ];
-
- $server = new DAV\Server($tree);
-
- $server->setBaseUri('/caldav');
-
- /*$aclPlugin = new DAVACL\Plugin();
- $aclPlugin->allowAccessToNodesWithoutACL = false;
- $server->addPlugin($aclPlugin);*/
-
- /* CalDAV support */
- $caldavPlugin = new CalDAV\Plugin();
- $server->addPlugin($caldavPlugin);
-
- /* WebDAV-Sync plugin */
- $server->addPlugin(new DAV\Sync\Plugin());
-
-// Support for html frontend
- $browser = new DAV\Browser\Plugin();
- $server->addPlugin($browser);
-
-// And off we go!
- $server->exec();
- return new Response();
- }
-
/**
* Lists all Event entities as ICS.
*
@@ -96,22 +46,14 @@ class EventController extends Controller
->setParameter('startdate', $now);
$entities = $qb->getQuery()->execute();
- $calendar = new Calendar();
- $calendar->setProdId('-//My Company//Cool Calendar App//EN');
+ $vcalendar = new VObject\Component\VCalendar();
foreach ($entities as $entity) {
- /** @var Event $entity */
- $event = $entity->ConvertToCalendarEvent();
- $calendar->addEvent($event);
+ /** @var Event $entity */
+ $vcalendar->add('VEVENT',$entity->ConvertToCalendarEvent());
}
- $calendarExport = new CalendarExport(new CalendarStream, new Formatter());
- $calendarExport->addCalendar($calendar);
-
- //output .ics formatted text
- $result = $calendarExport->getStream();
-
- $response = new Response($result);
+ $response = new Response($vcalendar->serialize());
$response->headers->set('Content-Type', 'text/calendar');
return $response;
diff --git a/src/Hackspace/Bundle/CalciferBundle/Controller/LocationController.php b/src/Hackspace/Bundle/CalciferBundle/Controller/LocationController.php
index bbdb83b..00d096e 100755
--- a/src/Hackspace/Bundle/CalciferBundle/Controller/LocationController.php
+++ b/src/Hackspace/Bundle/CalciferBundle/Controller/LocationController.php
@@ -16,12 +16,9 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Hackspace\Bundle\CalciferBundle\Entity\Event;
use Hackspace\Bundle\CalciferBundle\Form\EventType;
use Symfony\Component\HttpFoundation\Response;
-use Jsvrcek\ICS\Model\Calendar;
-use Jsvrcek\ICS\Utility\Formatter;
-use Jsvrcek\ICS\CalendarStream;
-use Jsvrcek\ICS\CalendarExport;
use Symfony\Component\HttpFoundation\AcceptHeader;
+use Sabre\VObject;
/**
* Location controller.
*
@@ -68,24 +65,15 @@ class LocationController extends Controller
$entities = $qb->getQuery()->execute();
if ($format == 'ics') {
- $calendar = new Calendar();
- $calendar->setProdId('-//My Company//Cool Calendar App//EN');
+ $vcalendar = new VObject\Component\VCalendar();
foreach ($entities as $entity) {
- /** @var Event $entity */
- $event = $entity->ConvertToCalendarEvent();
- $calendar->addEvent($event);
+ /** @var Event $entity */
+ $vcalendar->add('VEVENT',$entity->ConvertToCalendarEvent());
}
- $calendarExport = new CalendarExport(new CalendarStream, new Formatter());
- $calendarExport->addCalendar($calendar);
-
- //output .ics formatted text
- $result = $calendarExport->getStream();
-
- $response = new Response($result);
+ $response = new Response($vcalendar->serialize());
$response->headers->set('Content-Type', 'text/calendar');
-
return $response;
} else {
return array(
diff --git a/src/Hackspace/Bundle/CalciferBundle/Controller/TagController.php b/src/Hackspace/Bundle/CalciferBundle/Controller/TagController.php
index 230b828..09b76f3 100755
--- a/src/Hackspace/Bundle/CalciferBundle/Controller/TagController.php
+++ b/src/Hackspace/Bundle/CalciferBundle/Controller/TagController.php
@@ -7,7 +7,6 @@ use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\QueryBuilder;
use Hackspace\Bundle\CalciferBundle\Entity\Location;
use Hackspace\Bundle\CalciferBundle\Entity\Tag;
-use Jsvrcek\ICS\Model\Description\Geo;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
@@ -16,18 +15,12 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Hackspace\Bundle\CalciferBundle\Entity\Event;
use Hackspace\Bundle\CalciferBundle\Form\EventType;
use Symfony\Component\HttpFoundation\Response;
-use Jsvrcek\ICS\Model\Calendar;
-use Jsvrcek\ICS\Model\CalendarEvent;
-use Jsvrcek\ICS\Model\Relationship\Attendee;
-use Jsvrcek\ICS\Model\Relationship\Organizer;
-
-use Jsvrcek\ICS\Utility\Formatter;
-use Jsvrcek\ICS\CalendarStream;
-use Jsvrcek\ICS\CalendarExport;
use Symfony\Component\Validator\Constraints\DateTime;
use Doctrine\ORM\Query\ResultSetMappingBuilder;
use Symfony\Component\HttpFoundation\AcceptHeader;
+use Sabre\VObject;
+
/**
* Tag controller.
*
@@ -143,23 +136,14 @@ EOF;
}
if ($format == 'ics') {
- $calendar = new Calendar();
- $calendar->setProdId('-//My Company//Cool Calendar App//EN');
- $calendar->setTimeZone(new \DateTimeZone('Europe/Berlin'));
+ $vcalendar = new VObject\Component\VCalendar();
foreach ($entities as $entity) {
- /** @var Event $entity */
- $event = $entity->ConvertToCalendarEvent();
- $calendar->addEvent($event);
+ /** @var Event $entity */
+ $vcalendar->add('VEVENT',$entity->ConvertToCalendarEvent());
}
- $calendarExport = new CalendarExport(new CalendarStream, new Formatter());
- $calendarExport->addCalendar($calendar);
-
- //output .ics formatted text
- $result = $calendarExport->getStream();
-
- $response = new Response($result);
+ $response = new Response($vcalendar->serialize());
$response->headers->set('Content-Type', 'text/calendar');
return $response;
diff --git a/src/Hackspace/Bundle/CalciferBundle/Entity/Event.php b/src/Hackspace/Bundle/CalciferBundle/Entity/Event.php
index 93506ea..2dfb776 100755
--- a/src/Hackspace/Bundle/CalciferBundle/Entity/Event.php
+++ b/src/Hackspace/Bundle/CalciferBundle/Entity/Event.php
@@ -5,17 +5,7 @@ namespace Hackspace\Bundle\CalciferBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
-use Jsvrcek\ICS\Model\Description\Location As EventLocation;
use Symfony\Component\Validator\Constraints\DateTime;
-use Jsvrcek\ICS\Model\Calendar;
-use Jsvrcek\ICS\Model\CalendarEvent;
-use Jsvrcek\ICS\Model\Relationship\Attendee;
-use Jsvrcek\ICS\Model\Relationship\Organizer;
-
-use Jsvrcek\ICS\Utility\Formatter;
-use Jsvrcek\ICS\CalendarStream;
-use Jsvrcek\ICS\CalendarExport;
-use Jsvrcek\ICS\Model\Description\Geo;
/**
* Event
@@ -144,32 +134,30 @@ class Event extends BaseEntity
public function ConvertToCalendarEvent() {
- $event = new CalendarEvent();
- $event->setStart($this->startdate);
- if ($this->enddate instanceof \DateTime)
- $event->setEnd($this->enddate);
- $event->setSummary($this->summary);
- $event->setUrl($this->url);
- $uid = sprintf("https://%s/termine/%s",$_SERVER['HTTP_HOST'],$this->slug);
- $event->setUid($uid);
- if (count($this->tags) > 0) {
- $categories = [];
- foreach($this->tags as $tag) {
- $event->addCategory($tag->name);
- }
+ $categories = [];
+ foreach($this->tags as $tag) {
+ $categories[] = $tag->name;
}
+
+ $event = [
+ "VEVENT" => [
+ 'SUMMARY' => $this->summary,
+ 'DTSTART' => $this->startdate,
+ 'DESCRIPTION' => $this->description,
+ 'URL' => $this->url,
+ 'CATEGORIES' => $categories,
+ ]
+ ];
+ if (!is_null($this->enddate))
+ $event["VEVENT"]["DTEND"] = $this->enddate;
+
if ($this->location instanceof Location) {
- $location = new EventLocation();
- $location->setName($this->location->name);
- $event->setLocations([$location]);
+ $event["VEVENT"]["LOCATION"] = $this->location->name;
if (\is_float($this->location->lon) && \is_float($this->location->lat)) {
- $geo = new Geo();
- $geo->setLatitude($this->location->lat);
- $geo->setLongitude($this->location->lon);
- $event->setGeo($geo);
+ $event["VEVENT"]["GEO"] = [$this->location->lat, $this->location->lon];
}
}
- $event->setDescription($this->description);
+
return $event;
}
}
diff --git a/src/Hackspace/Bundle/CalciferBundle/libs/CalciferCaldavBackend.php b/src/Hackspace/Bundle/CalciferBundle/libs/CalciferCaldavBackend.php
deleted file mode 100644
index f2003f8..0000000
--- a/src/Hackspace/Bundle/CalciferBundle/libs/CalciferCaldavBackend.php
+++ /dev/null
@@ -1,312 +0,0 @@
-controller = $controller;
- }
-
- /**
- * Returns a list of calendars for a principal.
- *
- * Every project is an array with the following keys:
- * * id, a unique id that will be used by other functions to modify the
- * calendar. This can be the same as the uri or a database key.
- * * uri, which the basename of the uri with which the calendar is
- * accessed.
- * * principaluri. The owner of the calendar. Almost always the same as
- * principalUri passed to this method.
- *
- * Furthermore it can contain webdav properties in clark notation. A very
- * common one is '{DAV:}displayname'.
- *
- * Many clients also require:
- * {urn:ietf:params:xml:ns:caldav}supported-calendar-component-set
- * For this property, you can just return an instance of
- * Sabre\CalDAV\Property\SupportedCalendarComponentSet.
- *
- * @param string $principalUri
- * @return array
- */
- public function getCalendarsForUser($principalUri)
- {
- return [[
- 'id' => 1,
- 'uri' => 'calendar',
- 'principaluri' => '/caldav/calcifer',
- ]];
- }
-
- /**
- * Creates a new calendar for a principal.
- *
- * If the creation was a success, an id must be returned that can be used to reference
- * this calendar in other methods, such as updateCalendar.
- *
- * @param string $principalUri
- * @param string $calendarUri
- * @param array $properties
- * @return void
- */
- public function createCalendar($principalUri, $calendarUri, array $properties)
- {
- throw new \Exception('Not implemented');
- }
-
- /**
- * Delete a calendar and all it's objects
- *
- * @param mixed $calendarId
- * @return void
- */
- public function deleteCalendar($calendarId)
- {
- throw new \Exception('Not implemented');
- }
-
- private function FormatCalendarEvent(CalendarEvent $event)
- {
- $stream = new CalendarStream();
- $formatter = new Formatter();
- $stream->addItem('BEGIN:VEVENT')
- ->addItem('UID:' . $event->getUid())
- ->addItem('DTSTART:' . $formatter->getFormattedUTCDateTime($event->getStart()))
- ->addItem('DTEND:' . $formatter->getFormattedUTCDateTime($event->getEnd()))
- ->addItem('SUMMARY:' . $event->getSummary())
- ->addItem('DESCRIPTION:' . $event->getDescription());
-
- if ($event->getClass())
- $stream->addItem('CLASS:' . $event->getClass());
-
- /* @var $location Location */
- foreach ($event->getLocations() as $location) {
- $stream
- ->addItem('LOCATION' . $location->getUri() . $location->getLanguage() . ':' . $location->getName());
- }
-
- if ($event->getGeo())
- $stream->addItem('GEO:' . $event->getGeo()->getLatitude() . ';' . $event->getGeo()->getLongitude());
-
- if ($event->getUrl())
- $stream->addItem('URL:' . $event->getUrl());
-
- if ($event->getCreated())
- $stream->addItem('CREATED:' . $formatter->getFormattedUTCDateTime($event->getCreated()));
-
- if ($event->getLastModified())
- $stream->addItem('LAST-MODIFIED:' . $formatter->getFormattedUTCDateTime($event->getLastModified()));
-
- foreach ($event->getAttendees() as $attendee) {
- $stream->addItem($attendee->__toString());
- }
-
- if ($event->getOrganizer())
- $stream->addItem($event->getOrganizer()->__toString());
-
- $stream->addItem('END:VEVENT');
-
- return $stream->getStream();
- }
-
- private function formatEvent(Event $event)
- {
- /** @var CalendarEvent $calendar_event */
- $calendar_event = $event->ConvertToCalendarEvent();
- $calendar = new Calendar();
- $calendar->setProdId('-//My Company//Cool Calendar App//EN');
- $calendar->addEvent($calendar_event);
- $calendarExport = new CalendarExport(new CalendarStream, new Formatter());
- $calendarExport->addCalendar($calendar);
-
- //output .ics formatted text
- $calendar_data = $calendarExport->getStream();
-
-
- $event_data = [
- 'id' => $event->id,
- 'uri' => $event->slug . '.ics',
- 'lastmodified' => $event->startdate,
- 'etag' => '"' . sha1($calendar_data) . '"',
- 'calendarid' => 1,
- 'calendardata' => $calendar_data,
- 'size' => strlen($calendar_data),
- 'component' => 'VEVENT',
- ];
- return $event_data;
- }
-
- /**
- * Returns all calendar objects within a calendar.
- *
- * Every item contains an array with the following keys:
- * * id - unique identifier which will be used for subsequent updates
- * * calendardata - The iCalendar-compatible calendar data
- * * uri - a unique key which will be used to construct the uri. This can
- * be any arbitrary string, but making sure it ends with '.ics' is a
- * good idea. This is only the basename, or filename, not the full
- * path.
- * * lastmodified - a timestamp of the last modification time
- * * etag - An arbitrary string, surrounded by double-quotes. (e.g.:
- * '"abcdef"')
- * * calendarid - The calendarid as it was passed to this function.
- * * size - The size of the calendar objects, in bytes.
- * * component - optional, a string containing the type of object, such
- * as 'vevent' or 'vtodo'. If specified, this will be used to populate
- * the Content-Type header.
- *
- * Note that the etag is optional, but it's highly encouraged to return for
- * speed reasons.
- *
- * The calendardata is also optional. If it's not returned
- * 'getCalendarObject' will be called later, which *is* expected to return
- * calendardata.
- *
- * If neither etag or size are specified, the calendardata will be
- * used/fetched to determine these numbers. If both are specified the
- * amount of times this is needed is reduced by a great degree.
- *
- * @param mixed $calendarId
- * @return array
- */
- public function getCalendarObjects($calendarId)
- {
- /** @var EntityManager $em */
- $em = $this->controller->getDoctrine()->getManager();
-
- $now = new \DateTime();
- $now->setTime(0, 0, 0);
- /** @var QueryBuilder $qb */
- $qb = $em->createQueryBuilder();
- $qb->select(array('e'))
- ->from('CalciferBundle:Event', 'e')
- ->orderBy('e.startdate');
- $entities = $qb->getQuery()->execute();
-
- if (count($entities) > 0) {
- $events = [];
- foreach ($entities as $event) {
- /** @var Event $event */
- $events[] = $this->formatEvent($event);
- }
- return $events;
- }
- }
-
- /**
- * Returns information from a single calendar object, based on it's object
- * uri.
- *
- * The object uri is only the basename, or filename and not a full path.
- *
- * The returned array must have the same keys as getCalendarObjects. The
- * 'calendardata' object is required here though, while it's not required
- * for getCalendarObjects.
- *
- * This method must return null if the object did not exist.
- *
- * @param mixed $calendarId
- * @param string $objectUri
- * @return array|null
- */
- public function getCalendarObject($calendarId, $objectUri)
- {
- /** @var EntityManager $em */
- $em = $this->controller->getDoctrine()->getManager();
-
- /** @var EntityRepository $repo */
- $repo = $em->getRepository('CalciferBundle:Event');
-
- /** @var Event $entity */
- $event = $repo->findOneBy(['slug' => substr($objectUri,0,strlen($objectUri) - 4)]);
-
- if (!($event instanceof Event)) {
- throw $this->controller->createNotFoundException('Unable to find Event entity.');
- }
-
- return $this->formatEvent($event);
- }
-
- /**
- * Creates a new calendar object.
- *
- * The object uri is only the basename, or filename and not a full path.
- *
- * It is possible return an etag from this function, which will be used in
- * the response to this PUT request. Note that the ETag must be surrounded
- * by double-quotes.
- *
- * However, you should only really return this ETag if you don't mangle the
- * calendar-data. If the result of a subsequent GET to this object is not
- * the exact same as this request body, you should omit the ETag.
- *
- * @param mixed $calendarId
- * @param string $objectUri
- * @param string $calendarData
- * @return string|null
- */
- public function createCalendarObject($calendarId, $objectUri, $calendarData)
- {
- // TODO: Implement createCalendarObject() method.
- }
-
- /**
- * Updates an existing calendarobject, based on it's uri.
- *
- * The object uri is only the basename, or filename and not a full path.
- *
- * It is possible return an etag from this function, which will be used in
- * the response to this PUT request. Note that the ETag must be surrounded
- * by double-quotes.
- *
- * However, you should only really return this ETag if you don't mangle the
- * calendar-data. If the result of a subsequent GET to this object is not
- * the exact same as this request body, you should omit the ETag.
- *
- * @param mixed $calendarId
- * @param string $objectUri
- * @param string $calendarData
- * @return string|null
- */
- public function updateCalendarObject($calendarId, $objectUri, $calendarData)
- {
- throw new \Exception('Not implemented');
- }
-
- /**
- * Deletes an existing calendar object.
- *
- * The object uri is only the basename, or filename and not a full path.
- *
- * @param mixed $calendarId
- * @param string $objectUri
- * @return void
- */
- public function deleteCalendarObject($calendarId, $objectUri)
- {
- throw new \Exception('Not implemented');
- }
-}
\ No newline at end of file
diff --git a/src/Hackspace/Bundle/CalciferBundle/libs/CalciferPrincipalBackend.php b/src/Hackspace/Bundle/CalciferBundle/libs/CalciferPrincipalBackend.php
deleted file mode 100644
index aecf15b..0000000
--- a/src/Hackspace/Bundle/CalciferBundle/libs/CalciferPrincipalBackend.php
+++ /dev/null
@@ -1,158 +0,0 @@
- 'calcifer',
- '{http://sabredav.org/ns}email-address' => 'calcifer@example.com',
- 'uri' => '/caldav/calcifer',
- ]
- ];
- }
-
- /**
- * Returns a specific principal, specified by it's path.
- * The returned structure should be the exact same as from
- * getPrincipalsByPrefix.
- *
- * @param string $path
- * @return array
- */
- function getPrincipalByPath($path)
- {
- return [
- '{DAV:}displayname' => 'calcifer',
- '{http://sabredav.org/ns}email-address' => 'calcifer@example.com',
- 'uri' => '/caldav/calcifer',
- ];
- }
-
- /**
- * Updates one ore more webdav properties on a principal.
- *
- * The list of mutations is stored in a Sabre\DAV\PropPatch object.
- * To do the actual updates, you must tell this object which properties
- * you're going to process with the handle() method.
- *
- * Calling the handle method is like telling the PropPatch object "I
- * promise I can handle updating this property".
- *
- * Read the PropPatch documenation for more info and examples.
- *
- * @param string $path
- * @param \Sabre\DAV\PropPatch $propPatch
- * @return void
- */
- function updatePrincipal($path, \Sabre\DAV\PropPatch $propPatch)
- {
- throw new \Exception('Not implemented');
- }
-
- /**
- * This method is used to search for principals matching a set of
- * properties.
- *
- * This search is specifically used by RFC3744's principal-property-search
- * REPORT. You should at least allow searching on
- * http://sabredav.org/ns}email-address.
- *
- * The actual search should be a unicode-non-case-sensitive search. The
- * keys in searchProperties are the WebDAV property names, while the values
- * are the property values to search on.
- *
- * If multiple properties are being searched on, the search should be
- * AND'ed.
- *
- * This method should simply return an array with full principal uri's.
- *
- * If somebody attempted to search on a property the backend does not
- * support, you should simply return 0 results.
- *
- * You can also just return 0 results if you choose to not support
- * searching at all, but keep in mind that this may stop certain features
- * from working.
- *
- * @param string $prefixPath
- * @param array $searchProperties
- * @return array
- */
- function searchPrincipals($prefixPath, array $searchProperties, $test = 'allof')
- {
- return [
- [
- '{DAV:}displayname' => 'calcifer',
- '{http://sabredav.org/ns}email-address' => 'calcifer@example.com',
- 'uri' => '/caldav/calcifer',
- ]
- ];
- }
-
- /**
- * Returns the list of members for a group-principal
- *
- * @param string $principal
- * @return array
- */
- function getGroupMemberSet($principal)
- {
- throw new \Exception('Not implemented');
- }
-
- /**
- * Returns the list of groups a principal is a member of
- *
- * @param string $principal
- * @return array
- */
- function getGroupMembership($principal)
- {
- throw new \Exception('Not implemented');
- }
-
- /**
- * Updates the list of group members for a group principal.
- *
- * The principals should be passed as a list of uri's.
- *
- * @param string $principal
- * @param array $members
- * @return void
- */
- function setGroupMemberSet($principal, array $members)
- {
- throw new \Exception('Not implemented');
- }
-}
\ No newline at end of file