PageRenderTime 40ms CodeModel.GetById 10ms app.highlight 23ms RepoModel.GetById 1ms app.codeStats 0ms

/tests/Sabre/CalDAV/PluginTest.php

https://github.com/KOLANICH/SabreDAV
PHP | 1151 lines | 853 code | 248 blank | 50 comment | 12 complexity | fe50610b0eaac5d5876303432803e0af MD5 | raw file
   1<?php
   2
   3namespace Sabre\CalDAV;
   4use Sabre\DAVACL;
   5use Sabre\DAV;
   6use Sabre\HTTP;
   7
   8require_once 'Sabre/HTTP/ResponseMock.php';
   9require_once 'Sabre/CalDAV/TestUtil.php';
  10
  11class PluginTest extends \PHPUnit_Framework_TestCase {
  12
  13    /**
  14     * @var Sabre\DAV\Server
  15     */
  16    protected $server;
  17    /**
  18     * @var Sabre\CalDAV\Plugin
  19     */
  20    protected $plugin;
  21    protected $response;
  22    /**
  23     * @var Sabre\CalDAV\Backend\PDO
  24     */
  25    protected $caldavBackend;
  26
  27    function setup() {
  28
  29        $this->caldavBackend = new Backend\Mock(array(
  30            array(
  31                'id' => 1,
  32                'uri' => 'UUID-123467',
  33                'principaluri' => 'principals/user1',
  34                '{DAV:}displayname' => 'user1 calendar',
  35                '{urn:ietf:params:xml:ns:caldav}calendar-description' => 'Calendar description',
  36                '{http://apple.com/ns/ical/}calendar-order' => '1',
  37                '{http://apple.com/ns/ical/}calendar-color' => '#FF0000',
  38                '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set' => new Property\SupportedCalendarComponentSet(array('VEVENT','VTODO')),
  39            ),
  40            array(
  41                'id' => 2,
  42                'uri' => 'UUID-123468',
  43                'principaluri' => 'principals/user1',
  44                '{DAV:}displayname' => 'user1 calendar2',
  45                '{urn:ietf:params:xml:ns:caldav}calendar-description' => 'Calendar description',
  46                '{http://apple.com/ns/ical/}calendar-order' => '1',
  47                '{http://apple.com/ns/ical/}calendar-color' => '#FF0000',
  48                '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set' => new Property\SupportedCalendarComponentSet(array('VEVENT','VTODO')),
  49            )
  50        ), array(
  51            1 => array(
  52                'UUID-2345' => array(
  53                    'calendardata' => TestUtil::getTestCalendarData(),
  54                )
  55            )
  56        ));
  57        $principalBackend = new DAVACL\PrincipalBackend\Mock();
  58        $principalBackend->setGroupMemberSet('principals/admin/calendar-proxy-read',array('principals/user1'));
  59        $principalBackend->setGroupMemberSet('principals/admin/calendar-proxy-write',array('principals/user1'));
  60        $principalBackend->addPrincipal(array(
  61            'uri' => 'principals/admin/calendar-proxy-read',
  62        ));
  63        $principalBackend->addPrincipal(array(
  64            'uri' => 'principals/admin/calendar-proxy-write',
  65        ));
  66
  67        $calendars = new CalendarRootNode($principalBackend,$this->caldavBackend);
  68        $principals = new Principal\Collection($principalBackend);
  69
  70        $root = new DAV\SimpleCollection('root');
  71        $root->addChild($calendars);
  72        $root->addChild($principals);
  73
  74        $objectTree = new DAV\ObjectTree($root);
  75        $this->server = new DAV\Server($objectTree);
  76        $this->server->debugExceptions = true;
  77        $this->server->setBaseUri('/');
  78        $this->plugin = new Plugin();
  79        $this->server->addPlugin($this->plugin);
  80
  81        // Adding ACL plugin
  82        $this->server->addPlugin(new DAVACL\Plugin());
  83
  84        // Adding Auth plugin, and ensuring that we are logged in.
  85        $authBackend = new DAV\Auth\Backend\Mock();
  86        $authBackend->defaultUser = 'user1';
  87        $authPlugin = new DAV\Auth\Plugin($authBackend, 'SabreDAV');
  88        $this->server->addPlugin($authPlugin);
  89
  90        $authPlugin->beforeMethod('GET', '/');
  91
  92        $this->response = new HTTP\ResponseMock();
  93        $this->server->httpResponse = $this->response;
  94
  95    }
  96
  97    function testSimple() {
  98
  99        $this->assertEquals(array('MKCALENDAR'), $this->plugin->getHTTPMethods('calendars/user1/randomnewcalendar'));
 100        $this->assertEquals(array('calendar-access','calendar-proxy'), $this->plugin->getFeatures());
 101        $this->assertArrayHasKey('urn:ietf:params:xml:ns:caldav', $this->server->xmlNamespaces);
 102
 103    }
 104
 105    function testUnknownMethodPassThrough() {
 106
 107        $request = new HTTP\Request(array(
 108            'REQUEST_METHOD' => 'MKBREAKFAST',
 109            'REQUEST_URI'    => '/',
 110        ));
 111
 112        $this->server->httpRequest = $request;
 113        $this->server->exec();
 114
 115        $this->assertEquals('HTTP/1.1 501 Not Implemented', $this->response->status,'Incorrect status returned. Full response body:' . $this->response->body);
 116
 117    }
 118
 119    function testReportPassThrough() {
 120
 121        $request = new HTTP\Request(array(
 122            'REQUEST_METHOD'    => 'REPORT',
 123            'HTTP_CONTENT_TYPE' => 'application/xml',
 124            'REQUEST_URI'       => '/',
 125        ));
 126        $request->setBody('<?xml version="1.0"?><s:somereport xmlns:s="http://www.rooftopsolutions.nl/NS/example" />');
 127
 128        $this->server->httpRequest = $request;
 129        $this->server->exec();
 130
 131        $this->assertEquals('HTTP/1.1 403 Forbidden', $this->response->status);
 132
 133    }
 134
 135    function testMkCalendarBadLocation() {
 136
 137        $request = new HTTP\Request(array(
 138            'REQUEST_METHOD' => 'MKCALENDAR',
 139            'REQUEST_URI'    => '/blabla',
 140        ));
 141
 142        $body = '<?xml version="1.0" encoding="utf-8" ?>
 143   <C:mkcalendar xmlns:D="DAV:"
 144                 xmlns:C="urn:ietf:params:xml:ns:caldav">
 145     <D:set>
 146       <D:prop>
 147         <D:displayname>Lisa\'s Events</D:displayname>
 148         <C:calendar-description xml:lang="en"
 149   >Calendar restricted to events.</C:calendar-description>
 150         <C:supported-calendar-component-set>
 151           <C:comp name="VEVENT"/>
 152         </C:supported-calendar-component-set>
 153         <C:calendar-timezone><![CDATA[BEGIN:VCALENDAR
 154   PRODID:-//Example Corp.//CalDAV Client//EN
 155   VERSION:2.0
 156   BEGIN:VTIMEZONE
 157   TZID:US-Eastern
 158   LAST-MODIFIED:19870101T000000Z
 159   BEGIN:STANDARD
 160   DTSTART:19671029T020000
 161   RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
 162   TZOFFSETFROM:-0400
 163   TZOFFSETTO:-0500
 164   TZNAME:Eastern Standard Time (US & Canada)
 165   END:STANDARD
 166   BEGIN:DAYLIGHT
 167   DTSTART:19870405T020000
 168   RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
 169   TZOFFSETFROM:-0500
 170   TZOFFSETTO:-0400
 171   TZNAME:Eastern Daylight Time (US & Canada)
 172   END:DAYLIGHT
 173   END:VTIMEZONE
 174   END:VCALENDAR
 175   ]]></C:calendar-timezone>
 176       </D:prop>
 177     </D:set>
 178   </C:mkcalendar>';
 179
 180        $request->setBody($body);
 181        $this->server->httpRequest = $request;
 182        $this->server->exec();
 183
 184        $this->assertEquals('HTTP/1.1 403 Forbidden', $this->response->status);
 185
 186    }
 187
 188    function testMkCalendarNoParentNode() {
 189
 190        $request = new HTTP\Request(array(
 191            'REQUEST_METHOD' => 'MKCALENDAR',
 192            'REQUEST_URI'    => '/doesntexist/calendar',
 193        ));
 194
 195        $body = '<?xml version="1.0" encoding="utf-8" ?>
 196   <C:mkcalendar xmlns:D="DAV:"
 197                 xmlns:C="urn:ietf:params:xml:ns:caldav">
 198     <D:set>
 199       <D:prop>
 200         <D:displayname>Lisa\'s Events</D:displayname>
 201         <C:calendar-description xml:lang="en"
 202   >Calendar restricted to events.</C:calendar-description>
 203         <C:supported-calendar-component-set>
 204           <C:comp name="VEVENT"/>
 205         </C:supported-calendar-component-set>
 206         <C:calendar-timezone><![CDATA[BEGIN:VCALENDAR
 207   PRODID:-//Example Corp.//CalDAV Client//EN
 208   VERSION:2.0
 209   BEGIN:VTIMEZONE
 210   TZID:US-Eastern
 211   LAST-MODIFIED:19870101T000000Z
 212   BEGIN:STANDARD
 213   DTSTART:19671029T020000
 214   RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
 215   TZOFFSETFROM:-0400
 216   TZOFFSETTO:-0500
 217   TZNAME:Eastern Standard Time (US & Canada)
 218   END:STANDARD
 219   BEGIN:DAYLIGHT
 220   DTSTART:19870405T020000
 221   RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
 222   TZOFFSETFROM:-0500
 223   TZOFFSETTO:-0400
 224   TZNAME:Eastern Daylight Time (US & Canada)
 225   END:DAYLIGHT
 226   END:VTIMEZONE
 227   END:VCALENDAR
 228   ]]></C:calendar-timezone>
 229       </D:prop>
 230     </D:set>
 231   </C:mkcalendar>';
 232
 233        $request->setBody($body);
 234        $this->server->httpRequest = $request;
 235        $this->server->exec();
 236
 237        $this->assertEquals('HTTP/1.1 409 Conflict', $this->response->status);
 238
 239    }
 240
 241    function testMkCalendarExistingCalendar() {
 242
 243        $request = new HTTP\Request(array(
 244            'REQUEST_METHOD' => 'MKCALENDAR',
 245            'REQUEST_URI'    => '/calendars/user1/UUID-123467',
 246        ));
 247
 248        $body = '<?xml version="1.0" encoding="utf-8" ?>
 249   <C:mkcalendar xmlns:D="DAV:"
 250                 xmlns:C="urn:ietf:params:xml:ns:caldav">
 251     <D:set>
 252       <D:prop>
 253         <D:displayname>Lisa\'s Events</D:displayname>
 254         <C:calendar-description xml:lang="en"
 255   >Calendar restricted to events.</C:calendar-description>
 256         <C:supported-calendar-component-set>
 257           <C:comp name="VEVENT"/>
 258         </C:supported-calendar-component-set>
 259         <C:calendar-timezone><![CDATA[BEGIN:VCALENDAR
 260   PRODID:-//Example Corp.//CalDAV Client//EN
 261   VERSION:2.0
 262   BEGIN:VTIMEZONE
 263   TZID:US-Eastern
 264   LAST-MODIFIED:19870101T000000Z
 265   BEGIN:STANDARD
 266   DTSTART:19671029T020000
 267   RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
 268   TZOFFSETFROM:-0400
 269   TZOFFSETTO:-0500
 270   TZNAME:Eastern Standard Time (US & Canada)
 271   END:STANDARD
 272   BEGIN:DAYLIGHT
 273   DTSTART:19870405T020000
 274   RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
 275   TZOFFSETFROM:-0500
 276   TZOFFSETTO:-0400
 277   TZNAME:Eastern Daylight Time (US & Canada)
 278   END:DAYLIGHT
 279   END:VTIMEZONE
 280   END:VCALENDAR
 281   ]]></C:calendar-timezone>
 282       </D:prop>
 283     </D:set>
 284   </C:mkcalendar>';
 285
 286        $request->setBody($body);
 287        $this->server->httpRequest = $request;
 288        $this->server->exec();
 289
 290        $this->assertEquals('HTTP/1.1 405 Method Not Allowed', $this->response->status);
 291
 292    }
 293
 294    function testMkCalendarSucceed() {
 295
 296        $request = new HTTP\Request(array(
 297            'REQUEST_METHOD' => 'MKCALENDAR',
 298            'REQUEST_URI'    => '/calendars/user1/NEWCALENDAR',
 299        ));
 300
 301        $timezone = 'BEGIN:VCALENDAR
 302PRODID:-//Example Corp.//CalDAV Client//EN
 303VERSION:2.0
 304BEGIN:VTIMEZONE
 305TZID:US-Eastern
 306LAST-MODIFIED:19870101T000000Z
 307BEGIN:STANDARD
 308DTSTART:19671029T020000
 309RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
 310TZOFFSETFROM:-0400
 311TZOFFSETTO:-0500
 312TZNAME:Eastern Standard Time (US & Canada)
 313END:STANDARD
 314BEGIN:DAYLIGHT
 315DTSTART:19870405T020000
 316RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=4
 317TZOFFSETFROM:-0500
 318TZOFFSETTO:-0400
 319TZNAME:Eastern Daylight Time (US & Canada)
 320END:DAYLIGHT
 321END:VTIMEZONE
 322END:VCALENDAR';
 323
 324        $body = '<?xml version="1.0" encoding="utf-8" ?>
 325   <C:mkcalendar xmlns:D="DAV:"
 326                 xmlns:C="urn:ietf:params:xml:ns:caldav">
 327     <D:set>
 328       <D:prop>
 329         <D:displayname>Lisa\'s Events</D:displayname>
 330         <C:calendar-description xml:lang="en"
 331   >Calendar restricted to events.</C:calendar-description>
 332         <C:supported-calendar-component-set>
 333           <C:comp name="VEVENT"/>
 334         </C:supported-calendar-component-set>
 335         <C:calendar-timezone><![CDATA[' . $timezone . ']]></C:calendar-timezone>
 336       </D:prop>
 337     </D:set>
 338   </C:mkcalendar>';
 339
 340        $request->setBody($body);
 341        $this->server->httpRequest = $request;
 342        $this->server->exec();
 343
 344        $this->assertEquals('HTTP/1.1 201 Created', $this->response->status,'Invalid response code received. Full response body: ' .$this->response->body);
 345
 346        $calendars = $this->caldavBackend->getCalendarsForUser('principals/user1');
 347        $this->assertEquals(3, count($calendars));
 348
 349        $newCalendar = null;
 350        foreach($calendars as $calendar) {
 351           if ($calendar['uri'] === 'NEWCALENDAR') {
 352                $newCalendar = $calendar;
 353                break;
 354           }
 355        }
 356
 357        $this->assertInternalType('array',$newCalendar);
 358
 359        $keys = array(
 360            'uri' => 'NEWCALENDAR',
 361            'id' => null,
 362            '{urn:ietf:params:xml:ns:caldav}calendar-description' => 'Calendar restricted to events.',
 363            '{urn:ietf:params:xml:ns:caldav}calendar-timezone' => $timezone,
 364            '{DAV:}displayname' => 'Lisa\'s Events',
 365            '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set' => null,
 366        );
 367
 368        foreach($keys as $key=>$value) {
 369
 370            $this->assertArrayHasKey($key, $newCalendar);
 371
 372            if (is_null($value)) continue;
 373            $this->assertEquals($value, $newCalendar[$key]);
 374
 375        }
 376        $sccs = '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set';
 377        $this->assertTrue($newCalendar[$sccs] instanceof Property\SupportedCalendarComponentSet);
 378        $this->assertEquals(array('VEVENT'),$newCalendar[$sccs]->getValue());
 379
 380    }
 381
 382    function testMkCalendarEmptyBodySucceed() {
 383
 384        $request = new HTTP\Request(array(
 385            'REQUEST_METHOD' => 'MKCALENDAR',
 386            'REQUEST_URI'    => '/calendars/user1/NEWCALENDAR',
 387        ));
 388
 389        $request->setBody('');
 390        $this->server->httpRequest = $request;
 391        $this->server->exec();
 392
 393        $this->assertEquals('HTTP/1.1 201 Created', $this->response->status,'Invalid response code received. Full response body: ' .$this->response->body);
 394
 395        $calendars = $this->caldavBackend->getCalendarsForUser('principals/user1');
 396        $this->assertEquals(3, count($calendars));
 397
 398        $newCalendar = null;
 399        foreach($calendars as $calendar) {
 400           if ($calendar['uri'] === 'NEWCALENDAR') {
 401                $newCalendar = $calendar;
 402                break;
 403           }
 404        }
 405
 406        $this->assertInternalType('array',$newCalendar);
 407
 408        $keys = array(
 409            'uri' => 'NEWCALENDAR',
 410            'id' => null,
 411            '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set' => null,
 412        );
 413
 414        foreach($keys as $key=>$value) {
 415
 416            $this->assertArrayHasKey($key, $newCalendar);
 417
 418            if (is_null($value)) continue;
 419            $this->assertEquals($value, $newCalendar[$key]);
 420
 421        }
 422        $sccs = '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set';
 423        $this->assertTrue($newCalendar[$sccs] instanceof Property\SupportedCalendarComponentSet);
 424        $this->assertEquals(array('VEVENT','VTODO'),$newCalendar[$sccs]->getValue());
 425
 426    }
 427
 428    function testPrincipalProperties() {
 429
 430        $httpRequest = new HTTP\Request(array(
 431            'HTTP_HOST' => 'sabredav.org',
 432        ));
 433        $this->server->httpRequest = $httpRequest;
 434
 435        $props = $this->server->getPropertiesForPath('/principals/user1',array(
 436            '{urn:ietf:params:xml:ns:caldav}calendar-home-set',
 437            '{urn:ietf:params:xml:ns:caldav}schedule-outbox-URL',
 438            '{urn:ietf:params:xml:ns:caldav}calendar-user-address-set',
 439            '{' . Plugin::NS_CALENDARSERVER . '}calendar-proxy-read-for',
 440            '{' . Plugin::NS_CALENDARSERVER . '}calendar-proxy-write-for',
 441            '{' . Plugin::NS_CALENDARSERVER . '}notification-URL',
 442        ));
 443
 444        $this->assertArrayHasKey(0,$props);
 445        $this->assertArrayHasKey(200,$props[0]);
 446
 447
 448        $this->assertArrayHasKey('{urn:ietf:params:xml:ns:caldav}calendar-home-set',$props[0][200]);
 449        $prop = $props[0][200]['{urn:ietf:params:xml:ns:caldav}calendar-home-set'];
 450        $this->assertTrue($prop instanceof DAV\Property\Href);
 451        $this->assertEquals('calendars/user1/',$prop->getHref());
 452
 453        $this->assertArrayHasKey('{urn:ietf:params:xml:ns:caldav}schedule-outbox-URL',$props[0][200]);
 454        $prop = $props[0][200]['{urn:ietf:params:xml:ns:caldav}schedule-outbox-URL'];
 455        $this->assertTrue($prop instanceof DAV\Property\Href);
 456        $this->assertEquals('calendars/user1/outbox',$prop->getHref());
 457
 458        $this->assertArrayHasKey('{'.Plugin::NS_CALENDARSERVER .'}notification-URL',$props[0][200]);
 459        $prop = $props[0][200]['{'.Plugin::NS_CALENDARSERVER .'}notification-URL'];
 460        $this->assertTrue($prop instanceof DAV\Property\Href);
 461        $this->assertEquals('calendars/user1/notifications/',$prop->getHref());
 462
 463
 464        $this->assertArrayHasKey('{urn:ietf:params:xml:ns:caldav}calendar-user-address-set',$props[0][200]);
 465        $prop = $props[0][200]['{urn:ietf:params:xml:ns:caldav}calendar-user-address-set'];
 466        $this->assertTrue($prop instanceof DAV\Property\HrefList);
 467        $this->assertEquals(array('mailto:user1.sabredav@sabredav.org','/principals/user1/'),$prop->getHrefs());
 468
 469        $this->assertArrayHasKey('{http://calendarserver.org/ns/}calendar-proxy-read-for', $props[0][200]);
 470        $prop = $props[0][200]['{http://calendarserver.org/ns/}calendar-proxy-read-for'];
 471        $this->assertInstanceOf('Sabre\\DAV\\Property\\HrefList', $prop);
 472        $this->assertEquals(array('principals/admin'), $prop->getHrefs());
 473
 474        $this->assertArrayHasKey('{http://calendarserver.org/ns/}calendar-proxy-write-for', $props[0][200]);
 475        $prop = $props[0][200]['{http://calendarserver.org/ns/}calendar-proxy-write-for'];
 476        $this->assertInstanceOf('Sabre\\DAV\\Property\\HrefList', $prop);
 477        $this->assertEquals(array('principals/admin'), $prop->getHrefs());
 478
 479
 480    }
 481
 482    function testSupportedReportSetPropertyNonCalendar() {
 483
 484        $props = $this->server->getPropertiesForPath('/calendars/user1',array(
 485            '{DAV:}supported-report-set',
 486        ));
 487
 488        $this->assertArrayHasKey(0,$props);
 489        $this->assertArrayHasKey(200,$props[0]);
 490        $this->assertArrayHasKey('{DAV:}supported-report-set',$props[0][200]);
 491
 492        $prop = $props[0][200]['{DAV:}supported-report-set'];
 493
 494        $this->assertInstanceOf('\\Sabre\\DAV\\Property\\SupportedReportSet', $prop);
 495        $value = array(
 496            '{DAV:}expand-property',
 497            '{DAV:}principal-property-search',
 498            '{DAV:}principal-search-property-set'
 499        );
 500        $this->assertEquals($value,$prop->getValue());
 501
 502    }
 503
 504    /**
 505     * @depends testSupportedReportSetPropertyNonCalendar
 506     */
 507    function testSupportedReportSetProperty() {
 508
 509        $props = $this->server->getPropertiesForPath('/calendars/user1/UUID-123467',array(
 510            '{DAV:}supported-report-set',
 511        ));
 512
 513        $this->assertArrayHasKey(0,$props);
 514        $this->assertArrayHasKey(200,$props[0]);
 515        $this->assertArrayHasKey('{DAV:}supported-report-set',$props[0][200]);
 516
 517        $prop = $props[0][200]['{DAV:}supported-report-set'];
 518
 519        $this->assertTrue($prop instanceof \Sabre\DAV\Property\SupportedReportSet);
 520        $value = array(
 521            '{urn:ietf:params:xml:ns:caldav}calendar-multiget',
 522            '{urn:ietf:params:xml:ns:caldav}calendar-query',
 523            '{urn:ietf:params:xml:ns:caldav}free-busy-query',
 524            '{DAV:}expand-property',
 525            '{DAV:}principal-property-search',
 526            '{DAV:}principal-search-property-set'
 527        );
 528        $this->assertEquals($value,$prop->getValue());
 529
 530    }
 531
 532    function testSupportedReportSetUserCalendars() {
 533
 534        $this->server->addPlugin(new \Sabre\DAV\Sync\Plugin());
 535
 536        $props = $this->server->getPropertiesForPath('/calendars/user1',array(
 537            '{DAV:}supported-report-set',
 538        ));
 539
 540        $this->assertArrayHasKey(0,$props);
 541        $this->assertArrayHasKey(200,$props[0]);
 542        $this->assertArrayHasKey('{DAV:}supported-report-set',$props[0][200]);
 543
 544        $prop = $props[0][200]['{DAV:}supported-report-set'];
 545
 546        $this->assertTrue($prop instanceof \Sabre\DAV\Property\SupportedReportSet);
 547        $value = array(
 548            '{DAV:}sync-collection',
 549            '{DAV:}expand-property',
 550            '{DAV:}principal-property-search',
 551            '{DAV:}principal-search-property-set',
 552        );
 553        $this->assertEquals($value,$prop->getValue());
 554
 555    }
 556
 557    /**
 558     * @depends testSupportedReportSetProperty
 559     */
 560    function testCalendarMultiGetReport() {
 561
 562        $body =
 563            '<?xml version="1.0"?>' .
 564            '<c:calendar-multiget xmlns:c="urn:ietf:params:xml:ns:caldav" xmlns:d="DAV:">' .
 565            '<d:prop>' .
 566            '  <c:calendar-data />' .
 567            '  <d:getetag />' .
 568            '</d:prop>' .
 569            '<d:href>/calendars/user1/UUID-123467/UUID-2345</d:href>' .
 570            '</c:calendar-multiget>';
 571
 572        $request = new HTTP\Request(array(
 573            'REQUEST_METHOD' => 'REPORT',
 574            'REQUEST_URI'    => '/calendars/user1',
 575            'HTTP_DEPTH'     => '1',
 576        ));
 577        $request->setBody($body);
 578
 579        $this->server->httpRequest = $request;
 580        $this->server->exec();
 581
 582        $this->assertEquals('HTTP/1.1 207 Multi-Status',$this->response->status,'Invalid HTTP status received. Full response body: ' . $this->response->body);
 583
 584        $xml = simplexml_load_string(DAV\XMLUtil::convertDAVNamespace($this->response->body));
 585
 586        $xml->registerXPathNamespace('d','urn:DAV');
 587        $xml->registerXPathNamespace('c','urn:ietf:params:xml:ns:caldav');
 588
 589        $check = array(
 590            '/d:multistatus',
 591            '/d:multistatus/d:response',
 592            '/d:multistatus/d:response/d:href',
 593            '/d:multistatus/d:response/d:propstat',
 594            '/d:multistatus/d:response/d:propstat/d:prop',
 595            '/d:multistatus/d:response/d:propstat/d:prop/d:getetag',
 596            '/d:multistatus/d:response/d:propstat/d:prop/c:calendar-data',
 597            '/d:multistatus/d:response/d:propstat/d:status' => 'HTTP/1.1 200 OK',
 598        );
 599
 600        foreach($check as $v1=>$v2) {
 601
 602            $xpath = is_int($v1)?$v2:$v1;
 603
 604            $result = $xml->xpath($xpath);
 605            $this->assertEquals(1,count($result));
 606
 607            if (!is_int($v1)) $this->assertEquals($v2,(string)$result[0]);
 608
 609        }
 610
 611        // The response object should have a reference to the Asia/Seoul
 612        // timezone.
 613        $this->assertTrue(strpos($this->response->body,'Asia/Seoul')!==false);
 614
 615    }
 616
 617    /**
 618     * @depends testCalendarMultiGetReport
 619     */
 620    function testCalendarMultiGetReportExpand() {
 621
 622        $body =
 623            '<?xml version="1.0"?>' .
 624            '<c:calendar-multiget xmlns:c="urn:ietf:params:xml:ns:caldav" xmlns:d="DAV:">' .
 625            '<d:prop>' .
 626            '  <c:calendar-data>' .
 627            '     <c:expand start="20110101T000000Z" end="20111231T235959Z" />' .
 628            '  </c:calendar-data>' .
 629            '  <d:getetag />' .
 630            '</d:prop>' .
 631            '<d:href>/calendars/user1/UUID-123467/UUID-2345</d:href>' .
 632            '</c:calendar-multiget>';
 633
 634        $request = new HTTP\Request(array(
 635            'REQUEST_METHOD' => 'REPORT',
 636            'REQUEST_URI'    => '/calendars/user1',
 637            'HTTP_DEPTH'     => '1',
 638        ));
 639        $request->setBody($body);
 640
 641        $this->server->httpRequest = $request;
 642        $this->server->exec();
 643
 644        $this->assertEquals('HTTP/1.1 207 Multi-Status',$this->response->status,'Invalid HTTP status received. Full response body: ' . $this->response->body);
 645
 646        $xml = simplexml_load_string(DAV\XMLUtil::convertDAVNamespace($this->response->body));
 647
 648        $xml->registerXPathNamespace('d','urn:DAV');
 649        $xml->registerXPathNamespace('c','urn:ietf:params:xml:ns:caldav');
 650
 651        $check = array(
 652            '/d:multistatus',
 653            '/d:multistatus/d:response',
 654            '/d:multistatus/d:response/d:href',
 655            '/d:multistatus/d:response/d:propstat',
 656            '/d:multistatus/d:response/d:propstat/d:prop',
 657            '/d:multistatus/d:response/d:propstat/d:prop/d:getetag',
 658            '/d:multistatus/d:response/d:propstat/d:prop/c:calendar-data',
 659            '/d:multistatus/d:response/d:propstat/d:status' => 'HTTP/1.1 200 OK',
 660        );
 661
 662        foreach($check as $v1=>$v2) {
 663
 664            $xpath = is_int($v1)?$v2:$v1;
 665
 666            $result = $xml->xpath($xpath);
 667            $this->assertEquals(1,count($result));
 668
 669            if (!is_int($v1)) $this->assertEquals($v2,(string)$result[0]);
 670
 671        }
 672        // The response object should no longer hold references to timezones.
 673        $this->assertTrue(strpos($this->response->body,'Asia/Seoul')===false);
 674
 675    }
 676
 677    /**
 678     * @depends testSupportedReportSetProperty
 679     * @depends testCalendarMultiGetReport
 680     */
 681    function testCalendarQueryReport() {
 682
 683        $body =
 684            '<?xml version="1.0"?>' .
 685            '<c:calendar-query xmlns:c="urn:ietf:params:xml:ns:caldav" xmlns:d="DAV:">' .
 686            '<d:prop>' .
 687            '  <c:calendar-data>' .
 688            '     <c:expand start="20000101T000000Z" end="20101231T235959Z" />' .
 689            '  </c:calendar-data>' .
 690            '  <d:getetag />' .
 691            '</d:prop>' .
 692            '<c:filter>' .
 693            '  <c:comp-filter name="VCALENDAR">' .
 694            '    <c:comp-filter name="VEVENT" />' .
 695            '  </c:comp-filter>' .
 696            '</c:filter>' .
 697            '</c:calendar-query>';
 698
 699        $request = new HTTP\Request(array(
 700            'REQUEST_METHOD' => 'REPORT',
 701            'REQUEST_URI'    => '/calendars/user1/UUID-123467',
 702            'HTTP_DEPTH'     => '1',
 703        ));
 704        $request->setBody($body);
 705
 706        $this->server->httpRequest = $request;
 707        $this->server->exec();
 708
 709        $this->assertEquals('HTTP/1.1 207 Multi-Status',$this->response->status,'Received an unexpected status. Full response body: ' . $this->response->body);
 710
 711        $xml = simplexml_load_string(DAV\XMLUtil::convertDAVNamespace($this->response->body));
 712
 713        $xml->registerXPathNamespace('d','urn:DAV');
 714        $xml->registerXPathNamespace('c','urn:ietf:params:xml:ns:caldav');
 715
 716        $check = array(
 717            '/d:multistatus',
 718            '/d:multistatus/d:response',
 719            '/d:multistatus/d:response/d:href',
 720            '/d:multistatus/d:response/d:propstat',
 721            '/d:multistatus/d:response/d:propstat/d:prop',
 722            '/d:multistatus/d:response/d:propstat/d:prop/d:getetag',
 723            '/d:multistatus/d:response/d:propstat/d:prop/c:calendar-data',
 724            '/d:multistatus/d:response/d:propstat/d:status' => 'HTTP/1.1 200 OK',
 725        );
 726
 727        foreach($check as $v1=>$v2) {
 728
 729            $xpath = is_int($v1)?$v2:$v1;
 730
 731            $result = $xml->xpath($xpath);
 732            $this->assertEquals(1,count($result), 'We expected 1 ' . $xpath . ' elements. We\'ve found ' . count($result) . '. Full result: ' . $this->response->body);
 733
 734            if (!is_int($v1)) $this->assertEquals($v2,(string)$result[0]);
 735
 736        }
 737
 738    }
 739
 740    /**
 741     * @depends testCalendarQueryReport
 742     */
 743    function testCalendarQueryReportNoCalData() {
 744
 745        $body =
 746            '<?xml version="1.0"?>' .
 747            '<c:calendar-query xmlns:c="urn:ietf:params:xml:ns:caldav" xmlns:d="DAV:">' .
 748            '<d:prop>' .
 749            '  <d:getetag />' .
 750            '</d:prop>' .
 751            '<c:filter>' .
 752            '  <c:comp-filter name="VCALENDAR">' .
 753            '    <c:comp-filter name="VEVENT" />' .
 754            '  </c:comp-filter>' .
 755            '</c:filter>' .
 756            '</c:calendar-query>';
 757
 758        $request = new HTTP\Request(array(
 759            'REQUEST_METHOD' => 'REPORT',
 760            'REQUEST_URI'    => '/calendars/user1//UUID-123467',
 761            'HTTP_DEPTH'     => '1',
 762        ));
 763        $request->setBody($body);
 764
 765        $this->server->httpRequest = $request;
 766        $this->server->exec();
 767
 768        $this->assertEquals('HTTP/1.1 207 Multi-Status',$this->response->status,'Received an unexpected status. Full response body: ' . $this->response->body);
 769
 770        $xml = simplexml_load_string(DAV\XMLUtil::convertDAVNamespace($this->response->body));
 771
 772        $xml->registerXPathNamespace('d','urn:DAV');
 773        $xml->registerXPathNamespace('c','urn:ietf:params:xml:ns:caldav');
 774
 775        $check = array(
 776            '/d:multistatus',
 777            '/d:multistatus/d:response',
 778            '/d:multistatus/d:response/d:href',
 779            '/d:multistatus/d:response/d:propstat',
 780            '/d:multistatus/d:response/d:propstat/d:prop',
 781            '/d:multistatus/d:response/d:propstat/d:prop/d:getetag',
 782            '/d:multistatus/d:response/d:propstat/d:status' => 'HTTP/1.1 200 OK',
 783        );
 784
 785        foreach($check as $v1=>$v2) {
 786
 787            $xpath = is_int($v1)?$v2:$v1;
 788
 789            $result = $xml->xpath($xpath);
 790            $this->assertEquals(1,count($result), 'We expected 1 ' . $xpath . ' elements. We\'ve found ' . count($result) . '. Full result: ' . $this->response->body);
 791
 792            if (!is_int($v1)) $this->assertEquals($v2,(string)$result[0]);
 793
 794        }
 795
 796    }
 797
 798    /**
 799     * @depends testCalendarQueryReport
 800     */
 801    function testCalendarQueryReportNoFilters() {
 802
 803        $body =
 804            '<?xml version="1.0"?>' .
 805            '<c:calendar-query xmlns:c="urn:ietf:params:xml:ns:caldav" xmlns:d="DAV:">' .
 806            '<d:prop>' .
 807            '  <c:calendar-data />' .
 808            '  <d:getetag />' .
 809            '</d:prop>' .
 810            '</c:calendar-query>';
 811
 812        $request = new HTTP\Request(array(
 813            'REQUEST_METHOD' => 'REPORT',
 814            'REQUEST_URI'    => '/calendars/user1//UUID-123467',
 815        ));
 816        $request->setBody($body);
 817
 818        $this->server->httpRequest = $request;
 819        $this->server->exec();
 820
 821        $this->assertEquals('HTTP/1.1 400 Bad request',$this->response->status,'Received an unexpected status. Full response body: ' . $this->response->body);
 822
 823    }
 824
 825    /**
 826     * @depends testSupportedReportSetProperty
 827     * @depends testCalendarMultiGetReport
 828     */
 829    function testCalendarQueryReport1Object() {
 830
 831        $body =
 832            '<?xml version="1.0"?>' .
 833            '<c:calendar-query xmlns:c="urn:ietf:params:xml:ns:caldav" xmlns:d="DAV:">' .
 834            '<d:prop>' .
 835            '  <c:calendar-data>' .
 836            '     <c:expand start="20000101T000000Z" end="20101231T235959Z" />' .
 837            '  </c:calendar-data>' .
 838            '  <d:getetag />' .
 839            '</d:prop>' .
 840            '<c:filter>' .
 841            '  <c:comp-filter name="VCALENDAR">' .
 842            '    <c:comp-filter name="VEVENT" />' .
 843            '  </c:comp-filter>' .
 844            '</c:filter>' .
 845            '</c:calendar-query>';
 846
 847        $request = new HTTP\Request(array(
 848            'REQUEST_METHOD' => 'REPORT',
 849            'REQUEST_URI'    => '/calendars/user1/UUID-123467/UUID-2345',
 850            'HTTP_DEPTH'     => '0',
 851        ));
 852        $request->setBody($body);
 853
 854        $this->server->httpRequest = $request;
 855        $this->server->exec();
 856
 857        $this->assertEquals('HTTP/1.1 207 Multi-Status',$this->response->status,'Received an unexpected status. Full response body: ' . $this->response->body);
 858
 859        $xml = simplexml_load_string(DAV\XMLUtil::convertDAVNamespace($this->response->body));
 860
 861        $xml->registerXPathNamespace('d','urn:DAV');
 862        $xml->registerXPathNamespace('c','urn:ietf:params:xml:ns:caldav');
 863
 864        $check = array(
 865            '/d:multistatus',
 866            '/d:multistatus/d:response',
 867            '/d:multistatus/d:response/d:href',
 868            '/d:multistatus/d:response/d:propstat',
 869            '/d:multistatus/d:response/d:propstat/d:prop',
 870            '/d:multistatus/d:response/d:propstat/d:prop/d:getetag',
 871            '/d:multistatus/d:response/d:propstat/d:prop/c:calendar-data',
 872            '/d:multistatus/d:response/d:propstat/d:status' => 'HTTP/1.1 200 OK',
 873        );
 874
 875        foreach($check as $v1=>$v2) {
 876
 877            $xpath = is_int($v1)?$v2:$v1;
 878
 879            $result = $xml->xpath($xpath);
 880            $this->assertEquals(1,count($result), 'We expected 1 ' . $xpath . ' elements. We\'ve found ' . count($result) . '. Full result: ' . $this->response->body);
 881
 882            if (!is_int($v1)) $this->assertEquals($v2,(string)$result[0]);
 883
 884        }
 885
 886    }
 887
 888    /**
 889     * @depends testSupportedReportSetProperty
 890     * @depends testCalendarMultiGetReport
 891     */
 892    function testCalendarQueryReport1ObjectNoCalData() {
 893
 894        $body =
 895            '<?xml version="1.0"?>' .
 896            '<c:calendar-query xmlns:c="urn:ietf:params:xml:ns:caldav" xmlns:d="DAV:">' .
 897            '<d:prop>' .
 898            '  <d:getetag />' .
 899            '</d:prop>' .
 900            '<c:filter>' .
 901            '  <c:comp-filter name="VCALENDAR">' .
 902            '    <c:comp-filter name="VEVENT" />' .
 903            '  </c:comp-filter>' .
 904            '</c:filter>' .
 905            '</c:calendar-query>';
 906
 907        $request = new HTTP\Request(array(
 908            'REQUEST_METHOD' => 'REPORT',
 909            'REQUEST_URI'    => '/calendars/user1/UUID-123467/UUID-2345',
 910            'HTTP_DEPTH'     => '0',
 911        ));
 912        $request->setBody($body);
 913
 914        $this->server->httpRequest = $request;
 915        $this->server->exec();
 916
 917        $this->assertEquals('HTTP/1.1 207 Multi-Status',$this->response->status,'Received an unexpected status. Full response body: ' . $this->response->body);
 918
 919        $xml = simplexml_load_string(DAV\XMLUtil::convertDAVNamespace($this->response->body));
 920
 921        $xml->registerXPathNamespace('d','urn:DAV');
 922        $xml->registerXPathNamespace('c','urn:ietf:params:xml:ns:caldav');
 923
 924        $check = array(
 925            '/d:multistatus',
 926            '/d:multistatus/d:response',
 927            '/d:multistatus/d:response/d:href',
 928            '/d:multistatus/d:response/d:propstat',
 929            '/d:multistatus/d:response/d:propstat/d:prop',
 930            '/d:multistatus/d:response/d:propstat/d:prop/d:getetag',
 931            '/d:multistatus/d:response/d:propstat/d:status' => 'HTTP/1.1 200 OK',
 932        );
 933
 934        foreach($check as $v1=>$v2) {
 935
 936            $xpath = is_int($v1)?$v2:$v1;
 937
 938            $result = $xml->xpath($xpath);
 939            $this->assertEquals(1,count($result), 'We expected 1 ' . $xpath . ' elements. We\'ve found ' . count($result) . '. Full result: ' . $this->response->body);
 940
 941            if (!is_int($v1)) $this->assertEquals($v2,(string)$result[0]);
 942
 943        }
 944
 945    }
 946
 947    function testHTMLActionsPanel() {
 948
 949        $output = '';
 950        $r = $this->server->broadcastEvent('onHTMLActionsPanel', array($this->server->tree->getNodeForPath('calendars/user1'), &$output));
 951        $this->assertFalse($r);
 952
 953        $this->assertTrue(!!strpos($output,'Display name'));
 954
 955    }
 956
 957    function testBrowserPostAction() {
 958
 959        $r = $this->server->broadcastEvent('onBrowserPostAction', array('calendars/user1', 'mkcalendar', array(
 960            'name' => 'NEWCALENDAR',
 961            '{DAV:}displayname' => 'foo',
 962        )));
 963        $this->assertFalse($r);
 964
 965        $calendars = $this->caldavBackend->getCalendarsForUser('principals/user1');
 966        $this->assertEquals(3, count($calendars));
 967
 968        $newCalendar = null;
 969        foreach($calendars as $calendar) {
 970           if ($calendar['uri'] === 'NEWCALENDAR') {
 971                $newCalendar = $calendar;
 972                break;
 973           }
 974        }
 975        if (!$newCalendar)
 976            $this->fail('Could not find newly created calendar');
 977
 978
 979    }
 980
 981    /**
 982     * @depends testCalendarMultiGetReport
 983     */
 984    function testCalendarMultiGetReportNoEnd() {
 985
 986        $body =
 987            '<?xml version="1.0"?>' .
 988            '<c:calendar-multiget xmlns:c="urn:ietf:params:xml:ns:caldav" xmlns:d="DAV:">' .
 989            '<d:prop>' .
 990            '  <c:calendar-data>' .
 991            '     <c:expand start="20110101T000000Z" />' .
 992            '  </c:calendar-data>' .
 993            '  <d:getetag />' .
 994            '</d:prop>' .
 995            '<d:href>/calendars/user1/UUID-123467/UUID-2345</d:href>' .
 996            '</c:calendar-multiget>';
 997
 998        $request = new HTTP\Request(array(
 999            'REQUEST_METHOD' => 'REPORT',
1000            'REQUEST_URI'    => '/calendars/user1',
1001            'HTTP_DEPTH'     => '1',
1002        ));
1003        $request->setBody($body);
1004
1005        $this->server->httpRequest = $request;
1006        $this->server->exec();
1007
1008        $this->assertEquals('HTTP/1.1 400 Bad request',$this->response->status,'Invalid HTTP status received. Full response body: ' . $this->response->body);
1009
1010    }
1011
1012    /**
1013     * @depends testCalendarMultiGetReport
1014     */
1015    function testCalendarMultiGetReportNoStart() {
1016
1017        $body =
1018            '<?xml version="1.0"?>' .
1019            '<c:calendar-multiget xmlns:c="urn:ietf:params:xml:ns:caldav" xmlns:d="DAV:">' .
1020            '<d:prop>' .
1021            '  <c:calendar-data>' .
1022            '     <c:expand end="20110101T000000Z" />' .
1023            '  </c:calendar-data>' .
1024            '  <d:getetag />' .
1025            '</d:prop>' .
1026            '<d:href>/calendars/user1/UUID-123467/UUID-2345</d:href>' .
1027            '</c:calendar-multiget>';
1028
1029        $request = new HTTP\Request(array(
1030            'REQUEST_METHOD' => 'REPORT',
1031            'REQUEST_URI'    => '/calendars/user1',
1032            'HTTP_DEPTH'     => '1',
1033        ));
1034        $request->setBody($body);
1035
1036        $this->server->httpRequest = $request;
1037        $this->server->exec();
1038
1039        $this->assertEquals('HTTP/1.1 400 Bad request',$this->response->status,'Invalid HTTP status received. Full response body: ' . $this->response->body);
1040
1041    }
1042
1043    /**
1044     * @depends testCalendarMultiGetReport
1045     */
1046    function testCalendarMultiGetReportEndBeforeStart() {
1047
1048        $body =
1049            '<?xml version="1.0"?>' .
1050            '<c:calendar-multiget xmlns:c="urn:ietf:params:xml:ns:caldav" xmlns:d="DAV:">' .
1051            '<d:prop>' .
1052            '  <c:calendar-data>' .
1053            '     <c:expand start="20200101T000000Z" end="20110101T000000Z" />' .
1054            '  </c:calendar-data>' .
1055            '  <d:getetag />' .
1056            '</d:prop>' .
1057            '<d:href>/calendars/user1/UUID-123467/UUID-2345</d:href>' .
1058            '</c:calendar-multiget>';
1059
1060        $request = new HTTP\Request(array(
1061            'REQUEST_METHOD' => 'REPORT',
1062            'REQUEST_URI'    => '/calendars/user1',
1063            'HTTP_DEPTH'     => '1',
1064        ));
1065        $request->setBody($body);
1066
1067        $this->server->httpRequest = $request;
1068        $this->server->exec();
1069
1070        $this->assertEquals('HTTP/1.1 400 Bad request',$this->response->status,'Invalid HTTP status received. Full response body: ' . $this->response->body);
1071
1072    }
1073
1074    function testNotificationProperties() {
1075
1076        $request = array(
1077            '{' . Plugin::NS_CALENDARSERVER . '}notificationtype',
1078        );
1079        $result = array();
1080        $notification = new Notifications\Node(
1081            $this->caldavBackend,
1082            'principals/user1',
1083            new Notifications\Notification\SystemStatus('foo','"1"')
1084        );
1085        $this->plugin->beforeGetProperties('foo', $notification, $request, $result);
1086
1087        $this->assertEquals(
1088            array(
1089                200 => array(
1090                    '{' . Plugin::NS_CALENDARSERVER . '}notificationtype' => $notification->getNotificationType()
1091                )
1092            ), $result);
1093
1094    }
1095
1096    function testNotificationGet() {
1097
1098        $notification = new Notifications\Node(
1099            $this->caldavBackend,
1100            'principals/user1',
1101            new Notifications\Notification\SystemStatus('foo','"1"')
1102        );
1103
1104        $server = new DAV\Server(array($notification));
1105        $caldav = new Plugin();
1106
1107        $server->httpRequest = new HTTP\Request(array(
1108            'REQUEST_URI' => '/foo.xml',
1109        ));
1110        $httpResponse = new HTTP\ResponseMock();
1111        $server->httpResponse = $httpResponse;
1112
1113        $server->addPlugin($caldav);
1114
1115        $caldav->beforeMethod('GET','foo.xml');
1116
1117        $this->assertEquals('HTTP/1.1 200 OK', $httpResponse->status);
1118        $this->assertEquals(array(
1119            'Content-Type' => 'application/xml',
1120            'ETag'         => '"1"',
1121        ), $httpResponse->headers);
1122
1123        $expected =
1124'<?xml version="1.0" encoding="UTF-8"?>
1125<cs:notification xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns" xmlns:cal="urn:ietf:params:xml:ns:caldav" xmlns:cs="http://calendarserver.org/ns/">
1126  <cs:systemstatus type="high"/>
1127</cs:notification>
1128';
1129
1130        $this->assertEquals($expected, $httpResponse->body);
1131
1132    }
1133
1134    function testGETPassthrough() {
1135
1136        $server = new DAV\Server();
1137        $caldav = new Plugin();
1138
1139        $httpResponse = new HTTP\ResponseMock();
1140        $server->httpResponse = $httpResponse;
1141
1142        $server->addPlugin($caldav);
1143
1144        $caldav->beforeMethod('GET','foo');
1145
1146        $this->assertNull($caldav->beforeMethod('GET','foozz'));
1147
1148    }
1149
1150
1151}