2016-01-11 20:09:00 +03:00
|
|
|
<?php
|
|
|
|
/**
|
2016-07-21 17:49:16 +03:00
|
|
|
* @copyright Copyright (c) 2016, ownCloud, Inc.
|
|
|
|
*
|
2016-05-26 20:56:05 +03:00
|
|
|
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
|
2016-07-21 17:49:16 +03:00
|
|
|
* @author Vincent Petry <pvince81@owncloud.com>
|
2016-01-11 20:09:00 +03:00
|
|
|
*
|
|
|
|
* @license AGPL-3.0
|
|
|
|
*
|
|
|
|
* This code is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU Affero General Public License, version 3,
|
|
|
|
* as published by the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU Affero General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Affero General Public License, version 3,
|
2019-12-03 21:57:53 +03:00
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
2016-01-11 20:09:00 +03:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
namespace OCA\DAV\Comments;
|
|
|
|
|
|
|
|
use OCP\Comments\IComment;
|
|
|
|
use OCP\Comments\ICommentsManager;
|
2016-02-09 15:59:13 +03:00
|
|
|
use OCP\Comments\MessageTooLongException;
|
2016-01-11 20:09:00 +03:00
|
|
|
use OCP\ILogger;
|
|
|
|
use OCP\IUserManager;
|
2016-01-30 01:23:16 +03:00
|
|
|
use OCP\IUserSession;
|
2016-02-09 15:59:13 +03:00
|
|
|
use Sabre\DAV\Exception\BadRequest;
|
2016-02-04 14:57:48 +03:00
|
|
|
use Sabre\DAV\Exception\Forbidden;
|
2016-01-11 20:09:00 +03:00
|
|
|
use Sabre\DAV\Exception\MethodNotAllowed;
|
|
|
|
use Sabre\DAV\PropPatch;
|
|
|
|
|
|
|
|
class CommentNode implements \Sabre\DAV\INode, \Sabre\DAV\IProperties {
|
|
|
|
const NS_OWNCLOUD = 'http://owncloud.org/ns';
|
|
|
|
|
2016-01-30 01:23:16 +03:00
|
|
|
const PROPERTY_NAME_UNREAD = '{http://owncloud.org/ns}isUnread';
|
|
|
|
const PROPERTY_NAME_MESSAGE = '{http://owncloud.org/ns}message';
|
|
|
|
const PROPERTY_NAME_ACTOR_DISPLAYNAME = '{http://owncloud.org/ns}actorDisplayName';
|
2016-10-14 01:19:31 +03:00
|
|
|
const PROPERTY_NAME_MENTIONS = '{http://owncloud.org/ns}mentions';
|
|
|
|
const PROPERTY_NAME_MENTION = '{http://owncloud.org/ns}mention';
|
|
|
|
const PROPERTY_NAME_MENTION_TYPE = '{http://owncloud.org/ns}mentionType';
|
|
|
|
const PROPERTY_NAME_MENTION_ID = '{http://owncloud.org/ns}mentionId';
|
2016-10-16 21:28:36 +03:00
|
|
|
const PROPERTY_NAME_MENTION_DISPLAYNAME = '{http://owncloud.org/ns}mentionDisplayName';
|
2016-01-30 01:23:16 +03:00
|
|
|
|
2016-01-11 20:09:00 +03:00
|
|
|
/** @var IComment */
|
|
|
|
public $comment;
|
|
|
|
|
|
|
|
/** @var ICommentsManager */
|
|
|
|
protected $commentsManager;
|
|
|
|
|
|
|
|
/** @var ILogger */
|
|
|
|
protected $logger;
|
|
|
|
|
|
|
|
/** @var array list of properties with key being their name and value their setter */
|
|
|
|
protected $properties = [];
|
|
|
|
|
|
|
|
/** @var IUserManager */
|
|
|
|
protected $userManager;
|
|
|
|
|
2016-01-30 01:23:16 +03:00
|
|
|
/** @var IUserSession */
|
|
|
|
protected $userSession;
|
|
|
|
|
2016-01-11 20:09:00 +03:00
|
|
|
/**
|
|
|
|
* CommentNode constructor.
|
|
|
|
*
|
|
|
|
* @param ICommentsManager $commentsManager
|
|
|
|
* @param IComment $comment
|
|
|
|
* @param IUserManager $userManager
|
2016-01-30 01:23:16 +03:00
|
|
|
* @param IUserSession $userSession
|
2016-01-11 20:09:00 +03:00
|
|
|
* @param ILogger $logger
|
|
|
|
*/
|
|
|
|
public function __construct(
|
|
|
|
ICommentsManager $commentsManager,
|
|
|
|
IComment $comment,
|
|
|
|
IUserManager $userManager,
|
2016-01-30 01:23:16 +03:00
|
|
|
IUserSession $userSession,
|
2016-01-11 20:09:00 +03:00
|
|
|
ILogger $logger
|
|
|
|
) {
|
|
|
|
$this->commentsManager = $commentsManager;
|
|
|
|
$this->comment = $comment;
|
|
|
|
$this->logger = $logger;
|
|
|
|
|
|
|
|
$methods = get_class_methods($this->comment);
|
2020-04-09 14:53:40 +03:00
|
|
|
$methods = array_filter($methods, function ($name) {
|
2016-01-11 20:09:00 +03:00
|
|
|
return strpos($name, 'get') === 0;
|
|
|
|
});
|
|
|
|
foreach($methods as $getter) {
|
2016-10-14 01:19:31 +03:00
|
|
|
if($getter === 'getMentions') {
|
|
|
|
continue; // special treatment
|
|
|
|
}
|
2016-01-11 20:09:00 +03:00
|
|
|
$name = '{'.self::NS_OWNCLOUD.'}' . lcfirst(substr($getter, 3));
|
|
|
|
$this->properties[$name] = $getter;
|
|
|
|
}
|
|
|
|
$this->userManager = $userManager;
|
2016-01-30 01:23:16 +03:00
|
|
|
$this->userSession = $userSession;
|
2016-01-11 20:09:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* returns a list of all possible property names
|
|
|
|
*
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
static public function getPropertyNames() {
|
|
|
|
return [
|
|
|
|
'{http://owncloud.org/ns}id',
|
|
|
|
'{http://owncloud.org/ns}parentId',
|
|
|
|
'{http://owncloud.org/ns}topmostParentId',
|
|
|
|
'{http://owncloud.org/ns}childrenCount',
|
|
|
|
'{http://owncloud.org/ns}verb',
|
|
|
|
'{http://owncloud.org/ns}actorType',
|
|
|
|
'{http://owncloud.org/ns}actorId',
|
|
|
|
'{http://owncloud.org/ns}creationDateTime',
|
|
|
|
'{http://owncloud.org/ns}latestChildDateTime',
|
|
|
|
'{http://owncloud.org/ns}objectType',
|
|
|
|
'{http://owncloud.org/ns}objectId',
|
2016-01-30 01:23:16 +03:00
|
|
|
// re-used property names are defined as constants
|
|
|
|
self::PROPERTY_NAME_MESSAGE,
|
|
|
|
self::PROPERTY_NAME_ACTOR_DISPLAYNAME,
|
2016-10-14 01:19:31 +03:00
|
|
|
self::PROPERTY_NAME_UNREAD,
|
|
|
|
self::PROPERTY_NAME_MENTIONS,
|
|
|
|
self::PROPERTY_NAME_MENTION,
|
|
|
|
self::PROPERTY_NAME_MENTION_TYPE,
|
|
|
|
self::PROPERTY_NAME_MENTION_ID,
|
2016-10-16 21:28:36 +03:00
|
|
|
self::PROPERTY_NAME_MENTION_DISPLAYNAME,
|
2016-01-11 20:09:00 +03:00
|
|
|
];
|
|
|
|
}
|
|
|
|
|
2016-02-04 14:57:48 +03:00
|
|
|
protected function checkWriteAccessOnComment() {
|
|
|
|
$user = $this->userSession->getUser();
|
2020-04-09 17:07:47 +03:00
|
|
|
if($this->comment->getActorType() !== 'users'
|
2016-02-04 14:57:48 +03:00
|
|
|
|| is_null($user)
|
|
|
|
|| $this->comment->getActorId() !== $user->getUID()
|
|
|
|
) {
|
|
|
|
throw new Forbidden('Only authors are allowed to edit their comment.');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-11 20:09:00 +03:00
|
|
|
/**
|
|
|
|
* Deleted the current node
|
|
|
|
*
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
function delete() {
|
2016-02-04 14:57:48 +03:00
|
|
|
$this->checkWriteAccessOnComment();
|
2016-01-11 20:09:00 +03:00
|
|
|
$this->commentsManager->delete($this->comment->getId());
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the name of the node.
|
|
|
|
*
|
|
|
|
* This is used to generate the url.
|
|
|
|
*
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
function getName() {
|
|
|
|
return $this->comment->getId();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Renames the node
|
|
|
|
*
|
|
|
|
* @param string $name The new name
|
|
|
|
* @throws MethodNotAllowed
|
|
|
|
*/
|
|
|
|
function setName($name) {
|
|
|
|
throw new MethodNotAllowed();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the last modification time, as a unix timestamp
|
|
|
|
*
|
|
|
|
* @return int
|
|
|
|
*/
|
|
|
|
function getLastModified() {
|
2016-01-26 14:08:51 +03:00
|
|
|
return null;
|
2016-01-11 20:09:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* update the comment's message
|
|
|
|
*
|
|
|
|
* @param $propertyValue
|
|
|
|
* @return bool
|
2016-02-09 15:59:13 +03:00
|
|
|
* @throws BadRequest
|
2016-10-12 19:06:22 +03:00
|
|
|
* @throws \Exception
|
2016-01-11 20:09:00 +03:00
|
|
|
*/
|
|
|
|
public function updateComment($propertyValue) {
|
2016-02-04 14:57:48 +03:00
|
|
|
$this->checkWriteAccessOnComment();
|
2016-01-11 20:09:00 +03:00
|
|
|
try {
|
|
|
|
$this->comment->setMessage($propertyValue);
|
|
|
|
$this->commentsManager->save($this->comment);
|
|
|
|
return true;
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
$this->logger->logException($e, ['app' => 'dav/comments']);
|
2016-02-09 15:59:13 +03:00
|
|
|
if($e instanceof MessageTooLongException) {
|
|
|
|
$msg = 'Message exceeds allowed character limit of ';
|
|
|
|
throw new BadRequest($msg . IComment::MAX_MESSAGE_LENGTH, 0, $e);
|
|
|
|
}
|
2016-06-24 11:10:10 +03:00
|
|
|
throw $e;
|
2016-01-11 20:09:00 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Updates properties on this node.
|
|
|
|
*
|
|
|
|
* This method received a PropPatch object, which contains all the
|
|
|
|
* information about the update.
|
|
|
|
*
|
|
|
|
* To update specific properties, call the 'handle' method on this object.
|
|
|
|
* Read the PropPatch documentation for more information.
|
|
|
|
*
|
|
|
|
* @param PropPatch $propPatch
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
function propPatch(PropPatch $propPatch) {
|
|
|
|
// other properties than 'message' are read only
|
2016-01-30 01:23:16 +03:00
|
|
|
$propPatch->handle(self::PROPERTY_NAME_MESSAGE, [$this, 'updateComment']);
|
2016-01-11 20:09:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns a list of properties for this nodes.
|
|
|
|
*
|
|
|
|
* The properties list is a list of propertynames the client requested,
|
|
|
|
* encoded in clark-notation {xmlnamespace}tagname
|
|
|
|
*
|
|
|
|
* If the array is empty, it means 'all properties' were requested.
|
|
|
|
*
|
|
|
|
* Note that it's fine to liberally give properties back, instead of
|
|
|
|
* conforming to the list of requested properties.
|
|
|
|
* The Server class will filter out the extra.
|
|
|
|
*
|
|
|
|
* @param array $properties
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
function getProperties($properties) {
|
|
|
|
$properties = array_keys($this->properties);
|
|
|
|
|
|
|
|
$result = [];
|
|
|
|
foreach($properties as $property) {
|
|
|
|
$getter = $this->properties[$property];
|
|
|
|
if(method_exists($this->comment, $getter)) {
|
|
|
|
$result[$property] = $this->comment->$getter();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if($this->comment->getActorType() === 'users') {
|
|
|
|
$user = $this->userManager->get($this->comment->getActorId());
|
|
|
|
$displayName = is_null($user) ? null : $user->getDisplayName();
|
2016-01-30 01:23:16 +03:00
|
|
|
$result[self::PROPERTY_NAME_ACTOR_DISPLAYNAME] = $displayName;
|
|
|
|
}
|
|
|
|
|
2016-10-14 01:19:31 +03:00
|
|
|
$result[self::PROPERTY_NAME_MENTIONS] = $this->composeMentionsPropertyValue();
|
|
|
|
|
2016-01-30 01:23:16 +03:00
|
|
|
$unread = null;
|
|
|
|
$user = $this->userSession->getUser();
|
|
|
|
if(!is_null($user)) {
|
|
|
|
$readUntil = $this->commentsManager->getReadMark(
|
|
|
|
$this->comment->getObjectType(),
|
|
|
|
$this->comment->getObjectId(),
|
|
|
|
$user
|
|
|
|
);
|
|
|
|
if(is_null($readUntil)) {
|
|
|
|
$unread = 'true';
|
|
|
|
} else {
|
|
|
|
$unread = $this->comment->getCreationDateTime() > $readUntil;
|
|
|
|
// re-format for output
|
|
|
|
$unread = $unread ? 'true' : 'false';
|
|
|
|
}
|
2016-01-11 20:09:00 +03:00
|
|
|
}
|
2016-01-30 01:23:16 +03:00
|
|
|
$result[self::PROPERTY_NAME_UNREAD] = $unread;
|
2016-01-11 20:09:00 +03:00
|
|
|
|
|
|
|
return $result;
|
|
|
|
}
|
2016-10-14 01:19:31 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* transforms a mentions array as returned from IComment->getMentions to an
|
|
|
|
* array with DAV-compatible structure that can be assigned to the
|
|
|
|
* PROPERTY_NAME_MENTION property.
|
|
|
|
*
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
protected function composeMentionsPropertyValue() {
|
2020-04-09 14:53:40 +03:00
|
|
|
return array_map(function ($mention) {
|
2016-10-16 21:28:36 +03:00
|
|
|
try {
|
|
|
|
$displayName = $this->commentsManager->resolveDisplayName($mention['type'], $mention['id']);
|
|
|
|
} catch (\OutOfBoundsException $e) {
|
|
|
|
$this->logger->logException($e);
|
|
|
|
// No displayname, upon client's discretion what to display.
|
|
|
|
$displayName = '';
|
|
|
|
}
|
|
|
|
|
2016-10-14 01:19:31 +03:00
|
|
|
return [
|
|
|
|
self::PROPERTY_NAME_MENTION => [
|
2016-10-16 21:28:36 +03:00
|
|
|
self::PROPERTY_NAME_MENTION_TYPE => $mention['type'],
|
|
|
|
self::PROPERTY_NAME_MENTION_ID => $mention['id'],
|
|
|
|
self::PROPERTY_NAME_MENTION_DISPLAYNAME => $displayName,
|
2016-10-14 01:19:31 +03:00
|
|
|
]
|
|
|
|
];
|
|
|
|
}, $this->comment->getMentions());
|
|
|
|
}
|
2016-01-11 20:09:00 +03:00
|
|
|
}
|