Completed
Push — master ( 24957e...d8c031 )
by Thomas
16:29 queued 07:32
created

MiscCustomPropertiesBackend::delete()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 8

Duplication

Lines 11
Ratio 100 %

Importance

Changes 0
Metric Value
cc 2
eloc 8
nc 2
nop 1
dl 11
loc 11
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * @author Thomas Müller <[email protected]>
4
 *
5
 * @copyright Copyright (c) 2017, ownCloud GmbH
6
 * @license AGPL-3.0
7
 *
8
 * This code is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Affero General Public License, version 3,
10
 * as published by the Free Software Foundation.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
 * GNU Affero General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Affero General Public License, version 3,
18
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
19
 *
20
 */
21
22
namespace OCA\DAV\DAV;
23
24
use Doctrine\DBAL\Connection;
25
use Sabre\DAV\INode;
26
27
/**
28
 * Class MiscCustomPropertiesBackend
29
 *
30
 * Provides ability to store/retrieve custom properties
31
 * for card/calendar/whatever (excluding files)
32
 * via DAV server into oc_dav_properties DB table using propertypath as a reference to the item
33
 *
34
 * @package OCA\DAV\DAV
35
 */
36
class MiscCustomPropertiesBackend extends AbstractCustomPropertiesBackend {
37
38
	const SELECT_BY_PATH_STMT = 'SELECT * FROM `*PREFIX*dav_properties` WHERE `propertypath` = ?';
39
	const INSERT_BY_PATH_STMT = 'INSERT INTO `*PREFIX*dav_properties`'
40
	. ' (`propertypath`, `propertyname`, `propertyvalue`) VALUES(?,?,?)';
41
	const UPDATE_BY_PATH_STMT = 'UPDATE `*PREFIX*dav_properties`'
42
	. ' SET `propertypath` = ? WHERE `propertypath` = ?';
43
	const UPDATE_BY_PATH_AND_NAME_STMT = 'UPDATE `*PREFIX*dav_properties` '
44
	. 'SET `propertyvalue` = ? WHERE `propertypath` = ? AND `propertyname` = ?';
45
	const DELETE_BY_PATH_STMT = 'DELETE FROM `*PREFIX*dav_properties` WHERE `propertypath` = ?';
46
	const DELETE_BY_PATH_AND_NAME_STMT = 'DELETE FROM `*PREFIX*dav_properties`'
47
	. ' WHERE `propertypath` = ? AND `propertyname` = ?';
48
49
	/**
50
	 * This method is called after a node is deleted.
51
	 *
52
	 * @param string $path path of node for which to delete properties
53
	 */
54 View Code Duplication
	public function delete($path) {
55
		$node = $this->getNodeForPath($path);
56
		if (is_null($node)) {
57
			return;
58
		}
59
60
		$statement = $this->connection->prepare(self::DELETE_BY_PATH_STMT);
61
		$statement->execute([$path]);
62
		$statement->closeCursor();
63
		$this->offsetUnset($path);
64
	}
65
66
	/**
67
	 * This method is called after a successful MOVE
68
	 *
69
	 * @param string $source
70
	 * @param string $destination
71
	 *
72
	 * @return void
73
	 */
74 View Code Duplication
	public function move($source, $destination) {
75
		$node = $this->getNodeForPath($source);
76
		if (is_null($node)) {
77
			return;
78
		}
79
80
		$statement = $this->connection->prepare(self::UPDATE_BY_PATH_STMT);
81
		$statement->execute([$destination, $source]);
82
		$statement->closeCursor();
83
	}
84
85
	/**
86
	 * @inheritdoc
87
	 */
88 View Code Duplication
	protected function getProperties($path, INode $node, array $requestedProperties) {
89
		if (is_null($this->offsetGet($path))) {
90
			// TODO: chunking if more than 1000 properties
91
			$sql = self::SELECT_BY_PATH_STMT;
92
93
			$whereValues = [$path];
94
			$whereTypes = [null];
95
96
			if (!empty($requestedProperties)) {
97
				// request only a subset
98
				$sql .= ' AND `propertyname` in (?)';
99
				$whereValues[] = $requestedProperties;
100
				$whereTypes[] = Connection::PARAM_STR_ARRAY;
101
			}
102
103
			$props = $this->fetchProperties($sql, $whereValues, $whereTypes);
104
			$this->offsetSet($path, $props);
105
		}
106
		return $this->offsetGet($path);
107
	}
108
109
	/**
110
	 * @inheritdoc
111
	 */
112 View Code Duplication
	protected function updateProperties($path, INode $node, $changedProperties) {
113
		$existingProperties = $this->getProperties($path, $node, []);
114
		$deleteStatement = self::DELETE_BY_PATH_AND_NAME_STMT;
115
		$insertStatement = self::INSERT_BY_PATH_STMT;
116
		$updateStatement = self::UPDATE_BY_PATH_AND_NAME_STMT;
117
118
		// TODO: use "insert or update" strategy ?
119
		$this->connection->beginTransaction();
120
		foreach ($changedProperties as $propertyName => $propertyValue) {
121
			$propertyExists = array_key_exists($propertyName, $existingProperties);
122
			// If it was null, we need to delete the property
123
			if (is_null($propertyValue)) {
124
				if ($propertyExists) {
125
					$this->connection->executeUpdate($deleteStatement,
126
						[
127
							$path,
128
							$propertyName
129
						]
130
					);
131
				}
132
			} else {
133
				if (!$propertyExists) {
134
					$this->connection->executeUpdate($insertStatement,
135
						[
136
							$path,
137
							$propertyName,
138
							$propertyValue
139
						]
140
					);
141
				} else {
142
					$this->connection->executeUpdate($updateStatement,
143
						[
144
							$propertyValue,
145
							$path,
146
							$propertyName
147
						]
148
					);
149
				}
150
			}
151
		}
152
153
		$this->connection->commit();
154
		$this->offsetUnset($path);
155
156
		return true;
157
	}
158
159
	/**
160
	 * Bulk load properties for children
161
	 *
162
	 * @param INode $node
163
	 * @param array $requestedProperties requested properties
164
	 *
165
	 * @return void
166
	 */
167
	protected function loadChildrenProperties(INode $node, $requestedProperties) {
168
		// Not supported
169
	}
170
171
}
172