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