aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan-Hendrik Willms <tleilax+studip@gmail.com>2022-12-07 10:56:30 +0000
committerJan-Hendrik Willms <tleilax+studip@gmail.com>2022-12-07 10:56:30 +0000
commite160ba5fbe83c3a52f9b2f3619b84f4fc3daa9a9 (patch)
tree7e87be83f797c5f7c5a2c3c9b7426c91b95dedd8
parent3d8cb20aef2c55cadd38dccc3f51128d7e357ecf (diff)
migrate from storing last visit dates of blubber threads in config_values to...
Closes #744 Merge request studip/studip!1219
-rw-r--r--app/routes/Blubber.php19
-rw-r--r--db/migrations/5.1.37_migrate_blubber_user_config_to_object_user_visits.php66
-rw-r--r--lib/classes/sidebar/BlubberThreadsWidget.php22
-rw-r--r--lib/models/BlubberThread.php55
-rw-r--r--lib/models/ObjectUserVisit.php28
-rw-r--r--lib/modules/Blubber.class.php12
6 files changed, 172 insertions, 30 deletions
diff --git a/app/routes/Blubber.php b/app/routes/Blubber.php
index a30feb9..4fb6ab9 100644
--- a/app/routes/Blubber.php
+++ b/app/routes/Blubber.php
@@ -18,7 +18,7 @@ class Blubber extends \RESTAPI\RouteMap
*
* @get /blubber/threads/:thread_id
* @param string $thread_id id of the blubber thread or "global" if you want public threads (not comments). Remind the global thread is a virtual thread with a special behaviour.
- * @return Array the blubber as array
+ * @return array the blubber as array
*/
public function getThreadData($thread_id)
{
@@ -31,7 +31,6 @@ class Blubber extends \RESTAPI\RouteMap
$thread = \BlubberThread::upgradeThread($thread);
if (!$thread->isReadable()) {
$this->error(401);
- return;
}
$json = $thread->getJSONData(50, null, \Request::get("search"));
@@ -46,7 +45,7 @@ class Blubber extends \RESTAPI\RouteMap
* Get threads
*
* @get /blubber/threads
- * @return Array the stream as array
+ * @return array the stream as array
*/
public function getMyThreads()
{
@@ -83,7 +82,7 @@ class Blubber extends \RESTAPI\RouteMap
*
* @post /blubber/threads/:thread_id/comments
* @param string $thread_id id of the blubber thread
- * @return Array the comment as array
+ * @return array the comment as array
*/
public function postComment($thread_id)
{
@@ -93,13 +92,11 @@ class Blubber extends \RESTAPI\RouteMap
if (!trim($this->data['content'])) {
$this->error(406);
- return false;
}
$thread = \BlubberThread::find($thread_id);
if (!$thread->isCommentable()) {
$this->error(401);
- return;
}
$comment = new \BlubberComment();
@@ -109,7 +106,7 @@ class Blubber extends \RESTAPI\RouteMap
$comment['external_contact'] = 0;
$comment->store();
- $GLOBALS['user']->cfg->store("BLUBBERTHREAD_VISITED_".$thread_id, time());
+ $thread->setLastVisit();
return $comment->getJSONData();
}
@@ -122,14 +119,13 @@ class Blubber extends \RESTAPI\RouteMap
* @param string $thread_id id of the blubber thread
* @param string $comment id of the comment
*
- * @return Array the comment as array
+ * @return array the comment as array
*/
public function editComment($thread_id, $comment_id)
{
$comment = \BlubberComment::find($comment_id);
if (!$comment->isWritable()) {
$this->error(401);
- return;
}
$old_content = $comment['content'];
$comment['content'] = $this->data['content'];
@@ -176,7 +172,7 @@ class Blubber extends \RESTAPI\RouteMap
*
* @param string $thread_id id of the blubber thread
*
- * @return Array the comments as array
+ * @return array the comments as array
*/
public function getComments($thread_id)
{
@@ -187,7 +183,6 @@ class Blubber extends \RESTAPI\RouteMap
$thread = new \BlubberThread($thread_id);
if (!$thread->isReadable()) {
$this->error(401);
- return;
}
$modifier = \Request::get('modifier');
@@ -228,7 +223,7 @@ class Blubber extends \RESTAPI\RouteMap
FROM blubber_comments
WHERE blubber_comments.thread_id = :thread_id
AND blubber_comments.mkdate >= :timestamp
- ORDER BY mkdate ASC
+ ORDER BY mkdate
LIMIT :limit";
$comments = \DBManager::get()->fetchAll($query, [
'thread_id' => $thread_id,
diff --git a/db/migrations/5.1.37_migrate_blubber_user_config_to_object_user_visits.php b/db/migrations/5.1.37_migrate_blubber_user_config_to_object_user_visits.php
new file mode 100644
index 0000000..69e7ea6
--- /dev/null
+++ b/db/migrations/5.1.37_migrate_blubber_user_config_to_object_user_visits.php
@@ -0,0 +1,66 @@
+<?php
+final class MigrateBlubberUserConfigToObjectUserVisits extends Migration
+{
+ public function description()
+ {
+ return 'Migrates the blubber visited entrires from config_values to user_entries';
+ }
+
+ protected function up()
+ {
+ $query = "SELECT `pluginid`
+ FROM `plugins`
+ WHERE `pluginclassname` = 'Blubber'";
+ $blubber_plugin_id = DBManager::get()->fetchColumn($query);
+
+ $query = "INSERT INTO `object_user_visits` (
+ `object_id`,
+ `user_id`,
+ `plugin_id`,
+ `visitdate`,
+ `last_visitdate`
+ )
+ SELECT SUBSTR(`field`, 23) AS `object_id`,
+ `range_id` AS `user_id`,
+ ? AS `plugin_id`,
+ `value` AS `visitdate`,
+ `value` AS `last_visitdate`
+ FROM `config_values`
+ WHERE `field` LIKE 'BLUBBERTHREAD\\_VISITED\\_%'";
+ DBManager::get()->execute($query, [$blubber_plugin_id]);
+
+ $query = "DELETE FROM `config_values`
+ WHERE `field` LIKE 'BLUBBERTHREAD\\_VISITED\\_%'";
+ DBManager::get()->exec($query);
+ }
+
+ protected function down()
+ {
+ $query = "SELECT `pluginid`
+ FROM `plugins`
+ WHERE `pluginclassname` = 'Blubber'";
+ $blubber_plugin_id = DBManager::get()->fetchColumn($query);
+
+ $query = "INSERT INTO `config_values` (
+ `field`,
+ `range_id`,
+ `value`,
+ `mkdate`,
+ `chdate`,
+ `comment`
+ )
+ SELECT CONCAT('BLUBBERTHREAD_VISITED_', `object_id`) AS `field`,
+ `user_id` AS `range_id`,
+ `visitdate` AS `value`,
+ UNIX_TIMESTAMP() AS `mkdate`,
+ UNIX_TIMESTAMP() AS `chdate`,
+ '' AS `comment`
+ FROM `object_user_visits`
+ WHERE `plugin_id` = ?";
+ DBManager::get()->execute($query, [$blubber_plugin_id]);
+
+ $query = "DELETE FROM `object_user_visits`
+ WHERE `plugin_id` = ?";
+ DBManager::get()->execute($query, [$blubber_plugin_id]);
+ }
+}
diff --git a/lib/classes/sidebar/BlubberThreadsWidget.php b/lib/classes/sidebar/BlubberThreadsWidget.php
index b02e027..db80023 100644
--- a/lib/classes/sidebar/BlubberThreadsWidget.php
+++ b/lib/classes/sidebar/BlubberThreadsWidget.php
@@ -1,10 +1,16 @@
<?php
+/**
+ * @property BlubberThread[] $elements
+ */
class BlubberThreadsWidget extends SidebarWidget
{
protected $active_thread = null;
protected $with_composer = false;
+ /**
+ * @param BlubberThread $thread
+ */
public function addThread($thread)
{
$this->elements[] = $thread;
@@ -32,18 +38,18 @@ class BlubberThreadsWidget extends SidebarWidget
foreach ($this->elements as $thread) {
$unseen_comments = BlubberComment::countBySQL("thread_id = ? AND mkdate >= ?", [
$thread->getId(),
- $thread->getLastVisit() ?: object_get_visit_threshold()
+ $thread->getLastVisit()
]);
$json[] = [
- 'thread_id' => $thread->getId(),
- 'avatar' => $thread->getAvatar(),
- 'name' => $thread->getName(),
- 'timestamp' => (int) $thread->getLatestActivity(),
- 'mkdate' => (int) $thread->mkdate,
+ 'thread_id' => $thread->getId(),
+ 'avatar' => $thread->getAvatar(),
+ 'name' => $thread->getName(),
+ 'timestamp' => (int) $thread->getLatestActivity(),
+ 'mkdate' => (int) $thread->mkdate,
'unseen_comments' => $unseen_comments,
- 'notifications' => $thread->id === 'global' || ($thread->context_type === 'course' && !$GLOBALS['perm']->have_perm('admin')),
- 'followed' => $thread->isFollowedByUser(),
+ 'notifications' => $thread->id === 'global' || ($thread->context_type === 'course' && !$GLOBALS['perm']->have_perm('admin')),
+ 'followed' => $thread->isFollowedByUser(),
];
}
diff --git a/lib/models/BlubberThread.php b/lib/models/BlubberThread.php
index 0048c21..d0f2f89 100644
--- a/lib/models/BlubberThread.php
+++ b/lib/models/BlubberThread.php
@@ -41,14 +41,17 @@ class BlubberThread extends SimpleORMap implements PrivacyObject
'foreign_key' => 'user_id',
'assoc_foreign_key' => 'user_id',
];
+ $config['has_many']['visits'] = [
+ 'class_name' => ObjectUserVisit::class,
+ 'assoc_foreign_key' => 'object_id',
+ 'on_delete' => 'delete',
+ ];
$config['serialized_fields']['metadata'] = 'JSONArrayObject';
parent::configure($config);
}
- protected $last_visit = null;
-
/**
* Recognizes mentions in blubber as @username or @"Firstname lastname"
* and turns them into usual studip-links. The mentioned person is notified by
@@ -95,6 +98,9 @@ class BlubberThread extends SimpleORMap implements PrivacyObject
return $matches[0];
}
+ /**
+ * @return BlubberThread[]
+ */
public static function findBySQL($sql, $params = [])
{
return parent::findAndMapBySQL(function ($thread) {
@@ -102,6 +108,9 @@ class BlubberThread extends SimpleORMap implements PrivacyObject
}, $sql, $params);
}
+ /**
+ * @return BlubberThread|null
+ */
public static function find($id)
{
return self::upgradeThread(parent::find($id));
@@ -598,7 +607,39 @@ class BlubberThread extends SimpleORMap implements PrivacyObject
*/
public function getLastVisit(string $user_id = null)
{
- return UserConfig::get($user_id ?? $GLOBALS['user']->id)->getValue("BLUBBERTHREAD_VISITED_".$this->getId());
+ return object_get_visit(
+ $this->id,
+ $this->getBlubberPluginId(),
+ '',
+ '',
+ $user_id ?? User::findCurrent()->id
+ );
+ }
+
+ /**
+ * Sets the last visit timestamp for this thread
+ *
+ * @param string|null $user_id
+ */
+ public function setLastVisit(string $user_id = null): void
+ {
+ object_set_visit(
+ $this->id,
+ $this->getBlubberPluginId(),
+ $user_id ?? User::findCurrent()->id
+ );
+ }
+
+ /**
+ * Returns the id of the blubber plugin.
+ *
+ * @return int Id of the plugin
+ */
+ protected function getBlubberPluginId(): int
+ {
+ $plugin_info = PluginManager::getInstance()->getPluginInfo(Blubber::class);
+ return (int) $plugin_info['id'];
+
}
public function notifyUsersForNewComment($comment)
@@ -843,7 +884,7 @@ class BlubberThread extends SimpleORMap implements PrivacyObject
'more_down' => 0,
'unseen_comments' => BlubberComment::countBySQL("thread_id = ? AND mkdate >= ? AND user_id != ?", [
$this->getId(),
- $this->getLastVisit() ?: object_get_visit_threshold(),
+ $this->getLastVisit(),
$user_id
]),
'notifications' => $this->mayDisableNotifications(),
@@ -919,10 +960,8 @@ class BlubberThread extends SimpleORMap implements PrivacyObject
'user_id' => $user_id,
'html_id' => "blubberthread_".$this->getId()
]);
- $this->last_visit[$user_id] = empty($this->last_visit[$user_id])
- ? object_get_visit($this->getId(), "blubberthread", "last", "", $user_id)
- : $this->last_visit[$user_id];
- UserConfig::get($user_id)->store("BLUBBERTHREAD_VISITED_".$this->getId(), time());
+
+ $this->setLastVisit($user_id);
}
public function getHashtags($since = null)
diff --git a/lib/models/ObjectUserVisit.php b/lib/models/ObjectUserVisit.php
new file mode 100644
index 0000000..90a331e
--- /dev/null
+++ b/lib/models/ObjectUserVisit.php
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * @property array $id
+ * @property string $object_id
+ * @property string $user_id
+ * @property int $plugin_id
+ * @property int $visitdate
+ * @property int $last_visitdate
+ * @property User $user
+ */
+class ObjectUserVisit extends SimpleORMap
+{
+ protected static function configure($config = [])
+ {
+ $config['db_table'] = 'object_user_visits';
+
+ $config['belongs_to'] = [
+ 'user' => [
+ 'class_name' => User::class,
+ 'foreign_key' => 'user_id',
+ 'assoc_foreign_key' => 'user_id',
+ ]
+ ];
+
+ parent::configure($config);
+ }
+}
diff --git a/lib/modules/Blubber.class.php b/lib/modules/Blubber.class.php
index d9b5579..d2012b6 100644
--- a/lib/modules/Blubber.class.php
+++ b/lib/modules/Blubber.class.php
@@ -59,7 +59,11 @@ class Blubber extends CorePlugin implements StudipModule
'me' => $user_id,
]);
foreach ($comments as $comment) {
- if ($comment->thread->isVisibleInStream() && $comment->thread->isReadable() && ($comment->thread->getLatestActivity() > UserConfig::get($user_id)->getValue("BLUBBERTHREAD_VISITED_".$comment['thread_id']))) {
+ if (
+ $comment->thread->isVisibleInStream()
+ && $comment->thread->isReadable()
+ && $comment->thread->getLatestActivity() > $comment->thread->getLastVisit()
+ ) {
$icon->setImage(Icon::create('blubber', Icon::ROLE_NEW, ['title' => _('Es gibt neue Blubber')]));
$icon->setTitle(_('Es gibt neue Blubber'));
$icon->setBadgeNumber(count($comments));
@@ -83,7 +87,11 @@ class Blubber extends CorePlugin implements StudipModule
'me' => $GLOBALS['user']->id,
]);
foreach ($threads as $thread) {
- if ($thread->isVisibleInStream() && $thread->isReadable() && ($thread['mkdate'] > UserConfig::get($user_id)->getValue("BLUBBERTHREAD_VISITED_".$thread->getId()))) {
+ if (
+ $thread->isVisibleInStream()
+ && $thread->isReadable()
+ && $thread->mkdate > $thread->getLastVisit()
+ ) {
$icon->setImage(Icon::create('blubber', Icon::ROLE_ATTENTION, ['title' => _('Es gibt neue Blubber')]));
$icon->setTitle(_('Es gibt neue Blubber'));
break;