Browse Source
Add a more powerful notify mechanism
Add a more powerful notify mechanism
Signed-off-by: Robin Appelman <robin@icewind.nl>pull/2970/head
No known key found for this signature in database
GPG Key ID: 50F2B59C6DEBBCFE
8 changed files with 423 additions and 39 deletions
-
150apps/files_external/lib/Lib/Notify/SMBNotifyHandler.php
-
50apps/files_external/lib/Lib/Storage/SMB.php
-
65lib/private/Files/Notify/Change.php
-
52lib/private/Files/Notify/RenameChange.php
-
47lib/public/Files/Notify/IChange.php
-
52lib/public/Files/Notify/INotifyHandler.php
-
33lib/public/Files/Notify/IRenameChange.php
-
13lib/public/Files/Storage/INotifyStorage.php
@ -0,0 +1,150 @@ |
|||
<?php |
|||
/** |
|||
* @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl> |
|||
* |
|||
* @author Robin Appelman <robin@icewind.nl> |
|||
* |
|||
* @license GNU AGPL version 3 or any later version |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License as |
|||
* published by the Free Software Foundation, either version 3 of the |
|||
* License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
* |
|||
*/ |
|||
|
|||
namespace OCA\Files_External\Lib\Notify; |
|||
|
|||
use OC\Files\Notify\Change; |
|||
use OC\Files\Notify\RenameChange; |
|||
use OCP\Files\Notify\IChange; |
|||
use OCP\Files\Notify\INotifyHandler; |
|||
|
|||
class SMBNotifyHandler implements INotifyHandler { |
|||
/** |
|||
* @var \Icewind\SMB\INotifyHandler |
|||
*/ |
|||
private $shareNotifyHandler; |
|||
|
|||
/** |
|||
* @var string |
|||
*/ |
|||
private $root; |
|||
|
|||
private $oldRenamePath = null; |
|||
|
|||
/** |
|||
* SMBNotifyHandler constructor. |
|||
* |
|||
* @param \Icewind\SMB\INotifyHandler $shareNotifyHandler |
|||
* @param string $root |
|||
*/ |
|||
public function __construct(\Icewind\SMB\INotifyHandler $shareNotifyHandler, $root) { |
|||
$this->shareNotifyHandler = $shareNotifyHandler; |
|||
$this->root = $root; |
|||
} |
|||
|
|||
private function relativePath($fullPath) { |
|||
if ($fullPath === $this->root) { |
|||
return ''; |
|||
} else if (substr($fullPath, 0, strlen($this->root)) === $this->root) { |
|||
return substr($fullPath, strlen($this->root)); |
|||
} else { |
|||
return null; |
|||
} |
|||
} |
|||
|
|||
public function listen(callable $callback) { |
|||
$oldRenamePath = null; |
|||
$this->shareNotifyHandler->listen(function (\Icewind\SMB\Change $shareChange) use ($callback) { |
|||
$change = $this->mapChange($shareChange); |
|||
if (!is_null($change)) { |
|||
return $callback($change); |
|||
} else { |
|||
return true; |
|||
} |
|||
}); |
|||
} |
|||
|
|||
/** |
|||
* Get all changes detected since the start of the notify process or the last call to getChanges |
|||
* |
|||
* @return IChange[] |
|||
*/ |
|||
public function getChanges() { |
|||
$shareChanges = $this->shareNotifyHandler->getChanges(); |
|||
$changes = []; |
|||
foreach ($shareChanges as $shareChange) { |
|||
$change = $this->mapChange($shareChange); |
|||
if ($change) { |
|||
$changes[] = $change; |
|||
} |
|||
} |
|||
return $changes; |
|||
} |
|||
|
|||
/** |
|||
* Stop listening for changes |
|||
* |
|||
* Note that any pending changes will be discarded |
|||
*/ |
|||
public function stop() { |
|||
$this->shareNotifyHandler->stop(); |
|||
} |
|||
|
|||
/** |
|||
* @param \Icewind\SMB\Change $change |
|||
* @return IChange|null |
|||
*/ |
|||
private function mapChange(\Icewind\SMB\Change $change) { |
|||
$path = $this->relativePath($change->getPath()); |
|||
if (is_null($path)) { |
|||
return null; |
|||
} |
|||
if ($change->getCode() === \Icewind\SMB\INotifyHandler::NOTIFY_RENAMED_OLD) { |
|||
$this->oldRenamePath = $path; |
|||
return null; |
|||
} |
|||
$type = $this->mapNotifyType($change->getCode()); |
|||
if (is_null($type)) { |
|||
return null; |
|||
} |
|||
if ($type === IChange::RENAMED) { |
|||
if (!is_null($this->oldRenamePath)) { |
|||
$result = new RenameChange($type, $this->oldRenamePath, $path); |
|||
$this->oldRenamePath = null; |
|||
} else { |
|||
$result = null; |
|||
} |
|||
} else { |
|||
$result = new Change($type, $path); |
|||
} |
|||
return $result; |
|||
} |
|||
|
|||
private function mapNotifyType($smbType) { |
|||
switch ($smbType) { |
|||
case \Icewind\SMB\INotifyHandler::NOTIFY_ADDED: |
|||
return IChange::ADDED; |
|||
case \Icewind\SMB\INotifyHandler::NOTIFY_REMOVED: |
|||
return IChange::REMOVED; |
|||
case \Icewind\SMB\INotifyHandler::NOTIFY_MODIFIED: |
|||
case \Icewind\SMB\INotifyHandler::NOTIFY_ADDED_STREAM: |
|||
case \Icewind\SMB\INotifyHandler::NOTIFY_MODIFIED_STREAM: |
|||
case \Icewind\SMB\INotifyHandler::NOTIFY_REMOVED_STREAM: |
|||
return IChange::MODIFIED; |
|||
case \Icewind\SMB\INotifyHandler::NOTIFY_RENAMED_NEW: |
|||
return IChange::RENAMED; |
|||
default: |
|||
return null; |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,65 @@ |
|||
<?php |
|||
/** |
|||
* @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl> |
|||
* |
|||
* @author Robin Appelman <robin@icewind.nl> |
|||
* |
|||
* @license GNU AGPL version 3 or any later version |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License as |
|||
* published by the Free Software Foundation, either version 3 of the |
|||
* License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
* |
|||
*/ |
|||
|
|||
namespace OC\Files\Notify; |
|||
|
|||
use OCP\Files\Notify\IChange; |
|||
|
|||
class Change implements IChange { |
|||
/** @var int */ |
|||
private $type; |
|||
|
|||
/** @var string */ |
|||
private $path; |
|||
|
|||
/** |
|||
* Change constructor. |
|||
* |
|||
* @param int $type |
|||
* @param string $path |
|||
*/ |
|||
public function __construct($type, $path) { |
|||
$this->type = $type; |
|||
$this->path = $path; |
|||
} |
|||
|
|||
/** |
|||
* Get the type of the change |
|||
* |
|||
* @return int IChange::ADDED, IChange::REMOVED, IChange::MODIFIED or IChange::RENAMED |
|||
*/ |
|||
public function getType() { |
|||
return $this->type; |
|||
} |
|||
|
|||
/** |
|||
* Get the path of the file that was changed relative to the root of the storage |
|||
* |
|||
* Note, for rename changes this path is the old path for the file |
|||
* |
|||
* @return mixed |
|||
*/ |
|||
public function getPath() { |
|||
return $this->path; |
|||
} |
|||
} |
@ -0,0 +1,52 @@ |
|||
<?php |
|||
/** |
|||
* @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl> |
|||
* |
|||
* @author Robin Appelman <robin@icewind.nl> |
|||
* |
|||
* @license GNU AGPL version 3 or any later version |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License as |
|||
* published by the Free Software Foundation, either version 3 of the |
|||
* License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
* |
|||
*/ |
|||
|
|||
namespace OC\Files\Notify; |
|||
|
|||
use OCP\Files\Notify\IRenameChange; |
|||
|
|||
class RenameChange extends Change implements IRenameChange { |
|||
/** @var string */ |
|||
private $targetPath; |
|||
|
|||
/** |
|||
* Change constructor. |
|||
* |
|||
* @param int $type |
|||
* @param string $path |
|||
* @param string $targetPath |
|||
*/ |
|||
public function __construct($type, $path, $targetPath) { |
|||
parent::__construct($type, $path); |
|||
$this->targetPath = $targetPath; |
|||
} |
|||
|
|||
/** |
|||
* Get the new path of the renamed file relative to the storage root |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getTargetPath() { |
|||
return $this->targetPath; |
|||
} |
|||
} |
@ -0,0 +1,47 @@ |
|||
<?php |
|||
/** |
|||
* @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl> |
|||
* |
|||
* @author Robin Appelman <robin@icewind.nl> |
|||
* |
|||
* @license GNU AGPL version 3 or any later version |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License as |
|||
* published by the Free Software Foundation, either version 3 of the |
|||
* License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
* |
|||
*/ |
|||
|
|||
namespace OCP\Files\Notify; |
|||
|
|||
interface IChange { |
|||
const ADDED = 1; |
|||
const REMOVED = 2; |
|||
const MODIFIED = 3; |
|||
const RENAMED = 4; |
|||
|
|||
/** |
|||
* Get the type of the change |
|||
* |
|||
* @return int IChange::ADDED, IChange::REMOVED, IChange::MODIFIED or IChange::RENAMED |
|||
*/ |
|||
public function getType(); |
|||
|
|||
/** |
|||
* Get the path of the file that was changed relative to the root of the storage |
|||
* |
|||
* Note, for rename changes this path is the old path for the file |
|||
* |
|||
* @return mixed |
|||
*/ |
|||
public function getPath(); |
|||
} |
@ -0,0 +1,52 @@ |
|||
<?php |
|||
/** |
|||
* @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl> |
|||
* |
|||
* @author Robin Appelman <robin@icewind.nl> |
|||
* |
|||
* @license GNU AGPL version 3 or any later version |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License as |
|||
* published by the Free Software Foundation, either version 3 of the |
|||
* License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
* |
|||
*/ |
|||
|
|||
namespace OCP\Files\Notify; |
|||
|
|||
interface INotifyHandler { |
|||
/** |
|||
* Start listening for update notifications |
|||
* |
|||
* The provided callback will be called for every incoming notification with the following parameters |
|||
* - IChange|IRenameChange $change |
|||
* |
|||
* Note that this call is blocking and will not exit on it's own, to stop listening for notifications return `false` from the callback |
|||
* |
|||
* @param callable $callback |
|||
*/ |
|||
public function listen(callable $callback); |
|||
|
|||
/** |
|||
* Get all changes detected since the start of the notify process or the last call to getChanges |
|||
* |
|||
* @return IChange[] |
|||
*/ |
|||
public function getChanges(); |
|||
|
|||
/** |
|||
* Stop listening for changes |
|||
* |
|||
* Note that any pending changes will be discarded |
|||
*/ |
|||
public function stop(); |
|||
} |
@ -0,0 +1,33 @@ |
|||
<?php |
|||
/** |
|||
* @copyright Copyright (c) 2017 Robin Appelman <robin@icewind.nl> |
|||
* |
|||
* @author Robin Appelman <robin@icewind.nl> |
|||
* |
|||
* @license GNU AGPL version 3 or any later version |
|||
* |
|||
* This program is free software: you can redistribute it and/or modify |
|||
* it under the terms of the GNU Affero General Public License as |
|||
* published by the Free Software Foundation, either version 3 of the |
|||
* License, or (at your option) any later version. |
|||
* |
|||
* This program is distributed in the hope that it will be useful, |
|||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
* GNU Affero General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU Affero General Public License |
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
* |
|||
*/ |
|||
|
|||
namespace OCP\Files\Notify; |
|||
|
|||
interface IRenameChange extends IChange { |
|||
/** |
|||
* Get the new path of the renamed file relative to the storage root |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function getTargetPath(); |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue