3131use Sabre \DAV \PropFind ;
3232use Sabre \DAV \PropPatch ;
3333use Sabre \DAV \Tree ;
34+ use Sabre \DAV \Xml \Property \Complex ;
3435use function array_intersect ;
3536
3637class CustomPropertiesBackend implements BackendInterface {
3738
3839 /** @var string */
3940 private const TABLE_NAME = 'properties ' ;
4041
42+ /**
43+ * Value is stored as string.
44+ */
45+ public const PROPERTY_TYPE_STRING = 1 ;
46+
47+ /**
48+ * Value is stored as XML fragment.
49+ */
50+ public const PROPERTY_TYPE_XML = 2 ;
51+
52+ /**
53+ * Value is stored as a property object.
54+ */
55+ public const PROPERTY_TYPE_OBJECT = 3 ;
56+
4157 /**
4258 * Ignored properties
4359 *
@@ -239,7 +255,7 @@ private function getPublishedProperties(string $path, array $requestedProperties
239255 $ result = $ qb ->executeQuery ();
240256 $ props = [];
241257 while ($ row = $ result ->fetch ()) {
242- $ props [$ row ['propertyname ' ]] = $ row ['propertyvalue ' ];
258+ $ props [$ row ['propertyname ' ]] = $ this -> decodeValueFromDatabase ( $ row ['propertyvalue ' ], $ row [ ' valuetype ' ]) ;
243259 }
244260 $ result ->closeCursor ();
245261 return $ props ;
@@ -282,7 +298,7 @@ private function getUserProperties(string $path, array $requestedProperties) {
282298
283299 $ props = [];
284300 while ($ row = $ result ->fetch ()) {
285- $ props [$ row ['propertyname ' ]] = $ row ['propertyvalue ' ];
301+ $ props [$ row ['propertyname ' ]] = $ this -> decodeValueFromDatabase ( $ row ['propertyvalue ' ], $ row [ ' valuetype ' ]) ;
286302 }
287303
288304 $ result ->closeCursor ();
@@ -304,9 +320,9 @@ private function updateProperties(string $path, array $properties) {
304320 ' WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ? ' ;
305321
306322 $ insertStatement = 'INSERT INTO `*PREFIX*properties` ' .
307- ' (`userid`,`propertypath`,`propertyname`,`propertyvalue`) VALUES(?,?,?,?) ' ;
323+ ' (`userid`,`propertypath`,`propertyname`,`propertyvalue`, `valuetype` ) VALUES(?, ?,?,?,?) ' ;
308324
309- $ updateStatement = 'UPDATE `*PREFIX*properties` SET `propertyvalue` = ? ' .
325+ $ updateStatement = 'UPDATE `*PREFIX*properties` SET `propertyvalue` = ?, `valuetype` = ? ' .
310326 ' WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ? ' ;
311327
312328 // TODO: use "insert or update" strategy ?
@@ -325,24 +341,22 @@ private function updateProperties(string $path, array $properties) {
325341 );
326342 }
327343 } else {
328- if ($ propertyValue instanceOf \Sabre \DAV \Xml \Property \Complex) {
329- $ propertyValue = $ propertyValue ->getXml ();
330- } elseif (!is_string ($ propertyValue )) {
331- $ propertyValue = (string )$ propertyValue ;
332- }
344+ [$ value , $ valueType ] = $ this ->encodeValueForDatabase ($ propertyValue );
333345 if (!array_key_exists ($ propertyName , $ existing )) {
334346 $ this ->connection ->executeUpdate ($ insertStatement ,
335347 [
336348 $ this ->user ->getUID (),
337349 $ this ->formatPath ($ path ),
338350 $ propertyName ,
339- $ propertyValue ,
351+ $ value ,
352+ $ valueType
340353 ]
341354 );
342355 } else {
343356 $ this ->connection ->executeUpdate ($ updateStatement ,
344357 [
345- $ propertyValue ,
358+ $ value ,
359+ $ valueType ,
346360 $ this ->user ->getUID (),
347361 $ this ->formatPath ($ path ),
348362 $ propertyName ,
@@ -367,8 +381,40 @@ private function updateProperties(string $path, array $properties) {
367381 private function formatPath (string $ path ): string {
368382 if (strlen ($ path ) > 250 ) {
369383 return sha1 ($ path );
384+ }
385+
386+ return $ path ;
387+ }
388+
389+ /**
390+ * @param mixed $value
391+ * @return array
392+ */
393+ private function encodeValueForDatabase ($ value ): array {
394+ if (is_scalar ($ value )) {
395+ $ valueType = self ::PROPERTY_TYPE_STRING ;
396+ } elseif ($ value instanceof Complex) {
397+ $ valueType = self ::PROPERTY_TYPE_XML ;
398+ $ value = $ value ->getXml ();
370399 } else {
371- return $ path ;
400+ $ valueType = self ::PROPERTY_TYPE_OBJECT ;
401+ $ value = serialize ($ value );
402+ }
403+ return [$ value , $ valueType ];
404+ }
405+
406+ /**
407+ * @return mixed|Complex|string
408+ */
409+ private function decodeValueFromDatabase (string $ value , int $ valueType ) {
410+ switch ($ valueType ) {
411+ case self ::PROPERTY_TYPE_XML :
412+ return new Complex ($ value );
413+ case self ::PROPERTY_TYPE_OBJECT :
414+ return unserialize ($ value );
415+ case self ::PROPERTY_TYPE_STRING :
416+ default :
417+ return $ value ;
372418 }
373419 }
374420}
0 commit comments