xref: /plugin/davcal/vendor/sabre/dav/lib/DAV/Locks/Backend/PDO.php (revision a1a3b6794e0e143a4a8b51d3185ce2d339be61ab)
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