[Pkg-owncloud-commits] [php-sabredav] 18/220: Working towards implementing sharing in default backends.

David Prévot taffit at moszumanska.debian.org
Thu May 12 01:21:02 UTC 2016


This is an automated email from the git hooks/post-receive script.

taffit pushed a commit to branch master
in repository php-sabredav.

commit 11bdb03155ed63f4439c0223c12ef2315d2f38d5
Author: Evert Pot <me at evertpot.com>
Date:   Sat Oct 17 19:22:24 2015 -0400

    Working towards implementing sharing in default backends.
    
    Very broken at the moment.
---
 bin/migrateto31.php                   | 257 ++++++++++++++++++++++++++++++
 examples/sql/mysql.calendars.sql      |  12 +-
 examples/sql/sqlite.calendars.sql     |  10 +-
 lib/CalDAV/Backend/PDO.php            |  58 +++++--
 lib/CalDAV/Backend/SharingSupport.php |  34 +---
 lib/CalDAV/Backend/SimplePDO.php      | 287 ++++++++++++++++++++++++++++++++++
 lib/DAV/Sharing/Plugin.php            |   7 +-
 7 files changed, 617 insertions(+), 48 deletions(-)

diff --git a/bin/migrateto31.php b/bin/migrateto31.php
new file mode 100755
index 0000000..0052c6d
--- /dev/null
+++ b/bin/migrateto31.php
@@ -0,0 +1,257 @@
+#!/usr/bin/env php
+<?php
+
+echo "SabreDAV migrate script for version 3.1\n";
+
+if ($argc<2) {
+
+    echo <<<HELLO
+
+This script help you migrate from a 3.0 database to 3.1 and later
+
+Changes:
+* Created a new calendar_instances table to support calendar sharing.
+* Remove a lot of columns from calendars.
+
+Keep in mind that ALTER TABLE commands will be executed. If you have a large
+dataset this may mean that this process takes a while.
+
+Make a back-up first. This script has been tested, but the amount of
+potential variants are extremely high, so it's impossible to deal with every
+possible situation.
+
+In the worst case, you will lose all your data. This is not an overstatement.
+
+Lastly, if you are upgrading from an older version than 3.0, make sure you run
+the earlier migration script first. Migration scripts must be ran in order.
+
+Usage:
+
+php {$argv[0]} [pdo-dsn] [username] [password]
+
+For example:
+
+php {$argv[0]} "mysql:host=localhost;dbname=sabredav" root password
+php {$argv[0]} sqlite:data/sabredav.db
+
+HELLO;
+
+    exit();
+
+}
+
+// There's a bunch of places where the autoloader could be, so we'll try all of
+// them.
+$paths = [
+    __DIR__ . '/../vendor/autoload.php',
+    __DIR__ . '/../../../autoload.php',
+];
+
+foreach($paths as $path) {
+    if (file_exists($path)) {
+        include $path;
+        break;
+    }
+}
+
+$dsn = $argv[1];
+$user = isset($argv[2])?$argv[2]:null;
+$pass = isset($argv[3])?$argv[3]:null;
+
+$backupPostfix = time();
+
+echo "Connecting to database: " . $dsn . "\n";
+
+$pdo = new PDO($dsn, $user, $pass);
+$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
+
+$driver = $pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
+
+switch($driver) {
+
+    case 'mysql' :
+        echo "Detected MySQL.\n";
+        break;
+    case 'sqlite' :
+        echo "Detected SQLite.\n";
+        break;
+    default :
+        echo "Error: unsupported driver: " . $driver . "\n";
+        die(-1);
+}
+
+echo "Creating 'calendar_instances'\n";
+$addValueType = false;
+try {
+    $result = $pdo->query('SELECT * FROM calendar_instances LIMIT 1');
+    $result->fetch(\PDO::FETCH_ASSOC);
+    echo "calendar_instances exists. Assuming this part of the migration has already been done.\n";
+} catch (Exception $e) {
+    echo "calendar_instances does not yet exist. Creating table and migrating data.\n";
+
+    switch($driver) {
+        case 'mysql' :
+            $pdo->exec(<<<SQL
+CREATE TABLE calendar_instances (
+    id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
+    calendarid INTEGER UNSIGNED NOT NULL,
+    principaluri VARBINARY(100),
+    access TINYINT(1) NOT NULL DEFAULT '1' COMMENT '1 = owner, 2 = readwrite, 3 = read',
+    displayname VARCHAR(100),
+    uri VARBINARY(200),
+    description TEXT,
+    calendarorder INT(11) UNSIGNED NOT NULL DEFAULT '0',
+    calendarcolor VARBINARY(10),
+    timezone TEXT,
+    transparent TINYINT(1) NOT NULL DEFAULT '0',
+    UNIQUE(principaluri, uri)
+);
+SQL
+        );
+            $pdo->exec("
+INSERT INTO calendar_instances
+    (
+        calendarid,
+        principaluri,
+        access,
+        displayname,
+        uri,
+        description,
+        calendarorder,
+        calendarcolor,
+        transparent
+    )
+SELECT
+    id,
+    principaluri,
+    1,
+    displayname,
+    uri,
+    description,
+    calendarorder,
+    calendarcolor,
+    transparent
+FROM calendars
+"); 
+            break;
+        case 'sqlite' :
+            $pdo->exec(<<<SQL
+CREATE TABLE calendar_instances (
+    id integer primary key asc,
+    calendarid integer,
+    principaluri text,
+    access integer COMMENT '1 = owner, 2 = readwrite, 3 = read',
+    displayname text,
+    uri text,
+    description text,
+    calendarorder integer,
+    calendarcolor text,
+    timezone text,
+    transparent bool
+);
+SQL
+        );
+            $pdo->exec("
+INSERT INTO calendar_instances
+    (
+        calendarid,
+        principaluri,
+        access,
+        displayname,
+        uri,
+        description,
+        calendarorder,
+        calendarcolor,
+        transparent
+    )
+SELECT
+    id,
+    principaluri,
+    1,
+    displayname,
+    uri,
+    description,
+    calendarorder,
+    calendarcolor,
+    transparent
+FROM calendars
+"); 
+            break;
+    }
+
+}
+try {
+    $result = $pdo->query('SELECT * FROM calendars LIMIT 1');
+    $row = $result->fetch(\PDO::FETCH_ASSOC);
+
+    if (!$row) {
+        echo "Source table is empty.\n";
+        $migrateCalendars = true;
+    } 
+
+    $columnCount = count($row);
+    if ($columnCount === 3) {
+        echo "The calendars table has 3 columns already. Assuming this part of the migration was already done.\n";
+        $migrateCalendars = false;
+    } else {
+        echo "The calendars table has " . $columnCount . " columns.\n";
+        $migrateCalendars = true;
+    }
+
+} catch (Exception $e) {
+    echo "calendars table does not exist. This is a major problem. Exiting.\n";
+    exit(-1);
+}
+
+if ($migrateCalendars) {
+
+    $calendarBackup = 'calendars_3_0_' . $backupPostfix;
+    echo "Backing up 'calendars' to '", $calendarBackup, "'\n";
+
+    switch($driver) {
+        case 'mysql' :
+            $pdo->exec('RENAME TABLE calendars TO ' . $calendarBackup);
+            break;
+        case 'sqlite' :
+            $pdo->exec('ALTER TABLE calendars RENAME TO ' . $calendarBackup);
+            break;
+
+    }
+
+    echo "Creating new calendars table.\n";
+    switch($driver) {
+        case 'mysql' :
+            $pdo->exec(<<<SQL
+CREATE TABLE calendars (
+    id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
+    synctoken INTEGER UNSIGNED NOT NULL DEFAULT '1',
+    components VARBINARY(20)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+SQL
+);
+            break;
+        case 'sqlite' :
+            $pdo->exec(<<<SQL
+CREATE TABLE calendars (
+    id integer primary key asc,
+    synctoken integer,
+    components text
+);
+SQL
+        );
+            break;
+
+    }
+
+    echo "Migrating data from old to new table\n";
+
+    $pdo->exec(<<<SQL
+INSERT INTO calendars (id, synctoken, components) SELECT id, synctoken, components FROM $calendarBackup
+SQL
+    );
+
+}
+
+
+echo "Upgrade to 3.1 schema completed.\n";
diff --git a/examples/sql/mysql.calendars.sql b/examples/sql/mysql.calendars.sql
index 55d3b48..04775c5 100644
--- a/examples/sql/mysql.calendars.sql
+++ b/examples/sql/mysql.calendars.sql
@@ -15,18 +15,24 @@ CREATE TABLE calendarobjects (
 
 CREATE TABLE calendars (
     id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
+    synctoken INTEGER UNSIGNED NOT NULL DEFAULT '1',
+    components VARBINARY(20)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+
+CREATE TABLE calendar_instances (
+    id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
+    calendarid INTEGER UNSIGNED NOT NULL,
     principaluri VARBINARY(100),
+    access TINYINT(1) NOT NULL DEFAULT '1' COMMENT '1 = owner, 2 = readwrite, 3 = read',
     displayname VARCHAR(100),
     uri VARBINARY(200),
-    synctoken INTEGER UNSIGNED NOT NULL DEFAULT '1',
     description TEXT,
     calendarorder INT(11) UNSIGNED NOT NULL DEFAULT '0',
     calendarcolor VARBINARY(10),
     timezone TEXT,
-    components VARBINARY(20),
     transparent TINYINT(1) NOT NULL DEFAULT '0',
     UNIQUE(principaluri, uri)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+);
 
 CREATE TABLE calendarchanges (
     id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
diff --git a/examples/sql/sqlite.calendars.sql b/examples/sql/sqlite.calendars.sql
index 4a17f0d..87e5270 100644
--- a/examples/sql/sqlite.calendars.sql
+++ b/examples/sql/sqlite.calendars.sql
@@ -14,15 +14,21 @@ CREATE TABLE calendarobjects (
 
 CREATE TABLE calendars (
     id integer primary key asc,
+    synctoken integer,
+    components text
+);
+
+CREATE TABLE calendar_instances (
+    id integer primary key asc,
+    calendarid integer,
     principaluri text,
+    access integer COMMENT '1 = owner, 2 = readwrite, 3 = read',
     displayname text,
     uri text,
-    synctoken integer,
     description text,
     calendarorder integer,
     calendarcolor text,
     timezone text,
-    components text,
     transparent bool
 );
 
diff --git a/lib/CalDAV/Backend/PDO.php b/lib/CalDAV/Backend/PDO.php
index c35ffe2..97c90c0 100644
--- a/lib/CalDAV/Backend/PDO.php
+++ b/lib/CalDAV/Backend/PDO.php
@@ -17,7 +17,13 @@ use Sabre\DAV\Exception\Forbidden;
  * @author Evert Pot (http://evertpot.com/)
  * @license http://sabre.io/license/ Modified BSD License
  */
-class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, SchedulingSupport {
+class PDO extends AbstractBackend
+    implements
+        SyncSupport,
+        SubscriptionSupport,
+        SchedulingSupport,
+        SharingSupport
+    {
 
     /**
      * We need to specify a max date, because we need to stop *somewhere*
@@ -44,6 +50,16 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S
     public $calendarTableName = 'calendars';
 
     /**
+     * The table name that will be used for calendars instances.
+     *
+     * A single calendar can have multiple instances, if the calendar is
+     * shared.
+     *
+     * @var string
+     */
+    public $calendarTableName = 'calendar_instances';
+
+    /**
      * The table name that will be used for calendar objects
      *
      * @var string
@@ -140,16 +156,23 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S
     function getCalendarsForUser($principalUri) {
 
         $fields = array_values($this->propertyMap);
-        $fields[] = 'id';
+        $fields[] = 'calendarid';
         $fields[] = 'uri';
         $fields[] = 'synctoken';
         $fields[] = 'components';
         $fields[] = 'principaluri';
         $fields[] = 'transparent';
+        $fields[] = 'access';
 
         // Making fields a comma-delimited list
         $fields = implode(', ', $fields);
-        $stmt = $this->pdo->prepare("SELECT " . $fields . " FROM " . $this->calendarTableName . " WHERE principaluri = ? ORDER BY calendarorder ASC");
+        $stmt = $this->pdo->prepare(<<<SQL
+SELECT $fields FROM {$this->calendarInstancesTableName}
+    LEFT JOIN {$this->calendarTableName} ON
+        {$this->calendarInstancesTableName}.calendarid = {$this->calendarTableName}.id
+WHERE principaluri = ? ORDER BY calendarorder ASC
+SQL
+        );
         $stmt->execute([$principalUri]);
 
         $calendars = [];
@@ -170,6 +193,16 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S
                 '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-calendar-transp'         => new CalDAV\Xml\Property\ScheduleCalendarTransp($row['transparent'] ? 'transparent' : 'opaque'),
             ];
 
+            // 1 = owner, 2 = readonly, 3 = readwrite
+            if ($row['access'] > 1) {
+                // We need to find more information about the original owner.
+                $stmt2 = $this->pdo->prepare('SELECT principaluri FROM ' . $this->calendarInstancesTableName . ' WHERE access = 1 AND id = ?');
+                $stmt2->execute([$row['id']]);
+
+                $calendar['owner_principal'] = $stmt2->fetchColumn();
+                $calendar['read-only'] = $row['access']===3;
+            }
+
 
             foreach ($this->propertyMap as $xmlName => $dbName) {
                 $calendar[$xmlName] = $row[$dbName];
@@ -199,31 +232,34 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S
         $fieldNames = [
             'principaluri',
             'uri',
-            'synctoken',
             'transparent',
+            'calendarid',
         ];
         $values = [
             ':principaluri' => $principalUri,
             ':uri'          => $calendarUri,
-            ':synctoken'    => 1,
             ':transparent'  => 0,
         ];
 
-        // Default value
+
         $sccs = '{urn:ietf:params:xml:ns:caldav}supported-calendar-component-set';
-        $fieldNames[] = 'components';
         if (!isset($properties[$sccs])) {
-            $values[':components'] = 'VEVENT,VTODO';
+            // Default value
+            $components = 'VEVENT,VTODO';
         } else {
             if (!($properties[$sccs] instanceof CalDAV\Xml\Property\SupportedCalendarComponentSet)) {
                 throw new DAV\Exception('The ' . $sccs . ' property must be of type: \Sabre\CalDAV\Xml\Property\SupportedCalendarComponentSet');
             }
-            $values[':components'] = implode(',', $properties[$sccs]->getValue());
+            $components = implode(',', $properties[$sccs]->getValue());
         }
         $transp = '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-calendar-transp';
         if (isset($properties[$transp])) {
             $values[':transparent'] = $properties[$transp]->getValue() === 'transparent';
         }
+        $stmt = $this->pdo->prepare("INSERT INTO " . $this->calendarTableName . " (synctoken, components) VALUES (1, ?)");
+        $stmt->execute([$components]);
+
+        $values[':calendarid'] = $this->pdo->lastInsertId()
 
         foreach ($this->propertyMap as $xmlName => $dbName) {
             if (isset($properties[$xmlName])) {
@@ -233,7 +269,7 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S
             }
         }
 
-        $stmt = $this->pdo->prepare("INSERT INTO " . $this->calendarTableName . " (" . implode(', ', $fieldNames) . ") VALUES (" . implode(', ', array_keys($values)) . ")");
+        $stmt = $this->pdo->prepare("INSERT INTO " . $this->calendarInstancesTableName . " (" . implode(', ', $fieldNames) . ") VALUES (" . implode(', ', array_keys($values)) . ")");
         $stmt->execute($values);
 
         return $this->pdo->lastInsertId();
@@ -282,7 +318,7 @@ class PDO extends AbstractBackend implements SyncSupport, SubscriptionSupport, S
                 $valuesSql[] = $fieldName . ' = ?';
             }
 
-            $stmt = $this->pdo->prepare("UPDATE " . $this->calendarTableName . " SET " . implode(', ', $valuesSql) . " WHERE id = ?");
+            $stmt = $this->pdo->prepare("UPDATE " . $this->calendarInstancesTableName . " SET " . implode(', ', $valuesSql) . " WHERE id = ?");
             $newValues['id'] = $calendarId;
             $stmt->execute(array_values($newValues));
 
diff --git a/lib/CalDAV/Backend/SharingSupport.php b/lib/CalDAV/Backend/SharingSupport.php
index 2aed39f..a837607 100644
--- a/lib/CalDAV/Backend/SharingSupport.php
+++ b/lib/CalDAV/Backend/SharingSupport.php
@@ -8,24 +8,6 @@ namespace Sabre\CalDAV\Backend;
  * Note: This feature is experimental, and may change in between different
  * SabreDAV versions.
  *
- * Early warning: Currently SabreDAV provides no implementation for this. This
- * is, because in it's current state there is no elegant way to do this.
- * The problem lies in the fact that a real CalDAV server with sharing support
- * would first need email support (with invite notifications), and really also
- * a browser-frontend that allows people to accept or reject these shares.
- *
- * In addition, the CalDAV backends are currently kept as independent as
- * possible, and should not be aware of principals, email addresses or
- * accounts.
- *
- * Adding an implementation for Sharing to standard-sabredav would contradict
- * these goals, so for this reason this is currently not implemented, although
- * it may very well in the future; but probably not before SabreDAV 2.0.
- *
- * The interface works however, so if you implement all this, and do it
- * correctly sharing _will_ work. It's not particularly easy, and I _urge you_
- * to make yourself acquainted with the following document first:
- *
  * https://trac.calendarserver.org/browser/CalendarServer/trunk/doc/Extensions/caldav-sharing.txt
  *
  * An overview
@@ -65,12 +47,12 @@ namespace Sabre\CalDAV\Backend;
  * change.
  * This notification is always represented by:
  *
- * Sabre\CalDAV\Notifications\Notification\Invite
+ * Sabre\CalDAV\Xml\Notification\Invite
  *
  * In the case of an invite, the sharee may reply with an 'accept' or
  * 'decline'. These are always represented by:
  *
- * Sabre\CalDAV\Notifications\Notification\InviteReply
+ * Sabre\CalDAV\Xml\Notification\InviteReply
  *
  *
  * Calendar access by sharees
@@ -81,16 +63,12 @@ namespace Sabre\CalDAV\Backend;
  *
  * The following properties must be specified:
  *
- * 1. {http://calendarserver.org/ns/}shared-url
- *
- * This property MUST contain the url to the original calendar, that is.. the
- * path to the calendar from the owner.
- *
- * 2. {http://sabredav.org/ns}owner-principal
+ * 1. owner-principal 
  *
- * This is a url to to the principal who is sharing the calendar.
+ * If the calendar is shared, and the current user is not the owner, then this
+ * property MUST contain information to identify the real owner.
  *
- * 3. {http://sabredav.org/ns}read-only
+ * 2. read-only
  *
  * This should be either 0 or 1, depending on if the user has read-only or
  * read-write access to the calendar.
diff --git a/lib/CalDAV/Backend/SimplePDO.php b/lib/CalDAV/Backend/SimplePDO.php
new file mode 100644
index 0000000..fc009ec
--- /dev/null
+++ b/lib/CalDAV/Backend/SimplePDO.php
@@ -0,0 +1,287 @@
+<?php
+
+namespace Sabre\CalDAV\Backend;
+
+use Sabre\VObject;
+use Sabre\CalDAV;
+use Sabre\DAV;
+use Sabre\DAV\Exception\Forbidden;
+
+/**
+ * Simple PDO CalDAV backend.
+ *
+ * This backend class serves as a demononstration on how to create a very
+ * simple CalDAV backend.
+ *
+ * Unlike the 'PDO' class, this class only has the most basic features.
+ *
+ * To make this class work, you absolutely need to have the PropertyStorage
+ * plugin enabled.
+ *
+ * @copyright Copyright (C) 2007-2015 fruux GmbH (https://fruux.com/).
+ * @author Evert Pot (http://evertpot.com/)
+ * @license http://sabre.io/license/ Modified BSD License
+ */
+class SimplePDO extends AbstractBackend {
+
+    /**
+     * pdo
+     *
+     * @var \PDO
+     */
+    protected $pdo;
+
+    /**
+     * Creates the backend
+     *
+     * @param \PDO $pdo
+     */
+    function __construct(\PDO $pdo) {
+
+        $this->pdo = $pdo;
+
+    }
+
+    /**
+     * Returns a list of calendars for a principal.
+     *
+     * Every project is an array with the following keys:
+     *  * id, a unique id that will be used by other functions to modify the
+     *    calendar. This can be the same as the uri or a database key.
+     *  * uri. This is just the 'base uri' or 'filename' of the calendar.
+     *  * principaluri. The owner of the calendar. Almost always the same as
+     *    principalUri passed to this method.
+     *
+     * Furthermore it can contain webdav properties in clark notation. A very
+     * common one is '{DAV:}displayname'.
+     *
+     * Many clients also require:
+     * {urn:ietf:params:xml:ns:caldav}supported-calendar-component-set
+     * For this property, you can just return an instance of
+     * Sabre\CalDAV\Xml\Property\SupportedCalendarComponentSet.
+     *
+     * If you return {http://sabredav.org/ns}read-only and set the value to 1,
+     * ACL will automatically be put in read-only mode.
+     *
+     * @param string $principalUri
+     * @return array
+     */
+    function getCalendarsForUser($principalUri) {
+
+        // Making fields a comma-delimited list
+        $stmt = $this->pdo->prepare("SELECT id, uri FROM simple_calendars WHERE principaluri = ? ORDER BY calendarorder ASC");
+        $stmt->execute([$principalUri]);
+
+        $calendars = [];
+        while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
+
+            $calendars[] = [
+                'id'           => $row['id'],
+                'uri'          => $row['uri'],
+                'principaluri' => $principalUri,
+            ];
+
+        }
+
+        return $calendars;
+
+    }
+
+    /**
+     * Creates a new calendar for a principal.
+     *
+     * If the creation was a success, an id must be returned that can be used
+     * to reference this calendar in other methods, such as updateCalendar.
+     *
+     * @param string $principalUri
+     * @param string $calendarUri
+     * @param array $properties
+     * @return string
+     */
+    function createCalendar($principalUri, $calendarUri, array $properties) {
+
+        $stmt = $this->pdo->prepare("INSERT INTO simple_calendars (principaluri, uri) VALUES (?, ?)");
+        $stmt->execute($principalUri, $calendarUri);
+
+        return $this->pdo->lastInsertId();
+
+    }
+
+    /**
+     * Delete a calendar and all it's objects
+     *
+     * @param string $calendarId
+     * @return void
+     */
+    function deleteCalendar($calendarId) {
+
+        $stmt = $this->pdo->prepare('DELETE FROM simple_calendarobjects WHERE calendarid = ?');
+        $stmt->execute([$calendarId]);
+
+        $stmt = $this->pdo->prepare('DELETE FROM simple_calendars WHERE id = ?');
+        $stmt->execute([$calendarId]);
+
+    }
+
+    /**
+     * Returns all calendar objects within a calendar.
+     *
+     * Every item contains an array with the following keys:
+     *   * calendardata - The iCalendar-compatible calendar data
+     *   * uri - a unique key which will be used to construct the uri. This can
+     *     be any arbitrary string, but making sure it ends with '.ics' is a
+     *     good idea. This is only the basename, or filename, not the full
+     *     path.
+     *   * lastmodified - a timestamp of the last modification time
+     *   * etag - An arbitrary string, surrounded by double-quotes. (e.g.:
+     *   '  "abcdef"')
+     *   * size - The size of the calendar objects, in bytes.
+     *   * component - optional, a string containing the type of object, such
+     *     as 'vevent' or 'vtodo'. If specified, this will be used to populate
+     *     the Content-Type header.
+     *
+     * Note that the etag is optional, but it's highly encouraged to return for
+     * speed reasons.
+     *
+     * The calendardata is also optional. If it's not returned
+     * 'getCalendarObject' will be called later, which *is* expected to return
+     * calendardata.
+     *
+     * If neither etag or size are specified, the calendardata will be
+     * used/fetched to determine these numbers. If both are specified the
+     * amount of times this is needed is reduced by a great degree.
+     *
+     * @param string $calendarId
+     * @return array
+     */
+    function getCalendarObjects($calendarId) {
+
+        $stmt = $this->pdo->prepare('SELECT id, uri, calendardata FROM simple_calendarobjects WHERE calendarid = ?');
+        $stmt->execute([$calendarId]);
+
+        $result = [];
+        foreach ($stmt->fetchAll(\PDO::FETCH_ASSOC) as $row) {
+            $result[] = [
+                'id'           => $row['id'],
+                'uri'          => $row['uri'],
+                'etag'         => '"' . md5($row['calendardata']) . '"',
+                'calendarid'   => $calendarId,
+                'size'         => strlen($row['calendardata']),
+                'calendardata' => $row['calendardata'],
+            ];
+        }
+
+        return $result;
+
+    }
+
+    /**
+     * Returns information from a single calendar object, based on it's object
+     * uri.
+     *
+     * The object uri is only the basename, or filename and not a full path.
+     *
+     * The returned array must have the same keys as getCalendarObjects. The
+     * 'calendardata' object is required here though, while it's not required
+     * for getCalendarObjects.
+     *
+     * This method must return null if the object did not exist.
+     *
+     * @param string $calendarId
+     * @param string $objectUri
+     * @return array|null
+     */
+    function getCalendarObject($calendarId, $objectUri) {
+
+        $stmt = $this->pdo->prepare('SELECT id, uri, calendardata FROM simple_calendarobjects WHERE calendarid = ? AND uri = ?');
+        $stmt->execute([$calendarId, $objectUri]);
+        $row = $stmt->fetch(\PDO::FETCH_ASSOC);
+
+        if (!$row) return null;
+
+        return [
+            'id'            => $row['id'],
+            'uri'           => $row['uri'],
+            'etag'          => '"' . md5($row['calendardata']) . '"',
+            'calendarid'    => $calendarId,
+            'size'          => strlen($row['calendardata']),
+            'calendardata'  => $row['calendardata'],
+         ];
+
+    }
+
+    /**
+     * Creates a new calendar object.
+     *
+     * The object uri is only the basename, or filename and not a full path.
+     *
+     * It is possible return an etag from this function, which will be used in
+     * the response to this PUT request. Note that the ETag must be surrounded
+     * by double-quotes.
+     *
+     * However, you should only really return this ETag if you don't mangle the
+     * calendar-data. If the result of a subsequent GET to this object is not
+     * the exact same as this request body, you should omit the ETag.
+     *
+     * @param mixed $calendarId
+     * @param string $objectUri
+     * @param string $calendarData
+     * @return string|null
+     */
+    function createCalendarObject($calendarId, $objectUri, $calendarData) {
+
+        $stmt = $this->pdo->prepare('INSERT INTO simple_calendarobjects (calendarid, uri, calendardata) VALUES (?,?,?)');
+        $stmt->execute([
+            $calendarId,
+            $objectUri,
+            $calendarData
+        ]);
+
+        return '"' . md5($calendarData) . '"';
+
+    }
+
+    /**
+     * Updates an existing calendarobject, based on it's uri.
+     *
+     * The object uri is only the basename, or filename and not a full path.
+     *
+     * It is possible return an etag from this function, which will be used in
+     * the response to this PUT request. Note that the ETag must be surrounded
+     * by double-quotes.
+     *
+     * However, you should only really return this ETag if you don't mangle the
+     * calendar-data. If the result of a subsequent GET to this object is not
+     * the exact same as this request body, you should omit the ETag.
+     *
+     * @param mixed $calendarId
+     * @param string $objectUri
+     * @param string $calendarData
+     * @return string|null
+     */
+    function updateCalendarObject($calendarId, $objectUri, $calendarData) {
+
+        $stmt = $this->pdo->prepare('UPDATE simple_calendarobjects SET calendardata = ? WHERE calendarid = ? AND uri = ?');
+        $stmt->execute([$calendarData, $calendarId, $objectUri]);
+
+        return '"' . md5($calendarData) . '"';
+
+    }
+
+    /**
+     * Deletes an existing calendar object.
+     *
+     * The object uri is only the basename, or filename and not a full path.
+     *
+     * @param string $calendarId
+     * @param string $objectUri
+     * @return void
+     */
+    function deleteCalendarObject($calendarId, $objectUri) {
+
+        $stmt = $this->pdo->prepare('DELETE FROM simple_calendarobjects WHERE calendarid = ? AND uri = ?');
+        $stmt->execute([$calendarId, $objectUri]);
+
+    }
+
+}
diff --git a/lib/DAV/Sharing/Plugin.php b/lib/DAV/Sharing/Plugin.php
index 11432ae..b7327aa 100644
--- a/lib/DAV/Sharing/Plugin.php
+++ b/lib/DAV/Sharing/Plugin.php
@@ -147,13 +147,13 @@ class Plugin extends ServerPlugin {
      */
     function propFind(PropFind $propFind, INode $node) {
 
-        $propFind->handle('{DAV:}share-mode', function() {
+        $propFind->handle('{DAV:}share-mode', function() use ($node) {
 
-            if (INode instanceof ISharedNode) {
+            if ($node instanceof ISharedNode) {
 
                 return new Property\ShareMode(Property\ShareMode::SHARED);
 
-            } elseif (INode instanceof IShareableNode) {
+            } elseif ($node instanceof IShareableNode) {
 
                 return new Property\ShareMode(Property\ShareMode::SHAREDOWNER);
 
@@ -207,7 +207,6 @@ class Plugin extends ServerPlugin {
 
     }
 
-
     /**
      * Returns a bunch of meta-data about the plugin.
      *

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-php/php-sabredav.git



More information about the Pkg-owncloud-commits mailing list