implemented calendar-proxy
authorLars Kneschke <l.kneschke@metaways.de>
Fri, 25 Apr 2014 09:46:14 +0000 (11:46 +0200)
committerPhilipp Schüle <p.schuele@metaways.de>
Thu, 4 Sep 2014 09:26:18 +0000 (11:26 +0200)
Change-Id: I140fba5b1569af8f9045dbe294a9c57fb419433c
Reviewed-on: http://gerrit.tine20.com/customers/563
Reviewed-by: Lars Kneschke <l.kneschke@metaways.de>
Tested-by: Jenkins CI (http://ci.tine20.com/)
Reviewed-by: Philipp Schüle <p.schuele@metaways.de>
Reviewed-by: Cornelius Weiss <c.weiss@metaways.de>
28 files changed:
tests/tine20/Addressbook/Frontend/CardDAVTest.php
tests/tine20/Calendar/Frontend/CalDAV/AllTests.php
tests/tine20/Calendar/Frontend/CalDAV/ProxyTest.php [new file with mode: 0644]
tests/tine20/Calendar/Frontend/CalDAVTest.php
tests/tine20/Felamimail/AllTests.php
tests/tine20/Felamimail/Frontend/JsonTest.php [moved from tests/tine20/Felamimail/JsonTest.php with 99% similarity]
tests/tine20/Felamimail/Frontend/WebDAVTest.php [new file with mode: 0644]
tests/tine20/Filemanager/Frontend/WebDAVTest.php
tests/tine20/Tinebase/Frontend/WebDAV/RecordTest.php
tests/tine20/Tinebase/WebDav/Plugin/OwnCloudTest.php
tests/tine20/Tinebase/WebDav/PrincipalBackendTest.php
tests/tine20/Tinebase/WebDav/RootTest.php
tine20/Addressbook/Frontend/CardDAV.php [deleted file]
tine20/Addressbook/Frontend/WebDAV.php
tine20/Calendar/Frontend/CalDAV.php [deleted file]
tine20/Calendar/Frontend/CalDAV/PluginDefaultAlarms.php
tine20/Calendar/Frontend/WebDAV.php
tine20/Calendar/Frontend/WebDAV/Container.php
tine20/Felamimail/Frontend/WebDAV.php
tine20/Filemanager/Frontend/WebDAV.php
tine20/Tasks/Frontend/WebDAV.php
tine20/Tinebase/Frontend/WebDAV/Abstract.php
tine20/Tinebase/Server/WebDAV.php
tine20/Tinebase/WebDav/Collection/AbstractContainerTree.php [new file with mode: 0644]
tine20/Tinebase/WebDav/Container/Abstract.php
tine20/Tinebase/WebDav/Principal.php
tine20/Tinebase/WebDav/PrincipalBackend.php
tine20/Tinebase/WebDav/Root.php

index e8b0fe1..02be157 100644 (file)
@@ -4,80 +4,25 @@
  * 
  * @package     Addressbook
  * @license     http://www.gnu.org/licenses/agpl.html
- * @copyright   Copyright (c) 2011-2011 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright   Copyright (c) 2011-2041 Metaways Infosystems GmbH (http://www.metaways.de)
  * @author      Lars Kneschke <l.kneschke@metaways.de>
  */
 
 /**
- * Test helper
- */
-require_once dirname(dirname(dirname(__FILE__))) . DIRECTORY_SEPARATOR . 'TestHelper.php';
-
-if (!defined('PHPUnit_MAIN_METHOD')) {
-    define('PHPUnit_MAIN_METHOD', 'Addressbook_Frontend_CardDAVTest::main');
-}
-
-/**
  * Test class for Addressbook_Frontend_CardDAV
  */
-class Addressbook_Frontend_CardDAVTest extends PHPUnit_Framework_TestCase
+class Addressbook_Frontend_CardDAVTest extends TestCase
 {
     /**
-     * @var array test objects
-     */
-    protected $objects = array();
-    
-    /**
-     * Runs the test methods of this class.
-     *
-     * @access public
-     * @static
-     */
-    public static function main()
-    {
-        $suite  = new PHPUnit_Framework_TestSuite('Tine 2.0 Addressbook CardDAV Tests');
-        PHPUnit_TextUI_TestRunner::run($suite);
-    }
-
-    /**
-     * Sets up the fixture.
-     * This method is called before a test is executed.
-     *
-     * @access protected
-     */
-    protected function setUp()
-    {
-        Tinebase_TransactionManager::getInstance()->startTransaction(Tinebase_Core::getDb());
-        
-        $this->objects['initialContainer'] = Tinebase_Container::getInstance()->addContainer(new Tinebase_Model_Container(array(
-            'name'              => Tinebase_Record_Abstract::generateUID(),
-            'type'              => Tinebase_Model_Container::TYPE_PERSONAL,
-            'backend'           => 'Sql',
-            'application_id'    => Tinebase_Application::getInstance()->getApplicationByName('Addressbook')->getId(),
-        )));
-    }
-
-    /**
-     * Tears down the fixture
-     * This method is called after a test is executed.
-     *
-     * @access protected
-     */
-    protected function tearDown()
-    {
-        Tinebase_TransactionManager::getInstance()->rollBack();
-    }
-    
-    /**
      * test getChildren
      */
     public function testGetChildren()
     {
-        $collection = new Addressbook_Frontend_CardDAV();
+        $collection = new Addressbook_Frontend_WebDAV(\Sabre\CardDAV\Plugin::ADDRESSBOOK_ROOT, true);
         
         $children = $collection->getChildren();
         
-        $this->assertTrue($children[0] instanceof Addressbook_Frontend_WebDAV_Container);
+        $this->assertTrue($children[0] instanceof Addressbook_Frontend_WebDAV);
     }
         
     /**
@@ -85,9 +30,9 @@ class Addressbook_Frontend_CardDAVTest extends PHPUnit_Framework_TestCase
      */
     public function testGetChild()
     {
-        $collection = new Addressbook_Frontend_CardDAV();
+        $collection = new Addressbook_Frontend_WebDAV(\Sabre\CardDAV\Plugin::ADDRESSBOOK_ROOT . '/' . Tinebase_Core::getUser()->contact_id, true);
         
-        $child = $collection->getChild($this->objects['initialContainer']->getId());
+        $child = $collection->getChild($this->_getTestContainer()->getId());
         
         $this->assertTrue($child instanceof Addressbook_Frontend_WebDAV_Container);
     }
@@ -97,7 +42,7 @@ class Addressbook_Frontend_CardDAVTest extends PHPUnit_Framework_TestCase
      */
     public function testCreateFile()
     {
-        $collection = new Addressbook_Frontend_CardDAV();
+        $collection = new Addressbook_Frontend_WebDAV(\Sabre\CardDAV\Plugin::ADDRESSBOOK_ROOT . '/' . Tinebase_Core::getUser()->contact_id, true);
         
         $this->setExpectedException('Sabre\DAV\Exception\Forbidden');
         
@@ -111,7 +56,7 @@ class Addressbook_Frontend_CardDAVTest extends PHPUnit_Framework_TestCase
     {
         $randomName = Tinebase_Record_Abstract::generateUID();
         
-        $collection = new Addressbook_Frontend_CardDAV();
+        $collection = new Addressbook_Frontend_WebDAV(\Sabre\CardDAV\Plugin::ADDRESSBOOK_ROOT . '/' . Tinebase_Core::getUser()->contact_id, true);
         
         $collection->createDirectory($randomName);
         
@@ -124,10 +69,10 @@ class Addressbook_Frontend_CardDAVTest extends PHPUnit_Framework_TestCase
     {
         $_SERVER['HTTP_USER_AGENT'] = 'Mac OS X/10.9 (13A603) AddressBook/1365';
     
-        $collection = new Addressbook_Frontend_CardDAV();
+        $collection = new Addressbook_Frontend_WebDAV(\Sabre\CardDAV\Plugin::ADDRESSBOOK_ROOT . '/' . Tinebase_Core::getUser()->contact_id, true);
     
         $children = $collection->getChildren();
-    
+        
         $this->assertCount(1, $children, 'there should be just one global container');
         $this->assertTrue($children[0] instanceof Addressbook_Frontend_CardDAV_AllContacts, 'wrong instance');
     }
@@ -136,10 +81,27 @@ class Addressbook_Frontend_CardDAVTest extends PHPUnit_Framework_TestCase
     {
         $_SERVER['HTTP_USER_AGENT'] = 'FooBar User Agent';
     
-        $collection = new Addressbook_Frontend_CardDAV();
+        $collection = new Addressbook_Frontend_WebDAV(\Sabre\CardDAV\Plugin::ADDRESSBOOK_ROOT, true);
     
         $children = $collection->getChildren();
     
         $this->assertGreaterThanOrEqual(2, count($children), 'there should be more than one container');
     }
+    
+    /**
+     * create test container
+     * 
+     * @return Tinebase_Model_Container
+     */
+    protected function _getTestContainer()
+    {
+        $container = Tinebase_Container::getInstance()->addContainer(new Tinebase_Model_Container(array(
+            'name'              => Tinebase_Record_Abstract::generateUID(),
+            'type'              => Tinebase_Model_Container::TYPE_PERSONAL,
+            'backend'           => 'Sql',
+            'application_id'    => Tinebase_Application::getInstance()->getApplicationByName('Addressbook')->getId(),
+        )));
+        
+        return $container;
+    }
 }
index aa521b6..48725b5 100644 (file)
@@ -24,6 +24,7 @@ class Calendar_Frontend_CalDAV_AllTests
     {
         $suite = new PHPUnit_Framework_TestSuite('Tine 2.0 Calendar All Frontend CalDAV Tests');
         $suite->addTestSuite('Calendar_Frontend_CalDAV_PluginDefaultAlarmsTest');
+        $suite->addTestSuite('Calendar_Frontend_CalDAV_ProxyTest');
         return $suite;
     }
 }
diff --git a/tests/tine20/Calendar/Frontend/CalDAV/ProxyTest.php b/tests/tine20/Calendar/Frontend/CalDAV/ProxyTest.php
new file mode 100644 (file)
index 0000000..b41e19c
--- /dev/null
@@ -0,0 +1,200 @@
+<?php
+/**
+ * Tine 2.0 - http://www.tine20.org
+ * 
+ * @package     Calendar
+ * @subpackage  Frontend
+ * @license     http://www.gnu.org/licenses/agpl.html
+ * @copyright   Copyright (c) 2014-2014 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @author      Lars Kneschke <l.kneschke@metaways.de>
+ */
+
+/**
+ * Test helper
+ */
+require_once __DIR__ . '/../../../../../tine20/vendor/sabre/dav/tests/Sabre/HTTP/ResponseMock.php';
+
+/**
+ * Test class for Calendar_Frontend_CalDAV_ProxyTest
+ */
+class Calendar_Frontend_CalDAV_ProxyTest extends TestCase
+{
+    /**
+     * 
+     * @var Sabre\DAV\Server
+     */
+    protected $server;
+    
+    /**
+     * Sets up the fixture.
+     * This method is called before a test is executed.
+     *
+     * @access protected
+     */
+    protected function setUp()
+    {
+        parent::setUp();
+        
+        $this->server = new Sabre\DAV\Server(new Tinebase_WebDav_Root());
+        $this->server->debugExceptions = true;
+        $this->server->addPlugin(new \Sabre\CalDAV\Plugin());
+        $this->server->addPlugin(new \Sabre\CalDAV\SharingPlugin());
+        
+        $aclPlugin = new \Sabre\DAVACL\Plugin();
+        $aclPlugin->defaultUsernamePath    = Tinebase_WebDav_PrincipalBackend::PREFIX_USERS;
+        $aclPlugin->principalCollectionSet = array (Tinebase_WebDav_PrincipalBackend::PREFIX_USERS, Tinebase_WebDav_PrincipalBackend::PREFIX_GROUPS);
+        $this->server->addPlugin($aclPlugin);
+        
+        $this->response = new Sabre\HTTP\ResponseMock();
+        $this->server->httpResponse = $this->response;
+    }
+
+    /**
+     * test testGetProperties method
+     */
+    public function testGetProperties()
+    {
+        $body = '<?xml version="1.0" encoding="UTF-8"?>
+            <A:expand-property xmlns:A="DAV:">
+                <A:property name="calendar-proxy-read-for" namespace="http://calendarserver.org/ns/">
+                    <A:property name="email-address-set" namespace="http://calendarserver.org/ns/"/>
+                    <A:property name="displayname" namespace="DAV:"/>
+                    <A:property name="calendar-user-address-set" namespace="urn:ietf:params:xml:ns:caldav"/>
+                </A:property>
+                <A:property name="calendar-proxy-write-for" namespace="http://calendarserver.org/ns/">
+                    <A:property name="email-address-set" namespace="http://calendarserver.org/ns/"/>
+                    <A:property name="displayname" namespace="DAV:"/>
+                    <A:property name="calendar-user-address-set" namespace="urn:ietf:params:xml:ns:caldav"/>
+                </A:property>
+            </A:expand-property>';
+
+        $request = new Sabre\HTTP\Request(array(
+            'REQUEST_METHOD' => 'REPORT',
+            'REQUEST_URI'    => '/' . Tinebase_WebDav_PrincipalBackend::PREFIX_USERS . '/' . Tinebase_Core::getUser()->contact_id
+        ));
+        $request->setBody($body);
+
+        $this->server->httpRequest = $request;
+        $this->server->exec();
+        //var_dump($this->response->body);
+        
+        $this->assertEquals('HTTP/1.1 207 Multi-Status', $this->response->status);
+        
+        $responseDoc = new DOMDocument();
+        $responseDoc->loadXML($this->response->body);
+        //$responseDoc->formatOutput = true; echo $responseDoc->saveXML();
+        $xpath = new DomXPath($responseDoc);
+        $xpath->registerNamespace('cal', 'urn:ietf:params:xml:ns:caldav');
+        $xpath->registerNamespace('cs',  'http://calendarserver.org/ns/');
+        
+        $nodes = $xpath->query('//d:multistatus/d:response/d:propstat/d:prop/cs:calendar-proxy-read-for');
+        $this->assertEquals(1, $nodes->length, $responseDoc->saveXML());
+        #$this->assertEmpty($nodes->item(0)->nodeValue, $responseDoc->saveXML());
+        
+        $nodes = $xpath->query('//d:multistatus/d:response/d:propstat/d:prop/cs:calendar-proxy-write-for');
+        $this->assertEquals(1, $nodes->length, $responseDoc->saveXML());
+        #$this->assertEmpty($nodes->item(0)->nodeValue, $responseDoc->saveXML());
+    }
+    
+    /**
+     * test testGetProperties method
+     */
+    public function testGetPropertiesSharedUser()
+    {
+        $body = '<?xml version="1.0" encoding="UTF-8"?>
+            <A:expand-property xmlns:A="DAV:">
+                <A:property name="calendar-proxy-read-for" namespace="http://calendarserver.org/ns/">
+                    <A:property name="email-address-set" namespace="http://calendarserver.org/ns/"/>
+                    <A:property name="displayname" namespace="DAV:"/>
+                    <A:property name="calendar-user-address-set" namespace="urn:ietf:params:xml:ns:caldav"/>
+                </A:property>
+                <A:property name="calendar-proxy-write-for" namespace="http://calendarserver.org/ns/">
+                    <A:property name="email-address-set" namespace="http://calendarserver.org/ns/"/>
+                    <A:property name="displayname" namespace="DAV:"/>
+                    <A:property name="calendar-user-address-set" namespace="urn:ietf:params:xml:ns:caldav"/>
+                </A:property>
+            </A:expand-property>';
+
+        $request = new Sabre\HTTP\Request(array(
+            'REQUEST_METHOD' => 'REPORT',
+            'REQUEST_URI'    => '/' . Tinebase_WebDav_PrincipalBackend::PREFIX_USERS . '/' . Tinebase_WebDav_PrincipalBackend::SHARED
+        ));
+        $request->setBody($body);
+
+        $this->server->httpRequest = $request;
+        $this->server->exec();
+        //var_dump($this->response->body);
+        
+        $this->assertEquals('HTTP/1.1 207 Multi-Status', $this->response->status);
+        
+        $responseDoc = new DOMDocument();
+        $responseDoc->loadXML($this->response->body);
+        //$responseDoc->formatOutput = true; echo $responseDoc->saveXML();
+        $xpath = new DomXPath($responseDoc);
+        $xpath->registerNamespace('cal', 'urn:ietf:params:xml:ns:caldav');
+        $xpath->registerNamespace('cs',  'http://calendarserver.org/ns/');
+        
+        $nodes = $xpath->query('//d:multistatus/d:response/d:propstat/d:prop/cs:calendar-proxy-read-for');
+        $this->assertEquals(1, $nodes->length, $responseDoc->saveXML());
+        #$this->assertEmpty($nodes->item(0)->nodeValue, $responseDoc->saveXML());
+        
+        $nodes = $xpath->query('//d:multistatus/d:response/d:propstat/d:prop/cs:calendar-proxy-write-for');
+        $this->assertEquals(1, $nodes->length, $responseDoc->saveXML());
+        #$this->assertEmpty($nodes->item(0)->nodeValue, $responseDoc->saveXML());
+    }
+    
+    /**
+     * test testGetProperties method
+     */
+    public function testGetPropertiesSharedUserPrincipal()
+    {
+        $body = '<?xml version="1.0" encoding="UTF-8"?>
+            <A:propfind xmlns:A="DAV:">
+              <A:prop>
+                <B:calendar-home-set xmlns:B="urn:ietf:params:xml:ns:caldav"/>
+                <B:calendar-user-address-set xmlns:B="urn:ietf:params:xml:ns:caldav"/>
+                <A:current-user-principal/>
+                <A:displayname/>
+                <C:dropbox-home-URL xmlns:C="http://calendarserver.org/ns/"/>
+                <C:email-address-set xmlns:C="http://calendarserver.org/ns/"/>
+                <C:notification-URL xmlns:C="http://calendarserver.org/ns/"/>
+                <A:principal-collection-set/>
+                <A:principal-URL/>
+                <A:resource-id/>
+                <B:schedule-inbox-URL xmlns:B="urn:ietf:params:xml:ns:caldav"/>
+                <B:schedule-outbox-URL xmlns:B="urn:ietf:params:xml:ns:caldav"/>
+                <A:supported-report-set/>
+              </A:prop>
+            </A:propfind>';
+
+        $request = new Sabre\HTTP\Request(array(
+            'REQUEST_METHOD' => 'PROPFIND',
+            'REQUEST_URI'    => '/' . Tinebase_WebDav_PrincipalBackend::PREFIX_USERS . '/' . Tinebase_WebDav_PrincipalBackend::SHARED,
+            'HTTP_BRIEF'     => 't',
+            'HTTP_DEPTH'     => '0'
+        ));
+        $request->setBody($body);
+
+        $this->server->httpRequest = $request;
+        $this->server->exec();
+        //var_dump($this->response->body);
+        
+        $this->assertEquals('HTTP/1.1 207 Multi-Status', $this->response->status);
+        
+        $responseDoc = new DOMDocument();
+        $responseDoc->loadXML($this->response->body);
+        //$responseDoc->formatOutput = true; echo $responseDoc->saveXML();
+        $xpath = new DomXPath($responseDoc);
+        $xpath->registerNamespace('cal', 'urn:ietf:params:xml:ns:caldav');
+        $xpath->registerNamespace('cs',  'http://calendarserver.org/ns/');
+        $xpath->registerNamespace('d',  'DAV');
+        
+        $nodes = $xpath->query('//d:multistatus/d:response/d:propstat/d:prop/cal:calendar-home-set');
+        $this->assertEquals(1, $nodes->length, $responseDoc->saveXML());
+        #$this->assertEmpty($nodes->item(0)->nodeValue, $responseDoc->saveXML());
+        
+        $nodes = $xpath->query('//d:multistatus/d:response/d:propstat/d:prop/d:principal-URL');
+        $this->assertEquals(1, $nodes->length, $responseDoc->saveXML());
+        #$this->assertEmpty($nodes->item(0)->nodeValue, $responseDoc->saveXML());
+    }
+}
index def5130..4111f7f 100644 (file)
@@ -4,86 +4,30 @@
  * 
  * @package     Calendar
  * @license     http://www.gnu.org/licenses/agpl.html
- * @copyright   Copyright (c) 2011-2011 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright   Copyright (c) 2011-2014 Metaways Infosystems GmbH (http://www.metaways.de)
  * @author      Lars Kneschke <l.kneschke@metaways.de>
  */
 
 /**
- * Test helper
- */
-require_once dirname(dirname(dirname(__FILE__))) . DIRECTORY_SEPARATOR . 'TestHelper.php';
-
-if (!defined('PHPUnit_MAIN_METHOD')) {
-    define('PHPUnit_MAIN_METHOD', 'Calendar_Frontend_CalDAVTest::main');
-}
-
-/**
  * Test class for Calendar_Frontend_CalDAV
+ * 
+ * @package     Calendar
  */
-class Calendar_Frontend_CalDAVTest extends PHPUnit_Framework_TestCase
+class Calendar_Frontend_CalDAVTest extends TestCase
 {
     /**
-     * @var array test objects
-     */
-    protected $objects = array();
-    
-    /**
-     * Runs the test methods of this class.
+     * Tree
      *
-     * @access public
-     * @static
+     * @var Sabre\DAV\ObjectTree
      */
-    public static function main()
-    {
-        $suite  = new PHPUnit_Framework_TestSuite('Tine 2.0 Calendar CalDAV Tests');
-        PHPUnit_TextUI_TestRunner::run($suite);
-    }
-
-    /**
-     * Sets up the fixture.
-     * This method is called before a test is executed.
-     *
-     * @access protected
-     */
-    protected function setUp()
-    {
-        Tinebase_TransactionManager::getInstance()->startTransaction(Tinebase_Core::getDb());
-        
-        $this->objects['initialContainer'] = Tinebase_Container::getInstance()->addContainer(new Tinebase_Model_Container(array(
-            'name'              => Tinebase_Record_Abstract::generateUID(),
-            'model'             => 'Calendar_Model_Event',
-            'type'              => Tinebase_Model_Container::TYPE_PERSONAL,
-            'backend'           => 'Sql',
-            'application_id'    => Tinebase_Application::getInstance()->getApplicationByName('Calendar')->getId(),
-        )));
-        
-        $this->objects['tasksContainer'] = Tinebase_Container::getInstance()->addContainer(new Tinebase_Model_Container(array(
-            'name'              => Tinebase_Record_Abstract::generateUID(),
-            'model'             => 'Tasks_Model_Task',
-            'type'              => Tinebase_Model_Container::TYPE_PERSONAL,
-            'backend'           => 'Sql',
-            'application_id'    => Tinebase_Application::getInstance()->getApplicationByName('Tasks')->getId(),
-        )));
-    }
-
-    /**
-     * Tears down the fixture
-     * This method is called after a test is executed.
-     *
-     * @access protected
-     */
-    protected function tearDown()
-    {
-        Tinebase_TransactionManager::getInstance()->rollBack();
-        $_SERVER['HTTP_USER_AGENT'] = '';
-    }
+    protected $_webdavTree;
     
     /**
      * test getChildren
      */
     public function testGetChildren()
     {
-        $collection = new Calendar_Frontend_CalDAV();
+        $collection = new Calendar_Frontend_WebDAV(\Sabre\CalDAV\Plugin::CALENDAR_ROOT . '/' . Tinebase_Core::getUser()->contact_id, true);
         
         $children = $collection->getChildren();
         
@@ -95,25 +39,45 @@ class Calendar_Frontend_CalDAVTest extends PHPUnit_Framework_TestCase
         
         return $children;
     }
-        
+    
     /**
      * test getChild
      */
     public function testGetChild()
     {
-        $collection = new Calendar_Frontend_CalDAV();
+        $collection = new Calendar_Frontend_WebDAV(\Sabre\CalDAV\Plugin::CALENDAR_ROOT . '/' . Tinebase_Core::getUser()->contact_id, true);
         
-        $child = $collection->getChild($this->objects['initialContainer']->getId());
+        $child = $collection->getChild($this->_getCalendarTestContainer()->getId());
         
         $this->assertTrue($child instanceof Calendar_Frontend_WebDAV_Container);
     }
     
     /**
+     * test get calendar inbox
+     */
+    public function testGetCalendarInbox()
+    {
+        $node = $this->_getWebDAVTree()->getNodeForPath('/calendars/' . Tinebase_Core::getUser()->contact_id . '/inbox');
+        
+        $this->assertInstanceOf('Calendar_Frontend_CalDAV_ScheduleInbox', $node, 'wrong child class');
+    }
+    
+    /**
+     * test get calendar outbox
+     */
+    public function testGetCalendarOutbox()
+    {
+        $node = $this->_getWebDAVTree()->getNodeForPath('/calendars/' . Tinebase_Core::getUser()->contact_id . '/outbox');
+        
+        $this->assertInstanceOf('\Sabre\CalDAV\Schedule\Outbox', $node, 'wrong child class');
+    }
+    
+    /**
      * test getChild
      */
     public function testGetTasksChild()
     {
-        $collection = new Calendar_Frontend_CalDAV();
+        $collection = new Calendar_Frontend_WebDAV(\Sabre\CalDAV\Plugin::CALENDAR_ROOT . '/' . Tinebase_Core::getUser()->contact_id, true);
         $children = $this->testGetChildren();
         
         $taskContainer = array_reduce($children, function($result, $container){
@@ -126,12 +90,14 @@ class Calendar_Frontend_CalDAVTest extends PHPUnit_Framework_TestCase
     
     /**
      * test testGetTasksChild (Mac_OS_X)
+     * 
+     * @backupGlobals enabled
      */
     public function testGetTasksChildMacOSX()
     {
         $_SERVER['HTTP_USER_AGENT'] = 'Mac_OS_X/10.9 (13A603) CalendarAgent/174';
         
-        $collection = new Calendar_Frontend_CalDAV();
+        $collection = new Calendar_Frontend_WebDAV(\Sabre\CalDAV\Plugin::CALENDAR_ROOT, true);
         $children = $this->testGetChildren();
     }
     
@@ -140,7 +106,7 @@ class Calendar_Frontend_CalDAVTest extends PHPUnit_Framework_TestCase
      */
     public function testCreateFile()
     {
-        $collection = new Calendar_Frontend_CalDAV();
+        $collection = new Calendar_Frontend_WebDAV(\Sabre\CalDAV\Plugin::CALENDAR_ROOT . '/' . Tinebase_Core::getUser()->contact_id, true);
         
         $this->setExpectedException('Sabre\DAV\Exception\Forbidden');
         
@@ -154,7 +120,7 @@ class Calendar_Frontend_CalDAVTest extends PHPUnit_Framework_TestCase
     {
         $randomName = Tinebase_Record_Abstract::generateUID();
         
-        $collection = new Calendar_Frontend_CalDAV();
+        $collection = new Calendar_Frontend_WebDAV(\Sabre\CalDAV\Plugin::CALENDAR_ROOT . '/' . Tinebase_Core::getUser()->contact_id, true);
         
         $collection->createDirectory($randomName);
         
@@ -162,4 +128,51 @@ class Calendar_Frontend_CalDAVTest extends PHPUnit_Framework_TestCase
         
         $this->assertTrue($container instanceof Tinebase_Model_Container);
     }
+
+    /**
+     * 
+     * @return \Sabre\DAV\ObjectTree
+     */
+    protected function _getWebDAVTree()
+    {
+        if (! $this->_webdavTree instanceof \Sabre\DAV\ObjectTree) {
+            $this->_webdavTree = new \Sabre\DAV\ObjectTree(new Tinebase_WebDav_Root());
+        }
+        
+        return $this->_webdavTree;
+    }
+    
+    /**
+     * 
+     * @return Tinebase_Model_Container
+     */
+    protected function _getCalendarTestContainer()
+    {
+        $container = Tinebase_Container::getInstance()->addContainer(new Tinebase_Model_Container(array(
+            'name'              => Tinebase_Record_Abstract::generateUID(),
+            'model'             => 'Calendar_Model_Event',
+            'type'              => Tinebase_Model_Container::TYPE_PERSONAL,
+            'backend'           => 'Sql',
+            'application_id'    => Tinebase_Application::getInstance()->getApplicationByName('Calendar')->getId(),
+        )));
+        
+        return $container;
+    }
+    
+    /**
+     * 
+     * @return Tinebase_Model_Container
+     */
+    protected function _getTasksTestContainer()
+    {
+        $container = Tinebase_Container::getInstance()->addContainer(new Tinebase_Model_Container(array(
+            'name'              => Tinebase_Record_Abstract::generateUID(),
+            'model'             => 'Tasks_Model_Task',
+            'type'              => Tinebase_Model_Container::TYPE_PERSONAL,
+            'backend'           => 'Sql',
+            'application_id'    => Tinebase_Application::getInstance()->getApplicationByName('Tasks')->getId(),
+        )));
+        
+        return $container;
+    }    
 }
index 58a2338..191ad3e 100644 (file)
@@ -37,13 +37,14 @@ class Felamimail_AllTests
         $imapConfig = Tinebase_Config::getInstance()->get(Tinebase_Config::IMAP, new Tinebase_Config_Struct())->toArray();
         if (! empty($imapConfig) && (isset($imapConfig['useSystemAccount']) || array_key_exists('useSystemAccount', $imapConfig)) && $imapConfig['useSystemAccount']) {
             $suite->addTestSuite('Felamimail_Controller_Cache_MessageTest');
-            $suite->addTestSuite('Felamimail_JsonTest');
+            $suite->addTestSuite('Felamimail_Frontend_JsonTest');
             $suite->addTestSuite('Felamimail_Controller_FolderTest');
             $suite->addTestSuite('Felamimail_Controller_MessageTest');
             $suite->addTestSuite('Felamimail_Controller_AccountTest');
             $suite->addTestSuite('Felamimail_Model_MessageTest');
             $suite->addTestSuite('Felamimail_Model_AccountTest');
         }
+        $suite->addTestSuite('Felamimail_Frontend_WebDAVTest');
         $suite->addTestSuite('Felamimail_Sieve_Backend_ScriptTest');
         
         return $suite;
similarity index 99%
rename from tests/tine20/Felamimail/JsonTest.php
rename to tests/tine20/Felamimail/Frontend/JsonTest.php
index 8680df4..3f58cd4 100644 (file)
@@ -9,18 +9,17 @@ use Sabre\DAV;
  * @license     http://www.gnu.org/licenses/agpl.html
  * @copyright   Copyright (c) 2009-2014 Metaways Infosystems GmbH (http://www.metaways.de)
  * @author      Philipp Schüle <p.schuele@metaways.de>
- * 
  */
 
 /**
  * Test helper
  */
-require_once dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'TestHelper.php';
+require_once dirname(dirname(dirname(__FILE__))) . DIRECTORY_SEPARATOR . 'TestHelper.php';
 
 /**
  * Test class for Tinebase_Group
  */
-class Felamimail_JsonTest extends PHPUnit_Framework_TestCase
+class Felamimail_Frontend_JsonTest extends PHPUnit_Framework_TestCase
 {
     /**
      * @var Felamimail_Frontend_Json
@@ -944,7 +943,7 @@ class Felamimail_JsonTest extends PHPUnit_Framework_TestCase
     public function testForwardMessageWithAttachment()
     {
         $testFolder = $this->_getFolder($this->_testFolderName);
-        $message = fopen(dirname(__FILE__) . '/files/multipart_related.eml', 'r');
+        $message = fopen(dirname(__FILE__) . '/../files/multipart_related.eml', 'r');
         Felamimail_Controller_Message::getInstance()->appendMessage($testFolder, $message);
         
         $subject = 'Tine 2.0 bei Metaways - Verbessurngsvorschlag';
@@ -1118,7 +1117,7 @@ class Felamimail_JsonTest extends PHPUnit_Framework_TestCase
     public function testMessageWithInvalidICS()
     {
         $inbox = $this->_getFolder('INBOX');
-        $mailAsString = file_get_contents(dirname(__FILE__) . '/files/invalidimip.eml');
+        $mailAsString = file_get_contents(dirname(__FILE__) . '/../files/invalidimip.eml');
         Felamimail_Controller_Message::getInstance()->appendMessage($inbox, $mailAsString);
         
         $this->_foldersToClear = array('INBOX');
@@ -1341,7 +1340,7 @@ class Felamimail_JsonTest extends PHPUnit_Framework_TestCase
         $path = '/webdav/Felamimail/shared/Vacation Templates';
         $node = $webdavRoot->getNodeForPath($path);
         $this->_pathsToDelete[] = $path . '/' . $this->_sieveVacationTemplateFile;
-        $node->createFile($this->_sieveVacationTemplateFile, fopen(dirname(__FILE__) . '/files/' . $this->_sieveVacationTemplateFile, 'r'));
+        $node->createFile($this->_sieveVacationTemplateFile, fopen(dirname(__FILE__) . '/../files/' . $this->_sieveVacationTemplateFile, 'r'));
     }
     
     /**
diff --git a/tests/tine20/Felamimail/Frontend/WebDAVTest.php b/tests/tine20/Felamimail/Frontend/WebDAVTest.php
new file mode 100644 (file)
index 0000000..ac5b99f
--- /dev/null
@@ -0,0 +1,167 @@
+<?php
+/**
+ * Tine 2.0 - http://www.tine20.org
+ * 
+ * @package     Felamimail
+ * @license     http://www.gnu.org/licenses/agpl.html
+ * @copyright   Copyright (c) 2014-2014 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @author      Lars Kneschke <l.kneschke@metaways.de>
+ */
+
+/**
+ * Test class for Felamimail WebDAV frontend
+ * 
+ * @package     Felamimail
+ */
+class Felamimail_Frontend_WebDAVTest extends TestCase
+{
+    /**
+     * Tree
+     *
+     * @var Sabre\DAV\ObjectTree
+     */
+    protected $_webdavTree;
+    
+    /**
+     * testgetNodeForPath
+     */
+    public function testgetNodeForPath()
+    {
+        $node = $this->_getWebDAVTree()->getNodeForPath(null);
+        
+        $this->assertInstanceOf('Tinebase_WebDav_Root', $node, 'wrong node class');
+        
+        $children = $node->getChildren();
+        
+        $this->setExpectedException('Sabre\DAV\Exception\Forbidden');
+        
+        $this->_getWebDAVTree()->delete('/');
+    }
+    
+    public function testgetNodeForPath_webdav()
+    {
+        $node = $this->_getWebDAVTree()->getNodeForPath('/webdav');
+        
+        $this->assertInstanceOf('\Sabre\DAV\SimpleCollection', $node, 'wrong node class');
+        
+        $this->assertEquals('webdav', $node->getName());
+        
+        $children = $node->getChildren();
+        
+        $this->assertInstanceOf('Tinebase_WebDav_Collection_AbstractContainerTree', $children[0], 'wrong child class');
+        
+        $this->setExpectedException('Sabre\DAV\Exception\Forbidden');
+        
+        $this->_getWebDAVTree()->delete('/webdav');
+    }
+    
+    public function testgetNodeForPath_webdav_felamimail()
+    {
+        $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Felamimail');
+        
+        $this->assertInstanceOf('Felamimail_Frontend_WebDAV', $node, 'wrong node class');
+        
+        $this->assertEquals('Felamimail', $node->getName());
+        
+        $children = $node->getChildren();
+        
+        $this->assertEquals(1, count($children));
+        $this->assertInstanceOf('Felamimail_Frontend_WebDAV', $children[0], 'wrong node class');
+        
+        $this->setExpectedException('Sabre\DAV\Exception\Forbidden');
+        
+        $this->_getWebDAVTree()->delete('/webdav/Felamimail');
+    }
+    
+    public function testgetNodeForPath_webdav_felamimail_personal()
+    {
+        $this->setExpectedException('Sabre\DAV\Exception\NotFound');
+        
+        $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Felamimail/personal');
+    }
+    
+    public function testgetNodeForPath_webdav_felamimail_shared()
+    {
+        $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Felamimail/shared');
+        
+        $this->assertInstanceOf('Felamimail_Frontend_WebDAV', $node, 'wrong node class');
+        
+        $this->assertEquals('shared', $node->getName());
+        
+        $children = $node->getChildren();
+        
+        $this->setExpectedException('Sabre\DAV\Exception\Forbidden');
+        
+        $this->_getWebDAVTree()->delete('/webdav/Felamimail/shared');
+    }
+    
+    /**
+     * testgetNodeForPath_webdav_felamimail_shared_unittestdirectory
+     * 
+     * @return Felamimail_Frontend_WebDAV_Container
+     */
+    public function testgetNodeForPath_webdav_felamimail_shared_unittestdirectory()
+    {
+        $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Felamimail/shared');
+        
+        $node->createDirectory('unittestdirectory');
+        
+        $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Felamimail/shared/unittestdirectory');
+        
+        $this->assertInstanceOf('Felamimail_Frontend_WebDAV_Container', $node, 'wrong node class');
+        
+        $this->assertEquals('unittestdirectory', $node->getName());
+        
+        $children = $node->getChildren();
+        
+        $properties = $node->getProperties(array());
+        
+        return $node;
+    }
+    
+    /**
+     * @return Felamimail_Frontend_WebDAV_File
+     */
+    public function testgetNodeForPath_webdav_felamimail_shared_unittestdirectory_file()
+    {
+        $parent = $this->testgetNodeForPath_webdav_felamimail_shared_unittestdirectory();
+        
+        $etag = $parent->createFile('tine_logo.png', fopen(dirname(__FILE__) . '/../../Tinebase/files/tine_logo.png', 'r'));
+        
+        $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Felamimail/shared/unittestdirectory/tine_logo.png');
+        
+        $this->assertInstanceOf('Felamimail_Frontend_WebDAV_File', $node, 'wrong node class');
+        $this->assertTrue(is_resource($node->get()));
+        $this->assertEquals('tine_logo.png', $node->getName());
+        $this->assertEquals(7246, $node->getSize());
+        $this->assertEquals('image/png', $node->getContentType());
+        $this->assertEquals('"7424e2c16388bf388af1c4fe44c1dd67d31f468b"', $node->getETag());
+        $this->assertTrue(preg_match('/"\w+"/', $etag) === 1);
+        
+        return $node;
+    }
+    
+    public function testDeleteFile()
+    {
+        $node = $this->testgetNodeForPath_webdav_felamimail_shared_unittestdirectory_file();
+    
+        $this->_getWebDAVTree()->delete('/webdav/Felamimail/shared/unittestdirectory/tine_logo.png');
+    
+        $this->setExpectedException('Sabre\DAV\Exception\NotFound');
+        
+        $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Felamimail/shared/unittestdirectory/tine_logo.png');
+    }
+    
+    /**
+     * 
+     * @return \Sabre\DAV\ObjectTree
+     */
+    protected function _getWebDAVTree()
+    {
+        if (! $this->_webdavTree instanceof \Sabre\DAV\ObjectTree) {
+            $this->_webdavTree = new \Sabre\DAV\ObjectTree(new Tinebase_WebDav_Root());
+        }
+        
+        return $this->_webdavTree;
+    }
+}
index d22e9cd..4d8e966 100644 (file)
@@ -1,38 +1,21 @@
 <?php
-
-use Sabre\DAV;
-
 /**
  * Tine 2.0 - http://www.tine20.org
  * 
- * @package     Tinebase
+ * @package     Filemanager
  * @license     http://www.gnu.org/licenses/agpl.html
- * @copyright   Copyright (c) 2010-2010 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright   Copyright (c) 2010-2014 Metaways Infosystems GmbH (http://www.metaways.de)
  * @author      Lars Kneschke <l.kneschke@metaways.de>
  */
 
 /**
- * Test helper
- */
-require_once dirname(dirname(dirname(__FILE__))) . DIRECTORY_SEPARATOR . 'TestHelper.php';
-
-if (!defined('PHPUnit_MAIN_METHOD')) {
-    define('PHPUnit_MAIN_METHOD', 'Filemanager_Frontend_WebDAVTest::main');
-}
-
-/**
  * Test class for Filemanager_Frontend_Tree
  * 
- * @package     Tinebase
+ * @package     Filemanager
  */
-class Filemanager_Frontend_WebDAVTest extends PHPUnit_Framework_TestCase
+class Filemanager_Frontend_WebDAVTest extends TestCase
 {
     /**
-     * @var array test objects
-     */
-    protected $objects = array();
-
-    /**
      * Tree
      *
      * @var Sabre\DAV\ObjectTree
@@ -40,98 +23,59 @@ class Filemanager_Frontend_WebDAVTest extends PHPUnit_Framework_TestCase
     protected $_webdavTree;
     
     /**
-     * Runs the test methods of this class.
-     *
-     * @access public
-     * @static
-     */
-    public static function main()
-    {
-        $suite  = new PHPUnit_Framework_TestSuite('Tine 2.0 webdav tree tests');
-        PHPUnit_TextUI_TestRunner::run($suite);
-    }
-
-    /**
-     * Sets up the fixture.
-     * This method is called before a test is executed.
-     *
-     * @access protected
-     */
-    protected function setUp()
-    {
-        Tinebase_TransactionManager::getInstance()->startTransaction(Tinebase_Core::getDb());
-        
-        $this->_webdavTree = new DAV\ObjectTree(new Tinebase_WebDav_Root());
-    }
-
-    /**
-     * Tears down the fixture
-     * This method is called after a test is executed.
-     *
-     * @access protected
-     */
-    protected function tearDown()
-    {
-        Tinebase_TransactionManager::getInstance()->rollBack();
-        
-        unset($_SERVER['HTTP_OC_CHUNKED']);
-        unset($_SERVER['CONTENT_LENGTH']);
-    }
-    
-    /**
      * testgetNodeForPath
      */
     public function testgetNodeForPath()
     {
-        $node = $this->_webdavTree->getNodeForPath(null);
+        $node = $this->_getWebDAVTree()->getNodeForPath(null);
         
-        $this->assertTrue($node instanceof Tinebase_WebDav_Root, 'wrong node class');
+        $this->assertInstanceOf('Tinebase_WebDav_Root', $node, 'wrong node class');
         
         $children = $node->getChildren();
         
         $this->setExpectedException('Sabre\DAV\Exception\Forbidden');
         
-        $this->_webdavTree->delete('/');
+        $this->_getWebDAVTree()->delete('/');
     }
     
     public function testgetNodeForPath_webdav()
     {
-        $node = $this->_webdavTree->getNodeForPath('/webdav');
+        $node = $this->_getWebDAVTree()->getNodeForPath('/webdav');
         
-        $this->assertTrue($node instanceof DAV\SimpleCollection, 'wrong node class');
+        $this->assertInstanceOf('\Sabre\DAV\SimpleCollection', $node, 'wrong node class');
         $this->assertEquals('webdav', $node->getName());
         
         $children = $node->getChildren();
         
-        $this->assertTrue($children[0] instanceof Tinebase_WebDav_Collection_Abstract, 'wrong child class');
+        $this->assertInstanceOf('Tinebase_WebDav_Collection_AbstractContainerTree', $children[0], 'wrong child class');
         
         $this->setExpectedException('Sabre\DAV\Exception\Forbidden');
         
-        $this->_webdavTree->delete('/webdav');
+        $this->_getWebDAVTree()->delete('/webdav');
     }
     
     public function testgetNodeForPath_webdav_filemanager()
     {
-        $node = $this->_webdavTree->getNodeForPath('/webdav/Filemanager');
+        $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Filemanager');
         
-        $this->assertTrue($node instanceof Filemanager_Frontend_WebDAV, 'wrong node class');
+        $this->assertInstanceOf('Filemanager_Frontend_WebDAV', $node, 'wrong node class');
         $this->assertEquals('Filemanager', $node->getName());
         
         $children = $node->getChildren();
         
         $this->assertEquals(2, count($children));
-        $this->assertEquals('Filemanager_Frontend_WebDAV', get_class($children[0]), 'wrong child class');
+        $this->assertInstanceOf('Filemanager_Frontend_WebDAV', $children[0], 'wrong node class');
         
         $this->setExpectedException('Sabre\DAV\Exception\Forbidden');
         
-        $this->_webdavTree->delete('/webdav/Filemanager');
+        $this->_getWebDAVTree()->delete('/webdav/Filemanager');
     }
     
-    public function testgetNodeForPath_webdav_filemanager_personal()
+    public function ttestgetNodeForPath_webdav_filemanager_personal()
     {
-        $node = $this->_webdavTree->getNodeForPath('/webdav/Filemanager/personal');
+        $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Filemanager/personal');
         
-        $this->assertTrue($node instanceof Filemanager_Frontend_WebDAV, 'wrong node class');
+        $this->assertInstanceOf('Filemanager_Frontend_WebDAV', $node, 'wrong node class');
         $this->assertEquals('personal', $node->getName());
         
         $children = $node->getChildren();
@@ -141,65 +85,65 @@ class Filemanager_Frontend_WebDAVTest extends PHPUnit_Framework_TestCase
         
         $this->setExpectedException('Sabre\DAV\Exception\Forbidden');
         
-        $this->_webdavTree->delete('/webdav/Filemanager/personal');
+        $this->_getWebDAVTree()->delete('/webdav/Filemanager/personal');
     }
     
-    public function testgetNodeForPath_webdav_filemanager_personal_currentuser()
+    public function testgetNodeForPath_webdav_filemanager_currentuser()
     {
-        $node = $this->_webdavTree->getNodeForPath('/webdav/Filemanager/personal/' . Tinebase_Core::getUser()->accountLoginName);
+        $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Filemanager/' . Tinebase_Core::getUser()->accountDisplayName);
         
-        $this->assertTrue($node instanceof Filemanager_Frontend_WebDAV, 'wrong node class');
-        $this->assertEquals(Tinebase_Core::getUser()->accountLoginName, $node->getName());
+        $this->assertInstanceOf('Filemanager_Frontend_WebDAV', $node, 'wrong node class');
+        $this->assertEquals(Tinebase_Core::getUser()->accountDisplayName, $node->getName());
         
         $children = $node->getChildren();
         
         $this->assertGreaterThanOrEqual(1, count($children));
-        $this->assertTrue($children[0] instanceof Filemanager_Frontend_WebDAV_Container, 'wrong child class');
+        $this->assertInstanceOf('Filemanager_Frontend_WebDAV_Container', $children[0], 'wrong node class');
         
         $this->setExpectedException('Sabre\DAV\Exception\Forbidden');
         
-        $this->_webdavTree->delete('/webdav/Filemanager/personal/' . Tinebase_Core::getUser()->accountLoginName);
+        $this->_getWebDAVTree()->delete('/webdav/Filemanager/' . Tinebase_Core::getUser()->accountDisplayName);
     }
     
     /**
      * @return Filemanager_Frontend_WebDAV_Directory
      */
-    public function testgetNodeForPath_webdav_filemanager_personal_currentuser_unittestdirectory()
+    public function testgetNodeForPath_webdav_filemanager_currentuser_unittestdirectory()
     {
-        $node = $this->_webdavTree->getNodeForPath('/webdav/Filemanager/personal/' . Tinebase_Core::getUser()->accountLoginName);
+        $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Filemanager/' . Tinebase_Core::getUser()->accountDisplayName);
         
         $node->createDirectory('unittestdirectory');
         
-        $node = $this->_webdavTree->getNodeForPath('/webdav/Filemanager/personal/' . Tinebase_Core::getUser()->accountLoginName .'/unittestdirectory');
+        $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Filemanager/' . Tinebase_Core::getUser()->accountDisplayName .'/unittestdirectory');
         
-        $this->assertTrue($node instanceof Filemanager_Frontend_WebDAV_Container, 'wrong node class');
+        $this->assertInstanceOf('Filemanager_Frontend_WebDAV_Container', $node, 'wrong node class');
         $this->assertEquals('unittestdirectory', $node->getName());
         
-        $children = $this->_webdavTree->getChildren('/webdav/Filemanager/personal/' . Tinebase_Core::getUser()->accountLoginName);
+        $children = $this->_getWebDAVTree()->getChildren('/webdav/Filemanager/' . Tinebase_Core::getUser()->accountDisplayName);
         foreach ($children as $node) {
             $names[] = $node->getName();
         }
         $this->assertContains('unittestdirectory', $names);
         
-        $this->_webdavTree->delete('/webdav/Filemanager/personal/' . Tinebase_Core::getUser()->accountLoginName .'/unittestdirectory');
+        $this->_getWebDAVTree()->delete('/webdav/Filemanager/' . Tinebase_Core::getUser()->accountDisplayName .'/unittestdirectory');
         
         $this->setExpectedException('Sabre\DAV\Exception\NotFound');
         
-        $this->_webdavTree->getNodeForPath('/webdav/Filemanager/personal/' . Tinebase_Core::getUser()->accountLoginName .'/unittestdirectory');
+        $this->_getWebDAVTree()->getNodeForPath('/webdav/Filemanager/' . Tinebase_Core::getUser()->accountDisplayName .'/unittestdirectory');
     }
     
     public function testgetNodeForPath_webdav_filemanager_shared()
     {
-        $node = $this->_webdavTree->getNodeForPath('/webdav/Filemanager/shared');
+        $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Filemanager/shared');
         
-        $this->assertTrue($node instanceof Filemanager_Frontend_WebDAV, 'wrong node class');
+        $this->assertInstanceOf('Filemanager_Frontend_WebDAV', $node, 'wrong node class');
         $this->assertEquals('shared', $node->getName());
         
         $children = $node->getChildren();
         
         $this->setExpectedException('Sabre\DAV\Exception\Forbidden');
         
-        $this->_webdavTree->delete('/webdav/Filemanager/shared');
+        $this->_getWebDAVTree()->delete('/webdav/Filemanager/shared');
     }
     
     /**
@@ -209,13 +153,13 @@ class Filemanager_Frontend_WebDAVTest extends PHPUnit_Framework_TestCase
      */
     public function testgetNodeForPath_webdav_filemanager_shared_unittestdirectory()
     {
-        $node = $this->_webdavTree->getNodeForPath('/webdav/Filemanager/shared');
+        $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Filemanager/shared');
         
         $node->createDirectory('unittestdirectory');
         
-        $node = $this->_webdavTree->getNodeForPath('/webdav/Filemanager/shared/unittestdirectory');
+        $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Filemanager/shared/unittestdirectory');
         
-        $this->assertTrue($node instanceof Filemanager_Frontend_WebDAV_Container, 'wrong node class');
+        $this->assertInstanceOf('Filemanager_Frontend_WebDAV_Container', $node, 'wrong node class');
         $this->assertEquals('unittestdirectory', $node->getName());
         
         $children = $node->getChildren();
@@ -234,9 +178,9 @@ class Filemanager_Frontend_WebDAVTest extends PHPUnit_Framework_TestCase
         
         $etag = $parent->createFile('tine_logo.png', fopen(dirname(__FILE__) . '/../../Tinebase/files/tine_logo.png', 'r'));
         
-        $node = $this->_webdavTree->getNodeForPath('/webdav/Filemanager/shared/unittestdirectory/tine_logo.png');
+        $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Filemanager/shared/unittestdirectory/tine_logo.png');
         
-        $this->assertTrue($node instanceof Filemanager_Frontend_WebDAV_File, 'wrong node class: ' . get_class($node));
+        $this->assertInstanceOf('Filemanager_Frontend_WebDAV_File', $node, 'wrong node class');
         $this->assertTrue(is_resource($node->get()));
         $this->assertEquals('tine_logo.png', $node->getName());
         $this->assertEquals(7246, $node->getSize());
@@ -260,6 +204,7 @@ class Filemanager_Frontend_WebDAVTest extends PHPUnit_Framework_TestCase
     /**
      * test chunked upload from OwnCloud clients
      * 
+     * @backupGlobals enabled
      * @return Filemanager_Frontend_WebDAV_File
      */
     public function testOwnCloudChunkedUpload()
@@ -293,10 +238,10 @@ class Filemanager_Frontend_WebDAVTest extends PHPUnit_Framework_TestCase
         fclose($fileStream);
         
         // retrieve final node
-        $this->_webdavTree->markDirty('/webdav/Filemanager/shared/unittestdirectory/tine_logo.png');
-        $node = $this->_webdavTree->getNodeForPath('/webdav/Filemanager/shared/unittestdirectory/tine_logo.png');
+        $this->_getWebDAVTree()->markDirty('/webdav/Filemanager/shared/unittestdirectory/tine_logo.png');
+        $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Filemanager/shared/unittestdirectory/tine_logo.png');
         
-        $this->assertTrue($node instanceof Filemanager_Frontend_WebDAV_File, 'wrong node class: ' . get_class($node));
+        $this->assertInstanceOf('Filemanager_Frontend_WebDAV_File', $node, 'wrong node class');
         $this->assertTrue(is_resource($node->get()));
         $this->assertEquals('tine_logo.png', $node->getName());
         $this->assertEquals(7246, $node->getSize());
@@ -328,10 +273,10 @@ class Filemanager_Frontend_WebDAVTest extends PHPUnit_Framework_TestCase
         fclose($tempStream);
         
         // retrieve final node
-        $this->_webdavTree->markDirty('/webdav/Filemanager/shared/unittestdirectory/tine_logo.png');
-        $node = $this->_webdavTree->getNodeForPath('/webdav/Filemanager/shared/unittestdirectory/tine_logo.png');
+        $this->_getWebDAVTree()->markDirty('/webdav/Filemanager/shared/unittestdirectory/tine_logo.png');
+        $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Filemanager/shared/unittestdirectory/tine_logo.png');
         
-        $this->assertTrue($node instanceof Filemanager_Frontend_WebDAV_File, 'wrong node class: ' . get_class($node));
+        $this->assertInstanceOf('Filemanager_Frontend_WebDAV_File', $node, 'wrong node class');
         $this->assertTrue(is_resource($node->get()));
         $this->assertEquals('tine_logo.png', $node->getName());
         $this->assertEquals(7258, $node->getSize());
@@ -346,11 +291,11 @@ class Filemanager_Frontend_WebDAVTest extends PHPUnit_Framework_TestCase
     {
         $node = $this->testgetNodeForPath_webdav_filemanager_shared_unittestdirectory_file();
     
-        $this->_webdavTree->delete('/webdav/Filemanager/shared/unittestdirectory/tine_logo.png');
+        $this->_getWebDAVTree()->delete('/webdav/Filemanager/shared/unittestdirectory/tine_logo.png');
     
         $this->setExpectedException('Sabre\DAV\Exception\NotFound');
         
-        $node = $this->_webdavTree->getNodeForPath('/webdav/Filemanager/shared/unittestdirectory/tine_logo.png');
+        $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Filemanager/shared/unittestdirectory/tine_logo.png');
     }
     
     /**
@@ -362,9 +307,9 @@ class Filemanager_Frontend_WebDAVTest extends PHPUnit_Framework_TestCase
     
         $file = $parent->createDirectory('directory');
     
-        $node = $this->_webdavTree->getNodeForPath('/webdav/Filemanager/shared/unittestdirectory/directory');
+        $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Filemanager/shared/unittestdirectory/directory');
     
-        $this->assertTrue($node instanceof Filemanager_Frontend_WebDAV_Directory, 'wrong node class');
+        $this->assertInstanceOf('Filemanager_Frontend_WebDAV_Directory', $node, 'wrong node class');
         $this->assertEquals('directory', $node->getName());
             
         return $node;
@@ -374,25 +319,33 @@ class Filemanager_Frontend_WebDAVTest extends PHPUnit_Framework_TestCase
     {
         $this->setExpectedException('Sabre\DAV\Exception\NotFound');
         
-        $node = $this->_webdavTree->getNodeForPath('/webdav/invalidApplication');
+        $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/invalidApplication');
     }
     
     public function testgetNodeForPath_invalidContainerType()
     {
         $this->setExpectedException('Sabre\DAV\Exception\NotFound');
         
-        $node = $this->_webdavTree->getNodeForPath('/webdav/Filemanager/invalidContainerType');
+        $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Filemanager/invalidContainerType');
     }
     
     public function testgetNodeForPath_invalidFolder()
     {
         $this->setExpectedException('Sabre\DAV\Exception\NotFound');
         
-        $node = $this->_webdavTree->getNodeForPath('/webdav/Filemanager/shared/invalidContainer');
-    }    
-}        
+        $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Filemanager/shared/invalidContainer');
+    }
     
-
-if (PHPUnit_MAIN_METHOD == 'Filemanager_Frontend_WebDAVTest::main') {
-    Filemanager_Frontend_WebDAVTest::main();
+    /**
+     * 
+     * @return \Sabre\DAV\ObjectTree
+     */
+    protected function _getWebDAVTree()
+    {
+        if (! $this->_webdavTree instanceof \Sabre\DAV\ObjectTree) {
+            $this->_webdavTree = new \Sabre\DAV\ObjectTree(new Tinebase_WebDav_Root());
+        }
+        
+        return $this->_webdavTree;
+    }
 }
index 2afe534..26bba0a 100644 (file)
  */
 class Tinebase_Frontend_WebDAV_RecordTest extends TestCase
 {
+     /**
+      * Tree
+      *
+      * @var Sabre\DAV\ObjectTree
+      */
+    protected $_webdavTree;
+    
     /**
      * testDownloadAttachment
      */
@@ -34,9 +41,21 @@ class Tinebase_Frontend_WebDAV_RecordTest extends TestCase
         $this->assertTrue(isset($savedEvent->attachments) && count($savedEvent->attachments) === 1);
         
         // try to fetch attachment of event
-        $recordCollection = new Tinebase_Frontend_WebDAV_Record('Calendar/records/Calendar_Model_Event/' . $savedEvent->getId());
-        $file = $recordCollection->getChild($tempFile->name);
-        $this->assertEquals('text/plain', $file->getContentType());
-        $this->assertEquals(17, $file->getSize());
+        $node = $this->_getWebDAVTree()->getNodeForPath('/webdav/Calendar/records/Calendar_Model_Event/' . $savedEvent->getId() . '/' . $tempFile->name);
+        $this->assertEquals('text/plain', $node->getContentType());
+        $this->assertEquals(17, $node->getSize());
+    }
+    
+    /**
+     * 
+     * @return \Sabre\DAV\ObjectTree
+     */
+    protected function _getWebDAVTree()
+    {
+        if (! $this->_webdavTree instanceof \Sabre\DAV\ObjectTree) {
+            $this->_webdavTree = new \Sabre\DAV\ObjectTree(new Tinebase_WebDav_Root());
+        }
+        
+        return $this->_webdavTree;
     }
 }
index da5396f..a887099 100644 (file)
@@ -5,7 +5,7 @@
  * @package     Tinebase
  * @subpackage  Frontend
  * @license     http://www.gnu.org/licenses/agpl.html
- * @copyright   Copyright (c) 2013-2013 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright   Copyright (c) 2013-2014 Metaways Infosystems GmbH (http://www.metaways.de)
  * @author      Lars Kneschke <l.kneschke@metaways.de>
  */
 
@@ -85,7 +85,7 @@ class Tinebase_WebDav_Plugin_OwnCloudTest extends TestCase
 
         $request = new Sabre\HTTP\Request(array(
             'REQUEST_METHOD' => 'PROPFIND',
-            'REQUEST_URI'    => '/remote.php/webdav/personal/' . Tinebase_Core::getUser()->accountLoginName,
+            'REQUEST_URI'    => '/remote.php/webdav/' . Tinebase_Core::getUser()->accountDisplayName,
             'HTTP_DEPTH'     => '0',
         ));
         $request->setBody($body);
index 194191b..db9cbf8 100644 (file)
@@ -97,7 +97,7 @@ class Tinebase_WebDav_PrincipalBackendTest extends TestCase
         $this->assertGreaterThanOrEqual(1, count($groupMemberships));
     }
     
-    public function testSearchPrincipals()
+    public function testSearchPrincipalsByEMail()
     {
         $uris = $this->_backend->searchPrincipals(Tinebase_WebDav_PrincipalBackend::PREFIX_USERS, array(
             '{http://sabredav.org/ns}email-address' => Tinebase_Core::getUser()->accountEmailAddress)
@@ -106,4 +106,64 @@ class Tinebase_WebDav_PrincipalBackendTest extends TestCase
         $this->assertEquals(1, count($uris), 'could not find user by email address ' . Tinebase_Core::getUser()->accountEmailAddress);
         $this->assertContains('principals/users/' . Tinebase_Core::getUser()->contact_id, $uris);
     }
+    
+    public function testSearchPrincipalsByFirstName()
+    {
+        $uris = $this->_backend->searchPrincipals(Tinebase_WebDav_PrincipalBackend::PREFIX_USERS, array(
+            '{' . \Sabre\CalDAV\Plugin::NS_CALENDARSERVER . '}first-name' => Tinebase_Core::getUser()->accountFirstName)
+        );
+        
+        $this->assertEquals(1, count($uris), 'could not find user by email address ' . Tinebase_Core::getUser()->accountEmailAddress);
+        $this->assertContains('principals/users/' . Tinebase_Core::getUser()->contact_id, $uris);
+    }
+    
+    public function testSearchPrincipalsByLastName()
+    {
+        $uris = $this->_backend->searchPrincipals(Tinebase_WebDav_PrincipalBackend::PREFIX_USERS, array(
+            '{' . \Sabre\CalDAV\Plugin::NS_CALENDARSERVER . '}last-name' => Tinebase_Core::getUser()->accountLastName)
+        );
+        
+        $this->assertEquals(1, count($uris), 'could not find user by email address ' . Tinebase_Core::getUser()->accountEmailAddress);
+        $this->assertContains('principals/users/' . Tinebase_Core::getUser()->contact_id, $uris);
+    }
+    
+    public function testGetPrincipalByProxyWritePath()
+    {
+        $principal = $this->_backend->getPrincipalByPath(Tinebase_WebDav_PrincipalBackend::PREFIX_USERS . '/' . Tinebase_Core::getUser()->contact_id . '/calendar-proxy-write');
+        
+        //var_dump($principal);
+        
+        $this->assertEquals(Tinebase_WebDav_PrincipalBackend::PREFIX_USERS . '/' . Tinebase_Core::getUser()->contact_id . '/calendar-proxy-write', $principal['uri']);
+    }
+    
+    public function testGetMemberSetUser()
+    {
+        $groupMemberships = $this->_backend->getGroupMemberSet(Tinebase_WebDav_PrincipalBackend::PREFIX_USERS . '/' . Tinebase_Core::getUser()->contact_id);
+        
+        //var_dump($groupMemberships);
+        
+        $this->assertEquals(0, count($groupMemberships));
+    }
+    
+    public function testGetMemberSetGroup()
+    {
+        $list = Tinebase_Group::getInstance()->getGroupById(Tinebase_Core::getUser()->accountPrimaryGroup);
+        
+        $groupMemberships = $this->_backend->getGroupMemberSet(Tinebase_WebDav_PrincipalBackend::PREFIX_GROUPS . '/' . $list->list_id);
+        
+        //var_dump($groupMemberships);
+        
+        $this->assertGreaterThanOrEqual(1, count($groupMemberships));
+    }
+
+    public function testGetMemberSetProxyRead()
+    {
+        $this->markTestIncomplete('needs access to other accounts calendar');
+        
+        $groupMemberships = $this->_backend->getGroupMemberSet(Tinebase_WebDav_PrincipalBackend::PREFIX_USERS . '/' . Tinebase_Core::getUser()->contact_id . '/calendar-proxy-read');
+        
+        //var_dump($groupMemberships);
+        
+        $this->assertGreaterThanOrEqual(1, count($groupMemberships));
+    }
 }
index 451289b..af1b5e2 100644 (file)
@@ -5,32 +5,29 @@
  * @package     Tinebase
  * @subpackage  WebDav
  * @license     http://www.gnu.org/licenses/agpl.html
- * @copyright   Copyright (c) 2012-2013 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright   Copyright (c) 2012-2014 Metaways Infosystems GmbH (http://www.metaways.de)
  * @author      Lars Kneschke <l.kneschke@metaways.de>
  */
 
 /**
- * Test helper
- */
-require_once dirname(dirname(dirname(__FILE__))) . DIRECTORY_SEPARATOR . 'TestHelper.php';
-
-/**
  * Test class for Tinebase_WebDav_Root
  * 
  * @package     Tinebase
  * @subpackage  WebDav
  */
-class Tinebase_WebDav_RootTest extends PHPUnit_Framework_TestCase
+class Tinebase_WebDav_RootTest extends TestCase
 {
     /**
-     * @var array test objects
+     * Tree
+     *
+     * @var Sabre\DAV\ObjectTree
      */
-    protected $objects = array();
+    protected $_webdavTree;
     
     /**
-     * @var Tinebase_WebDav_Root
+     * @var array test objects
      */
-    protected $_rootNode;
+    protected $objects = array();
     
     /**
      * Runs the test methods of this class.
@@ -45,32 +42,11 @@ class Tinebase_WebDav_RootTest extends PHPUnit_Framework_TestCase
     }
 
     /**
-     * Sets up the fixture.
-     * This method is called before a test is executed.
-     *
-     * @access protected
-     */
-    protected function setUp()
-    {
-        $this->_rootNode = new Tinebase_WebDav_Root();
-    }
-    
-    /**
-     * Tears down the fixture
-     * This method is called after a test is executed.
-     *
-     * @access protected
-     */
-    protected function tearDown()
-    {
-    }
-    
-    /**
      * test getChildren method
      */
     public function testGetChildren()
     {
-        $children = $this->_rootNode->getChildren();
+        $children = $this->_getWebDAVTree()->getNodeForPath(null)->getChildren();
         
         $this->assertEquals(6, count($children));
     }
@@ -80,11 +56,11 @@ class Tinebase_WebDav_RootTest extends PHPUnit_Framework_TestCase
      */
     public function testGetLastModified()
     {
-        $remoteWebDav = $this->_rootNode->getChild('remote.php')->getChild('webdav');
+        $remoteWebDav = $this->_getWebDAVTree()->getNodeForPath('/remote.php/webdav');
         
         $this->assertNotEmpty($remoteWebDav->getLastModified());
         
-        $personal = $remoteWebDav->getChild('personal');
+        $personal = $remoteWebDav->getChild(Tinebase_Core::getUser()->accountDisplayName);
         
         $this->assertNotEmpty($personal->getLastModified());
         
@@ -100,15 +76,11 @@ class Tinebase_WebDav_RootTest extends PHPUnit_Framework_TestCase
      */
     public function testGetETag()
     {
-        $remoteWebDav = $this->_rootNode->getChild('remote.php')->getChild('webdav');
+        $remoteWebDav = $this->_getWebDAVTree()->getNodeForPath('/remote.php/webdav');
         $properties = $remoteWebDav->getProperties(array('{DAV:}getetag'));
         $this->assertArrayHasKey('{DAV:}getetag', $properties);
         
-        $personal = $remoteWebDav->getChild('personal');
-        $properties = $personal->getProperties(array('{DAV:}getetag'));
-        $this->assertArrayHasKey('{DAV:}getetag', $properties);
-        
-        $currentUser = $personal->getChild(Tinebase_Core::getUser()->accountLoginName);
+        $currentUser = $remoteWebDav->getChild(Tinebase_Core::getUser()->accountDisplayName);
         $properties = $currentUser->getProperties(array('{DAV:}getetag'));
         $this->assertArrayHasKey('{DAV:}getetag', $properties);
         
@@ -117,4 +89,17 @@ class Tinebase_WebDav_RootTest extends PHPUnit_Framework_TestCase
             $this->assertArrayHasKey('{DAV:}getetag', $properties);
         }
     }
+    
+    /**
+     * 
+     * @return \Sabre\DAV\ObjectTree
+     */
+    protected function _getWebDAVTree()
+    {
+        if (! $this->_webdavTree instanceof \Sabre\DAV\ObjectTree) {
+            $this->_webdavTree = new \Sabre\DAV\ObjectTree(new Tinebase_WebDav_Root());
+        }
+        
+        return $this->_webdavTree;
+    }
 }
diff --git a/tine20/Addressbook/Frontend/CardDAV.php b/tine20/Addressbook/Frontend/CardDAV.php
deleted file mode 100644 (file)
index 33b8aad..0000000
+++ /dev/null
@@ -1,360 +0,0 @@
-<?php
-
-use Sabre\DAV;
-use Sabre\DAVACL;
-
-/**
- * Tine 2.0
- *
- * @package     Addressbook
- * @subpackage  Frontend
- * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
- * @author      Lars Kneschke <l.kneschke@metaways.de>
- * @copyright   Copyright (c) 2011-2013 Metaways Infosystems GmbH (http://www.metaways.de)
- */
-
-/**
- * class to handle CardDAV tree
- *
- * @package     Addressbook
- * @subpackage  Frontend
- */
-class Addressbook_Frontend_CardDAV extends DAV\Collection implements DAV\IProperties, DAVACL\IACL
-{
-    /**
-     * the current application object
-     * 
-     * @var Tinebase_Model_Application
-     */
-    protected $_application;
-    
-    protected $_applicationName = 'Addressbook';
-    
-    protected $_model = 'Contact';
-    
-    /**
-     * the current path
-     * 
-     * @var string
-     */
-    protected $_path;
-    
-    /**
-     * contructor
-     * 
-     * @param  string|Tinebase_Model_Application  $_application  the current application
-     * @param  string                             $_path         the current path
-     */
-    public function __construct($_path = null)
-    {
-        $this->_path = (!empty($_path)) ? $_path : Tinebase_Core::getUser()->contact_id;
-        
-        $this->_application = Tinebase_Application::getInstance()->getApplicationByName($this->_applicationName);
-    }
-    
-    /**
-     * create addressbook collection from CardDAV client.
-     * 
-     * (non-PHPdoc)
-     * @see Sabre_DAV_Collection::createDirectory()
-     */
-    public function createDirectory($name)
-    {
-      $newContainer = new Tinebase_Model_Container(array(
-            'name'              => $name,
-            'type'              => Tinebase_Model_Container::TYPE_PERSONAL,
-            'backend'           => 'Sql',
-            'application_id'    => $this->_application->getId(),
-            'model'             => $this->_application->name . '_Model_' . $this->_model
-        ));
-
-        #if($newContainer->type !== Tinebase_Model_Container::TYPE_PERSONAL and $newContainer->type !== Tinebase_Model_Container::TYPE_SHARED) {
-        #    throw new Tinebase_Exception_InvalidArgument('Can add personal or shared containers only');
-        #}
-
-        $container = Tinebase_Container::getInstance()->addContainer($newContainer);
-
-        $result = $container->toArray();
-        $result['account_grants'] = Tinebase_Container::getInstance()->getGrantsOfAccount(Tinebase_Core::getUser(), $container->getId())->toArray();
-        $result['path'] = $container->getPath();
-        
-        return $result;
-    }
-    
-    /**
-     * (non-PHPdoc)
-     * @see Sabre\DAV\Collection::getChild()
-     */
-    public function getChild($_name)
-    {
-        Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ .' path: ' . $this->_path . ' name: ' . $_name);
-    
-        $pathParts = explode('/', trim($this->_path, '/'));
-        #Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ .' part count: ' . count($pathParts) . ' ' . print_r($pathParts, true));
-        switch(count($pathParts)) {
-            # path == /account->contact_id
-            # list container
-            case 1:
-                try {
-                    // getchild to new collection ou existing one.
-                    if ($_name == Addressbook_Frontend_CardDAV_AllContacts::NAME) {
-                        return new Addressbook_Frontend_CardDAV_AllContacts(Tinebase_Core::getUser());
-                    
-                    } else if ($_name instanceof Tinebase_Model_Container) {
-                        $container = $_name;
-                    } else if (is_numeric($_name)) {
-                        $container = Tinebase_Container::getInstance()->getContainerById($_name);
-                    } else {
-                        $container = Tinebase_Container::getInstance()->getContainerByName($this->_applicationName, $_name, Tinebase_Model_Container::TYPE_PERSONAL, Tinebase_Core::getUser());
-                    }
-
-                    //$container = $_name instanceof Tinebase_Model_Container ? $_name : Tinebase_Container::getInstance()->getContainerById($_name);
-                } catch (Tinebase_Exception_NotFound $tenf) {
-                    throw new DAV\Exception\NotFound('Directory not found');
-                } catch (Tinebase_Exception_InvalidArgument $teia) {
-                    // invalid container id provided
-                    throw new DAV\Exception\NotFound('Directory not found');
-                }
-                
-                if (!Tinebase_Core::getUser()->hasGrant($container, Tinebase_Model_Grants::GRANT_READ) || !Tinebase_Core::getUser()->hasGrant($container, Tinebase_Model_Grants::GRANT_SYNC)) {
-                    throw new DAV\Exception\NotFound('Directory permissions mismatch');
-                }
-                
-                $objectClass = $this->_application->name . '_Frontend_WebDAV_Container';
-                
-                return new $objectClass($container, true);
-                
-                break;
-            
-            default:
-                throw new DAV\Exception\NotFound('Child not found');
-            
-                break;
-        }
-    
-        
-    }
-    
-    /**
-     * Returns an array with all the child nodes
-     *
-     * @return Sabre\DAV\INode[]
-     */
-    function getChildren()
-    {
-        $pathParts = explode('/', trim($this->_path, '/'));
-        
-        Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ .' part count: ' . count($pathParts) . ' ' . print_r($pathParts, true));
-        
-        $children = array();
-        
-        switch(count($pathParts)) {
-            # path == /account->contact_id
-            # list container
-            case 1:
-                list ($client, $version) = Addressbook_Convert_Contact_VCard_Factory::getUserAgent();
-                if (in_array($client, array(Addressbook_Convert_Contact_VCard_Factory::CLIENT_MACOSX))) {
-                    $children[] = $this->getChild(Addressbook_Frontend_CardDAV_AllContacts::NAME);
-                }
-                
-                else {
-                    $containers = Tinebase_Container::getInstance()->getContainerByACL(Tinebase_Core::getUser(), $this->_application->name, Tinebase_Model_Grants::GRANT_SYNC);
-                    foreach ($containers as $container) {
-                        try {
-                            $children[] = $this->getChild($container);
-                        } catch (DAV\Exception\NotFound $defnf) {
-                            // skip child => no read permissions
-                        }
-                    }
-                }
-                break;
-        }
-        
-        return $children;
-        
-    }
-    
-    /**
-     * Returns a group principal
-     *
-     * This must be a url to a principal, or null if there's no owner
-     *
-     * @return string|null
-     */
-    public function getGroup()
-    {
-        return null;
-    }
-    
-    /**
-     * Returns a list of ACE's for this node.
-     *
-     * Each ACE has the following properties:
-     *   * 'privilege', a string such as {DAV:}read or {DAV:}write. These are
-     *     currently the only supported privileges
-     *   * 'principal', a url to the principal who owns the node
-     *   * 'protected' (optional), indicating that this ACE is not allowed to
-     *      be updated.
-     *      
-     * @todo implement real logic
-     * @return array
-     */
-    public function getACL() 
-    {
-        $principal = 'principals/users/' . Tinebase_Core::getUser()->contact_id;
-        
-        return array(
-            array(
-                'privilege' => '{DAV:}read',
-                'principal' => $principal,
-                'protected' => true,
-            ),
-            array(
-                'privilege' => '{DAV:}write',
-                'principal' => $principal,
-                'protected' => true,
-            )
-        );
-    
-    }
-    
-    /**
-     * Returns the name of the node
-     *
-     * @return string
-     */
-    public function getName()
-    {
-        list(,$name) = DAV\URLUtil::splitPath($this->_path);
-        
-        return $name;
-    }
-    
-    /**
-     * Returns the owner principal
-     *
-     * This must be a url to a principal, or null if there's no owner
-     * 
-     * @todo implement real logic
-     * @return string|null
-     */
-    public function getOwner()
-    {
-        return null;
-        return $this->addressBookInfo['principaluri'];
-    }
-    
-    /**
-     * Returns the list of properties
-     *
-     * @param array $requestedProperties
-     * @return array
-     */
-    public function getProperties($requestedProperties) 
-    {
-        $pathParts = explode('/', trim($this->_path, '/'));
-        
-        Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ .' part count: ' . count($pathParts) . ' ' . print_r($pathParts, true));
-        
-        $children = array();
-        
-        list(, $basename) = DAV\URLUtil::splitPath($this->_path);
-        
-        switch(count($pathParts)) {
-            # path == /accountLoginName
-            # list personal and shared folder
-            case 1:
-                $properties = array(
-                    '{http://calendarserver.org/ns/}getctag' => 1,
-                    'id'                => $basename,
-                    'uri'               => $basename,
-                    #'principaluri'      => $principalUri,
-                    '{DAV:}displayname' => Tinebase_Core::getUser()->accountDisplayName ,
-                );
-                break;
-        }
-        
-        #Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ .' path: ' . $this->_path . ' ' . print_r($requestedProperties, true));
-        #Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ .' path: ' . $this->_path . ' ' . print_r($properties, true));
-        
-        $response = array();
-    
-        foreach($requestedProperties as $prop) switch($prop) {
-            case '{DAV:}owner' :
-                $response[$prop] = new DAVACL\Property\Principal(DAVACL\Property\Principal::HREF, 'principals/users/' . Tinebase_Core::getUser()->contact_id);
-                break;
-                
-            default :
-                if (isset($properties[$prop])) $response[$prop] = $properties[$prop];
-                break;
-    
-        }
-        
-        Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ .' path: ' . $this->_path . ' ' . print_r($response, true));
-        
-        return $response;
-    }
-    
-    /**
-     * Updates the ACL
-     *
-     * This method will receive a list of new ACE's.
-     *
-     * @param array $acl
-     * @return void
-     */
-    public function setACL(array $acl)
-    {
-        throw new DAV\Exception\MethodNotAllowed('Changing ACL is not yet supported');
-    }
-    
-    /**
-     * Updates properties on this node,
-     *
-     * The properties array uses the propertyName in clark-notation as key,
-     * and the array value for the property value. In the case a property
-     * should be deleted, the property value will be null.
-     *
-     * This method must be atomic. If one property cannot be changed, the
-     * entire operation must fail.
-     *
-     * If the operation was successful, true can be returned.
-     * If the operation failed, false can be returned.
-     *
-     * Deletion of a non-existant property is always succesful.
-     *
-     * Lastly, it is optional to return detailed information about any
-     * failures. In this case an array should be returned with the following
-     * structure:
-     *
-     * array(
-     *   403 => array(
-     *      '{DAV:}displayname' => null,
-     *   ),
-     *   424 => array(
-     *      '{DAV:}owner' => null,
-     *   )
-     * )
-     *
-     * In this example it was forbidden to update {DAV:}displayname. 
-     * (403 Forbidden), which in turn also caused {DAV:}owner to fail
-     * (424 Failed Dependency) because the request needs to be atomic.
-     *
-     * @param array $mutations 
-     * @return bool|array 
-     */
-    public function updateProperties($mutations) 
-    {
-        return false;
-        
-        return $this->carddavBackend->updateAddressBook($this->addressBookInfo['id'], $mutations);
-    }
-    
-    /**
-     * 
-     */
-    public function getSupportedPrivilegeSet()
-    {
-        return null;
-    }
-}
index 4e4ac68..7828ab9 100644 (file)
@@ -6,16 +6,44 @@
  * @subpackage  Frontend
  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
  * @author      Lars Kneschke <l.kneschke@metaways.de>
- * @copyright   Copyright (c) 2011-2011 Metaways Infosystems GmbH (http://www.metaways.de)
- *
+ * @copyright   Copyright (c) 2014-2014 Metaways Infosystems GmbH (http://www.metaways.de)
  */
 
 /**
- * class to handle WebDAV tree
+ * class to handle container tree
  *
  * @package     Addressbook
  * @subpackage  Frontend
  */
-class Addressbook_Frontend_WebDAV extends Tinebase_WebDav_Collection_Abstract
+class Addressbook_Frontend_WebDAV extends Tinebase_WebDav_Collection_AbstractContainerTree
 {
+    /**
+     * (non-PHPdoc)
+     * @see Tinebase_WebDav_Collection_AbstractContainerTree::getChild()
+     */
+    public function getChild($name)
+    {
+        if (count($this->_getPathParts()) === 2 && $name == Addressbook_Frontend_CardDAV_AllContacts::NAME) {
+            return new Addressbook_Frontend_CardDAV_AllContacts(Tinebase_Core::getUser());
+        }
+        
+        return parent::getChild($name);
+    }
+    
+    /**
+     * (non-PHPdoc)
+     * @see Tinebase_WebDav_Collection_AbstractContainerTree::getChildren()
+     */
+    public function getChildren()
+    {
+        list ($client, $version) = Addressbook_Convert_Contact_VCard_Factory::getUserAgent();
+        
+        if (count($this->_getPathParts()) === 2 && in_array($client, array(Addressbook_Convert_Contact_VCard_Factory::CLIENT_MACOSX))) {
+            $children[] = $this->getChild(Addressbook_Frontend_CardDAV_AllContacts::NAME);
+            
+            return $children;
+        }
+        
+        return parent::getChildren();
+    }
 }
diff --git a/tine20/Calendar/Frontend/CalDAV.php b/tine20/Calendar/Frontend/CalDAV.php
deleted file mode 100644 (file)
index d08d786..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-<?php
-
-use Sabre\DAV;
-use Sabre\DAVACL;
-use Sabre\CalDAV;
-
-/**
- * Tine 2.0
- *
- * @package     Calendar
- * @subpackage  Frontend
- * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
- * @author      Lars Kneschke <l.kneschke@metaways.de>
- * @copyright   Copyright (c) 2011-2013 Metaways Infosystems GmbH (http://www.metaways.de)
- */
-
-/**
- * class to handle CalDAV tree
- *
- * @package     Calendar
- * @subpackage  Frontend
- */
-class Calendar_Frontend_CalDAV extends Addressbook_Frontend_CardDAV
-{
-    protected $_applicationName = 'Calendar';
-    
-    protected $_model = 'Event';
-    
-    /**
-     * Returns an array with all the child nodes
-     *
-     * @return Sabre_DAV_INode[]
-     */
-    public function getChildren()
-    {
-        $calendars = parent::getChildren();
-        
-        $TFCalDAV = new Tasks_Frontend_CalDAV();
-        $todoLists = $TFCalDAV->getChildren();
-        
-        return array_merge($calendars, $todoLists);
-    }
-    
-    /**
-     * (non-PHPdoc)
-     * @see Sabre\DAV\Collection::getChild()
-     * 
-     * @throws Sabre\DAV\Exception
-     * @throws Sabre\DAV\Exception\NotFound
-     */
-    public function getChild($_name)
-    {
-        if (version_compare(PHP_VERSION, '5.3.0', '<')) {
-            throw new Sabre\DAV\Exception('PHP 5.3+ is needed for CalDAV support.');
-        }
-        
-        if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ .' path: ' . $this->_path . ' name: ' . $_name);
-    
-        $pathParts = explode('/', trim($this->_path, '/'));
-        #Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ .' part count: ' . count($pathParts) . ' ' . print_r($pathParts, true));
-        switch(count($pathParts)) {
-            # path == /account->contact_id
-            # list container
-            case 1:
-                if ($_name == 'inbox') {
-                    return new Calendar_Frontend_CalDAV_ScheduleInbox(Tinebase_Core::getUser());
-                    
-                } elseif ($_name == 'outbox') {
-                    return new CalDAV\Schedule\Outbox('principals/users/' . Tinebase_Core::getUser()->contact_id);
-                    
-                } else {
-                    try {
-                        //modified to getchild for new collection or existing collection
-                        if ($_name instanceof Tinebase_Model_Container) {
-                            $container = $_name;
-                        } else if (is_numeric($_name)) {
-                            $container = Tinebase_Container::getInstance()->getContainerById($_name);
-                        } else {
-                            $container = Tinebase_Container::getInstance()->getContainerByName($this->_applicationName, $_name, Tinebase_Model_Container::TYPE_PERSONAL, Tinebase_Core::getUser());
-                        }
-                        
-                        //$container = $_name instanceof Tinebase_Model_Container ? $_name : Tinebase_Container::getInstance()->getContainerById($_name);
-                    } catch (Tinebase_Exception_NotFound $tenf) {
-                        throw new Sabre\DAV\Exception\NotFound('Directory not found');
-                    } catch (Tinebase_Exception_InvalidArgument $teia) {
-                        // invalid container id provided
-                        throw new Sabre\DAV\Exception\NotFound('Directory not found');
-                    }
-                    
-                    if (!Tinebase_Core::getUser()->hasGrant($container, Tinebase_Model_Grants::GRANT_READ) || !Tinebase_Core::getUser()->hasGrant($container, Tinebase_Model_Grants::GRANT_SYNC)) {
-                        throw new Sabre\DAV\Exception\NotFound('Directory not found');
-                    }
-                    
-                    $objectClass = array_value(0, explode('_', $container->model ?: 'Calendar')) . '_Frontend_WebDAV_Container';
-                    
-                    return new $objectClass($container, true);
-                }
-                
-                break;
-            
-            default:
-                throw new Sabre\DAV\Exception\NotFound('Child not found');
-            
-                break;
-        }   
-    }    
-}
index ecccccc..9b3db54 100644 (file)
@@ -84,7 +84,7 @@ class Calendar_Frontend_CalDAV_PluginDefaultAlarms extends \Sabre\DAV\ServerPlug
      */
     public function beforeGetProperties($path, \Sabre\DAV\INode $node, &$requestedProperties, &$returnedProperties) 
     {
-        if ($node instanceof \Sabre\CalDAV\ICalendar || $node instanceof Calendar_Frontend_CalDAV) {
+        if ($node instanceof \Sabre\CalDAV\ICalendar || $node instanceof Calendar_Frontend_WebDAV) {
             $vcalendar = new \Sabre\VObject\Component\VCalendar();
             
             $property = '{' . \Sabre\CalDAV\Plugin::NS_CALDAV . '}default-alarm-vevent-datetime';
index db8d301..0a7a824 100644 (file)
@@ -6,16 +6,56 @@
  * @subpackage  Frontend
  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
  * @author      Lars Kneschke <l.kneschke@metaways.de>
- * @copyright   Copyright (c) 2011-2011 Metaways Infosystems GmbH (http://www.metaways.de)
- *
+ * @copyright   Copyright (c) 2014-2014 Metaways Infosystems GmbH (http://www.metaways.de)
  */
 
 /**
- * class to handle WebDAV tree
+ * class to handle container tree
  *
  * @package     Calendar
  * @subpackage  Frontend
  */
-class Calendar_Frontend_WebDAV extends Tinebase_WebDav_Collection_Abstract
+class Calendar_Frontend_WebDAV extends Tinebase_WebDav_Collection_AbstractContainerTree
 {
+    /**
+     * (non-PHPdoc)
+     * @see Tinebase_WebDav_Collection_AbstractContainerTree::getChild()
+     */
+    public function getChild($name)
+    {
+        // do this only for caldav requests
+        if ($this->_useIdAsName && count($this->_getPathParts()) == 2 && in_array($name, array('inbox', 'outbox'))) {
+            switch ($name) {
+                case 'inbox':
+                    return new Calendar_Frontend_CalDAV_ScheduleInbox(Tinebase_Core::getUser());
+                    
+                    break;
+                    
+                case 'outbox':
+                    return new \Sabre\CalDAV\Schedule\Outbox('principals/users/' . Tinebase_Core::getUser()->contact_id);
+                    
+                    break;
+            }
+        }
+        
+        return parent::getChild($name);
+    }
+    
+    /**
+     * (non-PHPdoc)
+     * @see Tinebase_WebDav_Collection_AbstractContainerTree::getChildren()
+     */
+    public function getChildren()
+    {
+        $children = parent::getChildren();
+        
+        // do this only for caldav request 
+        if ($this->_useIdAsName && count($this->_getPathParts()) == 2) {
+            $tfwdavct = new Tasks_Frontend_WebDAV('tasks/' . array_value(1, $this->_getPathParts()), $this->_useIdAsName);
+            
+            $children = array_merge($children, $tfwdavct->getChildren());
+        }
+        
+        return $children;
+    }
 }
index beae4d8..43ea49b 100644 (file)
@@ -269,6 +269,7 @@ class Calendar_Frontend_WebDAV_Container extends Tinebase_WebDav_Container_Abstr
             $grants = new Tinebase_Record_RecordSet('Tinebase_Model_Grants');
             $grants->addRecord(Tinebase_Container::getInstance()->getGrantsOfAccount(Tinebase_Core::getUser(), $this->_container));
         }
+        
         foreach ($grants as $grant) {
             
             switch ($grant->account_type) {
@@ -278,7 +279,11 @@ class Calendar_Frontend_WebDAV_Container extends Tinebase_WebDav_Container_Abstr
                     break;
                 
                 case 'group':
-                    $list       = Tinebase_Group::getInstance()->getGroupById($grant->account_id);
+                    try {
+                        $list       = Tinebase_Group::getInstance()->getGroupById($grant->account_id);
+                    } catch (Tinebase_Exception_NotFound $tenf) {
+                        continue;
+                    }
                      
                     $href       = '/principals/groups/' . $list->list_id;
                     $commonName = $list->name;
@@ -286,7 +291,11 @@ class Calendar_Frontend_WebDAV_Container extends Tinebase_WebDav_Container_Abstr
                     break;
                     
                 case 'user':
-                    $contact    = Tinebase_User::getInstance()->getUserById($grant->account_id);
+                    try {
+                        $contact    = Tinebase_User::getInstance()->getUserById($grant->account_id);
+                    } catch (Tinebase_Exception_NotFound $tenf) {
+                        continue;
+                    }
                      
                     $href       = '/principals/users/' . $contact->contact_id;
                     $commonName = $contact->accountDisplayName;
index eb072b8..52bc0a4 100644 (file)
@@ -5,13 +5,12 @@
  * @package     Felamimail
  * @subpackage  Frontend
  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
- * @author      Philipp Schüle <p.schuele@metaways.de>
- * @copyright   Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de)
- *
+ * @author      Lars Kneschke <l.kneschke@metaways.de>
+ * @copyright   Copyright (c) 2014-2014 Metaways Infosystems GmbH (http://www.metaways.de)
  */
 
 /**
- * class to handle WebDAV tree
+ * class to handle container tree
  *
  * @package     Felamimail
  * @subpackage  Frontend
 class Felamimail_Frontend_WebDAV extends Tinebase_Frontend_WebDAV_Abstract
 {
     /**
-     * application name
-     * 
+     * app has personal folders
+     *
      * @var string
      */
-    protected $_applicationName = 'Felamimail';
+    protected $_hasPersonalFolders = false;
     
     /**
-    * app has personal folders
-    *
-    * @var string
-    */
-    protected $_hasPersonalFolders = FALSE;
+     * app has records folder
+     *
+     * @var string
+     */
+    protected $_hasRecordFolder = false;
 }
index c3fcde8..8293dba 100644 (file)
@@ -6,16 +6,21 @@
  * @subpackage  Frontend
  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
  * @author      Lars Kneschke <l.kneschke@metaways.de>
- * @copyright   Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de)
- *
+ * @copyright   Copyright (c) 2014-2014 Metaways Infosystems GmbH (http://www.metaways.de)
  */
 
 /**
- * class to handle WebDAV tree
+ * class to handle container tree
  *
  * @package     Filemanager
  * @subpackage  Frontend
  */
 class Filemanager_Frontend_WebDAV extends Tinebase_Frontend_WebDAV_Abstract
 {
+    /**
+     * app has records folder
+     *
+     * @var string
+     */
+    protected $_hasRecordFolder = false;
 }
index 09c65c6..a225217 100644 (file)
@@ -6,16 +6,15 @@
  * @subpackage  Frontend
  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
  * @author      Lars Kneschke <l.kneschke@metaways.de>
- * @copyright   Copyright (c) 2013-2013 Metaways Infosystems GmbH (http://www.metaways.de)
- *
+ * @copyright   Copyright (c) 2014-2014 Metaways Infosystems GmbH (http://www.metaways.de)
  */
 
 /**
- * class to handle WebDAV tree
+ * class to handle container tree
  *
  * @package     Tasks
  * @subpackage  Frontend
  */
-class Tasks_Frontend_WebDAV extends Tinebase_WebDav_Collection_Abstract
+class Tasks_Frontend_WebDAV extends Tinebase_WebDav_Collection_AbstractContainerTree
 {
 }
index 5a39b1d..e0488b5 100644 (file)
@@ -6,7 +6,7 @@
  * @subpackage  Frontend
  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
  * @author      Lars Kneschke <l.kneschke@metaways.de>
- * @copyright   Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright   Copyright (c) 2012-2014 Metaways Infosystems GmbH (http://www.metaways.de)
  *
  */
 
@@ -16,7 +16,7 @@
  * @package     Tinebase
  * @subpackage  Frontend
  */
-abstract class Tinebase_Frontend_WebDAV_Abstract extends Tinebase_WebDav_Collection_Abstract
+abstract class Tinebase_Frontend_WebDAV_Abstract extends Tinebase_WebDav_Collection_AbstractContainerTree
 {
     /**
      * Creates a new subdirectory
@@ -28,8 +28,8 @@ abstract class Tinebase_Frontend_WebDAV_Abstract extends Tinebase_WebDav_Collect
     public function createDirectory($name) 
     {
         $container = parent::createDirectory($name);
-                
-        $path = '/' . $this->_application->getId() . '/folders/' . $container->type . '/';
+        
+        $path = '/' . $this->_getApplication()->getId() . '/folders/' . $container->type . '/';
         
         if ($container->type == Tinebase_Model_Container::TYPE_PERSONAL) {
             $path .= Tinebase_Core::getUser()->accountId . '/';
index a47ffbd..ed64dbf 100644 (file)
@@ -102,6 +102,17 @@ class Tinebase_Server_WebDAV extends Tinebase_Server_Abstract implements Tinebas
         $aclPlugin = new \Sabre\DAVACL\Plugin();
         $aclPlugin->defaultUsernamePath    = Tinebase_WebDav_PrincipalBackend::PREFIX_USERS;
         $aclPlugin->principalCollectionSet = array (Tinebase_WebDav_PrincipalBackend::PREFIX_USERS, Tinebase_WebDav_PrincipalBackend::PREFIX_GROUPS);
+        
+        $aclPlugin->principalSearchPropertySet = array(
+            '{DAV:}displayname'                                                   => 'Display name',
+            '{' . \Sabre\DAV\Server::NS_SABREDAV . '}email-address'               => 'Email address',
+            '{' . \Sabre\CalDAV\Plugin::NS_CALENDARSERVER . '}email-address-set'  => 'Email addresses',
+            '{' . \Sabre\CalDAV\Plugin::NS_CALENDARSERVER . '}first-name'         => 'First name',
+            '{' . \Sabre\CalDAV\Plugin::NS_CALENDARSERVER . '}last-name'          => 'Last name',
+            '{' . \Sabre\CalDAV\Plugin::NS_CALDAV         . '}calendar-user-address-set' => 'Calendar user address set',
+            '{' . \Sabre\CalDAV\Plugin::NS_CALDAV         . '}calendar-user-type' => 'Calendar user type'
+        );
+        
         self::$_server->addPlugin($aclPlugin);
         
         self::$_server->addPlugin(new \Sabre\CardDAV\Plugin());
diff --git a/tine20/Tinebase/WebDav/Collection/AbstractContainerTree.php b/tine20/Tinebase/WebDav/Collection/AbstractContainerTree.php
new file mode 100644 (file)
index 0000000..5893558
--- /dev/null
@@ -0,0 +1,645 @@
+<?php
+/**
+ * Tine 2.0
+ *
+ * @package     Tinebase
+ * @subpackage  WebDAV
+ * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
+ * @author      Lars Kneschke <l.kneschke@metaways.de>
+ * @copyright   Copyright (c) 2014-2014 Metaways Infosystems GmbH (http://www.metaways.de)
+ */
+
+/**
+ * class to handle top level folders for an application
+ *
+ * @package     Tinebase
+ * @subpackage  WebDAV
+ */
+abstract class Tinebase_WebDav_Collection_AbstractContainerTree extends \Sabre\DAV\Collection implements \Sabre\DAV\IProperties, \Sabre\DAVACL\IACL
+{
+    /**
+     * the current application object
+     * 
+     * @var Tinebase_Model_Application
+     */
+    protected $_application;
+    
+    /**
+     * application name
+     *
+     * @var string
+     */
+    protected $_applicationName;
+    
+    /**
+     * app has personal folders
+     *
+     * @var string
+     */
+    protected $_hasPersonalFolders = true;
+    
+    /**
+     * app has records folder
+     *
+     * @var string
+     */
+    protected $_hasRecordFolder = true;
+    
+    /**
+     * the current path
+     * 
+     * @var string
+     */
+    protected $_path;
+    
+    /**
+     * @var array
+     */
+    protected $_pathParts;
+    
+    /**
+     * 
+     * @var boolean
+     */
+    protected $_useIdAsName;
+    
+    /**
+     * contructor
+     * 
+     * @param string $path         the current path
+     * @param bool   $useIdAsName  use name or id as node name
+     */
+    public function __construct($path, $useIdAsName = false)
+    {
+        $this->_path        = $path;
+        $this->_useIdAsName = $useIdAsName;
+    }
+    
+    /**
+     * (non-PHPdoc)
+     * @see \Sabre\DAV\Collection::createDirectory()
+     * 
+     * @todo allow to create personal folders only when in personal path
+     */
+    public function createDirectory($name) 
+    {
+        if (count($this->_getPathParts()) !== 2) {
+            throw new \Sabre\DAV\Exception\Forbidden('Permission denied to create directory ' . $name);
+        }
+        
+        $containerType = array_value(1, $this->_getPathParts()) == Tinebase_Model_Container::TYPE_SHARED ?
+            Tinebase_Model_Container::TYPE_SHARED :
+            Tinebase_Model_Container::TYPE_PERSONAL;
+        
+        $newContainer = new Tinebase_Model_Container(array(
+            'name'              => $name,
+            'type'              => $containerType,
+            'backend'           => 'Sql',
+            'application_id'    => $this->_getApplication()->getId(),
+            'model'             => Tinebase_Core::getApplicationInstance($this->_applicationName)->getDefaultModel()
+        ));
+
+        try {
+            $container = Tinebase_Container::getInstance()->addContainer($newContainer);
+        } catch (Tinebase_Exception_AccessDenied $tead) {
+            throw new \Sabre\DAV\Exception\Forbidden('Permission denied to create directory ' . $name);
+        }
+        
+        return $container;
+        
+        //$result = $container->toArray();
+        //$result['account_grants'] = Tinebase_Container::getInstance()->getGrantsOfAccount(Tinebase_Core::getUser(), $container->getId())->toArray();
+        //$result['path'] = $container->getPath();
+        
+        //return $result;
+        
+    }
+    
+    /**
+     * (non-PHPdoc)
+     * @see Sabre\DAV\Collection::getChild()
+     */
+    public function getChild($name)
+    {
+        switch (count($this->_getPathParts())) {
+            # path == /<applicationPrefix> (for example calendars)
+            # return folders for currentuser, other users and 'shared' folder
+            # $name can be
+            # * contact_id of user
+            # * 'shared'
+            case 1:
+                if ($name === Tinebase_Model_Container::TYPE_SHARED || 
+                    ($this->_hasRecordFolder && $name === Tinebase_FileSystem::FOLDER_TYPE_RECORDS)) {
+                    $path = $this->_path . '/' . $name;
+                    
+                } elseif ($this->_hasPersonalFolders) {
+                    try {
+                        $contact = $this->_getContact($name);
+                        
+                    } catch (Tinebase_Exception_NotFound $tenf) {
+                        throw new \Sabre\DAV\Exception\NotFound("Directory $this->_path/$name not found");
+                    }
+                    
+                    $path = $this->_path . '/' . ($this->_useIdAsName ? $contact->getId() : $contact->n_fileas);
+                    
+                } else {
+                    throw new \Sabre\DAV\Exception\NotFound("Directory $this->_path/$name not found");
+                }
+                
+                $className = $this->_getAppliationName() . '_Frontend_WebDAV';
+                
+                return new $className($path, $this->_useIdAsName);
+                
+                break;
+                
+            # path == /<applicationPrefix>/<contactid>|'shared'
+            # list container
+            case 2:
+                if (array_value(1, $this->_getPathParts()) == Tinebase_Model_Container::TYPE_SHARED) {
+                    try {
+                        if ($name instanceof Tinebase_Model_Container) {
+                            $container = $name;
+                        } elseif ($this->_useIdAsName) {
+                            $container = Tinebase_Container::getInstance()->getContainerById($name);
+                        } else {
+                            $container = Tinebase_Container::getInstance()->getContainerByName(
+                                $this->_getAppliationName(), 
+                                $name, 
+                                Tinebase_Model_Container::TYPE_SHARED
+                            );
+                        }
+                        
+                    } catch (Tinebase_Exception_NotFound $tenf) {
+                        throw new \Sabre\DAV\Exception\NotFound("Directory $this->_path/$name not found");
+                        
+                    } catch (Tinebase_Exception_InvalidArgument $teia) {
+                        // invalid container id provided
+                        throw new \SabreDAV\Exception\NotFound("Directory $this->_path/$name not found");
+                    }
+                } elseif ($this->_hasRecordFolder && array_value(1, $this->_getPathParts()) == Tinebase_FileSystem::FOLDER_TYPE_RECORDS) {
+                    
+                    return new Tinebase_Frontend_WebDAV_RecordCollection($this->_path . '/' . $name);
+                    
+                } elseif ($this->_hasPersonalFolders) {
+                    try {
+                        $contact = $this->_getContact(array_value(1, $this->_getPathParts()));
+                        
+                    } catch (Tinebase_Exception_NotFound $tenf) {
+                        throw new \Sabre\DAV\Exception\NotFound("Directory $this->_path/$name not found");
+                    }
+                    
+                    try {
+                        if ($name instanceof Tinebase_Model_Container) {
+                            $container = $name;
+                        } elseif ($this->_useIdAsName) {
+                            $container = Tinebase_Container::getInstance()->getContainerById($name);
+                        } else { 
+                            $container = Tinebase_Container::getInstance()->getContainerByName(
+                                $this->_getAppliationName(), 
+                                $name, 
+                                Tinebase_Model_Container::TYPE_PERSONAL, 
+                                $contact->account_id
+                            );
+                        }
+                        
+                    } catch (Tinebase_Exception_NotFound $tenf) {
+                        throw new \Sabre\DAV\Exception\NotFound("Directory $this->_path/$name not found");
+                        
+                    } catch (Tinebase_Exception_InvalidArgument $teia) {
+                        // invalid container id provided
+                        throw new \SabreDAV\Exception\NotFound("Directory $this->_path/$name not found");
+                    }
+                    
+                } else {
+                    throw new \Sabre\DAV\Exception\NotFound("Directory $this->_path/$name not found");
+                }
+                
+                if (!Tinebase_Core::getUser()->hasGrant($container, Tinebase_Model_Grants::GRANT_READ) ||
+                    !Tinebase_Core::getUser()->hasGrant($container, Tinebase_Model_Grants::GRANT_SYNC)) {
+                    throw new \Sabre\DAV\Exception\NotFound("Directory $this->_path/$name not found");
+                }
+                
+                $objectClass = Tinebase_Application::getInstance()->getApplicationById($container->application_id)->name . '_Frontend_WebDAV_Container';
+                
+                return new $objectClass($container, $this->_useIdAsName);
+                
+                break;
+                
+            default:
+                throw new Sabre\DAV\Exception\NotFound("Directory $this->_path/$name not found");
+            
+                break;
+        }
+    
+        
+    }
+    
+    /**
+     * Returns an array with all the child nodes
+     * 
+     * the records subtree is not returned as child here. It's only available via getChild().
+     *
+     * @return \Sabre\DAV\INode[]
+     */
+    function getChildren()
+    {
+        $children = array();
+        
+        switch (count($this->_getPathParts())) {
+            # path == /<applicationPrefix> (for example calendars)
+            # return folders for currentuser, other users and 'shared' folder
+            case 1:
+                $children[] = $this->getChild(Tinebase_Model_Container::TYPE_SHARED);
+                
+                if ($this->_hasPersonalFolders) {
+                    $children[] = $this->getChild($this->_useIdAsName ? Tinebase_Core::getUser()->contact_id : Tinebase_Core::getUser()->accountDisplayName);
+                    
+                    $otherUsers = Tinebase_Container::getInstance()->getOtherUsers(Tinebase_Core::getUser(), $this->_getAppliationName(), array(
+                        Tinebase_Model_Grants::GRANT_READ,
+                        Tinebase_Model_Grants::GRANT_SYNC
+                    ));
+                    
+                    foreach ($otherUsers as $user) {
+                        if ($user->contact_id && $user->visibility === Tinebase_Model_User::VISIBILITY_DISPLAYED) {
+                            try {
+                                $children[] = $this->getChild($this->_useIdAsName ? $user->contact_id : $user->accountDisplayName);
+                            } catch (\Sabre\DAV\Exception\NotFound $sdavenf) {
+                                // ignore contacts not found
+                            }
+                        }
+                    }
+                }
+        
+                break;
+            
+            # path == /<applicationPrefix>/<contactid>|'shared'
+            # list container
+            case 2:
+                if (array_value(1, $this->_getPathParts()) == Tinebase_Model_Container::TYPE_SHARED) {
+                    $containers = Tinebase_Container::getInstance()->getSharedContainer(
+                        Tinebase_Core::getUser(),
+                        $this->_getAppliationName(),
+                        array(
+                            Tinebase_Model_Grants::GRANT_READ,
+                            Tinebase_Model_Grants::GRANT_SYNC
+                        )
+                    );
+                    
+                } elseif ($this->_hasPersonalFolders) {
+                    try {
+                        $contact = $this->_getContact(array_value(1, $this->_getPathParts()));
+                    } catch (Tinebase_Exception_NotFound $tenf) {
+                        throw new \Sabre\DAV\Exception\NotFound("Path $this->_path not found");
+                    }
+                    
+                    $containers = Tinebase_Container::getInstance()->getPersonalContainer(
+                        Tinebase_Core::getUser(),
+                        $this->_getAppliationName(),
+                        $contact->account_id,
+                        array(
+                            Tinebase_Model_Grants::GRANT_READ, 
+                            Tinebase_Model_Grants::GRANT_SYNC
+                        )
+                    );
+                    
+                } else {
+                    throw new Sabre\DAV\Exception\NotFound("Path $this->_path not found");
+                }
+                
+                foreach ($containers as $container) {
+                    try {
+                        $children[] = $this->getChild($container);
+                    } catch (\Sabre\DAV\Exception\NotFound $sdavenf) {
+                        // ignore containers not found
+                    }
+                }
+                
+                break;
+                
+            default:
+                throw new Sabre\DAV\Exception\NotFound("Path $this->_path not found");
+                
+                break;
+        }
+        
+        return $children;
+    }
+    
+    /**
+     * return etag
+     * 
+     * @return string
+     */
+    public function getETag()
+    {
+        $etags = array();
+        
+        foreach ($this->getChildren() as $child) {
+            $etags[] = $child->getETag();
+        }
+        
+        return '"' . sha1(implode(null, $etags)) . '"';
+    }
+    
+    /**
+     * Returns a group principal
+     *
+     * This must be a url to a principal, or null if there's no owner
+     *
+     * @return string|null
+     */
+    public function getGroup()
+    {
+        return null;
+    }
+    
+    /**
+     * (non-PHPdoc)
+     * @see \Sabre\DAV\Node::getLastModified()
+     */
+    public function getLastModified()
+    {
+        $lastModified = 1;
+        
+        foreach ($this->getChildren() as $child) {
+            $lastModified = $child->getLastModified() > $lastModified ? $child->getLastModified() : $lastModified;
+        }
+        
+        return $lastModified;
+    }
+    
+    /**
+     * Returns a list of ACE's for this node.
+     *
+     * Each ACE has the following properties:
+     *   * 'privilege', a string such as {DAV:}read or {DAV:}write. These are
+     *     currently the only supported privileges
+     *   * 'principal', a url to the principal who owns the node
+     *   * 'protected' (optional), indicating that this ACE is not allowed to
+     *      be updated.
+     *      
+     * @todo implement real logic
+     * @return array
+     */
+    public function getACL() 
+    {
+        $principal = 'principals/users/' . Tinebase_Core::getUser()->contact_id;
+        
+        return array(
+            array(
+                'privilege' => '{DAV:}read',
+                'principal' => $principal,
+                'protected' => true,
+            ),
+            array(
+                'privilege' => '{DAV:}write',
+                'principal' => $principal,
+                'protected' => true,
+            )
+        );
+    }
+    
+    /**
+     * Returns the name of the node
+     *
+     * @return string
+     */
+    public function getName()
+    {
+        if (count($this->_getPathParts()) === 2 && 
+            array_value(1, $this->_getPathParts()) !== Tinebase_Model_Container::TYPE_SHARED &&
+            !$this->_useIdAsName
+        ) {
+            try {
+                $contact = $this->_getContact(array_value(1, $this->_getPathParts()));
+                
+                $name = $contact->n_fileas;
+                
+            } catch (Tinebase_Exception_NotFound $tenf) {
+                list(,$name) = Sabre\DAV\URLUtil::splitPath($this->_path);
+            }
+            
+        } else {
+            list(,$name) = Sabre\DAV\URLUtil::splitPath($this->_path);
+        }
+        
+        return $name;
+    }
+    
+    /**
+     * Returns the owner principal
+     *
+     * This must be a url to a principal, or null if there's no owner
+     * 
+     * @return string|null
+     */
+    public function getOwner()
+    {
+        if (count($this->_getPathParts()) === 2 && $this->getName() !== Tinebase_Model_Container::TYPE_SHARED) {
+            try {
+                $contact = $this->_getContact(array_value(1, $this->_getPathParts()));
+            } catch (Tinebase_Exception_NotFound $tenf) {
+                return null;
+            }
+            
+            return 'principals/users/' . $contact->getId();
+        }
+        
+        return null;
+    }
+    
+    /**
+     * Returns the list of properties
+     *
+     * @param array $requestedProperties
+     * @return array
+     */
+    public function getProperties($requestedProperties) 
+    {
+        if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(
+            __METHOD__ . '::' . __LINE__ . ' path: ' . $this->_path . ' ' . print_r($requestedProperties, true));
+        
+        $response = array();
+    
+        foreach ($requestedProperties as $property) {
+            switch ($property) {
+                case '{DAV:}displayname':
+                    if (count($this->_getPathParts()) === 2 && $this->getName() !== Tinebase_Model_Container::TYPE_SHARED) {
+                        try {
+                            $contact = $this->_getContact(array_value(1, $this->_getPathParts()));
+                        } catch (Tinebase_Exception_NotFound $tenf) {
+                            continue;
+                        }
+                        
+                        $response[$property] = $contact->n_fileas;
+                    }
+                    
+                    break;
+                    
+                case '{DAV:}owner':
+                    if ($this->getOwner()) {
+                        $response[$property] = new \Sabre\DAVACL\Property\Principal(
+                            \Sabre\DAVACL\Property\Principal::HREF, $this->getOwner()
+                        );
+                    }
+                    
+                    break;
+                    
+                case '{DAV:}getetag':
+                    $response[$property] = $this->getETag();
+                    
+                    break;
+            }
+        }
+        
+        if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(
+            __METHOD__ . '::' . __LINE__ . ' path: ' . $this->_path . ' ' . print_r($response, true));
+        
+        return $response;
+    }
+    
+    /**
+     * Updates the ACL
+     *
+     * This method will receive a list of new ACE's.
+     *
+     * @param array $acl
+     * @return void
+     */
+    public function setACL(array $acl)
+    {
+        throw new Sabre\DAV\Exception\MethodNotAllowed('Changing ACL is not yet supported');
+    }
+    
+    /**
+     * Updates properties on this node,
+     *
+     * The properties array uses the propertyName in clark-notation as key,
+     * and the array value for the property value. In the case a property
+     * should be deleted, the property value will be null.
+     *
+     * This method must be atomic. If one property cannot be changed, the
+     * entire operation must fail.
+     *
+     * If the operation was successful, true can be returned.
+     * If the operation failed, false can be returned.
+     *
+     * Deletion of a non-existant property is always succesful.
+     *
+     * Lastly, it is optional to return detailed information about any
+     * failures. In this case an array should be returned with the following
+     * structure:
+     *
+     * array(
+     *   403 => array(
+     *      '{DAV:}displayname' => null,
+     *   ),
+     *   424 => array(
+     *      '{DAV:}owner' => null,
+     *   )
+     * )
+     *
+     * In this example it was forbidden to update {DAV:}displayname. 
+     * (403 Forbidden), which in turn also caused {DAV:}owner to fail
+     * (424 Failed Dependency) because the request needs to be atomic.
+     *
+     * @param array $mutations 
+     * @return bool|array 
+     */
+    public function updateProperties($mutations) 
+    {
+        throw new Sabre\DAV\Exception\MethodNotAllowed('Changing properties is not yet supported');
+    }
+    
+    /**
+     * 
+     */
+    public function getSupportedPrivilegeSet()
+    {
+        return null;
+    }
+    
+    /**
+     * return application object
+     * 
+     * @return Tinebase_Model_Application
+     */
+    protected function _getApplication()
+    {
+        if (!$this->_application) {
+            $this->_application = Tinebase_Application::getInstance()->getApplicationByName($this->_getAppliationName());
+        }
+        
+        return $this->_application;
+    }
+    
+    /**
+     * return application name
+     * 
+     * @return string
+     */
+    protected function _getAppliationName()
+    {
+        if (!$this->_applicationName) {
+            $this->_applicationName = array_value(0, explode('_', get_class($this)));
+        }
+        
+        return $this->_applicationName;
+    }
+    
+    /**
+     * get path parts
+     * 
+     * @return array
+     */
+    protected function _getPathParts()
+    {
+        if (!$this->_pathParts) {
+            $this->_pathParts = $this->_parsePath($this->_path);
+        }
+        
+        return $this->_pathParts;
+    }
+    
+    /**
+     * split path into parts
+     * 
+     * @param  string  $_path
+     * @return array
+     */
+    protected function _parsePath($_path)
+    {
+        $pathParts = explode('/', trim($this->_path, '/'));
+        
+        return $pathParts;
+    }
+    
+    /**
+     * resolve contact_id to Addressbook_Model_Contact
+     * 
+     * @return Addressbook_Model_Contact
+     */
+    protected function _getContact($contactId)
+    {
+        $filter = new Addressbook_Model_ContactFilter(array(
+            array(
+                'field'     => 'type',
+                'operator'  => 'equals',
+                'value'     => Addressbook_Model_Contact::CONTACTTYPE_USER
+            ),
+            array(
+                'field'     => $this->_useIdAsName ? 'id' : 'n_fileas',
+                'operator'  => 'equals',
+                'value'     => $contactId
+            ),
+        ));
+        
+        $contact = Addressbook_Controller_Contact::getInstance()->search($filter)->getFirstRecord();
+        
+        if (!$contact) {
+            throw new Tinebase_Exception_NotFound('contact not found');
+        }
+        
+        return $contact;
+    }
+}
index 5a984b2..34a2aac 100644 (file)
@@ -1,8 +1,4 @@
 <?php
-
-use Sabre\DAV;
-use Sabre\CalDAV;
-
 /**
  * Tine 2.0
  *
@@ -10,7 +6,7 @@ use Sabre\CalDAV;
  * @subpackage  WebDAV
  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
  * @author      Lars Kneschke <l.kneschke@metaways.de>
- * @copyright   Copyright (c) 2011-2011 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright   Copyright (c) 2011-2014 Metaways Infosystems GmbH (http://www.metaways.de)
  *
  */
 
@@ -20,7 +16,7 @@ use Sabre\CalDAV;
  * @package     Tinebase
  * @subpackage  WebDAV
  */
-abstract class Tinebase_WebDav_Container_Abstract extends Sabre\DAV\Collection implements Sabre\DAV\IProperties, Sabre\DAVACL\IACL
+abstract class Tinebase_WebDav_Container_Abstract extends \Sabre\DAV\Collection implements \Sabre\DAV\IProperties, \Sabre\DAVACL\IACL
 {
     /**
      * the current application object
@@ -395,7 +391,7 @@ abstract class Tinebase_WebDav_Container_Abstract extends Sabre\DAV\Collection i
     public function updateProperties($mutations) 
     {
         if (!Tinebase_Core::getUser()->hasGrant($this->_container, Tinebase_Model_Grants::GRANT_ADMIN)) {
-            throw new DAV\Exception\Forbidden('permission to update container denied');
+            throw new \Sabre\DAV\Exception\Forbidden('permission to update container denied');
         }
         
         $result = array(
@@ -410,8 +406,8 @@ abstract class Tinebase_WebDav_Container_Abstract extends Sabre\DAV\Collection i
                     $result['200'][$key] = null;
                     break;
                     
-                case '{' . CalDAV\Plugin::NS_CALDAV . '}calendar-description':
-                case '{' . CalDAV\Plugin::NS_CALDAV . '}calendar-timezone':
+                case '{' . \Sabre\CalDAV\Plugin::NS_CALDAV . '}calendar-description':
+                case '{' . \Sabre\CalDAV\Plugin::NS_CALDAV . '}calendar-timezone':
                     // fake success
                     $result['200'][$key] = null;
                     break;
index 1904966..e623a72 100644 (file)
@@ -9,9 +9,80 @@
  * @author Evert Pot (http://evertpot.com/)
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
  */
-class Tinebase_WebDav_Principal extends Sabre\DAVACL\Principal 
+class Tinebase_WebDav_Principal extends \Sabre\DAVACL\Principal implements \Sabre\DAV\ICollection
 {
     /**
+     * (non-PHPdoc)
+     * @see \Sabre\DAV\ICollection::createFile()
+     */
+    public function createFile($name, $data = null) 
+    {
+        throw new \Sabre\DAV\Exception\Forbidden('Permission denied to create file (filename ' . $name . ')');
+    }
+
+    /**
+     * (non-PHPdoc)
+     * @see \Sabre\DAV\ICollection::createDirectory()
+     */
+    public function createDirectory($name) 
+    {
+        throw new \Sabre\DAV\Exception\Forbidden('Permission denied to create directory');
+    }
+
+    /**
+     * (non-PHPdoc)
+     * @see \Sabre\DAV\ICollection::getChild()
+     */
+    public function getChild($name) 
+    {
+        switch ($name) {
+            case 'calendar-proxy-read':
+                return new \Sabre\CalDAV\Principal\ProxyRead($this->principalBackend, $this->principalProperties);
+                
+                break;
+                
+            case 'calendar-proxy-write':
+                return new \Sabre\CalDAV\Principal\ProxyWrite($this->principalBackend, $this->principalProperties);
+                
+                break;
+        }
+
+        throw new \Sabre\DAV\Exception\NotFound('Node with name ' . $name . ' was not found');
+    }
+
+    /**
+     * (non-PHPdoc)
+     * @see \Sabre\DAV\ICollection::getChildren()
+     */
+    public function getChildren() 
+    {
+        $children = array(
+            new \Sabre\CalDAV\Principal\ProxyRead ($this->principalBackend, $this->principalProperties),
+            new \Sabre\CalDAV\Principal\ProxyWrite($this->principalBackend, $this->principalProperties)
+        );
+        
+        return $children;
+    }
+
+    /**
+     * Returns whether or not the child node exists
+     *
+     * @param string $name
+     * @return bool
+     */
+    public function childExists($name) 
+    {
+        try {
+            $this->getChild($name);
+            
+            return true;
+            
+        } catch (\Sabre\DAV\Exception\NotFound $e) {
+            return false;
+        }
+    }
+    
+    /**
      * Returns a list of ACE's for this node.
      *
      * Each ACE has the following properties:
@@ -23,14 +94,24 @@ class Tinebase_WebDav_Principal extends Sabre\DAVACL\Principal
      *
      * @return array
      */
-    public function getACL() {
-
+    public function getACL() 
+    {
         return array(
             array(
                 'privilege' => '{DAV:}read',
                 'principal' => '{DAV:}authenticated',
                 'protected' => true,
             ),
+            array(
+                'privilege' => '{DAV:}read',
+                'principal' => $this->principalProperties['uri'] . '/calendar-proxy-read',
+                'protected' => true,
+            ),
+            array(
+                'privilege' => '{DAV:}read',
+                'principal' => $this->principalProperties['uri'] . '/calendar-proxy-write',
+                'protected' => true,
+            )
         );
     }
 }
index de8f2c4..07795c3 100644 (file)
@@ -1,32 +1,29 @@
 <?php
-
-use Sabre\DAVACL;
-
 /**
  * Tine 2.0
  * 
  * @package     Tinebase
  * @subpackage  WebDav
  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
- * @copyright   Copyright (c) 2011-2013 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright   Copyright (c) 2011-2014 Metaways Infosystems GmbH (http://www.metaways.de)
  * @author      Lars Kneschke <l.kneschke@metaways.de>
  */
 
 /**
- * class to handle webdav principals
+ * principal backend class
  * 
  * @package     Tinebase
  * @subpackage  WebDav
  */
-class Tinebase_WebDav_PrincipalBackend implements DAVACL\PrincipalBackend\BackendInterface
+class Tinebase_WebDav_PrincipalBackend implements \Sabre\DAVACL\PrincipalBackend\BackendInterface
 {
     const PREFIX_USERS  = 'principals/users';
     const PREFIX_GROUPS = 'principals/groups';
+    const SHARED        = 'shared';
     
     /**
      * (non-PHPdoc)
      * @see Sabre\DAVACL\IPrincipalBackend::getPrincipalsByPrefix()
-     * @todo currently we return the current user and his groups only // we should return ALL users/groups here
      */
     public function getPrincipalsByPrefix($prefixPath) 
     {
@@ -65,6 +62,7 @@ class Tinebase_WebDav_PrincipalBackend implements DAVACL\PrincipalBackend\Backen
                     $principals[] = $this->_contactToPrincipal($contact);
                 }
                 
+                $principals[] = $this->_contactForSharedPrincipal();
                 
                 break;
         }
@@ -83,7 +81,39 @@ class Tinebase_WebDav_PrincipalBackend implements DAVACL\PrincipalBackend\Backen
         
         list($prefix, $id) = \Sabre\DAV\URLUtil::splitPath($path);
         
+        // special handling for calendar proxy principals
+        // they are groups in the user namespace
+        if (in_array($id, array('calendar-proxy-read', 'calendar-proxy-write'))) {
+            $path = $prefix;
+            
+            // set prefix to calendar-proxy-read or calendar-proxy-write
+            $prefix = $id;
+            
+            list(, $id) = \Sabre\DAV\URLUtil::splitPath($path);
+        }
+        
         switch ($prefix) {
+            case 'calendar-proxy-read':
+                return null;
+                
+                break;
+                
+            case 'calendar-proxy-write':
+                // does the account exist
+                $contactPrincipal = $this->getPrincipalByPath(self::PREFIX_USERS . '/' . $id);
+                
+                if (!$contactPrincipal) {
+                    return null;
+                }
+                
+                $principal = array(
+                    'uri'                     => $contactPrincipal['uri'] . '/' . $prefix,
+                    '{' . \Sabre\CalDAV\Plugin::NS_CALDAV . '}calendar-user-type'  => 'GROUP',
+                    '{' . \Sabre\CalDAV\Plugin::NS_CALENDARSERVER . '}record-type' => 'groups'
+                );
+                
+                break;
+                
             case self::PREFIX_GROUPS:
                 $filter = new Addressbook_Model_ListFilter(array(
                     array(
@@ -109,27 +139,32 @@ class Tinebase_WebDav_PrincipalBackend implements DAVACL\PrincipalBackend\Backen
                 break;
                 
             case self::PREFIX_USERS:
-                $filter = new Addressbook_Model_ContactFilter(array(
-                    array(
-                        'field'     => 'type',
-                        'operator'  => 'equals',
-                        'value'     => Addressbook_Model_Contact::CONTACTTYPE_USER
-                    ),
-                    array(
-                        'field'     => 'id',
-                        'operator'  => 'equals',
-                        'value'     => $id
-                    ),
-                ));
-                
-                $contact = Addressbook_Controller_Contact::getInstance()->search($filter)->getFirstRecord();
-                
-                if (!$contact) {
-                    return null;
+                if ($id === self::SHARED) {
+                    $principal = $this->_contactForSharedPrincipal();
+                    
+                } else {
+                    $filter = new Addressbook_Model_ContactFilter(array(
+                        array(
+                            'field'     => 'type',
+                            'operator'  => 'equals',
+                            'value'     => Addressbook_Model_Contact::CONTACTTYPE_USER
+                        ),
+                        array(
+                            'field'     => 'id',
+                            'operator'  => 'equals',
+                            'value'     => $id
+                        ),
+                    ));
+                    
+                    $contact = Addressbook_Controller_Contact::getInstance()->search($filter)->getFirstRecord();
+                    
+                    if (!$contact) {
+                        return null;
+                    }
+                    
+                    $principal = $this->_contactToPrincipal($contact);
                 }
                 
-                $principal = $this->_contactToPrincipal($contact);
-                
                 break;
         }
         
@@ -144,31 +179,107 @@ class Tinebase_WebDav_PrincipalBackend implements DAVACL\PrincipalBackend\Backen
     {
         $result = array();
         
-        list($path, $listId) = Sabre\DAV\URLUtil::splitPath($principal);
+        list($prefix, $id) = \Sabre\DAV\URLUtil::splitPath($principal);
         
-        if ($path == self::PREFIX_GROUPS) {
-            $filter = new Addressbook_Model_ListFilter(array(
-                array(
-                    'field'     => 'type',
-                    'operator'  => 'equals',
-                    'value'     => Addressbook_Model_List::LISTTYPE_GROUP
-                ),
-                array(
-                    'field'     => 'id',
-                    'operator'  => 'equals',
-                    'value'     => $listId
-                ),
-            ));
+        // special handling for calendar proxy principals
+        // they are groups in the user namespace
+        if (in_array($id, array('calendar-proxy-read', 'calendar-proxy-write'))) {
+            $path = $prefix;
             
-            $list = Addressbook_Controller_List::getInstance()->search($filter)->getFirstRecord();
+            // set prefix to calendar-proxy-read or calendar-proxy-write
+            $prefix = $id;
             
-            if (!$list) {
+            list(, $id) = \Sabre\DAV\URLUtil::splitPath($path);
+        }
+        
+        switch ($prefix) {
+            case 'calendar-proxy-read':
                 return array();
-            }
-            
-            foreach ($list->members as $member) {
-                $result[] = self::PREFIX_USERS . '/' . $member;
-            }
+                
+                break;
+                
+            case 'calendar-proxy-write':
+                if ($id === self::SHARED) {
+                    // check if account has the right to run the calendar at all
+                    if (!Tinebase_Acl_Roles::getInstance()->hasRight('Calendar', Tinebase_Core::getUser(), Tinebase_Acl_Rights::RUN)) {
+                        return array();
+                    }
+                    
+                    // collect all users which have access to any of the calendars of this user
+                    $sharedContainerSync = Tinebase_Container::getInstance()->getSharedContainer(Tinebase_Core::getUser(), 'Calendar_Model_Event', Tinebase_Model_Grants::GRANT_SYNC);
+                    
+                    if ($sharedContainerSync->count() > 0) {
+                        $sharedContainerRead = Tinebase_Container::getInstance()->getSharedContainer(Tinebase_Core::getUser(), 'Calendar_Model_Event', Tinebase_Model_Grants::GRANT_READ);
+                        
+                        $sharedContainerIds = array_intersect($sharedContainerSync->getArrayOfIds(), $sharedContainerRead->getArrayOfIds());
+                        
+                        $result = $this->_containerGrantsToPrincipals($sharedContainerSync->filter('id', $sharedContainerIds));
+                    }
+                    
+                } else {
+                    $filter = new Addressbook_Model_ContactFilter(array(
+                        array(
+                            'field'     => 'type',
+                            'operator'  => 'equals',
+                            'value'     => Addressbook_Model_Contact::CONTACTTYPE_USER
+                        ),
+                        array(
+                            'field'     => 'id',
+                            'operator'  => 'equals',
+                            'value'     => $id
+                        ),
+                    ));
+                    
+                    $contact = Addressbook_Controller_Contact::getInstance()->search($filter)->getFirstRecord();
+                    
+                    if (!$contact instanceof Addressbook_Model_Contact || !$contact->account_id) {
+                        return array();
+                    }
+                    
+                    // check if account has the right to run the calendar at all
+                    if (!Tinebase_Acl_Roles::getInstance()->hasRight('Calendar', $contact->account_id, Tinebase_Acl_Rights::RUN)) {
+                        return array();
+                    }
+                    
+                    // collect all users which have access to any of the calendars of this user
+                    $personalContainerSync = Tinebase_Container::getInstance()->getPersonalContainer(Tinebase_Core::getUser(), 'Calendar_Model_Event', $contact->account_id, Tinebase_Model_Grants::GRANT_SYNC);
+                    
+                    if ($personalContainerSync->count() > 0) {
+                        $personalContainerRead = Tinebase_Container::getInstance()->getPersonalContainer(Tinebase_Core::getUser(), 'Calendar_Model_Event', $contact->account_id, Tinebase_Model_Grants::GRANT_READ);
+                        
+                        $personalContainerIds = array_intersect($personalContainerSync->getArrayOfIds(), $personalContainerRead->getArrayOfIds());
+                        
+                        $result = $this->_containerGrantsToPrincipals($personalContainerSync->filter('id', $personalContainerIds));
+                    }
+                }
+                
+                break;
+                
+            case self::PREFIX_GROUPS:
+                $filter = new Addressbook_Model_ListFilter(array(
+                    array(
+                        'field'     => 'type',
+                        'operator'  => 'equals',
+                        'value'     => Addressbook_Model_List::LISTTYPE_GROUP
+                    ),
+                    array(
+                        'field'     => 'id',
+                        'operator'  => 'equals',
+                        'value'     => $id
+                    ),
+                ));
+                
+                $list = Addressbook_Controller_List::getInstance()->search($filter)->getFirstRecord();
+                
+                if (!$list) {
+                    return array();
+                }
+                
+                foreach ($list->members as $member) {
+                    $result[] = self::PREFIX_USERS . '/' . $member;
+                }
+                
+                break;
         }
         
         return $result;
@@ -190,15 +301,47 @@ class Tinebase_WebDav_PrincipalBackend implements DAVACL\PrincipalBackend\Backen
                 break;
         
             case self::PREFIX_USERS:
-                $user = Tinebase_User::getInstance()->getUserByProperty('contactId', $contactId);
-                
-                $groupIds = Tinebase_Group::getInstance()->getGroupMemberships($user);
-                $groups   = Tinebase_Group::getInstance()->getMultiple($groupIds);
-                
-                foreach ($groups as $group) {
-                    $result[] = self::PREFIX_GROUPS . '/' . $group->list_id;
+                if ($contactId !== self::SHARED) {
+                    $user = Tinebase_User::getInstance()->getUserByProperty('contactId', $contactId);
+                    
+                    $groupIds = Tinebase_Group::getInstance()->getGroupMemberships($user);
+                    $groups   = Tinebase_Group::getInstance()->getMultiple($groupIds);
+                    
+                    foreach ($groups as $group) {
+                        if ($group->list_id && $group->visibility == Tinebase_Model_Group::VISIBILITY_DISPLAYED) {
+                            $result[] = self::PREFIX_GROUPS . '/' . $group->list_id;
+                        }
+                    }
+                    
+                    // return user only, if the containers have the sync AND read grant set
+                    $otherUsersSync = Tinebase_Container::getInstance()->getOtherUsers($user, 'Calendar', Tinebase_Model_Grants::GRANT_SYNC);
+                    
+                    if ($otherUsersSync->count() > 0) {
+                        $otherUsersRead = Tinebase_Container::getInstance()->getOtherUsers($user, 'Calendar', Tinebase_Model_Grants::GRANT_READ);
+                        
+                        $otherUsersIds = array_intersect($otherUsersSync->getArrayOfIds(), $otherUsersRead->getArrayOfIds());
+                        
+                        foreach ($otherUsersIds as $userId) {
+                            if ($otherUsersSync->getById($userId)->contact_id && $otherUsersSync->getById($userId)->visibility == Tinebase_Model_User::VISIBILITY_DISPLAYED) {
+                                $result[] = self::PREFIX_USERS . '/' . $otherUsersSync->getById($userId)->contact_id . '/calendar-proxy-write';
+                            }
+                        }
+                    }
+                    
+                    // return user only, if the containers have the sync AND read grant set
+                    $sharedContainersSync = Tinebase_Container::getInstance()->getSharedContainer($user, 'Calendar', Tinebase_Model_Grants::GRANT_SYNC);
+                    
+                    if ($sharedContainersSync->count() > 0) {
+                        $sharedContainersRead = Tinebase_Container::getInstance()->getSharedContainer($user, 'Calendar', Tinebase_Model_Grants::GRANT_READ);
+                        
+                        $sharedContainerIds = array_intersect($sharedContainersSync->getArrayOfIds(), $sharedContainersRead->getArrayOfIds());
+                        
+                        if (count($sharedContainerIds) > 0) {
+                            $result[] = self::PREFIX_USERS . '/' . self::SHARED . '/calendar-proxy-write';
+                        }
+                    }
                 }
-        
+                
                 break;
         }
         
@@ -241,6 +384,7 @@ class Tinebase_WebDav_PrincipalBackend implements DAVACL\PrincipalBackend\Backen
      *
      * @param string $prefixPath
      * @param array $searchProperties
+     * @todo implement handling for shared pseudo user
      * @return array
      */
     public function searchPrincipals($prefixPath, array $searchProperties)
@@ -268,6 +412,14 @@ class Tinebase_WebDav_PrincipalBackend implements DAVACL\PrincipalBackend\Backen
                     )));
                 }
                 
+                if (!empty($searchProperties['{DAV:}displayname'])) {
+                    $filter->addFilter($filter->createFilter(array(
+                        'field'     => 'name',
+                        'operator'  => 'contains',
+                        'value'     => $searchProperties['{DAV:}displayname']
+                    )));
+                }
+                
                 $result = Addressbook_Controller_List::getInstance()->search($filter, null, false, true);
                 
                 foreach ($result as $listId) {
@@ -296,11 +448,38 @@ class Tinebase_WebDav_PrincipalBackend implements DAVACL\PrincipalBackend\Backen
                 if (!empty($searchProperties['{http://sabredav.org/ns}email-address'])) {
                     $filter->addFilter($filter->createFilter(array(
                         'field'     => 'email_query',
-                        'operator'  => 'equals',
+                        'operator'  => 'contains',
                         'value'     => $searchProperties['{http://sabredav.org/ns}email-address']
                     )));
                 }
                 
+                if (!empty($searchProperties['{DAV:}displayname'])) {
+                    $filter->addFilter($filter->createFilter(array(
+                        'field'     => 'query',
+                        'operator'  => 'contains',
+                        'value'     => $searchProperties['{DAV:}displayname']
+                    )));
+                }
+                
+                if (!empty($searchProperties['{' . \Sabre\CalDAV\Plugin::NS_CALENDARSERVER . '}first-name'])) {
+                    $filter->addFilter($filter->createFilter(array(
+                        'field'     => 'n_given',
+                        'operator'  => 'contains',
+                        'value'     => $searchProperties['{' . \Sabre\CalDAV\Plugin::NS_CALENDARSERVER . '}first-name']
+                    )));
+                }
+                
+                if (!empty($searchProperties['{' . \Sabre\CalDAV\Plugin::NS_CALENDARSERVER . '}last-name'])) {
+                    $filter->addFilter($filter->createFilter(array(
+                        'field'     => 'n_family',
+                        'operator'  => 'contains',
+                        'value'     => $searchProperties['{' . \Sabre\CalDAV\Plugin::NS_CALENDARSERVER . '}last-name']
+                    )));
+                }
+                
+                #if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(
+                #    __METHOD__ . '::' . __LINE__ . ' path: ' . $prefixPath . ' properties: ' . print_r($filter->toArray(), true));
+                
                 $result = Addressbook_Controller_Contact::getInstance()->search($filter, null, false, true);
                 
                 foreach ($result as $contactId) {
@@ -314,6 +493,26 @@ class Tinebase_WebDav_PrincipalBackend implements DAVACL\PrincipalBackend\Backen
     }
     
     /**
+     * return shared pseudo principal (principal for the shared containers) 
+     */
+    protected function _contactForSharedPrincipal()
+    {
+        $principal = array(
+            'uri'                     => self::PREFIX_USERS . '/' . self::SHARED,
+            '{DAV:}displayname'       => 'Principal for shared folders',
+            
+            '{' . \Sabre\CalDAV\Plugin::NS_CALDAV . '}calendar-user-type'  => 'INDIVIDUAL',
+            
+            '{' . \Sabre\CalDAV\Plugin::NS_CALENDARSERVER . '}record-type' => 'users',
+            '{' . \Sabre\CalDAV\Plugin::NS_CALENDARSERVER . '}first-name'  => 'Folders',
+            '{' . \Sabre\CalDAV\Plugin::NS_CALENDARSERVER . '}last-name'   => 'Shared'
+        );
+        
+        return $principal;
+        
+    }
+    
+    /**
      * convert contact model to principal array
      * 
      * @param Addressbook_Model_Contact $contact
@@ -340,6 +539,43 @@ class Tinebase_WebDav_PrincipalBackend implements DAVACL\PrincipalBackend\Backen
         return $principal;
     }
     
+    protected function _containerGrantsToPrincipals(Tinebase_Record_RecordSet $containers)
+    {
+        $result = array();
+        
+        foreach ($containers as $container) {
+            $grants = Tinebase_Container::getInstance()->getGrantsOfContainer($container);
+            
+            foreach ($grants as $grant) {
+                switch ($grant->account_type) {
+                    case 'group':
+                        $group = Tinebase_Group::getInstance()->getGroupById($grant->account_id);
+                        if ($group->list_id) {
+                            $result[] = self::PREFIX_GROUPS . '/' . $group->list_id;
+                        }
+                        break;
+                        
+                    case 'user':
+                        // skip if grant belongs to the owner of the calendar
+                        if ($contact->account_id == $grant->account_id) {
+                            continue;
+                        }
+                        $user = Tinebase_User::getInstance()->getUserById($grant->account_id);
+                        if ($user->contact_id) {
+                            $result[] = self::PREFIX_USERS . '/' . $user->contact_id;
+                        }
+                        
+                        break;
+                }
+            }
+        }
+        
+        // users and groups can be duplicate
+        $result = array_unique($result);
+        
+        return $result;
+    }
+    
     /**
      * convert list model to principal array
      * 
index 15b09a6..0a909e0 100644 (file)
@@ -1,10 +1,4 @@
 <?php
-
-use Sabre\DAV;
-use Sabre\DAVACL;
-use Sabre\CardDAV;
-use Sabre\CalDAV;
-
 /**
  * Tine 2.0
  *
@@ -12,7 +6,7 @@ use Sabre\CalDAV;
  * @subpackage  WebDAV
  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
  * @author      Lars Kneschke <l.kneschke@metaways.de>
- * @copyright   Copyright (c) 2011-2013 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright   Copyright (c) 2011-2014 Metaways Infosystems GmbH (http://www.metaways.de)
  */
 
 /**
@@ -22,53 +16,56 @@ use Sabre\CalDAV;
  *
  * @package     Tinebase
  * @subpackage  WebDAV
- * 
- * @todo this should look for webdav frontend in installed apps
  */
-class Tinebase_WebDav_Root extends DAV\SimpleCollection
+class Tinebase_WebDav_Root extends \Sabre\DAV\SimpleCollection
 {
     public function __construct()
     {
-        $caldavCalendarChildren = array();
-        $caldavTasksChildren    = array();
-        $carddavChildren        = array();
-        $webdavChildren         = array();
-        $ownCloudChildren       = array();
+        parent::__construct('root', array(
+            new \Sabre\DAV\SimpleCollection('principals', array(
+                new Tinebase_WebDav_PrincipalCollection(new Tinebase_WebDav_PrincipalBackend(), Tinebase_WebDav_PrincipalBackend::PREFIX_USERS),
+                new Tinebase_WebDav_PrincipalCollection(new Tinebase_WebDav_PrincipalBackend(), Tinebase_WebDav_PrincipalBackend::PREFIX_GROUPS)
+            ))
+        ));
         
-        if(Tinebase_Core::getUser()->hasRight('Calendar', Tinebase_Acl_Rights::RUN)) {
-            $caldavCalendarChildren[] = new Calendar_Frontend_CalDAV();
+        if (Tinebase_Core::getUser()->hasRight('Calendar', Tinebase_Acl_Rights::RUN)) {
+            $this->addChild(
+                new Calendar_Frontend_WebDAV(\Sabre\CalDAV\Plugin::CALENDAR_ROOT, true)
+            );
         }
        
-        if(Tinebase_Core::getUser()->hasRight('Tasks', Tinebase_Acl_Rights::RUN)) {
-            $caldavTasksChildren[]    = new Tasks_Frontend_CalDAV();
+        if (Tinebase_Core::getUser()->hasRight('Tasks', Tinebase_Acl_Rights::RUN)) {
+            $this->addChild(
+                new Tasks_Frontend_WebDAV('tasks', true)
+            );
         }
 
-        if(Tinebase_Core::getUser()->hasRight('Addressbook', Tinebase_Acl_Rights::RUN)) {
-            $carddavChildren[] = new Addressbook_Frontend_CardDAV();
+        if (Tinebase_Core::getUser()->hasRight('Addressbook', Tinebase_Acl_Rights::RUN)) {
+            $this->addChild(
+                new Addressbook_Frontend_WebDAV(\Sabre\CardDAV\Plugin::ADDRESSBOOK_ROOT, true)
+            );
         }
         
-        if(Tinebase_Core::getUser()->hasRight('Filemanager', Tinebase_Acl_Rights::RUN)) {
-            $ownCloudChildren[] = new Filemanager_Frontend_WebDAV('webdav');
+        // main entry point for ownCloud 
+        if (Tinebase_Core::getUser()->hasRight('Filemanager', Tinebase_Acl_Rights::RUN)) {
+            $this->addChild(
+                new \Sabre\DAV\SimpleCollection(
+                    'remote.php', 
+                    array(new Filemanager_Frontend_WebDAV('webdav'))
+                )
+            );
         }
         
-        foreach (array('Addressbook', 'Calendar', 'Felamimail', 'Filemanager', 'Tasks') as $application) {
+        // webdav tree
+        $webDAVCollection = new \Sabre\DAV\SimpleCollection('webdav');
+        
+        foreach (array('Addressbook', 'Calendar', 'Tasks', 'Felamimail', 'Filemanager') as $application) {
             $applicationClass = $application . '_Frontend_WebDAV';
             if (Tinebase_Core::getUser()->hasRight($application, Tinebase_Acl_Rights::RUN) && class_exists($applicationClass)) {
-                $webdavChildren[] = new $applicationClass($application);
+                $webDAVCollection->addChild(new $applicationClass($application));
             }
         }
         
-        parent::__construct('root', array(
-            new DAV\SimpleCollection(CardDAV\Plugin::ADDRESSBOOK_ROOT, $carddavChildren),
-            new DAV\SimpleCollection(CalDAV\Plugin::CALENDAR_ROOT,     $caldavCalendarChildren),
-            new DAV\SimpleCollection('tasks',                          $caldavTasksChildren),
-            new DAV\SimpleCollection('webdav',                         $webdavChildren),
-            new DAV\SimpleCollection('principals', array(
-                new Tinebase_WebDav_PrincipalCollection(new Tinebase_WebDav_PrincipalBackend(), Tinebase_WebDav_PrincipalBackend::PREFIX_USERS),
-                new Tinebase_WebDav_PrincipalCollection(new Tinebase_WebDav_PrincipalBackend(), Tinebase_WebDav_PrincipalBackend::PREFIX_GROUPS)
-            )),
-            // main entry point for ownCloud 
-            new DAV\SimpleCollection('remote.php',                     $ownCloudChildren)
-        ));
+        $this->addChild($webDAVCollection);
     }
 }