aboutsummaryrefslogtreecommitdiffstats
path: root/lib/private/Comments
diff options
context:
space:
mode:
Diffstat (limited to 'lib/private/Comments')
-rw-r--r--lib/private/Comments/Comment.php82
-rw-r--r--lib/private/Comments/Manager.php106
-rw-r--r--lib/private/Comments/ManagerFactory.php26
3 files changed, 89 insertions, 125 deletions
diff --git a/lib/private/Comments/Comment.php b/lib/private/Comments/Comment.php
index b1261a72520..7190f252c82 100644
--- a/lib/private/Comments/Comment.php
+++ b/lib/private/Comments/Comment.php
@@ -1,27 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @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,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Comments;
@@ -34,7 +16,7 @@ class Comment implements IComment {
'id' => '',
'parentId' => '0',
'topmostParentId' => '0',
- 'childrenCount' => '0',
+ 'childrenCount' => 0,
'message' => '',
'verb' => '',
'actorType' => '',
@@ -52,8 +34,8 @@ class Comment implements IComment {
/**
* Comment constructor.
*
- * @param array $data optional, array with keys according to column names from
- * the comments database scheme
+ * @param array $data optional, array with keys according to column names from
+ * the comments database scheme
*/
public function __construct(?array $data = null) {
if (is_array($data)) {
@@ -193,7 +175,7 @@ class Comment implements IComment {
}
$message = trim($message);
if ($maxLength && mb_strlen($message, 'UTF-8') > $maxLength) {
- throw new MessageTooLongException('Comment message must not exceed ' . $maxLength. ' characters');
+ throw new MessageTooLongException('Comment message must not exceed ' . $maxLength . ' characters');
}
$this->data['message'] = $message;
return $this;
@@ -203,24 +185,15 @@ class Comment implements IComment {
* returns an array containing mentions that are included in the comment
*
* @return array each mention provides a 'type' and an 'id', see example below
+ * @psalm-return list<array{type: 'guest'|'email'|'federated_group'|'group'|'federated_team'|'team'|'federated_user'|'user', id: non-empty-lowercase-string}>
+ * @since 30.0.2 Type 'email' is supported
+ * @since 29.0.0 Types 'federated_group', 'federated_team', 'team' and 'federated_user' are supported
+ * @since 23.0.0 Type 'group' is supported
+ * @since 17.0.0 Type 'guest' is supported
* @since 11.0.0
- *
- * The return array looks like:
- * [
- * [
- * 'type' => 'user',
- * 'id' => 'citizen4'
- * ],
- * [
- * 'type' => 'group',
- * 'id' => 'media'
- * ],
- * …
- * ]
- *
*/
public function getMentions(): array {
- $ok = preg_match_all("/\B(?<![^a-z0-9_\-@\.\'\s])@(\"guest\/[a-f0-9]+\"|\"(?:federated_)?(?:group|team|user){1}\/[a-z0-9_\-@\.\' \/:]+\"|\"[a-z0-9_\-@\.\' ]+\"|[a-z0-9_\-@\.\']+)/i", $this->getMessage(), $mentions);
+ $ok = preg_match_all("/\B(?<![^a-z0-9_\-@\.\'\s])@(\"(guest|email)\/[a-f0-9]+\"|\"(?:federated_)?(?:group|team|user){1}\/[a-z0-9_\-@\.\' \/:]+\"|\"[a-z0-9_\-@\.\' ]+\"|[a-z0-9_\-@\.\']+)/i", $this->getMessage(), $mentions);
if (!$ok || !isset($mentions[0])) {
return [];
}
@@ -231,20 +204,35 @@ class Comment implements IComment {
$result = [];
foreach ($mentionIds as $mentionId) {
// Cut-off the @ and remove wrapping double-quotes
+ /** @var non-empty-lowercase-string $cleanId */
$cleanId = trim(substr($mentionId, 1), '"');
if (str_starts_with($cleanId, 'guest/')) {
$result[] = ['type' => 'guest', 'id' => $cleanId];
+ } elseif (str_starts_with($cleanId, 'email/')) {
+ /** @var non-empty-lowercase-string $cleanId */
+ $cleanId = substr($cleanId, 6);
+ $result[] = ['type' => 'email', 'id' => $cleanId];
} elseif (str_starts_with($cleanId, 'federated_group/')) {
- $result[] = ['type' => 'federated_group', 'id' => substr($cleanId, 16)];
+ /** @var non-empty-lowercase-string $cleanId */
+ $cleanId = substr($cleanId, 16);
+ $result[] = ['type' => 'federated_group', 'id' => $cleanId];
} elseif (str_starts_with($cleanId, 'group/')) {
- $result[] = ['type' => 'group', 'id' => substr($cleanId, 6)];
+ /** @var non-empty-lowercase-string $cleanId */
+ $cleanId = substr($cleanId, 6);
+ $result[] = ['type' => 'group', 'id' => $cleanId];
} elseif (str_starts_with($cleanId, 'federated_team/')) {
- $result[] = ['type' => 'federated_team', 'id' => substr($cleanId, 15)];
+ /** @var non-empty-lowercase-string $cleanId */
+ $cleanId = substr($cleanId, 15);
+ $result[] = ['type' => 'federated_team', 'id' => $cleanId];
} elseif (str_starts_with($cleanId, 'team/')) {
- $result[] = ['type' => 'team', 'id' => substr($cleanId, 5)];
+ /** @var non-empty-lowercase-string $cleanId */
+ $cleanId = substr($cleanId, 5);
+ $result[] = ['type' => 'team', 'id' => $cleanId];
} elseif (str_starts_with($cleanId, 'federated_user/')) {
- $result[] = ['type' => 'federated_user', 'id' => substr($cleanId, 15)];
+ /** @var non-empty-lowercase-string $cleanId */
+ $cleanId = substr($cleanId, 15);
+ $result[] = ['type' => 'federated_user', 'id' => $cleanId];
} else {
$result[] = ['type' => 'user', 'id' => $cleanId];
}
@@ -315,7 +303,7 @@ class Comment implements IComment {
*
* If not explicitly set, it shall default to the time of initialization.
* @since 9.0.0
- * @throw \LogicException if creation date time is not set yet
+ * @throws \LogicException if creation date time is not set yet
*/
public function getCreationDateTime(): \DateTime {
if (!isset($this->data['creationDT'])) {
diff --git a/lib/private/Comments/Manager.php b/lib/private/Comments/Manager.php
index 3c5522de8ae..047fa361dad 100644
--- a/lib/private/Comments/Manager.php
+++ b/lib/private/Comments/Manager.php
@@ -1,30 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- * @author Morris Jobke <hey@morrisjobke.de>
- * @author Robin Appelman <robin@icewind.nl>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Simounet <contact@simounet.net>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- *
- * @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,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Comments;
@@ -37,6 +16,7 @@ use OCP\Comments\ICommentsEventHandler;
use OCP\Comments\ICommentsManager;
use OCP\Comments\NotFoundException;
use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\FileInfo;
use OCP\Files\Folder;
use OCP\Files\IRootFolder;
@@ -53,10 +33,10 @@ class Manager implements ICommentsManager {
/** @var IComment[] */
protected array $commentsCache = [];
- /** @var \Closure[] */
+ /** @var \Closure[] */
protected array $eventHandlerClosures = [];
- /** @var ICommentsEventHandler[] */
+ /** @var ICommentsEventHandler[] */
protected array $eventHandlers = [];
/** @var \Closure[] */
@@ -70,6 +50,7 @@ class Manager implements ICommentsManager {
protected IEmojiHelper $emojiHelper,
protected IInitialStateService $initialStateService,
protected IRootFolder $rootFolder,
+ protected IEventDispatcher $eventDispatcher,
) {
}
@@ -151,7 +132,7 @@ class Manager implements ICommentsManager {
try {
$comment->getCreationDateTime();
- } catch(\LogicException $e) {
+ } catch (\LogicException $e) {
$comment->setCreationDateTime(new \DateTime());
}
@@ -327,10 +308,10 @@ class Manager implements ICommentsManager {
* @param string $objectType the object type, e.g. 'files'
* @param string $objectId the id of the object
* @param int $limit optional, number of maximum comments to be returned. if
- * not specified, all comments are returned.
+ * not specified, all comments are returned.
* @param int $offset optional, starting point
* @param \DateTime $notOlderThan optional, timestamp of the oldest comments
- * that may be returned
+ * that may be returned
* @return list<IComment>
* @since 9.0.0
*/
@@ -339,7 +320,7 @@ class Manager implements ICommentsManager {
$objectId,
$limit = 0,
$offset = 0,
- ?\DateTime $notOlderThan = null
+ ?\DateTime $notOlderThan = null,
) {
$comments = [];
@@ -381,8 +362,9 @@ class Manager implements ICommentsManager {
* @param int $lastKnownCommentId the last known comment (will be used as offset)
* @param string $sortDirection direction of the comments (`asc` or `desc`)
* @param int $limit optional, number of maximum comments to be returned. if
- * set to 0, all comments are returned.
+ * set to 0, all comments are returned.
* @param bool $includeLastKnown
+ * @param string $topmostParentId Limit the comments to a list of replies and its original root comment
* @return list<IComment>
*/
public function getForObjectSince(
@@ -391,7 +373,8 @@ class Manager implements ICommentsManager {
int $lastKnownCommentId,
string $sortDirection = 'asc',
int $limit = 30,
- bool $includeLastKnown = false
+ bool $includeLastKnown = false,
+ string $topmostParentId = '',
): array {
return $this->getCommentsWithVerbForObjectSinceComment(
$objectType,
@@ -400,7 +383,8 @@ class Manager implements ICommentsManager {
$lastKnownCommentId,
$sortDirection,
$limit,
- $includeLastKnown
+ $includeLastKnown,
+ $topmostParentId,
);
}
@@ -411,8 +395,9 @@ class Manager implements ICommentsManager {
* @param int $lastKnownCommentId the last known comment (will be used as offset)
* @param string $sortDirection direction of the comments (`asc` or `desc`)
* @param int $limit optional, number of maximum comments to be returned. if
- * set to 0, all comments are returned.
+ * set to 0, all comments are returned.
* @param bool $includeLastKnown
+ * @param string $topmostParentId Limit the comments to a list of replies and its original root comment
* @return list<IComment>
*/
public function getCommentsWithVerbForObjectSinceComment(
@@ -422,7 +407,8 @@ class Manager implements ICommentsManager {
int $lastKnownCommentId,
string $sortDirection = 'asc',
int $limit = 30,
- bool $includeLastKnown = false
+ bool $includeLastKnown = false,
+ string $topmostParentId = '',
): array {
$comments = [];
@@ -442,6 +428,13 @@ class Manager implements ICommentsManager {
$query->andWhere($query->expr()->in('verb', $query->createNamedParameter($verbs, IQueryBuilder::PARAM_STR_ARRAY)));
}
+ if ($topmostParentId !== '') {
+ $query->andWhere($query->expr()->orX(
+ $query->expr()->eq('id', $query->createNamedParameter($topmostParentId)),
+ $query->expr()->eq('topmost_parent_id', $query->createNamedParameter($topmostParentId)),
+ ));
+ }
+
$lastKnownComment = $lastKnownCommentId > 0 ? $this->getLastKnownComment(
$objectType,
$objectId,
@@ -459,14 +452,14 @@ class Manager implements ICommentsManager {
$query->expr()->orX(
$query->expr()->lt(
'creation_timestamp',
- $query->createNamedParameter($lastKnownCommentDateTime, IQueryBuilder::PARAM_DATE),
- IQueryBuilder::PARAM_DATE
+ $query->createNamedParameter($lastKnownCommentDateTime, IQueryBuilder::PARAM_DATETIME_MUTABLE),
+ IQueryBuilder::PARAM_DATETIME_MUTABLE
),
$query->expr()->andX(
$query->expr()->eq(
'creation_timestamp',
- $query->createNamedParameter($lastKnownCommentDateTime, IQueryBuilder::PARAM_DATE),
- IQueryBuilder::PARAM_DATE
+ $query->createNamedParameter($lastKnownCommentDateTime, IQueryBuilder::PARAM_DATETIME_MUTABLE),
+ IQueryBuilder::PARAM_DATETIME_MUTABLE
),
$idComparison
)
@@ -482,14 +475,14 @@ class Manager implements ICommentsManager {
$query->expr()->orX(
$query->expr()->gt(
'creation_timestamp',
- $query->createNamedParameter($lastKnownCommentDateTime, IQueryBuilder::PARAM_DATE),
- IQueryBuilder::PARAM_DATE
+ $query->createNamedParameter($lastKnownCommentDateTime, IQueryBuilder::PARAM_DATETIME_MUTABLE),
+ IQueryBuilder::PARAM_DATETIME_MUTABLE
),
$query->expr()->andX(
$query->expr()->eq(
'creation_timestamp',
- $query->createNamedParameter($lastKnownCommentDateTime, IQueryBuilder::PARAM_DATE),
- IQueryBuilder::PARAM_DATE
+ $query->createNamedParameter($lastKnownCommentDateTime, IQueryBuilder::PARAM_DATETIME_MUTABLE),
+ IQueryBuilder::PARAM_DATETIME_MUTABLE
),
$idComparison
)
@@ -594,7 +587,7 @@ class Manager implements ICommentsManager {
if ($search !== '') {
$query->where($query->expr()->iLike('message', $query->createNamedParameter(
- '%' . $this->dbConn->escapeLikeParameter($search). '%'
+ '%' . $this->dbConn->escapeLikeParameter($search) . '%'
)));
}
@@ -627,7 +620,7 @@ class Manager implements ICommentsManager {
* @param $objectType string the object type, e.g. 'files'
* @param $objectId string the id of the object
* @param \DateTime $notOlderThan optional, timestamp of the oldest comments
- * that may be returned
+ * that may be returned
* @param string $verb Limit the verb of the comment - Added in 14.0.0
* @return Int
* @since 9.0.0
@@ -694,7 +687,7 @@ class Manager implements ICommentsManager {
$result = $query->executeQuery();
while ($row = $result->fetch()) {
- $unreadComments[$row['object_id']] = (int) $row['num_comments'];
+ $unreadComments[$row['object_id']] = (int)$row['num_comments'];
}
$result->closeCursor();
}
@@ -742,7 +735,7 @@ class Manager implements ICommentsManager {
$data = $result->fetch();
$result->closeCursor();
- return (int) ($data['num_messages'] ?? 0);
+ return (int)($data['num_messages'] ?? 0);
}
/**
@@ -759,7 +752,7 @@ class Manager implements ICommentsManager {
->from('comments')
->where($query->expr()->eq('object_type', $query->createNamedParameter($objectType)))
->andWhere($query->expr()->eq('object_id', $query->createNamedParameter($objectId)))
- ->andWhere($query->expr()->lt('creation_timestamp', $query->createNamedParameter($beforeDate, IQueryBuilder::PARAM_DATE)))
+ ->andWhere($query->expr()->lt('creation_timestamp', $query->createNamedParameter($beforeDate, IQueryBuilder::PARAM_DATETIME_MUTABLE)))
->orderBy('creation_timestamp', 'desc');
if ($verb !== '') {
@@ -770,7 +763,7 @@ class Manager implements ICommentsManager {
$data = $result->fetch();
$result->closeCursor();
- return (int) ($data['id'] ?? 0);
+ return (int)($data['id'] ?? 0);
}
/**
@@ -788,7 +781,7 @@ class Manager implements ICommentsManager {
string $objectId,
string $verb,
string $actorType,
- array $actors
+ array $actors,
): array {
$lastComments = [];
@@ -827,9 +820,9 @@ class Manager implements ICommentsManager {
return [];
}
$children = $directory->getDirectoryListing();
- $ids = array_map(fn (FileInfo $child) => (string) $child->getId(), $children);
+ $ids = array_map(fn (FileInfo $child) => (string)$child->getId(), $children);
- $ids[] = (string) $directory->getId();
+ $ids[] = (string)$directory->getId();
$counts = $this->getNumberOfUnreadCommentsForObjects('files', $ids, $user);
return array_filter($counts, function (int $count) {
return $count > 0;
@@ -1098,7 +1091,7 @@ class Manager implements ICommentsManager {
$result = $this->update($comment);
}
- if ($result && !!$comment->getParentId()) {
+ if ($result && (bool)$comment->getParentId()) {
$this->updateChildrenInformation(
$comment->getParentId(),
$comment->getCreationDateTime()
@@ -1160,7 +1153,7 @@ class Manager implements ICommentsManager {
->andWhere($qb->expr()->eq('actor_id', $qb->createNamedParameter($reaction->getActorId())))
->andWhere($qb->expr()->eq('reaction', $qb->createNamedParameter($reaction->getMessage())));
$result = $qb->executeQuery();
- $exists = (int) $result->fetchOne();
+ $exists = (int)$result->fetchOne();
if (!$exists) {
$qb = $this->dbConn->getQueryBuilder();
try {
@@ -1550,6 +1543,7 @@ class Manager implements ICommentsManager {
foreach ($entities as $entity) {
$entity->handle($event);
}
+ $this->eventDispatcher->dispatchTyped($event);
}
/**
@@ -1569,7 +1563,7 @@ class Manager implements ICommentsManager {
$qb = $this->dbConn->getQueryBuilder();
$qb->delete('comments')
->where($qb->expr()->lte('expire_date',
- $qb->createNamedParameter($this->timeFactory->getDateTime(), IQueryBuilder::PARAM_DATE)))
+ $qb->createNamedParameter($this->timeFactory->getDateTime(), IQueryBuilder::PARAM_DATETIME_MUTABLE)))
->andWhere($qb->expr()->eq('object_type', $qb->createNamedParameter($objectType)));
if ($objectId !== '') {
diff --git a/lib/private/Comments/ManagerFactory.php b/lib/private/Comments/ManagerFactory.php
index 2b59a284b61..2436ca74c66 100644
--- a/lib/private/Comments/ManagerFactory.php
+++ b/lib/private/Comments/ManagerFactory.php
@@ -1,27 +1,9 @@
<?php
+
/**
- * @copyright Copyright (c) 2016, ownCloud, Inc.
- *
- * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
- * @author Joas Schilling <coding@schilljs.com>
- * @author Roeland Jago Douma <roeland@famdouma.nl>
- * @author Thomas Müller <thomas.mueller@tmit.eu>
- * @author Vincent Petry <vincent@nextcloud.com>
- *
- * @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,
- * along with this program. If not, see <http://www.gnu.org/licenses/>
- *
+ * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
+ * SPDX-License-Identifier: AGPL-3.0-only
*/
namespace OC\Comments;