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(); } } }