ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
PDO.php
Go to the documentation of this file.
1 <?php
2 
4 
8 
21 class 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
131 INSERT INTO {$this->tableName} (path, name, valuetype, value)
132 VALUES (:path, :name, :valuetype, :value)
133 ON CONFLICT (path, name)
134 DO UPDATE SET valuetype = :valuetype, value = :value
135 SQL;
136 
137 
138  } else {
139  $updateSql = <<<SQL
140 REPLACE INTO {$this->tableName} (path, name, valuetype, value)
141 VALUES (:path, :name, :valuetype, :value)
142 SQL;
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 
219  function move($source, $destination) {
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 }
const VT_XML
Value is stored as XML fragment.
Definition: PDO.php:31
$path
Definition: aliased.php:25
This class represents a set of properties that are going to be updated.
Definition: PropPatch.php:20
$stmt
move($source, $destination)
This method is called after a successful MOVE.
Definition: PDO.php:219
const VT_OBJECT
Value is stored as a property object.
Definition: PDO.php:36
$destination
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&#39;t have a value yet.
Definition: PropFind.php:222
propFind($path, PropFind $propFind)
Fetches properties for a path.
Definition: PDO.php:80
__construct(\PDO $pdo)
Creates the PDO property storage engine.
Definition: PDO.php:57
isAllProps()
Returns true if this was an &#39;{DAV:}allprops&#39; request.
Definition: PropFind.php:255
$query
$row
const VT_STRING
Value is stored as string.
Definition: PDO.php:26
propPatch($path, PropPatch $propPatch)
Updates properties for a path.
Definition: PDO.php:123
$source
Definition: linkback.php:22
handleRemaining(callable $callback)
Call this function if you wish to handle all properties that haven&#39;t been handled by anything else ye...
Definition: PropPatch.php:123