Completed
Pull Request — master (#3620)
by Georg
11:18
created
apps/dav/lib/CalDAV/Calendar.php 1 patch
Indentation   +261 added lines, -261 removed lines patch added patch discarded remove patch
@@ -32,266 +32,266 @@
 block discarded – undo
32 32
 
33 33
 class Calendar extends \Sabre\CalDAV\Calendar implements IShareable {
34 34
 
35
-	public function __construct(BackendInterface $caldavBackend, $calendarInfo, IL10N $l10n) {
36
-		parent::__construct($caldavBackend, $calendarInfo);
37
-
38
-		if ($this->getName() === BirthdayService::BIRTHDAY_CALENDAR_URI) {
39
-			$this->calendarInfo['{DAV:}displayname'] = $l10n->t('Contact birthdays');
40
-		}
41
-		if ($this->getName() === CalDavBackend::PERSONAL_CALENDAR_URI &&
42
-			$this->calendarInfo['{DAV:}displayname'] === CalDavBackend::PERSONAL_CALENDAR_NAME) {
43
-			$this->calendarInfo['{DAV:}displayname'] = $l10n->t('Personal');
44
-		}
45
-	}
46
-
47
-	/**
48
-	 * Updates the list of shares.
49
-	 *
50
-	 * The first array is a list of people that are to be added to the
51
-	 * resource.
52
-	 *
53
-	 * Every element in the add array has the following properties:
54
-	 *   * href - A url. Usually a mailto: address
55
-	 *   * commonName - Usually a first and last name, or false
56
-	 *   * summary - A description of the share, can also be false
57
-	 *   * readOnly - A boolean value
58
-	 *
59
-	 * Every element in the remove array is just the address string.
60
-	 *
61
-	 * @param array $add
62
-	 * @param array $remove
63
-	 * @return void
64
-	 */
65
-	function updateShares(array $add, array $remove) {
66
-		/** @var CalDavBackend $calDavBackend */
67
-		$calDavBackend = $this->caldavBackend;
68
-		$calDavBackend->updateShares($this, $add, $remove);
69
-	}
70
-
71
-	/**
72
-	 * Returns the list of people whom this resource is shared with.
73
-	 *
74
-	 * Every element in this array should have the following properties:
75
-	 *   * href - Often a mailto: address
76
-	 *   * commonName - Optional, for example a first + last name
77
-	 *   * status - See the Sabre\CalDAV\SharingPlugin::STATUS_ constants.
78
-	 *   * readOnly - boolean
79
-	 *   * summary - Optional, a description for the share
80
-	 *
81
-	 * @return array
82
-	 */
83
-	function getShares() {
84
-		/** @var CalDavBackend $calDavBackend */
85
-		$calDavBackend = $this->caldavBackend;
86
-		return $calDavBackend->getShares($this->getResourceId());
87
-	}
88
-
89
-	/**
90
-	 * @return int
91
-	 */
92
-	public function getResourceId() {
93
-		return $this->calendarInfo['id'];
94
-	}
95
-
96
-	/**
97
-	 * @return string
98
-	 */
99
-	public function getPrincipalURI() {
100
-		return $this->calendarInfo['principaluri'];
101
-	}
102
-
103
-	function getACL() {
104
-		$acl =  [
105
-			[
106
-				'privilege' => '{DAV:}read',
107
-				'principal' => $this->getOwner(),
108
-				'protected' => true,
109
-			]];
110
-		if ($this->getName() !== BirthdayService::BIRTHDAY_CALENDAR_URI) {
111
-			$acl[] = [
112
-				'privilege' => '{DAV:}write',
113
-				'principal' => $this->getOwner(),
114
-				'protected' => true,
115
-			];
116
-		}
117
-		if ($this->getOwner() !== parent::getOwner()) {
118
-			$acl[] =  [
119
-					'privilege' => '{DAV:}read',
120
-					'principal' => parent::getOwner(),
121
-					'protected' => true,
122
-				];
123
-			if ($this->canWrite()) {
124
-				$acl[] = [
125
-					'privilege' => '{DAV:}write',
126
-					'principal' => parent::getOwner(),
127
-					'protected' => true,
128
-				];
129
-			}
130
-		}
131
-		if ($this->isPublic()) {
132
-			$acl[] = [
133
-				'privilege' => '{DAV:}read',
134
-				'principal' => 'principals/system/public',
135
-				'protected' => true,
136
-			];
137
-		}
138
-
139
-		/** @var CalDavBackend $calDavBackend */
140
-		$calDavBackend = $this->caldavBackend;
141
-		return $calDavBackend->applyShareAcl($this->getResourceId(), $acl);
142
-	}
143
-
144
-	function getChildACL() {
145
-		return $this->getACL();
146
-	}
147
-
148
-	function getOwner() {
149
-		if (isset($this->calendarInfo['{http://owncloud.org/ns}owner-principal'])) {
150
-			return $this->calendarInfo['{http://owncloud.org/ns}owner-principal'];
151
-		}
152
-		return parent::getOwner();
153
-	}
154
-
155
-	function delete() {
156
-		if (isset($this->calendarInfo['{http://owncloud.org/ns}owner-principal']) &&
157
-			$this->calendarInfo['{http://owncloud.org/ns}owner-principal'] !== $this->calendarInfo['principaluri']) {
158
-			$principal = 'principal:' . parent::getOwner();
159
-			$shares = $this->getShares();
160
-			$shares = array_filter($shares, function($share) use ($principal){
161
-				return $share['href'] === $principal;
162
-			});
163
-			if (empty($shares)) {
164
-				throw new Forbidden();
165
-			}
166
-
167
-			/** @var CalDavBackend $calDavBackend */
168
-			$calDavBackend = $this->caldavBackend;
169
-			$calDavBackend->updateShares($this, [], [
170
-				'href' => $principal
171
-			]);
172
-			return;
173
-		}
174
-		parent::delete();
175
-	}
176
-
177
-	function propPatch(PropPatch $propPatch) {
178
-		// parent::propPatch will only update calendars table
179
-		// if calendar is shared, changes has to be made in properties table
180
-		if (!$this->isShared()) {
181
-			parent::propPatch($propPatch);
182
-		}
183
-	}
184
-
185
-	function getChild($name) {
186
-
187
-		$obj = $this->caldavBackend->getCalendarObject($this->calendarInfo['id'], $name);
188
-
189
-		if (!$obj) {
190
-			throw new NotFound('Calendar object not found');
191
-		}
192
-
193
-		if ($this->isShared() && $obj['classification'] === CalDavBackend::CLASSIFICATION_PRIVATE) {
194
-			throw new NotFound('Calendar object not found');
195
-		}
196
-
197
-		$obj['acl'] = $this->getChildACL();
198
-
199
-		return new CalendarObject($this->caldavBackend, $this->calendarInfo, $obj);
200
-
201
-	}
202
-
203
-	function getChildren() {
204
-
205
-		$objs = $this->caldavBackend->getCalendarObjects($this->calendarInfo['id']);
206
-		$children = [];
207
-		foreach ($objs as $obj) {
208
-			if ($this->isShared() && $obj['classification'] === CalDavBackend::CLASSIFICATION_PRIVATE) {
209
-				continue;
210
-			}
211
-			$obj['acl'] = $this->getChildACL();
212
-			$children[] = new CalendarObject($this->caldavBackend, $this->calendarInfo, $obj);
213
-		}
214
-		return $children;
215
-
216
-	}
217
-
218
-	function getMultipleChildren(array $paths) {
219
-
220
-		$objs = $this->caldavBackend->getMultipleCalendarObjects($this->calendarInfo['id'], $paths);
221
-		$children = [];
222
-		foreach ($objs as $obj) {
223
-			if ($this->isShared() && $obj['classification'] === CalDavBackend::CLASSIFICATION_PRIVATE) {
224
-				continue;
225
-			}
226
-			$obj['acl'] = $this->getChildACL();
227
-			$children[] = new CalendarObject($this->caldavBackend, $this->calendarInfo, $obj);
228
-		}
229
-		return $children;
230
-
231
-	}
232
-
233
-	function childExists($name) {
234
-		$obj = $this->caldavBackend->getCalendarObject($this->calendarInfo['id'], $name);
235
-		if (!$obj) {
236
-			return false;
237
-		}
238
-		if ($this->isShared() && $obj['classification'] === CalDavBackend::CLASSIFICATION_PRIVATE) {
239
-			return false;
240
-		}
241
-
242
-		return true;
243
-	}
244
-
245
-	function calendarQuery(array $filters) {
246
-
247
-		$uris = $this->caldavBackend->calendarQuery($this->calendarInfo['id'], $filters);
248
-		if ($this->isShared()) {
249
-			return array_filter($uris, function ($uri) {
250
-				return $this->childExists($uri);
251
-			});
252
-		}
253
-
254
-		return $uris;
255
-	}
256
-
257
-	/**
258
-	 * @param boolean $value
259
-	 * @return string|null
260
-	 */
261
-	function setPublishStatus($value) {
262
-		$publicUri = $this->caldavBackend->setPublishStatus($value, $this);
263
-		$this->calendarInfo['publicuri'] = $publicUri;
264
-		return $publicUri;
265
-	}
266
-
267
-	/**
268
-	 * @return mixed $value
269
-	 */
270
-	function getPublishStatus() {
271
-		return $this->caldavBackend->getPublishStatus($this);
272
-	}
273
-
274
-	private function canWrite() {
275
-		if (isset($this->calendarInfo['{http://owncloud.org/ns}read-only'])) {
276
-			return !$this->calendarInfo['{http://owncloud.org/ns}read-only'];
277
-		}
278
-		return true;
279
-	}
280
-
281
-	private function isPublic() {
282
-		return isset($this->calendarInfo['{http://owncloud.org/ns}public']);
283
-	}
284
-
285
-	private function isShared() {
286
-		if (!isset($this->calendarInfo['{http://owncloud.org/ns}owner-principal'])) {
287
-			return false;
288
-		}
289
-
290
-		return $this->calendarInfo['{http://owncloud.org/ns}owner-principal'] !== $this->calendarInfo['principaluri'];
291
-	}
292
-
293
-	public function isSubscription() {
294
-		return isset($this->calendarInfo['{http://calendarserver.org/ns/}source']);
295
-	}
35
+    public function __construct(BackendInterface $caldavBackend, $calendarInfo, IL10N $l10n) {
36
+        parent::__construct($caldavBackend, $calendarInfo);
37
+
38
+        if ($this->getName() === BirthdayService::BIRTHDAY_CALENDAR_URI) {
39
+            $this->calendarInfo['{DAV:}displayname'] = $l10n->t('Contact birthdays');
40
+        }
41
+        if ($this->getName() === CalDavBackend::PERSONAL_CALENDAR_URI &&
42
+            $this->calendarInfo['{DAV:}displayname'] === CalDavBackend::PERSONAL_CALENDAR_NAME) {
43
+            $this->calendarInfo['{DAV:}displayname'] = $l10n->t('Personal');
44
+        }
45
+    }
46
+
47
+    /**
48
+     * Updates the list of shares.
49
+     *
50
+     * The first array is a list of people that are to be added to the
51
+     * resource.
52
+     *
53
+     * Every element in the add array has the following properties:
54
+     *   * href - A url. Usually a mailto: address
55
+     *   * commonName - Usually a first and last name, or false
56
+     *   * summary - A description of the share, can also be false
57
+     *   * readOnly - A boolean value
58
+     *
59
+     * Every element in the remove array is just the address string.
60
+     *
61
+     * @param array $add
62
+     * @param array $remove
63
+     * @return void
64
+     */
65
+    function updateShares(array $add, array $remove) {
66
+        /** @var CalDavBackend $calDavBackend */
67
+        $calDavBackend = $this->caldavBackend;
68
+        $calDavBackend->updateShares($this, $add, $remove);
69
+    }
70
+
71
+    /**
72
+     * Returns the list of people whom this resource is shared with.
73
+     *
74
+     * Every element in this array should have the following properties:
75
+     *   * href - Often a mailto: address
76
+     *   * commonName - Optional, for example a first + last name
77
+     *   * status - See the Sabre\CalDAV\SharingPlugin::STATUS_ constants.
78
+     *   * readOnly - boolean
79
+     *   * summary - Optional, a description for the share
80
+     *
81
+     * @return array
82
+     */
83
+    function getShares() {
84
+        /** @var CalDavBackend $calDavBackend */
85
+        $calDavBackend = $this->caldavBackend;
86
+        return $calDavBackend->getShares($this->getResourceId());
87
+    }
88
+
89
+    /**
90
+     * @return int
91
+     */
92
+    public function getResourceId() {
93
+        return $this->calendarInfo['id'];
94
+    }
95
+
96
+    /**
97
+     * @return string
98
+     */
99
+    public function getPrincipalURI() {
100
+        return $this->calendarInfo['principaluri'];
101
+    }
102
+
103
+    function getACL() {
104
+        $acl =  [
105
+            [
106
+                'privilege' => '{DAV:}read',
107
+                'principal' => $this->getOwner(),
108
+                'protected' => true,
109
+            ]];
110
+        if ($this->getName() !== BirthdayService::BIRTHDAY_CALENDAR_URI) {
111
+            $acl[] = [
112
+                'privilege' => '{DAV:}write',
113
+                'principal' => $this->getOwner(),
114
+                'protected' => true,
115
+            ];
116
+        }
117
+        if ($this->getOwner() !== parent::getOwner()) {
118
+            $acl[] =  [
119
+                    'privilege' => '{DAV:}read',
120
+                    'principal' => parent::getOwner(),
121
+                    'protected' => true,
122
+                ];
123
+            if ($this->canWrite()) {
124
+                $acl[] = [
125
+                    'privilege' => '{DAV:}write',
126
+                    'principal' => parent::getOwner(),
127
+                    'protected' => true,
128
+                ];
129
+            }
130
+        }
131
+        if ($this->isPublic()) {
132
+            $acl[] = [
133
+                'privilege' => '{DAV:}read',
134
+                'principal' => 'principals/system/public',
135
+                'protected' => true,
136
+            ];
137
+        }
138
+
139
+        /** @var CalDavBackend $calDavBackend */
140
+        $calDavBackend = $this->caldavBackend;
141
+        return $calDavBackend->applyShareAcl($this->getResourceId(), $acl);
142
+    }
143
+
144
+    function getChildACL() {
145
+        return $this->getACL();
146
+    }
147
+
148
+    function getOwner() {
149
+        if (isset($this->calendarInfo['{http://owncloud.org/ns}owner-principal'])) {
150
+            return $this->calendarInfo['{http://owncloud.org/ns}owner-principal'];
151
+        }
152
+        return parent::getOwner();
153
+    }
154
+
155
+    function delete() {
156
+        if (isset($this->calendarInfo['{http://owncloud.org/ns}owner-principal']) &&
157
+            $this->calendarInfo['{http://owncloud.org/ns}owner-principal'] !== $this->calendarInfo['principaluri']) {
158
+            $principal = 'principal:' . parent::getOwner();
159
+            $shares = $this->getShares();
160
+            $shares = array_filter($shares, function($share) use ($principal){
161
+                return $share['href'] === $principal;
162
+            });
163
+            if (empty($shares)) {
164
+                throw new Forbidden();
165
+            }
166
+
167
+            /** @var CalDavBackend $calDavBackend */
168
+            $calDavBackend = $this->caldavBackend;
169
+            $calDavBackend->updateShares($this, [], [
170
+                'href' => $principal
171
+            ]);
172
+            return;
173
+        }
174
+        parent::delete();
175
+    }
176
+
177
+    function propPatch(PropPatch $propPatch) {
178
+        // parent::propPatch will only update calendars table
179
+        // if calendar is shared, changes has to be made in properties table
180
+        if (!$this->isShared()) {
181
+            parent::propPatch($propPatch);
182
+        }
183
+    }
184
+
185
+    function getChild($name) {
186
+
187
+        $obj = $this->caldavBackend->getCalendarObject($this->calendarInfo['id'], $name);
188
+
189
+        if (!$obj) {
190
+            throw new NotFound('Calendar object not found');
191
+        }
192
+
193
+        if ($this->isShared() && $obj['classification'] === CalDavBackend::CLASSIFICATION_PRIVATE) {
194
+            throw new NotFound('Calendar object not found');
195
+        }
196
+
197
+        $obj['acl'] = $this->getChildACL();
198
+
199
+        return new CalendarObject($this->caldavBackend, $this->calendarInfo, $obj);
200
+
201
+    }
202
+
203
+    function getChildren() {
204
+
205
+        $objs = $this->caldavBackend->getCalendarObjects($this->calendarInfo['id']);
206
+        $children = [];
207
+        foreach ($objs as $obj) {
208
+            if ($this->isShared() && $obj['classification'] === CalDavBackend::CLASSIFICATION_PRIVATE) {
209
+                continue;
210
+            }
211
+            $obj['acl'] = $this->getChildACL();
212
+            $children[] = new CalendarObject($this->caldavBackend, $this->calendarInfo, $obj);
213
+        }
214
+        return $children;
215
+
216
+    }
217
+
218
+    function getMultipleChildren(array $paths) {
219
+
220
+        $objs = $this->caldavBackend->getMultipleCalendarObjects($this->calendarInfo['id'], $paths);
221
+        $children = [];
222
+        foreach ($objs as $obj) {
223
+            if ($this->isShared() && $obj['classification'] === CalDavBackend::CLASSIFICATION_PRIVATE) {
224
+                continue;
225
+            }
226
+            $obj['acl'] = $this->getChildACL();
227
+            $children[] = new CalendarObject($this->caldavBackend, $this->calendarInfo, $obj);
228
+        }
229
+        return $children;
230
+
231
+    }
232
+
233
+    function childExists($name) {
234
+        $obj = $this->caldavBackend->getCalendarObject($this->calendarInfo['id'], $name);
235
+        if (!$obj) {
236
+            return false;
237
+        }
238
+        if ($this->isShared() && $obj['classification'] === CalDavBackend::CLASSIFICATION_PRIVATE) {
239
+            return false;
240
+        }
241
+
242
+        return true;
243
+    }
244
+
245
+    function calendarQuery(array $filters) {
246
+
247
+        $uris = $this->caldavBackend->calendarQuery($this->calendarInfo['id'], $filters);
248
+        if ($this->isShared()) {
249
+            return array_filter($uris, function ($uri) {
250
+                return $this->childExists($uri);
251
+            });
252
+        }
253
+
254
+        return $uris;
255
+    }
256
+
257
+    /**
258
+     * @param boolean $value
259
+     * @return string|null
260
+     */
261
+    function setPublishStatus($value) {
262
+        $publicUri = $this->caldavBackend->setPublishStatus($value, $this);
263
+        $this->calendarInfo['publicuri'] = $publicUri;
264
+        return $publicUri;
265
+    }
266
+
267
+    /**
268
+     * @return mixed $value
269
+     */
270
+    function getPublishStatus() {
271
+        return $this->caldavBackend->getPublishStatus($this);
272
+    }
273
+
274
+    private function canWrite() {
275
+        if (isset($this->calendarInfo['{http://owncloud.org/ns}read-only'])) {
276
+            return !$this->calendarInfo['{http://owncloud.org/ns}read-only'];
277
+        }
278
+        return true;
279
+    }
280
+
281
+    private function isPublic() {
282
+        return isset($this->calendarInfo['{http://owncloud.org/ns}public']);
283
+    }
284
+
285
+    private function isShared() {
286
+        if (!isset($this->calendarInfo['{http://owncloud.org/ns}owner-principal'])) {
287
+            return false;
288
+        }
289
+
290
+        return $this->calendarInfo['{http://owncloud.org/ns}owner-principal'] !== $this->calendarInfo['principaluri'];
291
+    }
292
+
293
+    public function isSubscription() {
294
+        return isset($this->calendarInfo['{http://calendarserver.org/ns/}source']);
295
+    }
296 296
 
297 297
 }
Please login to merge, or discard this patch.
apps/dav/lib/Files/CustomPropertiesBackend.php 1 patch
Indentation   +253 added lines, -253 removed lines patch added patch discarded remove patch
@@ -32,258 +32,258 @@
 block discarded – undo
32 32
 
33 33
 class CustomPropertiesBackend implements BackendInterface {
34 34
 
35
-	/**
36
-	 * Ignored properties
37
-	 *
38
-	 * @var array
39
-	 */
40
-	private $ignoredProperties = array(
41
-		'{DAV:}getcontentlength',
42
-		'{DAV:}getcontenttype',
43
-		'{DAV:}getetag',
44
-		'{DAV:}quota-used-bytes',
45
-		'{DAV:}quota-available-bytes',
46
-		'{http://owncloud.org/ns}permissions',
47
-		'{http://owncloud.org/ns}downloadURL',
48
-		'{http://owncloud.org/ns}dDC',
49
-		'{http://owncloud.org/ns}size',
50
-	);
51
-
52
-	/**
53
-	 * @var Tree
54
-	 */
55
-	private $tree;
56
-
57
-	/**
58
-	 * @var IDBConnection
59
-	 */
60
-	private $connection;
61
-
62
-	/**
63
-	 * @var string
64
-	 */
65
-	private $user;
66
-
67
-	/**
68
-	 * Properties cache
69
-	 *
70
-	 * @var array
71
-	 */
72
-	private $cache = [];
73
-
74
-	/**
75
-	 * @param Tree $tree node tree
76
-	 * @param IDBConnection $connection database connection
77
-	 * @param IUser $user owner of the tree and properties
78
-	 */
79
-	public function __construct(
80
-		Tree $tree,
81
-		IDBConnection $connection,
82
-		IUser $user) {
83
-		$this->tree = $tree;
84
-		$this->connection = $connection;
85
-		$this->user = $user->getUID();
86
-	}
87
-
88
-	/**
89
-	 * Fetches properties for a path.
90
-	 *
91
-	 * @param string $path
92
-	 * @param PropFind $propFind
93
-	 * @return void
94
-	 */
95
-	public function propFind($path, PropFind $propFind) {
96
-
97
-		$requestedProps = $propFind->get404Properties();
98
-
99
-		// these might appear
100
-		$requestedProps = array_diff(
101
-			$requestedProps,
102
-			$this->ignoredProperties
103
-		);
104
-
105
-		// substr of calendars/ => path is inside the CalDAV component
106
-		// two '/' => this a calendar (no calendar-home nor calendar object)
107
-		if (substr($path, 0, 10) === 'calendars/' && substr_count($path, '/') === 2) {
108
-			$allRequestedProps = $propFind->getRequestedProperties();
109
-			$customPropertiesForShares = [
110
-				'{DAV:}displayname',
111
-				'{urn:ietf:params:xml:ns:caldav}calendar-description',
112
-				'{urn:ietf:params:xml:ns:caldav}calendar-timezone',
113
-				'{http://apple.com/ns/ical/}calendar-order',
114
-				'{http://apple.com/ns/ical/}calendar-color',
115
-				'{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp'
116
-			];
117
-
118
-			foreach ($customPropertiesForShares as $customPropertyForShares) {
119
-				if (in_array($customPropertyForShares, $allRequestedProps)) {
120
-					$requestedProps[] = $customPropertyForShares;
121
-				}
122
-			}
123
-		}
124
-
125
-		if (empty($requestedProps)) {
126
-			return;
127
-		}
128
-
129
-		$props = $this->getProperties($path, $requestedProps);
130
-		foreach ($props as $propName => $propValue) {
131
-			$propFind->set($propName, $propValue);
132
-		}
133
-	}
134
-
135
-	/**
136
-	 * Updates properties for a path
137
-	 *
138
-	 * @param string $path
139
-	 * @param PropPatch $propPatch
140
-	 *
141
-	 * @return void
142
-	 */
143
-	public function propPatch($path, PropPatch $propPatch) {
144
-		$propPatch->handleRemaining(function($changedProps) use ($path) {
145
-			return $this->updateProperties($path, $changedProps);
146
-		});
147
-	}
148
-
149
-	/**
150
-	 * This method is called after a node is deleted.
151
-	 *
152
-	 * @param string $path path of node for which to delete properties
153
-	 */
154
-	public function delete($path) {
155
-		$statement = $this->connection->prepare(
156
-			'DELETE FROM `*PREFIX*properties` WHERE `userid` = ? AND `propertypath` = ?'
157
-		);
158
-		$statement->execute(array($this->user, $path));
159
-		$statement->closeCursor();
160
-
161
-		unset($this->cache[$path]);
162
-	}
163
-
164
-	/**
165
-	 * This method is called after a successful MOVE
166
-	 *
167
-	 * @param string $source
168
-	 * @param string $destination
169
-	 *
170
-	 * @return void
171
-	 */
172
-	public function move($source, $destination) {
173
-		$statement = $this->connection->prepare(
174
-			'UPDATE `*PREFIX*properties` SET `propertypath` = ?' .
175
-			' WHERE `userid` = ? AND `propertypath` = ?'
176
-		);
177
-		$statement->execute(array($destination, $this->user, $source));
178
-		$statement->closeCursor();
179
-	}
180
-
181
-	/**
182
-	 * Returns a list of properties for this nodes.;
183
-	 * @param string $path
184
-	 * @param array $requestedProperties requested properties or empty array for "all"
185
-	 * @return array
186
-	 * @note The properties list is a list of propertynames the client
187
-	 * requested, encoded as xmlnamespace#tagName, for example:
188
-	 * http://www.example.org/namespace#author If the array is empty, all
189
-	 * properties should be returned
190
-	 */
191
-	private function getProperties($path, array $requestedProperties) {
192
-		if (isset($this->cache[$path])) {
193
-			return $this->cache[$path];
194
-		}
195
-
196
-		// TODO: chunking if more than 1000 properties
197
-		$sql = 'SELECT * FROM `*PREFIX*properties` WHERE `userid` = ? AND `propertypath` = ?';
198
-
199
-		$whereValues = array($this->user, $path);
200
-		$whereTypes = array(null, null);
201
-
202
-		if (!empty($requestedProperties)) {
203
-			// request only a subset
204
-			$sql .= ' AND `propertyname` in (?)';
205
-			$whereValues[] = $requestedProperties;
206
-			$whereTypes[] = \Doctrine\DBAL\Connection::PARAM_STR_ARRAY;
207
-		}
208
-
209
-		$result = $this->connection->executeQuery(
210
-			$sql,
211
-			$whereValues,
212
-			$whereTypes
213
-		);
214
-
215
-		$props = [];
216
-		while ($row = $result->fetch()) {
217
-			$props[$row['propertyname']] = $row['propertyvalue'];
218
-		}
219
-
220
-		$result->closeCursor();
221
-
222
-		$this->cache[$path] = $props;
223
-		return $props;
224
-	}
225
-
226
-	/**
227
-	 * Update properties
228
-	 *
229
-	 * @param string $path node for which to update properties
230
-	 * @param array $properties array of properties to update
231
-	 *
232
-	 * @return bool
233
-	 */
234
-	private function updateProperties($path, $properties) {
235
-
236
-		$deleteStatement = 'DELETE FROM `*PREFIX*properties`' .
237
-			' WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?';
238
-
239
-		$insertStatement = 'INSERT INTO `*PREFIX*properties`' .
240
-			' (`userid`,`propertypath`,`propertyname`,`propertyvalue`) VALUES(?,?,?,?)';
241
-
242
-		$updateStatement = 'UPDATE `*PREFIX*properties` SET `propertyvalue` = ?' .
243
-			' WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?';
244
-
245
-		// TODO: use "insert or update" strategy ?
246
-		$existing = $this->getProperties($path, array());
247
-		$this->connection->beginTransaction();
248
-		foreach ($properties as $propertyName => $propertyValue) {
249
-			// If it was null, we need to delete the property
250
-			if (is_null($propertyValue)) {
251
-				if (array_key_exists($propertyName, $existing)) {
252
-					$this->connection->executeUpdate($deleteStatement,
253
-						array(
254
-							$this->user,
255
-							$path,
256
-							$propertyName
257
-						)
258
-					);
259
-				}
260
-			} else {
261
-				if (!array_key_exists($propertyName, $existing)) {
262
-					$this->connection->executeUpdate($insertStatement,
263
-						array(
264
-							$this->user,
265
-							$path,
266
-							$propertyName,
267
-							$propertyValue
268
-						)
269
-					);
270
-				} else {
271
-					$this->connection->executeUpdate($updateStatement,
272
-						array(
273
-							$propertyValue,
274
-							$this->user,
275
-							$path,
276
-							$propertyName
277
-						)
278
-					);
279
-				}
280
-			}
281
-		}
282
-
283
-		$this->connection->commit();
284
-		unset($this->cache[$path]);
285
-
286
-		return true;
287
-	}
35
+    /**
36
+     * Ignored properties
37
+     *
38
+     * @var array
39
+     */
40
+    private $ignoredProperties = array(
41
+        '{DAV:}getcontentlength',
42
+        '{DAV:}getcontenttype',
43
+        '{DAV:}getetag',
44
+        '{DAV:}quota-used-bytes',
45
+        '{DAV:}quota-available-bytes',
46
+        '{http://owncloud.org/ns}permissions',
47
+        '{http://owncloud.org/ns}downloadURL',
48
+        '{http://owncloud.org/ns}dDC',
49
+        '{http://owncloud.org/ns}size',
50
+    );
51
+
52
+    /**
53
+     * @var Tree
54
+     */
55
+    private $tree;
56
+
57
+    /**
58
+     * @var IDBConnection
59
+     */
60
+    private $connection;
61
+
62
+    /**
63
+     * @var string
64
+     */
65
+    private $user;
66
+
67
+    /**
68
+     * Properties cache
69
+     *
70
+     * @var array
71
+     */
72
+    private $cache = [];
73
+
74
+    /**
75
+     * @param Tree $tree node tree
76
+     * @param IDBConnection $connection database connection
77
+     * @param IUser $user owner of the tree and properties
78
+     */
79
+    public function __construct(
80
+        Tree $tree,
81
+        IDBConnection $connection,
82
+        IUser $user) {
83
+        $this->tree = $tree;
84
+        $this->connection = $connection;
85
+        $this->user = $user->getUID();
86
+    }
87
+
88
+    /**
89
+     * Fetches properties for a path.
90
+     *
91
+     * @param string $path
92
+     * @param PropFind $propFind
93
+     * @return void
94
+     */
95
+    public function propFind($path, PropFind $propFind) {
96
+
97
+        $requestedProps = $propFind->get404Properties();
98
+
99
+        // these might appear
100
+        $requestedProps = array_diff(
101
+            $requestedProps,
102
+            $this->ignoredProperties
103
+        );
104
+
105
+        // substr of calendars/ => path is inside the CalDAV component
106
+        // two '/' => this a calendar (no calendar-home nor calendar object)
107
+        if (substr($path, 0, 10) === 'calendars/' && substr_count($path, '/') === 2) {
108
+            $allRequestedProps = $propFind->getRequestedProperties();
109
+            $customPropertiesForShares = [
110
+                '{DAV:}displayname',
111
+                '{urn:ietf:params:xml:ns:caldav}calendar-description',
112
+                '{urn:ietf:params:xml:ns:caldav}calendar-timezone',
113
+                '{http://apple.com/ns/ical/}calendar-order',
114
+                '{http://apple.com/ns/ical/}calendar-color',
115
+                '{urn:ietf:params:xml:ns:caldav}schedule-calendar-transp'
116
+            ];
117
+
118
+            foreach ($customPropertiesForShares as $customPropertyForShares) {
119
+                if (in_array($customPropertyForShares, $allRequestedProps)) {
120
+                    $requestedProps[] = $customPropertyForShares;
121
+                }
122
+            }
123
+        }
124
+
125
+        if (empty($requestedProps)) {
126
+            return;
127
+        }
128
+
129
+        $props = $this->getProperties($path, $requestedProps);
130
+        foreach ($props as $propName => $propValue) {
131
+            $propFind->set($propName, $propValue);
132
+        }
133
+    }
134
+
135
+    /**
136
+     * Updates properties for a path
137
+     *
138
+     * @param string $path
139
+     * @param PropPatch $propPatch
140
+     *
141
+     * @return void
142
+     */
143
+    public function propPatch($path, PropPatch $propPatch) {
144
+        $propPatch->handleRemaining(function($changedProps) use ($path) {
145
+            return $this->updateProperties($path, $changedProps);
146
+        });
147
+    }
148
+
149
+    /**
150
+     * This method is called after a node is deleted.
151
+     *
152
+     * @param string $path path of node for which to delete properties
153
+     */
154
+    public function delete($path) {
155
+        $statement = $this->connection->prepare(
156
+            'DELETE FROM `*PREFIX*properties` WHERE `userid` = ? AND `propertypath` = ?'
157
+        );
158
+        $statement->execute(array($this->user, $path));
159
+        $statement->closeCursor();
160
+
161
+        unset($this->cache[$path]);
162
+    }
163
+
164
+    /**
165
+     * This method is called after a successful MOVE
166
+     *
167
+     * @param string $source
168
+     * @param string $destination
169
+     *
170
+     * @return void
171
+     */
172
+    public function move($source, $destination) {
173
+        $statement = $this->connection->prepare(
174
+            'UPDATE `*PREFIX*properties` SET `propertypath` = ?' .
175
+            ' WHERE `userid` = ? AND `propertypath` = ?'
176
+        );
177
+        $statement->execute(array($destination, $this->user, $source));
178
+        $statement->closeCursor();
179
+    }
180
+
181
+    /**
182
+     * Returns a list of properties for this nodes.;
183
+     * @param string $path
184
+     * @param array $requestedProperties requested properties or empty array for "all"
185
+     * @return array
186
+     * @note The properties list is a list of propertynames the client
187
+     * requested, encoded as xmlnamespace#tagName, for example:
188
+     * http://www.example.org/namespace#author If the array is empty, all
189
+     * properties should be returned
190
+     */
191
+    private function getProperties($path, array $requestedProperties) {
192
+        if (isset($this->cache[$path])) {
193
+            return $this->cache[$path];
194
+        }
195
+
196
+        // TODO: chunking if more than 1000 properties
197
+        $sql = 'SELECT * FROM `*PREFIX*properties` WHERE `userid` = ? AND `propertypath` = ?';
198
+
199
+        $whereValues = array($this->user, $path);
200
+        $whereTypes = array(null, null);
201
+
202
+        if (!empty($requestedProperties)) {
203
+            // request only a subset
204
+            $sql .= ' AND `propertyname` in (?)';
205
+            $whereValues[] = $requestedProperties;
206
+            $whereTypes[] = \Doctrine\DBAL\Connection::PARAM_STR_ARRAY;
207
+        }
208
+
209
+        $result = $this->connection->executeQuery(
210
+            $sql,
211
+            $whereValues,
212
+            $whereTypes
213
+        );
214
+
215
+        $props = [];
216
+        while ($row = $result->fetch()) {
217
+            $props[$row['propertyname']] = $row['propertyvalue'];
218
+        }
219
+
220
+        $result->closeCursor();
221
+
222
+        $this->cache[$path] = $props;
223
+        return $props;
224
+    }
225
+
226
+    /**
227
+     * Update properties
228
+     *
229
+     * @param string $path node for which to update properties
230
+     * @param array $properties array of properties to update
231
+     *
232
+     * @return bool
233
+     */
234
+    private function updateProperties($path, $properties) {
235
+
236
+        $deleteStatement = 'DELETE FROM `*PREFIX*properties`' .
237
+            ' WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?';
238
+
239
+        $insertStatement = 'INSERT INTO `*PREFIX*properties`' .
240
+            ' (`userid`,`propertypath`,`propertyname`,`propertyvalue`) VALUES(?,?,?,?)';
241
+
242
+        $updateStatement = 'UPDATE `*PREFIX*properties` SET `propertyvalue` = ?' .
243
+            ' WHERE `userid` = ? AND `propertypath` = ? AND `propertyname` = ?';
244
+
245
+        // TODO: use "insert or update" strategy ?
246
+        $existing = $this->getProperties($path, array());
247
+        $this->connection->beginTransaction();
248
+        foreach ($properties as $propertyName => $propertyValue) {
249
+            // If it was null, we need to delete the property
250
+            if (is_null($propertyValue)) {
251
+                if (array_key_exists($propertyName, $existing)) {
252
+                    $this->connection->executeUpdate($deleteStatement,
253
+                        array(
254
+                            $this->user,
255
+                            $path,
256
+                            $propertyName
257
+                        )
258
+                    );
259
+                }
260
+            } else {
261
+                if (!array_key_exists($propertyName, $existing)) {
262
+                    $this->connection->executeUpdate($insertStatement,
263
+                        array(
264
+                            $this->user,
265
+                            $path,
266
+                            $propertyName,
267
+                            $propertyValue
268
+                        )
269
+                    );
270
+                } else {
271
+                    $this->connection->executeUpdate($updateStatement,
272
+                        array(
273
+                            $propertyValue,
274
+                            $this->user,
275
+                            $path,
276
+                            $propertyName
277
+                        )
278
+                    );
279
+                }
280
+            }
281
+        }
282
+
283
+        $this->connection->commit();
284
+        unset($this->cache[$path]);
285
+
286
+        return true;
287
+    }
288 288
 
289 289
 }
Please login to merge, or discard this patch.