diff options
Diffstat (limited to 'apps')
37 files changed, 265 insertions, 67 deletions
diff --git a/apps/dav/lib/CalDAV/Activity/Setting/CalDAVSetting.php b/apps/dav/lib/CalDAV/Activity/Setting/CalDAVSetting.php index 1d3dd1df675..af036b7581b 100644 --- a/apps/dav/lib/CalDAV/Activity/Setting/CalDAVSetting.php +++ b/apps/dav/lib/CalDAV/Activity/Setting/CalDAVSetting.php @@ -1,9 +1,12 @@ <?php declare(strict_types=1); + /** * @copyright Copyright (c) 2020 Robin Appelman <robin@icewind.nl> * + * @author Robin Appelman <robin@icewind.nl> + * * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify @@ -17,7 +20,7 @@ declare(strict_types=1); * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. + * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ diff --git a/apps/dav/lib/CalDAV/Activity/Setting/Calendar.php b/apps/dav/lib/CalDAV/Activity/Setting/Calendar.php index 06cbe33946d..7a0fc4601fe 100644 --- a/apps/dav/lib/CalDAV/Activity/Setting/Calendar.php +++ b/apps/dav/lib/CalDAV/Activity/Setting/Calendar.php @@ -3,6 +3,7 @@ * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com> * * @author Joas Schilling <coding@schilljs.com> + * @author Robin Appelman <robin@icewind.nl> * * @license GNU AGPL version 3 or any later version * diff --git a/apps/dav/lib/CalDAV/Activity/Setting/Event.php b/apps/dav/lib/CalDAV/Activity/Setting/Event.php index d0c1676773c..aa43f6c17e6 100644 --- a/apps/dav/lib/CalDAV/Activity/Setting/Event.php +++ b/apps/dav/lib/CalDAV/Activity/Setting/Event.php @@ -3,6 +3,7 @@ * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com> * * @author Joas Schilling <coding@schilljs.com> + * @author Robin Appelman <robin@icewind.nl> * * @license GNU AGPL version 3 or any later version * diff --git a/apps/dav/lib/CalDAV/Activity/Setting/Todo.php b/apps/dav/lib/CalDAV/Activity/Setting/Todo.php index 5ebc4ec2404..1c441e4d182 100644 --- a/apps/dav/lib/CalDAV/Activity/Setting/Todo.php +++ b/apps/dav/lib/CalDAV/Activity/Setting/Todo.php @@ -3,6 +3,7 @@ * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com> * * @author Joas Schilling <coding@schilljs.com> + * @author Robin Appelman <robin@icewind.nl> * * @license GNU AGPL version 3 or any later version * diff --git a/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php b/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php index 56517ab28c1..e360273383e 100644 --- a/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php +++ b/apps/dav/lib/CalDAV/Schedule/IMipPlugin.php @@ -3,6 +3,7 @@ * @copyright Copyright (c) 2016, ownCloud, Inc. * @copyright Copyright (c) 2017, Georg Ehrke * + * @author brad2014 <brad2014@users.noreply.github.com> * @author Brad Rubenstein <brad@wbr.tech> * @author Christoph Wurst <christoph@winzerhof-wurst.at> * @author Georg Ehrke <oc.list@georgehrke.com> diff --git a/apps/dav/lib/CardDAV/ImageExportPlugin.php b/apps/dav/lib/CardDAV/ImageExportPlugin.php index fa4d5ea23f2..17e544a85bc 100644 --- a/apps/dav/lib/CardDAV/ImageExportPlugin.php +++ b/apps/dav/lib/CardDAV/ImageExportPlugin.php @@ -4,6 +4,7 @@ * * @author Christoph Wurst <christoph@winzerhof-wurst.at> * @author Georg Ehrke <oc.list@georgehrke.com> + * @author Jacob Neplokh <me@jacobneplokh.com> * @author Roeland Jago Douma <roeland@famdouma.nl> * * @license AGPL-3.0 diff --git a/apps/dav/lib/CardDAV/PhotoCache.php b/apps/dav/lib/CardDAV/PhotoCache.php index 6ea999444af..620a88dcfb8 100644 --- a/apps/dav/lib/CardDAV/PhotoCache.php +++ b/apps/dav/lib/CardDAV/PhotoCache.php @@ -5,6 +5,7 @@ * @author Arthur Schiwon <blizzz@arthur-schiwon.de> * @author Christoph Wurst <christoph@winzerhof-wurst.at> * @author Daniel Kesselberg <mail@danielkesselberg.de> + * @author Jacob Neplokh <me@jacobneplokh.com> * @author Joas Schilling <coding@schilljs.com> * @author John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com> * @author Morris Jobke <hey@morrisjobke.de> diff --git a/apps/dav/lib/Connector/Sabre/File.php b/apps/dav/lib/Connector/Sabre/File.php index 476824a2e36..ab6cd47ba5b 100644 --- a/apps/dav/lib/Connector/Sabre/File.php +++ b/apps/dav/lib/Connector/Sabre/File.php @@ -10,6 +10,7 @@ * @author Jan-Philipp Litza <jplitza@users.noreply.github.com> * @author Joas Schilling <coding@schilljs.com> * @author Jörn Friedrich Dreyer <jfd@butonic.de> + * @author Julius Härtl <jus@bitgrid.net> * @author Lukas Reschke <lukas@statuscode.ch> * @author Morris Jobke <hey@morrisjobke.de> * @author Owen Winkler <a_github@midnightcircus.com> diff --git a/apps/dav/tests/unit/CardDAV/ImageExportPluginTest.php b/apps/dav/tests/unit/CardDAV/ImageExportPluginTest.php index c116a5ff775..47606a45241 100644 --- a/apps/dav/tests/unit/CardDAV/ImageExportPluginTest.php +++ b/apps/dav/tests/unit/CardDAV/ImageExportPluginTest.php @@ -4,7 +4,7 @@ * * @author Christoph Wurst <christoph@winzerhof-wurst.at> * @author Georg Ehrke <oc.list@georgehrke.com> - * @author Lukas Reschke <lukas@statuscode.ch> + * @author Jacob Neplokh <me@jacobneplokh.com> * @author Morris Jobke <hey@morrisjobke.de> * @author Roeland Jago Douma <roeland@famdouma.nl> * diff --git a/apps/files/lib/Service/OwnershipTransferService.php b/apps/files/lib/Service/OwnershipTransferService.php index 9f3e530478d..a8a1b9bd1d6 100644 --- a/apps/files/lib/Service/OwnershipTransferService.php +++ b/apps/files/lib/Service/OwnershipTransferService.php @@ -7,6 +7,7 @@ declare(strict_types=1); * * @author Christoph Wurst <christoph@winzerhof-wurst.at> * @author Joas Schilling <coding@schilljs.com> + * @author Julius Härtl <jus@bitgrid.net> * @author Morris Jobke <hey@morrisjobke.de> * @author rawtaz <rawtaz@users.noreply.github.com> * @author Roeland Jago Douma <roeland@famdouma.nl> diff --git a/apps/files_sharing/lib/External/Manager.php b/apps/files_sharing/lib/External/Manager.php index 9513fa0ce6f..526e4fcce45 100644 --- a/apps/files_sharing/lib/External/Manager.php +++ b/apps/files_sharing/lib/External/Manager.php @@ -8,6 +8,7 @@ * @author Daniel Hansson <daniel@techandme.se> * @author Joas Schilling <coding@schilljs.com> * @author Jörn Friedrich Dreyer <jfd@butonic.de> + * @author Julius Härtl <jus@bitgrid.net> * @author Lukas Reschke <lukas@statuscode.ch> * @author Morris Jobke <hey@morrisjobke.de> * @author Robin Appelman <robin@icewind.nl> diff --git a/apps/files_sharing/lib/SharedStorage.php b/apps/files_sharing/lib/SharedStorage.php index a90d347593f..1735cab43f6 100644 --- a/apps/files_sharing/lib/SharedStorage.php +++ b/apps/files_sharing/lib/SharedStorage.php @@ -4,7 +4,6 @@ * * @author Bart Visscher <bartv@thisnet.nl> * @author Björn Schießle <bjoern@schiessle.org> - * @author Christoph Wurst <christoph@winzerhof-wurst.at> * @author Joas Schilling <coding@schilljs.com> * @author Michael Gapczynski <GapczynskiM@gmail.com> * @author Morris Jobke <hey@morrisjobke.de> diff --git a/apps/files_trashbin/lib/Trashbin.php b/apps/files_trashbin/lib/Trashbin.php index 6e7ef18b139..276cdf4e2d9 100644 --- a/apps/files_trashbin/lib/Trashbin.php +++ b/apps/files_trashbin/lib/Trashbin.php @@ -7,6 +7,7 @@ * @author Bjoern Schiessle <bjoern@schiessle.org> * @author Björn Schießle <bjoern@schiessle.org> * @author Christoph Wurst <christoph@winzerhof-wurst.at> + * @author Daniel Kesselberg <mail@danielkesselberg.de> * @author Florin Peter <github@florin-peter.de> * @author Georg Ehrke <oc.list@georgehrke.com> * @author Joas Schilling <coding@schilljs.com> diff --git a/apps/files_trashbin/tests/TrashbinTest.php b/apps/files_trashbin/tests/TrashbinTest.php index 4835cb925cf..f0c3a29b05c 100644 --- a/apps/files_trashbin/tests/TrashbinTest.php +++ b/apps/files_trashbin/tests/TrashbinTest.php @@ -4,6 +4,7 @@ * * @author Björn Schießle <bjoern@schiessle.org> * @author Christoph Wurst <christoph@winzerhof-wurst.at> + * @author Daniel Kesselberg <mail@danielkesselberg.de> * @author Joas Schilling <coding@schilljs.com> * @author John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com> * @author Morris Jobke <hey@morrisjobke.de> diff --git a/apps/settings/appinfo/routes.php b/apps/settings/appinfo/routes.php index c927c01f1f6..c1d3938a739 100644 --- a/apps/settings/appinfo/routes.php +++ b/apps/settings/appinfo/routes.php @@ -6,6 +6,7 @@ declare(strict_types=1); * @copyright Copyright (c) 2016, ownCloud, Inc. * * @author Bart Visscher <bartv@thisnet.nl> + * @author Jan C. Borchardt <hey@jancborchardt.net> * @author Julius Härtl <jus@bitgrid.net> * @author Lukas Reschke <lukas@statuscode.ch> * @author Morris Jobke <hey@morrisjobke.de> diff --git a/apps/settings/lib/Controller/ReasonsController.php b/apps/settings/lib/Controller/ReasonsController.php index ff3cb73719c..9c897314091 100644 --- a/apps/settings/lib/Controller/ReasonsController.php +++ b/apps/settings/lib/Controller/ReasonsController.php @@ -1,10 +1,11 @@ <?php declare(strict_types=1); + /** * @copyright Copyright (c) 2020, Roeland Jago Douma <roeland@famdouma.nl> * - * @author Roeland Jago Douma <roeland@famdouma.nl> + * @author Jan C. Borchardt <hey@jancborchardt.net> * * @license GNU AGPL version 3 or any later version * @@ -19,7 +20,7 @@ declare(strict_types=1); * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. + * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ diff --git a/apps/settings/lib/Settings/Personal/ServerDevNotice.php b/apps/settings/lib/Settings/Personal/ServerDevNotice.php index 58314691021..05f2c1342f4 100644 --- a/apps/settings/lib/Settings/Personal/ServerDevNotice.php +++ b/apps/settings/lib/Settings/Personal/ServerDevNotice.php @@ -2,6 +2,7 @@ /** * @copyright 2016, Roeland Jago Douma <roeland@famdouma.nl> * + * @author Jan C. Borchardt <hey@jancborchardt.net> * @author Julius Härtl <jus@bitgrid.net> * @author Roeland Jago Douma <roeland@famdouma.nl> * @@ -77,6 +78,9 @@ class ServerDevNotice implements ISettings { $hasInitialState = false; + // viewer is default enabled and this makes a zero-cost assertion for Psalm + assert(class_exists(LoadViewer::class)); + // If the Reasons to use Nextcloud.pdf file is here, let's init Viewer if ($userFolder->nodeExists('Reasons to use Nextcloud.pdf')) { $this->eventDispatcher->dispatch(LoadViewer::class, new LoadViewer()); diff --git a/apps/settings/tests/Controller/AdminSettingsControllerTest.php b/apps/settings/tests/Controller/AdminSettingsControllerTest.php index 21bd29de355..e59e353c5a5 100644 --- a/apps/settings/tests/Controller/AdminSettingsControllerTest.php +++ b/apps/settings/tests/Controller/AdminSettingsControllerTest.php @@ -4,7 +4,7 @@ * * @author Arthur Schiwon <blizzz@arthur-schiwon.de> * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * @author Julius Härtl <jus@bitgrid.net> + * @author Jan C. Borchardt <hey@jancborchardt.net> * @author Lukas Reschke <lukas@statuscode.ch> * @author Roeland Jago Douma <roeland@famdouma.nl> * diff --git a/apps/settings/tests/Mailer/NewUserMailHelperTest.php b/apps/settings/tests/Mailer/NewUserMailHelperTest.php index 8060b69da04..f6e071135ea 100644 --- a/apps/settings/tests/Mailer/NewUserMailHelperTest.php +++ b/apps/settings/tests/Mailer/NewUserMailHelperTest.php @@ -3,6 +3,7 @@ * @copyright Copyright (c) 2017 Lukas Reschke <lukas@statuscode.ch> * * @author Arthur Schiwon <blizzz@arthur-schiwon.de> + * @author Brad Rubenstein <brad@wbr.tech> * @author Christoph Wurst <christoph@winzerhof-wurst.at> * @author Jan-Christoph Borchardt <hey@jancborchardt.net> * @author Joas Schilling <coding@schilljs.com> diff --git a/apps/user_ldap/lib/Migration/RemoveRefreshTime.php b/apps/user_ldap/lib/Migration/RemoveRefreshTime.php index b4b4e2c2628..8c8fec2253b 100644 --- a/apps/user_ldap/lib/Migration/RemoveRefreshTime.php +++ b/apps/user_ldap/lib/Migration/RemoveRefreshTime.php @@ -1,6 +1,7 @@ <?php declare(strict_types=1); + /** * @copyright Copyright (c) 2020 Arthur Schiwon <blizzz@arthur-schiwon.de> * @@ -19,7 +20,7 @@ declare(strict_types=1); * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. + * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ diff --git a/apps/user_ldap/tests/User/UserTest.php b/apps/user_ldap/tests/User/UserTest.php index 6ad69b500e7..25a896aee04 100644 --- a/apps/user_ldap/tests/User/UserTest.php +++ b/apps/user_ldap/tests/User/UserTest.php @@ -9,7 +9,6 @@ * @author Morris Jobke <hey@morrisjobke.de> * @author Roeland Jago Douma <roeland@famdouma.nl> * @author Roger Szabo <roger.szabo@web.de> - * @author sidey79 <s.butzek@gmx.de> * @author Thomas Müller <thomas.mueller@tmit.eu> * * @license AGPL-3.0 diff --git a/apps/user_status/appinfo/info.xml b/apps/user_status/appinfo/info.xml index 46036812f35..26d8113a842 100644 --- a/apps/user_status/appinfo/info.xml +++ b/apps/user_status/appinfo/info.xml @@ -5,7 +5,7 @@ <name>User status</name> <summary>User status</summary> <description><![CDATA[User status]]></description> - <version>0.0.2</version> + <version>1.0.0</version> <licence>agpl</licence> <author mail="oc.list@georgehrke.com" >Georg Ehrke</author> <namespace>UserStatus</namespace> diff --git a/apps/user_status/composer/composer/autoload_classmap.php b/apps/user_status/composer/composer/autoload_classmap.php index 151d8348078..ba2ed1f1762 100644 --- a/apps/user_status/composer/composer/autoload_classmap.php +++ b/apps/user_status/composer/composer/autoload_classmap.php @@ -27,6 +27,7 @@ return array( 'OCA\\UserStatus\\Listener\\UserDeletedListener' => $baseDir . '/../lib/Listener/UserDeletedListener.php', 'OCA\\UserStatus\\Listener\\UserLiveStatusListener' => $baseDir . '/../lib/Listener/UserLiveStatusListener.php', 'OCA\\UserStatus\\Migration\\Version0001Date20200602134824' => $baseDir . '/../lib/Migration/Version0001Date20200602134824.php', + 'OCA\\UserStatus\\Migration\\Version0002Date20200902144824' => $baseDir . '/../lib/Migration/Version0002Date20200902144824.php', 'OCA\\UserStatus\\Service\\EmojiService' => $baseDir . '/../lib/Service/EmojiService.php', 'OCA\\UserStatus\\Service\\JSDataService' => $baseDir . '/../lib/Service/JSDataService.php', 'OCA\\UserStatus\\Service\\PredefinedStatusService' => $baseDir . '/../lib/Service/PredefinedStatusService.php', diff --git a/apps/user_status/composer/composer/autoload_static.php b/apps/user_status/composer/composer/autoload_static.php index bed8bc364bf..fd05c1c1627 100644 --- a/apps/user_status/composer/composer/autoload_static.php +++ b/apps/user_status/composer/composer/autoload_static.php @@ -42,6 +42,7 @@ class ComposerStaticInitUserStatus 'OCA\\UserStatus\\Listener\\UserDeletedListener' => __DIR__ . '/..' . '/../lib/Listener/UserDeletedListener.php', 'OCA\\UserStatus\\Listener\\UserLiveStatusListener' => __DIR__ . '/..' . '/../lib/Listener/UserLiveStatusListener.php', 'OCA\\UserStatus\\Migration\\Version0001Date20200602134824' => __DIR__ . '/..' . '/../lib/Migration/Version0001Date20200602134824.php', + 'OCA\\UserStatus\\Migration\\Version0002Date20200902144824' => __DIR__ . '/..' . '/../lib/Migration/Version0002Date20200902144824.php', 'OCA\\UserStatus\\Service\\EmojiService' => __DIR__ . '/..' . '/../lib/Service/EmojiService.php', 'OCA\\UserStatus\\Service\\JSDataService' => __DIR__ . '/..' . '/../lib/Service/JSDataService.php', 'OCA\\UserStatus\\Service\\PredefinedStatusService' => __DIR__ . '/..' . '/../lib/Service/PredefinedStatusService.php', diff --git a/apps/user_status/lib/BackgroundJob/ClearOldStatusesBackgroundJob.php b/apps/user_status/lib/BackgroundJob/ClearOldStatusesBackgroundJob.php index 40639048843..3077fbec099 100644 --- a/apps/user_status/lib/BackgroundJob/ClearOldStatusesBackgroundJob.php +++ b/apps/user_status/lib/BackgroundJob/ClearOldStatusesBackgroundJob.php @@ -26,6 +26,7 @@ declare(strict_types=1); namespace OCA\UserStatus\BackgroundJob; use OCA\UserStatus\Db\UserStatusMapper; +use OCA\UserStatus\Service\StatusService; use OCP\AppFramework\Utility\ITimeFactory; use OCP\BackgroundJob\TimedJob; @@ -58,6 +59,9 @@ class ClearOldStatusesBackgroundJob extends TimedJob { * @inheritDoc */ protected function run($argument) { - $this->mapper->clearOlderThan($this->time->getTime()); + $now = $this->time->getTime(); + + $this->mapper->clearMessagesOlderThan($now); + $this->mapper->clearStatusesOlderThan($now - StatusService::INVALIDATE_STATUS_THRESHOLD, $now); } } diff --git a/apps/user_status/lib/Connector/UserStatus.php b/apps/user_status/lib/Connector/UserStatus.php index acbdac2007b..d6b075dcd8e 100644 --- a/apps/user_status/lib/Connector/UserStatus.php +++ b/apps/user_status/lib/Connector/UserStatus.php @@ -56,8 +56,8 @@ class UserStatus implements IUserStatus { $this->message = $status->getCustomMessage(); $this->icon = $status->getCustomIcon(); - if ($status->getStatus() === 'invisible') { - $this->status = 'offline'; + if ($status->getStatus() === IUserStatus::INVISIBLE) { + $this->status = IUserStatus::OFFLINE; } if ($status->getClearAt() !== null) { $this->clearAt = DateTimeImmutable::createFromFormat('U', (string)$status->getClearAt()); diff --git a/apps/user_status/lib/Controller/HeartbeatController.php b/apps/user_status/lib/Controller/HeartbeatController.php index fb8259a2ad7..02a0fd082cf 100644 --- a/apps/user_status/lib/Controller/HeartbeatController.php +++ b/apps/user_status/lib/Controller/HeartbeatController.php @@ -33,6 +33,7 @@ use OCP\EventDispatcher\IEventDispatcher; use OCP\IRequest; use OCP\IUserSession; use OCP\User\Events\UserLiveStatusEvent; +use OCP\UserStatus\IUserStatus; class HeartbeatController extends Controller { @@ -51,6 +52,8 @@ class HeartbeatController extends Controller { * @param string $appName * @param IRequest $request * @param IEventDispatcher $eventDispatcher + * @param IUserSession $userSession + * @param ITimeFactory $timeFactory */ public function __construct(string $appName, IRequest $request, @@ -70,7 +73,7 @@ class HeartbeatController extends Controller { * @return JSONResponse */ public function heartbeat(string $status): JSONResponse { - if (!\in_array($status, ['online', 'away'])) { + if (!\in_array($status, [IUserStatus::ONLINE, IUserStatus::AWAY], true)) { return new JSONResponse([], Http::STATUS_BAD_REQUEST); } diff --git a/apps/user_status/lib/Controller/StatusesController.php b/apps/user_status/lib/Controller/StatusesController.php index b707708f46a..4295fb76949 100644 --- a/apps/user_status/lib/Controller/StatusesController.php +++ b/apps/user_status/lib/Controller/StatusesController.php @@ -32,6 +32,7 @@ use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCS\OCSNotFoundException; use OCP\AppFramework\OCSController; use OCP\IRequest; +use OCP\UserStatus\IUserStatus; class StatusesController extends OCSController { @@ -92,8 +93,8 @@ class StatusesController extends OCSController { */ private function formatStatus(UserStatus $status): array { $visibleStatus = $status->getStatus(); - if ($visibleStatus === 'invisible') { - $visibleStatus = 'offline'; + if ($visibleStatus === IUserStatus::INVISIBLE) { + $visibleStatus = IUserStatus::OFFLINE; } return [ diff --git a/apps/user_status/lib/Dashboard/UserStatusWidget.php b/apps/user_status/lib/Dashboard/UserStatusWidget.php index 809aa000005..6ccea95acdc 100644 --- a/apps/user_status/lib/Dashboard/UserStatusWidget.php +++ b/apps/user_status/lib/Dashboard/UserStatusWidget.php @@ -32,6 +32,7 @@ use OCP\IInitialStateService; use OCP\IL10N; use OCP\IUserManager; use OCP\IUserSession; +use OCP\UserStatus\IUserStatus; /** * Class UserStatusWidget @@ -146,7 +147,9 @@ class UserStatusWidget implements IWidget { return [ 'userId' => $status->getUserId(), 'displayName' => $displayName, - 'status' => $status->getStatus() === 'invisible' ? 'offline' : $status->getStatus(), + 'status' => $status->getStatus() === IUserStatus::INVISIBLE + ? IUserStatus::OFFLINE + : $status->getStatus(), 'icon' => $status->getCustomIcon(), 'message' => $status->getCustomMessage(), 'timestamp' => $status->getStatusTimestamp(), diff --git a/apps/user_status/lib/Db/UserStatusMapper.php b/apps/user_status/lib/Db/UserStatusMapper.php index 2bd6a5024d0..dc54789d343 100644 --- a/apps/user_status/lib/Db/UserStatusMapper.php +++ b/apps/user_status/lib/Db/UserStatusMapper.php @@ -28,6 +28,7 @@ namespace OCA\UserStatus\Db; use OCP\AppFramework\Db\QBMapper; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IDBConnection; +use OCP\UserStatus\IUserStatus; /** * Class UserStatusMapper @@ -81,7 +82,7 @@ class UserStatusMapper extends QBMapper { ->select('*') ->from($this->tableName) ->orderBy('status_timestamp', 'DESC') - ->where($qb->expr()->notIn('status', $qb->createNamedParameter(['online', 'away'], IQueryBuilder::PARAM_STR_ARRAY))) + ->where($qb->expr()->notIn('status', $qb->createNamedParameter([IUserStatus::ONLINE, IUserStatus::AWAY, IUserStatus::OFFLINE], IQueryBuilder::PARAM_STR_ARRAY))) ->orWhere($qb->expr()->isNotNull('message_id')) ->orWhere($qb->expr()->isNotNull('custom_icon')) ->orWhere($qb->expr()->isNotNull('custom_message')); @@ -126,11 +127,30 @@ class UserStatusMapper extends QBMapper { } /** + * @param int $olderThan + * @param int $now + */ + public function clearStatusesOlderThan(int $olderThan, int $now): void { + $qb = $this->db->getQueryBuilder(); + $qb->update($this->tableName) + ->set('status', $qb->createNamedParameter(IUserStatus::OFFLINE)) + ->set('is_user_defined', $qb->createNamedParameter(false, IQueryBuilder::PARAM_BOOL)) + ->set('status_timestamp', $qb->createNamedParameter($now, IQueryBuilder::PARAM_INT)) + ->where($qb->expr()->lte('status_timestamp', $qb->createNamedParameter($olderThan, IQueryBuilder::PARAM_INT))) + ->andWhere($qb->expr()->orX( + $qb->expr()->eq('is_user_defined', $qb->createNamedParameter(false, IQueryBuilder::PARAM_BOOL), IQueryBuilder::PARAM_BOOL), + $qb->expr()->eq('status', $qb->createNamedParameter(IUserStatus::ONLINE)) + )); + + $qb->execute(); + } + + /** * Clear all statuses older than a given timestamp * * @param int $timestamp */ - public function clearOlderThan(int $timestamp): void { + public function clearMessagesOlderThan(int $timestamp): void { $qb = $this->db->getQueryBuilder(); $qb->update($this->tableName) ->set('message_id', $qb->createNamedParameter(null)) diff --git a/apps/user_status/lib/Listener/UserLiveStatusListener.php b/apps/user_status/lib/Listener/UserLiveStatusListener.php index ce97841d9ad..967810367eb 100644 --- a/apps/user_status/lib/Listener/UserLiveStatusListener.php +++ b/apps/user_status/lib/Listener/UserLiveStatusListener.php @@ -27,11 +27,13 @@ namespace OCA\UserStatus\Listener; use OCA\UserStatus\Db\UserStatus; use OCA\UserStatus\Db\UserStatusMapper; +use OCA\UserStatus\Service\StatusService; use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Utility\ITimeFactory; use OCP\EventDispatcher\IEventListener; use OCP\EventDispatcher\Event; use OCP\User\Events\UserLiveStatusEvent; +use OCP\UserStatus\IUserStatus; /** * Class UserDeletedListener @@ -46,25 +48,6 @@ class UserLiveStatusListener implements IEventListener { /** @var ITimeFactory */ private $timeFactory; - /** @var string[] */ - private $priorityOrderedStatuses = [ - 'online', - 'away', - 'dnd', - 'invisible', - 'offline' - ]; - - /** @var string[] */ - private $persistentUserStatuses = [ - 'away', - 'dnd', - 'invisible', - ]; - - /** @var int */ - private $offlineThreshold = 300; - /** * UserLiveStatusListener constructor. * @@ -92,7 +75,7 @@ class UserLiveStatusListener implements IEventListener { } catch (DoesNotExistException $ex) { $userStatus = new UserStatus(); $userStatus->setUserId($user->getUID()); - $userStatus->setStatus('offline'); + $userStatus->setStatus(IUserStatus::OFFLINE); $userStatus->setStatusTimestamp(0); $userStatus->setIsUserDefined(false); } @@ -100,7 +83,7 @@ class UserLiveStatusListener implements IEventListener { // If the status is user-defined and one of the persistent statuses, we // will not override it. if ($userStatus->getIsUserDefined() && - \in_array($userStatus->getStatus(), $this->persistentUserStatuses, true)) { + \in_array($userStatus->getStatus(), StatusService::PERSISTENT_STATUSES, true)) { return; } @@ -108,13 +91,13 @@ class UserLiveStatusListener implements IEventListener { // If the current status is older than 5 minutes, // treat it as outdated and update - if ($userStatus->getStatusTimestamp() < ($this->timeFactory->getTime() - $this->offlineThreshold)) { + if ($userStatus->getStatusTimestamp() < ($this->timeFactory->getTime() - StatusService::INVALIDATE_STATUS_THRESHOLD)) { $needsUpdate = true; } // If the emitted status is more important than the current status // treat it as outdated and update - if (array_search($event->getStatus(), $this->priorityOrderedStatuses) < array_search($userStatus->getStatus(), $this->priorityOrderedStatuses)) { + if (array_search($event->getStatus(), StatusService::PRIORITY_ORDERED_STATUSES) < array_search($userStatus->getStatus(), StatusService::PRIORITY_ORDERED_STATUSES)) { $needsUpdate = true; } diff --git a/apps/user_status/lib/Migration/Version0002Date20200902144824.php b/apps/user_status/lib/Migration/Version0002Date20200902144824.php new file mode 100644 index 00000000000..abec418058f --- /dev/null +++ b/apps/user_status/lib/Migration/Version0002Date20200902144824.php @@ -0,0 +1,57 @@ +<?php + +declare(strict_types=1); + +/** + * @copyright Copyright (c) 2020, Georg Ehrke + * + * @author Georg Ehrke <oc.list@georgehrke.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/> + * + */ + +namespace OCA\UserStatus\Migration; + +use OCP\DB\ISchemaWrapper; +use OCP\Migration\IOutput; +use OCP\Migration\SimpleMigrationStep; + +/** + * Class Version0001Date20200602134824 + * + * @package OCA\UserStatus\Migration + */ +class Version0002Date20200902144824 extends SimpleMigrationStep { + + /** + * @param IOutput $output + * @param \Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` + * @param array $options + * @return null|ISchemaWrapper + * @since 20.0.0 + */ + public function changeSchema(IOutput $output, \Closure $schemaClosure, array $options) { + /** @var ISchemaWrapper $schema */ + $schema = $schemaClosure(); + + $statusTable = $schema->getTable('user_status'); + + $statusTable->addIndex(['status_timestamp'], 'user_status_tstmp_ix'); + $statusTable->addIndex(['is_user_defined', 'status'], 'user_status_iud_ix'); + + return $schema; + } +} diff --git a/apps/user_status/lib/Service/JSDataService.php b/apps/user_status/lib/Service/JSDataService.php index ebe801cd57a..ca78943fafe 100644 --- a/apps/user_status/lib/Service/JSDataService.php +++ b/apps/user_status/lib/Service/JSDataService.php @@ -27,6 +27,7 @@ namespace OCA\UserStatus\Service; use OCP\AppFramework\Db\DoesNotExistException; use OCP\IUserSession; +use OCP\UserStatus\IUserStatus; class JSDataService implements \JsonSerializable { @@ -65,7 +66,7 @@ class JSDataService implements \JsonSerializable { 'messageIsPredefined' => false, 'icon' => null, 'clearAt' => null, - 'status' => 'offline', + 'status' => IUserStatus::OFFLINE, 'statusIsUserDefined' => false, ]; } diff --git a/apps/user_status/lib/Service/StatusService.php b/apps/user_status/lib/Service/StatusService.php index e36d605cee4..85368342b25 100644 --- a/apps/user_status/lib/Service/StatusService.php +++ b/apps/user_status/lib/Service/StatusService.php @@ -34,6 +34,7 @@ use OCA\UserStatus\Exception\InvalidStatusTypeException; use OCA\UserStatus\Exception\StatusMessageTooLongException; use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Utility\ITimeFactory; +use OCP\UserStatus\IUserStatus; /** * Class StatusService @@ -54,17 +55,32 @@ class StatusService { /** @var EmojiService */ private $emojiService; - /** @var string[] */ - private $allowedStatusTypes = [ - 'online', - 'away', - 'dnd', - 'invisible', - 'offline' + /** + * List of priorities ordered by their priority + */ + public const PRIORITY_ORDERED_STATUSES = [ + IUserStatus::ONLINE, + IUserStatus::AWAY, + IUserStatus::DND, + IUserStatus::INVISIBLE, + IUserStatus::OFFLINE + ]; + + /** + * List of statuses that persist the clear-up + * or UserLiveStatusEvents + */ + public const PERSISTENT_STATUSES = [ + IUserStatus::AWAY, + IUserStatus::DND, + IUserStatus::INVISIBLE, ]; /** @var int */ - private $maximumMessageLength = 80; + public const INVALIDATE_STATUS_THRESHOLD = 5 /* minutes */ * 60 /* seconds */; + + /** @var int */ + public const MAXIMUM_MESSAGE_LENGTH = 80; /** * StatusService constructor. @@ -145,7 +161,7 @@ class StatusService { } // Check if status-type is valid - if (!\in_array($status, $this->allowedStatusTypes, true)) { + if (!\in_array($status, self::PRIORITY_ORDERED_STATUSES, true)) { throw new InvalidStatusTypeException('Status-type "' . $status . '" is not supported'); } if ($statusTimestamp === null) { @@ -179,7 +195,7 @@ class StatusService { } catch (DoesNotExistException $ex) { $userStatus = new UserStatus(); $userStatus->setUserId($userId); - $userStatus->setStatus('offline'); + $userStatus->setStatus(IUserStatus::OFFLINE); $userStatus->setStatusTimestamp(0); $userStatus->setIsUserDefined(false); } @@ -224,7 +240,7 @@ class StatusService { } catch (DoesNotExistException $ex) { $userStatus = new UserStatus(); $userStatus->setUserId($userId); - $userStatus->setStatus('offline'); + $userStatus->setStatus(IUserStatus::OFFLINE); $userStatus->setStatusTimestamp(0); $userStatus->setIsUserDefined(false); } @@ -234,8 +250,8 @@ class StatusService { throw new InvalidStatusIconException('Status-Icon is longer than one character'); } // Check for maximum length of custom message - if (\mb_strlen($message) > $this->maximumMessageLength) { - throw new StatusMessageTooLongException('Message is longer than supported length of ' . $this->maximumMessageLength . ' characters'); + if (\mb_strlen($message) > self::MAXIMUM_MESSAGE_LENGTH) { + throw new StatusMessageTooLongException('Message is longer than supported length of ' . self::MAXIMUM_MESSAGE_LENGTH . ' characters'); } // Check that clearAt is in the future if ($clearAt !== null && $clearAt < $this->timeFactory->getTime()) { @@ -266,7 +282,7 @@ class StatusService { return false; } - $userStatus->setStatus('offline'); + $userStatus->setStatus(IUserStatus::OFFLINE); $userStatus->setStatusTimestamp(0); $userStatus->setIsUserDefined(false); @@ -320,9 +336,14 @@ class StatusService { */ private function processStatus(UserStatus $status): UserStatus { $clearAt = $status->getClearAt(); - if ($clearAt !== null && $clearAt < $this->timeFactory->getTime()) { + + if ($status->getStatusTimestamp() < $this->timeFactory->getTime() - self::INVALIDATE_STATUS_THRESHOLD + && (!$status->getIsUserDefined() || $status->getStatus() === IUserStatus::ONLINE)) { $this->cleanStatus($status); } + if ($clearAt !== null && $clearAt < $this->timeFactory->getTime()) { + $this->cleanStatusMessage($status); + } if ($status->getMessageId() !== null) { $this->addDefaultMessage($status); } @@ -334,6 +355,17 @@ class StatusService { * @param UserStatus $status */ private function cleanStatus(UserStatus $status): void { + $status->setStatus(IUserStatus::OFFLINE); + $status->setStatusTimestamp($this->timeFactory->getTime()); + $status->setIsUserDefined(false); + + $this->mapper->update($status); + } + + /** + * @param UserStatus $status + */ + private function cleanStatusMessage(UserStatus $status): void { $status->setMessageId(null); $status->setCustomIcon(null); $status->setCustomMessage(null); diff --git a/apps/user_status/tests/Unit/BackgroundJob/ClearOldStatusesBackgroundJobTest.php b/apps/user_status/tests/Unit/BackgroundJob/ClearOldStatusesBackgroundJobTest.php index 6c5f15d47e9..ccb649ecce3 100644 --- a/apps/user_status/tests/Unit/BackgroundJob/ClearOldStatusesBackgroundJobTest.php +++ b/apps/user_status/tests/Unit/BackgroundJob/ClearOldStatusesBackgroundJobTest.php @@ -52,8 +52,11 @@ class ClearOldStatusesBackgroundJobTest extends TestCase { public function testRun() { $this->mapper->expects($this->once()) - ->method('clearOlderThan') + ->method('clearMessagesOlderThan') ->with(1337); + $this->mapper->expects($this->once()) + ->method('clearStatusesOlderThan') + ->with(1037, 1337); $this->time->method('getTime') ->willReturn(1337); diff --git a/apps/user_status/tests/Unit/Db/UserStatusMapperTest.php b/apps/user_status/tests/Unit/Db/UserStatusMapperTest.php index bf4c911c812..e86cee6d68a 100644 --- a/apps/user_status/tests/Unit/Db/UserStatusMapperTest.php +++ b/apps/user_status/tests/Unit/Db/UserStatusMapperTest.php @@ -70,8 +70,8 @@ class UserStatusMapperTest extends TestCase { $allResults = $this->mapper->findAllRecent(2, 0); $this->assertCount(2, $allResults); - $this->assertEquals('user1', $allResults[0]->getUserId()); - $this->assertEquals('user2', $allResults[1]->getUserId()); + $this->assertEquals('user2', $allResults[0]->getUserId()); + $this->assertEquals('user1', $allResults[1]->getUserId()); } public function testGetFind(): void { @@ -98,7 +98,7 @@ class UserStatusMapperTest extends TestCase { $user2Status = $this->mapper->findByUserId('user2'); $this->assertEquals('user2', $user2Status->getUserId()); $this->assertEquals('away', $user2Status->getStatus()); - $this->assertEquals(5000, $user2Status->getStatusTimestamp()); + $this->assertEquals(6000, $user2Status->getStatusTimestamp()); $this->assertEquals(false, $user2Status->getIsUserDefined()); $this->assertEquals('🏝', $user2Status->getCustomIcon()); $this->assertEquals('On vacation', $user2Status->getCustomMessage()); @@ -123,7 +123,7 @@ class UserStatusMapperTest extends TestCase { $user2Status = $statuses[1]; $this->assertEquals('user2', $user2Status->getUserId()); $this->assertEquals('away', $user2Status->getStatus()); - $this->assertEquals(5000, $user2Status->getStatusTimestamp()); + $this->assertEquals(6000, $user2Status->getStatusTimestamp()); $this->assertEquals(false, $user2Status->getIsUserDefined()); $this->assertEquals('🏝', $user2Status->getCustomIcon()); $this->assertEquals('On vacation', $user2Status->getCustomMessage()); @@ -152,10 +152,60 @@ class UserStatusMapperTest extends TestCase { $this->mapper->insert($userStatus2); } - public function testClearOlderThan(): void { + /** + * @param string $status + * @param bool $isUserDefined + * @param int $timestamp + * @param bool $expectsClean + * + * @dataProvider clearStatusesOlderThanDataProvider + */ + public function testClearStatusesOlderThan(string $status, bool $isUserDefined, int $timestamp, bool $expectsClean): void { + $oldStatus = UserStatus::fromParams([ + 'userId' => 'john.doe', + 'status' => $status, + 'isUserDefined' => $isUserDefined, + 'statusTimestamp' => $timestamp, + ]); + + $this->mapper->insert($oldStatus); + + $this->mapper->clearStatusesOlderThan(5000, 8000); + + $updatedStatus = $this->mapper->findAll()[0]; + + if ($expectsClean) { + $this->assertEquals('offline', $updatedStatus->getStatus()); + $this->assertFalse($updatedStatus->getIsUserDefined()); + $this->assertEquals(8000, $updatedStatus->getStatusTimestamp()); + } else { + $this->assertEquals($status, $updatedStatus->getStatus()); + $this->assertEquals($isUserDefined, $updatedStatus->getIsUserDefined()); + $this->assertEquals($timestamp, $updatedStatus->getStatusTimestamp()); + } + } + + public function clearStatusesOlderThanDataProvider(): array { + return [ + ['online', true, 6000, false], + ['online', true, 4000, true], + ['online', false, 6000, false], + ['online', false, 4000, true], + ['away', true, 6000, false], + ['away', true, 4000, false], + ['away', false, 6000, false], + ['away', false, 4000, true], + ['dnd', true, 6000, false], + ['dnd', true, 4000, false], + ['invisible', true, 6000, false], + ['invisible', true, 4000, false], + ]; + } + + public function testClearMessagesOlderThan(): void { $this->insertSampleStatuses(); - $this->mapper->clearOlderThan(55000); + $this->mapper->clearMessagesOlderThan(55000); $allStatuses = $this->mapper->findAll(); $this->assertCount(3, $allStatuses); @@ -189,7 +239,7 @@ class UserStatusMapperTest extends TestCase { $userStatus3 = new UserStatus(); $userStatus3->setUserId('user2'); $userStatus3->setStatus('away'); - $userStatus3->setStatusTimestamp(5000); + $userStatus3->setStatusTimestamp(6000); $userStatus3->setIsUserDefined(false); $userStatus3->setCustomIcon('🏝'); $userStatus3->setCustomMessage('On vacation'); diff --git a/apps/user_status/tests/Unit/Service/StatusServiceTest.php b/apps/user_status/tests/Unit/Service/StatusServiceTest.php index d9d0b84750f..4f47070e7c1 100644 --- a/apps/user_status/tests/Unit/Service/StatusServiceTest.php +++ b/apps/user_status/tests/Unit/Service/StatusServiceTest.php @@ -147,11 +147,30 @@ class StatusServiceTest extends TestCase { public function testFindAllClearStatus(): void { $status = new UserStatus(); + $status->setStatus('online'); + $status->setStatusTimestamp(1000); + $status->setIsUserDefined(true); + + $this->timeFactory->method('getTime') + ->willReturn(1400); + $this->mapper->expects($this->once()) + ->method('findByUserId') + ->with('john.doe') + ->willReturn($status); + + $this->assertEquals($status, $this->service->findByUserId('john.doe')); + $this->assertEquals('offline', $status->getStatus()); + $this->assertEquals(1400, $status->getStatusTimestamp()); + $this->assertFalse($status->getIsUserDefined()); + } + + public function testFindAllClearMessage(): void { + $status = new UserStatus(); $status->setClearAt(50); $status->setMessageId('commuting'); + $status->setStatusTimestamp(60); - $this->timeFactory->expects($this->once()) - ->method('getTime') + $this->timeFactory->method('getTime') ->willReturn(60); $this->predefinedStatusService->expects($this->never()) ->method('getDefaultStatusById'); |