1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
|
<?php
namespace Studip\LTI13a;
use OAT\Library\Lti1p3Ags\Model\LineItem\LineItemCollection;
use OAT\Library\Lti1p3Ags\Model\LineItem\LineItemCollectionInterface;
use OAT\Library\Lti1p3Ags\Model\LineItem\LineItemInterface;
use OAT\Library\Lti1p3Ags\Repository\LineItemRepositoryInterface;
use Studip\LTIException;
use Grading\Definition;
class LineItemRepository implements LineItemRepositoryInterface
{
/**
* Converts the tool-ID and deployment-ID in the tool name used in the
* Stud.IP grading context.
*
* @param string $tool_id The Stud.IP LTI tool ID.
* @param string $deployment_id The Stud.IP LTI deployment ID.
* @return string The corresponding tool name used in the Stud.IP grading context.
*/
public static function getGradingToolName(string $tool_id, string $deployment_id) : string
{
return sprintf('lti-%s-%s', $tool_id, $deployment_id);
}
/**
* Converts the LTI line item identifier to search parameters to retrieve
* Stud.IP grading definitions.
*
* @param string $line_item_identifier The LTI line item identifier.
*
* @return array The search parameters for searching in the Stud.IP grading context.
* This is an associative array with two keys:
* 'tool' => The identifier of the tool in the Stud.IP grading context.
* 'course_id' => The Stud.IP course-ID.
* In case the search parameters cannot be generated, an empty array is returned.
*/
public static function getSearchParametersFromLineItemIdentifier(string $line_item_identifier) : array
{
//$lineItemIdentifier contains the full URL to the line item.
//We must extract the course-ID, tool-ID and deployment-ID
//from the URL parameters first, before searching a grading definition.
$url_parts = parse_url($line_item_identifier);
$parameters = [];
if (empty($url_parts['query'])) {
//Nothing we can convert.
return [];
}
parse_str($url_parts['query'], $parameters);
if (empty($parameters)) {
//Same as above.
return [];
}
$search_parameters = [
'course_id' => $parameters['cid'],
'tool' => self::getGradingToolName($parameters['tool_id'], $parameters['deployment_id'])
];
if (!empty($parameters['definition_id'])) {
$search_parameters['definition_id'] = $parameters['definition_id'];
}
return $search_parameters;
}
/**
* @inheritDoc
*/
public function find(string $lineItemIdentifier): ?LineItemInterface
{
$search_parameters = self::getSearchParametersFromLineItemIdentifier($lineItemIdentifier);
if (!$search_parameters) {
//Nothing we can search for.
return null;
}
$definition = null;
if (!empty($search_parameters['definition_id'])) {
$definition = Definition::find($search_parameters['definition_id']);
} else {
$definition = Definition::findOneBySQL(
"`course_id` = :course_id AND `tool` = :tool",
[
'course_id' => $search_parameters['course_id'],
'tool' => $search_parameters['tool']
]
);
}
if ($definition) {
return $definition->toLineItem();
}
return null;
}
/**
* @inheritDoc
*/
public function findCollection(
?string $resourceIdentifier = null,
?string $resourceLinkIdentifier = null,
?string $tag = null,
?int $limit = null,
?int $offset = null
): LineItemCollectionInterface
{
$result = new LineItemCollection();
if (!$resourceLinkIdentifier) {
//Nothing we can search for.
return $result;
}
//$resourceLinkIdentifier contains the Stud.IP tool-ID, the deployment-ID and the course-ID,
//separated by underscores.
$id_parts = explode('_', $resourceLinkIdentifier);
if (count($id_parts) !== 3) {
throw new LTIException('Invalid resource link identifier.');
}
$tool_id = $id_parts[0];
$deployment_id = $id_parts[1];
$course_id = $id_parts[2];
$sql = '';
$sql_params = [];
if ($tool_id && $course_id) {
$sql .= "`tool` = :tool AND `course_id` = :course_id";
$sql_params['tool'] = self::getGradingToolName($tool_id, $deployment_id);
$sql_params['course_id'] = $course_id;
} else {
//No tool-ID means no line item collection can be found.
return $result;
}
if ($limit) {
if (empty($sql)) {
$sql .= "TRUE ";
}
$sql .= "LIMIT :limit ";
$sql_params['limit'] = $limit;
}
if ($offset) {
$sql .= "OFFSET :offset";
$sql_params['offset'] = $offset;
}
$definitions = Definition::findBySql($sql, $sql_params);
foreach ($definitions as $definition) {
$result->add($definition->toLineItem());
}
return $result;
}
/**
* @inheritDoc
*/
public function save(LineItemInterface $lineItem): LineItemInterface
{
//The resource link identifier contains the Stud.IP tool-ID, deployment-ID and course-ID
//separated by underscores.
$studip_ids = explode('_', $lineItem->getResourceLinkIdentifier() ?? '');
$tool_id = $studip_ids[0];
$deployment_id = $studip_ids[1];
$course_id = $studip_ids[2];
$definition = new Definition();
$definition->id = $lineItem->getIdentifier();
$definition->name = $lineItem->getLabel();
$definition->course_id = $course_id;
$definition->tool = sprintf('lti-%s-%s', $tool_id, $deployment_id);
$definition->weight = '1.0';
if ($definition->store()) {
return $definition->toLineItem();
} else {
throw new LTIException('Could not save line item.');
}
}
/**
* @inheritDoc
*/
public function delete(string $lineItemIdentifier): void
{
$search_parameters = self::getSearchParametersFromLineItemIdentifier($lineItemIdentifier);
$definition = Definition::findOneBySQL(
'`course_id` = :course_id AND `tool` = :tool',
$search_parameters
);
if ($definition) {
$definition->delete();
}
}
}
|