Completed
Push — master ( 64a4da...21cb6b )
by Thomas
07:39
created

CommentNode::propPatch()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @author Arthur Schiwon <[email protected]>
4
 * @author Vincent Petry <[email protected]>
5
 *
6
 * @copyright Copyright (c) 2016, ownCloud GmbH.
7
 * @license AGPL-3.0
8
 *
9
 * This code is free software: you can redistribute it and/or modify
10
 * it under the terms of the GNU Affero General Public License, version 3,
11
 * as published by the Free Software Foundation.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
 * GNU Affero General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Affero General Public License, version 3,
19
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
20
 *
21
 */
22
23
namespace OCA\Comments\Dav;
24
25
26
use OCP\Comments\IComment;
27
use OCP\Comments\ICommentsManager;
28
use OCP\Comments\MessageTooLongException;
29
use OCP\ILogger;
30
use OCP\IUserManager;
31
use OCP\IUserSession;
32
use Sabre\DAV\Exception\BadRequest;
33
use Sabre\DAV\Exception\Forbidden;
34
use Sabre\DAV\Exception\MethodNotAllowed;
35
use Sabre\DAV\PropPatch;
36
37
class CommentNode implements \Sabre\DAV\INode, \Sabre\DAV\IProperties {
38
	const NS_OWNCLOUD = 'http://owncloud.org/ns';
39
40
	const PROPERTY_NAME_UNREAD = '{http://owncloud.org/ns}isUnread';
41
	const PROPERTY_NAME_MESSAGE = '{http://owncloud.org/ns}message';
42
	const PROPERTY_NAME_ACTOR_DISPLAYNAME = '{http://owncloud.org/ns}actorDisplayName';
43
44
	/** @var  IComment */
45
	public $comment;
46
47
	/** @var ICommentsManager */
48
	protected $commentsManager;
49
50
	/** @var  ILogger */
51
	protected $logger;
52
53
	/** @var array list of properties with key being their name and value their setter */
54
	protected $properties = [];
55
56
	/** @var IUserManager */
57
	protected $userManager;
58
59
	/** @var IUserSession */
60
	protected $userSession;
61
62
	/**
63
	 * CommentNode constructor.
64
	 *
65
	 * @param ICommentsManager $commentsManager
66
	 * @param IComment $comment
67
	 * @param IUserManager $userManager
68
	 * @param IUserSession $userSession
69
	 * @param ILogger $logger
70
	 */
71
	public function __construct(
72
		ICommentsManager $commentsManager,
73
		IComment $comment,
74
		IUserManager $userManager,
75
		IUserSession $userSession,
76
		ILogger $logger
77
	) {
78
		$this->commentsManager = $commentsManager;
79
		$this->comment = $comment;
80
		$this->logger = $logger;
81
82
		$methods = get_class_methods($this->comment);
83
		$methods = array_filter($methods, function($name){
84
			return strpos($name, 'get') === 0;
85
		});
86
		foreach($methods as $getter) {
87
			$name = '{'.self::NS_OWNCLOUD.'}' . lcfirst(substr($getter, 3));
88
			$this->properties[$name] = $getter;
89
		}
90
		$this->userManager = $userManager;
91
		$this->userSession = $userSession;
92
	}
93
94
	/**
95
	 * returns a list of all possible property names
96
	 *
97
	 * @return array
98
	 */
99
	static public function getPropertyNames() {
100
		return [
101
			'{http://owncloud.org/ns}id',
102
			'{http://owncloud.org/ns}parentId',
103
			'{http://owncloud.org/ns}topmostParentId',
104
			'{http://owncloud.org/ns}childrenCount',
105
			'{http://owncloud.org/ns}verb',
106
			'{http://owncloud.org/ns}actorType',
107
			'{http://owncloud.org/ns}actorId',
108
			'{http://owncloud.org/ns}creationDateTime',
109
			'{http://owncloud.org/ns}latestChildDateTime',
110
			'{http://owncloud.org/ns}objectType',
111
			'{http://owncloud.org/ns}objectId',
112
			// re-used property names are defined as constants
113
			self::PROPERTY_NAME_MESSAGE,
114
			self::PROPERTY_NAME_ACTOR_DISPLAYNAME,
115
			self::PROPERTY_NAME_UNREAD
116
		];
117
	}
118
119
	protected function checkWriteAccessOnComment() {
120
		$user = $this->userSession->getUser();
121
		if(    $this->comment->getActorType() !== 'users'
122
			|| is_null($user)
123
			|| $this->comment->getActorId() !== $user->getUID()
124
		) {
125
			throw new Forbidden('Only authors are allowed to edit their comment.');
126
		}
127
	}
128
129
	/**
130
	 * Deleted the current node
131
	 *
132
	 * @return void
133
	 */
134
	function delete() {
135
		$this->checkWriteAccessOnComment();
136
		$this->commentsManager->delete($this->comment->getId());
137
	}
138
139
	/**
140
	 * Returns the name of the node.
141
	 *
142
	 * This is used to generate the url.
143
	 *
144
	 * @return string
145
	 */
146
	function getName() {
147
		return $this->comment->getId();
148
	}
149
150
	/**
151
	 * Renames the node
152
	 *
153
	 * @param string $name The new name
154
	 * @throws MethodNotAllowed
155
	 */
156
	function setName($name) {
157
		throw new MethodNotAllowed();
158
	}
159
160
	/**
161
	 * Returns the last modification time, as a unix timestamp
162
	 *
163
	 * @return int
164
	 */
165
	function getLastModified() {
166
		return null;
167
	}
168
169
	/**
170
	 * update the comment's message
171
	 *
172
	 * @param $propertyValue
173
	 * @return bool
174
	 * @throws BadRequest
175
	 * @throws Forbidden
176
	 */
177
	public function updateComment($propertyValue) {
178
		$this->checkWriteAccessOnComment();
179
		try {
180
			$this->comment->setMessage($propertyValue);
181
			$this->commentsManager->save($this->comment);
182
			return true;
183
		} catch (\Exception $e) {
184
			$this->logger->logException($e, ['app' => 'dav/comments']);
185
			if($e instanceof MessageTooLongException) {
186
				$msg = 'Message exceeds allowed character limit of ';
187
				throw new BadRequest($msg . IComment::MAX_MESSAGE_LENGTH, 0, $e);
188
			}
189
			throw $e;
190
		}
191
	}
192
193
	/**
194
	 * Updates properties on this node.
195
	 *
196
	 * This method received a PropPatch object, which contains all the
197
	 * information about the update.
198
	 *
199
	 * To update specific properties, call the 'handle' method on this object.
200
	 * Read the PropPatch documentation for more information.
201
	 *
202
	 * @param PropPatch $propPatch
203
	 * @return void
204
	 */
205
	function propPatch(PropPatch $propPatch) {
206
		// other properties than 'message' are read only
207
		$propPatch->handle(self::PROPERTY_NAME_MESSAGE, [$this, 'updateComment']);
208
	}
209
210
	/**
211
	 * Returns a list of properties for this nodes.
212
	 *
213
	 * The properties list is a list of propertynames the client requested,
214
	 * encoded in clark-notation {xmlnamespace}tagname
215
	 *
216
	 * If the array is empty, it means 'all properties' were requested.
217
	 *
218
	 * Note that it's fine to liberally give properties back, instead of
219
	 * conforming to the list of requested properties.
220
	 * The Server class will filter out the extra.
221
	 *
222
	 * @param array $properties
223
	 * @return array
224
	 */
225
	function getProperties($properties) {
226
		$properties = array_keys($this->properties);
227
228
		$result = [];
229
		foreach($properties as $property) {
230
			$getter = $this->properties[$property];
231
			if(method_exists($this->comment, $getter)) {
232
				$result[$property] = $this->comment->$getter();
233
			}
234
		}
235
236
		if($this->comment->getActorType() === 'users') {
237
			$user = $this->userManager->get($this->comment->getActorId());
238
			$displayName = is_null($user) ? null : $user->getDisplayName();
239
			$result[self::PROPERTY_NAME_ACTOR_DISPLAYNAME] = $displayName;
240
		}
241
242
		$unread = null;
243
		$user =  $this->userSession->getUser();
244
		if(!is_null($user)) {
245
			$readUntil = $this->commentsManager->getReadMark(
246
				$this->comment->getObjectType(),
247
				$this->comment->getObjectId(),
248
				$user
249
			);
250
			if(is_null($readUntil)) {
251
				$unread = 'true';
252
			} else {
253
				$unread = $this->comment->getCreationDateTime() > $readUntil;
254
				// re-format for output
255
				$unread = $unread ? 'true' : 'false';
256
			}
257
		}
258
		$result[self::PROPERTY_NAME_UNREAD] = $unread;
259
260
		return $result;
261
	}
262
}
263