[Pkg-owncloud-commits] [php-sabredav] 256/275: Support for the test attribute in principal searches. Added findByUri to principal backends.

David Prévot taffit at moszumanska.debian.org
Thu Sep 25 14:56:16 UTC 2014


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

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

commit a1dad6a6bea4e9296979be5101f838833b5c122a
Author: Evert Pot <evert at rooftopsolutions.nl>
Date:   Tue Sep 23 18:37:55 2014 +0100

    Support for the test attribute in principal searches.
    Added findByUri to principal backends.
---
 lib/DAVACL/AbstractPrincipalCollection.php         |  31 ++++-
 lib/DAVACL/IPrincipalCollection.php                |  26 +++-
 lib/DAVACL/Plugin.php                              |  45 +++++--
 lib/DAVACL/PrincipalBackend/AbstractBackend.php    |  34 +++++
 lib/DAVACL/PrincipalBackend/BackendInterface.php   |  29 ++++-
 lib/DAVACL/PrincipalBackend/PDO.php                |  11 +-
 tests/Sabre/DAVACL/PrincipalBackend/Mock.php       |   9 +-
 tests/Sabre/DAVACL/PrincipalPropertySearchTest.php | 145 +++++++++++++++++++++
 8 files changed, 298 insertions(+), 32 deletions(-)

diff --git a/lib/DAVACL/AbstractPrincipalCollection.php b/lib/DAVACL/AbstractPrincipalCollection.php
index 6b58e9d..366b75e 100644
--- a/lib/DAVACL/AbstractPrincipalCollection.php
+++ b/lib/DAVACL/AbstractPrincipalCollection.php
@@ -133,8 +133,9 @@ abstract class AbstractPrincipalCollection extends DAV\Collection implements IPr
      * keys in searchProperties are the WebDAV property names, while the values
      * are the property values to search on.
      *
-     * If multiple properties are being searched on, the search should be
-     * AND'ed.
+     * By default, if multiple properties are submitted to this method, the
+     * various properties should be combined with 'AND'. If $test is set to
+     * 'anyof', it should be combined using 'OR'.
      *
      * This method should simply return a list of 'child names', which may be
      * used to call $this->getChild in the future.
@@ -142,9 +143,9 @@ abstract class AbstractPrincipalCollection extends DAV\Collection implements IPr
      * @param array $searchProperties
      * @return array
      */
-    function searchPrincipals(array $searchProperties) {
+    function searchPrincipals(array $searchProperties, $test = 'allof') {
 
-        $result = $this->principalBackend->searchPrincipals($this->principalPrefix, $searchProperties);
+        $result = $this->principalBackend->searchPrincipals($this->principalPrefix, $searchProperties, $test);
         $r = [];
 
         foreach($result as $row) {
@@ -155,4 +156,26 @@ abstract class AbstractPrincipalCollection extends DAV\Collection implements IPr
 
     }
 
+    /**
+     * Finds a principal by its URI.
+     *
+     * This method may receive any type of uri, but mailto: addresses will be
+     * the most common.
+     *
+     * Implementation of this API is optional. It is currently used by the
+     * CalDAV system to find principals based on their email addresses. If this
+     * API is not implemented, some features may not work correctly.
+     *
+     * This method must return a relative principal path, or null, if the
+     * principal was not found or you refuse to find it.
+     *
+     * @param string $uri
+     * @return string
+     */
+    function findByUri($uri) {
+
+        return $this->principalBackend->findByUri($uri);
+
+    }
+
 }
diff --git a/lib/DAVACL/IPrincipalCollection.php b/lib/DAVACL/IPrincipalCollection.php
index d09c9d6..238d8ca 100644
--- a/lib/DAVACL/IPrincipalCollection.php
+++ b/lib/DAVACL/IPrincipalCollection.php
@@ -28,15 +28,35 @@ interface IPrincipalCollection extends DAV\ICollection {
      * keys in searchProperties are the WebDAV property names, while the values
      * are the property values to search on.
      *
-     * If multiple properties are being searched on, the search should be
-     * AND'ed.
+     * By default, if multiple properties are submitted to this method, the
+     * various properties should be combined with 'AND'. If $test is set to
+     * 'anyof', it should be combined using 'OR'.
      *
      * This method should simply return a list of 'child names', which may be
      * used to call $this->getChild in the future.
      *
      * @param array $searchProperties
+     * @param string $test
      * @return array
      */
-    function searchPrincipals(array $searchProperties);
+    function searchPrincipals(array $searchProperties, $test = 'allof');
+
+    /**
+     * Finds a principal by its URI.
+     *
+     * This method may receive any type of uri, but mailto: addresses will be
+     * the most common.
+     *
+     * Implementation of this API is optional. It is currently used by the
+     * CalDAV system to find principals based on their email addresses. If this
+     * API is not implemented, some features may not work correctly.
+     *
+     * This method must return a relative principal path, or null, if the
+     * principal was not found or you refuse to find it.
+     *
+     * @param string $uri
+     * @return string
+     */
+    function findByUri($uri);
 
 }
diff --git a/lib/DAVACL/Plugin.php b/lib/DAVACL/Plugin.php
index 7fe452e..a72ac4d 100644
--- a/lib/DAVACL/Plugin.php
+++ b/lib/DAVACL/Plugin.php
@@ -596,20 +596,27 @@ class Plugin extends DAV\ServerPlugin {
      *
      * This method returns false if the principal could not be found.
      *
-     * @return string|bool
+     * @return string|null
      */
     function getPrincipalByEmail($email) {
 
-        $result = $this->principalSearch(
-            ['{http://sabredav.org/ns}email-address' => $email],
-            ['{DAV:}principal-URL']
-        );
+        $result = null;
+        $uris = $this->principalCollectionSet;
+        foreach($uris as $uri) {
 
-        if (!count($result)) {
-            return false;
-        }
+            $principalCollection = $this->server->tree->getNodeForPath($uri);
+            if (!$principalCollection instanceof IPrincipalCollection) {
+                // Not a principal collection, we're simply going to ignore
+                // this.
+                continue;
+            }
+
+            $result = $principalCollection->findByUri('mailto:' . $email);
+            if ($result) {
+                return $result;
+            }
 
-        return $result[0][200]['{DAV:}principal-URL'];
+        }
 
     }
 
@@ -630,12 +637,14 @@ class Plugin extends DAV\ServerPlugin {
      * @param string $collectionUri      The principal collection to search on.
      *                                   If this is ommitted, the standard
      *                                   principal collection-set will be used.
+     * @param string $test               "allof" to use AND to search the
+     *                                   properties. 'anyof' for OR.
      * @return array     This method returns an array structure similar to
      *                  Sabre\DAV\Server::getPropertiesForPath. Returned
      *                  properties are index by a HTTP status code.
      *
      */
-    function principalSearch(array $searchProperties, array $requestedProperties, $collectionUri = null) {
+    function principalSearch(array $searchProperties, array $requestedProperties, $collectionUri = null, $test = 'allof') {
 
         if (!is_null($collectionUri)) {
             $uris = [$collectionUri];
@@ -653,7 +662,7 @@ class Plugin extends DAV\ServerPlugin {
                 continue;
             }
 
-            $results = $principalCollection->searchPrincipals($searchProperties);
+            $results = $principalCollection->searchPrincipals($searchProperties, $test);
             foreach($results as $result) {
                 $lookupResults[] = rtrim($uri,'/') . '/' . $result;
             }
@@ -1299,13 +1308,18 @@ class Plugin extends DAV\ServerPlugin {
      */
     protected function principalPropertySearchReport(\DOMDocument $dom) {
 
-        list($searchProperties, $requestedProperties, $applyToPrincipalCollectionSet) = $this->parsePrincipalPropertySearchReportRequest($dom);
+        list(
+            $searchProperties,
+            $requestedProperties,
+            $applyToPrincipalCollectionSet,
+            $test
+        ) = $this->parsePrincipalPropertySearchReportRequest($dom);
 
         $uri = null;
         if (!$applyToPrincipalCollectionSet) {
             $uri = $this->server->getRequestUri();
         }
-        $result = $this->principalSearch($searchProperties, $requestedProperties, $uri);
+        $result = $this->principalSearch($searchProperties, $requestedProperties, $uri, $test);
 
         $prefer = $this->server->getHTTPPRefer();
 
@@ -1340,6 +1354,8 @@ class Plugin extends DAV\ServerPlugin {
 
         $applyToPrincipalCollectionSet = false;
 
+        $test = $dom->firstChild->getAttribute('test') === 'anyof' ? 'anyof' : 'allof';
+
         // Parsing the search request
         foreach($dom->firstChild->childNodes as $searchNode) {
 
@@ -1382,7 +1398,8 @@ class Plugin extends DAV\ServerPlugin {
         return [
             $searchProperties,
             array_keys(DAV\XMLUtil::parseProperties($dom->firstChild)),
-            $applyToPrincipalCollectionSet
+            $applyToPrincipalCollectionSet,
+            $test
         ];
 
     }
diff --git a/lib/DAVACL/PrincipalBackend/AbstractBackend.php b/lib/DAVACL/PrincipalBackend/AbstractBackend.php
index 984f9ad..f431653 100644
--- a/lib/DAVACL/PrincipalBackend/AbstractBackend.php
+++ b/lib/DAVACL/PrincipalBackend/AbstractBackend.php
@@ -15,4 +15,38 @@ namespace Sabre\DAVACL\PrincipalBackend;
  */
 abstract class AbstractBackend implements BackendInterface {
 
+    /**
+     * Finds a principal by its URI.
+     *
+     * This method may receive any type of uri, but mailto: addresses will be
+     * the most common.
+     *
+     * Implementation of this API is optional. It is currently used by the
+     * CalDAV system to find principals based on their email addresses. If this
+     * API is not implemented, some features may not work correctly.
+     *
+     * This method must return a relative principal path, or null, if the
+     * principal was not found or you refuse to find it.
+     *
+     * @param string $uri
+     * @return string
+     */
+    function findByUri($uri) {
+
+        // Note that the default implementation here is a bit slow and could
+        // likely be optimized.
+        if (substr($uri,0,7)!=='mailto:') {
+            return;
+        }
+        $result = $this->searchPrincipals(
+            '',
+            ['{http://sabredav.org/ns}email-address' => substr($uri,7)]
+        );
+
+        if ($result) {
+            return $result[0];
+        }
+
+    }
+
 }
diff --git a/lib/DAVACL/PrincipalBackend/BackendInterface.php b/lib/DAVACL/PrincipalBackend/BackendInterface.php
index 84636d7..6748228 100644
--- a/lib/DAVACL/PrincipalBackend/BackendInterface.php
+++ b/lib/DAVACL/PrincipalBackend/BackendInterface.php
@@ -66,15 +66,15 @@ interface BackendInterface {
      * properties.
      *
      * This search is specifically used by RFC3744's principal-property-search
-     * REPORT. You should at least allow searching on
-     * http://sabredav.org/ns}email-address.
+     * REPORT.
      *
      * The actual search should be a unicode-non-case-sensitive search. The
      * keys in searchProperties are the WebDAV property names, while the values
      * are the property values to search on.
      *
-     * If multiple properties are being searched on, the search should be
-     * AND'ed.
+     * By default, if multiple properties are submitted to this method, the
+     * various properties should be combined with 'AND'. If $test is set to
+     * 'anyof', it should be combined using 'OR'.
      *
      * This method should simply return an array with full principal uri's.
      *
@@ -87,9 +87,28 @@ interface BackendInterface {
      *
      * @param string $prefixPath
      * @param array $searchProperties
+     * @param string $test
      * @return array
      */
-    function searchPrincipals($prefixPath, array $searchProperties);
+    function searchPrincipals($prefixPath, array $searchProperties, $test = 'allof');
+
+    /**
+     * Finds a principal by its URI.
+     *
+     * This method may receive any type of uri, but mailto: addresses will be
+     * the most common.
+     *
+     * Implementation of this API is optional. It is currently used by the
+     * CalDAV system to find principals based on their email addresses. If this
+     * API is not implemented, some features may not work correctly.
+     *
+     * This method must return a relative principal path, or null, if the
+     * principal was not found or you refuse to find it.
+     *
+     * @param string $uri
+     * @return string
+     */
+    function findByUri($uri);
 
     /**
      * Returns the list of members for a group-principal
diff --git a/lib/DAVACL/PrincipalBackend/PDO.php b/lib/DAVACL/PrincipalBackend/PDO.php
index 1ca49fc..61598a6 100644
--- a/lib/DAVACL/PrincipalBackend/PDO.php
+++ b/lib/DAVACL/PrincipalBackend/PDO.php
@@ -232,15 +232,15 @@ class PDO extends AbstractBackend {
      * properties.
      *
      * This search is specifically used by RFC3744's principal-property-search
-     * REPORT. You should at least allow searching on
-     * http://sabredav.org/ns}email-address.
+     * REPORT.
      *
      * The actual search should be a unicode-non-case-sensitive search. The
      * keys in searchProperties are the WebDAV property names, while the values
      * are the property values to search on.
      *
-     * If multiple properties are being searched on, the search should be
-     * AND'ed.
+     * By default, if multiple properties are submitted to this method, the
+     * various properties should be combined with 'AND'. If $test is set to
+     * 'anyof', it should be combined using 'OR'.
      *
      * This method should simply return an array with full principal uri's.
      *
@@ -253,9 +253,10 @@ class PDO extends AbstractBackend {
      *
      * @param string $prefixPath
      * @param array $searchProperties
+     * @param string $test
      * @return array
      */
-    function searchPrincipals($prefixPath, array $searchProperties) {
+    function searchPrincipals($prefixPath, array $searchProperties, $test = 'allof') {
 
         $query = 'SELECT uri FROM ' . $this->tableName . ' WHERE 1=1 ';
         $values = [];
diff --git a/tests/Sabre/DAVACL/PrincipalBackend/Mock.php b/tests/Sabre/DAVACL/PrincipalBackend/Mock.php
index 1ce97c8..d58fe12 100644
--- a/tests/Sabre/DAVACL/PrincipalBackend/Mock.php
+++ b/tests/Sabre/DAVACL/PrincipalBackend/Mock.php
@@ -61,7 +61,7 @@ class Mock extends AbstractBackend {
 
     }
 
-    function searchPrincipals($prefixPath, array $searchProperties) {
+    function searchPrincipals($prefixPath, array $searchProperties, $test = 'allof') {
 
         $matches = array();
         foreach($this->getPrincipalsByPrefix($prefixPath) as $principal) {
@@ -75,6 +75,13 @@ class Mock extends AbstractBackend {
                     continue 2;
                 }
 
+                // We have a match for this searchProperty!
+                if ($test === 'allof') {
+                    continue;
+                } else {
+                    break;
+                }
+
             }
             $matches[] = $principal['uri'];
 
diff --git a/tests/Sabre/DAVACL/PrincipalPropertySearchTest.php b/tests/Sabre/DAVACL/PrincipalPropertySearchTest.php
index 39311ef..d01ee56 100644
--- a/tests/Sabre/DAVACL/PrincipalPropertySearchTest.php
+++ b/tests/Sabre/DAVACL/PrincipalPropertySearchTest.php
@@ -176,6 +176,151 @@ class PrincipalPropertySearchTest extends \PHPUnit_Framework_TestCase {
         }
 
     }
+
+    function testAND() {
+
+        $xml = '<?xml version="1.0"?>
+<d:principal-property-search xmlns:d="DAV:">
+  <d:apply-to-principal-collection-set />
+  <d:property-search>
+     <d:prop>
+       <d:displayname />
+     </d:prop>
+     <d:match>user</d:match>
+  </d:property-search>
+  <d:property-search>
+     <d:prop>
+       <d:foo />
+     </d:prop>
+     <d:match>bar</d:match>
+  </d:property-search>
+  <d:prop>
+    <d:displayname />
+    <d:getcontentlength />
+  </d:prop>
+</d:principal-property-search>';
+
+        $serverVars = array(
+            'REQUEST_METHOD' => 'REPORT',
+            'HTTP_DEPTH'     => '0',
+            'REQUEST_URI'    => '/',
+        );
+
+        $request = HTTP\Sapi::createFromServerArray($serverVars);
+        $request->setBody($xml);
+
+        $server = $this->getServer();
+        $server->httpRequest = $request;
+
+        $server->exec();
+
+        $this->assertEquals(207, $server->httpResponse->status, $server->httpResponse->body);
+        $this->assertEquals(array(
+            'X-Sabre-Version' => DAV\Version::VERSION,
+            'Content-Type' => 'application/xml; charset=utf-8',
+            'Vary'         => 'Brief,Prefer',
+        ), $server->httpResponse->getHeaders());
+
+
+        $check = array(
+            '/d:multistatus',
+            '/d:multistatus/d:response' => 0,
+            '/d:multistatus/d:response/d:href' => 0,
+            '/d:multistatus/d:response/d:propstat' => 0,
+            '/d:multistatus/d:response/d:propstat/d:prop' => 0,
+            '/d:multistatus/d:response/d:propstat/d:prop/d:displayname' => 0,
+            '/d:multistatus/d:response/d:propstat/d:prop/d:getcontentlength' => 0,
+            '/d:multistatus/d:response/d:propstat/d:status' => 0,
+        );
+
+        $xml = simplexml_load_string($server->httpResponse->body);
+        $xml->registerXPathNamespace('d','DAV:');
+        foreach($check as $v1=>$v2) {
+
+            $xpath = is_int($v1)?$v2:$v1;
+
+            $result = $xml->xpath($xpath);
+
+            $count = 1;
+            if (!is_int($v1)) $count = $v2;
+
+            $this->assertEquals($count,count($result), 'we expected ' . $count . ' appearances of ' . $xpath . ' . We found ' . count($result) . '. Full response body: ' . $server->httpResponse->body);
+
+        }
+
+    }
+    function testOR() {
+
+        $xml = '<?xml version="1.0"?>
+<d:principal-property-search xmlns:d="DAV:" test="anyof">
+  <d:apply-to-principal-collection-set />
+  <d:property-search>
+     <d:prop>
+       <d:displayname />
+     </d:prop>
+     <d:match>user</d:match>
+  </d:property-search>
+  <d:property-search>
+     <d:prop>
+       <d:foo />
+     </d:prop>
+     <d:match>bar</d:match>
+  </d:property-search>
+  <d:prop>
+    <d:displayname />
+    <d:getcontentlength />
+  </d:prop>
+</d:principal-property-search>';
+
+        $serverVars = array(
+            'REQUEST_METHOD' => 'REPORT',
+            'HTTP_DEPTH'     => '0',
+            'REQUEST_URI'    => '/',
+        );
+
+        $request = HTTP\Sapi::createFromServerArray($serverVars);
+        $request->setBody($xml);
+
+        $server = $this->getServer();
+        $server->httpRequest = $request;
+
+        $server->exec();
+
+        $this->assertEquals(207, $server->httpResponse->status, $server->httpResponse->body);
+        $this->assertEquals(array(
+            'X-Sabre-Version' => DAV\Version::VERSION,
+            'Content-Type' => 'application/xml; charset=utf-8',
+            'Vary'         => 'Brief,Prefer',
+        ), $server->httpResponse->getHeaders());
+
+
+        $check = array(
+            '/d:multistatus',
+            '/d:multistatus/d:response' => 2,
+            '/d:multistatus/d:response/d:href' => 2,
+            '/d:multistatus/d:response/d:propstat' => 4,
+            '/d:multistatus/d:response/d:propstat/d:prop' => 4,
+            '/d:multistatus/d:response/d:propstat/d:prop/d:displayname' => 2,
+            '/d:multistatus/d:response/d:propstat/d:prop/d:getcontentlength' => 2,
+            '/d:multistatus/d:response/d:propstat/d:status' => 4,
+        );
+
+        $xml = simplexml_load_string($server->httpResponse->body);
+        $xml->registerXPathNamespace('d','DAV:');
+        foreach($check as $v1=>$v2) {
+
+            $xpath = is_int($v1)?$v2:$v1;
+
+            $result = $xml->xpath($xpath);
+
+            $count = 1;
+            if (!is_int($v1)) $count = $v2;
+
+            $this->assertEquals($count,count($result), 'we expected ' . $count . ' appearances of ' . $xpath . ' . We found ' . count($result) . '. Full response body: ' . $server->httpResponse->body);
+
+        }
+
+    }
     function testWrongUri() {
 
         $xml = '<?xml version="1.0"?>

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



More information about the Pkg-owncloud-commits mailing list