From 4494e475e0d763163443cb7bc84354946aefd296 Mon Sep 17 00:00:00 2001
From: Laurent Laffont <llaffont@afi-sa.fr>
Date: Wed, 18 Jan 2017 15:14:43 +0100
Subject: [PATCH] hotline #52287 : external agendas : ical parser can import
 Archimed Ermes feeds

---
 VERSIONS_HOTLINE/52287                        |   1 +
 library/Class/WebService/ICalendar.php        |  12 +-
 .../ExternalAgendas/ExternalAgendasTest.php   |  45 +++++-
 tests/scenarios/ExternalAgendas/ermes.ics     | 128 ++++++++++++++++++
 4 files changed, 179 insertions(+), 7 deletions(-)
 create mode 100644 VERSIONS_HOTLINE/52287
 create mode 100644 tests/scenarios/ExternalAgendas/ermes.ics

diff --git a/VERSIONS_HOTLINE/52287 b/VERSIONS_HOTLINE/52287
new file mode 100644
index 00000000000..320d90632b3
--- /dev/null
+++ b/VERSIONS_HOTLINE/52287
@@ -0,0 +1 @@
+ - ticket #52287 : Agendas externes : adaptation du parser iCal aux flux Archimed Ermes.
\ No newline at end of file
diff --git a/library/Class/WebService/ICalendar.php b/library/Class/WebService/ICalendar.php
index f70b0e64174..51c52e71cb7 100644
--- a/library/Class/WebService/ICalendar.php
+++ b/library/Class/WebService/ICalendar.php
@@ -26,6 +26,7 @@ class Class_WebService_ICalendar extends Class_WebService_Abstract {
   protected
     $_events,
     $_current_event,
+    $_current_url,
     $_external_agenda;
 
   public function import($external_agenda) {
@@ -33,8 +34,12 @@ class Class_WebService_ICalendar extends Class_WebService_Abstract {
     $this->_events = new Storm_Model_Collection();
     $this->_current_event = null;
 
+
+    $ics_content = $this->httpGet($external_agenda->getUrl());
+    $ics_content = preg_replace('|\r\n\s|', '', $ics_content); //see RFC2445
+
     array_map([$this, '_importLine'],
-              explode("\r\n", $this->httpGet($external_agenda->getUrl())));
+              explode("\r\n", $ics_content));
 
     return $this->_events;
   }
@@ -44,8 +49,13 @@ class Class_WebService_ICalendar extends Class_WebService_Abstract {
 
 
   protected function _importLine($line) {
+    if (!$line)
+      return $this;
+
     list($key, $value) = explode(':', $line, 2);
     $this->_importData($key, $value);
+
+    return $this;
   }
 
 
diff --git a/tests/scenarios/ExternalAgendas/ExternalAgendasTest.php b/tests/scenarios/ExternalAgendas/ExternalAgendasTest.php
index e6e271ed0e6..3a9a882bb37 100644
--- a/tests/scenarios/ExternalAgendas/ExternalAgendasTest.php
+++ b/tests/scenarios/ExternalAgendas/ExternalAgendasTest.php
@@ -58,6 +58,12 @@ abstract class ExternalAgendasAdminTestCase extends Admin_AbstractControllerTest
   }
 
   public function __call($method, $args) { /** in order to stub Class_ExternalAgenda::import($this) */}
+
+
+  public function tearDown() {
+    Class_WebService_ICalendar::setDefaultHttpClient(null);
+    parent::tearDown();
+  }
 }
 
 
@@ -475,12 +481,6 @@ class ExternalAgendasAdminImportTest extends ExternalAgendasAdminTestCase {
   }
 
 
-  public function tearDown() {
-    Class_WebService_ICalendar::setDefaultHttpClient(null);
-    parent::tearDown();
-  }
-
-
   /** @test */
   public function titleShouldBeMoissonageDesEvenements() {
     $this->assertXPathContentContains('//h1', 'Moissonnage des évènements de l\'agenda "Personal Agenda"');
@@ -660,3 +660,36 @@ class ExternalAgendasAdminSecondImportTest extends ExternalAgendasAdminTestCase
     $this->assertEquals(1, Class_ArticleCategorie::countBy(['libelle' => 'Atelier']));
   }
 }
+
+
+
+
+
+class ExternalAgendasAdminErmesImportTest extends ExternalAgendasAdminTestCase {
+  public function setUp() {
+    parent::setUp();
+
+    Class_WebService_ICalendar::setDefaultHttpClient($this->mock()
+                                                     ->whenCalled('open_url')
+                                                     ->with('http://my.server.com/calendar.ics')
+                                                     ->answers(file_get_contents(__DIR__.'/ermes.ics'))
+                                                     ->beStrict());
+
+    $this->dispatch('/admin/external-agendas/import/id/124', true);
+    Class_Article::clearCache();
+  }
+
+
+
+  /** @test */
+  public function pageShouldContainsFiveEventsCreated() {
+    $this->assertXPathContentContains('//h2',
+                                      'Nombre d\'évènements créés : 5');
+  }
+
+
+  /** @test */
+  public function firstEventDescriptionShouldContainsEntreeLibre() {
+    $this->assertContains('entrée libre', Class_Article::find(1)->getContenu());
+  }
+}
diff --git a/tests/scenarios/ExternalAgendas/ermes.ics b/tests/scenarios/ExternalAgendas/ermes.ics
new file mode 100644
index 00000000000..a92980782c2
--- /dev/null
+++ b/tests/scenarios/ExternalAgendas/ermes.ics
@@ -0,0 +1,128 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:-//ddaysoftware.com//NONSGML DDay.iCal 1.0//EN
+X-ARCHIMED-IdAgenda:1
+X-ARCHIMED-Rights:
+X-WR-CALDESC:Ermes Calandar
+X-WR-CALNAME:Evenements des médiathèques de Lille
+BEGIN:VTIMEZONE
+TZID:Romance Standard Time
+BEGIN:STANDARD
+DTSTART:20161002T030000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYHOUR=3;BYMINUTE=0;BYMONTH=10
+TZNAME:Romance Standard Time
+TZOFFSETFROM:+0200
+TZOFFSETTO:+0100
+END:STANDARD
+BEGIN:DAYLIGHT
+DTSTART:20160301T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYHOUR=2;BYMINUTE=0;BYMONTH=3
+TZNAME:Romance Daylight Time
+TZOFFSETFROM:+0100
+TZOFFSETTO:+0200
+END:DAYLIGHT
+END:VTIMEZONE
+BEGIN:VEVENT
+CATEGORIES:Heure du conte
+CREATED:20160827T113132
+DESCRIPTION:Heure du conte pour les 0-3 ans<br />Parents-Enfants<br />entré
+ e libre
+DTEND:20160921T110000
+DTSTAMP:20170118T135101Z
+DTSTART:20160921T103000
+LAST-MODIFIED:20160927T114437
+LOCATION:Médiathèque de Wazemmes
+ORGANIZER;CN=Alexis SETFAOUI (admin):
+SEQUENCE:0
+STATUS:Tentative
+SUMMARY:Kilikili minus
+UID:a1bc19ad-9371-4627-80e1-16ed6d303b89
+X-ALT-DESC;FMTTYPE=text/html:Heure du conte pour les 0-3 ans<br />Parents-E
+ nfants<br />entrée libre
+X-ARCHIMED-CATEGORIECOLOR:#92E1C0
+X-ARCHIMED-LASTMODIFIEDBY:Alexis SETFAOUI (admin)
+END:VEVENT
+BEGIN:VEVENT
+CATEGORIES:Heure du conte
+CREATED:20160827T113132
+DESCRIPTION:Heure du conte pour les 0-3 ans<br />Parents-Enfants<br />entré
+ e libre
+DTEND:20161015T110000
+DTSTAMP:20170118T135101Z
+DTSTART:20161015T103000
+LAST-MODIFIED:20160927T114437
+LOCATION:Médiathèque de Wazemmes
+ORGANIZER;CN=Alexis SETFAOUI (admin):
+SEQUENCE:0
+STATUS:Tentative
+SUMMARY:Kilikili minus
+UID:c0de757c-ff46-4dac-b648-05e972da2784
+X-ALT-DESC;FMTTYPE=text/html:Heure du conte pour les 0-3 ans<br />Parents-E
+ nfants<br />entrée libre
+X-ARCHIMED-CATEGORIECOLOR:#92E1C0
+X-ARCHIMED-LASTMODIFIEDBY:Alexis SETFAOUI (admin)
+END:VEVENT
+BEGIN:VEVENT
+CATEGORIES:Heure du conte
+CREATED:20160827T113132
+DESCRIPTION:<p>Heure du conte bilingue français-anglais par Rebecca Grossbe
+ rg.</p>\n<p><br />Parents-Enfants.</p>\n<p><br />Entrée libre.</p>
+DTEND;VALUE=DATE:20160921
+DTSTAMP:20170118T135101Z
+DTSTART:20160921T150000
+LAST-MODIFIED:20161224T104312
+LOCATION:Médiathèque de Wazemmes
+ORGANIZER;CN=Alexis SETFAOUI (admin):
+SEQUENCE:0
+STATUS:Confirmed
+SUMMARY:Storytime
+UID:3905e44d-9fa9-48f8-b1ad-6a7beda0ee76
+X-ALT-DESC;FMTTYPE=text/html:<p>Heure du conte bilingue français-anglais pa
+ r Rebecca Grossberg.</p>\n<p><br />Parents-Enfants.</p>\n<p><br />Entrée l
+ ibre.</p>
+X-ARCHIMED-CATEGORIECOLOR:#92E1C0
+X-ARCHIMED-LASTMODIFIEDBY:Céline Verwaerde
+END:VEVENT
+BEGIN:VEVENT
+CATEGORIES:Heure du conte
+CREATED:20160827T113132
+DESCRIPTION:<p>Heure du conte bilingue français-anglais par Rebecca Grossbe
+ rg.</p>\n<p><br />Parents-Enfants.</p>\n<p><br />Entrée libre.</p>
+DTEND:20161012T160000
+DTSTAMP:20170118T135101Z
+DTSTART:20161012T150000
+LAST-MODIFIED:20161224T104312
+LOCATION:Médiathèque de Wazemmes
+ORGANIZER;CN=Alexis SETFAOUI (admin):
+SEQUENCE:0
+STATUS:Confirmed
+SUMMARY:Storytime
+UID:35b302c6-e362-4f8a-9861-b7b9b91eb568
+X-ALT-DESC;FMTTYPE=text/html:<p>Heure du conte bilingue français-anglais pa
+ r Rebecca Grossberg.</p>\n<p><br />Parents-Enfants.</p>\n<p><br />Entrée l
+ ibre.</p>
+X-ARCHIMED-CATEGORIECOLOR:#92E1C0
+X-ARCHIMED-LASTMODIFIEDBY:Céline Verwaerde
+END:VEVENT
+BEGIN:VEVENT
+CATEGORIES:Heure du conte
+CREATED:20160827T113132
+DESCRIPTION:<p>Heure du conte bilingue français-anglais par Rebecca Grossbe
+ rg.</p>\n<p><br />Parents-Enfants.</p>\n<p><br />Entrée libre.</p>
+DTEND:20161116T160000
+DTSTAMP:20170118T135101Z
+DTSTART:20161116T150000
+LAST-MODIFIED:20161224T104312
+LOCATION:Médiathèque de Wazemmes
+ORGANIZER;CN=Alexis SETFAOUI (admin):
+SEQUENCE:0
+STATUS:Confirmed
+SUMMARY:Storytime
+UID:bb7f02cf-3515-4dbc-ae57-3bdd35a341ad
+X-ALT-DESC;FMTTYPE=text/html:<p>Heure du conte bilingue français-anglais pa
+ r Rebecca Grossberg.</p>\n<p><br />Parents-Enfants.</p>\n<p><br />Entrée l
+ ibre.</p>
+X-ARCHIMED-CATEGORIECOLOR:#92E1C0
+X-ARCHIMED-LASTMODIFIEDBY:Céline Verwaerde
+END:VEVENT
+END:VCALENDAR
-- 
GitLab