aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMurtaza Sultani <sultani@data-quest.de>2026-01-06 12:50:37 +0100
committerMurtaza Sultani <sultani@data-quest.de>2026-03-19 17:34:49 +0100
commit1dff8c07dbcf12a9a1ef878d3db2d53274ffb766 (patch)
tree010ded65993b5d809d1f7b95cf5bd60016d0794c /lib
parent62852255073feb84effdf3a83878f947020fc46b (diff)
Refactor Deeplinking implementation
Diffstat (limited to 'lib')
-rw-r--r--lib/classes/LTI13a/LineItemRepository.php6
-rw-r--r--lib/classes/LTI13a/ResourceLinkRepository.php129
-rw-r--r--lib/models/Grading/Definition.php5
-rw-r--r--lib/models/Lti/ResourceLink.php24
-rw-r--r--lib/models/LtiResourceLink.php232
-rw-r--r--lib/modules/LtiToolModule.php7
6 files changed, 158 insertions, 245 deletions
diff --git a/lib/classes/LTI13a/LineItemRepository.php b/lib/classes/LTI13a/LineItemRepository.php
index e25a8b6..2d0034b 100644
--- a/lib/classes/LTI13a/LineItemRepository.php
+++ b/lib/classes/LTI13a/LineItemRepository.php
@@ -2,7 +2,7 @@
namespace Studip\LTI13a;
-use LtiResourceLink;
+use Lti\ResourceLink;
use OAT\Library\Lti1p3Ags\Model\LineItem\LineItemCollection;
use OAT\Library\Lti1p3Ags\Model\LineItem\LineItemCollectionInterface;
use OAT\Library\Lti1p3Ags\Model\LineItem\LineItemInterface;
@@ -112,7 +112,7 @@ class LineItemRepository implements LineItemRepositoryInterface
}
//Find the LTI resource link by its ID:
- $resourceLink = LtiResourceLink::find($resourceLinkIdentifier);
+ $resourceLink = ResourceLink::find($resourceLinkIdentifier);
if (!$resourceLink) {
throw new LTIException('Invalid resource link identifier.');
}
@@ -152,7 +152,7 @@ class LineItemRepository implements LineItemRepositoryInterface
*/
public function save(LineItemInterface $lineItem): LineItemInterface
{
- $resourceLink = LtiResourceLink::find($lineItem->getResourceLinkIdentifier());
+ $resourceLink = ResourceLink::find($lineItem->getResourceLinkIdentifier());
if (!$resourceLink) {
throw new LTIException('Invalid resource link identifier.');
}
diff --git a/lib/classes/LTI13a/ResourceLinkRepository.php b/lib/classes/LTI13a/ResourceLinkRepository.php
new file mode 100644
index 0000000..9bced85
--- /dev/null
+++ b/lib/classes/LTI13a/ResourceLinkRepository.php
@@ -0,0 +1,129 @@
+<?php
+namespace Studip\LTI13a;
+
+use Lti\ResourceLink;
+use OAT\Library\Lti1p3Core\Resource\LtiResourceLink\LtiResourceLinkInterface;
+use OAT\Library\Lti1p3Core\Util\Collection\Collection;
+use OAT\Library\Lti1p3Core\Util\Collection\CollectionInterface;
+
+class ResourceLinkRepository implements LtiResourceLinkInterface
+{
+ public function __construct(
+ protected ResourceLink $resourceLink
+ ) {}
+
+
+ public function getType(): string
+ {
+ return 'ltiResourceLink';
+ }
+
+ public function getUrl(): ?string
+ {
+ return $this->resourceLink->getLaunchURL();
+ }
+
+ public function getIcon(): ?array
+ {
+ // TODO: return icon URL
+ return [
+ $this->resourceLink->icon
+ ];
+ }
+
+ public function getThumbnail(): ?array
+ {
+ if ($this->resourceLink->course) {
+ return [
+ $this->resourceLink->course->getItemAvatarURL()
+ ];
+ }
+
+ return null;
+ }
+
+ public function getIframe(): ?array
+ {
+ //Not supported.
+ return null;
+ }
+
+ public function getCustom(): ?array
+ {
+ //Not supported.
+ return null;
+ }
+
+ public function getLineItem(): ?array
+ {
+ // TODO: Implement getLineItem() method.
+ return null;
+ }
+
+ public function getAvailability(): ?array
+ {
+ // TODO: Implement getAvailability() method.
+ return null;
+ }
+
+ public function getSubmission(): ?array
+ {
+ // TODO: Implement getSubmission() method.
+ return null;
+ }
+
+ public function getIdentifier(): string
+ {
+ return strval($this->resourceLink->id);
+ }
+
+ public function getTitle(): ?string
+ {
+ return $this->resourceLink->title ?? $this->resourceLink->deployment->registration->name;
+ }
+
+ public function getText(): ?string
+ {
+ return $this->resourceLink->description;
+ }
+
+ public function getProperties(): CollectionInterface
+ {
+ $collection = new Collection();
+ $collection->add([
+ 'url' => $this->getUrl(),
+ 'title' => $this->getTitle()
+ ]);
+
+ return $collection;
+ }
+
+ public function normalize(): array
+ {
+ return array_filter([
+ ...$this->getProperties()->all(),
+ 'type' => $this->getType()
+ ]);
+ }
+
+ public function getCustomLtiParameters(): array
+ {
+ $parameterStr = $this->resourceLink->getCustomParameters();
+ if (trim($parameterStr) === '') {
+ return [];
+ }
+
+ $custom = [];
+ foreach (explode("\n", $parameterStr) as $line) {
+ [$key, $value] = array_map('trim', explode('=', $line, 2) + [null, null]);
+
+ if ($key !== null && $value !== null) {
+ $custom[$key] = $value;
+ }
+ }
+
+ return [
+ 'https://purl.imsglobal.org/spec/lti/claim/custom' => $custom
+ ];
+ }
+}
diff --git a/lib/models/Grading/Definition.php b/lib/models/Grading/Definition.php
index 5f2d3a4..e4d5b58 100644
--- a/lib/models/Grading/Definition.php
+++ b/lib/models/Grading/Definition.php
@@ -2,10 +2,9 @@
namespace Grading;
-use LtiResourceLink;
+use Lti\ResourceLink;
use OAT\Library\Lti1p3Ags\Model\LineItem\LineItem;
use OAT\Library\Lti1p3Ags\Model\LineItem\LineItemInterface;
-use OAT\Library\Lti1p3Ags\Model\LineItem\LineItemSubmissionReview;
use URLHelper;
/**
@@ -77,7 +76,7 @@ class Definition extends \SimpleORMap
$resourceLinkIdentifier = $this->tool ?? '';
$deploymentId = '';
if ($resourceLinkIdentifier) {
- $ltiResourceLink = LtiResourceLink::find($resourceLinkIdentifier);
+ $ltiResourceLink = ResourceLink::find($resourceLinkIdentifier);
if ($ltiResourceLink) {
$deploymentId = $ltiResourceLink->deployment_id;
}
diff --git a/lib/models/Lti/ResourceLink.php b/lib/models/Lti/ResourceLink.php
index 5b76445..a2c7cd0 100644
--- a/lib/models/Lti/ResourceLink.php
+++ b/lib/models/Lti/ResourceLink.php
@@ -5,7 +5,9 @@ use Course;
use DBManager;
use JSONArrayObject;
use Lti\Enum\ResourceLaunchContainer;
+use OAT\Library\Lti1p3Core\Resource\LtiResourceLink\LtiResourceLinkInterface;
use SimpleORMap;
+use Studip\LTI13a\ResourceLinkRepository;
class ResourceLink extends SimpleORMap
{
@@ -32,12 +34,12 @@ class ResourceLink extends SimpleORMap
/**
* Calculates the position for a new LTI resource link in the course.
*/
- public function cbCalculatePosition() : void
+ public function cbCalculatePosition(): void
{
$this->position = self::countByCourse_id($this->course_id);
}
- public function delete()
+ public function delete(): bool
{
$course_id = $this->course_id;
$position = $this->position;
@@ -76,14 +78,28 @@ class ResourceLink extends SimpleORMap
return $base;
}
- public function getLaunchURL()
+ public function getLaunchURL(): string
{
$registration = $this->deployment->registration;
$registrationConfigs = $registration->getConfigValues();
- if (!empty($registration) && empty($registrationConfigs['allow_custom_url']) && empty($registrationConfigs['deep_linking']) || empty($registrationConfigs['launch_url'])) {
+ if (empty($registrationConfigs['allow_custom_url']) && empty($registrationConfigs['deep_linking']) || empty($registrationConfigs['launch_url'])) {
return $registrationConfigs['launch_url'];
}
return $registrationConfigs['launch_url'];
}
+
+ public function getCustomParameters(): string
+ {
+ if (!empty($this->custom_parameters)) {
+ return $this->custom_parameters;
+ }
+
+ return $this->deployment->registration->getConfigValues()['custom_parameters'];
+ }
+
+ public function toLti1p3ResourceLink(): LtiResourceLinkInterface
+ {
+ return new ResourceLinkRepository($this);
+ }
}
diff --git a/lib/models/LtiResourceLink.php b/lib/models/LtiResourceLink.php
deleted file mode 100644
index 9f18481..0000000
--- a/lib/models/LtiResourceLink.php
+++ /dev/null
@@ -1,232 +0,0 @@
-<?php
-/*
- * LtiResourceLink.php
- * This file is part of Stud.IP.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * @author Moritz Strohm
- * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
- */
-
-
-use Lti\Deployment;
-use OAT\Library\Lti1p3Core\Resource\LtiResourceLink\LtiResourceLinkInterface;
-use OAT\Library\Lti1p3Core\Util\Collection\Collection;
-use OAT\Library\Lti1p3Core\Util\Collection\CollectionInterface;
-
-/**
- * The LtiResourceLink class is a model for the lti_resource_links table.
- *
- * @property int $id database column
- * @property int $deployment_id database column
- * @property string $course_id database column
- * @property string $title database column
- * @property string $description database column
- * @property int $position database column
- * @property string $launch_url database column
- * @property JSONArrayObject|null $options database column
- * @property int $mkdate database column
- * @property int $chdate database column
- * @property ?Deployment $deployment related object
- * @property ?Course $course related object
- */
-class LtiResourceLink extends SimpleORMap implements LtiResourceLinkInterface
-{
- protected static function configure($config = [])
- {
- $config['db_table'] = 'lti_resource_links';
-
- $config['serialized_fields']['options'] = JSONArrayObject::class;
-
- $config['belongs_to']['course'] = [
- 'class_name' => Course::class,
- 'foreign_key' => 'course_id'
- ];
-
- $config['belongs_to']['deployment'] = [
- 'class_name' => Deployment::class,
- 'foreign_key' => 'deployment_id'
- ];
-
- $config['has_many']['grades'] = [
- 'class_name' => LtiGrade::class,
- 'assoc_foreign_key' => 'link_id',
- 'on_delete' => 'delete'
- ];
-
- $config['registered_callbacks']['before_create'] = ['cbCalculatePosition'];
-
- parent::configure($config);
- }
-
- /**
- * Calculates the position for a new LTI resource link in the course.
- */
- public function cbCalculatePosition() : void
- {
- $this->position = self::countByCourse_id($this->course_id);
- }
-
- /**
- * Delete this entity.
- */
- public function delete()
- {
- $course_id = $this->course_id;
- $position = $this->position;
- if ($result = parent::delete()) {
- DBManager::get()->execute(
- "UPDATE `lti_resource_links`
- SET `position` = position - 1
- WHERE `course_id` = :course_id AND `position` > :position",
- [
- 'course_id' => $course_id,
- 'position' => $position
- ]
- );
- }
-
- return $result;
- }
-
- /**
- * Find a single entry by course_id and position.
- *
- * @return static|null
- */
- public static function findByCourseAndPosition($course_id, $position)
- {
- return self::findOneBySQL('course_id = ? AND position = ?', [$course_id, $position]);
- }
-
- public function getLaunchURL()
- {
- $registration = $this->deployment->registration;
- $registrationConfigs = $registration->getConfigValues();
-
- if (!empty($registration) && empty($registrationConfigs['allow_custom_url']) && empty($registrationConfigs['deep_linking']) || empty($registrationConfigs['launch_url'])) {
- return $registrationConfigs['launch_url'];
- }
- return $registrationConfigs['launch_url'];
- }
-
- //OAT library LtiResourceLinkInterface and ResourceInterface implementation:
-
- public function getUrl(): ?string
- {
- return $this->getLaunchURL();
- }
-
- public function getIcon(): ?array
- {
- return null;
- }
-
- public function getThumbnail(): ?array
- {
- if ($this->course) {
- return [$this->course->getItemAvatarURL()];
- }
- return null;
- }
-
- public function getIframe(): ?array
- {
- //Not supported.
- return null;
- }
-
- public function getCustom(): ?array
- {
- //Not supported.
- return null;
- }
-
- public function getLineItem(): ?array
- {
- // TODO: Implement getLineItem() method.
- return null;
- }
-
- public function getAvailability(): ?array
- {
- // TODO: Implement getAvailability() method.
- return null;
- }
-
- public function getSubmission(): ?array
- {
- // TODO: Implement getSubmission() method.
- return null;
- }
-
- public function getIdentifier(): string
- {
- return strval($this->id);
- }
-
- public function getType(): string
- {
- return 'ltiResourceLink';
- }
-
- public function getTitle(): ?string
- {
- return $this->title ?? $this->deployment->registration->name ?? null;
- }
-
- public function getText(): ?string
- {
- return null;
- }
-
- public function getProperties(): CollectionInterface
- {
- $collection = new Collection();
- $collection->add([
- 'url' => $this->getUrl(),
- 'title' => $this->getTitle()
- ]);
- return $collection;
- }
-
- public function normalize(): array
- {
- return array_filter(
- array_merge(
- $this->getProperties()->all(),
- ['type' => $this->getType()]
- )
- );
- }
-
- public function getCustomParameters(): string
- {
- if (!empty($this->custom_parameters)) {
- return $this->custom_parameters;
- }
-
- return $this->deployment->registration->getConfigValues()['custom_parameters'];
- }
-
- public function getCustomLtiParameterArray() : array
- {
- $parameterStr = $this->getCustomParameters();
- if (empty($parameterStr)) {
- return [];
- }
- $parameters = explode("\n", $parameterStr);
- $array = [];
- foreach ($parameters as $parameter) {
- $key_value_parts = explode('=', $parameter, 2);
- if (count($key_value_parts) === 2) {
- $array[trim($key_value_parts[0])] = trim($key_value_parts[1]);
- }
- }
- return ['https://purl.imsglobal.org/spec/lti/claim/custom' => $array];
- }
-}
diff --git a/lib/modules/LtiToolModule.php b/lib/modules/LtiToolModule.php
index 906eb1b..5b1f248 100644
--- a/lib/modules/LtiToolModule.php
+++ b/lib/modules/LtiToolModule.php
@@ -1,6 +1,7 @@
<?php
use Lti\Grade;
+use Lti\ResourceLink;
/**
* LtiToolModule.php - LTI consumer API for Stud.IP
@@ -32,7 +33,7 @@ class LtiToolModule extends CorePlugin implements StudipModule, SystemPlugin, Pr
});
NotificationCenter::on('CourseDidDelete', function ($event, $course) {
- LtiResourceLink::deleteBySQL('course_id = ?', [$course->id]);
+ ResourceLink::deleteBySQL('course_id = ?', [$course->id]);
});
}
@@ -45,7 +46,7 @@ class LtiToolModule extends CorePlugin implements StudipModule, SystemPlugin, Pr
return null;
}
- $changed = LtiResourceLink::countBySQL('course_id = ? AND chdate > ?', [$course_id, $last_visit]);
+ $changed = ResourceLink::countBySQL('course_id = ? AND chdate > ?', [$course_id, $last_visit]);
$icon = Icon::create('plugin', $changed ? Icon::ROLE_NEW : Icon::ROLE_CLICKABLE);
@@ -65,7 +66,7 @@ class LtiToolModule extends CorePlugin implements StudipModule, SystemPlugin, Pr
return [];
}
- $grades = LtiResourceLink::countBySQL('course_id = ?', [$course_id]);
+ $grades = ResourceLink::countBySQL('course_id = ?', [$course_id]);
$navigation = new Navigation(_('LTI'));
$navigation->setImage(Icon::create('link-extern', Icon::ROLE_INFO_ALT));