implemented createExtendCollection needed for MKCALENDAR and MKCOL
authorLars Kneschke <l.kneschke@metaways.de>
Tue, 29 Apr 2014 14:04:07 +0000 (16:04 +0200)
committerPhilipp Schüle <p.schuele@metaways.de>
Thu, 4 Sep 2014 09:26:34 +0000 (11:26 +0200)
support

* added generic createExtendCollection to AbstractContainerTree class
* added support for Tasks container to Calender WebDAV frontend class

Change-Id: I7786a3950c27affc89ceabcb3f0e15176ec3a5e7
Reviewed-on: http://gerrit.tine20.com/customers/578
Tested-by: Jenkins CI (http://ci.tine20.com/)
Reviewed-by: Lars Kneschke <l.kneschke@metaways.de>
Reviewed-by: Philipp Schüle <p.schuele@metaways.de>
tests/tine20/Calendar/Frontend/CalDAVTest.php
tine20/Calendar/Frontend/WebDAV.php
tine20/Tinebase/WebDav/Collection/AbstractContainerTree.php
tine20/Tinebase/WebDav/Container/Abstract.php

index 4111f7f..43a7306 100644 (file)
@@ -130,6 +130,64 @@ class Calendar_Frontend_CalDAVTest extends TestCase
     }
 
     /**
+     * test to create a new directory
+     */
+    public function testCreateExtendedCollectionVEvent()
+    {
+        $randomName = Tinebase_Record_Abstract::generateUID();
+        
+        $collection = new Calendar_Frontend_WebDAV(\Sabre\CalDAV\Plugin::CALENDAR_ROOT . '/' . Tinebase_Core::getUser()->contact_id, true);
+        
+        $collection->createExtendedCollection(
+            'B1B3BEA0-F1F9-409F-B1A0-43E41119F851', 
+            array('{DAV:}collection', '{urn:ietf:params:xml:ns:caldav}calendar'),
+            array(
+                '{DAV:}displayname' => $randomName,
+                '{http://apple.com/ns/ical/}calendar-color' => '#711A76FF',
+                '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set' => new \Sabre\CalDAV\Property\SupportedCalendarComponentSet(array('VEVENT'))
+            )
+        );
+        
+        $container = Tinebase_Container::getInstance()->getContainerByName('Calendar', $randomName, Tinebase_Model_Container::TYPE_PERSONAL, Tinebase_Core::getUser());
+        $this->assertTrue($container instanceof Tinebase_Model_Container);
+        
+        $subCollection = $collection->getChild('B1B3BEA0-F1F9-409F-B1A0-43E41119F851');
+        $this->assertEquals('B1B3BEA0-F1F9-409F-B1A0-43E41119F851', $subCollection->getName());
+        
+        $properties = $subCollection->getProperties(array('{DAV:}displayname'));
+        $this->assertEquals($randomName, $properties['{DAV:}displayname']);
+    }
+
+    /**
+     * test to create a new directory
+     */
+    public function testCreateExtendedCollectionVTodo()
+    {
+        $randomName = Tinebase_Record_Abstract::generateUID();
+        
+        $collection = new Calendar_Frontend_WebDAV(\Sabre\CalDAV\Plugin::CALENDAR_ROOT . '/' . Tinebase_Core::getUser()->contact_id, true);
+        
+        $collection->createExtendedCollection(
+            'B1B3BEA0-F1F9-409F-B1A0-43E41119F851', 
+            array('{DAV:}collection', '{urn:ietf:params:xml:ns:caldav}calendar'),
+            array(
+                '{DAV:}displayname' => $randomName,
+                '{http://apple.com/ns/ical/}calendar-color' => '#711A76FF',
+                '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set' => new \Sabre\CalDAV\Property\SupportedCalendarComponentSet(array('VTODO'))
+            )
+        );
+        
+        $container = Tinebase_Container::getInstance()->getContainerByName('Tasks', $randomName, Tinebase_Model_Container::TYPE_PERSONAL, Tinebase_Core::getUser());
+        $this->assertTrue($container instanceof Tinebase_Model_Container);
+        
+        $subCollection = $collection->getChild('B1B3BEA0-F1F9-409F-B1A0-43E41119F851');
+        $this->assertEquals('B1B3BEA0-F1F9-409F-B1A0-43E41119F851', $subCollection->getName());
+        
+        $properties = $subCollection->getProperties(array('{DAV:}displayname'));
+        $this->assertEquals($randomName, $properties['{DAV:}displayname']);
+    }
+
+    /**
      * 
      * @return \Sabre\DAV\ObjectTree
      */
index 0a7a824..f73412f 100644 (file)
@@ -19,6 +19,28 @@ class Calendar_Frontend_WebDAV extends Tinebase_WebDav_Collection_AbstractContai
 {
     /**
      * (non-PHPdoc)
+     * @see \Sabre\DAV\IExtendedCollection::createExtendedCollection()
+     */
+    function createExtendedCollection($name, array $resourceType, array $properties)
+    {
+        if (count($this->_getPathParts()) === 2 && isset($properties['{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set'])) {
+            $componentSet = $properties['{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set'];
+            
+            if ($componentSet instanceof \Sabre\CalDAV\Property\SupportedCalendarComponentSet &&
+                in_array('VTODO', $componentSet->getValue()) &&
+                Tinebase_Core::getUser()->hasRight('Tasks', Tinebase_Acl_Rights::RUN)
+            ) {
+                $tasks = new Tasks_Frontend_WebDAV('tasks/' . $this->getName(), $this->_useIdAsName);
+                
+                return $tasks->createExtendedCollection($name, $resourceType, $properties);
+            }
+        }
+        
+        return parent::createExtendedCollection($name, $resourceType, $properties);
+    }
+    
+    /**
+     * (non-PHPdoc)
      * @see Tinebase_WebDav_Collection_AbstractContainerTree::getChild()
      */
     public function getChild($name)
index 5893558..54212dd 100644 (file)
@@ -15,7 +15,7 @@
  * @package     Tinebase
  * @subpackage  WebDAV
  */
-abstract class Tinebase_WebDav_Collection_AbstractContainerTree extends \Sabre\DAV\Collection implements \Sabre\DAV\IProperties, \Sabre\DAVACL\IACL
+abstract class Tinebase_WebDav_Collection_AbstractContainerTree extends \Sabre\DAV\Collection implements \Sabre\DAV\IProperties, \Sabre\DAVACL\IACL, \Sabre\DAV\IExtendedCollection
 {
     /**
      * the current application object
@@ -78,41 +78,25 @@ abstract class Tinebase_WebDav_Collection_AbstractContainerTree extends \Sabre\D
     /**
      * (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()
+        return $this->_createContainer(array(
+            'name' => $name
+        ));
+    }
+    
+    /**
+     * (non-PHPdoc)
+     * @see \Sabre\DAV\IExtendedCollection::createExtendedCollection()
+     */
+    function createExtendedCollection($name, array $resourceType, array $properties)
+    {
+        return $this->_createContainer(array(
+            'name'  => isset($properties['{DAV:}displayname']) ? $properties['{DAV:}displayname'] : $name,
+            'uuid'  => $name,
+            'color' => isset($properties['{http://apple.com/ns/ical/}calendar-color']) ? substr($properties['{http://apple.com/ns/ical/}calendar-color'], 0, 7) : null
         ));
-
-        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;
-        
     }
     
     /**
@@ -156,11 +140,17 @@ abstract class Tinebase_WebDav_Collection_AbstractContainerTree extends \Sabre\D
             # list container
             case 2:
                 if (array_value(1, $this->_getPathParts()) == Tinebase_Model_Container::TYPE_SHARED) {
-                    try {
+                    try { 
                         if ($name instanceof Tinebase_Model_Container) {
                             $container = $name;
                         } elseif ($this->_useIdAsName) {
-                            $container = Tinebase_Container::getInstance()->getContainerById($name);
+                            // first try to fetch by uuid ...
+                            try {
+                                $container = Tinebase_Container::getInstance()->getByProperty($name, 'uuid');
+                            } catch (Tinebase_Exception_NotFound $tenf) {
+                                // ... if that fails by id
+                                $container = Tinebase_Container::getInstance()->getContainerById($name);
+                            }
                         } else {
                             $container = Tinebase_Container::getInstance()->getContainerByName(
                                 $this->_getAppliationName(), 
@@ -174,7 +164,7 @@ abstract class Tinebase_WebDav_Collection_AbstractContainerTree extends \Sabre\D
                         
                     } catch (Tinebase_Exception_InvalidArgument $teia) {
                         // invalid container id provided
-                        throw new \SabreDAV\Exception\NotFound("Directory $this->_path/$name not found");
+                        throw new \Sabre\DAV\Exception\NotFound("Directory $this->_path/$name not found");
                     }
                 } elseif ($this->_hasRecordFolder && array_value(1, $this->_getPathParts()) == Tinebase_FileSystem::FOLDER_TYPE_RECORDS) {
                     
@@ -192,7 +182,14 @@ abstract class Tinebase_WebDav_Collection_AbstractContainerTree extends \Sabre\D
                         if ($name instanceof Tinebase_Model_Container) {
                             $container = $name;
                         } elseif ($this->_useIdAsName) {
-                            $container = Tinebase_Container::getInstance()->getContainerById($name);
+                            // first try to fetch by uuid ...
+                            try {
+                                $container = Tinebase_Container::getInstance()->getByProperty((string) $name, 'uuid');
+                            } catch (Tinebase_Exception_NotFound $tenf) {
+                                // ... if that fails by id
+                                $container = Tinebase_Container::getInstance()->getContainerById($name);
+                            }
+                            
                         } else { 
                             $container = Tinebase_Container::getInstance()->getContainerByName(
                                 $this->_getAppliationName(), 
@@ -207,7 +204,7 @@ abstract class Tinebase_WebDav_Collection_AbstractContainerTree extends \Sabre\D
                         
                     } catch (Tinebase_Exception_InvalidArgument $teia) {
                         // invalid container id provided
-                        throw new \SabreDAV\Exception\NotFound("Directory $this->_path/$name not found");
+                        throw new \Sabre\DAV\Exception\NotFound("Directory $this->_path/$name not found");
                     }
                     
                 } else {
@@ -574,6 +571,41 @@ abstract class Tinebase_WebDav_Collection_AbstractContainerTree extends \Sabre\D
     }
     
     /**
+     * creates a new container
+     * 
+     * @todo allow to create personal folders only when in currents users own path
+     * 
+     * @param  array  $properties  properties for new container
+     * @throws \Sabre\DAV\Exception\Forbidden
+     * @return Tinebase_Model_Container
+     */
+    protected function _createContainer(array $properties) 
+    {
+        if (count($this->_getPathParts()) !== 2) {
+            throw new \Sabre\DAV\Exception\Forbidden('Permission denied to create directory ' . $properties['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_merge($properties, array(
+            '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;
+    }
+    
+    /**
      * return application name
      * 
      * @return string
index 34a2aac..1627594 100644 (file)
@@ -289,7 +289,15 @@ abstract class Tinebase_WebDav_Container_Abstract extends \Sabre\DAV\Collection
      */
     public function getName()
     {
-        return $this->_useIdAsName == true ? $this->_container->getId() : $this->_container->name;
+        if ($this->_useIdAsName == true) {
+            if ($this->_container->uuid) {
+                return $this->_container->uuid;
+            } else {
+                return $this->_container->getId();
+            }
+        } 
+        
+        return $this->_container->name;
     }
     
     /**