aboutsummaryrefslogtreecommitdiff
path: root/app/controllers/activityfeed.php
diff options
context:
space:
mode:
authorPhilipp Schüttlöffel <schuettloeffel@zqs.uni-hannover.de>2024-09-24 10:53:31 +0200
committerPhilipp Schüttlöffel <schuettloeffel@zqs.uni-hannover.de>2024-09-24 10:53:31 +0200
commit4459dd7917f4d1c34f40bb68f0e991e9c3d53e4c (patch)
tree5c07151ae61276d334e88f6309c30d439a85c12e /app/controllers/activityfeed.php
parentda0022e5c1abbf9825ae76debaabdff7e8623bb4 (diff)
parent97a188592c679890a25c37ab78463add76a52ff7 (diff)
Merge branch 'main' into issue-3911issue-3911
Diffstat (limited to 'app/controllers/activityfeed.php')
-rw-r--r--app/controllers/activityfeed.php193
1 files changed, 191 insertions, 2 deletions
diff --git a/app/controllers/activityfeed.php b/app/controllers/activityfeed.php
index 2f93aa1..ee83826 100644
--- a/app/controllers/activityfeed.php
+++ b/app/controllers/activityfeed.php
@@ -53,7 +53,7 @@ class ActivityfeedController extends AuthenticatedController
unset($modules[Context::INSTITUTE]['participants']);
unset($modules[Context::INSTITUTE]['schedule']);
- $standard_plugins = PluginManager::getInstance()->getPlugins("StandardPlugin");
+ $standard_plugins = PluginManager::getInstance()->getPlugins(StandardPlugin::class);
foreach ($standard_plugins as $plugin) {
if ($plugin instanceof ActivityProvider) {
$modules[Context::COURSE][$plugin->getPluginName()] = $plugin->getPluginName();
@@ -67,7 +67,7 @@ class ActivityfeedController extends AuthenticatedController
'blubber' => _('Blubber'),
];
- $homepage_plugins = PluginEngine::getPlugins('HomepagePlugin');
+ $homepage_plugins = PluginEngine::getPlugins(HomepagePlugin::class);
foreach ($homepage_plugins as $plugin) {
if ($plugin->isActivated($GLOBALS['user']->id, 'user')) {
if ($plugin instanceof ActivityProvider) {
@@ -92,4 +92,193 @@ class ActivityfeedController extends AuthenticatedController
PageLayout::setTitle(_('Aktivitäten konfigurieren'));
}
+
+ public function load_action(): void
+ {
+ $user = User::findCurrent();
+
+ // failsafe einbauen - falls es keine älteren Aktivitäten mehr im System gibt, Abbruch!
+
+ $oldest_activity = \Studip\Activity\Activity::getOldestActivity();
+ $max_age = $oldest_activity ? $oldest_activity->mkdate : time();
+
+
+ $contexts = [];
+
+ // create system context
+ $system_context = new \Studip\Activity\SystemContext($user);
+ $contexts[] = $system_context;
+
+ $contexts[] = new \Studip\Activity\UserContext($user, $user);
+ $user->contacts->each(function ($another_user) use (&$contexts, $user) {
+ $contexts[] = new \Studip\Activity\UserContext($another_user, $user);
+ });
+
+ if (!in_array($user->perms, ['admin','root'])) {
+ // create courses and institutes context
+ foreach (\Course::findMany($user->course_memberships->pluck('seminar_id')) as $course) {
+ $contexts[] = new \Studip\Activity\CourseContext($course, $user);
+ }
+ foreach (\Institute::findMany($user->institute_memberships->pluck('institut_id')) as $institute) {
+ $contexts[] = new \Studip\Activity\InstituteContext($institute, $user);
+ }
+ }
+
+
+ // add filters
+ $filter = new \Studip\Activity\Filter();
+
+ $start = Request::int('start', strtotime('yesterday'));
+ $end = Request::int('end', time());
+
+
+ $scrollfrom = Request::int('scrollfrom', false);
+ $filtertype = Request::get('filtertype', '');
+
+ $objectType = Request::get('object_type');
+ $filter->setObjectType($objectType);
+
+ $objectId = Request::get('object_id');
+ $filter->setObjectId($objectId);
+
+ $context = Request::get('context_type');
+ $filter->setContext($context);
+
+ $contextId = Request::get('context_id');
+ $filter->setContextId($contextId);
+
+ if (!empty($filtertype)) {
+ $filter->setType(json_decode($filtertype));
+ }
+
+ if ($scrollfrom) {
+ // shorten "watch-window" by one second to prevent duplication of activities
+ $scrollfrom -= 1;
+
+ if ($scrollfrom > $max_age){
+ $end = $scrollfrom;
+ $start = strtotime('yesterday', $end);
+ $data = [];
+
+ $backtrack = 1;
+
+ while (empty($data)) {
+ $filter->setStartDate($start);
+ $filter->setEndDate($end);
+
+ $data = $this->getStreamData($contexts, $filter);
+
+ if ($start < $max_age) {
+ break;
+ }
+
+ // move "watch-window" back one day at a time
+ $end = $start - 1;
+ $start = strtotime("-{$backtrack} days", $start);
+
+ // enforce maximum "watch-window", currently 2 weeks
+ $backtrack = min(14, $backtrack + 1);
+ }
+ } else {
+ $data = false;
+ }
+ } else {
+ $filter->setStartDate($start);
+ $filter->setEndDate($end);
+ $data = $this->getStreamData($contexts, $filter);
+ }
+
+ // set etag for preventing resending the same stuff over and over again
+ $etag = md5(serialize($data));
+ $this->response->add_header('ETag', '"' . $etag . '"');
+ if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && $this->etagMatches($etag, $_SERVER['HTTP_IF_NONE_MATCH'])) {
+ $this->set_status(304);
+ $this->render_nothing();
+ return;
+ }
+ if (isset($_SERVER['HTTP_IF_MATCH']) && !$this->etagMatches($etag, $_SERVER['HTTP_IF_MATCH'])) {
+ $this->set_status(412);
+ $this->render_nothing();
+ return;
+ }
+
+ $this->render_json($data);
+ }
+
+ /**
+ * private helper function to get stream data for given contexts and filter
+ *
+ * @param $contexts
+ * @param $filter
+ * @return array
+ */
+
+ private function getStreamData($contexts, $filter): array
+ {
+ $stream = new Studip\Activity\Stream($contexts, $filter);
+ $data = $stream->toArray();
+
+ foreach ($data as $key => $act) {
+ $actor = [
+ 'type' => $act['actor_type'],
+ 'id' => $act['actor_id'],
+ ];
+
+ if ($act['actor_type'] == 'user') {
+ $a_user = \User::findFull($act['actor_id']);
+ $actor['details'] = $this->getMiniUser($a_user ?: new \User());
+ } elseif ($act['actor_type'] === 'anonymous') {
+ $actor['details'] = [
+ 'name' => _('Anonym'),
+ ];
+ }
+
+ unset($data[$key]['actor_type']);
+ unset($data[$key]['actor_id']);
+
+ $data[$key]['actor'] = $actor;
+ }
+
+ return $data;
+ }
+
+ private function getMiniUser(User $user): array
+ {
+ $avatar = \Avatar::getAvatar($user->id);
+
+ return [
+ 'id' => $user->id,
+ 'name' => $this->getNamesOfUser($user),
+ 'avatar_small' => $avatar->getURL(\Avatar::SMALL),
+ 'avatar_medium' => $avatar->getURL(\Avatar::MEDIUM),
+ 'avatar_normal' => $avatar->getURL(\Avatar::NORMAL),
+ 'avatar_original' => $avatar->getURL(\Avatar::NORMAL)
+ ];
+ }
+
+ private function getNamesOfUser(User $user): array
+ {
+ return [
+ 'username' => $user->username,
+ 'formatted' => $user->getFullName(),
+ 'family' => $user->nachname,
+ 'given' => $user->vorname,
+ 'prefix' => $user->title_front,
+ 'suffix' => $user->title_rear,
+ ];
+ }
+
+ // Helper method checking if a ETag value list includes the current ETag.
+ private function etagMatches(string $etag, string $list)
+ {
+ if ($list === '*') {
+ return true;
+ }
+
+ return in_array(
+ $etag,
+ preg_split('/\s*,\s*/', $list)
+ );
+ }
+
}