aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMurtaza Sultani <sultani@data-quest.de>2026-01-21 13:23:09 +0100
committerMurtaza Sultani <sultani@data-quest.de>2026-03-19 17:36:04 +0100
commit3de4660db08a48fedce6de7b6bf74319e9a92a6c (patch)
tree6d4d03e35db09824492f22b98451341a6e92bba2
parent54bcb72a352073c52a8cb58fcc8bf970d67884c0 (diff)
Add JSON API routes
-rw-r--r--app/controllers/admin/lti/AdminBaseController.php6
-rw-r--r--app/controllers/course/lti.php2
-rw-r--r--lib/classes/JsonApi/RouteMap.php2
-rw-r--r--lib/classes/JsonApi/Routes/Lti/PublicationIndex.php65
-rw-r--r--lib/classes/JsonApi/Routes/Lti/RegistrationIndex.php2
-rw-r--r--lib/classes/JsonApi/Routes/Lti/RegistrationShow.php2
-rw-r--r--lib/classes/JsonApi/Routes/Lti/ResourceIndex.php65
-rw-r--r--lib/classes/JsonApi/SchemaMap.php4
-rw-r--r--lib/classes/JsonApi/Schemas/Lti/Deployment.php64
-rw-r--r--lib/classes/JsonApi/Schemas/Lti/Publication.php95
-rw-r--r--lib/classes/JsonApi/Schemas/Lti/PublicationMember.php75
-rw-r--r--lib/classes/JsonApi/Schemas/Lti/Registration.php8
-rw-r--r--lib/classes/JsonApi/Schemas/Lti/Resource.php101
-rw-r--r--lib/models/Lti/ResourceLink.php9
-rw-r--r--lib/modules/LtiToolModule.php15
-rw-r--r--resources/vue/apps/lti/resources/Index.vue3
-rw-r--r--resources/vue/apps/responsive/ResponsiveNavigation.vue2
17 files changed, 499 insertions, 21 deletions
diff --git a/app/controllers/admin/lti/AdminBaseController.php b/app/controllers/admin/lti/AdminBaseController.php
index c11896e..543176e 100644
--- a/app/controllers/admin/lti/AdminBaseController.php
+++ b/app/controllers/admin/lti/AdminBaseController.php
@@ -3,19 +3,17 @@ namespace LTI;
use AccessDeniedException;
use AuthenticatedController;
-use Config;
use Context;
use Icon;
use LtiToolModule;
use Sidebar;
use ActionsWidget;
-use User;
use ViewsWidget;
abstract class AdminBaseController extends AuthenticatedController
{
- protected $range_id = null;
- protected $isToolSharingEnabled = false;
+ protected ?string $range_id = null;
+ protected bool $isToolSharingEnabled = false;
public function before_filter(&$action, &$args)
{
diff --git a/app/controllers/course/lti.php b/app/controllers/course/lti.php
index 07181b1..d2ddd93 100644
--- a/app/controllers/course/lti.php
+++ b/app/controllers/course/lti.php
@@ -77,7 +77,7 @@ class Course_LtiController extends StudipController
/**
* Display the list of LTI content blocks.
*/
- public function index_action()
+ public function index_action(): void
{
Helpbar::get()->addPlainText('', _('Auf dieser Seite können Sie externe Anwendungen einbinden, sofern diese den LTI-Standard (Version 1.x order 1.3a) unterstützen.'));
diff --git a/lib/classes/JsonApi/RouteMap.php b/lib/classes/JsonApi/RouteMap.php
index 6656452..2e320cb 100644
--- a/lib/classes/JsonApi/RouteMap.php
+++ b/lib/classes/JsonApi/RouteMap.php
@@ -318,6 +318,8 @@ class RouteMap
$group->group('/courses/{range_id}', function ($lti) {
$lti->get('/lti-configs', Routes\Lti\ConfigIndex::class);
$lti->get('/lti-registrations', Routes\Lti\RegistrationIndex::class);
+ $lti->get('/lti-resources', Routes\Lti\ResourceIndex::class);
+ $lti->get('/lti-publications', Routes\Lti\PublicationIndex::class);
});
$group->get('/lti-registrations', Routes\Lti\RegistrationIndex::class);
diff --git a/lib/classes/JsonApi/Routes/Lti/PublicationIndex.php b/lib/classes/JsonApi/Routes/Lti/PublicationIndex.php
new file mode 100644
index 0000000..a3724ef
--- /dev/null
+++ b/lib/classes/JsonApi/Routes/Lti/PublicationIndex.php
@@ -0,0 +1,65 @@
+<?php
+
+namespace JsonApi\Routes\Lti;
+
+use Range;
+use Lti\Publication;
+use JsonApi\JsonApiController;
+use JsonApi\Errors\AuthorizationFailedException;
+use Psr\Http\Message\ResponseInterface as Response;
+use Psr\Http\Message\ServerRequestInterface as Request;
+use JsonApi\Schemas\Lti\Publication as PublicationSchema;
+
+class PublicationIndex extends JsonApiController
+{
+ protected $allowedPagingParameters = ['offset', 'limit'];
+ protected $allowedFilteringParameters = [
+ 'status'
+ ];
+
+ protected $allowedIncludePaths = [
+ PublicationSchema::REL_RANGE,
+ PublicationSchema::REL_USER,
+ PublicationSchema::REL_MEMBERS,
+ ];
+
+ public function __invoke(Request $request, Response $response, $args): Response
+ {
+ $range = get_object_by_range_id($args['range_id']);
+ if (!Authority::canShowRegistration($range, $this->getUser($request))) {
+ throw new AuthorizationFailedException();
+ }
+
+ $baseQuery = $this->resolveBaseQuery($range);
+
+ $totalCount = Publication::countBySql(...$baseQuery);
+ $resourceLinks = Publication::findBySQL(
+ $baseQuery[0]." LIMIT ?, ?",
+ [
+ ...$baseQuery[1],
+ ...$this->getOffsetAndLimit()
+ ]
+ );
+
+ return $this->getPaginatedContentResponse($resourceLinks, $totalCount);
+ }
+
+ private function resolveBaseQuery(Range $range): array
+ {
+ $filtering = $this->getQueryParameters()->getFilteringParameters() ?? [];
+
+ $baseQuery = [
+ "`range_id` = :range_id",
+ [
+ 'range_id' => $range->id
+ ]
+ ];
+
+ if (isset($filtering['status'])) {
+ $baseQuery[0] .= " AND `status` IN (:status)";
+ $baseQuery[1]['status'] = explode(',', $filtering['status']);
+ }
+
+ return $baseQuery;
+ }
+}
diff --git a/lib/classes/JsonApi/Routes/Lti/RegistrationIndex.php b/lib/classes/JsonApi/Routes/Lti/RegistrationIndex.php
index 733b972..92d7be4 100644
--- a/lib/classes/JsonApi/Routes/Lti/RegistrationIndex.php
+++ b/lib/classes/JsonApi/Routes/Lti/RegistrationIndex.php
@@ -20,7 +20,7 @@ class RegistrationIndex extends JsonApiController
RegistrationSchema::REL_RANGE
];
- public function __invoke(Request $request, Response $response, $args)
+ public function __invoke(Request $request, Response $response, $args): Response
{
$range = null;
if (isset($args['range_id'])) {
diff --git a/lib/classes/JsonApi/Routes/Lti/RegistrationShow.php b/lib/classes/JsonApi/Routes/Lti/RegistrationShow.php
index 39db0ff..43e6af9 100644
--- a/lib/classes/JsonApi/Routes/Lti/RegistrationShow.php
+++ b/lib/classes/JsonApi/Routes/Lti/RegistrationShow.php
@@ -16,7 +16,7 @@ class RegistrationShow extends JsonApiController
RegistrationSchema::REL_RANGE
];
- public function __invoke(Request $request, Response $response, $args)
+ public function __invoke(Request $request, Response $response, $args): Response
{
if (!$registration = Registration::find($args['id'])) {
throw new RecordNotFoundException();
diff --git a/lib/classes/JsonApi/Routes/Lti/ResourceIndex.php b/lib/classes/JsonApi/Routes/Lti/ResourceIndex.php
new file mode 100644
index 0000000..6e40899
--- /dev/null
+++ b/lib/classes/JsonApi/Routes/Lti/ResourceIndex.php
@@ -0,0 +1,65 @@
+<?php
+
+namespace JsonApi\Routes\Lti;
+
+use JsonApi\Errors\AuthorizationFailedException;
+use Lti\ResourceLink;
+use Psr\Http\Message\ResponseInterface as Response;
+use Psr\Http\Message\ServerRequestInterface as Request;
+use JsonApi\JsonApiController;
+use JsonApi\Schemas\Lti\Resource as ResourceSchema;
+use Range;
+
+class ResourceIndex extends JsonApiController
+{
+ protected $allowedPagingParameters = ['offset', 'limit'];
+ protected $allowedFilteringParameters = [
+ 'launch-types'
+ ];
+
+ protected $allowedIncludePaths = [
+ ResourceSchema::REL_RANGE,
+ ResourceSchema::REL_REGISTRATION,
+ ResourceSchema::REL_DEPLOYMENT
+ ];
+
+ public function __invoke(Request $request, Response $response, $args): Response
+ {
+ $range = get_object_by_range_id($args['range_id']);
+ if (!Authority::canShowRegistration($range, $this->getUser($request))) {
+ throw new AuthorizationFailedException();
+ }
+
+ $baseQuery = $this->resolveBaseQuery($range);
+
+ $totalCount = ResourceLink::countBySql(...$baseQuery);
+ $resourceLinks = ResourceLink::findBySQL(
+ $baseQuery[0]." ORDER BY `position` LIMIT ?, ?",
+ [
+ ...$baseQuery[1],
+ ...$this->getOffsetAndLimit()
+ ]
+ );
+
+ return $this->getPaginatedContentResponse($resourceLinks, $totalCount);
+ }
+
+ private function resolveBaseQuery(Range $range): array
+ {
+ $filtering = $this->getQueryParameters()->getFilteringParameters() ?? [];
+
+ $baseQuery = [
+ "`course_id` = :range_id",
+ [
+ 'range_id' => $range->id
+ ]
+ ];
+
+ if (isset($filtering['launch-type'])) {
+ $baseQuery[0] .= " AND `launch_type` IN (:launch_types)";
+ $baseQuery[1]['launch_types'] = explode(',', $filtering['launch-types']);
+ }
+
+ return $baseQuery;
+ }
+}
diff --git a/lib/classes/JsonApi/SchemaMap.php b/lib/classes/JsonApi/SchemaMap.php
index 6b4fcd0..1536472 100644
--- a/lib/classes/JsonApi/SchemaMap.php
+++ b/lib/classes/JsonApi/SchemaMap.php
@@ -54,6 +54,10 @@ class SchemaMap
\Institute::class => Schemas\Institute::class,
\InstituteMember::class => Schemas\InstituteMember::class,
\Lti\Registration::class => Schemas\Lti\Registration::class,
+ \Lti\ResourceLink::class => Schemas\Lti\Resource::class,
+ \Lti\Deployment::class => Schemas\Lti\Deployment::class,
+ \Lti\Publication::class => Schemas\Lti\Publication::class,
+ \Lti\PublicationUser::class => Schemas\Lti\PublicationMember::class,
\MassMail\MassMailMessage::class => Schemas\MassMailMessage::class,
\MassMail\MassMailPermission::class => Schemas\MassMailPermission::class,
\Message::class => Schemas\Message::class,
diff --git a/lib/classes/JsonApi/Schemas/Lti/Deployment.php b/lib/classes/JsonApi/Schemas/Lti/Deployment.php
new file mode 100644
index 0000000..858160d
--- /dev/null
+++ b/lib/classes/JsonApi/Schemas/Lti/Deployment.php
@@ -0,0 +1,64 @@
+<?php
+
+namespace JsonApi\Schemas\Lti;
+
+use Neomerx\JsonApi\Schema\Link;
+use JsonApi\Schemas\SchemaProvider;
+use Lti\Deployment as DeploymentModel;
+use Neomerx\JsonApi\Contracts\Schema\ContextInterface;
+
+class Deployment extends SchemaProvider
+{
+ const TYPE = 'lti-deployment';
+ const REL_REGISTRATION = 'registration';
+
+ /**
+ * @param DeploymentModel $resource
+ */
+ public function getId($resource): ?string
+ {
+ return $resource->id;
+ }
+
+ /**
+ * @param DeploymentModel $resource
+ */
+ public function getAttributes($resource, ContextInterface $context): iterable
+ {
+ return [
+ 'name' => $resource->name,
+ 'purpose' => $resource->purpose,
+ 'is-default' => (bool) $resource->is_default,
+ 'deployment-key' => $resource->deployment_key,
+ 'client-id' => $resource->client_id,
+ 'mkdate' => date('c', $resource->mkdate),
+ 'chdate' => date('c', $resource->chdate)
+ ];
+ }
+
+ /**
+ * @param DeploymentModel $resource
+ */
+ public function getRelationships($resource, ContextInterface $context): iterable
+ {
+ $relationships = [];
+
+ $relationships = $this->addRegistrationRelationship($relationships, $resource, $this->shouldInclude($context, self::REL_REGISTRATION));
+
+ return $relationships;
+ }
+
+ private function addRegistrationRelationship(array $relationships, DeploymentModel $deployment, bool $withRegistration = false): array
+ {
+ if ($withRegistration) {
+ $relationships[self::REL_REGISTRATION] = [
+ self::RELATIONSHIP_LINKS => [
+ Link::RELATED => $this->createLinkToResource($deployment->registration)
+ ],
+ self::RELATIONSHIP_DATA => $deployment->registration
+ ];
+ }
+
+ return $relationships;
+ }
+}
diff --git a/lib/classes/JsonApi/Schemas/Lti/Publication.php b/lib/classes/JsonApi/Schemas/Lti/Publication.php
new file mode 100644
index 0000000..3d0a530
--- /dev/null
+++ b/lib/classes/JsonApi/Schemas/Lti/Publication.php
@@ -0,0 +1,95 @@
+<?php
+
+namespace JsonApi\Schemas\Lti;
+
+use Neomerx\JsonApi\Schema\Link;
+use JsonApi\Schemas\SchemaProvider;
+use Lti\Publication as PublicationModel;
+use Neomerx\JsonApi\Contracts\Schema\ContextInterface;
+
+class Publication extends SchemaProvider
+{
+ const TYPE = 'lti-publication';
+ const REL_RANGE = 'range';
+ const REL_USER = 'user';
+ const REL_MEMBERS = 'members';
+
+ /**
+ * @param PublicationModel $resource
+ */
+ public function getId($resource): ?string
+ {
+ return $resource->id;
+ }
+
+ /**
+ * @param PublicationModel $resource
+ */
+ public function getAttributes($resource, ContextInterface $context): iterable
+ {
+ return [
+ 'name' => $resource->name,
+ 'publication-key' => $resource->publication_key,
+ 'status' => (bool) $resource->status,
+ 'version' => $resource->version,
+ 'mkdate' => date('c', $resource->mkdate),
+ 'chdate' => date('c', $resource->chdate)
+ ];
+ }
+
+ /**
+ * @param PublicationModel $resource
+ */
+ public function getRelationships($resource, ContextInterface $context): iterable
+ {
+ $relationships = [];
+
+ $relationships = $this->addRangeRelationship($relationships, $resource, $this->shouldInclude($context, self::REL_RANGE));
+ $relationships = $this->addUserRelationship($relationships, $resource, $this->shouldInclude($context, self::REL_USER));
+ $relationships = $this->addMembersRelationship($relationships, $resource, $this->shouldInclude($context, self::REL_MEMBERS));
+
+ return $relationships;
+ }
+
+ private function addRangeRelationship(array $relationships, PublicationModel $publication, bool $withRange = false): array
+ {
+ if ($withRange && $publication->range) {
+ $relationships[self::REL_RANGE] = [
+ self::RELATIONSHIP_LINKS => [
+ Link::RELATED => $this->createLinkToResource($publication->range)
+ ],
+ self::RELATIONSHIP_DATA => $publication->range
+ ];
+ }
+
+ return $relationships;
+ }
+
+ private function addUserRelationship(array $relationships, PublicationModel $publication, bool $withUser = false): array
+ {
+ if ($withUser && $publication->user) {
+ $relationships[self::REL_USER] = [
+ self::RELATIONSHIP_LINKS => [
+ Link::RELATED => $this->createLinkToResource($publication->user)
+ ],
+ self::RELATIONSHIP_DATA => $publication->user
+ ];
+ }
+
+ return $relationships;
+ }
+
+ private function addMembersRelationship(array $relationships, PublicationModel $publication, bool $withUsers = false): array
+ {
+ if ($withUsers) {
+ $relationships[self::REL_MEMBERS] = [
+ self::RELATIONSHIP_LINKS => [
+ Link::RELATED => $this->getRelationshipRelatedLink($publication, self::REL_MEMBERS)
+ ],
+ self::RELATIONSHIP_DATA => $publication->members
+ ];
+ }
+
+ return $relationships;
+ }
+}
diff --git a/lib/classes/JsonApi/Schemas/Lti/PublicationMember.php b/lib/classes/JsonApi/Schemas/Lti/PublicationMember.php
new file mode 100644
index 0000000..9615749
--- /dev/null
+++ b/lib/classes/JsonApi/Schemas/Lti/PublicationMember.php
@@ -0,0 +1,75 @@
+<?php
+
+namespace JsonApi\Schemas\Lti;
+
+use Neomerx\JsonApi\Schema\Link;
+use JsonApi\Schemas\SchemaProvider;
+use Lti\PublicationUser as PublicationUserModel;
+use Neomerx\JsonApi\Contracts\Schema\ContextInterface;
+
+class PublicationMember extends SchemaProvider
+{
+ const TYPE = 'lti-publication-member';
+ const REL_PUBLICATION = 'publication';
+ const REL_USER = 'user';
+
+ /**
+ * @param PublicationUserModel $resource
+ */
+ public function getId($resource): ?string
+ {
+ return $resource->id;
+ }
+
+ /**
+ * @param PublicationUserModel $resource
+ */
+ public function getAttributes($resource, ContextInterface $context): iterable
+ {
+ return [
+ 'mkdate' => date('c', $resource->mkdate),
+ 'chdate' => date('c', $resource->chdate)
+ ];
+ }
+
+ /**
+ * @param PublicationUserModel $resource
+ */
+ public function getRelationships($resource, ContextInterface $context): iterable
+ {
+ $relationships = [];
+
+ $relationships = $this->addPublicationRelationship($relationships, $resource, $this->shouldInclude($context, self::REL_PUBLICATION));
+ $relationships = $this->addUserRelationship($relationships, $resource, $this->shouldInclude($context, self::REL_USER));
+
+ return $relationships;
+ }
+
+ private function addPublicationRelationship(array $relationships, PublicationUserModel $publicationUser, bool $withPublication = false): array
+ {
+ if ($withPublication && $publicationUser->publication) {
+ $relationships[self::REL_PUBLICATION] = [
+ self::RELATIONSHIP_LINKS => [
+ Link::RELATED => $this->createLinkToResource($publicationUser->publication)
+ ],
+ self::RELATIONSHIP_DATA => $publicationUser->publication
+ ];
+ }
+
+ return $relationships;
+ }
+
+ private function addUserRelationship(array $relationships, PublicationUserModel $publicationUser, bool $withUser = false): array
+ {
+ if ($withUser && $publicationUser->user) {
+ $relationships[self::REL_USER] = [
+ self::RELATIONSHIP_LINKS => [
+ Link::RELATED => $this->createLinkToResource($publicationUser->user)
+ ],
+ self::RELATIONSHIP_DATA => $publicationUser->user
+ ];
+ }
+
+ return $relationships;
+ }
+}
diff --git a/lib/classes/JsonApi/Schemas/Lti/Registration.php b/lib/classes/JsonApi/Schemas/Lti/Registration.php
index 859d06d..55acf59 100644
--- a/lib/classes/JsonApi/Schemas/Lti/Registration.php
+++ b/lib/classes/JsonApi/Schemas/Lti/Registration.php
@@ -11,7 +11,7 @@ use Neomerx\JsonApi\Contracts\Schema\ContextInterface;
class Registration extends SchemaProvider
{
- const TYPE = 'lti-registrations';
+ const TYPE = 'lti-registration';
const REL_RANGE = 'range';
/**
@@ -85,14 +85,14 @@ class Registration extends SchemaProvider
return $relationships;
}
- private function addRangeRelationship(array $relationships, RegistrationModel $registration, bool $withRange = false)
+ private function addRangeRelationship(array $relationships, RegistrationModel $registration, bool $withRange = false): array
{
if ($withRange && $registration->range) {
$relationships[self::REL_RANGE] = [
self::RELATIONSHIP_LINKS => [
- Link::RELATED => $this->createLinkToResource($registration->range),
+ Link::RELATED => $this->createLinkToResource($registration->range)
],
- self::RELATIONSHIP_DATA => $registration->range,
+ self::RELATIONSHIP_DATA => $registration->range
];
}
diff --git a/lib/classes/JsonApi/Schemas/Lti/Resource.php b/lib/classes/JsonApi/Schemas/Lti/Resource.php
new file mode 100644
index 0000000..8a97bb7
--- /dev/null
+++ b/lib/classes/JsonApi/Schemas/Lti/Resource.php
@@ -0,0 +1,101 @@
+<?php
+
+namespace JsonApi\Schemas\Lti;
+
+use Neomerx\JsonApi\Schema\Link;
+use JsonApi\Schemas\SchemaProvider;
+use Lti\ResourceLink;
+use Neomerx\JsonApi\Contracts\Schema\ContextInterface;
+
+class Resource extends SchemaProvider
+{
+ const TYPE = 'lti-resource';
+ const REL_RANGE = 'range';
+ const REL_REGISTRATION = 'registration';
+ const REL_DEPLOYMENT = 'deployment';
+
+ /**
+ * @param ResourceLink $resource
+ */
+ public function getId($resource): ?string
+ {
+ return $resource->id;
+ }
+
+ /**
+ * @param ResourceLink $resource
+ */
+ public function getAttributes($resource, ContextInterface $context): iterable
+ {
+ return [
+ 'title' => $resource->title,
+ 'description' => $resource->description,
+ 'position' => (int) $resource->position,
+ 'color' => $resource->color,
+ 'icon' => $resource->icon,
+ 'launch-url' => $resource->launch_url,
+ 'options' => $resource->options,
+ 'custom-parameters' => $resource->custom_parameters,
+ 'launch-container' => $resource->launch_container,
+ 'launch-type' => $resource->launch_type,
+ 'mkdate' => date('c', $resource->mkdate),
+ 'chdate' => date('c', $resource->chdate)
+ ];
+ }
+
+ /**
+ * @param ResourceLink $resource
+ */
+ public function getRelationships($resource, ContextInterface $context): iterable
+ {
+ $relationships = [];
+
+ $relationships = $this->addRangeRelationship($relationships, $resource, $this->shouldInclude($context, self::REL_RANGE));
+ $relationships = $this->addRegistrationRelationship($relationships, $resource, $this->shouldInclude($context, self::REL_REGISTRATION));
+ $relationships = $this->addDeploymentRelationship($relationships, $resource, $this->shouldInclude($context, self::REL_DEPLOYMENT));
+
+ return $relationships;
+ }
+
+ private function addRangeRelationship(array $relationships, ResourceLink $resource, bool $withRange = false): array
+ {
+ if ($withRange && $resource->course) {
+ $relationships[self::REL_RANGE] = [
+ self::RELATIONSHIP_LINKS => [
+ Link::RELATED => $this->createLinkToResource($resource->course)
+ ],
+ self::RELATIONSHIP_DATA => $resource->course
+ ];
+ }
+
+ return $relationships;
+ }
+
+ private function addRegistrationRelationship(array $relationships, ResourceLink $resource, bool $withRegistration = false): array
+ {
+ if ($withRegistration && $resource->registration) {
+ $relationships[self::REL_REGISTRATION] = [
+ self::RELATIONSHIP_LINKS => [
+ Link::RELATED => $this->createLinkToResource($resource->registration)
+ ],
+ self::RELATIONSHIP_DATA => $resource->registration
+ ];
+ }
+
+ return $relationships;
+ }
+
+ private function addDeploymentRelationship(array $relationships, ResourceLink $resource, bool $withDeployment = false): array
+ {
+ if ($withDeployment) {
+ $relationships[self::REL_DEPLOYMENT] = [
+ self::RELATIONSHIP_LINKS => [
+ Link::RELATED => $this->createLinkToResource($resource->deployment)
+ ],
+ self::RELATIONSHIP_DATA => $resource->deployment
+ ];
+ }
+
+ return $relationships;
+ }
+}
diff --git a/lib/models/Lti/ResourceLink.php b/lib/models/Lti/ResourceLink.php
index 8522b31..31fca8e 100644
--- a/lib/models/Lti/ResourceLink.php
+++ b/lib/models/Lti/ResourceLink.php
@@ -24,6 +24,7 @@ use Studip\LTI13a\ResourceLinkRepository;
* @property int $chdate
* @property Course $course
* @property Deployment $deployment
+ * @property Registration $registration
*/
class ResourceLink extends SimpleORMap
{
@@ -37,11 +38,14 @@ class ResourceLink extends SimpleORMap
'class_name' => Course::class,
'foreign_key' => 'course_id'
];
+
$config['belongs_to']['deployment'] = [
'class_name' => Deployment::class,
'foreign_key' => 'deployment_id'
];
+ $config['additional_fields']['registration']['get'] = 'getRegistration';
+
$config['registered_callbacks']['before_create'] = ['cbCalculatePosition'];
parent::configure($config);
@@ -118,4 +122,9 @@ class ResourceLink extends SimpleORMap
{
return new ResourceLinkRepository($this);
}
+
+ public function getRegistration(): Registration
+ {
+ return $this->deployment->registration;
+ }
}
diff --git a/lib/modules/LtiToolModule.php b/lib/modules/LtiToolModule.php
index e696e97..3dea47f 100644
--- a/lib/modules/LtiToolModule.php
+++ b/lib/modules/LtiToolModule.php
@@ -64,15 +64,15 @@ class LtiToolModule extends CorePlugin implements StudipModule, SystemPlugin, Pr
/**
* {@inheritdoc}
*/
- public function getTabNavigation($course_id)
+ public function getTabNavigation($course_id): array
{
if ($GLOBALS['user']->id === 'nobody') {
- return [];
+ return ['lti' => null];
}
$grades = ResourceLink::countBySQL('course_id = ?', [$course_id]);
- $navigation = new Navigation(_('LTI'));
+ $navigation = new Navigation(_('LTI'), 'dispatch.php/course/lti');
$navigation->setImage(Icon::create('link-extern', Icon::ROLE_INFO_ALT));
$navigation->setActiveImage(Icon::create('link-extern', Icon::ROLE_INFO));
$navigation->addSubNavigation('index', new Navigation(_('LTI-Ressourcen'), 'dispatch.php/course/lti'));
@@ -113,8 +113,9 @@ class LtiToolModule extends CorePlugin implements StudipModule, SystemPlugin, Pr
public static function isModerator($courseId, $userId = null): bool
{
- return User::findCurrent()->auth_plugin === 'standard'
- && (self::isAdmin($userId) || $GLOBALS['perm']->have_studip_perm('tutor', $courseId, $userId));
+ return
+ User::findCurrent()->auth_plugin === 'standard'
+ && (self::isAdmin($userId) || $GLOBALS['perm']->have_studip_perm('tutor', $courseId, $userId));
}
/**
@@ -122,9 +123,7 @@ class LtiToolModule extends CorePlugin implements StudipModule, SystemPlugin, Pr
*/
public function exportUserData(StoredUserData $storage)
{
- $db = DBManager::get();
-
- $data = $db->fetchAll('SELECT * FROM lti_grade WHERE user_id = ?', [$storage->user_id]);
+ $data = DBManager::get()->fetchAll("SELECT * FROM `lti_grade` WHERE `user_id` = ?", [$storage->user_id]);
$storage->addTabularData(_('LTI-Ergebnisse'), 'lti_grade', $data);
}
diff --git a/resources/vue/apps/lti/resources/Index.vue b/resources/vue/apps/lti/resources/Index.vue
index 265bd12..60ce4a4 100644
--- a/resources/vue/apps/lti/resources/Index.vue
+++ b/resources/vue/apps/lti/resources/Index.vue
@@ -20,7 +20,7 @@ const props = defineProps({
}
});
-const filteredResources = ref([]);
+const filteredResources = ref(props.resources);
const createResource = () => STUDIP.Dialog.fromURL(createResourceURL(), {width: '700', height: '700'});
@@ -80,7 +80,6 @@ const swapResource = (resourceId, step) => {
onMounted(() => {
// filteredResources.value = props.resources.filter(r => ltiConfig.isModerator || r.launch_type !== 'deep_linking');
- filteredResources.value = props.resources;
});
</script>
diff --git a/resources/vue/apps/responsive/ResponsiveNavigation.vue b/resources/vue/apps/responsive/ResponsiveNavigation.vue
index 11039b1..146cd98 100644
--- a/resources/vue/apps/responsive/ResponsiveNavigation.vue
+++ b/resources/vue/apps/responsive/ResponsiveNavigation.vue
@@ -256,6 +256,8 @@ export default {
};
} else {
// Found requested item at current level.
+ console.log('navigation', navigation);
+ console.log('path', path);
if (navigation[path]) {
return navigation[path];
} else {