ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
PDO.php
Go to the documentation of this file.
1<?php
2
4
8
21class PDO implements BackendInterface {
22
26 const VT_STRING = 1;
27
31 const VT_XML = 2;
32
36 const VT_OBJECT = 3;
37
43 protected $pdo;
44
50 public $tableName = 'propertystorage';
51
57 function __construct(\PDO $pdo) {
58
59 $this->pdo = $pdo;
60
61 }
62
80 function propFind($path, PropFind $propFind) {
81
82 if (!$propFind->isAllProps() && count($propFind->get404Properties()) === 0) {
83 return;
84 }
85
86 $query = 'SELECT name, value, valuetype FROM ' . $this->tableName . ' WHERE path = ?';
87 $stmt = $this->pdo->prepare($query);
88 $stmt->execute([$path]);
89
90 while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
91 if (gettype($row['value']) === 'resource') {
92 $row['value'] = stream_get_contents($row['value']);
93 }
94 switch ($row['valuetype']) {
95 case null :
96 case self::VT_STRING :
97 $propFind->set($row['name'], $row['value']);
98 break;
99 case self::VT_XML :
100 $propFind->set($row['name'], new Complex($row['value']));
101 break;
102 case self::VT_OBJECT :
103 $propFind->set($row['name'], unserialize($row['value']));
104 break;
105 }
106 }
107
108 }
109
123 function propPatch($path, PropPatch $propPatch) {
124
125 $propPatch->handleRemaining(function($properties) use ($path) {
126
127
128 if ($this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME) === 'pgsql') {
129
130 $updateSql = <<<SQL
131INSERT INTO {$this->tableName} (path, name, valuetype, value)
132VALUES (:path, :name, :valuetype, :value)
133ON CONFLICT (path, name)
134DO UPDATE SET valuetype = :valuetype, value = :value
135SQL;
136
137
138 } else {
139 $updateSql = <<<SQL
140REPLACE INTO {$this->tableName} (path, name, valuetype, value)
141VALUES (:path, :name, :valuetype, :value)
142SQL;
143
144 }
145
146 $updateStmt = $this->pdo->prepare($updateSql);
147 $deleteStmt = $this->pdo->prepare("DELETE FROM " . $this->tableName . " WHERE path = ? AND name = ?");
148
149 foreach ($properties as $name => $value) {
150
151 if (!is_null($value)) {
152 if (is_scalar($value)) {
153 $valueType = self::VT_STRING;
154 } elseif ($value instanceof Complex) {
155 $valueType = self::VT_XML;
156 $value = $value->getXml();
157 } else {
158 $valueType = self::VT_OBJECT;
159 $value = serialize($value);
160 }
161
162 $updateStmt->bindParam('path', $path, \PDO::PARAM_STR);
163 $updateStmt->bindParam('name', $name, \PDO::PARAM_STR);
164 $updateStmt->bindParam('valuetype', $valueType, \PDO::PARAM_INT);
165 $updateStmt->bindParam('value', $value, \PDO::PARAM_LOB);
166
167 $updateStmt->execute();
168
169 } else {
170 $deleteStmt->execute([$path, $name]);
171 }
172
173 }
174
175 return true;
176
177 });
178
179 }
180
192 function delete($path) {
193
194 $stmt = $this->pdo->prepare("DELETE FROM " . $this->tableName . " WHERE path = ? OR path LIKE ? ESCAPE '='");
195 $childPath = strtr(
196 $path,
197 [
198 '=' => '==',
199 '%' => '=%',
200 '_' => '=_'
201 ]
202 ) . '/%';
203
204 $stmt->execute([$path, $childPath]);
205
206 }
207
220
221 // I don't know a way to write this all in a single sql query that's
222 // also compatible across db engines, so we're letting PHP do all the
223 // updates. Much slower, but it should still be pretty fast in most
224 // cases.
225 $select = $this->pdo->prepare('SELECT id, path FROM ' . $this->tableName . ' WHERE path = ? OR path LIKE ?');
226 $select->execute([$source, $source . '/%']);
227
228 $update = $this->pdo->prepare('UPDATE ' . $this->tableName . ' SET path = ? WHERE id = ?');
229 while ($row = $select->fetch(\PDO::FETCH_ASSOC)) {
230
231 // Sanity check. SQL may select too many records, such as records
232 // with different cases.
233 if ($row['path'] !== $source && strpos($row['path'], $source . '/') !== 0) continue;
234
235 $trailingPart = substr($row['path'], strlen($source) + 1);
236 $newPath = $destination;
237 if ($trailingPart) {
238 $newPath .= '/' . $trailingPart;
239 }
240 $update->execute([$newPath, $row['id']]);
241
242 }
243
244 }
245
246}
$path
Definition: aliased.php:25
$source
Definition: linkback.php:22
An exception for terminatinating execution or to throw for unit testing.
This class holds all the information about a PROPFIND request.
Definition: PropFind.php:11
set($propertyName, $value, $status=null)
Sets the value of the property.
Definition: PropFind.php:121
get404Properties()
Returns all propertynames that have a 404 status, and thus don't have a value yet.
Definition: PropFind.php:222
isAllProps()
Returns true if this was an '{DAV:}allprops' request.
Definition: PropFind.php:255
This class represents a set of properties that are going to be updated.
Definition: PropPatch.php:20
handleRemaining(callable $callback)
Call this function if you wish to handle all properties that haven't been handled by anything else ye...
Definition: PropPatch.php:123
PropertyStorage PDO backend.
Definition: PDO.php:21
const VT_XML
Value is stored as XML fragment.
Definition: PDO.php:31
__construct(\PDO $pdo)
Creates the PDO property storage engine.
Definition: PDO.php:57
const VT_STRING
Value is stored as string.
Definition: PDO.php:26
propFind($path, PropFind $propFind)
Fetches properties for a path.
Definition: PDO.php:80
move($source, $destination)
This method is called after a successful MOVE.
Definition: PDO.php:219
propPatch($path, PropPatch $propPatch)
Updates properties for a path.
Definition: PDO.php:123
const VT_OBJECT
Value is stored as a property object.
Definition: PDO.php:36
This class represents a 'complex' property that didn't have a default decoder.
Definition: Complex.php:18
$destination
$row
$stmt
$query