[Pkg-owncloud-commits] [php-sabredav] 36/163: Refactoring the property-updating system. Work in progress.
David Prévot
taffit at moszumanska.debian.org
Tue May 20 18:54:51 UTC 2014
This is an automated email from the git hooks/post-receive script.
taffit pushed a commit to annotated tag upstream/2.0.0_beta1
in repository php-sabredav.
commit 7a1a7fdb755096f0b7445f8a41ead1fbfa7cc716
Author: Evert Pot <evert at rooftopsolutions.nl>
Date: Fri Apr 4 23:24:47 2014 -0400
Refactoring the property-updating system. Work in progress.
---
.gitignore | 35 ++-
lib/Sabre/DAV/CorePlugin.php | 64 ++++-
lib/Sabre/DAV/FSExt/Node.php | 41 +--
lib/Sabre/DAV/IProperties.php | 37 +--
lib/Sabre/DAV/PropPatch.php | 342 +++++++++++++++++++++++
lib/Sabre/DAV/Server.php | 41 ++-
lib/Sabre/DAV/Tree.php | 6 +-
tests/Sabre/DAV/FSExt/NodeTest.php | 35 ++-
tests/Sabre/DAV/HTTPPreferParsingTest.php | 9 +-
tests/Sabre/DAV/Mock/PropertiesNode.php | 56 ++++
tests/Sabre/DAV/PropPatchTest.php | 127 +++++++++
tests/Sabre/DAV/ServerPropsInfiniteDepthTest.php | 45 +--
tests/Sabre/DAV/ServerPropsTest.php | 32 ---
tests/Sabre/DAV/TreeTest.php | 20 +-
14 files changed, 730 insertions(+), 160 deletions(-)
diff --git a/.gitignore b/.gitignore
index 5514165..a0b83ed 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,23 +1,34 @@
-docs/api
-docs/wikidocs
-build.properties
-build
-public
-data
-fileserver.php
-fileserver2.php
-calendarserver.php
-groupwareserver.php
-package.xml
-tmpdata
+# Unit tests
tests/temp
tests/.sabredav
+tests/cov
+
+# ViM
*.swp
+
+# Composer
composer.lock
vendor
+# Composer binaries
bin/phing
bin/phpunit
bin/vobject
bin/phpdocmd
bin/phpunit
+
+# Various debugging/testing stuff
+fileserver.php
+fileserver2.php
+calendarserver.php
+groupwareserver.php
+tmpdata
+public
+
+# Build
+build
+build.properties
+
+# Docs
+docs/api
+docs/wikidocs
diff --git a/lib/Sabre/DAV/CorePlugin.php b/lib/Sabre/DAV/CorePlugin.php
index 4bef056..1d47c3b 100644
--- a/lib/Sabre/DAV/CorePlugin.php
+++ b/lib/Sabre/DAV/CorePlugin.php
@@ -43,6 +43,9 @@ class CorePlugin extends ServerPlugin {
$server->on('method:COPY', [$this, 'httpCopy']);
$server->on('method:REPORT', [$this, 'httpReport']);
+ $server->on('propPatch', [$this, 'propPatchProtectedPropertyCheck'], 100);
+ $server->on('propPatch', [$this, 'propPatchNodeUpdate'], 200);
+
}
/**
@@ -377,7 +380,7 @@ class CorePlugin extends ServerPlugin {
// request was succesful, and don't need to return the
// multi-status.
$ok = true;
- foreach($result as $code=>$prop) {
+ foreach($result as $prop=>$code) {
if ((int)$code > 299) {
$ok = false;
}
@@ -395,8 +398,20 @@ class CorePlugin extends ServerPlugin {
$response->setStatus(207);
$response->setHeader('Content-Type','application/xml; charset=utf-8');
+
+ // Reorganizing the result for generateMultiStatus
+ $multiStatus = [];
+ foreach($result as $propertyName => $code) {
+ if (isset($multiStatus[$code])) {
+ $multiStatus[$code][$propertyName] = null;
+ } else {
+ $multiStatus[$code] = [$propertyName => null];
+ }
+ }
+ $multiStatus['href'] = $path;
+
$response->setBody(
- $this->server->generateMultiStatus([$result])
+ $this->server->generateMultiStatus([$multiStatus])
);
// Sending back false will interupt the event chain and tell the server
@@ -713,4 +728,49 @@ class CorePlugin extends ServerPlugin {
}
+ /**
+ * This method is called during property updates.
+ *
+ * Here we check if a user attempted to update a protected property and
+ * ensure that the process fails if this is the case.
+ *
+ * @param PropPatch $propPatch
+ * @return void
+ */
+ public function propPatchProtectedPropertyCheck($path, PropPatch $propPatch) {
+
+ // Comparing the mutation list to the list of propetected properties.
+ $mutations = $propPatch->getMutations();
+
+ $protected = array_intersect(
+ $this->server->protectedProperties,
+ array_keys($mutations)
+ );
+
+ if ($protected) {
+ $propPatch->setRemainingResultCode($protected, 403);
+ }
+
+ }
+
+ /**
+ * This method is called during property updates.
+ *
+ * Here we check if a node implements IProperties and let the node handle
+ * updating of (some) properties.
+ *
+ * @param PropPatch $propPatch
+ * @return void
+ */
+ public function propPatchNodeUpdate($path, PropPatch $propPatch) {
+
+ // This should trigger a 404 if the node doesn't exist.
+ $node = $this->server->tree->getNodeForPath($path);
+
+ if ($node instanceof IProperties) {
+ $node->propPatch($propPatch);
+ }
+
+ }
+
}
diff --git a/lib/Sabre/DAV/FSExt/Node.php b/lib/Sabre/DAV/FSExt/Node.php
index 906eda6..e736ae0 100644
--- a/lib/Sabre/DAV/FSExt/Node.php
+++ b/lib/Sabre/DAV/FSExt/Node.php
@@ -4,7 +4,8 @@ namespace Sabre\DAV\FSExt;
use
Sabre\DAV,
- Sabre\HTTP\URLUtil;
+ Sabre\HTTP\URLUtil,
+ Sabre\DAV\PropPatch;
/**
* Base node-class
@@ -18,31 +19,39 @@ use
abstract class Node extends DAV\FS\Node implements DAV\IProperties {
/**
- * Updates properties on this node,
+ * Updates properties on this node.
*
- * @param array $properties
- * @see Sabre\DAV\IProperties::updateProperties
+ * This method received a PropPatch object, which contains all the
+ * information about the update.
+ *
+ * To update specific properties, call the 'handle' method on this object.
+ * Read the PropPatch documentation for more information.
+ *
+ * @param array $mutations
* @return bool|array
*/
- public function updateProperties($properties) {
+ public function propPatch(PropPatch $proppatch) {
- $resourceData = $this->getResourceData();
+ $proppatch->handleRemaining(function(array $properties) {
- foreach($properties as $propertyName=>$propertyValue) {
+ $resourceData = $this->getResourceData();
+ foreach($properties as $propertyName=>$propertyValue) {
- // If it was null, we need to delete the property
- if (is_null($propertyValue)) {
- if (isset($resourceData['properties'][$propertyName])) {
- unset($resourceData['properties'][$propertyName]);
+ // If it was null, we need to delete the property
+ if (is_null($propertyValue)) {
+ if (isset($resourceData['properties'][$propertyName])) {
+ unset($resourceData['properties'][$propertyName]);
+ }
+ } else {
+ $resourceData['properties'][$propertyName] = $propertyValue;
}
- } else {
- $resourceData['properties'][$propertyName] = $propertyValue;
+
}
+ $this->putResourceData($resourceData);
- }
+ return true;
+ });
- $this->putResourceData($resourceData);
- return true;
}
/**
diff --git a/lib/Sabre/DAV/IProperties.php b/lib/Sabre/DAV/IProperties.php
index fc10cfc..5a35cf8 100644
--- a/lib/Sabre/DAV/IProperties.php
+++ b/lib/Sabre/DAV/IProperties.php
@@ -14,41 +14,18 @@ namespace Sabre\DAV;
interface IProperties extends INode {
/**
- * Updates properties on this node,
+ * Updates properties on this node.
*
- * The properties array uses the propertyName in clark-notation as key,
- * and the array value for the property value. In the case a property
- * should be deleted, the property value will be null.
+ * This method received a PropPatch object, which contains all the
+ * information about the update.
*
- * This method must be atomic. If one property cannot be changed, the
- * entire operation must fail.
- *
- * If the operation was successful, true can be returned.
- * If the operation failed, false can be returned.
- *
- * Deletion of a non-existent property is always successful.
- *
- * Lastly, it is optional to return detailed information about any
- * failures. In this case an array should be returned with the following
- * structure:
- *
- * array(
- * 403 => array(
- * '{DAV:}displayname' => null,
- * ),
- * 424 => array(
- * '{DAV:}owner' => null,
- * )
- * )
- *
- * In this example it was forbidden to update {DAV:}displayname.
- * (403 Forbidden), which in turn also caused {DAV:}owner to fail
- * (424 Failed Dependency) because the request needs to be atomic.
+ * To update specific properties, call the 'handle' method on this object.
+ * Read the PropPatch documentation for more information.
*
* @param array $mutations
* @return bool|array
*/
- function updateProperties($mutations);
+ public function propPatch(PropPatch $proppatch);
/**
* Returns a list of properties for this nodes.
@@ -65,7 +42,7 @@ interface IProperties extends INode {
* @param array $properties
* @return array
*/
- function getProperties($properties);
+ public function getProperties($properties);
}
diff --git a/lib/Sabre/DAV/PropPatch.php b/lib/Sabre/DAV/PropPatch.php
new file mode 100644
index 0000000..6379b0c
--- /dev/null
+++ b/lib/Sabre/DAV/PropPatch.php
@@ -0,0 +1,342 @@
+<?php
+
+namespace Sabre\DAV;
+
+/**
+ * This class represents a set of properties that are going to be updated.
+ *
+ * Usually this is simply a PROPPATCH request, but it can also be used for
+ * internal updates.
+ *
+ * Property updates must always be atomic. This means that a property update
+ * must either completely succeed, or completely fail.
+ *
+ * @copyright Copyright (C) 2007-2014 fruux GmbH. All rights reserved.
+ * @author Evert Pot (http://evertpot.com/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class PropPatch {
+
+ /**
+ * Properties that are being updated.
+ *
+ * This is a key-value list. If the value is null, the property is supposed
+ * to be deleted.
+ *
+ * @var array
+ */
+ protected $mutations;
+
+ /**
+ * A list of properties and the result of the update. The result is in the
+ * form of a HTTP status code.
+ *
+ * @var array
+ */
+ protected $result = [];
+
+ /**
+ * This is the list of callbacks when we're performing the actual update.
+ *
+ * @var array
+ */
+ protected $propertyUpdateCallbacks = [];
+
+ /**
+ * This property will be set to true if the operation failed.
+ *
+ * @var bool
+ */
+ protected $failed = false;
+
+ /**
+ * Constructor
+ *
+ * @param array $mutations A list of updates
+ */
+ public function __construct(array $mutations) {
+
+ $this->mutations = $mutations;
+
+ }
+
+ /**
+ * Call this function if you wish to handle updating certain properties.
+ * For instance, your class may be responsible for handling updates for the
+ * {DAV:}displayname property.
+ *
+ * In that case, call this method with the first argument
+ * "{DAV:}displayname" and a second argument that's a method that does the
+ * actual updating.
+ *
+ * It's possible to specify more than one property.
+ *
+ * @param string|array $properties
+ * @param callable $callback
+ * @return void
+ */
+ public function handle($properties, callable $callback) {
+
+ $usedProperties = [];
+ foreach((array)$properties as $propertyName) {
+
+ if (isset($this->mutations[$propertyName]) && !isset($this->result[$propertyName])) {
+
+ $usedProperties[] = $propertyName;
+ // HTTP Accepted
+ $this->result[$propertyName] = 202;
+ }
+
+ }
+
+ // Only registering if there's any unhandled properties.
+ if (!$usedProperties) {
+ return;
+ }
+ $this->propertyUpdateCallbacks[] = [
+ // We need to set this as a string, so the commit function knows
+ // how to format the arguments to the callback.
+ is_string($properties)?$properties:$usedProperties,
+ $callback
+ ];
+
+ }
+
+ /**
+ * Call this function if you wish to handle _all_ properties that haven't
+ * been handled by anything else yet. Note that you effectively claim with
+ * this that you promise to process _all_ properties that are coming in.
+ *
+ * @param string|array $properties
+ * @param callable $callback
+ * @return void
+ */
+ public function handleRemaining(callable $callback) {
+
+ $properties = $this->getRemainingMutations();
+ if (!$properties) {
+ // Nothing to do, don't register callback
+ return;
+ }
+
+ foreach($properties as $propertyName) {
+ // HTTP Accepted
+ $this->result[$propertyName] = 202;
+
+ $this->propertyUpdateCallbacks[] = [
+ $properties,
+ $callback
+ ];
+ }
+
+ }
+
+ /**
+ * Sets the result code for one or more properties.
+ *
+ * Properties can either be specified as a single string, or an array of
+ * strings.
+ *
+ * @param string|array $properties
+ * @param int $resultCode
+ * @return void
+ */
+ public function setResultCode($properties, $resultCode) {
+
+ foreach((array)$properties as $propertyName) {
+ $this->result[$propertyName] = $resultCode;
+ }
+
+ if ($resultCode>=400) {
+ $this->failed = true;
+ }
+
+ }
+
+ /**
+ * Sets the result code for all properties that did not have a result yet.
+ *
+ * @param int $resultCode
+ * @return void
+ */
+ public function setRemainingResultCode($resultCode) {
+
+ $this->setResultCode(
+ $this->getRemainingMutations(),
+ $resultCode
+ );
+
+ }
+
+ /**
+ * Returns the list of properties that don't have a result code yet.
+ *
+ * @return array
+ */
+ public function getRemainingMutations() {
+
+ $remaining = [];
+ foreach($this->mutations as $propertyName => $propValue) {
+ if (!isset($this->result[$propertyName])) {
+ $remaining[] = $propertyName;
+ }
+ }
+
+ return $remaining;
+
+ }
+
+ /**
+ * Performs the actual update, and calls all callbacks.
+ *
+ * This method returns true or false depending on if the operation was
+ * successful.
+ *
+ * @return void
+ */
+ public function commit() {
+
+ // First we validate if every property has a handler
+ foreach($this->mutations as $propertyName => $value) {
+
+ if (!isset($this->result[$propertyName])) {
+ $this->failed = true;
+ $this->result[$propertyName] = 403;
+ }
+
+ }
+
+ foreach($this->propertyUpdateCallbacks as $callbackInfo) {
+
+ if (is_string($callbackInfo[0])) {
+ $this->doCallbackSingleProp($callbackInfo[0], $callbackInfo[1]);
+ } else {
+ $this->doCallbackMultiProp($callbackInfo[0], $callbackInfo[1]);
+ }
+ if ($this->failed) {
+ break;
+ }
+
+ }
+
+ /**
+ * If anywhere in this operation updating a property failed, we must
+ * update all other properties accordingly.
+ */
+ if ($this->failed) {
+
+ foreach($this->result as $propertyName=>$status) {
+ if ($status === 202) {
+ // Failed dependency
+ $this->result[$propertyName][$status] = 424;
+ }
+ }
+
+ }
+
+ return !$this->failed;
+
+ }
+
+ /**
+ * Executes a property callback with the single-property syntax.
+ *
+ * @param string $propertyName
+ * @param callable $callback
+ * @return void
+ */
+ private function doCallBackSingleProp($propertyName, callable $callback) {
+
+ $result = $callback($this->mutations[$propertyName]);
+ if (is_bool($result)) {
+ if ($result) {
+ if (is_null($this->mutations[$propertyName])) {
+ // Delete
+ $result = 204;
+ } else {
+ // Update
+ $result = 200;
+ }
+ } else {
+ // Fail
+ $result = 403;
+ }
+ }
+ if (!is_int($result)) {
+ throw new UnexpectedValueException('A callback sent to handle() did not return an int or a bool');
+ }
+ $this->mutations[$propertyName] = $result;
+ if ($result>=400) {
+ $this->failed = true;
+ }
+
+ }
+
+ /**
+ * Executes a property callback with the multi-property syntax.
+ *
+ * @param array $propertyName
+ * @param callable $callback
+ * @return void
+ */
+ private function doCallBackMultiProp(array $propertyList, callable $callback) {
+
+ $argument = [];
+ foreach($propertyList as $propertyName) {
+ $argument[$propertyName] = $this->mutations[$propertyName];
+ }
+
+ $result = $callback($propertyName);
+
+ if (is_array($result)) {
+ foreach($propertyList as $propertyName) {
+ if (!isset($result[$propertyName])) {
+ $resultCode = 500;
+ }
+ $resultCode = $result[$propertyName];
+ if ($resultCode >= 400) {
+ $this->failed = true;
+ }
+ $this->result[$propertyName] = $resultCode;
+
+ }
+ } elseif ($result === true) {
+
+ // Success
+ foreach($argument as $propertyName=>$propertyValue) {
+ $this->result[$propertyName] = is_null($propertyValue)?204:200;
+ }
+
+ } elseif ($result === false) {
+ // Fail :(
+ $this->failed = true;
+ foreach($propertyList as $propertyName) {
+ $this->result[$propertyName] = 403;
+ }
+ }
+
+ }
+
+ /**
+ * Returns the result of the operation.
+ *
+ * @return array
+ */
+ public function getResult() {
+
+ return $this->result;
+
+ }
+
+ /**
+ * Returns the full list of mutations
+ *
+ * @return array
+ */
+ public function getMutations() {
+
+ return $this->mutations;
+
+ }
+
+}
diff --git a/lib/Sabre/DAV/Server.php b/lib/Sabre/DAV/Server.php
index 588feca..2a2ace5 100644
--- a/lib/Sabre/DAV/Server.php
+++ b/lib/Sabre/DAV/Server.php
@@ -1281,7 +1281,19 @@ class Server extends EventEmitter {
// Re-throwing exception
if ($exception) throw $exception;
- return $errorResult;
+ // Re-arranging the result so it makes sense for
+ // generateMultiStatus.
+ $newResult = [
+ 'href' => $uri,
+ ];
+ foreach($errorResult as $property=>$code) {
+ if (!isset($newResult[$code])) {
+ $newResult[$code] = [$property => null];
+ } else {
+ $newResult[$code][$property] = null;
+ }
+ }
+ return $newResult;
}
}
@@ -1300,15 +1312,31 @@ class Server extends EventEmitter {
* Note that this request should either completely succeed, or
* completely fail.
*
- * The response is an array with statuscodes for keys, which in turn
- * contain arrays with propertynames. This response can be used
- * to generate a multistatus body.
+ * The response is an array with properties for keys, and http status codes
+ * as their values.
*
- * @param string $uri
+ * @param string $path
* @param array $properties
* @return array
*/
- public function updateProperties($uri, array $properties) {
+ public function updateProperties($path, array $properties) {
+
+ $propPatch = new PropPatch($properties);
+ $this->emit('propPatch', [$path, $propPatch]);
+ $propPatch->commit();
+
+ return $propPatch->getResult();
+
+ /*
+ $restructuredResult = [];
+ foreach($result as $key=>$value) {
+ if (isset($restructedResult[$value])) {
+ $restructedResult[$value] = [
+ $key => null,
+ ];
+ }
+ }
+
// we'll start by grabbing the node, this will throw the appropriate
// exceptions if it doesn't.
@@ -1405,6 +1433,7 @@ class Server extends EventEmitter {
}
$result['href'] = $uri;
return $result;
+ */
}
diff --git a/lib/Sabre/DAV/Tree.php b/lib/Sabre/DAV/Tree.php
index c15c4ea..2ce8fff 100644
--- a/lib/Sabre/DAV/Tree.php
+++ b/lib/Sabre/DAV/Tree.php
@@ -177,7 +177,7 @@ abstract class Tree {
* @param string $destinationName
* @return void
*/
- protected function copyNode(INode $source,ICollection $destinationParent,$destinationName = null) {
+ protected function copyNode(INode $source, ICollection $destinationParent, $destinationName = null) {
if (!$destinationName) $destinationName = $source->getName();
@@ -210,7 +210,9 @@ abstract class Tree {
if ($source instanceof IProperties && $destination instanceof IProperties) {
$props = $source->getProperties(array());
- $destination->updateProperties($props);
+ $propPatch = new PropPatch($props);
+ $destination->propPatch($propPatch);
+ $propPatch->commit();
}
diff --git a/tests/Sabre/DAV/FSExt/NodeTest.php b/tests/Sabre/DAV/FSExt/NodeTest.php
index 275075b..3b20a58 100644
--- a/tests/Sabre/DAV/FSExt/NodeTest.php
+++ b/tests/Sabre/DAV/FSExt/NodeTest.php
@@ -1,7 +1,9 @@
<?php
namespace Sabre\DAV\FSExt;
+
use Sabre\DAV;
+use Sabre\DAV\PropPatch;
require_once 'Sabre/TestUtil.php';
@@ -29,13 +31,11 @@ class NodeTest extends \PHPUnit_Framework_TestCase {
'{http://sabredav.org/NS/2010}test2' => 'bar',
);
- $result = $file->updateProperties($properties);
- $expected = true;
-
- $this->assertEquals($expected, $result);
+ $propPatch = new PropPatch($properties);
+ $file->propPatch($propPatch);
+ $propPatch->commit();
$getProperties = $file->getProperties(array_keys($properties));
-
$this->assertEquals($properties, $getProperties);
}
@@ -51,7 +51,9 @@ class NodeTest extends \PHPUnit_Framework_TestCase {
'{http://sabredav.org/NS/2010}test2' => 'bar',
);
- $result = $file->updateProperties($mutations);
+ $propPatch = new PropPatch($mutations);
+ $file->propPatch($propPatch);
+ $result = $propPatch->commit();
$this->assertEquals(true, $result);
@@ -60,7 +62,9 @@ class NodeTest extends \PHPUnit_Framework_TestCase {
'{http://sabredav.org/NS/2010}test3' => 'baz',
);
- $result = $file->updateProperties($mutations);
+ $propPatch = new PropPatch($mutations);
+ $file->propPatch($propPatch);
+ $result = $propPatch->commit();
$this->assertEquals(true, $result);
}
@@ -77,7 +81,9 @@ class NodeTest extends \PHPUnit_Framework_TestCase {
'{http://sabredav.org/NS/2010}test2' => 'bar',
);
- $result = $file->updateProperties($mutations);
+ $propPatch = new PropPatch($mutations);
+ $file->propPatch($propPatch);
+ $result = $propPatch->commit();
$this->assertEquals(true, $result);
@@ -86,7 +92,10 @@ class NodeTest extends \PHPUnit_Framework_TestCase {
'{http://sabredav.org/NS/2010}test3' => null
);
- $result = $file->updateProperties($mutations);
+
+ $propPatch = new PropPatch($mutations);
+ $file->propPatch($propPatch);
+ $result = $propPatch->commit();
$this->assertEquals(true, $result);
@@ -109,7 +118,9 @@ class NodeTest extends \PHPUnit_Framework_TestCase {
'{http://sabredav.org/NS/2010}test2' => 'bar',
);
- $result = $file->updateProperties($mutations);
+ $propPatch = new PropPatch($mutations);
+ $file->propPatch($propPatch);
+ $result = $propPatch->commit();
$this->assertEquals(true, $result);
@@ -149,7 +160,9 @@ class NodeTest extends \PHPUnit_Framework_TestCase {
'{http://sabredav.org/NS/2010}test2' => 'bar',
);
- $result = $file->updateProperties($mutations);
+ $propPatch = new PropPatch($mutations);
+ $file->propPatch($propPatch);
+ $result = $propPatch->commit();
$this->assertEquals(true, $result);
diff --git a/tests/Sabre/DAV/HTTPPreferParsingTest.php b/tests/Sabre/DAV/HTTPPreferParsingTest.php
index 73c7926..9eaed82 100644
--- a/tests/Sabre/DAV/HTTPPreferParsingTest.php
+++ b/tests/Sabre/DAV/HTTPPreferParsingTest.php
@@ -155,12 +155,11 @@ BLA
BLA
);
- $this->server->on('updateProperties', function(&$props, &$result) {
+ $this->server->on('propPatch', function($path, PropPatch $propPatch) {
- if (isset($props['{DAV:}something'])) {
- unset($props['{DAV:}something']);
- $result[200]['{DAV:}something'] = null;
- }
+ $propPatch->handle('{DAV:}something', function($props) {
+ return true;
+ });
});
diff --git a/tests/Sabre/DAV/Mock/PropertiesNode.php b/tests/Sabre/DAV/Mock/PropertiesNode.php
new file mode 100644
index 0000000..ef1d285
--- /dev/null
+++ b/tests/Sabre/DAV/Mock/PropertiesNode.php
@@ -0,0 +1,56 @@
+<?php
+
+namespace Sabre\DAV\Mock;
+
+use
+ Sabre\DAV\IProperties;
+
+/**
+ * A node specifically for testing property-related operations
+ *
+ * @copyright Copyright (C) 2007-2014 fruux GmbH. All rights reserved.
+ * @author Evert Pot (http://evertpot.com/)
+ * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
+ */
+class PropertiesCollection extends Collection implements IProperties {
+
+ public $failMode = false;
+
+ /**
+ * Updates properties on this node.
+ *
+ * This method received a PropPatch object, which contains all the
+ * information about the update.
+ *
+ * To update specific properties, call the 'handle' method on this object.
+ * Read the PropPatch documentation for more information.
+ *
+ * @param array $mutations
+ * @return bool|array
+ */
+ public function propPatch(PropPatch $proppatch) {
+
+ $proppatch->on('commit', function() {
+
+ switch($this->failMode) {
+ case 'updatepropsfalse' : return false;
+ case 'updatepropsarray' :
+ $r = array(402 => array());
+ foreach($updateProperties as $k=>$v) $r[402][$k] = null;
+ return $r;
+ case 'updatepropsobj' :
+ return new \STDClass();
+ }
+
+ });
+
+ }
+
+ function getProperties($requestedPropeties) {
+
+ return array();
+
+ }
+
+
+}
diff --git a/tests/Sabre/DAV/PropPatchTest.php b/tests/Sabre/DAV/PropPatchTest.php
new file mode 100644
index 0000000..87233a1
--- /dev/null
+++ b/tests/Sabre/DAV/PropPatchTest.php
@@ -0,0 +1,127 @@
+<?php
+
+namespace Sabre\DAV;
+
+class PropPatchTest extends \PHPUnit_Framework_TestCase {
+
+ protected $propPatch;
+
+ public function setUp() {
+
+ $this->propPatch = new PropPatch([
+ '{DAV:}displayname' => 'foo',
+ ]);
+
+ }
+
+ public function testHandleSuccess() {
+
+ $hasRan = false;
+
+ $this->propPatch->handle('{DAV:}displayname', function($value) use (&$hasRan) {
+ $hasRan = true;
+ $this->assertEquals('foo', $value);
+ return true;
+ });
+
+ $this->assertTrue($this->propPatch->commit());
+ $result = $this->propPatch->getResult();
+ $this->assertEquals(['{DAV:}displayname' => 200], $result);
+
+ $this->assertTrue($hasRan);
+
+ }
+ public function testHandleNothing() {
+
+ $hasRan = false;
+
+ $this->propPatch->handle('{DAV:}foobar', function($value) use (&$hasRan) {
+ $hasRan = true;
+ });
+
+ $this->assertFalse($hasRan);
+
+ }
+
+ public function testHandleRemaining() {
+
+ $hasRan = false;
+
+ $this->propPatch->handleRemaining(function($mutations) use (&$hasRan) {
+ $hasRan = true;
+ $this->assertEquals(['{DAV:}displayname' => 'foo'], $mutations);
+ return true;
+ });
+
+ $this->assertTrue($this->propPatch->commit());
+ $result = $this->propPatch->getResult();
+ $this->assertEquals(['{DAV:}displayname' => 200], $result);
+
+ $this->assertTrue($hasRan);
+
+ }
+ public function testHandleRemainingNothingToDo() {
+
+ $hasRan = false;
+
+ $this->propPatch->handle('{DAV:}displayname', function() {} );
+ $this->propPatch->handleRemaining(function($mutations) use (&$hasRan) {
+ $hasRan = true;
+ });
+
+ $this->assertFalse($hasRan);
+
+ }
+
+ public function testSetResultCode() {
+
+ $this->propPatch->setResultCode('{DAV:}displayname', 201);
+ $this->assertTrue($this->propPatch->commit());
+ $result = $this->propPatch->getResult();
+ $this->assertEquals(['{DAV:}displayname' => 201], $result);
+
+ }
+
+ public function testSetResultCodeFail() {
+
+ $this->propPatch->setResultCode('{DAV:}displayname', 402);
+ $this->assertFalse($this->propPatch->commit());
+ $result = $this->propPatch->getResult();
+ $this->assertEquals(['{DAV:}displayname' => 402], $result);
+
+ }
+
+ public function testSetRemainingResultCode() {
+
+ $this->propPatch->setRemainingResultCode(204);
+ $this->assertTrue($this->propPatch->commit());
+ $result = $this->propPatch->getResult();
+ $this->assertEquals(['{DAV:}displayname' => 204], $result);
+
+ }
+
+ public function testCommitNoHandler() {
+
+ $this->assertFalse($this->propPatch->commit());
+ $result = $this->propPatch->getResult();
+ $this->assertEquals(['{DAV:}displayname' => 403], $result);
+
+ }
+
+ public function testHandlerNotCalled() {
+
+ $hasRan = false;
+
+ $this->propPatch->setResultCode('{DAV:}displayname', 402);
+ $this->propPatch->handle('{DAV:}displayname', function($value) use (&$hasRan) {
+ $hasRan = true;
+ });
+
+ $this->propPatch->commit();
+
+ // The handler is not supposed to have ran
+ $this->assertFalse($hasRan);
+
+ }
+
+}
diff --git a/tests/Sabre/DAV/ServerPropsInfiniteDepthTest.php b/tests/Sabre/DAV/ServerPropsInfiniteDepthTest.php
index 605714c..4b7a00b 100644
--- a/tests/Sabre/DAV/ServerPropsInfiniteDepthTest.php
+++ b/tests/Sabre/DAV/ServerPropsInfiniteDepthTest.php
@@ -209,10 +209,9 @@ class ServerPropsInfiniteDepthTest extends AbstractServer {
$result = $this->server->updateProperties('/test2.txt',$props);
- $this->assertEquals(array(
- '200' => array('{http://sabredav.org/NS/test}someprop' => null),
- 'href' => '/test2.txt',
- ), $result);
+ $this->assertEquals([
+ '{http://sabredav.org/NS/test}someprop' => 200,
+ ], $result);
}
@@ -230,9 +229,8 @@ class ServerPropsInfiniteDepthTest extends AbstractServer {
$result = $this->server->updateProperties('/test2.txt',$props);
$this->assertEquals(array(
- '424' => array('{http://sabredav.org/NS/test}someprop' => null),
- '403' => array('{DAV:}getcontentlength' => null),
- 'href' => '/test2.txt',
+ '{http://sabredav.org/NS/test}someprop' => array(),
+ '{DAV:}getcontentlength' => array(),
), $result);
}
@@ -379,36 +377,3 @@ class ServerPropsInfiniteDepthTest extends AbstractServer {
}
}
-
-class PropInfiniteDepthTestDirMock extends SimpleCollection implements IProperties {
-
- public $type;
-
- function __construct($type) {
-
- $this->type =$type;
- parent::__construct('root');
-
- }
-
- function updateProperties($updateProperties) {
-
- switch($this->type) {
- case 'updatepropsfalse' : return false;
- case 'updatepropsarray' :
- $r = array(402 => array());
- foreach($updateProperties as $k=>$v) $r[402][$k] = null;
- return $r;
- case 'updatepropsobj' :
- return new \STDClass();
- }
-
- }
-
- function getProperties($requestedPropeties) {
-
- return array();
-
- }
-
-}
diff --git a/tests/Sabre/DAV/ServerPropsTest.php b/tests/Sabre/DAV/ServerPropsTest.php
index ff373b0..d3d07d0 100644
--- a/tests/Sabre/DAV/ServerPropsTest.php
+++ b/tests/Sabre/DAV/ServerPropsTest.php
@@ -378,35 +378,3 @@ class ServerPropsTest extends AbstractServer {
}
-class PropTestDirMock extends SimpleCollection implements IProperties {
-
- public $type;
-
- function __construct($type) {
-
- $this->type =$type;
- parent::__construct('root');
-
- }
-
- function updateProperties($updateProperties) {
-
- switch($this->type) {
- case 'updatepropsfalse' : return false;
- case 'updatepropsarray' :
- $r = array(402 => array());
- foreach($updateProperties as $k=>$v) $r[402][$k] = null;
- return $r;
- case 'updatepropsobj' :
- return new \STDClass();
- }
-
- }
-
- function getProperties($requestedPropeties) {
-
- return array();
-
- }
-
-}
diff --git a/tests/Sabre/DAV/TreeTest.php b/tests/Sabre/DAV/TreeTest.php
index 90df642..49470e1 100644
--- a/tests/Sabre/DAV/TreeTest.php
+++ b/tests/Sabre/DAV/TreeTest.php
@@ -164,10 +164,22 @@ class TreeFileTester extends File implements IProperties {
}
- function updateProperties($properties) {
-
- $this->properties = $properties;
- return true;
+ /**
+ * Updates properties on this node.
+ *
+ * This method received a PropPatch object, which contains all the
+ * information about the update.
+ *
+ * To update specific properties, call the 'handle' method on this object.
+ * Read the PropPatch documentation for more information.
+ *
+ * @param array $mutations
+ * @return bool|array
+ */
+ public function propPatch(PropPatch $propPatch) {
+
+ $this->properties = $propPatch->getMutations();
+ $propPatch->setRemainingResultCode(200);
}
--
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