[Pkg-owncloud-commits] [php-sabredav] 46/275: Propertystorage must transfer properties after MOVE requests.
David Prévot
taffit at moszumanska.debian.org
Thu Sep 25 14:55:50 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 4470aef7706803bbb86476d26cb9b23b5f27a8b3
Author: Evert Pot <me at evertpot.com>
Date: Tue May 27 01:43:36 2014 -0400
Propertystorage must transfer properties after MOVE requests.
---
ChangeLog.md | 4 +++
lib/DAV/CorePlugin.php | 7 ++++
.../PropertyStorage/Backend/BackendInterface.php | 13 ++++++++
lib/DAV/PropertyStorage/Backend/PDO.php | 38 ++++++++++++++++++++++
lib/DAV/PropertyStorage/Plugin.php | 23 +++++++++++--
.../PropertyStorage/Backend/AbstractPDOTest.php | 34 +++++++++++++++++++
tests/Sabre/DAV/PropertyStorage/Backend/Mock.php | 30 +++++++++++++++++
7 files changed, 147 insertions(+), 2 deletions(-)
diff --git a/ChangeLog.md b/ChangeLog.md
index 51ab79f..974476e 100644
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -3,11 +3,15 @@ ChangeLog
2.1.0-alpha1 (2014-??-??)
-------------------------
+* Changed: PropertyStorage backends now have a `move` method.
+* Added: `beforeMove`, and `afterMove` events.
+* #460: PropertyStorage must move properties during MOVE requests
2.0.1 (2014-??-??)
* #459: PROPFIND requests on Files with no Depth header would return a fatal
error.
+
2.0.0 (2014-05-22)
------------------
diff --git a/lib/DAV/CorePlugin.php b/lib/DAV/CorePlugin.php
index 09b8ff0..5a7bb9e 100644
--- a/lib/DAV/CorePlugin.php
+++ b/lib/DAV/CorePlugin.php
@@ -639,7 +639,14 @@ class CorePlugin extends ServerPlugin {
if (!$this->server->emit('beforeUnbind',[$path])) return false;
if (!$this->server->emit('beforeBind',[$moveInfo['destination']])) return false;
+ if (!$this->server->emit('beforeMove', [$path, $moveInfo['destination']])) return false;
$this->server->tree->move($path, $moveInfo['destination']);
+
+ // Its important afterMove is called before afterUnbind, because it
+ // allows systems to transfer data from one path to another.
+ // PropertyStorage uses this. If afterUnbind was first, it would clean
+ // up all the properties before it has a chance.
+ !$this->server->emit('afterMove', [$path, $moveInfo['destination']]);
$this->server->emit('afterUnbind',[$path]);
$this->server->emit('afterBind',[$moveInfo['destination']]);
diff --git a/lib/DAV/PropertyStorage/Backend/BackendInterface.php b/lib/DAV/PropertyStorage/Backend/BackendInterface.php
index c2e03d5..e4f9e58 100644
--- a/lib/DAV/PropertyStorage/Backend/BackendInterface.php
+++ b/lib/DAV/PropertyStorage/Backend/BackendInterface.php
@@ -45,4 +45,17 @@ interface BackendInterface {
*/
public function delete($path);
+ /**
+ * This method is called after a successful MOVE
+ *
+ * This should be used to migrate all properties from one path to another.
+ * Note that entire collections may be moved, so ensure that all properties
+ * for children are also moved along.
+ *
+ * @param string $source
+ * @param string $destination
+ * @return void
+ */
+ public function move($source, $destination);
+
}
diff --git a/lib/DAV/PropertyStorage/Backend/PDO.php b/lib/DAV/PropertyStorage/Backend/PDO.php
index 08ab0d6..3b2d23d 100644
--- a/lib/DAV/PropertyStorage/Backend/PDO.php
+++ b/lib/DAV/PropertyStorage/Backend/PDO.php
@@ -104,4 +104,42 @@ class PDO implements BackendInterface {
}
+ /**
+ * This method is called after a successful MOVE
+ *
+ * This should be used to migrate all properties from one path to another.
+ * Note that entire collections may be moved, so ensure that all properties
+ * for children are also moved along.
+ *
+ * @param string $source
+ * @param string $destination
+ * @return void
+ */
+ public function move($source, $destination) {
+
+ // I don't know a way to write this all in a single sql query that's
+ // also compatible across db engines, so we're letting PHP do all the
+ // updates. Much slower, but it should still be pretty fast in most
+ // cases.
+ $select = $this->pdo->prepare('SELECT id, path FROM propertystorage WHERE path = ? OR path LIKE ?');
+ $select->execute([$source, $source . '/%']);
+
+ $update = $this->pdo->prepare('UPDATE propertystorage SET path = ? WHERE id = ?');
+ while($row = $select->fetch(\PDO::FETCH_ASSOC)) {
+
+ // Sanity check. SQL may select too many records, such as records
+ // with different cases.
+ if ($row['path'] !== $source && strpos($row['path'], $source . '/')!==0) continue;
+
+ $trailingPart = substr($row['path'], strlen($source)+1);
+ $newPath = $destination;
+ if ($trailingPart) {
+ $newPath.='/' . $trailingPart;
+ }
+ $update->execute([$newPath, $row['id']]);
+
+ }
+
+ }
+
}
diff --git a/lib/DAV/PropertyStorage/Plugin.php b/lib/DAV/PropertyStorage/Plugin.php
index f3dbc59..9d2872a 100644
--- a/lib/DAV/PropertyStorage/Plugin.php
+++ b/lib/DAV/PropertyStorage/Plugin.php
@@ -46,8 +46,9 @@ class Plugin extends ServerPlugin {
*/
public function initialize(Server $server) {
- $server->on('propFind', [$this, 'propFind'], 130);
- $server->on('propPatch', [$this, 'propPatch'], 300);
+ $server->on('propFind', [$this, 'propFind'], 130);
+ $server->on('propPatch', [$this, 'propPatch'], 300);
+ $server->on('afterMove', [$this, 'afterMove']);
$server->on('afterUnbind', [$this, 'afterUnbind']);
}
@@ -103,4 +104,22 @@ class Plugin extends ServerPlugin {
}
+ /**
+ * Called after a node is moved.
+ *
+ * This allows the backend to move all the associated properties.
+ *
+ * @param string $path
+ * @return void
+ */
+ public function afterMove($source, $destination) {
+
+ if ($this->pathFilter && !$this->pathFilter($source)) return;
+ // If the destination is filtered, afterUnbind will handle cleaning up
+ // the properties.
+ if ($this->pathFilter && !$this->pathFilter($destination)) return;
+
+ $this->backend->move($source, $destination);
+
+ }
}
diff --git a/tests/Sabre/DAV/PropertyStorage/Backend/AbstractPDOTest.php b/tests/Sabre/DAV/PropertyStorage/Backend/AbstractPDOTest.php
index cb96100..31f56f2 100644
--- a/tests/Sabre/DAV/PropertyStorage/Backend/AbstractPDOTest.php
+++ b/tests/Sabre/DAV/PropertyStorage/Backend/AbstractPDOTest.php
@@ -93,4 +93,38 @@ abstract class AbstractPDOTest extends \PHPUnit_Framework_TestCase {
}
+ /**
+ * @depends testPropFind
+ */
+ function testMove() {
+
+ $backend = $this->getBackend();
+ // Creating a new child property.
+ $propPatch = new PropPatch(['{DAV:}displayname' => 'child']);
+ $backend->propPatch('dir/child', $propPatch);
+ $propPatch->commit();
+
+ $backend->move('dir','dir2');
+
+ // Old 'dir'
+ $propFind = new PropFind('dir', ['{DAV:}displayname']);
+ $backend->propFind('dir', $propFind);
+ $this->assertEquals(null, $propFind->get('{DAV:}displayname'));
+
+ // Old 'dir/child'
+ $propFind = new PropFind('dir/child', ['{DAV:}displayname']);
+ $backend->propFind('dir/child', $propFind);
+ $this->assertEquals(null, $propFind->get('{DAV:}displayname'));
+
+ // New 'dir2'
+ $propFind = new PropFind('dir2', ['{DAV:}displayname']);
+ $backend->propFind('dir2', $propFind);
+ $this->assertEquals('Directory', $propFind->get('{DAV:}displayname'));
+
+ // New 'dir2/child'
+ $propFind = new PropFind('dir2/child', ['{DAV:}displayname']);
+ $backend->propFind('dir2/child', $propFind);
+ $this->assertEquals('child', $propFind->get('{DAV:}displayname'));
+ }
+
}
diff --git a/tests/Sabre/DAV/PropertyStorage/Backend/Mock.php b/tests/Sabre/DAV/PropertyStorage/Backend/Mock.php
index d5769aa..87e7280 100644
--- a/tests/Sabre/DAV/PropertyStorage/Backend/Mock.php
+++ b/tests/Sabre/DAV/PropertyStorage/Backend/Mock.php
@@ -81,4 +81,34 @@ class Mock implements BackendInterface {
}
+ /**
+ * This method is called after a successful MOVE
+ *
+ * This should be used to migrate all properties from one path to another.
+ * Note that entire collections may be moved, so ensure that all properties
+ * for children are also moved along.
+ *
+ * @param string $source
+ * @param string $destination
+ * @return void
+ */
+ public function move($source, $destination) {
+
+ foreach($this->data as $path => $props) {
+
+ if ($path === $source) {
+ $this->data[$destination] = $props;
+ unset($this->data[$path]);
+ continue;
+ }
+
+ if (strpos($path, $source . '/')===0) {
+ $this->data[$destination . substr($path, strlen($source)+1)] = $props;
+ unset($this->data[$path]);
+ }
+
+ }
+
+ }
+
}
--
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