feat: upgrade to sabre project with last version comptabile with php 7.1

This commit is contained in:
Florian HENRY 2023-05-26 11:09:51 +02:00
parent 0cc761dccd
commit 580f803f73
330 changed files with 12093 additions and 10531 deletions

View file

@ -41,3 +41,5 @@ docs/wikidocs
# Mac
.DS_Store
.php_cs.cache

View file

@ -0,0 +1,12 @@
<?php
$config = PhpCsFixer\Config::create();
$config->getFinder()
->exclude('vendor')
->in(__DIR__);
$config->setRules([
'@PSR1' => true,
'@Symfony' =>true
]);
return $config;

View file

@ -1,35 +1,51 @@
language: php
sudo: required
php:
- 5.5
- 5.6
- 7.0
- 7.1
- 7.2
- 7.3
env:
global:
- SABRE_MYSQLUSER="root"
- SABRE_MYSQLPASS=""
- SABRE_MYSQLDSN="mysql:host=127.0.0.1;dbname=sabredav_test"
- RUN_PHPSTAN="FALSE"
matrix:
- LOWEST_DEPS="" TEST_DEPS=""
- LOWEST_DEPS="--prefer-lowest" TEST_DEPS="tests/Sabre/"
- LOWEST_DEPS="" TEST_DEPS="" WITH_COVERAGE="--coverage-clover=coverage.xml"
- LOWEST_DEPS="--prefer-lowest" TEST_DEPS="tests/Sabre/" $WITH_COVERAGE=""
matrix:
include:
- name: 'PHPStan'
php: 7.2
env: RUN_PHPSTAN="TRUE"
services:
- mysql
- postgresql
sudo: false
install:
- if [ $RUN_PHPSTAN == "TRUE" ]; then wget https://github.com/phpstan/phpstan/releases/download/0.11.8/phpstan.phar; fi
before_script:
- mysql -e 'create database sabredav_test'
# - mysql -u root -h 127.0.0.1 sabredav_test -e 'SELECT VERSION();'
#- mysql -u root -h 127.0.0.1 -e 'create database sabredav_test'
- psql -c "create database sabredav_test" -U postgres
- psql -c "create user sabredav with PASSWORD 'sabredav';GRANT ALL PRIVILEGES ON DATABASE sabredav_test TO sabredav" -U postgres
# - composer self-update
- composer update --prefer-dist $LOWEST_DEPS
# addons:
# postgresql: "9.5"
addons:
postgresql: "9.5"
script:
- ./bin/phpunit --configuration tests/phpunit.xml.dist $TEST_DEPS
- ./bin/sabre-cs-fixer fix . --dry-run --diff
- if [ $RUN_PHPSTAN == "FALSE" ]; then ./bin/phpunit --verbose --configuration tests/phpunit.xml.dist $WITH_COVERAGE $TEST_DEPS; fi
- if [ $RUN_PHPSTAN == "FALSE" ]; then rm -f ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/xdebug.ini; fi
- if [ $RUN_PHPSTAN == "TRUE" ]; then php phpstan.phar analyse -c phpstan.neon lib; fi
after_success:
- bash <(curl -s https://codecov.io/bash)
cache:
directories:

File diff suppressed because it is too large Load diff

View file

@ -78,6 +78,28 @@ to accept the patch, but we'd still really like your contribution!
To run the testsuite jump into the directory `cd tests` and trigger `phpunit`.
Make sure you did a `composer install` beforehand.
Release process
---------------
Generally, these are the steps taken to do releases.
1. Update the changelog. Every repo will have a `CHANGELOG.md` file. This file
should have a new version, and contain all the changes since the last
release. I generally run a `git diff` to figure out if I missed any changes.
This file should also have the current date.
2. If there were BC breaks, this usually now means a major version bump.
3. Ensure that `lib/Version.php` or `lib/DAV/Version.php` also matches this
version number.
4. Tag the release (Example `git tag 3.0.1` and push the tag (`git push --tags`).
5. (only for the sabre/dav project), create a zip distribution. Run
`php bin/build.php`.
6. For the relevant project, go to github and click the 'releases' tab. On this
tab I create the release with the relevant version. I also set the
description of the release to the same information of the changelog. In the
case of the `sabre/dav` project I also upload the zip distribution here.
7. Write a blog post on sabre.io. This also automatically updates twitter.
[1]: http://www.php-fig.org/psr/psr-1/
[2]: http://www.php-fig.org/psr/psr-4/
[3]: http://www.php-fig.org/psr/psr-2/

View file

@ -0,0 +1,27 @@
Copyright (C) 2007-2016 fruux GmbH (https://fruux.com/).
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of SabreDAV nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,38 @@
![sabre's logo](http://sabre.io/img/logo.png) sabre/dav
=======================================================
Introduction
------------
sabre/dav is the most popular WebDAV framework for PHP. Use it to create WebDAV, CalDAV and CardDAV servers.
Full documentation can be found on the website:
http://sabre.io/
Build status
------------
| branch | status | minimum PHP version |
| ------------ | ------ | ------------------- |
| master | [![Build Status](https://travis-ci.org/sabre-io/dav.svg?branch=master)](https://travis-ci.org/sabre-io/dav) | PHP 7.0 |
| 3.1 | [![Build Status](https://travis-ci.org/sabre-io/dav.svg?branch=3.0)](https://travis-ci.org/sabre-io/dav) | PHP 5.5 |
| 3.0 | [![Build Status](https://travis-ci.org/sabre-io/dav.svg?branch=3.0)](https://travis-ci.org/sabre-io/dav) | PHP 5.4 |
| 2.1 | [![Build Status](https://travis-ci.org/sabre-io/dav.svg?branch=2.1)](https://travis-ci.org/sabre-io/dav) | PHP 5.4 |
| 2.0 | [![Build Status](https://travis-ci.org/sabre-io/dav.svg?branch=2.0)](https://travis-ci.org/sabre-io/dav) | PHP 5.4 |
| 1.8 | [![Build Status](https://travis-ci.org/sabre-io/dav.svg?branch=1.8)](https://travis-ci.org/sabre-io/dav) | PHP 5.3 |
| 1.7 | [![Build Status](https://travis-ci.org/sabre-io/dav.svg?branch=1.7)](https://travis-ci.org/sabre-io/dav) | PHP 5.3 |
| 1.6 | [![Build Status](https://travis-ci.org/sabre-io/dav.svg?branch=1.6)](https://travis-ci.org/sabre-io/dav) | PHP 5.3 |
Documentation
-------------
* [Introduction](http://sabre.io/dav/).
* [Installation](http://sabre.io/dav/install/).
Made at fruux
-------------
SabreDAV is being developed by [fruux](https://fruux.com/). Drop us a line for commercial services or enterprise support.

88
htdocs/includes/sabre/sabre/dav/bin/build.php Normal file → Executable file
View file

@ -2,7 +2,6 @@
<?php
$tasks = [
'buildzip' => [
'init', 'test', 'clean',
],
@ -10,25 +9,29 @@ $tasks = [
'init', 'test', 'clean',
],
'clean' => [],
'test' => [
'test' => [
'composerupdate',
],
'init' => [],
'init' => [],
'composerupdate' => [],
];
$default = 'buildzip';
$baseDir = __DIR__ . '/../';
$baseDir = __DIR__.'/../';
chdir($baseDir);
$currentTask = $default;
if ($argc > 1) $currentTask = $argv[1];
if ($argc > 1) {
$currentTask = $argv[1];
}
$version = null;
if ($argc > 2) $version = $argv[2];
if ($argc > 2) {
$version = $argv[2];
}
if (!isset($tasks[$currentTask])) {
echo "Task not found: ", $currentTask, "\n";
echo 'Task not found: ', $currentTask, "\n";
die(1);
}
@ -37,11 +40,9 @@ $newTaskList = [];
$oldTaskList = [$currentTask => true];
while (count($oldTaskList) > 0) {
foreach ($oldTaskList as $task => $foo) {
if (!isset($tasks[$task])) {
echo "Dependency not found: " . $task, "\n";
echo 'Dependency not found: '.$task, "\n";
die(1);
}
$dependencies = $tasks[$task];
@ -55,82 +56,74 @@ while (count($oldTaskList) > 0) {
$oldTaskList[$dependency] = true;
$fullFilled = false;
}
}
if ($fullFilled) {
unset($oldTaskList[$task]);
$newTaskList[$task] = 1;
}
}
}
foreach (array_keys($newTaskList) as $task) {
echo "task: " . $task, "\n";
echo 'task: '.$task, "\n";
call_user_func($task);
echo "\n";
}
function init() {
function init()
{
global $version;
if (!$version) {
include __DIR__ . '/../vendor/autoload.php';
include __DIR__.'/../vendor/autoload.php';
$version = Sabre\DAV\Version::VERSION;
}
echo " Building sabre/dav " . $version, "\n";
echo ' Building sabre/dav '.$version, "\n";
}
function clean() {
function clean()
{
global $baseDir;
echo " Removing build files\n";
$outputDir = $baseDir . '/build/SabreDAV';
$outputDir = $baseDir.'/build/SabreDAV';
if (is_dir($outputDir)) {
system('rm -r ' . $baseDir . '/build/SabreDAV');
system('rm -r '.$baseDir.'/build/SabreDAV');
}
}
function composerupdate() {
function composerupdate()
{
global $baseDir;
echo " Updating composer packages to latest version\n\n";
system('cd ' . $baseDir . '; composer update');
system('cd '.$baseDir.'; composer update');
}
function test() {
function test()
{
global $baseDir;
echo " Running all unittests.\n";
echo " This may take a while.\n\n";
system(__DIR__ . '/phpunit --configuration ' . $baseDir . '/tests/phpunit.xml.dist --stop-on-failure', $code);
if ($code != 0) {
system(__DIR__.'/phpunit --configuration '.$baseDir.'/tests/phpunit.xml.dist --stop-on-failure', $code);
if (0 != $code) {
echo "PHPUnit reported error code $code\n";
die(1);
}
}
function buildzip() {
function buildzip()
{
global $baseDir, $version;
echo " Generating composer.json\n";
$input = json_decode(file_get_contents(__DIR__ . '/../composer.json'), true);
$input = json_decode(file_get_contents(__DIR__.'/../composer.json'), true);
$newComposer = [
"require" => $input['require'],
"config" => [
"bin-dir" => "./bin",
'require' => $input['require'],
'config' => [
'bin-dir' => './bin',
],
"prefer-stable" => true,
"minimum-stability" => "alpha",
'prefer-stable' => true,
'minimum-stability' => 'alpha',
];
unset(
$newComposer['require']['sabre/vobject'],
@ -143,8 +136,8 @@ function buildzip() {
file_put_contents('build/SabreDAV/composer.json', json_encode($newComposer, JSON_PRETTY_PRINT));
echo " Downloading dependencies\n";
system("cd build/SabreDAV; composer install -n", $code);
if ($code !== 0) {
system('cd build/SabreDAV; composer install -n', $code);
if (0 !== $code) {
echo "Composer reported error code $code\n";
die(1);
}
@ -163,15 +156,14 @@ function buildzip() {
];
foreach ($fileNames as $fileName) {
echo " $fileName\n";
rename('build/SabreDAV/vendor/sabre/dav/' . $fileName, 'build/SabreDAV/' . $fileName);
rename('build/SabreDAV/vendor/sabre/dav/'.$fileName, 'build/SabreDAV/'.$fileName);
}
// <zip destfile="build/SabreDAV-${sabredav.version}.zip" basedir="build/SabreDAV" prefix="SabreDAV/" />
echo "\n";
echo "Zipping the sabredav distribution\n\n";
system('cd build; zip -qr sabredav-' . $version . '.zip SabreDAV');
echo "Done.";
system('cd build; zip -qr sabredav-'.$version.'.zip SabreDAV');
echo 'Done.';
}

View file

152
htdocs/includes/sabre/sabre/dav/bin/migrateto20.php Normal file → Executable file
View file

@ -4,7 +4,6 @@
echo "SabreDAV migrate script for version 2.0\n";
if ($argc < 2) {
echo <<<HELLO
This script help you migrate from a pre-2.0 database to 2.0 and later
@ -36,14 +35,13 @@ 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',
__DIR__.'/../vendor/autoload.php',
__DIR__.'/../../../autoload.php',
];
foreach ($paths as $path) {
@ -57,7 +55,7 @@ $dsn = $argv[1];
$user = isset($argv[2]) ? $argv[2] : null;
$pass = isset($argv[3]) ? $argv[3] : null;
echo "Connecting to database: " . $dsn . "\n";
echo 'Connecting to database: '.$dsn."\n";
$pdo = new PDO($dsn, $user, $pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
@ -66,23 +64,21 @@ $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$driver = $pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
switch ($driver) {
case 'mysql' :
case 'mysql':
echo "Detected MySQL.\n";
break;
case 'sqlite' :
case 'sqlite':
echo "Detected SQLite.\n";
break;
default :
echo "Error: unsupported driver: " . $driver . "\n";
default:
echo 'Error: unsupported driver: '.$driver."\n";
die(-1);
}
foreach (['calendar', 'addressbook'] as $itemType) {
$tableName = $itemType . 's';
$tableNameOld = $tableName . '_old';
$changesTable = $itemType . 'changes';
$tableName = $itemType.'s';
$tableNameOld = $tableName.'_old';
$changesTable = $itemType.'changes';
echo "Upgrading '$tableName'\n";
@ -90,18 +86,16 @@ foreach (['calendar', 'addressbook'] as $itemType) {
$row = $pdo->query("SELECT * FROM $tableName LIMIT 1")->fetch();
if (!$row) {
echo "No records were found in the '$tableName' table.\n";
echo "\n";
echo "We're going to rename the old table to $tableNameOld (just in case).\n";
echo "and re-create the new table.\n";
switch ($driver) {
case 'mysql' :
case 'mysql':
$pdo->exec("RENAME TABLE $tableName TO $tableNameOld");
switch ($itemType) {
case 'calendar' :
case 'calendar':
$pdo->exec("
CREATE TABLE calendars (
id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
@ -119,7 +113,7 @@ foreach (['calendar', 'addressbook'] as $itemType) {
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
");
break;
case 'addressbook' :
case 'addressbook':
$pdo->exec("
CREATE TABLE addressbooks (
id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
@ -135,13 +129,13 @@ foreach (['calendar', 'addressbook'] as $itemType) {
}
break;
case 'sqlite' :
case 'sqlite':
$pdo->exec("ALTER TABLE $tableName RENAME TO $tableNameOld");
switch ($itemType) {
case 'calendar' :
$pdo->exec("
case 'calendar':
$pdo->exec('
CREATE TABLE calendars (
id integer primary key asc,
principaluri text,
@ -155,10 +149,10 @@ foreach (['calendar', 'addressbook'] as $itemType) {
components text,
transparent bool
);
");
');
break;
case 'addressbook' :
$pdo->exec("
case 'addressbook':
$pdo->exec('
CREATE TABLE addressbooks (
id integer primary key asc,
principaluri text,
@ -167,45 +161,37 @@ foreach (['calendar', 'addressbook'] as $itemType) {
description text,
synctoken integer
);
");
');
break;
}
break;
}
echo "Creation of 2.0 $tableName table is complete\n";
} else {
// Checking if there's a synctoken field already.
if (array_key_exists('synctoken', $row)) {
echo "The 'synctoken' field already exists in the $tableName table.\n";
echo "It's likely you already upgraded, so we're simply leaving\n";
echo "the $tableName table alone\n";
} else {
echo "1.8 table schema detected\n";
switch ($driver) {
case 'mysql' :
case 'mysql':
$pdo->exec("ALTER TABLE $tableName ADD synctoken INT(11) UNSIGNED NOT NULL DEFAULT '1'");
$pdo->exec("ALTER TABLE $tableName DROP ctag");
$pdo->exec("UPDATE $tableName SET synctoken = '1'");
break;
case 'sqlite' :
case 'sqlite':
$pdo->exec("ALTER TABLE $tableName ADD synctoken integer");
$pdo->exec("UPDATE $tableName SET synctoken = '1'");
echo "Note: there's no easy way to remove fields in sqlite.\n";
echo "The ctag field is no longer used, but it's kept in place\n";
break;
}
echo "Upgraded '$tableName' to 2.0 schema.\n";
}
}
try {
@ -213,13 +199,11 @@ foreach (['calendar', 'addressbook'] as $itemType) {
echo "'$changesTable' already exists. Assuming that this part of the\n";
echo "upgrade was already completed.\n";
} catch (Exception $e) {
echo "Creating '$changesTable' table.\n";
switch ($driver) {
case 'mysql' :
case 'mysql':
$pdo->exec("
CREATE TABLE $changesTable (
id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
@ -232,7 +216,7 @@ foreach (['calendar', 'addressbook'] as $itemType) {
");
break;
case 'sqlite' :
case 'sqlite':
$pdo->exec("
CREATE TABLE $changesTable (
@ -246,25 +230,20 @@ foreach (['calendar', 'addressbook'] as $itemType) {
");
$pdo->exec("CREATE INDEX {$itemType}id_synctoken ON $changesTable ({$itemType}id, synctoken);");
break;
}
}
}
try {
$pdo->query("SELECT * FROM calendarsubscriptions LIMIT 1");
$pdo->query('SELECT * FROM calendarsubscriptions LIMIT 1');
echo "'calendarsubscriptions' already exists. Assuming that this part of the\n";
echo "upgrade was already completed.\n";
} catch (Exception $e) {
echo "Creating calendarsubscriptions table.\n";
switch ($driver) {
case 'mysql' :
case 'mysql':
$pdo->exec("
CREATE TABLE calendarsubscriptions (
id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
@ -283,8 +262,8 @@ CREATE TABLE calendarsubscriptions (
);
");
break;
case 'sqlite' :
$pdo->exec("
case 'sqlite':
$pdo->exec('
CREATE TABLE calendarsubscriptions (
id integer primary key asc,
@ -300,64 +279,57 @@ CREATE TABLE calendarsubscriptions (
stripattachments bool,
lastmodified int
);
");
');
$pdo->exec("CREATE INDEX principaluri_uri ON calendarsubscriptions (principaluri, uri);");
$pdo->exec('CREATE INDEX principaluri_uri ON calendarsubscriptions (principaluri, uri);');
break;
}
}
try {
$pdo->query("SELECT * FROM propertystorage LIMIT 1");
$pdo->query('SELECT * FROM propertystorage LIMIT 1');
echo "'propertystorage' already exists. Assuming that this part of the\n";
echo "upgrade was already completed.\n";
} catch (Exception $e) {
echo "Creating propertystorage table.\n";
switch ($driver) {
case 'mysql' :
$pdo->exec("
case 'mysql':
$pdo->exec('
CREATE TABLE propertystorage (
id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
path VARBINARY(1024) NOT NULL,
name VARBINARY(100) NOT NULL,
value MEDIUMBLOB
);
");
$pdo->exec("
');
$pdo->exec('
CREATE UNIQUE INDEX path_property ON propertystorage (path(600), name(100));
");
');
break;
case 'sqlite' :
$pdo->exec("
case 'sqlite':
$pdo->exec('
CREATE TABLE propertystorage (
id integer primary key asc,
path TEXT,
name TEXT,
value TEXT
);
");
$pdo->exec("
');
$pdo->exec('
CREATE UNIQUE INDEX path_property ON propertystorage (path, name);
");
');
break;
}
}
echo "Upgrading cards table to 2.0 schema\n";
try {
$create = false;
$row = $pdo->query("SELECT * FROM cards LIMIT 1")->fetch();
$row = $pdo->query('SELECT * FROM cards LIMIT 1')->fetch();
if (!$row) {
$random = mt_rand(1000, 9999);
echo "There was no data in the cards table, so we're re-creating it\n";
@ -366,28 +338,24 @@ try {
$create = true;
switch ($driver) {
case 'mysql' :
case 'mysql':
$pdo->exec("RENAME TABLE cards TO cards_old$random");
break;
case 'sqlite' :
case 'sqlite':
$pdo->exec("ALTER TABLE cards RENAME TO cards_old$random");
break;
}
}
} catch (Exception $e) {
echo "Exception while checking cards table. Assuming that the table does not yet exist.\n";
echo "Debug: ", $e->getMessage(), "\n";
echo 'Debug: ', $e->getMessage(), "\n";
$create = true;
}
if ($create) {
switch ($driver) {
case 'mysql' :
$pdo->exec("
case 'mysql':
$pdo->exec('
CREATE TABLE cards (
id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
addressbookid INT(11) UNSIGNED NOT NULL,
@ -398,12 +366,12 @@ CREATE TABLE cards (
size INT(11) UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
");
');
break;
case 'sqlite' :
case 'sqlite':
$pdo->exec("
$pdo->exec('
CREATE TABLE cards (
id integer primary key asc,
addressbookid integer,
@ -413,28 +381,26 @@ CREATE TABLE cards (
etag text,
size integer
);
");
');
break;
}
} else {
switch ($driver) {
case 'mysql' :
$pdo->exec("
case 'mysql':
$pdo->exec('
ALTER TABLE cards
ADD etag VARBINARY(32),
ADD size INT(11) UNSIGNED NOT NULL;
");
');
break;
case 'sqlite' :
case 'sqlite':
$pdo->exec("
$pdo->exec('
ALTER TABLE cards ADD etag text;
ALTER TABLE cards ADD size integer;
");
');
break;
}
echo "Reading all old vcards and populating etag and size fields.\n";
$result = $pdo->query('SELECT id, carddata FROM cards');
@ -443,11 +409,9 @@ CREATE TABLE cards (
$stmt->execute([
md5($row['carddata']),
strlen($row['carddata']),
$row['id']
$row['id'],
]);
}
}
echo "Upgrade to 2.0 schema completed.\n";

36
htdocs/includes/sabre/sabre/dav/bin/migrateto21.php Normal file → Executable file
View file

@ -4,7 +4,6 @@
echo "SabreDAV migrate script for version 2.1\n";
if ($argc < 2) {
echo <<<HELLO
This script help you migrate from a pre-2.1 database to 2.1.
@ -37,14 +36,13 @@ 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',
__DIR__.'/../vendor/autoload.php',
__DIR__.'/../../../autoload.php',
];
foreach ($paths as $path) {
@ -58,7 +56,7 @@ $dsn = $argv[1];
$user = isset($argv[2]) ? $argv[2] : null;
$pass = isset($argv[3]) ? $argv[3] : null;
echo "Connecting to database: " . $dsn . "\n";
echo 'Connecting to database: '.$dsn."\n";
$pdo = new PDO($dsn, $user, $pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
@ -67,15 +65,14 @@ $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$driver = $pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
switch ($driver) {
case 'mysql' :
case 'mysql':
echo "Detected MySQL.\n";
break;
case 'sqlite' :
case 'sqlite':
echo "Detected SQLite.\n";
break;
default :
echo "Error: unsupported driver: " . $driver . "\n";
default:
echo 'Error: unsupported driver: '.$driver."\n";
die(-1);
}
@ -95,19 +92,17 @@ try {
echo "2.0 schema detected.\n";
$addUid = true;
}
} catch (Exception $e) {
echo "Could not find a calendarobjects table. Skipping this part of the\n";
echo "upgrade.\n";
}
if ($addUid) {
switch ($driver) {
case 'mysql' :
case 'mysql':
$pdo->exec('ALTER TABLE calendarobjects ADD uid VARCHAR(200)');
break;
case 'sqlite' :
case 'sqlite':
$pdo->exec('ALTER TABLE calendarobjects ADD uid TEXT');
break;
}
@ -117,7 +112,6 @@ if ($addUid) {
$counter = 0;
while ($row = $result->fetch(\PDO::FETCH_ASSOC)) {
try {
$vobj = \Sabre\VObject\Reader::read($row['calendardata']);
} catch (\Exception $e) {
@ -130,19 +124,16 @@ if ($addUid) {
echo "Warning! Item with id $item[id] does NOT have a UID property and this is required.\n";
continue;
}
$uid = (string)$item->UID;
$uid = (string) $item->UID;
$stmt->execute([$uid, $row['id']]);
$counter++;
++$counter;
}
}
echo "Creating 'schedulingobjects'\n";
switch ($driver) {
case 'mysql' :
case 'mysql':
$pdo->exec('CREATE TABLE IF NOT EXISTS schedulingobjects
(
id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
@ -156,8 +147,7 @@ switch ($driver) {
');
break;
case 'sqlite' :
case 'sqlite':
$pdo->exec('CREATE TABLE IF NOT EXISTS schedulingobjects (
id integer primary key asc,
principaluri text,

44
htdocs/includes/sabre/sabre/dav/bin/migrateto30.php Normal file → Executable file
View file

@ -4,7 +4,6 @@
echo "SabreDAV migrate script for version 3.0\n";
if ($argc < 2) {
echo <<<HELLO
This script help you migrate from a pre-3.0 database to 3.0 and later
@ -36,14 +35,13 @@ 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',
__DIR__.'/../vendor/autoload.php',
__DIR__.'/../../../autoload.php',
];
foreach ($paths as $path) {
@ -57,7 +55,7 @@ $dsn = $argv[1];
$user = isset($argv[2]) ? $argv[2] : null;
$pass = isset($argv[3]) ? $argv[3] : null;
echo "Connecting to database: " . $dsn . "\n";
echo 'Connecting to database: '.$dsn."\n";
$pdo = new PDO($dsn, $user, $pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
@ -66,15 +64,14 @@ $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$driver = $pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
switch ($driver) {
case 'mysql' :
case 'mysql':
echo "Detected MySQL.\n";
break;
case 'sqlite' :
case 'sqlite':
echo "Detected SQLite.\n";
break;
default :
echo "Error: unsupported driver: " . $driver . "\n";
default:
echo 'Error: unsupported driver: '.$driver."\n";
die(-1);
}
@ -90,9 +87,8 @@ try {
echo "Renaming propertystorage -> propertystorage_old$random and creating new table.\n";
switch ($driver) {
case 'mysql' :
$pdo->exec('RENAME TABLE propertystorage TO propertystorage_old' . $random);
case 'mysql':
$pdo->exec('RENAME TABLE propertystorage TO propertystorage_old'.$random);
$pdo->exec('
CREATE TABLE propertystorage (
id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
@ -102,10 +98,10 @@ try {
value MEDIUMBLOB
);
');
$pdo->exec('CREATE UNIQUE INDEX path_property_' . $random . ' ON propertystorage (path(600), name(100));');
$pdo->exec('CREATE UNIQUE INDEX path_property_'.$random.' ON propertystorage (path(600), name(100));');
break;
case 'sqlite' :
$pdo->exec('ALTER TABLE propertystorage RENAME TO propertystorage_old' . $random);
case 'sqlite':
$pdo->exec('ALTER TABLE propertystorage RENAME TO propertystorage_old'.$random);
$pdo->exec('
CREATE TABLE propertystorage (
id integer primary key asc,
@ -115,9 +111,8 @@ CREATE TABLE propertystorage (
value blob
);');
$pdo->exec('CREATE UNIQUE INDEX path_property_' . $random . ' ON propertystorage (path, name);');
$pdo->exec('CREATE UNIQUE INDEX path_property_'.$random.' ON propertystorage (path, name);');
break;
}
} elseif (array_key_exists('valuetype', $row)) {
echo "valuetype field exists. Assuming that this part of the migration has\n";
@ -126,7 +121,6 @@ CREATE TABLE propertystorage (
echo "2.1 schema detected. Going to perform upgrade.\n";
$addValueType = true;
}
} catch (Exception $e) {
echo "Could not find a propertystorage table. Skipping this part of the\n";
echo "upgrade.\n";
@ -134,19 +128,17 @@ CREATE TABLE propertystorage (
}
if ($addValueType) {
switch ($driver) {
case 'mysql' :
case 'mysql':
$pdo->exec('ALTER TABLE propertystorage ADD valuetype INT UNSIGNED');
break;
case 'sqlite' :
case 'sqlite':
$pdo->exec('ALTER TABLE propertystorage ADD valuetype INT');
break;
}
$pdo->exec('UPDATE propertystorage SET valuetype = 1 WHERE valuetype IS NULL ');
}
echo "Migrating vcardurl\n";
@ -155,16 +147,14 @@ $result = $pdo->query('SELECT id, uri, vcardurl FROM principals WHERE vcardurl I
$stmt1 = $pdo->prepare('INSERT INTO propertystorage (path, name, valuetype, value) VALUES (?, ?, 3, ?)');
while ($row = $result->fetch(\PDO::FETCH_ASSOC)) {
// Inserting the new record
$stmt1->execute([
'addressbooks/' . basename($row['uri']),
'addressbooks/'.basename($row['uri']),
'{http://calendarserver.org/ns/}me-card',
serialize(new Sabre\DAV\Xml\Property\Href($row['vcardurl']))
serialize(new Sabre\DAV\Xml\Property\Href($row['vcardurl'])),
]);
echo serialize(new Sabre\DAV\Xml\Property\Href($row['vcardurl']));
}
echo "Done.\n";

54
htdocs/includes/sabre/sabre/dav/bin/migrateto32.php Normal file → Executable file
View file

@ -4,7 +4,6 @@
echo "SabreDAV migrate script for version 3.2\n";
if ($argc < 2) {
echo <<<HELLO
This script help you migrate from a 3.1 database to 3.2 and later
@ -37,14 +36,13 @@ 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',
__DIR__.'/../vendor/autoload.php',
__DIR__.'/../../../autoload.php',
];
foreach ($paths as $path) {
@ -60,7 +58,7 @@ $pass = isset($argv[3]) ? $argv[3] : null;
$backupPostfix = time();
echo "Connecting to database: " . $dsn . "\n";
echo 'Connecting to database: '.$dsn."\n";
$pdo = new PDO($dsn, $user, $pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
@ -69,15 +67,14 @@ $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$driver = $pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
switch ($driver) {
case 'mysql' :
case 'mysql':
echo "Detected MySQL.\n";
break;
case 'sqlite' :
case 'sqlite':
echo "Detected SQLite.\n";
break;
default :
echo "Error: unsupported driver: " . $driver . "\n";
default:
echo 'Error: unsupported driver: '.$driver."\n";
die(-1);
}
@ -91,7 +88,7 @@ try {
echo "calendarinstances does not yet exist. Creating table and migrating data.\n";
switch ($driver) {
case 'mysql' :
case 'mysql':
$pdo->exec(<<<SQL
CREATE TABLE calendarinstances (
id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
@ -114,7 +111,7 @@ CREATE TABLE calendarinstances (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
SQL
);
$pdo->exec("
$pdo->exec('
INSERT INTO calendarinstances
(
calendarid,
@ -138,9 +135,9 @@ SELECT
calendarcolor,
transparent
FROM calendars
");
');
break;
case 'sqlite' :
case 'sqlite':
$pdo->exec(<<<SQL
CREATE TABLE calendarinstances (
id integer primary key asc NOT NULL,
@ -163,7 +160,7 @@ CREATE TABLE calendarinstances (
);
SQL
);
$pdo->exec("
$pdo->exec('
INSERT INTO calendarinstances
(
calendarid,
@ -187,10 +184,9 @@ SELECT
calendarcolor,
transparent
FROM calendars
");
');
break;
}
}
try {
$result = $pdo->query('SELECT * FROM calendars LIMIT 1');
@ -202,37 +198,34 @@ try {
}
$columnCount = count($row);
if ($columnCount === 3) {
if (3 === $columnCount) {
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";
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_1_' . $backupPostfix;
$calendarBackup = 'calendars_3_1_'.$backupPostfix;
echo "Backing up 'calendars' to '", $calendarBackup, "'\n";
switch ($driver) {
case 'mysql' :
$pdo->exec('RENAME TABLE calendars TO ' . $calendarBackup);
case 'mysql':
$pdo->exec('RENAME TABLE calendars TO '.$calendarBackup);
break;
case 'sqlite' :
$pdo->exec('ALTER TABLE calendars RENAME TO ' . $calendarBackup);
case 'sqlite':
$pdo->exec('ALTER TABLE calendars RENAME TO '.$calendarBackup);
break;
}
echo "Creating new calendars table.\n";
switch ($driver) {
case 'mysql' :
case 'mysql':
$pdo->exec(<<<SQL
CREATE TABLE calendars (
id INTEGER UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
@ -242,7 +235,7 @@ CREATE TABLE calendars (
SQL
);
break;
case 'sqlite' :
case 'sqlite':
$pdo->exec(<<<SQL
CREATE TABLE calendars (
id integer primary key asc NOT NULL,
@ -252,7 +245,6 @@ CREATE TABLE calendars (
SQL
);
break;
}
echo "Migrating data from old to new table\n";
@ -261,8 +253,6 @@ SQL
INSERT INTO calendars (id, synctoken, components) SELECT id, synctoken, COALESCE(components,"VEVENT,VTODO,VJOURNAL") as components FROM $calendarBackup
SQL
);
}
echo "Upgrade to 3.2 schema completed.\n";

0
htdocs/includes/sabre/sabre/dav/bin/naturalselection Normal file → Executable file
View file

0
htdocs/includes/sabre/sabre/dav/bin/sabredav Normal file → Executable file
View file

26
htdocs/includes/sabre/sabre/dav/bin/sabredav.php Normal file → Executable file
View file

@ -2,34 +2,32 @@
// SabreDAV test server.
class CliLog {
class CliLog
{
protected $stream;
function __construct() {
public function __construct()
{
$this->stream = fopen('php://stdout', 'w');
}
function log($msg) {
fwrite($this->stream, $msg . "\n");
public function log($msg)
{
fwrite($this->stream, $msg."\n");
}
}
$log = new CliLog();
if (php_sapi_name() !== 'cli-server') {
die("This script is intended to run on the built-in php webserver");
if ('cli-server' !== php_sapi_name()) {
die('This script is intended to run on the built-in php webserver');
}
// Finding composer
$paths = [
__DIR__ . '/../vendor/autoload.php',
__DIR__ . '/../../../autoload.php',
__DIR__.'/../vendor/autoload.php',
__DIR__.'/../../../autoload.php',
];
foreach ($paths as $path) {
@ -41,7 +39,7 @@ foreach ($paths as $path) {
use Sabre\DAV;
// Root
// Root
$root = new DAV\FS\Directory(getcwd());
// Setting up server.

View file

@ -14,12 +14,12 @@
}
],
"require": {
"php": ">=5.5.0",
"php": ">=7.0.0",
"sabre/vobject": "^4.2.2",
"sabre/event" : ">=2.0.0, <4.0.0",
"sabre/xml" : "^1.4.0",
"sabre/http" : "^4.2.1",
"sabre/uri" : "^1.0.1",
"sabre/event" : "^5.0",
"sabre/xml" : "^2.2.5",
"sabre/http" : "^5.0.5",
"sabre/uri" : "^2.2.3",
"ext-dom": "*",
"ext-pcre": "*",
"ext-spl": "*",
@ -29,17 +29,18 @@
"ext-date" : "*",
"ext-iconv" : "*",
"lib-libxml" : ">=2.7.0",
"psr/log": "^1.0"
"psr/log": "^1.0",
"ext-json": "*"
},
"require-dev" : {
"phpunit/phpunit" : "> 4.8, <6.0.0",
"phpunit/phpunit" : "^6",
"evert/phpdoc-md" : "~0.1.0",
"sabre/cs" : "^1.0.0",
"monolog/monolog": "^1.18"
},
"suggest" : {
"ext-curl" : "*",
"ext-pdo" : "*"
"ext-pdo" : "*",
"ext-imap": "*"
},
"autoload": {
"psr-4" : {
@ -59,10 +60,5 @@
],
"config" : {
"bin-dir" : "./bin"
},
"extra" : {
"branch-alias": {
"dev-master": "3.1.0-dev"
}
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Backend;
use Sabre\CalDAV;
@ -14,8 +16,8 @@ use Sabre\VObject;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
abstract class AbstractBackend implements BackendInterface {
abstract class AbstractBackend implements BackendInterface
{
/**
* Updates properties for a calendar.
*
@ -28,12 +30,11 @@ abstract class AbstractBackend implements BackendInterface {
*
* Read the PropPatch documentation for more info and examples.
*
* @param mixed $calendarId
* @param mixed $calendarId
* @param \Sabre\DAV\PropPatch $propPatch
* @return void
*/
function updateCalendar($calendarId, \Sabre\DAV\PropPatch $propPatch) {
public function updateCalendar($calendarId, \Sabre\DAV\PropPatch $propPatch)
{
}
/**
@ -46,14 +47,14 @@ abstract class AbstractBackend implements BackendInterface {
*
* @param mixed $calendarId
* @param array $uris
*
* @return array
*/
function getMultipleCalendarObjects($calendarId, array $uris) {
return array_map(function($uri) use ($calendarId) {
public function getMultipleCalendarObjects($calendarId, array $uris)
{
return array_map(function ($uri) use ($calendarId) {
return $this->getCalendarObject($calendarId, $uri);
}, $uris);
}
/**
@ -103,23 +104,21 @@ abstract class AbstractBackend implements BackendInterface {
*
* @param mixed $calendarId
* @param array $filters
*
* @return array
*/
function calendarQuery($calendarId, array $filters) {
public function calendarQuery($calendarId, array $filters)
{
$result = [];
$objects = $this->getCalendarObjects($calendarId);
foreach ($objects as $object) {
if ($this->validateFilterForObject($object, $filters)) {
$result[] = $object['uri'];
}
}
return $result;
}
/**
@ -128,10 +127,11 @@ abstract class AbstractBackend implements BackendInterface {
*
* @param array $object
* @param array $filters
*
* @return bool
*/
protected function validateFilterForObject(array $object, array $filters) {
protected function validateFilterForObject(array $object, array $filters)
{
// Unfortunately, setting the 'calendardata' here is optional. If
// it was excluded, we actually need another call to get this as
// well.
@ -148,7 +148,6 @@ abstract class AbstractBackend implements BackendInterface {
$vObject->destroy();
return $result;
}
/**
@ -168,14 +167,14 @@ abstract class AbstractBackend implements BackendInterface {
*
* @param string $principalUri
* @param string $uid
*
* @return string|null
*/
function getCalendarObjectByUID($principalUri, $uid) {
public function getCalendarObjectByUID($principalUri, $uid)
{
// Note: this is a super slow naive implementation of this method. You
// are highly recommended to optimize it, if your backend allows it.
foreach ($this->getCalendarsForUser($principalUri) as $calendar) {
// We must ignore calendars owned by other principals.
if ($calendar['principaluri'] !== $principalUri) {
continue;
@ -189,38 +188,35 @@ abstract class AbstractBackend implements BackendInterface {
$results = $this->calendarQuery(
$calendar['id'],
[
'name' => 'VCALENDAR',
'name' => 'VCALENDAR',
'prop-filters' => [],
'comp-filters' => [
[
'name' => 'VEVENT',
'name' => 'VEVENT',
'is-not-defined' => false,
'time-range' => null,
'comp-filters' => [],
'prop-filters' => [
'time-range' => null,
'comp-filters' => [],
'prop-filters' => [
[
'name' => 'UID',
'name' => 'UID',
'is-not-defined' => false,
'time-range' => null,
'text-match' => [
'value' => $uid,
'time-range' => null,
'text-match' => [
'value' => $uid,
'negate-condition' => false,
'collation' => 'i;octet',
'collation' => 'i;octet',
],
'param-filters' => [],
],
]
]
],
],
],
]
);
if ($results) {
// We have a match
return $calendar['uri'] . '/' . $results[0];
return $calendar['uri'].'/'.$results[0];
}
}
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Backend;
/**
@ -9,8 +11,8 @@ namespace Sabre\CalDAV\Backend;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
interface BackendInterface {
interface BackendInterface
{
/**
* Returns a list of calendars for a principal.
*
@ -34,9 +36,10 @@ interface BackendInterface {
* ACL will automatically be put in read-only mode.
*
* @param string $principalUri
*
* @return array
*/
function getCalendarsForUser($principalUri);
public function getCalendarsForUser($principalUri);
/**
* Creates a new calendar for a principal.
@ -48,10 +51,11 @@ interface BackendInterface {
*
* @param string $principalUri
* @param string $calendarUri
* @param array $properties
* @param array $properties
*
* @return mixed
*/
function createCalendar($principalUri, $calendarUri, array $properties);
public function createCalendar($principalUri, $calendarUri, array $properties);
/**
* Updates properties for a calendar.
@ -65,19 +69,17 @@ interface BackendInterface {
*
* Read the PropPatch documentation for more info and examples.
*
* @param mixed $calendarId
* @param mixed $calendarId
* @param \Sabre\DAV\PropPatch $propPatch
* @return void
*/
function updateCalendar($calendarId, \Sabre\DAV\PropPatch $propPatch);
public function updateCalendar($calendarId, \Sabre\DAV\PropPatch $propPatch);
/**
* Delete a calendar and all its objects
* Delete a calendar and all its objects.
*
* @param mixed $calendarId
* @return void
*/
function deleteCalendar($calendarId);
public function deleteCalendar($calendarId);
/**
* Returns all calendar objects within a calendar.
@ -108,9 +110,10 @@ interface BackendInterface {
* amount of times this is needed is reduced by a great degree.
*
* @param mixed $calendarId
*
* @return array
*/
function getCalendarObjects($calendarId);
public function getCalendarObjects($calendarId);
/**
* Returns information from a single calendar object, based on it's object
@ -124,11 +127,12 @@ interface BackendInterface {
*
* This method must return null if the object did not exist.
*
* @param mixed $calendarId
* @param mixed $calendarId
* @param string $objectUri
*
* @return array|null
*/
function getCalendarObject($calendarId, $objectUri);
public function getCalendarObject($calendarId, $objectUri);
/**
* Returns a list of calendar objects.
@ -140,9 +144,10 @@ interface BackendInterface {
*
* @param mixed $calendarId
* @param array $uris
*
* @return array
*/
function getMultipleCalendarObjects($calendarId, array $uris);
public function getMultipleCalendarObjects($calendarId, array $uris);
/**
* Creates a new calendar object.
@ -157,12 +162,13 @@ interface BackendInterface {
* 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 mixed $calendarId
* @param string $objectUri
* @param string $calendarData
*
* @return string|null
*/
function createCalendarObject($calendarId, $objectUri, $calendarData);
public function createCalendarObject($calendarId, $objectUri, $calendarData);
/**
* Updates an existing calendarobject, based on it's uri.
@ -177,23 +183,23 @@ interface BackendInterface {
* 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 mixed $calendarId
* @param string $objectUri
* @param string $calendarData
*
* @return string|null
*/
function updateCalendarObject($calendarId, $objectUri, $calendarData);
public function updateCalendarObject($calendarId, $objectUri, $calendarData);
/**
* Deletes an existing calendar object.
*
* The object uri is only the basename, or filename and not a full path.
*
* @param mixed $calendarId
* @param mixed $calendarId
* @param string $objectUri
* @return void
*/
function deleteCalendarObject($calendarId, $objectUri);
public function deleteCalendarObject($calendarId, $objectUri);
/**
* Performs a calendar-query on the contents of this calendar.
@ -242,9 +248,10 @@ interface BackendInterface {
*
* @param mixed $calendarId
* @param array $filters
*
* @return array
*/
function calendarQuery($calendarId, array $filters);
public function calendarQuery($calendarId, array $filters);
/**
* Searches through all of a users calendars and calendar objects to find
@ -263,8 +270,8 @@ interface BackendInterface {
*
* @param string $principalUri
* @param string $uid
*
* @return string|null
*/
function getCalendarObjectByUID($principalUri, $uid);
public function getCalendarObjectByUID($principalUri, $uid);
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Backend;
use Sabre\CalDAV\Xml\Notification\NotificationInterface;
@ -22,26 +24,26 @@ use Sabre\CalDAV\Xml\Notification\NotificationInterface;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
interface NotificationSupport extends BackendInterface {
interface NotificationSupport extends BackendInterface
{
/**
* Returns a list of notifications for a given principal url.
*
* @param string $principalUri
*
* @return NotificationInterface[]
*/
function getNotificationsForPrincipal($principalUri);
public function getNotificationsForPrincipal($principalUri);
/**
* This deletes a specific notifcation.
*
* This may be called by a client once it deems a notification handled.
*
* @param string $principalUri
* @param string $principalUri
* @param NotificationInterface $notification
* @return void
*/
function deleteNotification($principalUri, NotificationInterface $notification);
public function deleteNotification($principalUri, NotificationInterface $notification);
/**
* This method is called when a user replied to a request to share.
@ -49,13 +51,13 @@ interface NotificationSupport extends BackendInterface {
* If the user chose to accept the share, this method should return the
* newly created calendar url.
*
* @param string $href The sharee who is replying (often a mailto: address)
* @param int $status One of the SharingPlugin::STATUS_* constants
* @param string $href The sharee who is replying (often a mailto: address)
* @param int $status One of the SharingPlugin::STATUS_* constants
* @param string $calendarUri The url to the calendar thats being shared
* @param string $inReplyTo The unique id this message is a response to
* @param string $summary A description of the reply
* @return null|string
* @param string $inReplyTo The unique id this message is a response to
* @param string $summary A description of the reply
*
* @return string|null
*/
function shareReply($href, $status, $calendarUri, $inReplyTo, $summary = null);
public function shareReply($href, $status, $calendarUri, $inReplyTo, $summary = null);
}

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Backend;
/**
@ -10,8 +12,8 @@ namespace Sabre\CalDAV\Backend;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
interface SchedulingSupport extends BackendInterface {
interface SchedulingSupport extends BackendInterface
{
/**
* Returns a single scheduling object for the inbox collection.
*
@ -26,9 +28,10 @@ interface SchedulingSupport extends BackendInterface {
*
* @param string $principalUri
* @param string $objectUri
*
* @return array
*/
function getSchedulingObject($principalUri, $objectUri);
public function getSchedulingObject($principalUri, $objectUri);
/**
* Returns all scheduling objects for the inbox collection.
@ -39,18 +42,18 @@ interface SchedulingSupport extends BackendInterface {
* The main difference is that 'calendardata' is optional.
*
* @param string $principalUri
*
* @return array
*/
function getSchedulingObjects($principalUri);
public function getSchedulingObjects($principalUri);
/**
* Deletes a scheduling object from the inbox collection.
*
* @param string $principalUri
* @param string $objectUri
* @return void
*/
function deleteSchedulingObject($principalUri, $objectUri);
public function deleteSchedulingObject($principalUri, $objectUri);
/**
* Creates a new scheduling object. This should land in a users' inbox.
@ -58,8 +61,6 @@ interface SchedulingSupport extends BackendInterface {
* @param string $principalUri
* @param string $objectUri
* @param string $objectData
* @return void
*/
function createSchedulingObject($principalUri, $objectUri, $objectData);
public function createSchedulingObject($principalUri, $objectUri, $objectData);
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Backend;
/**
@ -20,16 +22,15 @@ namespace Sabre\CalDAV\Backend;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
interface SharingSupport extends BackendInterface {
interface SharingSupport extends BackendInterface
{
/**
* Updates the list of shares.
*
* @param mixed $calendarId
* @param mixed $calendarId
* @param \Sabre\DAV\Xml\Element\Sharee[] $sharees
* @return void
*/
function updateInvites($calendarId, array $sharees);
public function updateInvites($calendarId, array $sharees);
/**
* Returns the list of people whom this calendar is shared with.
@ -44,17 +45,16 @@ interface SharingSupport extends BackendInterface {
* $properties
*
* @param mixed $calendarId
*
* @return \Sabre\DAV\Xml\Element\Sharee[]
*/
function getInvites($calendarId);
public function getInvites($calendarId);
/**
* Publishes a calendar
* Publishes a calendar.
*
* @param mixed $calendarId
* @param bool $value
* @return void
* @param bool $value
*/
function setPublishStatus($calendarId, $value);
public function setPublishStatus($calendarId, $value);
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Backend;
use Sabre\CalDAV;
@ -31,24 +33,23 @@ use Sabre\DAV;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class SimplePDO extends AbstractBackend {
class SimplePDO extends AbstractBackend
{
/**
* pdo
* pdo.
*
* @var \PDO
*/
protected $pdo;
/**
* Creates the backend
* Creates the backend.
*
* @param \PDO $pdo
*/
function __construct(\PDO $pdo) {
public function __construct(\PDO $pdo)
{
$this->pdo = $pdo;
}
/**
@ -73,27 +74,25 @@ class SimplePDO extends AbstractBackend {
* ACL will automatically be put in read-only mode.
*
* @param string $principalUri
*
* @return array
*/
function getCalendarsForUser($principalUri) {
public function getCalendarsForUser($principalUri)
{
// Making fields a comma-delimited list
$stmt = $this->pdo->prepare("SELECT id, uri FROM simple_calendars WHERE principaluri = ? ORDER BY id ASC");
$stmt = $this->pdo->prepare('SELECT id, uri FROM simple_calendars WHERE principaluri = ? ORDER BY id ASC');
$stmt->execute([$principalUri]);
$calendars = [];
while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
$calendars[] = [
'id' => $row['id'],
'uri' => $row['uri'],
'id' => $row['id'],
'uri' => $row['uri'],
'principaluri' => $principalUri,
];
}
return $calendars;
}
/**
@ -104,32 +103,30 @@ class SimplePDO extends AbstractBackend {
*
* @param string $principalUri
* @param string $calendarUri
* @param array $properties
* @param array $properties
*
* @return string
*/
function createCalendar($principalUri, $calendarUri, array $properties) {
$stmt = $this->pdo->prepare("INSERT INTO simple_calendars (principaluri, uri) VALUES (?, ?)");
public 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
* Delete a calendar and all it's objects.
*
* @param string $calendarId
* @return void
*/
function deleteCalendar($calendarId) {
public 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]);
}
/**
@ -161,27 +158,27 @@ class SimplePDO extends AbstractBackend {
* amount of times this is needed is reduced by a great degree.
*
* @param string $calendarId
*
* @return array
*/
function getCalendarObjects($calendarId) {
public 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']),
'id' => $row['id'],
'uri' => $row['uri'],
'etag' => '"'.md5($row['calendardata']).'"',
'calendarid' => $calendarId,
'size' => strlen($row['calendardata']),
'calendardata' => $row['calendardata'],
];
}
return $result;
}
/**
@ -198,25 +195,27 @@ class SimplePDO extends AbstractBackend {
*
* @param string $calendarId
* @param string $objectUri
*
* @return array|null
*/
function getCalendarObject($calendarId, $objectUri) {
public 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;
if (!$row) {
return null;
}
return [
'id' => $row['id'],
'uri' => $row['uri'],
'etag' => '"' . md5($row['calendardata']) . '"',
'calendarid' => $calendarId,
'size' => strlen($row['calendardata']),
'id' => $row['id'],
'uri' => $row['uri'],
'etag' => '"'.md5($row['calendardata']).'"',
'calendarid' => $calendarId,
'size' => strlen($row['calendardata']),
'calendardata' => $row['calendardata'],
];
}
/**
@ -232,22 +231,22 @@ class SimplePDO extends AbstractBackend {
* 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 mixed $calendarId
* @param string $objectUri
* @param string $calendarData
*
* @return string|null
*/
function createCalendarObject($calendarId, $objectUri, $calendarData) {
public function createCalendarObject($calendarId, $objectUri, $calendarData)
{
$stmt = $this->pdo->prepare('INSERT INTO simple_calendarobjects (calendarid, uri, calendardata) VALUES (?,?,?)');
$stmt->execute([
$calendarId,
$objectUri,
$calendarData
$calendarData,
]);
return '"' . md5($calendarData) . '"';
return '"'.md5($calendarData).'"';
}
/**
@ -263,18 +262,18 @@ class SimplePDO extends AbstractBackend {
* 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 mixed $calendarId
* @param string $objectUri
* @param string $calendarData
*
* @return string|null
*/
function updateCalendarObject($calendarId, $objectUri, $calendarData) {
public 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) . '"';
return '"'.md5($calendarData).'"';
}
/**
@ -284,13 +283,10 @@ class SimplePDO extends AbstractBackend {
*
* @param string $calendarId
* @param string $objectUri
* @return void
*/
function deleteCalendarObject($calendarId, $objectUri) {
public function deleteCalendarObject($calendarId, $objectUri)
{
$stmt = $this->pdo->prepare('DELETE FROM simple_calendarobjects WHERE calendarid = ? AND uri = ?');
$stmt->execute([$calendarId, $objectUri]);
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Backend;
use Sabre\DAV;
@ -11,8 +13,8 @@ use Sabre\DAV;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
interface SubscriptionSupport extends BackendInterface {
interface SubscriptionSupport extends BackendInterface
{
/**
* Returns a list of subscriptions for a principal.
*
@ -43,9 +45,10 @@ interface SubscriptionSupport extends BackendInterface {
* default components).
*
* @param string $principalUri
*
* @return array
*/
function getSubscriptionsForUser($principalUri);
public function getSubscriptionsForUser($principalUri);
/**
* Creates a new subscription for a principal.
@ -55,13 +58,14 @@ interface SubscriptionSupport extends BackendInterface {
*
* @param string $principalUri
* @param string $uri
* @param array $properties
* @param array $properties
*
* @return mixed
*/
function createSubscription($principalUri, $uri, array $properties);
public function createSubscription($principalUri, $uri, array $properties);
/**
* Updates a subscription
* Updates a subscription.
*
* The list of mutations is stored in a Sabre\DAV\PropPatch object.
* To do the actual updates, you must tell this object which properties
@ -72,18 +76,15 @@ interface SubscriptionSupport extends BackendInterface {
*
* Read the PropPatch documentation for more info and examples.
*
* @param mixed $subscriptionId
* @param mixed $subscriptionId
* @param \Sabre\DAV\PropPatch $propPatch
* @return void
*/
function updateSubscription($subscriptionId, DAV\PropPatch $propPatch);
public function updateSubscription($subscriptionId, DAV\PropPatch $propPatch);
/**
* Deletes a subscription.
*
* @param mixed $subscriptionId
* @return void
*/
function deleteSubscription($subscriptionId);
public function deleteSubscription($subscriptionId);
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Backend;
/**
@ -18,8 +20,8 @@ namespace Sabre\CalDAV\Backend;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
interface SyncSupport extends BackendInterface {
interface SyncSupport extends BackendInterface
{
/**
* The getChanges method returns all the changes that have happened, since
* the specified syncToken in the specified calendar.
@ -72,10 +74,10 @@ interface SyncSupport extends BackendInterface {
*
* @param string $calendarId
* @param string $syncToken
* @param int $syncLevel
* @param int $limit
* @param int $syncLevel
* @param int $limit
*
* @return array
*/
function getChangesForCalendar($calendarId, $syncToken, $syncLevel, $limit = null);
public function getChangesForCalendar($calendarId, $syncToken, $syncLevel, $limit = null);
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV;
use Sabre\DAV;
@ -16,46 +18,44 @@ use Sabre\DAVACL;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class Calendar implements ICalendar, DAV\IProperties, DAV\Sync\ISyncCollection, DAV\IMultiGet {
class Calendar implements ICalendar, DAV\IProperties, DAV\Sync\ISyncCollection, DAV\IMultiGet
{
use DAVACL\ACLTrait;
/**
* This is an array with calendar information
* This is an array with calendar information.
*
* @var array
*/
protected $calendarInfo;
/**
* CalDAV backend
* CalDAV backend.
*
* @var Backend\BackendInterface
*/
protected $caldavBackend;
/**
* Constructor
* Constructor.
*
* @param Backend\BackendInterface $caldavBackend
* @param array $calendarInfo
* @param array $calendarInfo
*/
function __construct(Backend\BackendInterface $caldavBackend, $calendarInfo) {
public function __construct(Backend\BackendInterface $caldavBackend, $calendarInfo)
{
$this->caldavBackend = $caldavBackend;
$this->calendarInfo = $calendarInfo;
}
/**
* Returns the name of the calendar
* Returns the name of the calendar.
*
* @return string
*/
function getName() {
public function getName()
{
return $this->calendarInfo['uri'];
}
/**
@ -68,69 +68,68 @@ class Calendar implements ICalendar, DAV\IProperties, DAV\Sync\ISyncCollection,
* Read the PropPatch documentation for more information.
*
* @param PropPatch $propPatch
* @return void
*/
function propPatch(PropPatch $propPatch) {
public function propPatch(PropPatch $propPatch)
{
return $this->caldavBackend->updateCalendar($this->calendarInfo['id'], $propPatch);
}
/**
* Returns the list of properties
* Returns the list of properties.
*
* @param array $requestedProperties
*
* @return array
*/
function getProperties($requestedProperties) {
public function getProperties($requestedProperties)
{
$response = [];
foreach ($this->calendarInfo as $propName => $propValue) {
if (!is_null($propValue) && $propName[0] === '{')
if (!is_null($propValue) && '{' === $propName[0]) {
$response[$propName] = $this->calendarInfo[$propName];
}
}
return $response;
return $response;
}
/**
* Returns a calendar object
* Returns a calendar object.
*
* The contained calendar objects are for example Events or Todo's.
*
* @param string $name
*
* @return \Sabre\CalDAV\ICalendarObject
*/
function getChild($name) {
public function getChild($name)
{
$obj = $this->caldavBackend->getCalendarObject($this->calendarInfo['id'], $name);
if (!$obj) throw new DAV\Exception\NotFound('Calendar object not found');
if (!$obj) {
throw new DAV\Exception\NotFound('Calendar object not found');
}
$obj['acl'] = $this->getChildACL();
return new CalendarObject($this->caldavBackend, $this->calendarInfo, $obj);
}
/**
* Returns the full list of calendar objects
* Returns the full list of calendar objects.
*
* @return array
*/
function getChildren() {
public function getChildren()
{
$objs = $this->caldavBackend->getCalendarObjects($this->calendarInfo['id']);
$children = [];
foreach ($objs as $obj) {
$obj['acl'] = $this->getChildACL();
$children[] = new CalendarObject($this->caldavBackend, $this->calendarInfo, $obj);
}
return $children;
return $children;
}
/**
@ -140,77 +139,75 @@ class Calendar implements ICalendar, DAV\IProperties, DAV\Sync\ISyncCollection,
* If any children are not found, you do not have to return them.
*
* @param string[] $paths
*
* @return array
*/
function getMultipleChildren(array $paths) {
public function getMultipleChildren(array $paths)
{
$objs = $this->caldavBackend->getMultipleCalendarObjects($this->calendarInfo['id'], $paths);
$children = [];
foreach ($objs as $obj) {
$obj['acl'] = $this->getChildACL();
$children[] = new CalendarObject($this->caldavBackend, $this->calendarInfo, $obj);
}
return $children;
return $children;
}
/**
* Checks if a child-node exists.
*
* @param string $name
*
* @return bool
*/
function childExists($name) {
public function childExists($name)
{
$obj = $this->caldavBackend->getCalendarObject($this->calendarInfo['id'], $name);
if (!$obj)
if (!$obj) {
return false;
else
} else {
return true;
}
}
/**
* Creates a new directory
* Creates a new directory.
*
* We actually block this, as subdirectories are not allowed in calendars.
*
* @param string $name
* @return void
*/
function createDirectory($name) {
public function createDirectory($name)
{
throw new DAV\Exception\MethodNotAllowed('Creating collections in calendar objects is not allowed');
}
/**
* Creates a new file
* Creates a new file.
*
* The contents of the new file must be a valid ICalendar string.
*
* @param string $name
* @param string $name
* @param resource $calendarData
*
* @return string|null
*/
function createFile($name, $calendarData = null) {
public function createFile($name, $calendarData = null)
{
if (is_resource($calendarData)) {
$calendarData = stream_get_contents($calendarData);
}
return $this->caldavBackend->createCalendarObject($this->calendarInfo['id'], $name, $calendarData);
return $this->caldavBackend->createCalendarObject($this->calendarInfo['id'], $name, $calendarData);
}
/**
* Deletes the calendar.
*
* @return void
*/
function delete() {
public function delete()
{
$this->caldavBackend->deleteCalendar($this->calendarInfo['id']);
}
/**
@ -218,36 +215,30 @@ class Calendar implements ICalendar, DAV\IProperties, DAV\Sync\ISyncCollection,
* {DAV:}displayname to display a name to display a name.
*
* @param string $newName
* @return void
*/
function setName($newName) {
public function setName($newName)
{
throw new DAV\Exception\MethodNotAllowed('Renaming calendars is not yet supported');
}
/**
* Returns the last modification date as a unix timestamp.
*
* @return null
*/
function getLastModified() {
public function getLastModified()
{
return null;
}
/**
* Returns the owner principal
* Returns the owner principal.
*
* This must be a url to a principal, or null if there's no owner
*
* @return string|null
*/
function getOwner() {
public function getOwner()
{
return $this->calendarInfo['principaluri'];
}
/**
@ -262,8 +253,8 @@ class Calendar implements ICalendar, DAV\IProperties, DAV\Sync\ISyncCollection,
*
* @return array
*/
function getACL() {
public function getACL()
{
$acl = [
[
'privilege' => '{DAV:}read',
@ -272,20 +263,19 @@ class Calendar implements ICalendar, DAV\IProperties, DAV\Sync\ISyncCollection,
],
[
'privilege' => '{DAV:}read',
'principal' => $this->getOwner() . '/calendar-proxy-write',
'principal' => $this->getOwner().'/calendar-proxy-write',
'protected' => true,
],
[
'privilege' => '{DAV:}read',
'principal' => $this->getOwner() . '/calendar-proxy-read',
'principal' => $this->getOwner().'/calendar-proxy-read',
'protected' => true,
],
[
'privilege' => '{' . Plugin::NS_CALDAV . '}read-free-busy',
'privilege' => '{'.Plugin::NS_CALDAV.'}read-free-busy',
'principal' => '{DAV:}authenticated',
'protected' => true,
],
];
if (empty($this->calendarInfo['{http://sabredav.org/ns}read-only'])) {
$acl[] = [
@ -295,13 +285,12 @@ class Calendar implements ICalendar, DAV\IProperties, DAV\Sync\ISyncCollection,
];
$acl[] = [
'privilege' => '{DAV:}write',
'principal' => $this->getOwner() . '/calendar-proxy-write',
'principal' => $this->getOwner().'/calendar-proxy-write',
'protected' => true,
];
}
return $acl;
}
/**
@ -311,8 +300,8 @@ class Calendar implements ICalendar, DAV\IProperties, DAV\Sync\ISyncCollection,
*
* @return array
*/
function getChildACL() {
public function getChildACL()
{
$acl = [
[
'privilege' => '{DAV:}read',
@ -322,15 +311,14 @@ class Calendar implements ICalendar, DAV\IProperties, DAV\Sync\ISyncCollection,
[
'privilege' => '{DAV:}read',
'principal' => $this->getOwner() . '/calendar-proxy-write',
'principal' => $this->getOwner().'/calendar-proxy-write',
'protected' => true,
],
[
'privilege' => '{DAV:}read',
'principal' => $this->getOwner() . '/calendar-proxy-read',
'principal' => $this->getOwner().'/calendar-proxy-read',
'protected' => true,
],
];
if (empty($this->calendarInfo['{http://sabredav.org/ns}read-only'])) {
$acl[] = [
@ -340,16 +328,14 @@ class Calendar implements ICalendar, DAV\IProperties, DAV\Sync\ISyncCollection,
];
$acl[] = [
'privilege' => '{DAV:}write',
'principal' => $this->getOwner() . '/calendar-proxy-write',
'principal' => $this->getOwner().'/calendar-proxy-write',
'protected' => true,
];
}
return $acl;
}
/**
* Performs a calendar-query on the contents of this calendar.
*
@ -365,12 +351,12 @@ class Calendar implements ICalendar, DAV\IProperties, DAV\Sync\ISyncCollection,
* documented by Sabre\CalDAV\CalendarQueryParser.
*
* @param array $filters
*
* @return array
*/
function calendarQuery(array $filters) {
public function calendarQuery(array $filters)
{
return $this->caldavBackend->calendarQuery($this->calendarInfo['id'], $filters);
}
/**
@ -382,8 +368,8 @@ class Calendar implements ICalendar, DAV\IProperties, DAV\Sync\ISyncCollection,
*
* @return string|null
*/
function getSyncToken() {
public function getSyncToken()
{
if (
$this->caldavBackend instanceof Backend\SyncSupport &&
isset($this->calendarInfo['{DAV:}sync-token'])
@ -396,7 +382,6 @@ class Calendar implements ICalendar, DAV\IProperties, DAV\Sync\ISyncCollection,
) {
return $this->calendarInfo['{http://sabredav.org/ns}sync-token'];
}
}
/**
@ -450,12 +435,13 @@ class Calendar implements ICalendar, DAV\IProperties, DAV\Sync\ISyncCollection,
* The limit is 'suggestive'. You are free to ignore it.
*
* @param string $syncToken
* @param int $syncLevel
* @param int $limit
* @param int $syncLevel
* @param int $limit
*
* @return array
*/
function getChanges($syncToken, $syncLevel, $limit = null) {
public function getChanges($syncToken, $syncLevel, $limit = null)
{
if (!$this->caldavBackend instanceof Backend\SyncSupport) {
return null;
}
@ -466,7 +452,5 @@ class Calendar implements ICalendar, DAV\IProperties, DAV\Sync\ISyncCollection,
$syncLevel,
$limit
);
}
}

View file

@ -1,12 +1,14 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV;
use Sabre\DAV;
use Sabre\DAV\Exception\NotFound;
use Sabre\DAV\MkCol;
use Sabre\DAVACL;
use Sabre\HTTP\URLUtil;
use Sabre\Uri;
/**
* The CalendarHome represents a node that is usually in a users'
@ -20,81 +22,74 @@ use Sabre\HTTP\URLUtil;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class CalendarHome implements DAV\IExtendedCollection, DAVACL\IACL {
class CalendarHome implements DAV\IExtendedCollection, DAVACL\IACL
{
use DAVACL\ACLTrait;
/**
* CalDAV backend
* CalDAV backend.
*
* @var Backend\BackendInterface
*/
protected $caldavBackend;
/**
* Principal information
* Principal information.
*
* @var array
*/
protected $principalInfo;
/**
* Constructor
* Constructor.
*
* @param Backend\BackendInterface $caldavBackend
* @param array $principalInfo
* @param array $principalInfo
*/
function __construct(Backend\BackendInterface $caldavBackend, $principalInfo) {
public function __construct(Backend\BackendInterface $caldavBackend, $principalInfo)
{
$this->caldavBackend = $caldavBackend;
$this->principalInfo = $principalInfo;
}
/**
* Returns the name of this object
* Returns the name of this object.
*
* @return string
*/
function getName() {
public function getName()
{
list(, $name) = Uri\split($this->principalInfo['uri']);
list(, $name) = URLUtil::splitPath($this->principalInfo['uri']);
return $name;
}
/**
* Updates the name of this object
* Updates the name of this object.
*
* @param string $name
* @return void
*/
function setName($name) {
public function setName($name)
{
throw new DAV\Exception\Forbidden();
}
/**
* Deletes this object
*
* @return void
* Deletes this object.
*/
function delete() {
public function delete()
{
throw new DAV\Exception\Forbidden();
}
/**
* Returns the last modification date
* Returns the last modification date.
*
* @return int
*/
function getLastModified() {
public function getLastModified()
{
return null;
}
/**
@ -102,14 +97,12 @@ class CalendarHome implements DAV\IExtendedCollection, DAVACL\IACL {
*
* This is currently not allowed
*
* @param string $filename
* @param string $filename
* @param resource $data
* @return void
*/
function createFile($filename, $data = null) {
public function createFile($filename, $data = null)
{
throw new DAV\Exception\MethodNotAllowed('Creating new files in this collection is not supported');
}
/**
@ -118,30 +111,29 @@ class CalendarHome implements DAV\IExtendedCollection, DAVACL\IACL {
* This is currently not allowed.
*
* @param string $filename
* @return void
*/
function createDirectory($filename) {
public function createDirectory($filename)
{
throw new DAV\Exception\MethodNotAllowed('Creating new collections in this collection is not supported');
}
/**
* Returns a single calendar, by name
* Returns a single calendar, by name.
*
* @param string $name
*
* @return Calendar
*/
function getChild($name) {
public function getChild($name)
{
// Special nodes
if ($name === 'inbox' && $this->caldavBackend instanceof Backend\SchedulingSupport) {
if ('inbox' === $name && $this->caldavBackend instanceof Backend\SchedulingSupport) {
return new Schedule\Inbox($this->caldavBackend, $this->principalInfo['uri']);
}
if ($name === 'outbox' && $this->caldavBackend instanceof Backend\SchedulingSupport) {
if ('outbox' === $name && $this->caldavBackend instanceof Backend\SchedulingSupport) {
return new Schedule\Outbox($this->principalInfo['uri']);
}
if ($name === 'notifications' && $this->caldavBackend instanceof Backend\NotificationSupport) {
if ('notifications' === $name && $this->caldavBackend instanceof Backend\NotificationSupport) {
return new Notifications\Collection($this->caldavBackend, $this->principalInfo['uri']);
}
@ -162,36 +154,34 @@ class CalendarHome implements DAV\IExtendedCollection, DAVACL\IACL {
return new Subscriptions\Subscription($this->caldavBackend, $subscription);
}
}
}
throw new NotFound('Node with name \'' . $name . '\' could not be found');
throw new NotFound('Node with name \''.$name.'\' could not be found');
}
/**
* Checks if a calendar exists.
*
* @param string $name
*
* @return bool
*/
function childExists($name) {
public function childExists($name)
{
try {
return !!$this->getChild($name);
return (bool) $this->getChild($name);
} catch (NotFound $e) {
return false;
}
}
/**
* Returns a list of calendars
* Returns a list of calendars.
*
* @return array
*/
function getChildren() {
public function getChildren()
{
$calendars = $this->caldavBackend->getCalendarsForUser($this->principalInfo['uri']);
$objs = [];
foreach ($calendars as $calendar) {
@ -220,35 +210,34 @@ class CalendarHome implements DAV\IExtendedCollection, DAVACL\IACL {
}
return $objs;
}
/**
* Creates a new calendar or subscription.
*
* @param string $name
* @param MkCol $mkCol
* @param MkCol $mkCol
*
* @throws DAV\Exception\InvalidResourceType
* @return void
*/
function createExtendedCollection($name, MkCol $mkCol) {
public function createExtendedCollection($name, MkCol $mkCol)
{
$isCalendar = false;
$isSubscription = false;
foreach ($mkCol->getResourceType() as $rt) {
switch ($rt) {
case '{DAV:}collection' :
case '{http://calendarserver.org/ns/}shared-owner' :
case '{DAV:}collection':
case '{http://calendarserver.org/ns/}shared-owner':
// ignore
break;
case '{urn:ietf:params:xml:ns:caldav}calendar' :
case '{urn:ietf:params:xml:ns:caldav}calendar':
$isCalendar = true;
break;
case '{http://calendarserver.org/ns/}subscribed' :
case '{http://calendarserver.org/ns/}subscribed':
$isSubscription = true;
break;
default :
throw new DAV\Exception\InvalidResourceType('Unknown resourceType: ' . $rt);
default:
throw new DAV\Exception\InvalidResourceType('Unknown resourceType: '.$rt);
}
}
@ -260,15 +249,11 @@ class CalendarHome implements DAV\IExtendedCollection, DAVACL\IACL {
throw new DAV\Exception\InvalidResourceType('This backend does not support subscriptions');
}
$this->caldavBackend->createSubscription($this->principalInfo['uri'], $name, $properties);
} elseif ($isCalendar) {
$this->caldavBackend->createCalendar($this->principalInfo['uri'], $name, $properties);
} else {
throw new DAV\Exception\InvalidResourceType('You can only create calendars and subscriptions in this collection');
}
}
/**
@ -276,10 +261,9 @@ class CalendarHome implements DAV\IExtendedCollection, DAVACL\IACL {
*
* @return string
*/
function getOwner() {
public function getOwner()
{
return $this->principalInfo['uri'];
}
/**
@ -294,8 +278,8 @@ class CalendarHome implements DAV\IExtendedCollection, DAVACL\IACL {
*
* @return array
*/
function getACL() {
public function getACL()
{
return [
[
'privilege' => '{DAV:}read',
@ -309,46 +293,43 @@ class CalendarHome implements DAV\IExtendedCollection, DAVACL\IACL {
],
[
'privilege' => '{DAV:}read',
'principal' => $this->principalInfo['uri'] . '/calendar-proxy-write',
'principal' => $this->principalInfo['uri'].'/calendar-proxy-write',
'protected' => true,
],
[
'privilege' => '{DAV:}write',
'principal' => $this->principalInfo['uri'] . '/calendar-proxy-write',
'principal' => $this->principalInfo['uri'].'/calendar-proxy-write',
'protected' => true,
],
[
'privilege' => '{DAV:}read',
'principal' => $this->principalInfo['uri'] . '/calendar-proxy-read',
'principal' => $this->principalInfo['uri'].'/calendar-proxy-read',
'protected' => true,
],
];
}
/**
* This method is called when a user replied to a request to share.
*
* This method should return the url of the newly created calendar if the
* share was accepted.
*
* @param string $href The sharee who is replying (often a mailto: address)
* @param int $status One of the SharingPlugin::STATUS_* constants
* @param string $href The sharee who is replying (often a mailto: address)
* @param int $status One of the SharingPlugin::STATUS_* constants
* @param string $calendarUri The url to the calendar thats being shared
* @param string $inReplyTo The unique id this message is a response to
* @param string $summary A description of the reply
* @return null|string
* @param string $inReplyTo The unique id this message is a response to
* @param string $summary A description of the reply
*
* @return string|null
*/
function shareReply($href, $status, $calendarUri, $inReplyTo, $summary = null) {
public function shareReply($href, $status, $calendarUri, $inReplyTo, $summary = null)
{
if (!$this->caldavBackend instanceof Backend\SharingSupport) {
throw new DAV\Exception\NotImplemented('Sharing support is not implemented by this backend.');
}
return $this->caldavBackend->shareReply($href, $status, $calendarUri, $inReplyTo, $summary);
}
/**
@ -367,12 +348,11 @@ class CalendarHome implements DAV\IExtendedCollection, DAVACL\IACL {
* collection should be ignored.
*
* @param string $uid
*
* @return string|null
*/
function getCalendarObjectByUID($uid) {
public function getCalendarObjectByUID($uid)
{
return $this->caldavBackend->getCalendarObjectByUID($this->principalInfo['uri'], $uid);
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV;
/**
@ -9,33 +11,33 @@ namespace Sabre\CalDAV;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class CalendarObject extends \Sabre\DAV\File implements ICalendarObject, \Sabre\DAVACL\IACL {
class CalendarObject extends \Sabre\DAV\File implements ICalendarObject, \Sabre\DAVACL\IACL
{
use \Sabre\DAVACL\ACLTrait;
/**
* Sabre\CalDAV\Backend\BackendInterface
* Sabre\CalDAV\Backend\BackendInterface.
*
* @var Backend\AbstractBackend
*/
protected $caldavBackend;
/**
* Array with information about this CalendarObject
* Array with information about this CalendarObject.
*
* @var array
*/
protected $objectData;
/**
* Array with information about the containing calendar
* Array with information about the containing calendar.
*
* @var array
*/
protected $calendarInfo;
/**
* Constructor
* Constructor.
*
* The following properties may be passed within $objectData:
*
@ -49,11 +51,11 @@ class CalendarObject extends \Sabre\DAV\File implements ICalendarObject, \Sabre\
* * acl - (optional) Use this to override the default ACL for the node.
*
* @param Backend\BackendInterface $caldavBackend
* @param array $calendarInfo
* @param array $objectData
* @param array $calendarInfo
* @param array $objectData
*/
function __construct(Backend\BackendInterface $caldavBackend, array $calendarInfo, array $objectData) {
public function __construct(Backend\BackendInterface $caldavBackend, array $calendarInfo, array $objectData)
{
$this->caldavBackend = $caldavBackend;
if (!isset($objectData['uri'])) {
@ -62,44 +64,43 @@ class CalendarObject extends \Sabre\DAV\File implements ICalendarObject, \Sabre\
$this->calendarInfo = $calendarInfo;
$this->objectData = $objectData;
}
/**
* Returns the uri for this object
* Returns the uri for this object.
*
* @return string
*/
function getName() {
public function getName()
{
return $this->objectData['uri'];
}
/**
* Returns the ICalendar-formatted object
* Returns the ICalendar-formatted object.
*
* @return string
*/
function get() {
public function get()
{
// Pre-populating the 'calendardata' is optional, if we don't have it
// already we fetch it from the backend.
if (!isset($this->objectData['calendardata'])) {
$this->objectData = $this->caldavBackend->getCalendarObject($this->calendarInfo['id'], $this->objectData['uri']);
}
return $this->objectData['calendardata'];
return $this->objectData['calendardata'];
}
/**
* Updates the ICalendar-formatted object
* Updates the ICalendar-formatted object.
*
* @param string|resource $calendarData
*
* @return string
*/
function put($calendarData) {
public function put($calendarData)
{
if (is_resource($calendarData)) {
$calendarData = stream_get_contents($calendarData);
}
@ -108,33 +109,29 @@ class CalendarObject extends \Sabre\DAV\File implements ICalendarObject, \Sabre\
$this->objectData['etag'] = $etag;
return $etag;
}
/**
* Deletes the calendar object
*
* @return void
* Deletes the calendar object.
*/
function delete() {
public function delete()
{
$this->caldavBackend->deleteCalendarObject($this->calendarInfo['id'], $this->objectData['uri']);
}
/**
* Returns the mime content-type
* Returns the mime content-type.
*
* @return string
*/
function getContentType() {
public function getContentType()
{
$mime = 'text/calendar; charset=utf-8';
if (isset($this->objectData['component']) && $this->objectData['component']) {
$mime .= '; component=' . $this->objectData['component'];
$mime .= '; component='.$this->objectData['component'];
}
return $mime;
return $mime;
}
/**
@ -144,53 +141,49 @@ class CalendarObject extends \Sabre\DAV\File implements ICalendarObject, \Sabre\
*
* @return string
*/
function getETag() {
public function getETag()
{
if (isset($this->objectData['etag'])) {
return $this->objectData['etag'];
} else {
return '"' . md5($this->get()) . '"';
return '"'.md5($this->get()).'"';
}
}
/**
* Returns the last modification date as a unix timestamp
* Returns the last modification date as a unix timestamp.
*
* @return int
*/
function getLastModified() {
public function getLastModified()
{
return $this->objectData['lastmodified'];
}
/**
* Returns the size of this object in bytes
* Returns the size of this object in bytes.
*
* @return int
*/
function getSize() {
public function getSize()
{
if (array_key_exists('size', $this->objectData)) {
return $this->objectData['size'];
} else {
return strlen($this->get());
}
}
/**
* Returns the owner principal
* Returns the owner principal.
*
* This must be a url to a principal, or null if there's no owner
*
* @return string|null
*/
function getOwner() {
public function getOwner()
{
return $this->calendarInfo['principaluri'];
}
/**
@ -205,8 +198,8 @@ class CalendarObject extends \Sabre\DAV\File implements ICalendarObject, \Sabre\
*
* @return array
*/
function getACL() {
public function getACL()
{
// An alternative acl may be specified in the object data.
if (isset($this->objectData['acl'])) {
return $this->objectData['acl'];
@ -221,17 +214,14 @@ class CalendarObject extends \Sabre\DAV\File implements ICalendarObject, \Sabre\
],
[
'privilege' => '{DAV:}all',
'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write',
'principal' => $this->calendarInfo['principaluri'].'/calendar-proxy-write',
'protected' => true,
],
[
'privilege' => '{DAV:}read',
'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-read',
'principal' => $this->calendarInfo['principaluri'].'/calendar-proxy-read',
'protected' => true,
],
];
}
}

View file

@ -1,12 +1,14 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV;
use DateTime;
use Sabre\VObject;
/**
* CalendarQuery Validator
* CalendarQuery Validator.
*
* This class is responsible for checking if an iCalendar object matches a set
* of filters. The main function to do this is 'validate'.
@ -18,19 +20,20 @@ use Sabre\VObject;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class CalendarQueryValidator {
class CalendarQueryValidator
{
/**
* Verify if a list of filters applies to the calendar data object
* Verify if a list of filters applies to the calendar data object.
*
* The list of filters must be formatted as parsed by \Sabre\CalDAV\CalendarQueryParser
*
* @param VObject\Component\VCalendar $vObject
* @param array $filters
* @param array $filters
*
* @return bool
*/
function validate(VObject\Component\VCalendar $vObject, array $filters) {
public function validate(VObject\Component\VCalendar $vObject, array $filters)
{
// The top level object is always a component filter.
// We'll parse it manually, as it's pretty simple.
if ($vObject->name !== $filters['name']) {
@ -40,8 +43,6 @@ class CalendarQueryValidator {
return
$this->validateCompFilters($vObject, $filters['comp-filters']) &&
$this->validatePropFilters($vObject, $filters['prop-filters']);
}
/**
@ -52,23 +53,21 @@ class CalendarQueryValidator {
* itself.
*
* @param VObject\Component $parent
* @param array $filters
* @param array $filters
*
* @return bool
*/
protected function validateCompFilters(VObject\Component $parent, array $filters) {
protected function validateCompFilters(VObject\Component $parent, array $filters)
{
foreach ($filters as $filter) {
$isDefined = isset($parent->{$filter['name']});
if ($filter['is-not-defined']) {
if ($isDefined) {
return false;
} else {
continue;
}
}
if (!$isDefined) {
return false;
@ -80,6 +79,7 @@ class CalendarQueryValidator {
continue 2;
}
}
return false;
}
@ -90,27 +90,23 @@ class CalendarQueryValidator {
// If there are sub-filters, we need to find at least one component
// for which the subfilters hold true.
foreach ($parent->{$filter['name']} as $subComponent) {
if (
$this->validateCompFilters($subComponent, $filter['comp-filters']) &&
$this->validatePropFilters($subComponent, $filter['prop-filters'])) {
// We had a match, so this comp-filter succeeds
continue 2;
// We had a match, so this comp-filter succeeds
continue 2;
}
}
// If we got here it means there were sub-comp-filters or
// sub-prop-filters and there was no match. This means this filter
// needs to return false.
return false;
}
// If we got here it means we got through all comp-filters alive so the
// filters were all true.
return true;
}
/**
@ -121,23 +117,21 @@ class CalendarQueryValidator {
* itself.
*
* @param VObject\Component $parent
* @param array $filters
* @param array $filters
*
* @return bool
*/
protected function validatePropFilters(VObject\Component $parent, array $filters) {
protected function validatePropFilters(VObject\Component $parent, array $filters)
{
foreach ($filters as $filter) {
$isDefined = isset($parent->{$filter['name']});
if ($filter['is-not-defined']) {
if ($isDefined) {
return false;
} else {
continue;
}
}
if (!$isDefined) {
return false;
@ -149,6 +143,7 @@ class CalendarQueryValidator {
continue 2;
}
}
return false;
}
@ -159,7 +154,6 @@ class CalendarQueryValidator {
// If there are sub-filters, we need to find at least one property
// for which the subfilters hold true.
foreach ($parent->{$filter['name']} as $subComponent) {
if (
$this->validateParamFilters($subComponent, $filter['param-filters']) &&
(!$filter['text-match'] || $this->validateTextMatch($subComponent, $filter['text-match']))
@ -167,20 +161,17 @@ class CalendarQueryValidator {
// We had a match, so this prop-filter succeeds
continue 2;
}
}
// If we got here it means there were sub-param-filters or
// text-match filters and there was no match. This means the
// filter needs to return false.
return false;
}
// If we got here it means we got through all prop-filters alive so the
// filters were all true.
return true;
}
/**
@ -191,23 +182,21 @@ class CalendarQueryValidator {
* itself.
*
* @param VObject\Property $parent
* @param array $filters
* @param array $filters
*
* @return bool
*/
protected function validateParamFilters(VObject\Property $parent, array $filters) {
protected function validateParamFilters(VObject\Property $parent, array $filters)
{
foreach ($filters as $filter) {
$isDefined = isset($parent[$filter['name']]);
if ($filter['is-not-defined']) {
if ($isDefined) {
return false;
} else {
continue;
}
}
if (!$isDefined) {
return false;
@ -220,24 +209,20 @@ class CalendarQueryValidator {
// If there are sub-filters, we need to find at least one parameter
// for which the subfilters hold true.
foreach ($parent[$filter['name']]->getParts() as $paramPart) {
if ($this->validateTextMatch($paramPart, $filter['text-match'])) {
// We had a match, so this param-filter succeeds
continue 2;
}
}
// If we got here it means there was a text-match filter and there
// were no matches. This means the filter needs to return false.
return false;
}
// If we got here it means we got through all param-filters alive so the
// filters were all true.
return true;
}
/**
@ -246,20 +231,20 @@ class CalendarQueryValidator {
* A single text-match should be specified as well as the specific property
* or parameter we need to validate.
*
* @param VObject\Node|string $check Value to check against.
* @param array $textMatch
* @param VObject\Node|string $check value to check against
* @param array $textMatch
*
* @return bool
*/
protected function validateTextMatch($check, array $textMatch) {
protected function validateTextMatch($check, array $textMatch)
{
if ($check instanceof VObject\Node) {
$check = $check->getValue();
}
$isMatching = \Sabre\DAV\StringUtil::textMatch($check, $textMatch['value'], $textMatch['collation']);
return ($textMatch['negate-condition'] xor $isMatching);
return $textMatch['negate-condition'] xor $isMatching;
}
/**
@ -269,12 +254,13 @@ class CalendarQueryValidator {
* complex.
*
* @param VObject\Node $component
* @param DateTime $start
* @param DateTime $end
* @param DateTime $start
* @param DateTime $end
*
* @return bool
*/
protected function validateTimeRange(VObject\Node $component, $start, $end) {
protected function validateTimeRange(VObject\Node $component, $start, $end)
{
if (is_null($start)) {
$start = new DateTime('1900-01-01');
}
@ -283,14 +269,13 @@ class CalendarQueryValidator {
}
switch ($component->name) {
case 'VEVENT' :
case 'VTODO' :
case 'VJOURNAL' :
case 'VEVENT':
case 'VTODO':
case 'VJOURNAL':
return $component->isInTimeRange($start, $end);
case 'VALARM' :
case 'VALARM':
// If the valarm is wrapped in a recurring event, we need to
// expand the recursions, and validate each.
@ -298,10 +283,9 @@ class CalendarQueryValidator {
// Our datamodel doesn't easily allow us to do this straight
// in the VALARM component code, so this is a hack, and an
// expensive one too.
if ($component->parent->name === 'VEVENT' && $component->parent->RRULE) {
if ('VEVENT' === $component->parent->name && $component->parent->RRULE) {
// Fire up the iterator!
$it = new VObject\Recur\EventIterator($component->parent->parent, (string)$component->parent->UID);
$it = new VObject\Recur\EventIterator($component->parent->parent, (string) $component->parent->UID);
while ($it->valid()) {
$expandedEvent = $it->getEventObject();
@ -309,15 +293,14 @@ class CalendarQueryValidator {
// one is the first to trigger. Based on this, we can
// determine if we can 'give up' expanding events.
$firstAlarm = null;
if ($expandedEvent->VALARM !== null) {
if (null !== $expandedEvent->VALARM) {
foreach ($expandedEvent->VALARM as $expandedAlarm) {
$effectiveTrigger = $expandedAlarm->getEffectiveTriggerTime();
if ($expandedAlarm->isInTimeRange($start, $end)) {
return true;
}
if ((string)$expandedAlarm->TRIGGER['VALUE'] === 'DATE-TIME') {
if ('DATE-TIME' === (string) $expandedAlarm->TRIGGER['VALUE']) {
// This is an alarm with a non-relative trigger
// time, likely created by a buggy client. The
// implication is that every alarm in this
@ -346,30 +329,26 @@ class CalendarQueryValidator {
}
$it->next();
}
return false;
} else {
return $component->isInTimeRange($start, $end);
}
case 'VFREEBUSY' :
throw new \Sabre\DAV\Exception\NotImplemented('time-range filters are currently not supported on ' . $component->name . ' components');
case 'COMPLETED' :
case 'CREATED' :
case 'DTEND' :
case 'DTSTAMP' :
case 'DTSTART' :
case 'DUE' :
case 'LAST-MODIFIED' :
return ($start <= $component->getDateTime() && $end >= $component->getDateTime());
default :
throw new \Sabre\DAV\Exception\BadRequest('You cannot create a time-range filter on a ' . $component->name . ' component');
// no break
case 'VFREEBUSY':
throw new \Sabre\DAV\Exception\NotImplemented('time-range filters are currently not supported on '.$component->name.' components');
case 'COMPLETED':
case 'CREATED':
case 'DTEND':
case 'DTSTAMP':
case 'DTSTART':
case 'DUE':
case 'LAST-MODIFIED':
return $start <= $component->getDateTime() && $end >= $component->getDateTime();
default:
throw new \Sabre\DAV\Exception\BadRequest('You cannot create a time-range filter on a '.$component->name.' component');
}
}
}

View file

@ -1,11 +1,13 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV;
use Sabre\DAVACL\PrincipalBackend;
/**
* Calendars collection
* Calendars collection.
*
* This object is responsible for generating a list of calendar-homes for each
* user.
@ -17,17 +19,17 @@ use Sabre\DAVACL\PrincipalBackend;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class CalendarRoot extends \Sabre\DAVACL\AbstractPrincipalCollection {
class CalendarRoot extends \Sabre\DAVACL\AbstractPrincipalCollection
{
/**
* CalDAV backend
* CalDAV backend.
*
* @var Backend\BackendInterface
*/
protected $caldavBackend;
/**
* Constructor
* Constructor.
*
* This constructor needs both an authentication and a caldav backend.
*
@ -37,28 +39,26 @@ class CalendarRoot extends \Sabre\DAVACL\AbstractPrincipalCollection {
* to override this.
*
* @param PrincipalBackend\BackendInterface $principalBackend
* @param Backend\BackendInterface $caldavBackend
* @param string $principalPrefix
* @param Backend\BackendInterface $caldavBackend
* @param string $principalPrefix
*/
function __construct(PrincipalBackend\BackendInterface $principalBackend, Backend\BackendInterface $caldavBackend, $principalPrefix = 'principals') {
public function __construct(PrincipalBackend\BackendInterface $principalBackend, Backend\BackendInterface $caldavBackend, $principalPrefix = 'principals')
{
parent::__construct($principalBackend, $principalPrefix);
$this->caldavBackend = $caldavBackend;
}
/**
* Returns the nodename
* Returns the nodename.
*
* We're overriding this, because the default will be the 'principalPrefix',
* and we want it to be Sabre\CalDAV\Plugin::CALENDAR_ROOT
*
* @return string
*/
function getName() {
public function getName()
{
return Plugin::CALENDAR_ROOT;
}
/**
@ -69,12 +69,11 @@ class CalendarRoot extends \Sabre\DAVACL\AbstractPrincipalCollection {
* supplied by the authentication backend.
*
* @param array $principal
*
* @return \Sabre\DAV\INode
*/
function getChildForPrincipal(array $principal) {
public function getChildForPrincipal(array $principal)
{
return new CalendarHome($this->caldavBackend, $principal);
}
}

View file

@ -1,35 +1,34 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Exception;
use Sabre\CalDAV;
use Sabre\DAV;
/**
* InvalidComponentType
* InvalidComponentType.
*
* @copyright Copyright (C) fruux GmbH (https://fruux.com/)
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class InvalidComponentType extends DAV\Exception\Forbidden {
class InvalidComponentType extends DAV\Exception\Forbidden
{
/**
* Adds in extra information in the xml response.
*
* This method adds the {CALDAV:}supported-calendar-component as defined in rfc4791
*
* @param DAV\Server $server
* @param DAV\Server $server
* @param \DOMElement $errorNode
* @return void
*/
function serialize(DAV\Server $server, \DOMElement $errorNode) {
public function serialize(DAV\Server $server, \DOMElement $errorNode)
{
$doc = $errorNode->ownerDocument;
$np = $doc->createElementNS(CalDAV\Plugin::NS_CALDAV, 'cal:supported-calendar-component');
$errorNode->appendChild($np);
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV;
use DateTime;
@ -11,7 +13,7 @@ use Sabre\HTTP\ResponseInterface;
use Sabre\VObject;
/**
* ICS Exporter
* ICS Exporter.
*
* This plugin adds the ability to export entire calendars as .ics files.
* This is useful for clients that don't support CalDAV yet. They often do
@ -44,44 +46,49 @@ use Sabre\VObject;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class ICSExportPlugin extends DAV\ServerPlugin {
class ICSExportPlugin extends DAV\ServerPlugin
{
/**
* Reference to Server class
* Reference to Server class.
*
* @var \Sabre\DAV\Server
*/
protected $server;
/**
* Initializes the plugin and registers event handlers
* Initializes the plugin and registers event handlers.
*
* @param \Sabre\DAV\Server $server
* @return void
*/
function initialize(DAV\Server $server) {
public function initialize(DAV\Server $server)
{
$this->server = $server;
$server->on('method:GET', [$this, 'httpGet'], 90);
$server->on('browserButtonActions', function($path, $node, &$actions) {
$server->on('browserButtonActions', function ($path, $node, &$actions) {
if ($node instanceof ICalendar) {
$actions .= '<a href="' . htmlspecialchars($path, ENT_QUOTES, 'UTF-8') . '?export"><span class="oi" data-glyph="calendar"></span></a>';
$actions .= '<a href="'.htmlspecialchars($path, ENT_QUOTES, 'UTF-8').'?export"><span class="oi" data-glyph="calendar"></span></a>';
}
});
}
/**
* Intercepts GET requests on calendar urls ending with ?export.
*
* @param RequestInterface $request
* @param RequestInterface $request
* @param ResponseInterface $response
*
* @throws BadRequest
* @throws DAV\Exception\NotFound
* @throws VObject\InvalidDataException
*
* @return bool
*/
function httpGet(RequestInterface $request, ResponseInterface $response) {
public function httpGet(RequestInterface $request, ResponseInterface $response)
{
$queryParams = $request->getQueryParameters();
if (!array_key_exists('export', $queryParams)) return;
if (!array_key_exists('export', $queryParams)) {
return;
}
$path = $request->getPath();
@ -93,7 +100,7 @@ class ICSExportPlugin extends DAV\ServerPlugin {
'{http://apple.com/ns/ical/}calendar-color',
]);
if (!isset($node['{DAV:}resourcetype']) || !$node['{DAV:}resourcetype']->is('{' . Plugin::NS_CALDAV . '}calendar')) {
if (!isset($node['{DAV:}resourcetype']) || !$node['{DAV:}resourcetype']->is('{'.Plugin::NS_CALDAV.'}calendar')) {
return;
}
// Marking the transactionType, for logging purposes.
@ -117,7 +124,7 @@ class ICSExportPlugin extends DAV\ServerPlugin {
}
$end = DateTime::createFromFormat('U', $queryParams['end']);
}
if (isset($queryParams['expand']) && !!$queryParams['expand']) {
if (isset($queryParams['expand']) && (bool) $queryParams['expand']) {
if (!$start || !$end) {
throw new BadRequest('If you\'d like to expand recurrences, you must specify both a start= and end= parameter.');
}
@ -126,12 +133,12 @@ class ICSExportPlugin extends DAV\ServerPlugin {
}
if (isset($queryParams['componentType'])) {
if (!in_array($queryParams['componentType'], ['VEVENT', 'VTODO', 'VJOURNAL'])) {
throw new BadRequest('You are not allowed to search for components of type: ' . $queryParams['componentType'] . ' here');
throw new BadRequest('You are not allowed to search for components of type: '.$queryParams['componentType'].' here');
}
$componentType = $queryParams['componentType'];
}
$format = \Sabre\HTTP\Util::Negotiate(
$format = \Sabre\HTTP\negotiateContentType(
$request->getHeader('Accept'),
[
'text/calendar',
@ -140,7 +147,7 @@ class ICSExportPlugin extends DAV\ServerPlugin {
);
if (isset($queryParams['accept'])) {
if ($queryParams['accept'] === 'application/calendar+json' || $queryParams['accept'] === 'jcal') {
if ('application/calendar+json' === $queryParams['accept'] || 'jcal' === $queryParams['accept']) {
$format = 'application/calendar+json';
}
}
@ -152,61 +159,61 @@ class ICSExportPlugin extends DAV\ServerPlugin {
// Returning false to break the event chain
return false;
}
/**
* This method is responsible for generating the actual, full response.
*
* @param string $path
* @param DateTime|null $start
* @param DateTime|null $end
* @param bool $expand
* @param string $componentType
* @param string $format
* @param array $properties
* @param string $path
* @param DateTime|null $start
* @param DateTime|null $end
* @param bool $expand
* @param string $componentType
* @param string $format
* @param array $properties
* @param ResponseInterface $response
*
* @throws DAV\Exception\NotFound
* @throws VObject\InvalidDataException
*/
protected function generateResponse($path, $start, $end, $expand, $componentType, $format, $properties, ResponseInterface $response) {
$calDataProp = '{' . Plugin::NS_CALDAV . '}calendar-data';
protected function generateResponse($path, $start, $end, $expand, $componentType, $format, $properties, ResponseInterface $response)
{
$calDataProp = '{'.Plugin::NS_CALDAV.'}calendar-data';
$calendarNode = $this->server->tree->getNodeForPath($path);
$blobs = [];
if ($start || $end || $componentType) {
// If there was a start or end filter, we need to enlist
// calendarQuery for speed.
$queryResult = $calendarNode->calendarQuery([
'name' => 'VCALENDAR',
'name' => 'VCALENDAR',
'comp-filters' => [
[
'name' => $componentType,
'comp-filters' => [],
'prop-filters' => [],
'name' => $componentType,
'comp-filters' => [],
'prop-filters' => [],
'is-not-defined' => false,
'time-range' => [
'time-range' => [
'start' => $start,
'end' => $end,
'end' => $end,
],
],
],
'prop-filters' => [],
'prop-filters' => [],
'is-not-defined' => false,
'time-range' => null,
'time-range' => null,
]);
// queryResult is just a list of base urls. We need to prefix the
// calendar path.
$queryResult = array_map(
function($item) use ($path) {
return $path . '/' . $item;
function ($item) use ($path) {
return $path.'/'.$item;
},
$queryResult
);
$nodes = $this->server->getPropertiesForMultiplePaths($queryResult, [$calDataProp]);
unset($queryResult);
} else {
$nodes = $this->server->getPropertiesForPath($path, [$calDataProp], 1);
}
@ -228,7 +235,7 @@ class ICSExportPlugin extends DAV\ServerPlugin {
$calendarTimeZone = null;
// We're expanding, and for that we need to figure out the
// calendar's timezone.
$tzProp = '{' . Plugin::NS_CALDAV . '}calendar-timezone';
$tzProp = '{'.Plugin::NS_CALDAV.'}calendar-timezone';
$tzResult = $this->server->getProperties($path, [$tzProp]);
if (isset($tzResult[$tzProp])) {
// This property contains a VCALENDAR with a single
@ -249,11 +256,11 @@ class ICSExportPlugin extends DAV\ServerPlugin {
$filenameExtension = '.ics';
switch ($format) {
case 'text/calendar' :
case 'text/calendar':
$mergedCalendar = $mergedCalendar->serialize();
$filenameExtension = '.ics';
break;
case 'application/calendar+json' :
case 'application/calendar+json':
$mergedCalendar = json_encode($mergedCalendar->jsonSerialize());
$filenameExtension = '.json';
break;
@ -264,29 +271,29 @@ class ICSExportPlugin extends DAV\ServerPlugin {
'',
$calendarNode->getName()
);
$filename .= '-' . date('Y-m-d') . $filenameExtension;
$filename .= '-'.date('Y-m-d').$filenameExtension;
$response->setHeader('Content-Disposition', 'attachment; filename="' . $filename . '"');
$response->setHeader('Content-Disposition', 'attachment; filename="'.$filename.'"');
$response->setHeader('Content-Type', $format);
$response->setStatus(200);
$response->setBody($mergedCalendar);
}
/**
* Merges all calendar objects, and builds one big iCalendar blob.
*
* @param array $properties Some CalDAV properties
* @param array $properties Some CalDAV properties
* @param array $inputObjects
*
* @return VObject\Component\VCalendar
*/
function mergeObjects(array $properties, array $inputObjects) {
public function mergeObjects(array $properties, array $inputObjects)
{
$calendar = new VObject\Component\VCalendar();
$calendar->VERSION = '2.0';
if (DAV\Server::$exposeVersion) {
$calendar->PRODID = '-//SabreDAV//SabreDAV ' . DAV\Version::VERSION . '//EN';
$calendar->PRODID = '-//SabreDAV//SabreDAV '.DAV\Version::VERSION.'//EN';
} else {
$calendar->PRODID = '-//SabreDAV//SabreDAV//EN';
}
@ -303,41 +310,41 @@ class ICSExportPlugin extends DAV\ServerPlugin {
$objects = [];
foreach ($inputObjects as $href => $inputObject) {
$nodeComp = VObject\Reader::read($inputObject);
foreach ($nodeComp->children() as $child) {
switch ($child->name) {
case 'VEVENT' :
case 'VTODO' :
case 'VJOURNAL' :
case 'VEVENT':
case 'VTODO':
case 'VJOURNAL':
$objects[] = clone $child;
break;
// VTIMEZONE is special, because we need to filter out the duplicates
case 'VTIMEZONE' :
case 'VTIMEZONE':
// Naively just checking tzid.
if (in_array((string)$child->TZID, $collectedTimezones)) continue;
if (in_array((string) $child->TZID, $collectedTimezones)) {
break;
}
$timezones[] = clone $child;
$collectedTimezones[] = $child->TZID;
break;
}
}
// Destroy circular references to PHP will GC the object.
$nodeComp->destroy();
unset($nodeComp);
}
foreach ($timezones as $tz) $calendar->add($tz);
foreach ($objects as $obj) $calendar->add($obj);
foreach ($timezones as $tz) {
$calendar->add($tz);
}
foreach ($objects as $obj) {
$calendar->add($obj);
}
return $calendar;
}
/**
@ -348,10 +355,9 @@ class ICSExportPlugin extends DAV\ServerPlugin {
*
* @return string
*/
function getPluginName() {
public function getPluginName()
{
return 'ics-export';
}
/**
@ -365,14 +371,12 @@ class ICSExportPlugin extends DAV\ServerPlugin {
*
* @return array
*/
function getPluginInfo() {
public function getPluginInfo()
{
return [
'name' => $this->getPluginName(),
'name' => $this->getPluginName(),
'description' => 'Adds the ability to export CalDAV calendars as a single iCalendar file.',
'link' => 'http://sabre.io/dav/ics-export-plugin/',
'link' => 'http://sabre.io/dav/ics-export-plugin/',
];
}
}

View file

@ -1,11 +1,13 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV;
use Sabre\DAVACL;
/**
* Calendar interface
* Calendar interface.
*
* Implement this interface to allow a node to be recognized as an calendar.
*
@ -13,6 +15,6 @@ use Sabre\DAVACL;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
interface ICalendar extends ICalendarObjectContainer, DAVACL\IACL {
interface ICalendar extends ICalendarObjectContainer, DAVACL\IACL
{
}

View file

@ -1,11 +1,13 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV;
use Sabre\DAV;
/**
* CalendarObject interface
* CalendarObject interface.
*
* Extend the ICalendarObject interface to allow your custom nodes to be picked up as
* CalendarObjects.
@ -16,6 +18,6 @@ use Sabre\DAV;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
interface ICalendarObject extends DAV\IFile {
interface ICalendarObject extends DAV\IFile
{
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV;
/**
@ -15,8 +17,8 @@ namespace Sabre\CalDAV;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
interface ICalendarObjectContainer extends \Sabre\DAV\ICollection {
interface ICalendarObjectContainer extends \Sabre\DAV\ICollection
{
/**
* Performs a calendar-query on the contents of this calendar.
*
@ -32,8 +34,8 @@ interface ICalendarObjectContainer extends \Sabre\DAV\ICollection {
* documented by \Sabre\CalDAV\CalendarQueryParser.
*
* @param array $filters
*
* @return array
*/
function calendarQuery(array $filters);
public function calendarQuery(array $filters);
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV;
use Sabre\DAV\Sharing\ISharedNode;
@ -11,8 +13,8 @@ use Sabre\DAV\Sharing\ISharedNode;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
interface ISharedCalendar extends ISharedNode {
interface ISharedCalendar extends ISharedNode
{
/**
* Marks this calendar as published.
*
@ -20,7 +22,6 @@ interface ISharedCalendar extends ISharedNode {
* subscribable calendar.
*
* @param bool $value
* @return void
*/
function setPublishStatus($value);
public function setPublishStatus($value);
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Notifications;
use Sabre\CalDAV;
@ -20,49 +22,47 @@ use Sabre\DAVACL;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class Collection extends DAV\Collection implements ICollection, DAVACL\IACL {
class Collection extends DAV\Collection implements ICollection, DAVACL\IACL
{
use DAVACL\ACLTrait;
/**
* The notification backend
* The notification backend.
*
* @var CalDAV\Backend\NotificationSupport
*/
protected $caldavBackend;
/**
* Principal uri
* Principal uri.
*
* @var string
*/
protected $principalUri;
/**
* Constructor
* Constructor.
*
* @param CalDAV\Backend\NotificationSupport $caldavBackend
* @param string $principalUri
* @param string $principalUri
*/
function __construct(CalDAV\Backend\NotificationSupport $caldavBackend, $principalUri) {
public function __construct(CalDAV\Backend\NotificationSupport $caldavBackend, $principalUri)
{
$this->caldavBackend = $caldavBackend;
$this->principalUri = $principalUri;
}
/**
* Returns all notifications for a principal
* Returns all notifications for a principal.
*
* @return array
*/
function getChildren() {
public function getChildren()
{
$children = [];
$notifications = $this->caldavBackend->getNotificationsForPrincipal($this->principalUri);
foreach ($notifications as $notification) {
$children[] = new Node(
$this->caldavBackend,
$this->principalUri,
@ -71,31 +71,27 @@ class Collection extends DAV\Collection implements ICollection, DAVACL\IACL {
}
return $children;
}
/**
* Returns the name of this object
* Returns the name of this object.
*
* @return string
*/
function getName() {
public function getName()
{
return 'notifications';
}
/**
* Returns the owner principal
* Returns the owner principal.
*
* This must be a url to a principal, or null if there's no owner
*
* @return string|null
*/
function getOwner() {
public function getOwner()
{
return $this->principalUri;
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Notifications;
use Sabre\DAV;
@ -18,6 +20,6 @@ use Sabre\DAV;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
interface ICollection extends DAV\ICollection {
interface ICollection extends DAV\ICollection
{
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Notifications;
use Sabre\CalDAV\Xml\Notification\NotificationInterface;
@ -18,15 +20,15 @@ use Sabre\CalDAV\Xml\Notification\NotificationInterface;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
interface INode {
interface INode
{
/**
* This method must return an xml element, using the
* Sabre\CalDAV\Xml\Notification\NotificationInterface classes.
*
* @return NotificationInterface
*/
function getNotificationType();
public function getNotificationType();
/**
* Returns the etag for the notification.
@ -35,6 +37,5 @@ interface INode {
*
* @return string
*/
function getETag();
public function getETag();
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Notifications;
use Sabre\CalDAV;
@ -18,55 +20,53 @@ use Sabre\DAVACL;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class Node extends DAV\File implements INode, DAVACL\IACL {
class Node extends DAV\File implements INode, DAVACL\IACL
{
use DAVACL\ACLTrait;
/**
* The notification backend
* The notification backend.
*
* @var CalDAV\Backend\NotificationSupport
*/
protected $caldavBackend;
/**
* The actual notification
* The actual notification.
*
* @var NotificationInterface
*/
protected $notification;
/**
* Owner principal of the notification
* Owner principal of the notification.
*
* @var string
*/
protected $principalUri;
/**
* Constructor
* Constructor.
*
* @param CalDAV\Backend\NotificationSupport $caldavBackend
* @param string $principalUri
* @param NotificationInterface $notification
* @param string $principalUri
* @param NotificationInterface $notification
*/
function __construct(CalDAV\Backend\NotificationSupport $caldavBackend, $principalUri, NotificationInterface $notification) {
public function __construct(CalDAV\Backend\NotificationSupport $caldavBackend, $principalUri, NotificationInterface $notification)
{
$this->caldavBackend = $caldavBackend;
$this->principalUri = $principalUri;
$this->notification = $notification;
}
/**
* Returns the path name for this notification
* Returns the path name for this notification.
*
* @return string
*/
function getName() {
return $this->notification->getId() . '.xml';
public function getName()
{
return $this->notification->getId().'.xml';
}
/**
@ -76,10 +76,9 @@ class Node extends DAV\File implements INode, DAVACL\IACL {
*
* @return string
*/
function getETag() {
public function getETag()
{
return $this->notification->getETag();
}
/**
@ -88,34 +87,28 @@ class Node extends DAV\File implements INode, DAVACL\IACL {
*
* @return NotificationInterface
*/
function getNotificationType() {
public function getNotificationType()
{
return $this->notification;
}
/**
* Deletes this notification
*
* @return void
* Deletes this notification.
*/
function delete() {
public function delete()
{
$this->caldavBackend->deleteNotification($this->getOwner(), $this->notification);
}
/**
* Returns the owner principal
* Returns the owner principal.
*
* This must be a url to a principal, or null if there's no owner
*
* @return string|null
*/
function getOwner() {
public function getOwner()
{
return $this->principalUri;
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Notifications;
use Sabre\DAV;
@ -12,7 +14,7 @@ use Sabre\HTTP\RequestInterface;
use Sabre\HTTP\ResponseInterface;
/**
* Notifications plugin
* Notifications plugin.
*
* This plugin implements several features required by the caldav-notification
* draft specification.
@ -24,10 +26,10 @@ use Sabre\HTTP\ResponseInterface;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class Plugin extends ServerPlugin {
class Plugin extends ServerPlugin
{
/**
* This is the namespace for the proprietary calendarserver extensions
* This is the namespace for the proprietary calendarserver extensions.
*/
const NS_CALENDARSERVER = 'http://calendarserver.org/ns/';
@ -46,10 +48,9 @@ class Plugin extends ServerPlugin {
*
* @return string
*/
function getPluginName() {
public function getPluginName()
{
return 'notifications';
}
/**
@ -61,58 +62,49 @@ class Plugin extends ServerPlugin {
* This method should set up the required event subscriptions.
*
* @param Server $server
* @return void
*/
function initialize(Server $server) {
public function initialize(Server $server)
{
$this->server = $server;
$server->on('method:GET', [$this, 'httpGet'], 90);
$server->on('propFind', [$this, 'propFind']);
$server->on('propFind', [$this, 'propFind']);
$server->xml->namespaceMap[self::NS_CALENDARSERVER] = 'cs';
$server->resourceTypeMapping['\\Sabre\\CalDAV\\Notifications\\ICollection'] = '{' . self::NS_CALENDARSERVER . '}notification';
$server->resourceTypeMapping['\\Sabre\\CalDAV\\Notifications\\ICollection'] = '{'.self::NS_CALENDARSERVER.'}notification';
array_push($server->protectedProperties,
'{' . self::NS_CALENDARSERVER . '}notification-URL',
'{' . self::NS_CALENDARSERVER . '}notificationtype'
'{'.self::NS_CALENDARSERVER.'}notification-URL',
'{'.self::NS_CALENDARSERVER.'}notificationtype'
);
}
/**
* PropFind
* PropFind.
*
* @param PropFind $propFind
* @param PropFind $propFind
* @param BaseINode $node
* @return void
*/
function propFind(PropFind $propFind, BaseINode $node) {
public function propFind(PropFind $propFind, BaseINode $node)
{
$caldavPlugin = $this->server->getPlugin('caldav');
if ($node instanceof DAVACL\IPrincipal) {
$principalUrl = $node->getPrincipalUrl();
// notification-URL property
$propFind->handle('{' . self::NS_CALENDARSERVER . '}notification-URL', function() use ($principalUrl, $caldavPlugin) {
$propFind->handle('{'.self::NS_CALENDARSERVER.'}notification-URL', function () use ($principalUrl, $caldavPlugin) {
$notificationPath = $caldavPlugin->getCalendarHomeForPrincipal($principalUrl).'/notifications/';
$notificationPath = $caldavPlugin->getCalendarHomeForPrincipal($principalUrl) . '/notifications/';
return new DAV\Xml\Property\Href($notificationPath);
});
}
if ($node instanceof INode) {
$propFind->handle(
'{' . self::NS_CALENDARSERVER . '}notificationtype',
'{'.self::NS_CALENDARSERVER.'}notificationtype',
[$node, 'getNotificationType']
);
}
}
/**
@ -121,12 +113,11 @@ class Plugin extends ServerPlugin {
* We use this to intercept GET calls to notification nodes, and return the
* proper response.
*
* @param RequestInterface $request
* @param RequestInterface $request
* @param ResponseInterface $response
* @return void
*/
function httpGet(RequestInterface $request, ResponseInterface $response) {
public function httpGet(RequestInterface $request, ResponseInterface $response)
{
$path = $request->getPath();
try {
@ -135,8 +126,9 @@ class Plugin extends ServerPlugin {
return;
}
if (!$node instanceof INode)
if (!$node instanceof INode) {
return;
}
$writer = $this->server->xml->getWriter();
$writer->contextUri = $this->server->getBaseUri();
@ -153,7 +145,6 @@ class Plugin extends ServerPlugin {
// Return false to break the event chain.
return false;
}
/**
@ -167,14 +158,12 @@ class Plugin extends ServerPlugin {
*
* @return array
*/
function getPluginInfo() {
public function getPluginInfo()
{
return [
'name' => $this->getPluginName(),
'name' => $this->getPluginName(),
'description' => 'Adds support for caldav-notifications, which is required to enable caldav-sharing.',
'link' => 'http://sabre.io/dav/caldav-sharing/',
'link' => 'http://sabre.io/dav/caldav-sharing/',
];
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,11 +1,13 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Principal;
use Sabre\DAVACL;
/**
* Principal collection
* Principal collection.
*
* This is an alternative collection to the standard ACL principal collection.
* This collection adds support for the calendar-proxy-read and
@ -16,18 +18,17 @@ use Sabre\DAVACL;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class Collection extends DAVACL\PrincipalCollection {
class Collection extends DAVACL\PrincipalCollection
{
/**
* Returns a child object based on principal information
* Returns a child object based on principal information.
*
* @param array $principalInfo
*
* @return User
*/
function getChildForPrincipal(array $principalInfo) {
public function getChildForPrincipal(array $principalInfo)
{
return new User($this->principalBackend, $principalInfo);
}
}

View file

@ -1,11 +1,13 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Principal;
use Sabre\DAVACL;
/**
* ProxyRead principal interface
* ProxyRead principal interface.
*
* Any principal node implementing this interface will be picked up as a 'proxy
* principal group'.
@ -14,6 +16,6 @@ use Sabre\DAVACL;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
interface IProxyRead extends DAVACL\IPrincipal {
interface IProxyRead extends DAVACL\IPrincipal
{
}

View file

@ -1,11 +1,13 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Principal;
use Sabre\DAVACL;
/**
* ProxyWrite principal interface
* ProxyWrite principal interface.
*
* Any principal node implementing this interface will be picked up as a 'proxy
* principal group'.
@ -14,6 +16,6 @@ use Sabre\DAVACL;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
interface IProxyWrite extends DAVACL\IPrincipal {
interface IProxyWrite extends DAVACL\IPrincipal
{
}

View file

@ -1,12 +1,14 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Principal;
use Sabre\DAV;
use Sabre\DAVACL;
/**
* ProxyRead principal
* ProxyRead principal.
*
* This class represents a principal group, hosted under the main principal.
* This is needed to implement 'Calendar delegation' support. This class is
@ -16,8 +18,8 @@ use Sabre\DAVACL;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class ProxyRead implements IProxyRead {
class ProxyRead implements IProxyRead
{
/**
* Principal information from the parent principal.
*
@ -26,7 +28,7 @@ class ProxyRead implements IProxyRead {
protected $principalInfo;
/**
* Principal backend
* Principal backend.
*
* @var DAVACL\PrincipalBackend\BackendInterface
*/
@ -38,13 +40,12 @@ class ProxyRead implements IProxyRead {
* Note that you MUST supply the parent principal information.
*
* @param DAVACL\PrincipalBackend\BackendInterface $principalBackend
* @param array $principalInfo
* @param array $principalInfo
*/
function __construct(DAVACL\PrincipalBackend\BackendInterface $principalBackend, array $principalInfo) {
public function __construct(DAVACL\PrincipalBackend\BackendInterface $principalBackend, array $principalInfo)
{
$this->principalInfo = $principalInfo;
$this->principalBackend = $principalBackend;
}
/**
@ -52,103 +53,91 @@ class ProxyRead implements IProxyRead {
*
* @return string
*/
function getName() {
public function getName()
{
return 'calendar-proxy-read';
}
/**
* Returns the last modification time
*
* @return null
* Returns the last modification time.
*/
function getLastModified() {
public function getLastModified()
{
return null;
}
/**
* Deletes the current node
* Deletes the current node.
*
* @throws DAV\Exception\Forbidden
* @return void
*/
function delete() {
public function delete()
{
throw new DAV\Exception\Forbidden('Permission denied to delete node');
}
/**
* Renames the node
* Renames the node.
*
* @param string $name The new name
*
* @throws DAV\Exception\Forbidden
* @return void
*/
function setName($name) {
public function setName($name)
{
throw new DAV\Exception\Forbidden('Permission denied to rename file');
}
/**
* Returns a list of alternative urls for a principal
* Returns a list of alternative urls for a principal.
*
* This can for example be an email address, or ldap url.
*
* @return array
*/
function getAlternateUriSet() {
public function getAlternateUriSet()
{
return [];
}
/**
* Returns the full principal url
* Returns the full principal url.
*
* @return string
*/
function getPrincipalUrl() {
return $this->principalInfo['uri'] . '/' . $this->getName();
public function getPrincipalUrl()
{
return $this->principalInfo['uri'].'/'.$this->getName();
}
/**
* Returns the list of group members
* Returns the list of group members.
*
* If this principal is a group, this function should return
* all member principal uri's for the group.
*
* @return array
*/
function getGroupMemberSet() {
public function getGroupMemberSet()
{
return $this->principalBackend->getGroupMemberSet($this->getPrincipalUrl());
}
/**
* Returns the list of groups this principal is member of
* Returns the list of groups this principal is member of.
*
* If this principal is a member of a (list of) groups, this function
* should return a list of principal uri's for it's members.
*
* @return array
*/
function getGroupMembership() {
public function getGroupMembership()
{
return $this->principalBackend->getGroupMembership($this->getPrincipalUrl());
}
/**
* Sets a list of group members
* Sets a list of group members.
*
* If this principal is a group, this method sets all the group members.
* The list of members is always overwritten, never appended to.
@ -156,26 +145,22 @@ class ProxyRead implements IProxyRead {
* This method should throw an exception if the members could not be set.
*
* @param array $principals
* @return void
*/
function setGroupMemberSet(array $principals) {
public function setGroupMemberSet(array $principals)
{
$this->principalBackend->setGroupMemberSet($this->getPrincipalUrl(), $principals);
}
/**
* Returns the displayname
* Returns the displayname.
*
* This should be a human readable name for the principal.
* If none is available, return the nodename.
*
* @return string
*/
function getDisplayName() {
public function getDisplayName()
{
return $this->getName();
}
}

View file

@ -1,12 +1,14 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Principal;
use Sabre\DAV;
use Sabre\DAVACL;
/**
* ProxyWrite principal
* ProxyWrite principal.
*
* This class represents a principal group, hosted under the main principal.
* This is needed to implement 'Calendar delegation' support. This class is
@ -16,35 +18,34 @@ use Sabre\DAVACL;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class ProxyWrite implements IProxyWrite {
class ProxyWrite implements IProxyWrite
{
/**
* Parent principal information
* Parent principal information.
*
* @var array
*/
protected $principalInfo;
/**
* Principal Backend
* Principal Backend.
*
* @var DAVACL\PrincipalBackend\BackendInterface
*/
protected $principalBackend;
/**
* Creates the object
* Creates the object.
*
* Note that you MUST supply the parent principal information.
*
* @param DAVACL\PrincipalBackend\BackendInterface $principalBackend
* @param array $principalInfo
* @param array $principalInfo
*/
function __construct(DAVACL\PrincipalBackend\BackendInterface $principalBackend, array $principalInfo) {
public function __construct(DAVACL\PrincipalBackend\BackendInterface $principalBackend, array $principalInfo)
{
$this->principalInfo = $principalInfo;
$this->principalBackend = $principalBackend;
}
/**
@ -52,103 +53,91 @@ class ProxyWrite implements IProxyWrite {
*
* @return string
*/
function getName() {
public function getName()
{
return 'calendar-proxy-write';
}
/**
* Returns the last modification time
*
* @return null
* Returns the last modification time.
*/
function getLastModified() {
public function getLastModified()
{
return null;
}
/**
* Deletes the current node
* Deletes the current node.
*
* @throws DAV\Exception\Forbidden
* @return void
*/
function delete() {
public function delete()
{
throw new DAV\Exception\Forbidden('Permission denied to delete node');
}
/**
* Renames the node
* Renames the node.
*
* @param string $name The new name
*
* @throws DAV\Exception\Forbidden
* @return void
*/
function setName($name) {
public function setName($name)
{
throw new DAV\Exception\Forbidden('Permission denied to rename file');
}
/**
* Returns a list of alternative urls for a principal
* Returns a list of alternative urls for a principal.
*
* This can for example be an email address, or ldap url.
*
* @return array
*/
function getAlternateUriSet() {
public function getAlternateUriSet()
{
return [];
}
/**
* Returns the full principal url
* Returns the full principal url.
*
* @return string
*/
function getPrincipalUrl() {
return $this->principalInfo['uri'] . '/' . $this->getName();
public function getPrincipalUrl()
{
return $this->principalInfo['uri'].'/'.$this->getName();
}
/**
* Returns the list of group members
* Returns the list of group members.
*
* If this principal is a group, this function should return
* all member principal uri's for the group.
*
* @return array
*/
function getGroupMemberSet() {
public function getGroupMemberSet()
{
return $this->principalBackend->getGroupMemberSet($this->getPrincipalUrl());
}
/**
* Returns the list of groups this principal is member of
* Returns the list of groups this principal is member of.
*
* If this principal is a member of a (list of) groups, this function
* should return a list of principal uri's for it's members.
*
* @return array
*/
function getGroupMembership() {
public function getGroupMembership()
{
return $this->principalBackend->getGroupMembership($this->getPrincipalUrl());
}
/**
* Sets a list of group members
* Sets a list of group members.
*
* If this principal is a group, this method sets all the group members.
* The list of members is always overwritten, never appended to.
@ -156,26 +145,22 @@ class ProxyWrite implements IProxyWrite {
* This method should throw an exception if the members could not be set.
*
* @param array $principals
* @return void
*/
function setGroupMemberSet(array $principals) {
public function setGroupMemberSet(array $principals)
{
$this->principalBackend->setGroupMemberSet($this->getPrincipalUrl(), $principals);
}
/**
* Returns the displayname
* Returns the displayname.
*
* This should be a human readable name for the principal.
* If none is available, return the nodename.
*
* @return string
*/
function getDisplayName() {
public function getDisplayName()
{
return $this->getName();
}
}

View file

@ -1,12 +1,14 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Principal;
use Sabre\DAV;
use Sabre\DAVACL;
/**
* CalDAV principal
* CalDAV principal.
*
* This is a standard user-principal for CalDAV. This principal is also a
* collection and returns the caldav-proxy-read and caldav-proxy-write child
@ -16,91 +18,91 @@ use Sabre\DAVACL;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class User extends DAVACL\Principal implements DAV\ICollection {
class User extends DAVACL\Principal implements DAV\ICollection
{
/**
* Creates a new file in the directory
* Creates a new file in the directory.
*
* @param string $name Name of the file
* @param resource $data initial payload, passed as a readable stream resource
*
* @param string $name Name of the file
* @param resource $data Initial payload, passed as a readable stream resource.
* @throws DAV\Exception\Forbidden
* @return void
*/
function createFile($name, $data = null) {
throw new DAV\Exception\Forbidden('Permission denied to create file (filename ' . $name . ')');
public function createFile($name, $data = null)
{
throw new DAV\Exception\Forbidden('Permission denied to create file (filename '.$name.')');
}
/**
* Creates a new subdirectory
* Creates a new subdirectory.
*
* @param string $name
*
* @throws DAV\Exception\Forbidden
* @return void
*/
function createDirectory($name) {
public function createDirectory($name)
{
throw new DAV\Exception\Forbidden('Permission denied to create directory');
}
/**
* Returns a specific child node, referenced by its name
* Returns a specific child node, referenced by its name.
*
* @param string $name
*
* @return DAV\INode
*/
function getChild($name) {
$principal = $this->principalBackend->getPrincipalByPath($this->getPrincipalURL() . '/' . $name);
public function getChild($name)
{
$principal = $this->principalBackend->getPrincipalByPath($this->getPrincipalURL().'/'.$name);
if (!$principal) {
throw new DAV\Exception\NotFound('Node with name ' . $name . ' was not found');
throw new DAV\Exception\NotFound('Node with name '.$name.' was not found');
}
if ($name === 'calendar-proxy-read')
if ('calendar-proxy-read' === $name) {
return new ProxyRead($this->principalBackend, $this->principalProperties);
}
if ($name === 'calendar-proxy-write')
if ('calendar-proxy-write' === $name) {
return new ProxyWrite($this->principalBackend, $this->principalProperties);
}
throw new DAV\Exception\NotFound('Node with name ' . $name . ' was not found');
throw new DAV\Exception\NotFound('Node with name '.$name.' was not found');
}
/**
* Returns an array with all the child nodes
* Returns an array with all the child nodes.
*
* @return DAV\INode[]
*/
function getChildren() {
public function getChildren()
{
$r = [];
if ($this->principalBackend->getPrincipalByPath($this->getPrincipalURL() . '/calendar-proxy-read')) {
if ($this->principalBackend->getPrincipalByPath($this->getPrincipalURL().'/calendar-proxy-read')) {
$r[] = new ProxyRead($this->principalBackend, $this->principalProperties);
}
if ($this->principalBackend->getPrincipalByPath($this->getPrincipalURL() . '/calendar-proxy-write')) {
if ($this->principalBackend->getPrincipalByPath($this->getPrincipalURL().'/calendar-proxy-write')) {
$r[] = new ProxyWrite($this->principalBackend, $this->principalProperties);
}
return $r;
}
/**
* Returns whether or not the child node exists
* Returns whether or not the child node exists.
*
* @param string $name
*
* @return bool
*/
function childExists($name) {
public function childExists($name)
{
try {
$this->getChild($name);
return true;
} catch (DAV\Exception\NotFound $e) {
return false;
}
}
/**
@ -115,21 +117,20 @@ class User extends DAVACL\Principal implements DAV\ICollection {
*
* @return array
*/
function getACL() {
public function getACL()
{
$acl = parent::getACL();
$acl[] = [
'privilege' => '{DAV:}read',
'principal' => $this->principalProperties['uri'] . '/calendar-proxy-read',
'principal' => $this->principalProperties['uri'].'/calendar-proxy-read',
'protected' => true,
];
$acl[] = [
'privilege' => '{DAV:}read',
'principal' => $this->principalProperties['uri'] . '/calendar-proxy-write',
'principal' => $this->principalProperties['uri'].'/calendar-proxy-write',
'protected' => true,
];
return $acl;
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Schedule;
/**
@ -10,6 +12,6 @@ namespace Sabre\CalDAV\Schedule;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
interface IInbox extends \Sabre\CalDAV\ICalendarObjectContainer, \Sabre\DAVACL\IACL {
interface IInbox extends \Sabre\CalDAV\ICalendarObjectContainer, \Sabre\DAVACL\IACL
{
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Schedule;
use Sabre\DAV;
@ -19,8 +21,8 @@ use Sabre\VObject\ITip;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class IMipPlugin extends DAV\ServerPlugin {
class IMipPlugin extends DAV\ServerPlugin
{
/**
* Email address used in From: header.
*
@ -29,7 +31,7 @@ class IMipPlugin extends DAV\ServerPlugin {
protected $senderEmail;
/**
* ITipMessage
* ITipMessage.
*
* @var ITip\Message
*/
@ -43,10 +45,9 @@ class IMipPlugin extends DAV\ServerPlugin {
* generally be some kind of no-reply email
* address you own.
*/
function __construct($senderEmail) {
public function __construct($senderEmail)
{
$this->senderEmail = $senderEmail;
}
/*
@ -60,10 +61,9 @@ class IMipPlugin extends DAV\ServerPlugin {
* @param DAV\Server $server
* @return void
*/
function initialize(DAV\Server $server) {
public function initialize(DAV\Server $server)
{
$server->on('schedule', [$this, 'schedule'], 120);
}
/**
@ -74,67 +74,68 @@ class IMipPlugin extends DAV\ServerPlugin {
*
* @return string
*/
function getPluginName() {
public function getPluginName()
{
return 'imip';
}
/**
* Event handler for the 'schedule' event.
*
* @param ITip\Message $iTipMessage
* @return void
*/
function schedule(ITip\Message $iTipMessage) {
public function schedule(ITip\Message $iTipMessage)
{
// Not sending any emails if the system considers the update
// insignificant.
if (!$iTipMessage->significantChange) {
if (!$iTipMessage->scheduleStatus) {
$iTipMessage->scheduleStatus = '1.0;We got the message, but it\'s not significant enough to warrant an email';
}
return;
}
$summary = $iTipMessage->message->VEVENT->SUMMARY;
if (parse_url($iTipMessage->sender, PHP_URL_SCHEME) !== 'mailto')
if ('mailto' !== parse_url($iTipMessage->sender, PHP_URL_SCHEME)) {
return;
}
if (parse_url($iTipMessage->recipient, PHP_URL_SCHEME) !== 'mailto')
if ('mailto' !== parse_url($iTipMessage->recipient, PHP_URL_SCHEME)) {
return;
}
$sender = substr($iTipMessage->sender, 7);
$recipient = substr($iTipMessage->recipient, 7);
if ($iTipMessage->senderName) {
$sender = $iTipMessage->senderName . ' <' . $sender . '>';
$sender = $iTipMessage->senderName.' <'.$sender.'>';
}
if ($iTipMessage->recipientName) {
$recipient = $iTipMessage->recipientName . ' <' . $recipient . '>';
if ($iTipMessage->recipientName && $iTipMessage->recipientName != $recipient) {
$recipient = $iTipMessage->recipientName.' <'.$recipient.'>';
}
$subject = 'SabreDAV iTIP message';
switch (strtoupper($iTipMessage->method)) {
case 'REPLY' :
$subject = 'Re: ' . $summary;
case 'REPLY':
$subject = 'Re: '.$summary;
break;
case 'REQUEST' :
$subject = $summary;
case 'REQUEST':
$subject = 'Invitation: '.$summary;
break;
case 'CANCEL' :
$subject = 'Cancelled: ' . $summary;
case 'CANCEL':
$subject = 'Cancelled: '.$summary;
break;
}
$headers = [
'Reply-To: ' . $sender,
'From: ' . $this->senderEmail,
'Content-Type: text/calendar; charset=UTF-8; method=' . $iTipMessage->method,
'Reply-To: '.$sender,
'From: '.$iTipMessage->senderName.' <'.$this->senderEmail.'>',
'Content-Type: text/calendar; charset=UTF-8; method='.$iTipMessage->method,
];
if (DAV\Server::$exposeVersion) {
$headers[] = 'X-Sabre-Version: ' . DAV\Version::VERSION;
$headers[] = 'X-Sabre-Version: '.DAV\Version::VERSION;
}
$this->mail(
$recipient,
@ -143,7 +144,6 @@ class IMipPlugin extends DAV\ServerPlugin {
$headers
);
$iTipMessage->scheduleStatus = '1.1; Scheduling message is sent via iMip';
}
// @codeCoverageIgnoreStart
@ -152,16 +152,14 @@ class IMipPlugin extends DAV\ServerPlugin {
/**
* This function is responsible for sending the actual email.
*
* @param string $to Recipient email address
* @param string $to Recipient email address
* @param string $subject Subject of the email
* @param string $body iCalendar body
* @param array $headers List of headers
* @return void
* @param string $body iCalendar body
* @param array $headers List of headers
*/
protected function mail($to, $subject, $body, array $headers) {
protected function mail($to, $subject, $body, array $headers)
{
mail($to, $subject, $body, implode("\r\n", $headers));
}
// @codeCoverageIgnoreEnd
@ -177,14 +175,12 @@ class IMipPlugin extends DAV\ServerPlugin {
*
* @return array
*/
function getPluginInfo() {
public function getPluginInfo()
{
return [
'name' => $this->getPluginName(),
'name' => $this->getPluginName(),
'description' => 'Email delivery (rfc6047) for CalDAV scheduling',
'link' => 'http://sabre.io/dav/scheduling/',
'link' => 'http://sabre.io/dav/scheduling/',
];
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Schedule;
/**
@ -10,6 +12,6 @@ namespace Sabre\CalDAV\Schedule;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
interface IOutbox extends \Sabre\DAV\ICollection, \Sabre\DAVACL\IACL {
interface IOutbox extends \Sabre\DAV\ICollection, \Sabre\DAVACL\IACL
{
}

View file

@ -1,13 +1,15 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Schedule;
/**
* The SchedulingObject represents a scheduling object in the Inbox collection
* The SchedulingObject represents a scheduling object in the Inbox collection.
*
* @license http://sabre.io/license/ Modified BSD License
* @copyright Copyright (C) fruux GmbH (https://fruux.com/)
*/
interface ISchedulingObject extends \Sabre\CalDAV\ICalendarObject {
interface ISchedulingObject extends \Sabre\CalDAV\ICalendarObject
{
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Schedule;
use Sabre\CalDAV;
@ -9,41 +11,40 @@ use Sabre\DAVACL;
use Sabre\VObject;
/**
* The CalDAV scheduling inbox
* The CalDAV scheduling inbox.
*
* @copyright Copyright (C) fruux GmbH (https://fruux.com/)
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class Inbox extends DAV\Collection implements IInbox {
class Inbox extends DAV\Collection implements IInbox
{
use DAVACL\ACLTrait;
/**
* CalDAV backend
* CalDAV backend.
*
* @var Backend\BackendInterface
*/
protected $caldavBackend;
/**
* The principal Uri
* The principal Uri.
*
* @var string
*/
protected $principalUri;
/**
* Constructor
* Constructor.
*
* @param Backend\SchedulingSupport $caldavBackend
* @param string $principalUri
* @param string $principalUri
*/
function __construct(Backend\SchedulingSupport $caldavBackend, $principalUri) {
public function __construct(Backend\SchedulingSupport $caldavBackend, $principalUri)
{
$this->caldavBackend = $caldavBackend;
$this->principalUri = $principalUri;
}
/**
@ -53,19 +54,18 @@ class Inbox extends DAV\Collection implements IInbox {
*
* @return string
*/
function getName() {
public function getName()
{
return 'inbox';
}
/**
* Returns an array with all the child nodes
* Returns an array with all the child nodes.
*
* @return \Sabre\DAV\INode[]
*/
function getChildren() {
public function getChildren()
{
$objs = $this->caldavBackend->getSchedulingObjects($this->principalUri);
$children = [];
foreach ($objs as $obj) {
@ -73,12 +73,12 @@ class Inbox extends DAV\Collection implements IInbox {
$obj['principaluri'] = $this->principalUri;
$children[] = new SchedulingObject($this->caldavBackend, $obj);
}
return $children;
return $children;
}
/**
* Creates a new file in the directory
* Creates a new file in the directory.
*
* Data will either be supplied as a stream resource, or in certain cases
* as a string. Keep in mind that you may have to support either.
@ -97,27 +97,26 @@ class Inbox extends DAV\Collection implements IInbox {
* return the same contents of what was submitted here, you are strongly
* recommended to omit the ETag.
*
* @param string $name Name of the file
* @param string $name Name of the file
* @param resource|string $data Initial payload
* @return null|string
*
* @return string|null
*/
function createFile($name, $data = null) {
public function createFile($name, $data = null)
{
$this->caldavBackend->createSchedulingObject($this->principalUri, $name, $data);
}
/**
* Returns the owner principal
* Returns the owner principal.
*
* This must be a url to a principal, or null if there's no owner
*
* @return string|null
*/
function getOwner() {
public function getOwner()
{
return $this->principalUri;
}
/**
@ -132,8 +131,8 @@ class Inbox extends DAV\Collection implements IInbox {
*
* @return array
*/
function getACL() {
public function getACL()
{
return [
[
'privilege' => '{DAV:}read',
@ -152,16 +151,15 @@ class Inbox extends DAV\Collection implements IInbox {
],
[
'privilege' => '{DAV:}unbind',
'principal' => $this->getOwner() . '/calendar-proxy-write',
'principal' => $this->getOwner().'/calendar-proxy-write',
'protected' => true,
],
[
'privilege' => '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-deliver',
'privilege' => '{'.CalDAV\Plugin::NS_CALDAV.'}schedule-deliver',
'principal' => '{DAV:}authenticated',
'protected' => true,
],
];
}
/**
@ -179,10 +177,11 @@ class Inbox extends DAV\Collection implements IInbox {
* documented by \Sabre\CalDAV\CalendarQueryParser.
*
* @param array $filters
*
* @return array
*/
function calendarQuery(array $filters) {
public function calendarQuery(array $filters)
{
$result = [];
$validator = new CalDAV\CalendarQueryValidator();
@ -196,8 +195,7 @@ class Inbox extends DAV\Collection implements IInbox {
// Destroy circular references to PHP will GC the object.
$vObject->destroy();
}
return $result;
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Schedule;
use Sabre\CalDAV;
@ -7,7 +9,7 @@ use Sabre\DAV;
use Sabre\DAVACL;
/**
* The CalDAV scheduling outbox
* The CalDAV scheduling outbox.
*
* The outbox is mainly used as an endpoint in the tree for a client to do
* free-busy requests. This functionality is completely handled by the
@ -17,26 +19,25 @@ use Sabre\DAVACL;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class Outbox extends DAV\Collection implements IOutbox {
class Outbox extends DAV\Collection implements IOutbox
{
use DAVACL\ACLTrait;
/**
* The principal Uri
* The principal Uri.
*
* @var string
*/
protected $principalUri;
/**
* Constructor
* Constructor.
*
* @param string $principalUri
*/
function __construct($principalUri) {
public function __construct($principalUri)
{
$this->principalUri = $principalUri;
}
/**
@ -46,34 +47,31 @@ class Outbox extends DAV\Collection implements IOutbox {
*
* @return string
*/
function getName() {
public function getName()
{
return 'outbox';
}
/**
* Returns an array with all the child nodes
* Returns an array with all the child nodes.
*
* @return \Sabre\DAV\INode[]
*/
function getChildren() {
public function getChildren()
{
return [];
}
/**
* Returns the owner principal
* Returns the owner principal.
*
* This must be a url to a principal, or null if there's no owner
*
* @return string|null
*/
function getOwner() {
public function getOwner()
{
return $this->principalUri;
}
/**
@ -88,11 +86,11 @@ class Outbox extends DAV\Collection implements IOutbox {
*
* @return array
*/
function getACL() {
public function getACL()
{
return [
[
'privilege' => '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-send',
'privilege' => '{'.CalDAV\Plugin::NS_CALDAV.'}schedule-send',
'principal' => $this->getOwner(),
'protected' => true,
],
@ -102,22 +100,20 @@ class Outbox extends DAV\Collection implements IOutbox {
'protected' => true,
],
[
'privilege' => '{' . CalDAV\Plugin::NS_CALDAV . '}schedule-send',
'principal' => $this->getOwner() . '/calendar-proxy-write',
'privilege' => '{'.CalDAV\Plugin::NS_CALDAV.'}schedule-send',
'principal' => $this->getOwner().'/calendar-proxy-write',
'protected' => true,
],
[
'privilege' => '{DAV:}read',
'principal' => $this->getOwner() . '/calendar-proxy-read',
'principal' => $this->getOwner().'/calendar-proxy-read',
'protected' => true,
],
[
'privilege' => '{DAV:}read',
'principal' => $this->getOwner() . '/calendar-proxy-write',
'principal' => $this->getOwner().'/calendar-proxy-write',
'protected' => true,
],
];
}
}

View file

@ -1,35 +1,23 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Schedule;
use Sabre\CalDAV\Backend;
use Sabre\DAV\Exception\MethodNotAllowed;
/**
* The SchedulingObject represents a scheduling object in the Inbox collection
* The SchedulingObject represents a scheduling object in the Inbox collection.
*
* @author Brett (https://github.com/bretten)
* @license http://sabre.io/license/ Modified BSD License
* @copyright Copyright (C) fruux GmbH (https://fruux.com/)
*/
class SchedulingObject extends \Sabre\CalDAV\CalendarObject implements ISchedulingObject {
class SchedulingObject extends \Sabre\CalDAV\CalendarObject implements ISchedulingObject
{
/**
/* The CalDAV backend
*
* @var Backend\SchedulingSupport
*/
protected $caldavBackend;
/**
* Array with information about this SchedulingObject
*
* @var array
*/
protected $objectData;
/**
* Constructor
* Constructor.
*
* The following properties may be passed within $objectData:
*
@ -43,73 +31,65 @@ class SchedulingObject extends \Sabre\CalDAV\CalendarObject implements IScheduli
* * acl - (optional) Use this to override the default ACL for the node.
*
* @param Backend\SchedulingSupport $caldavBackend
* @param array $objectData
* @param array $objectData
*/
function __construct(Backend\SchedulingSupport $caldavBackend, array $objectData) {
$this->caldavBackend = $caldavBackend;
public function __construct(Backend\SchedulingSupport $caldavBackend, array $objectData)
{
parent::__construct($caldavBackend, [], $objectData);
if (!isset($objectData['uri'])) {
throw new \InvalidArgumentException('The objectData argument must contain an \'uri\' property');
}
$this->objectData = $objectData;
}
/**
* Returns the ICalendar-formatted object
* Returns the ICalendar-formatted object.
*
* @return string
*/
function get() {
public function get()
{
// Pre-populating the 'calendardata' is optional, if we don't have it
// already we fetch it from the backend.
if (!isset($this->objectData['calendardata'])) {
$this->objectData = $this->caldavBackend->getSchedulingObject($this->objectData['principaluri'], $this->objectData['uri']);
}
return $this->objectData['calendardata'];
return $this->objectData['calendardata'];
}
/**
* Updates the ICalendar-formatted object
* Updates the ICalendar-formatted object.
*
* @param string|resource $calendarData
*
* @return string
*/
function put($calendarData) {
public function put($calendarData)
{
throw new MethodNotAllowed('Updating scheduling objects is not supported');
}
/**
* Deletes the scheduling message
*
* @return void
* Deletes the scheduling message.
*/
function delete() {
public function delete()
{
$this->caldavBackend->deleteSchedulingObject($this->objectData['principaluri'], $this->objectData['uri']);
}
/**
* Returns the owner principal
* Returns the owner principal.
*
* This must be a url to a principal, or null if there's no owner
*
* @return string|null
*/
function getOwner() {
public function getOwner()
{
return $this->objectData['principaluri'];
}
/**
* Returns a list of ACE's for this node.
*
@ -122,8 +102,8 @@ class SchedulingObject extends \Sabre\CalDAV\CalendarObject implements IScheduli
*
* @return array
*/
function getACL() {
public function getACL()
{
// An alternative acl may be specified in the object data.
//
@ -140,16 +120,14 @@ class SchedulingObject extends \Sabre\CalDAV\CalendarObject implements IScheduli
],
[
'privilege' => '{DAV:}all',
'principal' => $this->objectData['principaluri'] . '/calendar-proxy-write',
'principal' => $this->objectData['principaluri'].'/calendar-proxy-write',
'protected' => true,
],
[
'privilege' => '{DAV:}read',
'principal' => $this->objectData['principaluri'] . '/calendar-proxy-read',
'principal' => $this->objectData['principaluri'].'/calendar-proxy-read',
'protected' => true,
],
];
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV;
use Sabre\DAV\Sharing\Plugin as SPlugin;
@ -11,8 +13,8 @@ use Sabre\DAV\Sharing\Plugin as SPlugin;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class SharedCalendar extends Calendar implements ISharedCalendar {
class SharedCalendar extends Calendar implements ISharedCalendar
{
/**
* Returns the 'access level' for the instance of this shared resource.
*
@ -21,10 +23,9 @@ class SharedCalendar extends Calendar implements ISharedCalendar {
*
* @return int
*/
function getShareAccess() {
public function getShareAccess()
{
return isset($this->calendarInfo['share-access']) ? $this->calendarInfo['share-access'] : SPlugin::ACCESS_NOTSHARED;
}
/**
@ -38,10 +39,9 @@ class SharedCalendar extends Calendar implements ISharedCalendar {
*
* @return string
*/
function getShareResourceUri() {
public function getShareResourceUri()
{
return $this->calendarInfo['share-resource-uri'];
}
/**
@ -50,12 +50,10 @@ class SharedCalendar extends Calendar implements ISharedCalendar {
* Every item must be a Sharee object.
*
* @param \Sabre\DAV\Xml\Element\Sharee[] $sharees
* @return void
*/
function updateInvites(array $sharees) {
public function updateInvites(array $sharees)
{
$this->caldavBackend->updateInvites($this->calendarInfo['id'], $sharees);
}
/**
@ -74,10 +72,9 @@ class SharedCalendar extends Calendar implements ISharedCalendar {
*
* @return \Sabre\DAV\Xml\Element\Sharee[]
*/
function getInvites() {
public function getInvites()
{
return $this->caldavBackend->getInvites($this->calendarInfo['id']);
}
/**
@ -87,12 +84,10 @@ class SharedCalendar extends Calendar implements ISharedCalendar {
* subscribable calendar.
*
* @param bool $value
* @return void
*/
function setPublishStatus($value) {
public function setPublishStatus($value)
{
$this->caldavBackend->setPublishStatus($this->calendarInfo['id'], $value);
}
/**
@ -107,13 +102,13 @@ class SharedCalendar extends Calendar implements ISharedCalendar {
*
* @return array
*/
function getACL() {
public function getACL()
{
$acl = [];
switch ($this->getShareAccess()) {
case SPlugin::ACCESS_NOTSHARED :
case SPlugin::ACCESS_SHAREDOWNER :
case SPlugin::ACCESS_NOTSHARED:
case SPlugin::ACCESS_SHAREDOWNER:
$acl[] = [
'privilege' => '{DAV:}share',
'principal' => $this->calendarInfo['principaluri'],
@ -121,76 +116,10 @@ class SharedCalendar extends Calendar implements ISharedCalendar {
];
$acl[] = [
'privilege' => '{DAV:}share',
'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write',
'principal' => $this->calendarInfo['principaluri'].'/calendar-proxy-write',
'protected' => true,
];
// No break intentional!
case SPlugin::ACCESS_READWRITE :
$acl[] = [
'privilege' => '{DAV:}write',
'principal' => $this->calendarInfo['principaluri'],
'protected' => true,
];
$acl[] = [
'privilege' => '{DAV:}write',
'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write',
'protected' => true,
];
// No break intentional!
case SPlugin::ACCESS_READ :
$acl[] = [
'privilege' => '{DAV:}write-properties',
'principal' => $this->calendarInfo['principaluri'],
'protected' => true,
];
$acl[] = [
'privilege' => '{DAV:}write-properties',
'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write',
'protected' => true,
];
$acl[] = [
'privilege' => '{DAV:}read',
'principal' => $this->calendarInfo['principaluri'],
'protected' => true,
];
$acl[] = [
'privilege' => '{DAV:}read',
'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-read',
'protected' => true,
];
$acl[] = [
'privilege' => '{DAV:}read',
'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write',
'protected' => true,
];
$acl[] = [
'privilege' => '{' . Plugin::NS_CALDAV . '}read-free-busy',
'principal' => '{DAV:}authenticated',
'protected' => true,
];
break;
}
return $acl;
}
/**
* This method returns the ACL's for calendar objects in this calendar.
* The result of this method automatically gets passed to the
* calendar-object nodes in the calendar.
*
* @return array
*/
function getChildACL() {
$acl = [];
switch ($this->getShareAccess()) {
case SPlugin::ACCESS_NOTSHARED :
// No break intentional
case SPlugin::ACCESS_SHAREDOWNER :
// No break intentional
// no break intentional!
case SPlugin::ACCESS_READWRITE:
$acl[] = [
'privilege' => '{DAV:}write',
@ -199,10 +128,73 @@ class SharedCalendar extends Calendar implements ISharedCalendar {
];
$acl[] = [
'privilege' => '{DAV:}write',
'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write',
'principal' => $this->calendarInfo['principaluri'].'/calendar-proxy-write',
'protected' => true,
];
// No break intentional
// no break intentional!
case SPlugin::ACCESS_READ:
$acl[] = [
'privilege' => '{DAV:}write-properties',
'principal' => $this->calendarInfo['principaluri'],
'protected' => true,
];
$acl[] = [
'privilege' => '{DAV:}write-properties',
'principal' => $this->calendarInfo['principaluri'].'/calendar-proxy-write',
'protected' => true,
];
$acl[] = [
'privilege' => '{DAV:}read',
'principal' => $this->calendarInfo['principaluri'],
'protected' => true,
];
$acl[] = [
'privilege' => '{DAV:}read',
'principal' => $this->calendarInfo['principaluri'].'/calendar-proxy-read',
'protected' => true,
];
$acl[] = [
'privilege' => '{DAV:}read',
'principal' => $this->calendarInfo['principaluri'].'/calendar-proxy-write',
'protected' => true,
];
$acl[] = [
'privilege' => '{'.Plugin::NS_CALDAV.'}read-free-busy',
'principal' => '{DAV:}authenticated',
'protected' => true,
];
break;
}
return $acl;
}
/**
* This method returns the ACL's for calendar objects in this calendar.
* The result of this method automatically gets passed to the
* calendar-object nodes in the calendar.
*
* @return array
*/
public function getChildACL()
{
$acl = [];
switch ($this->getShareAccess()) {
case SPlugin::ACCESS_NOTSHARED:
case SPlugin::ACCESS_SHAREDOWNER:
case SPlugin::ACCESS_READWRITE:
$acl[] = [
'privilege' => '{DAV:}write',
'principal' => $this->calendarInfo['principaluri'],
'protected' => true,
];
$acl[] = [
'privilege' => '{DAV:}write',
'principal' => $this->calendarInfo['principaluri'].'/calendar-proxy-write',
'protected' => true,
];
// no break intentional
case SPlugin::ACCESS_READ:
$acl[] = [
'privilege' => '{DAV:}read',
@ -211,19 +203,17 @@ class SharedCalendar extends Calendar implements ISharedCalendar {
];
$acl[] = [
'privilege' => '{DAV:}read',
'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-write',
'principal' => $this->calendarInfo['principaluri'].'/calendar-proxy-write',
'protected' => true,
];
$acl[] = [
'privilege' => '{DAV:}read',
'principal' => $this->calendarInfo['principaluri'] . '/calendar-proxy-read',
'principal' => $this->calendarInfo['principaluri'].'/calendar-proxy-read',
'protected' => true,
];
break;
}
return $acl;
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV;
use Sabre\DAV;
@ -23,8 +25,8 @@ use Sabre\HTTP\ResponseInterface;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class SharingPlugin extends DAV\ServerPlugin {
class SharingPlugin extends DAV\ServerPlugin
{
/**
* Reference to SabreDAV server object.
*
@ -40,10 +42,9 @@ class SharingPlugin extends DAV\ServerPlugin {
*
* @return array
*/
function getFeatures() {
public function getFeatures()
{
return ['calendarserver-sharing'];
}
/**
@ -54,10 +55,9 @@ class SharingPlugin extends DAV\ServerPlugin {
*
* @return string
*/
function getPluginName() {
public function getPluginName()
{
return 'caldav-sharing';
}
/**
@ -69,10 +69,9 @@ class SharingPlugin extends DAV\ServerPlugin {
* This method should set up the required event subscriptions.
*
* @param DAV\Server $server
* @return void
*/
function initialize(DAV\Server $server) {
public function initialize(DAV\Server $server)
{
$this->server = $server;
if (is_null($this->server->getPlugin('sharing'))) {
@ -81,19 +80,18 @@ class SharingPlugin extends DAV\ServerPlugin {
array_push(
$this->server->protectedProperties,
'{' . Plugin::NS_CALENDARSERVER . '}invite',
'{' . Plugin::NS_CALENDARSERVER . '}allowed-sharing-modes',
'{' . Plugin::NS_CALENDARSERVER . '}shared-url'
'{'.Plugin::NS_CALENDARSERVER.'}invite',
'{'.Plugin::NS_CALENDARSERVER.'}allowed-sharing-modes',
'{'.Plugin::NS_CALENDARSERVER.'}shared-url'
);
$this->server->xml->elementMap['{' . Plugin::NS_CALENDARSERVER . '}share'] = 'Sabre\\CalDAV\\Xml\\Request\\Share';
$this->server->xml->elementMap['{' . Plugin::NS_CALENDARSERVER . '}invite-reply'] = 'Sabre\\CalDAV\\Xml\\Request\\InviteReply';
$this->server->on('propFind', [$this, 'propFindEarly']);
$this->server->on('propFind', [$this, 'propFindLate'], 150);
$this->server->on('propPatch', [$this, 'propPatch'], 40);
$this->server->on('method:POST', [$this, 'httpPost']);
$this->server->xml->elementMap['{'.Plugin::NS_CALENDARSERVER.'}share'] = 'Sabre\\CalDAV\\Xml\\Request\\Share';
$this->server->xml->elementMap['{'.Plugin::NS_CALENDARSERVER.'}invite-reply'] = 'Sabre\\CalDAV\\Xml\\Request\\InviteReply';
$this->server->on('propFind', [$this, 'propFindEarly']);
$this->server->on('propFind', [$this, 'propFindLate'], 150);
$this->server->on('propPatch', [$this, 'propPatch'], 40);
$this->server->on('method:POST', [$this, 'httpPost']);
}
/**
@ -103,47 +101,17 @@ class SharingPlugin extends DAV\ServerPlugin {
* This allows us to inject any properties early.
*
* @param DAV\PropFind $propFind
* @param DAV\INode $node
* @return void
* @param DAV\INode $node
*/
function propFindEarly(DAV\PropFind $propFind, DAV\INode $node) {
public function propFindEarly(DAV\PropFind $propFind, DAV\INode $node)
{
if ($node instanceof ISharedCalendar) {
$propFind->handle('{' . Plugin::NS_CALENDARSERVER . '}invite', function() use ($node) {
// Fetching owner information
$props = $this->server->getPropertiesForPath($node->getOwner(), [
'{http://sabredav.org/ns}email-address',
'{DAV:}displayname',
], 0);
$ownerInfo = [
'href' => $node->getOwner(),
];
if (isset($props[0][200])) {
// We're mapping the internal webdav properties to the
// elements caldav-sharing expects.
if (isset($props[0][200]['{http://sabredav.org/ns}email-address'])) {
$ownerInfo['href'] = 'mailto:' . $props[0][200]['{http://sabredav.org/ns}email-address'];
}
if (isset($props[0][200]['{DAV:}displayname'])) {
$ownerInfo['commonName'] = $props[0][200]['{DAV:}displayname'];
}
}
$propFind->handle('{'.Plugin::NS_CALENDARSERVER.'}invite', function () use ($node) {
return new Xml\Property\Invite(
$node->getInvites(),
$ownerInfo
$node->getInvites()
);
});
}
}
/**
@ -152,31 +120,27 @@ class SharingPlugin extends DAV\ServerPlugin {
* have been shared.
*
* @param DAV\PropFind $propFind
* @param DAV\INode $node
* @return void
* @param DAV\INode $node
*/
function propFindLate(DAV\PropFind $propFind, DAV\INode $node) {
public function propFindLate(DAV\PropFind $propFind, DAV\INode $node)
{
if ($node instanceof ISharedCalendar) {
$shareAccess = $node->getShareAccess();
if ($rt = $propFind->get('{DAV:}resourcetype')) {
switch ($shareAccess) {
case \Sabre\DAV\Sharing\Plugin::ACCESS_SHAREDOWNER :
$rt->add('{' . Plugin::NS_CALENDARSERVER . '}shared-owner');
case \Sabre\DAV\Sharing\Plugin::ACCESS_SHAREDOWNER:
$rt->add('{'.Plugin::NS_CALENDARSERVER.'}shared-owner');
break;
case \Sabre\DAV\Sharing\Plugin::ACCESS_READ :
case \Sabre\DAV\Sharing\Plugin::ACCESS_READWRITE :
$rt->add('{' . Plugin::NS_CALENDARSERVER . '}shared');
case \Sabre\DAV\Sharing\Plugin::ACCESS_READ:
case \Sabre\DAV\Sharing\Plugin::ACCESS_READWRITE:
$rt->add('{'.Plugin::NS_CALENDARSERVER.'}shared');
break;
}
}
$propFind->handle('{' . Plugin::NS_CALENDARSERVER . '}allowed-sharing-modes', function() {
$propFind->handle('{'.Plugin::NS_CALENDARSERVER.'}allowed-sharing-modes', function () {
return new Xml\Property\AllowedSharingModes(true, false);
});
}
}
/**
@ -190,20 +154,21 @@ class SharingPlugin extends DAV\ServerPlugin {
* Even though this is no longer in the current spec, we keep this around
* because OS X 10.7 may still make use of this feature.
*
* @param string $path
* @param string $path
* @param DAV\PropPatch $propPatch
* @return void
*/
function propPatch($path, DAV\PropPatch $propPatch) {
public function propPatch($path, DAV\PropPatch $propPatch)
{
$node = $this->server->tree->getNodeForPath($path);
if (!$node instanceof ISharedCalendar)
if (!$node instanceof ISharedCalendar) {
return;
}
if ($node->getShareAccess() === \Sabre\DAV\Sharing\Plugin::ACCESS_SHAREDOWNER || $node->getShareAccess() === \Sabre\DAV\Sharing\Plugin::ACCESS_NOTSHARED) {
$propPatch->handle('{DAV:}resourcetype', function($value) use ($node) {
if ($value->is('{' . Plugin::NS_CALENDARSERVER . '}shared-owner')) return false;
if (\Sabre\DAV\Sharing\Plugin::ACCESS_SHAREDOWNER === $node->getShareAccess() || \Sabre\DAV\Sharing\Plugin::ACCESS_NOTSHARED === $node->getShareAccess()) {
$propPatch->handle('{DAV:}resourcetype', function ($value) use ($node) {
if ($value->is('{'.Plugin::NS_CALENDARSERVER.'}shared-owner')) {
return false;
}
$shares = $node->getInvites();
foreach ($shares as $share) {
$share->access = DAV\Sharing\Plugin::ACCESS_NOACCESS;
@ -211,28 +176,30 @@ class SharingPlugin extends DAV\ServerPlugin {
$node->updateInvites($shares);
return true;
});
}
}
/**
* We intercept this to handle POST requests on calendars.
*
* @param RequestInterface $request
* @param RequestInterface $request
* @param ResponseInterface $response
* @return null|bool
*
* @return bool|null
*/
function httpPost(RequestInterface $request, ResponseInterface $response) {
public function httpPost(RequestInterface $request, ResponseInterface $response)
{
$path = $request->getPath();
// Only handling xml
$contentType = $request->getHeader('Content-Type');
if (strpos($contentType, 'application/xml') === false && strpos($contentType, 'text/xml') === false)
if (null === $contentType) {
return;
}
if (false === strpos($contentType, 'application/xml') && false === strpos($contentType, 'text/xml')) {
return;
}
// Making sure the node exists
try {
@ -255,10 +222,9 @@ class SharingPlugin extends DAV\ServerPlugin {
$message = $this->server->xml->parse($requestBody, $request->getUrl(), $documentType);
switch ($documentType) {
// Both the DAV:share-resource and CALENDARSERVER:share requests
// behave identically.
case '{' . Plugin::NS_CALENDARSERVER . '}share' :
case '{'.Plugin::NS_CALENDARSERVER.'}share':
$sharingPlugin = $this->server->getPlugin('sharing');
$sharingPlugin->shareResource($path, $message->sharees);
@ -273,7 +239,7 @@ class SharingPlugin extends DAV\ServerPlugin {
// The invite-reply document is sent when the user replies to an
// invitation of a calendar share.
case '{' . Plugin::NS_CALENDARSERVER . '}invite-reply' :
case '{'.Plugin::NS_CALENDARSERVER.'}invite-reply':
// This only works on the calendar-home-root node.
if (!$node instanceof CalendarHome) {
@ -304,20 +270,20 @@ class SharingPlugin extends DAV\ServerPlugin {
if ($url) {
$writer = $this->server->xml->getWriter();
$writer->contextUri = $request->getUrl();
$writer->openMemory();
$writer->startDocument();
$writer->startElement('{' . Plugin::NS_CALENDARSERVER . '}shared-as');
$writer->startElement('{'.Plugin::NS_CALENDARSERVER.'}shared-as');
$writer->write(new LocalHref($url));
$writer->endElement();
$response->setHeader('Content-Type', 'application/xml');
$response->setBody($writer->outputMemory());
}
// Breaking the event chain
return false;
case '{' . Plugin::NS_CALENDARSERVER . '}publish-calendar' :
case '{'.Plugin::NS_CALENDARSERVER.'}publish-calendar':
// We can only deal with IShareableCalendar objects
if (!$node instanceof ISharedCalendar) {
@ -345,7 +311,7 @@ class SharingPlugin extends DAV\ServerPlugin {
// Breaking the event chain
return false;
case '{' . Plugin::NS_CALENDARSERVER . '}unpublish-calendar' :
case '{'.Plugin::NS_CALENDARSERVER.'}unpublish-calendar':
// We can only deal with IShareableCalendar objects
if (!$node instanceof ISharedCalendar) {
@ -371,11 +337,7 @@ class SharingPlugin extends DAV\ServerPlugin {
// Breaking the event chain
return false;
}
}
/**
@ -389,13 +351,12 @@ class SharingPlugin extends DAV\ServerPlugin {
*
* @return array
*/
function getPluginInfo() {
public function getPluginInfo()
{
return [
'name' => $this->getPluginName(),
'name' => $this->getPluginName(),
'description' => 'Adds support for caldav-sharing.',
'link' => 'http://sabre.io/dav/caldav-sharing/',
'link' => 'http://sabre.io/dav/caldav-sharing/',
];
}
}

View file

@ -1,12 +1,14 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Subscriptions;
use Sabre\DAV\ICollection;
use Sabre\DAV\IProperties;
/**
* ISubscription
* ISubscription.
*
* Nodes implementing this interface represent calendar subscriptions.
*
@ -34,7 +36,6 @@ use Sabre\DAV\IProperties;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
interface ISubscription extends ICollection, IProperties {
interface ISubscription extends ICollection, IProperties
{
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Subscriptions;
use Sabre\DAV\INode;
@ -17,8 +19,8 @@ use Sabre\DAV\ServerPlugin;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class Plugin extends ServerPlugin {
class Plugin extends ServerPlugin
{
/**
* This initializes the plugin.
*
@ -28,10 +30,9 @@ class Plugin extends ServerPlugin {
* This method should set up the required event subscriptions.
*
* @param Server $server
* @return void
*/
function initialize(Server $server) {
public function initialize(Server $server)
{
$server->resourceTypeMapping['Sabre\\CalDAV\\Subscriptions\\ISubscription'] =
'{http://calendarserver.org/ns/}subscribed';
@ -39,7 +40,6 @@ class Plugin extends ServerPlugin {
'Sabre\\DAV\\Xml\\Property\\Href';
$server->on('propFind', [$this, 'propFind'], 150);
}
/**
@ -50,21 +50,19 @@ class Plugin extends ServerPlugin {
*
* @return array
*/
function getFeatures() {
public function getFeatures()
{
return ['calendarserver-subscribed'];
}
/**
* Triggered after properties have been fetched.
*
* @param PropFind $propFind
* @param INode $node
* @return void
* @param INode $node
*/
function propFind(PropFind $propFind, INode $node) {
public function propFind(PropFind $propFind, INode $node)
{
// There's a bunch of properties that must appear as a self-closing
// xml-element. This event handler ensures that this will be the case.
$props = [
@ -74,13 +72,10 @@ class Plugin extends ServerPlugin {
];
foreach ($props as $prop) {
if ($propFind->getStatus($prop) === 200) {
if (200 === $propFind->getStatus($prop)) {
$propFind->set($prop, '', 200);
}
}
}
/**
@ -91,10 +86,9 @@ class Plugin extends ServerPlugin {
*
* @return string
*/
function getPluginName() {
public function getPluginName()
{
return 'subscriptions';
}
/**
@ -108,13 +102,12 @@ class Plugin extends ServerPlugin {
*
* @return array
*/
function getPluginInfo() {
public function getPluginInfo()
{
return [
'name' => $this->getPluginName(),
'name' => $this->getPluginName(),
'description' => 'This plugin allows users to store iCalendar subscriptions in their calendar-home.',
'link' => null,
'link' => null,
];
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Subscriptions;
use Sabre\CalDAV\Backend\SubscriptionSupport;
@ -10,7 +12,7 @@ use Sabre\DAVACL\ACLTrait;
use Sabre\DAVACL\IACL;
/**
* Subscription Node
* Subscription Node.
*
* This node represents a subscription.
*
@ -18,32 +20,32 @@ use Sabre\DAVACL\IACL;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class Subscription extends Collection implements ISubscription, IACL {
class Subscription extends Collection implements ISubscription, IACL
{
use ACLTrait;
/**
* caldavBackend
* caldavBackend.
*
* @var SubscriptionSupport
*/
protected $caldavBackend;
/**
* subscriptionInfo
* subscriptionInfo.
*
* @var array
*/
protected $subscriptionInfo;
/**
* Constructor
* Constructor.
*
* @param SubscriptionSupport $caldavBackend
* @param array $subscriptionInfo
* @param array $subscriptionInfo
*/
function __construct(SubscriptionSupport $caldavBackend, array $subscriptionInfo) {
public function __construct(SubscriptionSupport $caldavBackend, array $subscriptionInfo)
{
$this->caldavBackend = $caldavBackend;
$this->subscriptionInfo = $subscriptionInfo;
@ -56,10 +58,9 @@ class Subscription extends Collection implements ISubscription, IACL {
foreach ($required as $r) {
if (!isset($subscriptionInfo[$r])) {
throw new \InvalidArgumentException('The ' . $r . ' field is required when creating a subscription node');
throw new \InvalidArgumentException('The '.$r.' field is required when creating a subscription node');
}
}
}
/**
@ -69,47 +70,41 @@ class Subscription extends Collection implements ISubscription, IACL {
*
* @return string
*/
function getName() {
public function getName()
{
return $this->subscriptionInfo['uri'];
}
/**
* Returns the last modification time
* Returns the last modification time.
*
* @return int
*/
function getLastModified() {
public function getLastModified()
{
if (isset($this->subscriptionInfo['lastmodified'])) {
return $this->subscriptionInfo['lastmodified'];
}
}
/**
* Deletes the current node
*
* @return void
* Deletes the current node.
*/
function delete() {
public function delete()
{
$this->caldavBackend->deleteSubscription(
$this->subscriptionInfo['id']
);
}
/**
* Returns an array with all the child nodes
* Returns an array with all the child nodes.
*
* @return \Sabre\DAV\INode[]
*/
function getChildren() {
public function getChildren()
{
return [];
}
/**
@ -122,15 +117,13 @@ class Subscription extends Collection implements ISubscription, IACL {
* Read the PropPatch documentation for more information.
*
* @param PropPatch $propPatch
* @return void
*/
function propPatch(PropPatch $propPatch) {
public function propPatch(PropPatch $propPatch)
{
return $this->caldavBackend->updateSubscription(
$this->subscriptionInfo['id'],
$propPatch
);
}
/**
@ -146,29 +139,27 @@ class Subscription extends Collection implements ISubscription, IACL {
* The Server class will filter out the extra.
*
* @param array $properties
*
* @return array
*/
function getProperties($properties) {
public function getProperties($properties)
{
$r = [];
foreach ($properties as $prop) {
switch ($prop) {
case '{http://calendarserver.org/ns/}source' :
case '{http://calendarserver.org/ns/}source':
$r[$prop] = new Href($this->subscriptionInfo['source']);
break;
default :
default:
if (array_key_exists($prop, $this->subscriptionInfo)) {
$r[$prop] = $this->subscriptionInfo[$prop];
}
break;
}
}
return $r;
}
/**
@ -178,10 +169,9 @@ class Subscription extends Collection implements ISubscription, IACL {
*
* @return string|null
*/
function getOwner() {
public function getOwner()
{
return $this->subscriptionInfo['principaluri'];
}
/**
@ -196,8 +186,8 @@ class Subscription extends Collection implements ISubscription, IACL {
*
* @return array
*/
function getACL() {
public function getACL()
{
return [
[
'privilege' => '{DAV:}all',
@ -206,16 +196,14 @@ class Subscription extends Collection implements ISubscription, IACL {
],
[
'privilege' => '{DAV:}all',
'principal' => $this->getOwner() . '/calendar-proxy-write',
'principal' => $this->getOwner().'/calendar-proxy-write',
'protected' => true,
],
[
'privilege' => '{DAV:}read',
'principal' => $this->getOwner() . '/calendar-proxy-read',
'principal' => $this->getOwner().'/calendar-proxy-read',
'protected' => true,
]
],
];
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Xml\Filter;
use Sabre\CalDAV\Plugin;
@ -25,8 +27,8 @@ use Sabre\Xml\XmlDeserializable;
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://sabre.io/license/ Modified BSD License
*/
class CalendarData implements XmlDeserializable {
class CalendarData implements XmlDeserializable
{
/**
* The deserialize method is called during xml parsing.
*
@ -46,24 +48,24 @@ class CalendarData implements XmlDeserializable {
* the next element.
*
* @param Reader $reader
*
* @return mixed
*/
static function xmlDeserialize(Reader $reader) {
public static function xmlDeserialize(Reader $reader)
{
$result = [
'contentType' => $reader->getAttribute('content-type') ?: 'text/calendar',
'version' => $reader->getAttribute('version') ?: '2.0',
'version' => $reader->getAttribute('version') ?: '2.0',
];
$elems = (array)$reader->parseInnerTree();
$elems = (array) $reader->parseInnerTree();
foreach ($elems as $elem) {
switch ($elem['name']) {
case '{' . Plugin::NS_CALDAV . '}expand' :
case '{'.Plugin::NS_CALDAV.'}expand':
$result['expand'] = [
'start' => isset($elem['attributes']['start']) ? DateTimeParser::parseDateTime($elem['attributes']['start']) : null,
'end' => isset($elem['attributes']['end']) ? DateTimeParser::parseDateTime($elem['attributes']['end']) : null,
'end' => isset($elem['attributes']['end']) ? DateTimeParser::parseDateTime($elem['attributes']['end']) : null,
];
if (!$result['expand']['start'] || !$result['expand']['end']) {
@ -74,11 +76,8 @@ class CalendarData implements XmlDeserializable {
}
break;
}
}
return $result;
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Xml\Filter;
use Sabre\CalDAV\Plugin;
@ -22,8 +24,8 @@ use Sabre\Xml\XmlDeserializable;
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://sabre.io/license/ Modified BSD License
*/
class CompFilter implements XmlDeserializable {
class CompFilter implements XmlDeserializable
{
/**
* The deserialize method is called during xml parsing.
*
@ -43,16 +45,17 @@ class CompFilter implements XmlDeserializable {
* the next element.
*
* @param Reader $reader
*
* @return mixed
*/
static function xmlDeserialize(Reader $reader) {
public static function xmlDeserialize(Reader $reader)
{
$result = [
'name' => null,
'name' => null,
'is-not-defined' => false,
'comp-filters' => [],
'prop-filters' => [],
'time-range' => false,
'comp-filters' => [],
'prop-filters' => [],
'time-range' => false,
];
$att = $reader->parseAttributes();
@ -60,38 +63,34 @@ class CompFilter implements XmlDeserializable {
$elems = $reader->parseInnerTree();
if (is_array($elems)) foreach ($elems as $elem) {
switch ($elem['name']) {
case '{' . Plugin::NS_CALDAV . '}comp-filter' :
if (is_array($elems)) {
foreach ($elems as $elem) {
switch ($elem['name']) {
case '{'.Plugin::NS_CALDAV.'}comp-filter':
$result['comp-filters'][] = $elem['value'];
break;
case '{' . Plugin::NS_CALDAV . '}prop-filter' :
case '{'.Plugin::NS_CALDAV.'}prop-filter':
$result['prop-filters'][] = $elem['value'];
break;
case '{' . Plugin::NS_CALDAV . '}is-not-defined' :
case '{'.Plugin::NS_CALDAV.'}is-not-defined':
$result['is-not-defined'] = true;
break;
case '{' . Plugin::NS_CALDAV . '}time-range' :
if ($result['name'] === 'VCALENDAR') {
case '{'.Plugin::NS_CALDAV.'}time-range':
if ('VCALENDAR' === $result['name']) {
throw new BadRequest('You cannot add time-range filters on the VCALENDAR component');
}
$result['time-range'] = [
'start' => isset($elem['attributes']['start']) ? DateTimeParser::parseDateTime($elem['attributes']['start']) : null,
'end' => isset($elem['attributes']['end']) ? DateTimeParser::parseDateTime($elem['attributes']['end']) : null,
'end' => isset($elem['attributes']['end']) ? DateTimeParser::parseDateTime($elem['attributes']['end']) : null,
];
if ($result['time-range']['start'] && $result['time-range']['end'] && $result['time-range']['end'] <= $result['time-range']['start']) {
throw new BadRequest('The end-date must be larger than the start-date');
}
break;
}
}
}
return $result;
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Xml\Filter;
use Sabre\CalDAV\Plugin;
@ -20,8 +22,8 @@ use Sabre\Xml\XmlDeserializable;
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://sabre.io/license/ Modified BSD License
*/
class ParamFilter implements XmlDeserializable {
class ParamFilter implements XmlDeserializable
{
/**
* The deserialize method is called during xml parsing.
*
@ -41,14 +43,15 @@ class ParamFilter implements XmlDeserializable {
* the next element.
*
* @param Reader $reader
*
* @return mixed
*/
static function xmlDeserialize(Reader $reader) {
public static function xmlDeserialize(Reader $reader)
{
$result = [
'name' => null,
'name' => null,
'is-not-defined' => false,
'text-match' => null,
'text-match' => null,
];
$att = $reader->parseAttributes();
@ -56,27 +59,23 @@ class ParamFilter implements XmlDeserializable {
$elems = $reader->parseInnerTree();
if (is_array($elems)) foreach ($elems as $elem) {
switch ($elem['name']) {
case '{' . Plugin::NS_CALDAV . '}is-not-defined' :
if (is_array($elems)) {
foreach ($elems as $elem) {
switch ($elem['name']) {
case '{'.Plugin::NS_CALDAV.'}is-not-defined':
$result['is-not-defined'] = true;
break;
case '{' . Plugin::NS_CALDAV . '}text-match' :
case '{'.Plugin::NS_CALDAV.'}text-match':
$result['text-match'] = [
'negate-condition' => isset($elem['attributes']['negate-condition']) && $elem['attributes']['negate-condition'] === 'yes',
'collation' => isset($elem['attributes']['collation']) ? $elem['attributes']['collation'] : 'i;ascii-casemap',
'value' => $elem['value'],
'negate-condition' => isset($elem['attributes']['negate-condition']) && 'yes' === $elem['attributes']['negate-condition'],
'collation' => isset($elem['attributes']['collation']) ? $elem['attributes']['collation'] : 'i;ascii-casemap',
'value' => $elem['value'],
];
break;
}
}
}
return $result;
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Xml\Filter;
use Sabre\CalDAV\Plugin;
@ -22,8 +24,8 @@ use Sabre\Xml\XmlDeserializable;
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://sabre.io/license/ Modified BSD License
*/
class PropFilter implements XmlDeserializable {
class PropFilter implements XmlDeserializable
{
/**
* The deserialize method is called during xml parsing.
*
@ -43,16 +45,17 @@ class PropFilter implements XmlDeserializable {
* the next element.
*
* @param Reader $reader
*
* @return mixed
*/
static function xmlDeserialize(Reader $reader) {
public static function xmlDeserialize(Reader $reader)
{
$result = [
'name' => null,
'name' => null,
'is-not-defined' => false,
'param-filters' => [],
'text-match' => null,
'time-range' => false,
'param-filters' => [],
'text-match' => null,
'time-range' => false,
];
$att = $reader->parseAttributes();
@ -60,39 +63,35 @@ class PropFilter implements XmlDeserializable {
$elems = $reader->parseInnerTree();
if (is_array($elems)) foreach ($elems as $elem) {
switch ($elem['name']) {
case '{' . Plugin::NS_CALDAV . '}param-filter' :
if (is_array($elems)) {
foreach ($elems as $elem) {
switch ($elem['name']) {
case '{'.Plugin::NS_CALDAV.'}param-filter':
$result['param-filters'][] = $elem['value'];
break;
case '{' . Plugin::NS_CALDAV . '}is-not-defined' :
case '{'.Plugin::NS_CALDAV.'}is-not-defined':
$result['is-not-defined'] = true;
break;
case '{' . Plugin::NS_CALDAV . '}time-range' :
case '{'.Plugin::NS_CALDAV.'}time-range':
$result['time-range'] = [
'start' => isset($elem['attributes']['start']) ? DateTimeParser::parseDateTime($elem['attributes']['start']) : null,
'end' => isset($elem['attributes']['end']) ? DateTimeParser::parseDateTime($elem['attributes']['end']) : null,
'end' => isset($elem['attributes']['end']) ? DateTimeParser::parseDateTime($elem['attributes']['end']) : null,
];
if ($result['time-range']['start'] && $result['time-range']['end'] && $result['time-range']['end'] <= $result['time-range']['start']) {
throw new BadRequest('The end-date must be larger than the start-date');
}
break;
case '{' . Plugin::NS_CALDAV . '}text-match' :
case '{'.Plugin::NS_CALDAV.'}text-match':
$result['text-match'] = [
'negate-condition' => isset($elem['attributes']['negate-condition']) && $elem['attributes']['negate-condition'] === 'yes',
'collation' => isset($elem['attributes']['collation']) ? $elem['attributes']['collation'] : 'i;ascii-casemap',
'value' => $elem['value'],
'negate-condition' => isset($elem['attributes']['negate-condition']) && 'yes' === $elem['attributes']['negate-condition'],
'collation' => isset($elem['attributes']['collation']) ? $elem['attributes']['collation'] : 'i;ascii-casemap',
'value' => $elem['value'],
];
break;
}
}
}
return $result;
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Xml\Notification;
use Sabre\CalDAV;
@ -17,19 +19,19 @@ use Sabre\Xml\Writer;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class Invite implements NotificationInterface {
class Invite implements NotificationInterface
{
/**
* A unique id for the message
* A unique id for the message.
*
* @var string
*/
protected $id;
/**
* Timestamp of the notification
* Timestamp of the notification.
*
* @var DateTime
* @var \DateTime
*/
protected $dtStamp;
@ -63,7 +65,7 @@ class Invite implements NotificationInterface {
protected $hostUrl;
/**
* Url to the sharer of the calendar
* Url to the sharer of the calendar.
*
* @var string
*/
@ -91,21 +93,21 @@ class Invite implements NotificationInterface {
protected $lastName;
/**
* A description of the share request
* A description of the share request.
*
* @var string
*/
protected $summary;
/**
* The Etag for the notification
* The Etag for the notification.
*
* @var string
*/
protected $etag;
/**
* The list of supported components
* The list of supported components.
*
* @var CalDAV\Xml\Property\SupportedCalendarComponentSet
*/
@ -138,8 +140,8 @@ class Invite implements NotificationInterface {
*
* @param array $values All the options
*/
function __construct(array $values) {
public function __construct(array $values)
{
$required = [
'id',
'etag',
@ -152,17 +154,16 @@ class Invite implements NotificationInterface {
];
foreach ($required as $item) {
if (!isset($values[$item])) {
throw new \InvalidArgumentException($item . ' is a required constructor option');
throw new \InvalidArgumentException($item.' is a required constructor option');
}
}
foreach ($values as $key => $value) {
if (!property_exists($this, $key)) {
throw new \InvalidArgumentException('Unknown option: ' . $key);
throw new \InvalidArgumentException('Unknown option: '.$key);
}
$this->$key = $value;
}
}
/**
@ -182,12 +183,10 @@ class Invite implements NotificationInterface {
* If you are opening new elements, you must also close them again.
*
* @param Writer $writer
* @return void
*/
function xmlSerialize(Writer $writer) {
$writer->writeElement('{' . CalDAV\Plugin::NS_CALENDARSERVER . '}invite-notification');
public function xmlSerialize(Writer $writer)
{
$writer->writeElement('{'.CalDAV\Plugin::NS_CALENDARSERVER.'}invite-notification');
}
/**
@ -195,95 +194,90 @@ class Invite implements NotificationInterface {
* response body.
*
* @param Writer $writer
* @return void
*/
function xmlSerializeFull(Writer $writer) {
public function xmlSerializeFull(Writer $writer)
{
$cs = '{'.CalDAV\Plugin::NS_CALENDARSERVER.'}';
$cs = '{' . CalDAV\Plugin::NS_CALENDARSERVER . '}';
$this->dtStamp->setTimezone(new \DateTimeZone('GMT'));
$writer->writeElement($cs.'dtstamp', $this->dtStamp->format('Ymd\\THis\\Z'));
$this->dtStamp->setTimezone(new \DateTimezone('GMT'));
$writer->writeElement($cs . 'dtstamp', $this->dtStamp->format('Ymd\\THis\\Z'));
$writer->startElement($cs.'invite-notification');
$writer->startElement($cs . 'invite-notification');
$writer->writeElement($cs . 'uid', $this->id);
$writer->writeElement($cs.'uid', $this->id);
$writer->writeElement('{DAV:}href', $this->href);
switch ($this->type) {
case DAV\Sharing\Plugin::INVITE_ACCEPTED :
$writer->writeElement($cs . 'invite-accepted');
case DAV\Sharing\Plugin::INVITE_ACCEPTED:
$writer->writeElement($cs.'invite-accepted');
break;
case DAV\Sharing\Plugin::INVITE_NORESPONSE :
$writer->writeElement($cs . 'invite-noresponse');
case DAV\Sharing\Plugin::INVITE_NORESPONSE:
$writer->writeElement($cs.'invite-noresponse');
break;
}
$writer->writeElement($cs . 'hosturl', [
'{DAV:}href' => $writer->contextUri . $this->hostUrl
$writer->writeElement($cs.'hosturl', [
'{DAV:}href' => $writer->contextUri.$this->hostUrl,
]);
if ($this->summary) {
$writer->writeElement($cs . 'summary', $this->summary);
$writer->writeElement($cs.'summary', $this->summary);
}
$writer->startElement($cs . 'access');
$writer->startElement($cs.'access');
if ($this->readOnly) {
$writer->writeElement($cs . 'read');
$writer->writeElement($cs.'read');
} else {
$writer->writeElement($cs . 'read-write');
$writer->writeElement($cs.'read-write');
}
$writer->endElement(); // access
$writer->startElement($cs . 'organizer');
$writer->startElement($cs.'organizer');
// If the organizer contains a 'mailto:' part, it means it should be
// treated as absolute.
if (strtolower(substr($this->organizer, 0, 7)) === 'mailto:') {
if ('mailto:' === strtolower(substr($this->organizer, 0, 7))) {
$writer->writeElement('{DAV:}href', $this->organizer);
} else {
$writer->writeElement('{DAV:}href', $writer->contextUri . $this->organizer);
$writer->writeElement('{DAV:}href', $writer->contextUri.$this->organizer);
}
if ($this->commonName) {
$writer->writeElement($cs . 'common-name', $this->commonName);
$writer->writeElement($cs.'common-name', $this->commonName);
}
if ($this->firstName) {
$writer->writeElement($cs . 'first-name', $this->firstName);
$writer->writeElement($cs.'first-name', $this->firstName);
}
if ($this->lastName) {
$writer->writeElement($cs . 'last-name', $this->lastName);
$writer->writeElement($cs.'last-name', $this->lastName);
}
$writer->endElement(); // organizer
if ($this->commonName) {
$writer->writeElement($cs . 'organizer-cn', $this->commonName);
$writer->writeElement($cs.'organizer-cn', $this->commonName);
}
if ($this->firstName) {
$writer->writeElement($cs . 'organizer-first', $this->firstName);
$writer->writeElement($cs.'organizer-first', $this->firstName);
}
if ($this->lastName) {
$writer->writeElement($cs . 'organizer-last', $this->lastName);
$writer->writeElement($cs.'organizer-last', $this->lastName);
}
if ($this->supportedComponents) {
$writer->writeElement('{' . CalDAV\Plugin::NS_CALDAV . '}supported-calendar-component-set', $this->supportedComponents);
$writer->writeElement('{'.CalDAV\Plugin::NS_CALDAV.'}supported-calendar-component-set', $this->supportedComponents);
}
$writer->endElement(); // invite-notification
}
/**
* Returns a unique id for this notification
* Returns a unique id for this notification.
*
* This is just the base url. This should generally be some kind of unique
* id.
*
* @return string
*/
function getId() {
public function getId()
{
return $this->id;
}
/**
@ -293,10 +287,8 @@ class Invite implements NotificationInterface {
*
* @return string
*/
function getETag() {
public function getETag()
{
return $this->etag;
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Xml\Notification;
use Sabre\CalDAV;
@ -14,19 +16,19 @@ use Sabre\Xml\Writer;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class InviteReply implements NotificationInterface {
class InviteReply implements NotificationInterface
{
/**
* A unique id for the message
* A unique id for the message.
*
* @var string
*/
protected $id;
/**
* Timestamp of the notification
* Timestamp of the notification.
*
* @var DateTime
* @var \DateTime
*/
protected $dtStamp;
@ -59,14 +61,14 @@ class InviteReply implements NotificationInterface {
protected $hostUrl;
/**
* A description of the share request
* A description of the share request.
*
* @var string
*/
protected $summary;
/**
* Notification Etag
* Notification Etag.
*
* @var string
*/
@ -90,8 +92,8 @@ class InviteReply implements NotificationInterface {
*
* @param array $values
*/
function __construct(array $values) {
public function __construct(array $values)
{
$required = [
'id',
'etag',
@ -103,17 +105,16 @@ class InviteReply implements NotificationInterface {
];
foreach ($required as $item) {
if (!isset($values[$item])) {
throw new \InvalidArgumentException($item . ' is a required constructor option');
throw new \InvalidArgumentException($item.' is a required constructor option');
}
}
foreach ($values as $key => $value) {
if (!property_exists($this, $key)) {
throw new \InvalidArgumentException('Unknown option: ' . $key);
throw new \InvalidArgumentException('Unknown option: '.$key);
}
$this->$key = $value;
}
}
/**
@ -133,12 +134,10 @@ class InviteReply implements NotificationInterface {
* If you are opening new elements, you must also close them again.
*
* @param Writer $writer
* @return void
*/
function xmlSerialize(Writer $writer) {
$writer->writeElement('{' . CalDAV\Plugin::NS_CALENDARSERVER . '}invite-reply');
public function xmlSerialize(Writer $writer)
{
$writer->writeElement('{'.CalDAV\Plugin::NS_CALENDARSERVER.'}invite-reply');
}
/**
@ -146,55 +145,50 @@ class InviteReply implements NotificationInterface {
* response body.
*
* @param Writer $writer
* @return void
*/
function xmlSerializeFull(Writer $writer) {
public function xmlSerializeFull(Writer $writer)
{
$cs = '{'.CalDAV\Plugin::NS_CALENDARSERVER.'}';
$cs = '{' . CalDAV\Plugin::NS_CALENDARSERVER . '}';
$this->dtStamp->setTimezone(new \DateTimeZone('GMT'));
$writer->writeElement($cs.'dtstamp', $this->dtStamp->format('Ymd\\THis\\Z'));
$this->dtStamp->setTimezone(new \DateTimezone('GMT'));
$writer->writeElement($cs . 'dtstamp', $this->dtStamp->format('Ymd\\THis\\Z'));
$writer->startElement($cs.'invite-reply');
$writer->startElement($cs . 'invite-reply');
$writer->writeElement($cs . 'uid', $this->id);
$writer->writeElement($cs . 'in-reply-to', $this->inReplyTo);
$writer->writeElement($cs.'uid', $this->id);
$writer->writeElement($cs.'in-reply-to', $this->inReplyTo);
$writer->writeElement('{DAV:}href', $this->href);
switch ($this->type) {
case DAV\Sharing\Plugin::INVITE_ACCEPTED :
$writer->writeElement($cs . 'invite-accepted');
case DAV\Sharing\Plugin::INVITE_ACCEPTED:
$writer->writeElement($cs.'invite-accepted');
break;
case DAV\Sharing\Plugin::INVITE_DECLINED :
$writer->writeElement($cs . 'invite-declined');
case DAV\Sharing\Plugin::INVITE_DECLINED:
$writer->writeElement($cs.'invite-declined');
break;
}
$writer->writeElement($cs . 'hosturl', [
'{DAV:}href' => $writer->contextUri . $this->hostUrl
$writer->writeElement($cs.'hosturl', [
'{DAV:}href' => $writer->contextUri.$this->hostUrl,
]);
if ($this->summary) {
$writer->writeElement($cs . 'summary', $this->summary);
$writer->writeElement($cs.'summary', $this->summary);
}
$writer->endElement(); // invite-reply
}
/**
* Returns a unique id for this notification
* Returns a unique id for this notification.
*
* This is just the base url. This should generally be some kind of unique
* id.
*
* @return string
*/
function getId() {
public function getId()
{
return $this->id;
}
/**
@ -204,10 +198,8 @@ class InviteReply implements NotificationInterface {
*
* @return string
*/
function getETag() {
public function getETag()
{
return $this->etag;
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Xml\Notification;
use Sabre\Xml\Writer;
@ -12,26 +14,25 @@ use Sabre\Xml\XmlSerializable;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
interface NotificationInterface extends XmlSerializable {
interface NotificationInterface extends XmlSerializable
{
/**
* This method serializes the entire notification, as it is used in the
* response body.
*
* @param Writer $writer
* @return void
*/
function xmlSerializeFull(Writer $writer);
public function xmlSerializeFull(Writer $writer);
/**
* Returns a unique id for this notification
* Returns a unique id for this notification.
*
* This is just the base url. This should generally be some kind of unique
* id.
*
* @return string
*/
function getId();
public function getId();
/**
* Returns the ETag for this notification.
@ -40,6 +41,5 @@ interface NotificationInterface extends XmlSerializable {
*
* @return string
*/
function getETag();
public function getETag();
}

View file

@ -1,12 +1,14 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Xml\Notification;
use Sabre\CalDAV\Plugin;
use Sabre\Xml\Writer;
/**
* SystemStatus notification
* SystemStatus notification.
*
* This notification can be used to indicate to the user that the system is
* down.
@ -15,14 +17,14 @@ use Sabre\Xml\Writer;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class SystemStatus implements NotificationInterface {
class SystemStatus implements NotificationInterface
{
const TYPE_LOW = 1;
const TYPE_MEDIUM = 2;
const TYPE_HIGH = 3;
/**
* A unique id
* A unique id.
*
* @var string
*/
@ -50,7 +52,7 @@ class SystemStatus implements NotificationInterface {
protected $href;
/**
* Notification Etag
* Notification Etag.
*
* @var string
*/
@ -64,18 +66,17 @@ class SystemStatus implements NotificationInterface {
*
* @param string $id
* @param string $etag
* @param int $type
* @param int $type
* @param string $description
* @param string $href
*/
function __construct($id, $etag, $type = self::TYPE_HIGH, $description = null, $href = null) {
public function __construct($id, $etag, $type = self::TYPE_HIGH, $description = null, $href = null)
{
$this->id = $id;
$this->type = $type;
$this->description = $description;
$this->href = $href;
$this->etag = $etag;
}
/**
@ -91,27 +92,25 @@ class SystemStatus implements NotificationInterface {
* responsible for closing them.
*
* @param Writer $writer
* @return void
*/
function xmlSerialize(Writer $writer) {
public function xmlSerialize(Writer $writer)
{
switch ($this->type) {
case self::TYPE_LOW :
case self::TYPE_LOW:
$type = 'low';
break;
case self::TYPE_MEDIUM :
case self::TYPE_MEDIUM:
$type = 'medium';
break;
default :
case self::TYPE_HIGH :
default:
case self::TYPE_HIGH:
$type = 'high';
break;
}
$writer->startElement('{' . Plugin::NS_CALENDARSERVER . '}systemstatus');
$writer->startElement('{'.Plugin::NS_CALENDARSERVER.'}systemstatus');
$writer->writeAttribute('type', $type);
$writer->endElement();
}
/**
@ -119,51 +118,47 @@ class SystemStatus implements NotificationInterface {
* response body.
*
* @param Writer $writer
* @return void
*/
function xmlSerializeFull(Writer $writer) {
$cs = '{' . Plugin::NS_CALENDARSERVER . '}';
public function xmlSerializeFull(Writer $writer)
{
$cs = '{'.Plugin::NS_CALENDARSERVER.'}';
switch ($this->type) {
case self::TYPE_LOW :
case self::TYPE_LOW:
$type = 'low';
break;
case self::TYPE_MEDIUM :
case self::TYPE_MEDIUM:
$type = 'medium';
break;
default :
case self::TYPE_HIGH :
default:
case self::TYPE_HIGH:
$type = 'high';
break;
}
$writer->startElement($cs . 'systemstatus');
$writer->startElement($cs.'systemstatus');
$writer->writeAttribute('type', $type);
if ($this->description) {
$writer->writeElement($cs . 'description', $this->description);
$writer->writeElement($cs.'description', $this->description);
}
if ($this->href) {
$writer->writeElement('{DAV:}href', $this->href);
}
$writer->endElement(); // systemstatus
}
/**
* Returns a unique id for this notification
* Returns a unique id for this notification.
*
* This is just the base url. This should generally be some kind of unique
* id.
*
* @return string
*/
function getId() {
public function getId()
{
return $this->id;
}
/*
@ -173,10 +168,8 @@ class SystemStatus implements NotificationInterface {
*
* @return string
*/
function getETag() {
public function getETag()
{
return $this->etag;
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Xml\Property;
use Sabre\CalDAV\Plugin;
@ -7,7 +9,7 @@ use Sabre\Xml\Writer;
use Sabre\Xml\XmlSerializable;
/**
* AllowedSharingModes
* AllowedSharingModes.
*
* This property encodes the 'allowed-sharing-modes' property, as defined by
* the 'caldav-sharing-02' spec, in the http://calendarserver.org/ns/
@ -18,14 +20,15 @@ use Sabre\Xml\XmlSerializable;
* such as VEVENT, VTODO
*
* @see https://trac.calendarserver.org/browser/CalendarServer/trunk/doc/Extensions/caldav-sharing-02.txt
*
* @copyright Copyright (C) fruux GmbH (https://fruux.com/)
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://sabre.io/license/ Modified BSD License
*/
class AllowedSharingModes implements XmlSerializable {
class AllowedSharingModes implements XmlSerializable
{
/**
* Whether or not a calendar can be shared with another user
* Whether or not a calendar can be shared with another user.
*
* @var bool
*/
@ -39,17 +42,15 @@ class AllowedSharingModes implements XmlSerializable {
protected $canBePublished;
/**
* Constructor
* Constructor.
*
* @param bool $canBeShared
* @param bool $canBePublished
* @return void
*/
function __construct($canBeShared, $canBePublished) {
public function __construct($canBeShared, $canBePublished)
{
$this->canBeShared = $canBeShared;
$this->canBePublished = $canBePublished;
}
/**
@ -69,19 +70,14 @@ class AllowedSharingModes implements XmlSerializable {
* If you are opening new elements, you must also close them again.
*
* @param Writer $writer
* @return void
*/
function xmlSerialize(Writer $writer) {
public function xmlSerialize(Writer $writer)
{
if ($this->canBeShared) {
$writer->writeElement('{' . Plugin::NS_CALENDARSERVER . '}can-be-shared');
$writer->writeElement('{'.Plugin::NS_CALENDARSERVER.'}can-be-shared');
}
if ($this->canBePublished) {
$writer->writeElement('{' . Plugin::NS_CALENDARSERVER . '}can-be-published');
$writer->writeElement('{'.Plugin::NS_CALENDARSERVER.'}can-be-published');
}
}
}

View file

@ -1,12 +1,14 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Xml\Property;
use Sabre\Xml\Writer;
use Sabre\Xml\XmlSerializable;
/**
* email-address-set property
* email-address-set property.
*
* This property represents the email-address-set property in the
* http://calendarserver.org/ns/ namespace.
@ -17,35 +19,33 @@ use Sabre\Xml\XmlSerializable;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class EmailAddressSet implements XmlSerializable {
class EmailAddressSet implements XmlSerializable
{
/**
* emails
* emails.
*
* @var array
*/
private $emails;
/**
* __construct
* __construct.
*
* @param array $emails
*/
function __construct(array $emails) {
public function __construct(array $emails)
{
$this->emails = $emails;
}
/**
* Returns the email addresses
* Returns the email addresses.
*
* @return array
*/
function getValue() {
public function getValue()
{
return $this->emails;
}
/**
@ -65,16 +65,11 @@ class EmailAddressSet implements XmlSerializable {
* If you are opening new elements, you must also close them again.
*
* @param Writer $writer
* @return void
*/
function xmlSerialize(Writer $writer) {
public function xmlSerialize(Writer $writer)
{
foreach ($this->emails as $email) {
$writer->writeElement('{http://calendarserver.org/ns/}email-address', $email);
}
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Xml\Property;
use Sabre\CalDAV\Plugin;
@ -9,19 +11,20 @@ use Sabre\Xml\Writer;
use Sabre\Xml\XmlSerializable;
/**
* Invite property
* Invite property.
*
* This property encodes the 'invite' property, as defined by
* the 'caldav-sharing-02' spec, in the http://calendarserver.org/ns/
* namespace.
*
* @see https://trac.calendarserver.org/browser/CalendarServer/trunk/doc/Extensions/caldav-sharing-02.txt
*
* @copyright Copyright (C) fruux GmbH (https://fruux.com/)
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class Invite implements XmlSerializable {
class Invite implements XmlSerializable
{
/**
* The list of users a calendar has been shared to.
*
@ -34,10 +37,9 @@ class Invite implements XmlSerializable {
*
* @param Sharee[] $sharees
*/
function __construct(array $sharees) {
public function __construct(array $sharees)
{
$this->sharees = $sharees;
}
/**
@ -45,10 +47,9 @@ class Invite implements XmlSerializable {
*
* @return array
*/
function getValue() {
public function getValue()
{
return $this->sharees;
}
/**
@ -68,61 +69,54 @@ class Invite implements XmlSerializable {
* If you are opening new elements, you must also close them again.
*
* @param Writer $writer
* @return void
*/
function xmlSerialize(Writer $writer) {
$cs = '{' . Plugin::NS_CALENDARSERVER . '}';
public function xmlSerialize(Writer $writer)
{
$cs = '{'.Plugin::NS_CALENDARSERVER.'}';
foreach ($this->sharees as $sharee) {
if ($sharee->access === DAV\Sharing\Plugin::ACCESS_SHAREDOWNER) {
$writer->startElement($cs . 'organizer');
if (DAV\Sharing\Plugin::ACCESS_SHAREDOWNER === $sharee->access) {
$writer->startElement($cs.'organizer');
} else {
$writer->startElement($cs . 'user');
$writer->startElement($cs.'user');
switch ($sharee->inviteStatus) {
case DAV\Sharing\Plugin::INVITE_ACCEPTED :
$writer->writeElement($cs . 'invite-accepted');
case DAV\Sharing\Plugin::INVITE_ACCEPTED:
$writer->writeElement($cs.'invite-accepted');
break;
case DAV\Sharing\Plugin::INVITE_DECLINED :
$writer->writeElement($cs . 'invite-declined');
case DAV\Sharing\Plugin::INVITE_DECLINED:
$writer->writeElement($cs.'invite-declined');
break;
case DAV\Sharing\Plugin::INVITE_NORESPONSE :
$writer->writeElement($cs . 'invite-noresponse');
case DAV\Sharing\Plugin::INVITE_NORESPONSE:
$writer->writeElement($cs.'invite-noresponse');
break;
case DAV\Sharing\Plugin::INVITE_INVALID :
$writer->writeElement($cs . 'invite-invalid');
case DAV\Sharing\Plugin::INVITE_INVALID:
$writer->writeElement($cs.'invite-invalid');
break;
}
$writer->startElement($cs . 'access');
$writer->startElement($cs.'access');
switch ($sharee->access) {
case DAV\Sharing\Plugin::ACCESS_READWRITE :
$writer->writeElement($cs . 'read-write');
case DAV\Sharing\Plugin::ACCESS_READWRITE:
$writer->writeElement($cs.'read-write');
break;
case DAV\Sharing\Plugin::ACCESS_READ :
$writer->writeElement($cs . 'read');
case DAV\Sharing\Plugin::ACCESS_READ:
$writer->writeElement($cs.'read');
break;
}
$writer->endElement(); // access
}
$href = new DAV\Xml\Property\Href($sharee->href);
$href->xmlSerialize($writer);
if (isset($sharee->properties['{DAV:}displayname'])) {
$writer->writeElement($cs . 'common-name', $sharee->properties['{DAV:}displayname']);
$writer->writeElement($cs.'common-name', $sharee->properties['{DAV:}displayname']);
}
if ($sharee->comment) {
$writer->writeElement($cs . 'summary', $sharee->comment);
$writer->writeElement($cs.'summary', $sharee->comment);
}
$writer->endElement(); // organizer or user
}
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Xml\Property;
use Sabre\CalDAV\Plugin;
@ -24,41 +26,39 @@ use Sabre\Xml\Writer;
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://sabre.io/license/ Modified BSD License
*/
class ScheduleCalendarTransp implements Element {
class ScheduleCalendarTransp implements Element
{
const TRANSPARENT = 'transparent';
const OPAQUE = 'opaque';
/**
* value
* value.
*
* @var string
*/
protected $value;
/**
* Creates the property
* Creates the property.
*
* @param string $value
*/
function __construct($value) {
if ($value !== self::TRANSPARENT && $value !== self::OPAQUE) {
public function __construct($value)
{
if (self::TRANSPARENT !== $value && self::OPAQUE !== $value) {
throw new \InvalidArgumentException('The value must either be specified as "transparent" or "opaque"');
}
$this->value = $value;
}
/**
* Returns the current value
* Returns the current value.
*
* @return string
*/
function getValue() {
public function getValue()
{
return $this->value;
}
/**
@ -78,19 +78,17 @@ class ScheduleCalendarTransp implements Element {
* If you are opening new elements, you must also close them again.
*
* @param Writer $writer
* @return void
*/
function xmlSerialize(Writer $writer) {
public function xmlSerialize(Writer $writer)
{
switch ($this->value) {
case self::TRANSPARENT :
$writer->writeElement('{' . Plugin::NS_CALDAV . '}transparent');
case self::TRANSPARENT:
$writer->writeElement('{'.Plugin::NS_CALDAV.'}transparent');
break;
case self::OPAQUE :
$writer->writeElement('{' . Plugin::NS_CALDAV . '}opaque');
case self::OPAQUE:
$writer->writeElement('{'.Plugin::NS_CALDAV.'}opaque');
break;
}
}
/**
@ -112,10 +110,11 @@ class ScheduleCalendarTransp implements Element {
* the next element.
*
* @param Reader $reader
*
* @return mixed
*/
static function xmlDeserialize(Reader $reader) {
public static function xmlDeserialize(Reader $reader)
{
$elems = Deserializer\enum($reader, Plugin::NS_CALDAV);
if (in_array('transparent', $elems)) {
@ -123,8 +122,7 @@ class ScheduleCalendarTransp implements Element {
} else {
$value = self::OPAQUE;
}
return new self($value);
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Xml\Property;
use Sabre\CalDAV\Plugin;
@ -21,8 +23,8 @@ use Sabre\Xml\Writer;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class SupportedCalendarComponentSet implements Element {
class SupportedCalendarComponentSet implements Element
{
/**
* List of supported components.
*
@ -37,21 +39,19 @@ class SupportedCalendarComponentSet implements Element {
*
* @param array $components
*/
function __construct(array $components) {
public function __construct(array $components)
{
$this->components = $components;
}
/**
* Returns the list of supported components
* Returns the list of supported components.
*
* @return array
*/
function getValue() {
public function getValue()
{
return $this->components;
}
/**
@ -71,18 +71,14 @@ class SupportedCalendarComponentSet implements Element {
* If you are opening new elements, you must also close them again.
*
* @param Writer $writer
* @return void
*/
function xmlSerialize(Writer $writer) {
public function xmlSerialize(Writer $writer)
{
foreach ($this->components as $component) {
$writer->startElement('{' . Plugin::NS_CALDAV . '}comp');
$writer->startElement('{'.Plugin::NS_CALDAV.'}comp');
$writer->writeAttributes(['name' => $component]);
$writer->endElement();
}
}
/**
@ -104,16 +100,17 @@ class SupportedCalendarComponentSet implements Element {
* the next element.
*
* @param Reader $reader
*
* @return mixed
*/
static function xmlDeserialize(Reader $reader) {
public static function xmlDeserialize(Reader $reader)
{
$elems = $reader->parseInnerTree();
$components = [];
foreach ((array)$elems as $elem) {
if ($elem['name'] === '{' . Plugin::NS_CALDAV . '}comp') {
foreach ((array) $elems as $elem) {
if ($elem['name'] === '{'.Plugin::NS_CALDAV.'}comp') {
$components[] = $elem['attributes']['name'];
}
}
@ -123,7 +120,5 @@ class SupportedCalendarComponentSet implements Element {
}
return new self($components);
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Xml\Property;
use Sabre\CalDAV\Plugin;
@ -7,7 +9,7 @@ use Sabre\Xml\Writer;
use Sabre\Xml\XmlSerializable;
/**
* Supported-calendar-data property
* Supported-calendar-data property.
*
* This property is a representation of the supported-calendar-data property
* in the CalDAV namespace. SabreDAV only has support for text/calendar;2.0
@ -20,8 +22,8 @@ use Sabre\Xml\XmlSerializable;
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://sabre.io/license/ Modified BSD License
*/
class SupportedCalendarData implements XmlSerializable {
class SupportedCalendarData implements XmlSerializable
{
/**
* The xmlSerialize method is called during xml writing.
*
@ -39,22 +41,19 @@ class SupportedCalendarData implements XmlSerializable {
* If you are opening new elements, you must also close them again.
*
* @param Writer $writer
* @return void
*/
function xmlSerialize(Writer $writer) {
$writer->startElement('{' . Plugin::NS_CALDAV . '}calendar-data');
public function xmlSerialize(Writer $writer)
{
$writer->startElement('{'.Plugin::NS_CALDAV.'}calendar-data');
$writer->writeAttributes([
'content-type' => 'text/calendar',
'version' => '2.0',
'version' => '2.0',
]);
$writer->endElement(); // calendar-data
$writer->startElement('{' . Plugin::NS_CALDAV . '}calendar-data');
$writer->startElement('{'.Plugin::NS_CALDAV.'}calendar-data');
$writer->writeAttributes([
'content-type' => 'application/calendar+json',
]);
$writer->endElement(); // calendar-data
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Xml\Property;
use Sabre\CalDAV\Plugin;
@ -7,7 +9,7 @@ use Sabre\Xml\Writer;
use Sabre\Xml\XmlSerializable;
/**
* supported-collation-set property
* supported-collation-set property.
*
* This property is a representation of the supported-collation-set property
* in the CalDAV namespace.
@ -19,8 +21,8 @@ use Sabre\Xml\XmlSerializable;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class SupportedCollationSet implements XmlSerializable {
class SupportedCollationSet implements XmlSerializable
{
/**
* The xmlSerialize method is called during xml writing.
*
@ -38,20 +40,17 @@ class SupportedCollationSet implements XmlSerializable {
* If you are opening new elements, you must also close them again.
*
* @param Writer $writer
* @return void
*/
function xmlSerialize(Writer $writer) {
public function xmlSerialize(Writer $writer)
{
$collations = [
'i;ascii-casemap',
'i;octet',
'i;unicode-casemap'
'i;unicode-casemap',
];
foreach ($collations as $collation) {
$writer->writeElement('{' . Plugin::NS_CALDAV . '}supported-collation', $collation);
$writer->writeElement('{'.Plugin::NS_CALDAV.'}supported-collation', $collation);
}
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Xml\Request;
use Sabre\CalDAV\Plugin;
@ -19,8 +21,8 @@ use Sabre\Xml\XmlDeserializable;
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://sabre.io/license/ Modified BSD License
*/
class CalendarMultiGetReport implements XmlDeserializable {
class CalendarMultiGetReport implements XmlDeserializable
{
/**
* An array with requested properties.
*
@ -80,36 +82,33 @@ class CalendarMultiGetReport implements XmlDeserializable {
* the next element.
*
* @param Reader $reader
*
* @return mixed
*/
static function xmlDeserialize(Reader $reader) {
public static function xmlDeserialize(Reader $reader)
{
$elems = $reader->parseInnerTree([
'{urn:ietf:params:xml:ns:caldav}calendar-data' => 'Sabre\\CalDAV\\Xml\\Filter\\CalendarData',
'{DAV:}prop' => 'Sabre\\Xml\\Element\\KeyValue',
'{DAV:}prop' => 'Sabre\\Xml\\Element\\KeyValue',
]);
$newProps = [
'hrefs' => [],
'hrefs' => [],
'properties' => [],
];
foreach ($elems as $elem) {
switch ($elem['name']) {
case '{DAV:}prop' :
case '{DAV:}prop':
$newProps['properties'] = array_keys($elem['value']);
if (isset($elem['value']['{' . Plugin::NS_CALDAV . '}calendar-data'])) {
$newProps += $elem['value']['{' . Plugin::NS_CALDAV . '}calendar-data'];
if (isset($elem['value']['{'.Plugin::NS_CALDAV.'}calendar-data'])) {
$newProps += $elem['value']['{'.Plugin::NS_CALDAV.'}calendar-data'];
}
break;
case '{DAV:}href' :
case '{DAV:}href':
$newProps['hrefs'][] = Uri\resolve($reader->contextUri, $elem['value']);
break;
}
}
$obj = new self();
@ -118,7 +117,5 @@ class CalendarMultiGetReport implements XmlDeserializable {
}
return $obj;
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Xml\Request;
use Sabre\CalDAV\Plugin;
@ -19,8 +21,8 @@ use Sabre\Xml\XmlDeserializable;
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://sabre.io/license/ Modified BSD License
*/
class CalendarQueryReport implements XmlDeserializable {
class CalendarQueryReport implements XmlDeserializable
{
/**
* An array with requested properties.
*
@ -80,38 +82,39 @@ class CalendarQueryReport implements XmlDeserializable {
* the next element.
*
* @param Reader $reader
*
* @return mixed
*/
static function xmlDeserialize(Reader $reader) {
public static function xmlDeserialize(Reader $reader)
{
$elems = $reader->parseInnerTree([
'{urn:ietf:params:xml:ns:caldav}comp-filter' => 'Sabre\\CalDAV\\Xml\\Filter\\CompFilter',
'{urn:ietf:params:xml:ns:caldav}prop-filter' => 'Sabre\\CalDAV\\Xml\\Filter\\PropFilter',
'{urn:ietf:params:xml:ns:caldav}param-filter' => 'Sabre\\CalDAV\\Xml\\Filter\\ParamFilter',
'{urn:ietf:params:xml:ns:caldav}comp-filter' => 'Sabre\\CalDAV\\Xml\\Filter\\CompFilter',
'{urn:ietf:params:xml:ns:caldav}prop-filter' => 'Sabre\\CalDAV\\Xml\\Filter\\PropFilter',
'{urn:ietf:params:xml:ns:caldav}param-filter' => 'Sabre\\CalDAV\\Xml\\Filter\\ParamFilter',
'{urn:ietf:params:xml:ns:caldav}calendar-data' => 'Sabre\\CalDAV\\Xml\\Filter\\CalendarData',
'{DAV:}prop' => 'Sabre\\Xml\\Element\\KeyValue',
'{DAV:}prop' => 'Sabre\\Xml\\Element\\KeyValue',
]);
$newProps = [
'filters' => null,
'filters' => null,
'properties' => [],
];
if (!is_array($elems)) $elems = [];
if (!is_array($elems)) {
$elems = [];
}
foreach ($elems as $elem) {
switch ($elem['name']) {
case '{DAV:}prop' :
case '{DAV:}prop':
$newProps['properties'] = array_keys($elem['value']);
if (isset($elem['value']['{' . Plugin::NS_CALDAV . '}calendar-data'])) {
$newProps += $elem['value']['{' . Plugin::NS_CALDAV . '}calendar-data'];
if (isset($elem['value']['{'.Plugin::NS_CALDAV.'}calendar-data'])) {
$newProps += $elem['value']['{'.Plugin::NS_CALDAV.'}calendar-data'];
}
break;
case '{' . Plugin::NS_CALDAV . '}filter' :
case '{'.Plugin::NS_CALDAV.'}filter':
foreach ($elem['value'] as $subElem) {
if ($subElem['name'] === '{' . Plugin::NS_CALDAV . '}comp-filter') {
if ($subElem['name'] === '{'.Plugin::NS_CALDAV.'}comp-filter') {
if (!is_null($newProps['filters'])) {
throw new BadRequest('Only one top-level comp-filter may be defined');
}
@ -119,21 +122,18 @@ class CalendarQueryReport implements XmlDeserializable {
}
}
break;
}
}
if (is_null($newProps['filters'])) {
throw new BadRequest('The {' . Plugin::NS_CALDAV . '}filter element is required for this request');
throw new BadRequest('The {'.Plugin::NS_CALDAV.'}filter element is required for this request');
}
$obj = new self();
foreach ($newProps as $key => $value) {
$obj->$key = $value;
}
return $obj;
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Xml\Request;
use Sabre\CalDAV\Plugin;
@ -9,7 +11,7 @@ use Sabre\Xml\Reader;
use Sabre\Xml\XmlDeserializable;
/**
* FreeBusyQueryReport
* FreeBusyQueryReport.
*
* This class parses the {DAV:}free-busy-query REPORT, as defined in:
*
@ -19,19 +21,19 @@ use Sabre\Xml\XmlDeserializable;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class FreeBusyQueryReport implements XmlDeserializable {
class FreeBusyQueryReport implements XmlDeserializable
{
/**
* Starttime of report
* Starttime of report.
*
* @var DateTime|null
* @var \DateTime|null
*/
public $start;
/**
* End time of report
* End time of report.
*
* @var DateTime|null
* @var \DateTime|null
*/
public $end;
@ -54,22 +56,23 @@ class FreeBusyQueryReport implements XmlDeserializable {
* the next element.
*
* @param Reader $reader
*
* @return mixed
*/
static function xmlDeserialize(Reader $reader) {
$timeRange = '{' . Plugin::NS_CALDAV . '}time-range';
public static function xmlDeserialize(Reader $reader)
{
$timeRange = '{'.Plugin::NS_CALDAV.'}time-range';
$start = null;
$end = null;
foreach ((array)$reader->parseInnerTree([]) as $elem) {
if ($elem['name'] !== $timeRange) continue;
foreach ((array) $reader->parseInnerTree([]) as $elem) {
if ($elem['name'] !== $timeRange) {
continue;
}
$start = empty($elem['attributes']['start']) ?: $elem['attributes']['start'];
$end = empty($elem['attributes']['end']) ?: $elem['attributes']['end'];
}
if (!$start && !$end) {
throw new BadRequest('The freebusy report must have a time-range element');
@ -85,7 +88,5 @@ class FreeBusyQueryReport implements XmlDeserializable {
$result->end = $end;
return $result;
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Xml\Request;
use Sabre\CalDAV\Plugin;
@ -11,7 +13,7 @@ use Sabre\Xml\Reader;
use Sabre\Xml\XmlDeserializable;
/**
* Invite-reply POST request parser
* Invite-reply POST request parser.
*
* This class parses the invite-reply POST request, as defined in:
*
@ -21,8 +23,8 @@ use Sabre\Xml\XmlDeserializable;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class InviteReply implements XmlDeserializable {
class InviteReply implements XmlDeserializable
{
/**
* The sharee calendar user address.
*
@ -40,14 +42,14 @@ class InviteReply implements XmlDeserializable {
public $calendarUri;
/**
* The id of the invite message that's being responded to
* The id of the invite message that's being responded to.
*
* @var string
*/
public $inReplyTo;
/**
* An optional message
* An optional message.
*
* @var string
*/
@ -61,22 +63,21 @@ class InviteReply implements XmlDeserializable {
public $status;
/**
* Constructor
* Constructor.
*
* @param string $href
* @param string $calendarUri
* @param string $inReplyTo
* @param string $summary
* @param int $status
* @param int $status
*/
function __construct($href, $calendarUri, $inReplyTo, $summary, $status) {
public function __construct($href, $calendarUri, $inReplyTo, $summary, $status)
{
$this->href = $href;
$this->calendarUri = $calendarUri;
$this->inReplyTo = $inReplyTo;
$this->summary = $summary;
$this->status = $status;
}
/**
@ -98,10 +99,11 @@ class InviteReply implements XmlDeserializable {
* the next element.
*
* @param Reader $reader
*
* @return mixed
*/
static function xmlDeserialize(Reader $reader) {
public static function xmlDeserialize(Reader $reader)
{
$elems = KeyValue::xmlDeserialize($reader);
$href = null;
@ -111,40 +113,35 @@ class InviteReply implements XmlDeserializable {
$status = null;
foreach ($elems as $name => $value) {
switch ($name) {
case '{' . Plugin::NS_CALENDARSERVER . '}hosturl' :
case '{'.Plugin::NS_CALENDARSERVER.'}hosturl':
foreach ($value as $bla) {
if ($bla['name'] === '{DAV:}href') {
if ('{DAV:}href' === $bla['name']) {
$calendarUri = $bla['value'];
}
}
break;
case '{' . Plugin::NS_CALENDARSERVER . '}invite-accepted' :
case '{'.Plugin::NS_CALENDARSERVER.'}invite-accepted':
$status = DAV\Sharing\Plugin::INVITE_ACCEPTED;
break;
case '{' . Plugin::NS_CALENDARSERVER . '}invite-declined' :
case '{'.Plugin::NS_CALENDARSERVER.'}invite-declined':
$status = DAV\Sharing\Plugin::INVITE_DECLINED;
break;
case '{' . Plugin::NS_CALENDARSERVER . '}in-reply-to' :
case '{'.Plugin::NS_CALENDARSERVER.'}in-reply-to':
$inReplyTo = $value;
break;
case '{' . Plugin::NS_CALENDARSERVER . '}summary' :
case '{'.Plugin::NS_CALENDARSERVER.'}summary':
$summary = $value;
break;
case '{DAV:}href' :
case '{DAV:}href':
$href = $value;
break;
}
}
if (is_null($calendarUri)) {
throw new BadRequest('The {http://calendarserver.org/ns/}hosturl/{DAV:}href element must exist');
}
return new self($href, $calendarUri, $inReplyTo, $summary, $status);
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Xml\Request;
use Sabre\Xml\Reader;
@ -16,8 +18,8 @@ use Sabre\Xml\XmlDeserializable;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class MkCalendar implements XmlDeserializable {
class MkCalendar implements XmlDeserializable
{
/**
* The list of properties that will be set.
*
@ -30,10 +32,9 @@ class MkCalendar implements XmlDeserializable {
*
* @return array
*/
function getProperties() {
public function getProperties()
{
return $this->properties;
}
/**
@ -55,10 +56,11 @@ class MkCalendar implements XmlDeserializable {
* the next element.
*
* @param Reader $reader
*
* @return mixed
*/
static function xmlDeserialize(Reader $reader) {
public static function xmlDeserialize(Reader $reader)
{
$self = new self();
$elementMap = $reader->elementMap;
@ -67,13 +69,11 @@ class MkCalendar implements XmlDeserializable {
$elems = $reader->parseInnerTree($elementMap);
foreach ($elems as $elem) {
if ($elem['name'] === '{DAV:}set') {
if ('{DAV:}set' === $elem['name']) {
$self->properties = array_merge($self->properties, $elem['value']['{DAV:}prop']);
}
}
return $self;
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CalDAV\Xml\Request;
use Sabre\CalDAV\Plugin;
@ -8,7 +10,7 @@ use Sabre\Xml\Reader;
use Sabre\Xml\XmlDeserializable;
/**
* Share POST request parser
* Share POST request parser.
*
* This class parses the share POST request, as defined in:
*
@ -18,8 +20,8 @@ use Sabre\Xml\XmlDeserializable;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class Share implements XmlDeserializable {
class Share implements XmlDeserializable
{
/**
* The list of new people added or updated or removed from the share.
*
@ -28,14 +30,13 @@ class Share implements XmlDeserializable {
public $sharees = [];
/**
* Constructor
* Constructor.
*
* @param Sharee[] $sharees
*/
function __construct(array $sharees) {
public function __construct(array $sharees)
{
$this->sharees = $sharees;
}
/**
@ -57,55 +58,52 @@ class Share implements XmlDeserializable {
* the next element.
*
* @param Reader $reader
*
* @return mixed
*/
static function xmlDeserialize(Reader $reader) {
public static function xmlDeserialize(Reader $reader)
{
$elems = $reader->parseGetElements([
'{' . Plugin::NS_CALENDARSERVER . '}set' => 'Sabre\\Xml\\Element\\KeyValue',
'{' . Plugin::NS_CALENDARSERVER . '}remove' => 'Sabre\\Xml\\Element\\KeyValue',
'{'.Plugin::NS_CALENDARSERVER.'}set' => 'Sabre\\Xml\\Element\\KeyValue',
'{'.Plugin::NS_CALENDARSERVER.'}remove' => 'Sabre\\Xml\\Element\\KeyValue',
]);
$sharees = [];
foreach ($elems as $elem) {
switch ($elem['name']) {
case '{' . Plugin::NS_CALENDARSERVER . '}set' :
case '{'.Plugin::NS_CALENDARSERVER.'}set':
$sharee = $elem['value'];
$sumElem = '{' . Plugin::NS_CALENDARSERVER . '}summary';
$commonName = '{' . Plugin::NS_CALENDARSERVER . '}common-name';
$sumElem = '{'.Plugin::NS_CALENDARSERVER.'}summary';
$commonName = '{'.Plugin::NS_CALENDARSERVER.'}common-name';
$properties = [];
if (isset($sharee[$commonName])) {
$properties['{DAV:}displayname'] = $sharee[$commonName];
}
$access = array_key_exists('{' . Plugin::NS_CALENDARSERVER . '}read-write', $sharee)
$access = array_key_exists('{'.Plugin::NS_CALENDARSERVER.'}read-write', $sharee)
? \Sabre\DAV\Sharing\Plugin::ACCESS_READWRITE
: \Sabre\DAV\Sharing\Plugin::ACCESS_READ;
$sharees[] = new Sharee([
'href' => $sharee['{DAV:}href'],
'href' => $sharee['{DAV:}href'],
'properties' => $properties,
'access' => $access,
'comment' => isset($sharee[$sumElem]) ? $sharee[$sumElem] : null
'access' => $access,
'comment' => isset($sharee[$sumElem]) ? $sharee[$sumElem] : null,
]);
break;
case '{' . Plugin::NS_CALENDARSERVER . '}remove' :
case '{'.Plugin::NS_CALENDARSERVER.'}remove':
$sharees[] = new Sharee([
'href' => $elem['value']['{DAV:}href'],
'access' => \Sabre\DAV\Sharing\Plugin::ACCESS_NOACCESS
'href' => $elem['value']['{DAV:}href'],
'access' => \Sabre\DAV\Sharing\Plugin::ACCESS_NOACCESS,
]);
break;
}
}
return new self($sharees);
}
}

View file

@ -1,12 +1,14 @@
<?php
declare(strict_types=1);
namespace Sabre\CardDAV;
use Sabre\DAV;
use Sabre\DAVACL;
/**
* The AddressBook class represents a CardDAV addressbook, owned by a specific user
* The AddressBook class represents a CardDAV addressbook, owned by a specific user.
*
* The AddressBook can contain multiple vcards
*
@ -14,77 +16,78 @@ use Sabre\DAVACL;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class AddressBook extends DAV\Collection implements IAddressBook, DAV\IProperties, DAVACL\IACL, DAV\Sync\ISyncCollection, DAV\IMultiGet {
class AddressBook extends DAV\Collection implements IAddressBook, DAV\IProperties, DAVACL\IACL, DAV\Sync\ISyncCollection, DAV\IMultiGet
{
use DAVACL\ACLTrait;
/**
* This is an array with addressbook information
* This is an array with addressbook information.
*
* @var array
*/
protected $addressBookInfo;
/**
* CardDAV backend
* CardDAV backend.
*
* @var Backend\BackendInterface
*/
protected $carddavBackend;
/**
* Constructor
* Constructor.
*
* @param Backend\BackendInterface $carddavBackend
* @param array $addressBookInfo
* @param array $addressBookInfo
*/
function __construct(Backend\BackendInterface $carddavBackend, array $addressBookInfo) {
public function __construct(Backend\BackendInterface $carddavBackend, array $addressBookInfo)
{
$this->carddavBackend = $carddavBackend;
$this->addressBookInfo = $addressBookInfo;
}
/**
* Returns the name of the addressbook
* Returns the name of the addressbook.
*
* @return string
*/
function getName() {
public function getName()
{
return $this->addressBookInfo['uri'];
}
/**
* Returns a card
* Returns a card.
*
* @param string $name
*
* @return Card
*/
function getChild($name) {
public function getChild($name)
{
$obj = $this->carddavBackend->getCard($this->addressBookInfo['id'], $name);
if (!$obj) throw new DAV\Exception\NotFound('Card not found');
return new Card($this->carddavBackend, $this->addressBookInfo, $obj);
if (!$obj) {
throw new DAV\Exception\NotFound('Card not found');
}
return new Card($this->carddavBackend, $this->addressBookInfo, $obj);
}
/**
* Returns the full list of cards
* Returns the full list of cards.
*
* @return array
*/
function getChildren() {
public function getChildren()
{
$objs = $this->carddavBackend->getCards($this->addressBookInfo['id']);
$children = [];
foreach ($objs as $obj) {
$obj['acl'] = $this->getChildACL();
$children[] = new Card($this->carddavBackend, $this->addressBookInfo, $obj);
}
return $children;
return $children;
}
/**
@ -94,47 +97,47 @@ class AddressBook extends DAV\Collection implements IAddressBook, DAV\IPropertie
* If any children are not found, you do not have to return them.
*
* @param string[] $paths
*
* @return array
*/
function getMultipleChildren(array $paths) {
public function getMultipleChildren(array $paths)
{
$objs = $this->carddavBackend->getMultipleCards($this->addressBookInfo['id'], $paths);
$children = [];
foreach ($objs as $obj) {
$obj['acl'] = $this->getChildACL();
$children[] = new Card($this->carddavBackend, $this->addressBookInfo, $obj);
}
return $children;
return $children;
}
/**
* Creates a new directory
* Creates a new directory.
*
* We actually block this, as subdirectories are not allowed in addressbooks.
*
* @param string $name
* @return void
*/
function createDirectory($name) {
public function createDirectory($name)
{
throw new DAV\Exception\MethodNotAllowed('Creating collections in addressbooks is not allowed');
}
/**
* Creates a new file
* Creates a new file.
*
* The contents of the new file must be a valid VCARD.
*
* This method may return an ETag.
*
* @param string $name
* @param string $name
* @param resource $vcardData
*
* @return string|null
*/
function createFile($name, $vcardData = null) {
public function createFile($name, $vcardData = null)
{
if (is_resource($vcardData)) {
$vcardData = stream_get_contents($vcardData);
}
@ -142,41 +145,32 @@ class AddressBook extends DAV\Collection implements IAddressBook, DAV\IPropertie
$vcardData = DAV\StringUtil::ensureUTF8($vcardData);
return $this->carddavBackend->createCard($this->addressBookInfo['id'], $name, $vcardData);
}
/**
* Deletes the entire addressbook.
*
* @return void
*/
function delete() {
public function delete()
{
$this->carddavBackend->deleteAddressBook($this->addressBookInfo['id']);
}
/**
* Renames the addressbook
* Renames the addressbook.
*
* @param string $newName
* @return void
*/
function setName($newName) {
public function setName($newName)
{
throw new DAV\Exception\MethodNotAllowed('Renaming addressbooks is not yet supported');
}
/**
* Returns the last modification date as a unix timestamp.
*
* @return void
*/
function getLastModified() {
public function getLastModified()
{
return null;
}
/**
@ -189,12 +183,10 @@ class AddressBook extends DAV\Collection implements IAddressBook, DAV\IPropertie
* Read the PropPatch documentation for more information.
*
* @param DAV\PropPatch $propPatch
* @return void
*/
function propPatch(DAV\PropPatch $propPatch) {
public function propPatch(DAV\PropPatch $propPatch)
{
return $this->carddavBackend->updateAddressBook($this->addressBookInfo['id'], $propPatch);
}
/**
@ -206,39 +198,33 @@ class AddressBook extends DAV\Collection implements IAddressBook, DAV\IPropertie
* If the array is empty, it means 'all properties' were requested.
*
* @param array $properties
*
* @return array
*/
function getProperties($properties) {
public function getProperties($properties)
{
$response = [];
foreach ($properties as $propertyName) {
if (isset($this->addressBookInfo[$propertyName])) {
$response[$propertyName] = $this->addressBookInfo[$propertyName];
}
}
return $response;
}
/**
* Returns the owner principal
* Returns the owner principal.
*
* This must be a url to a principal, or null if there's no owner
*
* @return string|null
*/
function getOwner() {
public function getOwner()
{
return $this->addressBookInfo['principaluri'];
}
/**
* This method returns the ACL's for card nodes in this address book.
* The result of this method automatically gets passed to the
@ -246,8 +232,8 @@ class AddressBook extends DAV\Collection implements IAddressBook, DAV\IPropertie
*
* @return array
*/
function getChildACL() {
public function getChildACL()
{
return [
[
'privilege' => '{DAV:}all',
@ -255,10 +241,8 @@ class AddressBook extends DAV\Collection implements IAddressBook, DAV\IPropertie
'protected' => true,
],
];
}
/**
* This method returns the current sync-token for this collection.
* This can be any string.
@ -268,8 +252,8 @@ class AddressBook extends DAV\Collection implements IAddressBook, DAV\IPropertie
*
* @return string|null
*/
function getSyncToken() {
public function getSyncToken()
{
if (
$this->carddavBackend instanceof Backend\SyncSupport &&
isset($this->addressBookInfo['{DAV:}sync-token'])
@ -282,7 +266,6 @@ class AddressBook extends DAV\Collection implements IAddressBook, DAV\IPropertie
) {
return $this->addressBookInfo['{http://sabredav.org/ns}sync-token'];
}
}
/**
@ -336,12 +319,13 @@ class AddressBook extends DAV\Collection implements IAddressBook, DAV\IPropertie
* The limit is 'suggestive'. You are free to ignore it.
*
* @param string $syncToken
* @param int $syncLevel
* @param int $limit
* @param int $syncLevel
* @param int $limit
*
* @return array
*/
function getChanges($syncToken, $syncLevel, $limit = null) {
public function getChanges($syncToken, $syncLevel, $limit = null)
{
if (!$this->carddavBackend instanceof Backend\SyncSupport) {
return null;
}
@ -352,6 +336,5 @@ class AddressBook extends DAV\Collection implements IAddressBook, DAV\IPropertie
$syncLevel,
$limit
);
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CardDAV;
use Sabre\DAV;
@ -8,7 +10,7 @@ use Sabre\DAVACL;
use Sabre\Uri;
/**
* AddressBook Home class
* AddressBook Home class.
*
* This collection contains a list of addressbooks associated with one user.
*
@ -16,81 +18,74 @@ use Sabre\Uri;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class AddressBookHome extends DAV\Collection implements DAV\IExtendedCollection, DAVACL\IACL {
class AddressBookHome extends DAV\Collection implements DAV\IExtendedCollection, DAVACL\IACL
{
use DAVACL\ACLTrait;
/**
* Principal uri
* Principal uri.
*
* @var array
*/
protected $principalUri;
/**
* carddavBackend
* carddavBackend.
*
* @var Backend\BackendInterface
*/
protected $carddavBackend;
/**
* Constructor
* Constructor.
*
* @param Backend\BackendInterface $carddavBackend
* @param string $principalUri
* @param string $principalUri
*/
function __construct(Backend\BackendInterface $carddavBackend, $principalUri) {
public function __construct(Backend\BackendInterface $carddavBackend, $principalUri)
{
$this->carddavBackend = $carddavBackend;
$this->principalUri = $principalUri;
}
/**
* Returns the name of this object
* Returns the name of this object.
*
* @return string
*/
function getName() {
public function getName()
{
list(, $name) = Uri\split($this->principalUri);
return $name;
return $name;
}
/**
* Updates the name of this object
* Updates the name of this object.
*
* @param string $name
* @return void
*/
function setName($name) {
public function setName($name)
{
throw new DAV\Exception\MethodNotAllowed();
}
/**
* Deletes this object
*
* @return void
* Deletes this object.
*/
function delete() {
public function delete()
{
throw new DAV\Exception\MethodNotAllowed();
}
/**
* Returns the last modification date
* Returns the last modification date.
*
* @return int
*/
function getLastModified() {
public function getLastModified()
{
return null;
}
/**
@ -98,14 +93,12 @@ class AddressBookHome extends DAV\Collection implements DAV\IExtendedCollection,
*
* This is currently not allowed
*
* @param string $filename
* @param string $filename
* @param resource $data
* @return void
*/
function createFile($filename, $data = null) {
public function createFile($filename, $data = null)
{
throw new DAV\Exception\MethodNotAllowed('Creating new files in this collection is not supported');
}
/**
@ -114,78 +107,74 @@ class AddressBookHome extends DAV\Collection implements DAV\IExtendedCollection,
* This is currently not allowed.
*
* @param string $filename
* @return void
*/
function createDirectory($filename) {
public function createDirectory($filename)
{
throw new DAV\Exception\MethodNotAllowed('Creating new collections in this collection is not supported');
}
/**
* Returns a single addressbook, by name
* Returns a single addressbook, by name.
*
* @param string $name
*
* @todo needs optimizing
*
* @return AddressBook
*/
function getChild($name) {
public function getChild($name)
{
foreach ($this->getChildren() as $child) {
if ($name == $child->getName())
if ($name == $child->getName()) {
return $child;
}
}
throw new DAV\Exception\NotFound('Addressbook with name \'' . $name . '\' could not be found');
throw new DAV\Exception\NotFound('Addressbook with name \''.$name.'\' could not be found');
}
/**
* Returns a list of addressbooks
* Returns a list of addressbooks.
*
* @return array
*/
function getChildren() {
public function getChildren()
{
$addressbooks = $this->carddavBackend->getAddressBooksForUser($this->principalUri);
$objs = [];
foreach ($addressbooks as $addressbook) {
$objs[] = new AddressBook($this->carddavBackend, $addressbook);
}
return $objs;
return $objs;
}
/**
* Creates a new address book.
*
* @param string $name
* @param MkCol $mkCol
* @param MkCol $mkCol
*
* @throws DAV\Exception\InvalidResourceType
* @return void
*/
function createExtendedCollection($name, MkCol $mkCol) {
if (!$mkCol->hasResourceType('{' . Plugin::NS_CARDDAV . '}addressbook')) {
public function createExtendedCollection($name, MkCol $mkCol)
{
if (!$mkCol->hasResourceType('{'.Plugin::NS_CARDDAV.'}addressbook')) {
throw new DAV\Exception\InvalidResourceType('Unknown resourceType for this collection');
}
$properties = $mkCol->getRemainingValues();
$mkCol->setRemainingResultCode(201);
$this->carddavBackend->createAddressBook($this->principalUri, $name, $properties);
}
/**
* Returns the owner principal
* Returns the owner principal.
*
* This must be a url to a principal, or null if there's no owner
*
* @return string|null
*/
function getOwner() {
public function getOwner()
{
return $this->principalUri;
}
}

View file

@ -1,11 +1,13 @@
<?php
declare(strict_types=1);
namespace Sabre\CardDAV;
use Sabre\DAVACL;
/**
* AddressBook rootnode
* AddressBook rootnode.
*
* This object lists a collection of users, which can contain addressbooks.
*
@ -13,24 +15,24 @@ use Sabre\DAVACL;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class AddressBookRoot extends DAVACL\AbstractPrincipalCollection {
class AddressBookRoot extends DAVACL\AbstractPrincipalCollection
{
/**
* Principal Backend
* Principal Backend.
*
* @var DAVACL\PrincipalBackend\BackendInterface
*/
protected $principalBackend;
/**
* CardDAV backend
* CardDAV backend.
*
* @var Backend\BackendInterface
*/
protected $carddavBackend;
/**
* Constructor
* Constructor.
*
* This constructor needs both a principal and a carddav backend.
*
@ -40,25 +42,23 @@ class AddressBookRoot extends DAVACL\AbstractPrincipalCollection {
* to override this.
*
* @param DAVACL\PrincipalBackend\BackendInterface $principalBackend
* @param Backend\BackendInterface $carddavBackend
* @param string $principalPrefix
* @param Backend\BackendInterface $carddavBackend
* @param string $principalPrefix
*/
function __construct(DAVACL\PrincipalBackend\BackendInterface $principalBackend, Backend\BackendInterface $carddavBackend, $principalPrefix = 'principals') {
public function __construct(DAVACL\PrincipalBackend\BackendInterface $principalBackend, Backend\BackendInterface $carddavBackend, $principalPrefix = 'principals')
{
$this->carddavBackend = $carddavBackend;
parent::__construct($principalBackend, $principalPrefix);
}
/**
* Returns the name of the node
* Returns the name of the node.
*
* @return string
*/
function getName() {
public function getName()
{
return Plugin::ADDRESSBOOK_ROOT;
}
/**
@ -69,12 +69,11 @@ class AddressBookRoot extends DAVACL\AbstractPrincipalCollection {
* supplied by the authentication backend.
*
* @param array $principal
*
* @return \Sabre\DAV\INode
*/
function getChildForPrincipal(array $principal) {
public function getChildForPrincipal(array $principal)
{
return new AddressBookHome($this->carddavBackend, $principal['uri']);
}
}

View file

@ -1,9 +1,11 @@
<?php
declare(strict_types=1);
namespace Sabre\CardDAV\Backend;
/**
* CardDAV abstract Backend
* CardDAV abstract Backend.
*
* This class serves as a base-class for addressbook backends
*
@ -13,8 +15,8 @@ namespace Sabre\CardDAV\Backend;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
abstract class AbstractBackend implements BackendInterface {
abstract class AbstractBackend implements BackendInterface
{
/**
* Returns a list of cards.
*
@ -25,14 +27,13 @@ abstract class AbstractBackend implements BackendInterface {
*
* @param mixed $addressBookId
* @param array $uris
*
* @return array
*/
function getMultipleCards($addressBookId, array $uris) {
return array_map(function($uri) use ($addressBookId) {
public function getMultipleCards($addressBookId, array $uris)
{
return array_map(function ($uri) use ($addressBookId) {
return $this->getCard($addressBookId, $uri);
}, $uris);
}
}

View file

@ -1,9 +1,11 @@
<?php
declare(strict_types=1);
namespace Sabre\CardDAV\Backend;
/**
* CardDAV Backend Interface
* CardDAV Backend Interface.
*
* Any CardDAV backend must implement this interface.
*
@ -15,8 +17,8 @@ namespace Sabre\CardDAV\Backend;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
interface BackendInterface {
interface BackendInterface
{
/**
* Returns the list of addressbooks for a specific user.
*
@ -32,9 +34,10 @@ interface BackendInterface {
* {http://calendarserver.org/ns/}getctag
*
* @param string $principalUri
*
* @return array
*/
function getAddressBooksForUser($principalUri);
public function getAddressBooksForUser($principalUri);
/**
* Updates properties for an address book.
@ -48,11 +51,10 @@ interface BackendInterface {
*
* Read the PropPatch documentation for more info and examples.
*
* @param string $addressBookId
* @param string $addressBookId
* @param \Sabre\DAV\PropPatch $propPatch
* @return void
*/
function updateAddressBook($addressBookId, \Sabre\DAV\PropPatch $propPatch);
public function updateAddressBook($addressBookId, \Sabre\DAV\PropPatch $propPatch);
/**
* Creates a new address book.
@ -61,19 +63,19 @@ interface BackendInterface {
* in any format, including ints, strings, arrays or objects.
*
* @param string $principalUri
* @param string $url Just the 'basename' of the url.
* @param array $properties
* @param string $url just the 'basename' of the url
* @param array $properties
*
* @return mixed
*/
function createAddressBook($principalUri, $url, array $properties);
public function createAddressBook($principalUri, $url, array $properties);
/**
* Deletes an entire addressbook and all its contents
* Deletes an entire addressbook and all its contents.
*
* @param mixed $addressBookId
* @return void
*/
function deleteAddressBook($addressBookId);
public function deleteAddressBook($addressBookId);
/**
* Returns all cards for a specific addressbook id.
@ -92,9 +94,10 @@ interface BackendInterface {
* This may speed up certain requests, especially with large cards.
*
* @param mixed $addressbookId
*
* @return array
*/
function getCards($addressbookId);
public function getCards($addressbookId);
/**
* Returns a specfic card.
@ -104,11 +107,12 @@ interface BackendInterface {
*
* If the card does not exist, you must return false.
*
* @param mixed $addressBookId
* @param mixed $addressBookId
* @param string $cardUri
*
* @return array
*/
function getCard($addressBookId, $cardUri);
public function getCard($addressBookId, $cardUri);
/**
* Returns a list of cards.
@ -120,9 +124,10 @@ interface BackendInterface {
*
* @param mixed $addressBookId
* @param array $uris
*
* @return array
*/
function getMultipleCards($addressBookId, array $uris);
public function getMultipleCards($addressBookId, array $uris);
/**
* Creates a new card.
@ -144,12 +149,13 @@ interface BackendInterface {
*
* If you don't return an ETag, you can just return null.
*
* @param mixed $addressBookId
* @param mixed $addressBookId
* @param string $cardUri
* @param string $cardData
*
* @return string|null
*/
function createCard($addressBookId, $cardUri, $cardData);
public function createCard($addressBookId, $cardUri, $cardData);
/**
* Updates a card.
@ -171,20 +177,21 @@ interface BackendInterface {
*
* If you don't return an ETag, you can just return null.
*
* @param mixed $addressBookId
* @param mixed $addressBookId
* @param string $cardUri
* @param string $cardData
*
* @return string|null
*/
function updateCard($addressBookId, $cardUri, $cardData);
public function updateCard($addressBookId, $cardUri, $cardData);
/**
* Deletes a card
* Deletes a card.
*
* @param mixed $addressBookId
* @param mixed $addressBookId
* @param string $cardUri
*
* @return bool
*/
function deleteCard($addressBookId, $cardUri);
public function deleteCard($addressBookId, $cardUri);
}

View file

@ -1,12 +1,14 @@
<?php
declare(strict_types=1);
namespace Sabre\CardDAV\Backend;
use Sabre\CardDAV;
use Sabre\DAV;
/**
* PDO CardDAV backend
* PDO CardDAV backend.
*
* This CardDAV backend uses PDO to store addressbooks
*
@ -14,22 +16,22 @@ use Sabre\DAV;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class PDO extends AbstractBackend implements SyncSupport {
class PDO extends AbstractBackend implements SyncSupport
{
/**
* PDO connection
* PDO connection.
*
* @var PDO
*/
protected $pdo;
/**
* The PDO table name used to store addressbooks
* The PDO table name used to store addressbooks.
*/
public $addressBooksTableName = 'addressbooks';
/**
* The PDO table name used to store cards
* The PDO table name used to store cards.
*/
public $cardsTableName = 'cards';
@ -41,48 +43,44 @@ class PDO extends AbstractBackend implements SyncSupport {
public $addressBookChangesTableName = 'addressbookchanges';
/**
* Sets up the object
* Sets up the object.
*
* @param \PDO $pdo
*/
function __construct(\PDO $pdo) {
public function __construct(\PDO $pdo)
{
$this->pdo = $pdo;
}
/**
* Returns the list of addressbooks for a specific user.
*
* @param string $principalUri
*
* @return array
*/
function getAddressBooksForUser($principalUri) {
$stmt = $this->pdo->prepare('SELECT id, uri, displayname, principaluri, description, synctoken FROM ' . $this->addressBooksTableName . ' WHERE principaluri = ?');
public function getAddressBooksForUser($principalUri)
{
$stmt = $this->pdo->prepare('SELECT id, uri, displayname, principaluri, description, synctoken FROM '.$this->addressBooksTableName.' WHERE principaluri = ?');
$stmt->execute([$principalUri]);
$addressBooks = [];
foreach ($stmt->fetchAll() as $row) {
$addressBooks[] = [
'id' => $row['id'],
'uri' => $row['uri'],
'principaluri' => $row['principaluri'],
'{DAV:}displayname' => $row['displayname'],
'{' . CardDAV\Plugin::NS_CARDDAV . '}addressbook-description' => $row['description'],
'{http://calendarserver.org/ns/}getctag' => $row['synctoken'],
'{http://sabredav.org/ns}sync-token' => $row['synctoken'] ? $row['synctoken'] : '0',
'id' => $row['id'],
'uri' => $row['uri'],
'principaluri' => $row['principaluri'],
'{DAV:}displayname' => $row['displayname'],
'{'.CardDAV\Plugin::NS_CARDDAV.'}addressbook-description' => $row['description'],
'{http://calendarserver.org/ns/}getctag' => $row['synctoken'],
'{http://sabredav.org/ns}sync-token' => $row['synctoken'] ? $row['synctoken'] : '0',
];
}
return $addressBooks;
}
/**
* Updates properties for an address book.
*
@ -95,32 +93,29 @@ class PDO extends AbstractBackend implements SyncSupport {
*
* Read the PropPatch documentation for more info and examples.
*
* @param string $addressBookId
* @param string $addressBookId
* @param \Sabre\DAV\PropPatch $propPatch
* @return void
*/
function updateAddressBook($addressBookId, \Sabre\DAV\PropPatch $propPatch) {
public function updateAddressBook($addressBookId, \Sabre\DAV\PropPatch $propPatch)
{
$supportedProperties = [
'{DAV:}displayname',
'{' . CardDAV\Plugin::NS_CARDDAV . '}addressbook-description',
'{'.CardDAV\Plugin::NS_CARDDAV.'}addressbook-description',
];
$propPatch->handle($supportedProperties, function($mutations) use ($addressBookId) {
$propPatch->handle($supportedProperties, function ($mutations) use ($addressBookId) {
$updates = [];
foreach ($mutations as $property => $newValue) {
switch ($property) {
case '{DAV:}displayname' :
case '{DAV:}displayname':
$updates['displayname'] = $newValue;
break;
case '{' . CardDAV\Plugin::NS_CARDDAV . '}addressbook-description' :
case '{'.CardDAV\Plugin::NS_CARDDAV.'}addressbook-description':
$updates['description'] = $newValue;
break;
}
}
$query = 'UPDATE ' . $this->addressBooksTableName . ' SET ';
$query = 'UPDATE '.$this->addressBooksTableName.' SET ';
$first = true;
foreach ($updates as $key => $value) {
if ($first) {
@ -128,7 +123,7 @@ class PDO extends AbstractBackend implements SyncSupport {
} else {
$query .= ', ';
}
$query .= ' ' . $key . ' = :' . $key . ' ';
$query .= ' '.$key.' = :'.$key.' ';
}
$query .= ' WHERE id = :addressbookid';
@ -137,72 +132,67 @@ class PDO extends AbstractBackend implements SyncSupport {
$stmt->execute($updates);
$this->addChange($addressBookId, "", 2);
$this->addChange($addressBookId, '', 2);
return true;
});
}
/**
* Creates a new address book
* Creates a new address book.
*
* @param string $principalUri
* @param string $url Just the 'basename' of the url.
* @param array $properties
* @param string $url just the 'basename' of the url
* @param array $properties
*
* @return int Last insert id
*/
function createAddressBook($principalUri, $url, array $properties) {
public function createAddressBook($principalUri, $url, array $properties)
{
$values = [
'displayname' => null,
'description' => null,
'displayname' => null,
'description' => null,
'principaluri' => $principalUri,
'uri' => $url,
'uri' => $url,
];
foreach ($properties as $property => $newValue) {
switch ($property) {
case '{DAV:}displayname' :
case '{DAV:}displayname':
$values['displayname'] = $newValue;
break;
case '{' . CardDAV\Plugin::NS_CARDDAV . '}addressbook-description' :
case '{'.CardDAV\Plugin::NS_CARDDAV.'}addressbook-description':
$values['description'] = $newValue;
break;
default :
throw new DAV\Exception\BadRequest('Unknown property: ' . $property);
default:
throw new DAV\Exception\BadRequest('Unknown property: '.$property);
}
}
$query = 'INSERT INTO ' . $this->addressBooksTableName . ' (uri, displayname, description, principaluri, synctoken) VALUES (:uri, :displayname, :description, :principaluri, 1)';
$query = 'INSERT INTO '.$this->addressBooksTableName.' (uri, displayname, description, principaluri, synctoken) VALUES (:uri, :displayname, :description, :principaluri, 1)';
$stmt = $this->pdo->prepare($query);
$stmt->execute($values);
return $this->pdo->lastInsertId(
$this->addressBooksTableName . '_id_seq'
);
return $this->pdo->lastInsertId(
$this->addressBooksTableName.'_id_seq'
);
}
/**
* Deletes an entire addressbook and all its contents
* Deletes an entire addressbook and all its contents.
*
* @param int $addressBookId
* @return void
*/
function deleteAddressBook($addressBookId) {
$stmt = $this->pdo->prepare('DELETE FROM ' . $this->cardsTableName . ' WHERE addressbookid = ?');
public function deleteAddressBook($addressBookId)
{
$stmt = $this->pdo->prepare('DELETE FROM '.$this->cardsTableName.' WHERE addressbookid = ?');
$stmt->execute([$addressBookId]);
$stmt = $this->pdo->prepare('DELETE FROM ' . $this->addressBooksTableName . ' WHERE id = ?');
$stmt = $this->pdo->prepare('DELETE FROM '.$this->addressBooksTableName.' WHERE id = ?');
$stmt->execute([$addressBookId]);
$stmt = $this->pdo->prepare('DELETE FROM ' . $this->addressBookChangesTableName . ' WHERE addressbookid = ?');
$stmt = $this->pdo->prepare('DELETE FROM '.$this->addressBookChangesTableName.' WHERE addressbookid = ?');
$stmt->execute([$addressBookId]);
}
/**
@ -222,21 +212,22 @@ class PDO extends AbstractBackend implements SyncSupport {
* This may speed up certain requests, especially with large cards.
*
* @param mixed $addressbookId
*
* @return array
*/
function getCards($addressbookId) {
$stmt = $this->pdo->prepare('SELECT id, uri, lastmodified, etag, size FROM ' . $this->cardsTableName . ' WHERE addressbookid = ?');
public function getCards($addressbookId)
{
$stmt = $this->pdo->prepare('SELECT id, uri, lastmodified, etag, size FROM '.$this->cardsTableName.' WHERE addressbookid = ?');
$stmt->execute([$addressbookId]);
$result = [];
while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
$row['etag'] = '"' . $row['etag'] . '"';
$row['lastmodified'] = (int)$row['lastmodified'];
$row['etag'] = '"'.$row['etag'].'"';
$row['lastmodified'] = (int) $row['lastmodified'];
$result[] = $row;
}
return $result;
return $result;
}
/**
@ -247,23 +238,26 @@ class PDO extends AbstractBackend implements SyncSupport {
*
* If the card does not exist, you must return false.
*
* @param mixed $addressBookId
* @param mixed $addressBookId
* @param string $cardUri
*
* @return array
*/
function getCard($addressBookId, $cardUri) {
$stmt = $this->pdo->prepare('SELECT id, carddata, uri, lastmodified, etag, size FROM ' . $this->cardsTableName . ' WHERE addressbookid = ? AND uri = ? LIMIT 1');
public function getCard($addressBookId, $cardUri)
{
$stmt = $this->pdo->prepare('SELECT id, carddata, uri, lastmodified, etag, size FROM '.$this->cardsTableName.' WHERE addressbookid = ? AND uri = ? LIMIT 1');
$stmt->execute([$addressBookId, $cardUri]);
$result = $stmt->fetch(\PDO::FETCH_ASSOC);
if (!$result) return false;
if (!$result) {
return false;
}
$result['etag'] = '"'.$result['etag'].'"';
$result['lastmodified'] = (int) $result['lastmodified'];
$result['etag'] = '"' . $result['etag'] . '"';
$result['lastmodified'] = (int)$result['lastmodified'];
return $result;
}
/**
@ -276,11 +270,12 @@ class PDO extends AbstractBackend implements SyncSupport {
*
* @param mixed $addressBookId
* @param array $uris
*
* @return array
*/
function getMultipleCards($addressBookId, array $uris) {
$query = 'SELECT id, uri, lastmodified, etag, size, carddata FROM ' . $this->cardsTableName . ' WHERE addressbookid = ? AND uri IN (';
public function getMultipleCards($addressBookId, array $uris)
{
$query = 'SELECT id, uri, lastmodified, etag, size, carddata FROM '.$this->cardsTableName.' WHERE addressbookid = ? AND uri IN (';
// Inserting a whole bunch of question marks
$query .= implode(',', array_fill(0, count($uris), '?'));
$query .= ')';
@ -289,12 +284,12 @@ class PDO extends AbstractBackend implements SyncSupport {
$stmt->execute(array_merge([$addressBookId], $uris));
$result = [];
while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
$row['etag'] = '"' . $row['etag'] . '"';
$row['lastmodified'] = (int)$row['lastmodified'];
$row['etag'] = '"'.$row['etag'].'"';
$row['lastmodified'] = (int) $row['lastmodified'];
$result[] = $row;
}
return $result;
return $result;
}
/**
@ -317,14 +312,15 @@ class PDO extends AbstractBackend implements SyncSupport {
*
* If you don't return an ETag, you can just return null.
*
* @param mixed $addressBookId
* @param mixed $addressBookId
* @param string $cardUri
* @param string $cardData
*
* @return string|null
*/
function createCard($addressBookId, $cardUri, $cardData) {
$stmt = $this->pdo->prepare('INSERT INTO ' . $this->cardsTableName . ' (carddata, uri, lastmodified, addressbookid, size, etag) VALUES (?, ?, ?, ?, ?, ?)');
public function createCard($addressBookId, $cardUri, $cardData)
{
$stmt = $this->pdo->prepare('INSERT INTO '.$this->cardsTableName.' (carddata, uri, lastmodified, addressbookid, size, etag) VALUES (?, ?, ?, ?, ?, ?)');
$etag = md5($cardData);
@ -339,8 +335,7 @@ class PDO extends AbstractBackend implements SyncSupport {
$this->addChange($addressBookId, $cardUri, 1);
return '"' . $etag . '"';
return '"'.$etag.'"';
}
/**
@ -363,14 +358,15 @@ class PDO extends AbstractBackend implements SyncSupport {
*
* If you don't return an ETag, you can just return null.
*
* @param mixed $addressBookId
* @param mixed $addressBookId
* @param string $cardUri
* @param string $cardData
*
* @return string|null
*/
function updateCard($addressBookId, $cardUri, $cardData) {
$stmt = $this->pdo->prepare('UPDATE ' . $this->cardsTableName . ' SET carddata = ?, lastmodified = ?, size = ?, etag = ? WHERE uri = ? AND addressbookid =?');
public function updateCard($addressBookId, $cardUri, $cardData)
{
$stmt = $this->pdo->prepare('UPDATE '.$this->cardsTableName.' SET carddata = ?, lastmodified = ?, size = ?, etag = ? WHERE uri = ? AND addressbookid =?');
$etag = md5($cardData);
$stmt->execute([
@ -379,31 +375,30 @@ class PDO extends AbstractBackend implements SyncSupport {
strlen($cardData),
$etag,
$cardUri,
$addressBookId
$addressBookId,
]);
$this->addChange($addressBookId, $cardUri, 2);
return '"' . $etag . '"';
return '"'.$etag.'"';
}
/**
* Deletes a card
* Deletes a card.
*
* @param mixed $addressBookId
* @param mixed $addressBookId
* @param string $cardUri
*
* @return bool
*/
function deleteCard($addressBookId, $cardUri) {
$stmt = $this->pdo->prepare('DELETE FROM ' . $this->cardsTableName . ' WHERE addressbookid = ? AND uri = ?');
public function deleteCard($addressBookId, $cardUri)
{
$stmt = $this->pdo->prepare('DELETE FROM '.$this->cardsTableName.' WHERE addressbookid = ? AND uri = ?');
$stmt->execute([$addressBookId, $cardUri]);
$this->addChange($addressBookId, $cardUri, 3);
return $stmt->rowCount() === 1;
return 1 === $stmt->rowCount();
}
/**
@ -458,30 +453,34 @@ class PDO extends AbstractBackend implements SyncSupport {
*
* @param string $addressBookId
* @param string $syncToken
* @param int $syncLevel
* @param int $limit
* @param int $syncLevel
* @param int $limit
*
* @return array
*/
function getChangesForAddressBook($addressBookId, $syncToken, $syncLevel, $limit = null) {
public function getChangesForAddressBook($addressBookId, $syncToken, $syncLevel, $limit = null)
{
// Current synctoken
$stmt = $this->pdo->prepare('SELECT synctoken FROM ' . $this->addressBooksTableName . ' WHERE id = ?');
$stmt = $this->pdo->prepare('SELECT synctoken FROM '.$this->addressBooksTableName.' WHERE id = ?');
$stmt->execute([$addressBookId]);
$currentToken = $stmt->fetchColumn(0);
if (is_null($currentToken)) return null;
if (is_null($currentToken)) {
return null;
}
$result = [
'syncToken' => $currentToken,
'added' => [],
'modified' => [],
'deleted' => [],
'added' => [],
'modified' => [],
'deleted' => [],
];
if ($syncToken) {
$query = "SELECT uri, operation FROM " . $this->addressBookChangesTableName . " WHERE synctoken >= ? AND synctoken < ? AND addressbookid = ? ORDER BY synctoken";
if ($limit > 0) $query .= " LIMIT " . (int)$limit;
$query = 'SELECT uri, operation FROM '.$this->addressBookChangesTableName.' WHERE synctoken >= ? AND synctoken < ? AND addressbookid = ? ORDER BY synctoken';
if ($limit > 0) {
$query .= ' LIMIT '.(int) $limit;
}
// Fetching all changes
$stmt = $this->pdo->prepare($query);
@ -492,13 +491,10 @@ class PDO extends AbstractBackend implements SyncSupport {
// This loop ensures that any duplicates are overwritten, only the
// last change on a node is relevant.
while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
$changes[$row['uri']] = $row['operation'];
}
foreach ($changes as $uri => $operation) {
switch ($operation) {
case 1:
$result['added'][] = $uri;
@ -510,41 +506,38 @@ class PDO extends AbstractBackend implements SyncSupport {
$result['deleted'][] = $uri;
break;
}
}
} else {
// No synctoken supplied, this is the initial sync.
$query = "SELECT uri FROM " . $this->cardsTableName . " WHERE addressbookid = ?";
$query = 'SELECT uri FROM '.$this->cardsTableName.' WHERE addressbookid = ?';
$stmt = $this->pdo->prepare($query);
$stmt->execute([$addressBookId]);
$result['added'] = $stmt->fetchAll(\PDO::FETCH_COLUMN);
}
return $result;
return $result;
}
/**
* Adds a change record to the addressbookchanges table.
*
* @param mixed $addressBookId
* @param mixed $addressBookId
* @param string $objectUri
* @param int $operation 1 = add, 2 = modify, 3 = delete
* @return void
* @param int $operation 1 = add, 2 = modify, 3 = delete
*/
protected function addChange($addressBookId, $objectUri, $operation) {
$stmt = $this->pdo->prepare('INSERT INTO ' . $this->addressBookChangesTableName . ' (uri, synctoken, addressbookid, operation) SELECT ?, synctoken, ?, ? FROM ' . $this->addressBooksTableName . ' WHERE id = ?');
protected function addChange($addressBookId, $objectUri, $operation)
{
$stmt = $this->pdo->prepare('INSERT INTO '.$this->addressBookChangesTableName.' (uri, synctoken, addressbookid, operation) SELECT ?, synctoken, ?, ? FROM '.$this->addressBooksTableName.' WHERE id = ?');
$stmt->execute([
$objectUri,
$addressBookId,
$operation,
$addressBookId
$addressBookId,
]);
$stmt = $this->pdo->prepare('UPDATE ' . $this->addressBooksTableName . ' SET synctoken = synctoken + 1 WHERE id = ?');
$stmt = $this->pdo->prepare('UPDATE '.$this->addressBooksTableName.' SET synctoken = synctoken + 1 WHERE id = ?');
$stmt->execute([
$addressBookId
$addressBookId,
]);
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CardDAV\Backend;
/**
@ -18,8 +20,8 @@ namespace Sabre\CardDAV\Backend;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
interface SyncSupport extends BackendInterface {
interface SyncSupport extends BackendInterface
{
/**
* The getChanges method returns all the changes that have happened, since
* the specified syncToken in the specified address book.
@ -72,10 +74,10 @@ interface SyncSupport extends BackendInterface {
*
* @param string $addressBookId
* @param string $syncToken
* @param int $syncLevel
* @param int $limit
* @param int $syncLevel
* @param int $limit
*
* @return array
*/
function getChangesForAddressBook($addressBookId, $syncToken, $syncLevel, $limit = null);
public function getChangesForAddressBook($addressBookId, $syncToken, $syncLevel, $limit = null);
}

View file

@ -1,94 +1,96 @@
<?php
declare(strict_types=1);
namespace Sabre\CardDAV;
use Sabre\DAV;
use Sabre\DAVACL;
/**
* The Card object represents a single Card from an addressbook
* The Card object represents a single Card from an addressbook.
*
* @copyright Copyright (C) fruux GmbH (https://fruux.com/)
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class Card extends DAV\File implements ICard, DAVACL\IACL {
class Card extends DAV\File implements ICard, DAVACL\IACL
{
use DAVACL\ACLTrait;
/**
* CardDAV backend
* CardDAV backend.
*
* @var Backend\BackendInterface
*/
protected $carddavBackend;
/**
* Array with information about this Card
* Array with information about this Card.
*
* @var array
*/
protected $cardData;
/**
* Array with information about the containing addressbook
* Array with information about the containing addressbook.
*
* @var array
*/
protected $addressBookInfo;
/**
* Constructor
* Constructor.
*
* @param Backend\BackendInterface $carddavBackend
* @param array $addressBookInfo
* @param array $cardData
* @param array $addressBookInfo
* @param array $cardData
*/
function __construct(Backend\BackendInterface $carddavBackend, array $addressBookInfo, array $cardData) {
public function __construct(Backend\BackendInterface $carddavBackend, array $addressBookInfo, array $cardData)
{
$this->carddavBackend = $carddavBackend;
$this->addressBookInfo = $addressBookInfo;
$this->cardData = $cardData;
}
/**
* Returns the uri for this object
* Returns the uri for this object.
*
* @return string
*/
function getName() {
public function getName()
{
return $this->cardData['uri'];
}
/**
* Returns the VCard-formatted object
* Returns the VCard-formatted object.
*
* @return string
*/
function get() {
public function get()
{
// Pre-populating 'carddata' is optional. If we don't yet have it
// already, we fetch it from the backend.
if (!isset($this->cardData['carddata'])) {
$this->cardData = $this->carddavBackend->getCard($this->addressBookInfo['id'], $this->cardData['uri']);
}
return $this->cardData['carddata'];
return $this->cardData['carddata'];
}
/**
* Updates the VCard-formatted object
* Updates the VCard-formatted object.
*
* @param string $cardData
*
* @return string|null
*/
function put($cardData) {
if (is_resource($cardData))
public function put($cardData)
{
if (is_resource($cardData)) {
$cardData = stream_get_contents($cardData);
}
// Converting to UTF-8, if needed
$cardData = DAV\StringUtil::ensureUTF8($cardData);
@ -98,92 +100,82 @@ class Card extends DAV\File implements ICard, DAVACL\IACL {
$this->cardData['etag'] = $etag;
return $etag;
}
/**
* Deletes the card
*
* @return void
* Deletes the card.
*/
function delete() {
public function delete()
{
$this->carddavBackend->deleteCard($this->addressBookInfo['id'], $this->cardData['uri']);
}
/**
* Returns the mime content-type
* Returns the mime content-type.
*
* @return string
*/
function getContentType() {
public function getContentType()
{
return 'text/vcard; charset=utf-8';
}
/**
* Returns an ETag for this object
* Returns an ETag for this object.
*
* @return string
*/
function getETag() {
public function getETag()
{
if (isset($this->cardData['etag'])) {
return $this->cardData['etag'];
} else {
$data = $this->get();
if (is_string($data)) {
return '"' . md5($data) . '"';
return '"'.md5($data).'"';
} else {
// We refuse to calculate the md5 if it's a stream.
return null;
}
}
}
/**
* Returns the last modification date as a unix timestamp
* Returns the last modification date as a unix timestamp.
*
* @return int
*/
function getLastModified() {
public function getLastModified()
{
return isset($this->cardData['lastmodified']) ? $this->cardData['lastmodified'] : null;
}
/**
* Returns the size of this object in bytes
* Returns the size of this object in bytes.
*
* @return int
*/
function getSize() {
public function getSize()
{
if (array_key_exists('size', $this->cardData)) {
return $this->cardData['size'];
} else {
return strlen($this->get());
}
}
/**
* Returns the owner principal
* Returns the owner principal.
*
* This must be a url to a principal, or null if there's no owner
*
* @return string|null
*/
function getOwner() {
public function getOwner()
{
return $this->addressBookInfo['principaluri'];
}
/**
* Returns a list of ACE's for this node.
*
@ -196,8 +188,8 @@ class Card extends DAV\File implements ICard, DAVACL\IACL {
*
* @return array
*/
function getACL() {
public function getACL()
{
// An alternative acl may be specified through the cardData array.
if (isset($this->cardData['acl'])) {
return $this->cardData['acl'];
@ -210,7 +202,5 @@ class Card extends DAV\File implements ICard, DAVACL\IACL {
'protected' => true,
],
];
}
}

View file

@ -1,11 +1,13 @@
<?php
declare(strict_types=1);
namespace Sabre\CardDAV;
use Sabre\DAV;
/**
* AddressBook interface
* AddressBook interface.
*
* Implement this interface to allow a node to be recognized as an addressbook.
*
@ -13,6 +15,6 @@ use Sabre\DAV;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
interface IAddressBook extends DAV\ICollection {
interface IAddressBook extends DAV\ICollection
{
}

View file

@ -1,11 +1,13 @@
<?php
declare(strict_types=1);
namespace Sabre\CardDAV;
use Sabre\DAV;
/**
* Card interface
* Card interface.
*
* Extend the ICard interface to allow your custom nodes to be picked up as
* 'Cards'.
@ -14,6 +16,6 @@ use Sabre\DAV;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
interface ICard extends DAV\IFile {
interface ICard extends DAV\IFile
{
}

View file

@ -1,9 +1,11 @@
<?php
declare(strict_types=1);
namespace Sabre\CardDAV;
/**
* IDirectory interface
* IDirectory interface.
*
* Implement this interface to have an addressbook marked as a 'directory'. A
* directory is an (often) global addressbook.
@ -15,6 +17,6 @@ namespace Sabre\CardDAV;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
interface IDirectory extends IAddressBook {
interface IDirectory extends IAddressBook
{
}

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CardDAV;
use Sabre\DAV;
@ -8,7 +10,7 @@ use Sabre\HTTP\ResponseInterface;
use Sabre\VObject;
/**
* VCF Exporter
* VCF Exporter.
*
* This plugin adds the ability to export entire address books as .vcf files.
* This is useful for clients that don't support CardDAV yet. They often do
@ -19,28 +21,27 @@ use Sabre\VObject;
* @author Thomas Tanghus (http://tanghus.net/)
* @license http://sabre.io/license/ Modified BSD License
*/
class VCFExportPlugin extends DAV\ServerPlugin {
class VCFExportPlugin extends DAV\ServerPlugin
{
/**
* Reference to Server class
* Reference to Server class.
*
* @var DAV\Server
*/
protected $server;
/**
* Initializes the plugin and registers event handlers
* Initializes the plugin and registers event handlers.
*
* @param DAV\Server $server
* @return void
*/
function initialize(DAV\Server $server) {
public function initialize(DAV\Server $server)
{
$this->server = $server;
$this->server->on('method:GET', [$this, 'httpGet'], 90);
$server->on('browserButtonActions', function($path, $node, &$actions) {
$server->on('browserButtonActions', function ($path, $node, &$actions) {
if ($node instanceof IAddressBook) {
$actions .= '<a href="' . htmlspecialchars($path, ENT_QUOTES, 'UTF-8') . '?export"><span class="oi" data-glyph="book"></span></a>';
$actions .= '<a href="'.htmlspecialchars($path, ENT_QUOTES, 'UTF-8').'?export"><span class="oi" data-glyph="book"></span></a>';
}
});
}
@ -48,20 +49,25 @@ class VCFExportPlugin extends DAV\ServerPlugin {
/**
* Intercepts GET requests on addressbook urls ending with ?export.
*
* @param RequestInterface $request
* @param RequestInterface $request
* @param ResponseInterface $response
*
* @return bool
*/
function httpGet(RequestInterface $request, ResponseInterface $response) {
public function httpGet(RequestInterface $request, ResponseInterface $response)
{
$queryParams = $request->getQueryParameters();
if (!array_key_exists('export', $queryParams)) return;
if (!array_key_exists('export', $queryParams)) {
return;
}
$path = $request->getPath();
$node = $this->server->tree->getNodeForPath($path);
if (!($node instanceof IAddressBook)) return;
if (!($node instanceof IAddressBook)) {
return;
}
$this->server->transactionType = 'get-addressbook-export';
@ -71,7 +77,7 @@ class VCFExportPlugin extends DAV\ServerPlugin {
}
$nodes = $this->server->getPropertiesForPath($path, [
'{' . Plugin::NS_CARDDAV . '}address-data',
'{'.Plugin::NS_CARDDAV.'}address-data',
], 1);
$format = 'text/directory';
@ -91,9 +97,9 @@ class VCFExportPlugin extends DAV\ServerPlugin {
'',
$node->getName()
);
$filename .= '-' . date('Y-m-d') . $filenameExtension;
$filename .= '-'.date('Y-m-d').$filenameExtension;
$response->setHeader('Content-Disposition', 'attachment; filename="' . $filename . '"');
$response->setHeader('Content-Disposition', 'attachment; filename="'.$filename.'"');
$response->setHeader('Content-Type', $format);
$response->setStatus(200);
@ -101,25 +107,24 @@ class VCFExportPlugin extends DAV\ServerPlugin {
// Returning false to break the event chain
return false;
}
/**
* Merges all vcard objects, and builds one big vcf export
* Merges all vcard objects, and builds one big vcf export.
*
* @param array $nodes
*
* @return string
*/
function generateVCF(array $nodes) {
$output = "";
public function generateVCF(array $nodes)
{
$output = '';
foreach ($nodes as $node) {
if (!isset($node[200]['{' . Plugin::NS_CARDDAV . '}address-data'])) {
if (!isset($node[200]['{'.Plugin::NS_CARDDAV.'}address-data'])) {
continue;
}
$nodeData = $node[200]['{' . Plugin::NS_CARDDAV . '}address-data'];
$nodeData = $node[200]['{'.Plugin::NS_CARDDAV.'}address-data'];
// Parsing this node so VObject can clean up the output.
$vcard = VObject\Reader::read($nodeData);
@ -127,11 +132,9 @@ class VCFExportPlugin extends DAV\ServerPlugin {
// Destroy circular references to PHP will GC the object.
$vcard->destroy();
}
return $output;
}
/**
@ -142,10 +145,9 @@ class VCFExportPlugin extends DAV\ServerPlugin {
*
* @return string
*/
function getPluginName() {
public function getPluginName()
{
return 'vcf-export';
}
/**
@ -159,14 +161,12 @@ class VCFExportPlugin extends DAV\ServerPlugin {
*
* @return array
*/
function getPluginInfo() {
public function getPluginInfo()
{
return [
'name' => $this->getPluginName(),
'name' => $this->getPluginName(),
'description' => 'Adds the ability to export CardDAV addressbooks as a single vCard file.',
'link' => 'http://sabre.io/dav/vcf-export-plugin/',
'link' => 'http://sabre.io/dav/vcf-export-plugin/',
];
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CardDAV\Xml\Filter;
use Sabre\Xml\Reader;
@ -21,8 +23,8 @@ use Sabre\Xml\XmlDeserializable;
* @author Evert Pot (http://www.rooftopsolutions.nl/)
* @license http://sabre.io/license/ Modified BSD License
*/
class AddressData implements XmlDeserializable {
class AddressData implements XmlDeserializable
{
/**
* The deserialize method is called during xml parsing.
*
@ -42,22 +44,25 @@ class AddressData implements XmlDeserializable {
* the next element.
*
* @param Reader $reader
*
* @return mixed
*/
static function xmlDeserialize(Reader $reader) {
public static function xmlDeserialize(Reader $reader)
{
$result = [
'contentType' => $reader->getAttribute('content-type') ?: 'text/vcard',
'version' => $reader->getAttribute('version') ?: '3.0',
'version' => $reader->getAttribute('version') ?: '3.0',
];
$elems = (array)$reader->parseInnerTree();
$result['addressDataProperties'] = array_map(function($element) {
$elems = (array) $reader->parseInnerTree();
$elems = array_filter($elems, function ($element) {
return '{urn:ietf:params:xml:ns:carddav}prop' === $element['name'] &&
isset($element['attributes']['name']);
});
$result['addressDataProperties'] = array_map(function ($element) {
return $element['attributes']['name'];
}, $elems);
return $result;
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CardDAV\Xml\Filter;
use Sabre\CardDAV\Plugin;
@ -21,8 +23,8 @@ use Sabre\Xml\Reader;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
abstract class ParamFilter implements Element {
abstract class ParamFilter implements Element
{
/**
* The deserialize method is called during xml parsing.
*
@ -42,14 +44,15 @@ abstract class ParamFilter implements Element {
* the next element.
*
* @param Reader $reader
*
* @return mixed
*/
static function xmlDeserialize(Reader $reader) {
public static function xmlDeserialize(Reader $reader)
{
$result = [
'name' => null,
'name' => null,
'is-not-defined' => false,
'text-match' => null,
'text-match' => null,
];
$att = $reader->parseAttributes();
@ -57,33 +60,29 @@ abstract class ParamFilter implements Element {
$elems = $reader->parseInnerTree();
if (is_array($elems)) foreach ($elems as $elem) {
switch ($elem['name']) {
case '{' . Plugin::NS_CARDDAV . '}is-not-defined' :
if (is_array($elems)) {
foreach ($elems as $elem) {
switch ($elem['name']) {
case '{'.Plugin::NS_CARDDAV.'}is-not-defined':
$result['is-not-defined'] = true;
break;
case '{' . Plugin::NS_CARDDAV . '}text-match' :
case '{'.Plugin::NS_CARDDAV.'}text-match':
$matchType = isset($elem['attributes']['match-type']) ? $elem['attributes']['match-type'] : 'contains';
if (!in_array($matchType, ['contains', 'equals', 'starts-with', 'ends-with'])) {
throw new BadRequest('Unknown match-type: ' . $matchType);
throw new BadRequest('Unknown match-type: '.$matchType);
}
$result['text-match'] = [
'negate-condition' => isset($elem['attributes']['negate-condition']) && $elem['attributes']['negate-condition'] === 'yes',
'collation' => isset($elem['attributes']['collation']) ? $elem['attributes']['collation'] : 'i;unicode-casemap',
'value' => $elem['value'],
'match-type' => $matchType,
'negate-condition' => isset($elem['attributes']['negate-condition']) && 'yes' === $elem['attributes']['negate-condition'],
'collation' => isset($elem['attributes']['collation']) ? $elem['attributes']['collation'] : 'i;unicode-casemap',
'value' => $elem['value'],
'match-type' => $matchType,
];
break;
}
}
}
return $result;
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CardDAV\Xml\Filter;
use Sabre\CardDAV\Plugin;
@ -21,8 +23,8 @@ use Sabre\Xml\XmlDeserializable;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class PropFilter implements XmlDeserializable {
class PropFilter implements XmlDeserializable
{
/**
* The deserialize method is called during xml parsing.
*
@ -42,57 +44,54 @@ class PropFilter implements XmlDeserializable {
* the next element.
*
* @param Reader $reader
*
* @return mixed
*/
static function xmlDeserialize(Reader $reader) {
public static function xmlDeserialize(Reader $reader)
{
$result = [
'name' => null,
'test' => 'anyof',
'name' => null,
'test' => 'anyof',
'is-not-defined' => false,
'param-filters' => [],
'text-matches' => [],
'param-filters' => [],
'text-matches' => [],
];
$att = $reader->parseAttributes();
$result['name'] = $att['name'];
if (isset($att['test']) && $att['test'] === 'allof') {
if (isset($att['test']) && 'allof' === $att['test']) {
$result['test'] = 'allof';
}
$elems = $reader->parseInnerTree();
if (is_array($elems)) foreach ($elems as $elem) {
switch ($elem['name']) {
case '{' . Plugin::NS_CARDDAV . '}param-filter' :
if (is_array($elems)) {
foreach ($elems as $elem) {
switch ($elem['name']) {
case '{'.Plugin::NS_CARDDAV.'}param-filter':
$result['param-filters'][] = $elem['value'];
break;
case '{' . Plugin::NS_CARDDAV . '}is-not-defined' :
case '{'.Plugin::NS_CARDDAV.'}is-not-defined':
$result['is-not-defined'] = true;
break;
case '{' . Plugin::NS_CARDDAV . '}text-match' :
case '{'.Plugin::NS_CARDDAV.'}text-match':
$matchType = isset($elem['attributes']['match-type']) ? $elem['attributes']['match-type'] : 'contains';
if (!in_array($matchType, ['contains', 'equals', 'starts-with', 'ends-with'])) {
throw new BadRequest('Unknown match-type: ' . $matchType);
throw new BadRequest('Unknown match-type: '.$matchType);
}
$result['text-matches'][] = [
'negate-condition' => isset($elem['attributes']['negate-condition']) && $elem['attributes']['negate-condition'] === 'yes',
'collation' => isset($elem['attributes']['collation']) ? $elem['attributes']['collation'] : 'i;unicode-casemap',
'value' => $elem['value'],
'match-type' => $matchType,
'negate-condition' => isset($elem['attributes']['negate-condition']) && 'yes' === $elem['attributes']['negate-condition'],
'collation' => isset($elem['attributes']['collation']) ? $elem['attributes']['collation'] : 'i;unicode-casemap',
'value' => $elem['value'],
'match-type' => $matchType,
];
break;
}
}
}
return $result;
}
}

View file

@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
namespace Sabre\CardDAV\Xml\Property;
use Sabre\CardDAV\Plugin;
@ -7,7 +9,7 @@ use Sabre\Xml\Writer;
use Sabre\Xml\XmlSerializable;
/**
* Supported-address-data property
* Supported-address-data property.
*
* This property is a representation of the supported-address-data property
* in the CardDAV namespace.
@ -20,22 +22,22 @@ use Sabre\Xml\XmlSerializable;
* @author Evert Pot (http://evertpot.com/)
* @license http://sabre.io/license/ Modified BSD License
*/
class SupportedAddressData implements XmlSerializable {
class SupportedAddressData implements XmlSerializable
{
/**
* supported versions
* supported versions.
*
* @var array
*/
protected $supportedData = [];
/**
* Creates the property
* Creates the property.
*
* @param array|null $supportedData
*/
function __construct(array $supportedData = null) {
public function __construct(array $supportedData = null)
{
if (is_null($supportedData)) {
$supportedData = [
['contentType' => 'text/vcard', 'version' => '3.0'],
@ -45,7 +47,6 @@ class SupportedAddressData implements XmlSerializable {
}
$this->supportedData = $supportedData;
}
/**
@ -65,19 +66,16 @@ class SupportedAddressData implements XmlSerializable {
* If you are opening new elements, you must also close them again.
*
* @param Writer $writer
* @return void
*/
function xmlSerialize(Writer $writer) {
public function xmlSerialize(Writer $writer)
{
foreach ($this->supportedData as $supported) {
$writer->startElement('{' . Plugin::NS_CARDDAV . '}address-data-type');
$writer->startElement('{'.Plugin::NS_CARDDAV.'}address-data-type');
$writer->writeAttributes([
'content-type' => $supported['contentType'],
'version' => $supported['version']
'version' => $supported['version'],
]);
$writer->endElement(); // address-data-type
}
}
}

Some files were not shown because too many files have changed in this diff Show more