SMBNotifyHandler.php 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-License-Identifier: AGPL-3.0-or-later
  5. */
  6. namespace OCA\Files_External\Lib\Notify;
  7. use OC\Files\Notify\Change;
  8. use OC\Files\Notify\RenameChange;
  9. use OCP\Files\Notify\IChange;
  10. use OCP\Files\Notify\INotifyHandler;
  11. class SMBNotifyHandler implements INotifyHandler {
  12. /**
  13. * @var string
  14. */
  15. private $root;
  16. private $oldRenamePath = null;
  17. /**
  18. * SMBNotifyHandler constructor.
  19. *
  20. * @param \Icewind\SMB\INotifyHandler $shareNotifyHandler
  21. * @param string $root
  22. */
  23. public function __construct(
  24. private \Icewind\SMB\INotifyHandler $shareNotifyHandler,
  25. $root,
  26. ) {
  27. $this->root = str_replace('\\', '/', $root);
  28. }
  29. private function relativePath($fullPath) {
  30. if ($fullPath === $this->root) {
  31. return '';
  32. } elseif (substr($fullPath, 0, strlen($this->root)) === $this->root) {
  33. return substr($fullPath, strlen($this->root));
  34. } else {
  35. return null;
  36. }
  37. }
  38. public function listen(callable $callback) {
  39. $oldRenamePath = null;
  40. $this->shareNotifyHandler->listen(function (\Icewind\SMB\Change $shareChange) use ($callback) {
  41. $change = $this->mapChange($shareChange);
  42. if (!is_null($change)) {
  43. return $callback($change);
  44. } else {
  45. return true;
  46. }
  47. });
  48. }
  49. /**
  50. * Get all changes detected since the start of the notify process or the last call to getChanges
  51. *
  52. * @return IChange[]
  53. */
  54. public function getChanges() {
  55. $shareChanges = $this->shareNotifyHandler->getChanges();
  56. $changes = [];
  57. foreach ($shareChanges as $shareChange) {
  58. $change = $this->mapChange($shareChange);
  59. if ($change) {
  60. $changes[] = $change;
  61. }
  62. }
  63. return $changes;
  64. }
  65. /**
  66. * Stop listening for changes
  67. *
  68. * Note that any pending changes will be discarded
  69. */
  70. public function stop() {
  71. $this->shareNotifyHandler->stop();
  72. }
  73. /**
  74. * @param \Icewind\SMB\Change $change
  75. * @return IChange|null
  76. */
  77. private function mapChange(\Icewind\SMB\Change $change) {
  78. $path = $this->relativePath($change->getPath());
  79. if (is_null($path)) {
  80. return null;
  81. }
  82. if ($change->getCode() === \Icewind\SMB\INotifyHandler::NOTIFY_RENAMED_OLD) {
  83. $this->oldRenamePath = $path;
  84. return null;
  85. }
  86. $type = $this->mapNotifyType($change->getCode());
  87. if (is_null($type)) {
  88. return null;
  89. }
  90. if ($type === IChange::RENAMED) {
  91. if (!is_null($this->oldRenamePath)) {
  92. $result = new RenameChange($type, $this->oldRenamePath, $path);
  93. $this->oldRenamePath = null;
  94. } else {
  95. $result = null;
  96. }
  97. } else {
  98. $result = new Change($type, $path);
  99. }
  100. return $result;
  101. }
  102. private function mapNotifyType($smbType) {
  103. switch ($smbType) {
  104. case \Icewind\SMB\INotifyHandler::NOTIFY_ADDED:
  105. return IChange::ADDED;
  106. case \Icewind\SMB\INotifyHandler::NOTIFY_REMOVED:
  107. return IChange::REMOVED;
  108. case \Icewind\SMB\INotifyHandler::NOTIFY_MODIFIED:
  109. case \Icewind\SMB\INotifyHandler::NOTIFY_ADDED_STREAM:
  110. case \Icewind\SMB\INotifyHandler::NOTIFY_MODIFIED_STREAM:
  111. case \Icewind\SMB\INotifyHandler::NOTIFY_REMOVED_STREAM:
  112. return IChange::MODIFIED;
  113. case \Icewind\SMB\INotifyHandler::NOTIFY_RENAMED_NEW:
  114. return IChange::RENAMED;
  115. default:
  116. return null;
  117. }
  118. }
  119. }