PDO.php 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. <?php
  2. declare(strict_types=1);
  3. namespace Sabre\DAV\Locks\Backend;
  4. use Sabre\DAV\Locks\LockInfo;
  5. /**
  6. * The Lock manager allows you to handle all file-locks centrally.
  7. *
  8. * This Lock Manager stores all its data in a database. You must pass a PDO
  9. * connection object in the constructor.
  10. *
  11. * @copyright Copyright (C) fruux GmbH (https://fruux.com/)
  12. * @author Evert Pot (http://evertpot.com/)
  13. * @license http://sabre.io/license/ Modified BSD License
  14. */
  15. class PDO extends AbstractBackend
  16. {
  17. /**
  18. * The PDO tablename this backend uses.
  19. *
  20. * @var string
  21. */
  22. public $tableName = 'locks';
  23. /**
  24. * The PDO connection object.
  25. *
  26. * @var pdo
  27. */
  28. protected $pdo;
  29. /**
  30. * Constructor.
  31. */
  32. public function __construct(\PDO $pdo)
  33. {
  34. $this->pdo = $pdo;
  35. }
  36. /**
  37. * Returns a list of Sabre\DAV\Locks\LockInfo objects.
  38. *
  39. * This method should return all the locks for a particular uri, including
  40. * locks that might be set on a parent uri.
  41. *
  42. * If returnChildLocks is set to true, this method should also look for
  43. * any locks in the subtree of the uri for locks.
  44. *
  45. * @param string $uri
  46. * @param bool $returnChildLocks
  47. *
  48. * @return array
  49. */
  50. public function getLocks($uri, $returnChildLocks)
  51. {
  52. // NOTE: the following 10 lines or so could be easily replaced by
  53. // pure sql. MySQL's non-standard string concatenation prevents us
  54. // from doing this though.
  55. $query = 'SELECT owner, token, timeout, created, scope, depth, uri FROM '.$this->tableName.' WHERE (created > (? - timeout)) AND ((uri = ?)';
  56. $params = [time(), $uri];
  57. // We need to check locks for every part in the uri.
  58. $uriParts = explode('/', $uri);
  59. // We already covered the last part of the uri
  60. array_pop($uriParts);
  61. $currentPath = '';
  62. foreach ($uriParts as $part) {
  63. if ($currentPath) {
  64. $currentPath .= '/';
  65. }
  66. $currentPath .= $part;
  67. $query .= ' OR (depth!=0 AND uri = ?)';
  68. $params[] = $currentPath;
  69. }
  70. if ($returnChildLocks) {
  71. $query .= ' OR (uri LIKE ?)';
  72. $params[] = $uri.'/%';
  73. }
  74. $query .= ')';
  75. $stmt = $this->pdo->prepare($query);
  76. $stmt->execute($params);
  77. $result = $stmt->fetchAll();
  78. $lockList = [];
  79. foreach ($result as $row) {
  80. $lockInfo = new LockInfo();
  81. $lockInfo->owner = $row['owner'];
  82. $lockInfo->token = $row['token'];
  83. $lockInfo->timeout = $row['timeout'];
  84. $lockInfo->created = $row['created'];
  85. $lockInfo->scope = $row['scope'];
  86. $lockInfo->depth = $row['depth'];
  87. $lockInfo->uri = $row['uri'];
  88. $lockList[] = $lockInfo;
  89. }
  90. return $lockList;
  91. }
  92. /**
  93. * Locks a uri.
  94. *
  95. * @param string $uri
  96. *
  97. * @return bool
  98. */
  99. public function lock($uri, LockInfo $lockInfo)
  100. {
  101. // We're making the lock timeout 30 minutes
  102. $lockInfo->timeout = 30 * 60;
  103. $lockInfo->created = time();
  104. $lockInfo->uri = $uri;
  105. $locks = $this->getLocks($uri, false);
  106. $exists = false;
  107. foreach ($locks as $lock) {
  108. if ($lock->token == $lockInfo->token) {
  109. $exists = true;
  110. }
  111. }
  112. if ($exists) {
  113. $stmt = $this->pdo->prepare('UPDATE '.$this->tableName.' SET owner = ?, timeout = ?, scope = ?, depth = ?, uri = ?, created = ? WHERE token = ?');
  114. $stmt->execute([
  115. $lockInfo->owner,
  116. $lockInfo->timeout,
  117. $lockInfo->scope,
  118. $lockInfo->depth,
  119. $uri,
  120. $lockInfo->created,
  121. $lockInfo->token,
  122. ]);
  123. } else {
  124. $stmt = $this->pdo->prepare('INSERT INTO '.$this->tableName.' (owner,timeout,scope,depth,uri,created,token) VALUES (?,?,?,?,?,?,?)');
  125. $stmt->execute([
  126. $lockInfo->owner,
  127. $lockInfo->timeout,
  128. $lockInfo->scope,
  129. $lockInfo->depth,
  130. $uri,
  131. $lockInfo->created,
  132. $lockInfo->token,
  133. ]);
  134. }
  135. return true;
  136. }
  137. /**
  138. * Removes a lock from a uri.
  139. *
  140. * @param string $uri
  141. *
  142. * @return bool
  143. */
  144. public function unlock($uri, LockInfo $lockInfo)
  145. {
  146. $stmt = $this->pdo->prepare('DELETE FROM '.$this->tableName.' WHERE uri = ? AND token = ?');
  147. $stmt->execute([$uri, $lockInfo->token]);
  148. return 1 === $stmt->rowCount();
  149. }
  150. }