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