'suffix' => 'dl',
'group' => 'deep_linking_settings',
'claim' => 'accept_copy_advice',
- 'isarray' => false
+ 'isarray' => false,
+ 'type' => 'boolean'
],
'accept_media_types' => [
'suffix' => 'dl',
'suffix' => 'dl',
'group' => 'deep_linking_settings',
'claim' => 'accept_multiple',
- 'isarray' => false
+ 'isarray' => false,
+ 'type' => 'boolean'
],
'accept_presentation_document_targets' => [
'suffix' => 'dl',
'suffix' => 'dl',
'group' => 'deep_linking_settings',
'claim' => 'accept_unsigned',
- 'isarray' => false
+ 'isarray' => false,
+ 'type' => 'boolean'
],
'auto_create' => [
'suffix' => 'dl',
'group' => 'deep_linking_settings',
'claim' => 'auto_create',
- 'isarray' => false
+ 'isarray' => false,
+ 'type' => 'boolean'
],
'can_confirm' => [
'suffix' => 'dl',
'group' => 'deep_linking_settings',
'claim' => 'can_confirm',
- 'isarray' => false
+ 'isarray' => false,
+ 'type' => 'boolean'
],
'content_item_return_url' => [
'suffix' => 'dl',
'tool_consumer_info_product_family_code' => [
'suffix' => '',
'group' => 'tool_platform',
- 'claim' => 'family_code',
+ 'claim' => 'product_family_code',
'isarray' => false
],
'tool_consumer_info_version' => [
'isarray' => false
],
'lis_outcome_service_url' => [
- 'suffix' => 'bos',
- 'group' => 'basicoutcomesservice',
+ 'suffix' => 'bo',
+ 'group' => 'basicoutcome',
'claim' => 'lis_outcome_service_url',
'isarray' => false
],
'lis_result_sourcedid' => [
- 'suffix' => 'bos',
- 'group' => 'basicoutcomesservice',
+ 'suffix' => 'bo',
+ 'group' => 'basicoutcome',
'claim' => 'lis_result_sourcedid',
'isarray' => false
],
* @throws coding_exception For invalid media type and presentation target parameters.
*/
function lti_build_content_item_selection_request($id, $course, moodle_url $returnurl, $title = '', $text = '', $mediatypes = [],
- $presentationtargets = [], $autocreate = false, $multiple = false,
+ $presentationtargets = [], $autocreate = false, $multiple = true,
$unsigned = false, $canconfirm = false, $copyadvice = false, $nonce = '') {
global $USER;
return $tool;
}
+/**
+ * Converts LTI 1.1 Content Item for LTI Link to Form data.
+ *
+ * @param object $tool Tool for which the item is created for.
+ * @param object $typeconfig The tool configuration.
+ * @param object $item Item populated from JSON to be converted to Form form
+ *
+ * @return stdClass Form config for the item
+ */
+function content_item_to_form(object $tool, object $typeconfig, object $item) : stdClass {
+ $config = new stdClass();
+ $config->name = '';
+ if (isset($item->title)) {
+ $config->name = $item->title;
+ }
+ if (empty($config->name)) {
+ $config->name = $tool->name;
+ }
+ if (isset($item->text)) {
+ $config->introeditor = [
+ 'text' => $item->text,
+ 'format' => FORMAT_PLAIN
+ ];
+ } else {
+ $config->introeditor = [
+ 'text' => '',
+ 'format' => FORMAT_PLAIN
+ ];
+ }
+ if (isset($item->icon->{'@id'})) {
+ $iconurl = new moodle_url($item->icon->{'@id'});
+ // Assign item's icon URL to secureicon or icon depending on its scheme.
+ if (strtolower($iconurl->get_scheme()) === 'https') {
+ $config->secureicon = $iconurl->out(false);
+ } else {
+ $config->icon = $iconurl->out(false);
+ }
+ }
+ if (isset($item->url)) {
+ $url = new moodle_url($item->url);
+ $config->toolurl = $url->out(false);
+ $config->typeid = 0;
+ } else {
+ $config->typeid = $tool->id;
+ }
+ $config->instructorchoiceacceptgrades = LTI_SETTING_NEVER;
+ $islti2 = $tool->ltiversion === LTI_VERSION_2;
+ if (!$islti2 && isset($typeconfig->lti_acceptgrades)) {
+ $acceptgrades = $typeconfig->lti_acceptgrades;
+ if ($acceptgrades == LTI_SETTING_ALWAYS) {
+ // We create a line item regardless if the definition contains one or not.
+ $config->instructorchoiceacceptgrades = LTI_SETTING_ALWAYS;
+ $config->grade_modgrade_point = 100;
+ }
+ if ($acceptgrades == LTI_SETTING_DELEGATE || $acceptgrades == LTI_SETTING_ALWAYS) {
+ if (isset($item->lineItem)) {
+ $lineitem = $item->lineItem;
+ $config->instructorchoiceacceptgrades = LTI_SETTING_ALWAYS;
+ $maxscore = 100;
+ if (isset($lineitem->scoreConstraints)) {
+ $sc = $lineitem->scoreConstraints;
+ if (isset($sc->totalMaximum)) {
+ $maxscore = $sc->totalMaximum;
+ } else if (isset($sc->normalMaximum)) {
+ $maxscore = $sc->normalMaximum;
+ }
+ }
+ $config->grade_modgrade_point = $maxscore;
+ $config->lineitemresourceid = '';
+ $config->lineitemtag = '';
+ if (isset($lineitem->assignedActivity) && isset($lineitem->assignedActivity->activityId)) {
+ $config->lineitemresourceid = $lineitem->assignedActivity->activityId?:'';
+ }
+ if (isset($lineitem->tag)) {
+ $config->lineitemtag = $lineitem->tag?:'';
+ }
+ }
+ }
+ }
+ $config->instructorchoicesendname = LTI_SETTING_NEVER;
+ $config->instructorchoicesendemailaddr = LTI_SETTING_NEVER;
+ $config->launchcontainer = LTI_LAUNCH_CONTAINER_DEFAULT;
+ if (isset($item->placementAdvice->presentationDocumentTarget)) {
+ if ($item->placementAdvice->presentationDocumentTarget === 'window') {
+ $config->launchcontainer = LTI_LAUNCH_CONTAINER_WINDOW;
+ } else if ($item->placementAdvice->presentationDocumentTarget === 'frame') {
+ $config->launchcontainer = LTI_LAUNCH_CONTAINER_EMBED_NO_BLOCKS;
+ } else if ($item->placementAdvice->presentationDocumentTarget === 'iframe') {
+ $config->launchcontainer = LTI_LAUNCH_CONTAINER_EMBED;
+ }
+ }
+ if (isset($item->custom)) {
+ $customparameters = [];
+ foreach ($item->custom as $key => $value) {
+ $customparameters[] = "{$key}={$value}";
+ }
+ $config->instructorcustomparameters = implode("\n", $customparameters);
+ }
+ // Including a JSON version of the form data to support adding many items in one submit.
+ $config->contentitemjson = json_encode($item);
+ return $config;
+}
+
/**
* Processes the tool provider's response to the ContentItemSelectionRequest and builds the configuration data from the
* selected content item. This configuration data can be then used when adding a tool into the course.
if (empty($items)) {
throw new moodle_exception('errorinvaliddata', 'mod_lti', '', $contentitemsjson);
}
- if (!isset($items->{'@graph'}) || !is_array($items->{'@graph'}) || (count($items->{'@graph'}) > 1)) {
+ if (!isset($items->{'@graph'}) || !is_array($items->{'@graph'})) {
throw new moodle_exception('errorinvalidresponseformat', 'mod_lti');
}
$config = null;
- if (!empty($items->{'@graph'})) {
- $item = $items->{'@graph'}[0];
+ $items = $items->{'@graph'};
+ if (!empty($items)) {
$typeconfig = lti_get_type_type_config($tool->id);
-
- $config = new stdClass();
- $config->name = '';
- if (isset($item->title)) {
- $config->name = $item->title;
- }
- if (empty($config->name)) {
- $config->name = $tool->name;
- }
- if (isset($item->text)) {
- $config->introeditor = [
- 'text' => $item->text,
- 'format' => FORMAT_PLAIN
- ];
- }
- if (isset($item->icon->{'@id'})) {
- $iconurl = new moodle_url($item->icon->{'@id'});
- // Assign item's icon URL to secureicon or icon depending on its scheme.
- if (strtolower($iconurl->get_scheme()) === 'https') {
- $config->secureicon = $iconurl->out(false);
- } else {
- $config->icon = $iconurl->out(false);
- }
- }
- if (isset($item->url)) {
- $url = new moodle_url($item->url);
- $config->toolurl = $url->out(false);
- $config->typeid = 0;
+ if (count($items) == 1) {
+ $config = content_item_to_form($tool, $typeconfig, $items[0]);
} else {
- $config->typeid = $tool->id;
- }
- $config->instructorchoiceacceptgrades = LTI_SETTING_NEVER;
- if (!$islti2 && isset($typeconfig->lti_acceptgrades)) {
- $acceptgrades = $typeconfig->lti_acceptgrades;
- if ($acceptgrades == LTI_SETTING_ALWAYS) {
- // We create a line item regardless if the definition contains one or not.
- $config->instructorchoiceacceptgrades = LTI_SETTING_ALWAYS;
- }
- if ($acceptgrades == LTI_SETTING_DELEGATE || $acceptgrades == LTI_SETTING_ALWAYS) {
- if (isset($item->lineItem)) {
- $lineitem = $item->lineItem;
- $config->instructorchoiceacceptgrades = LTI_SETTING_ALWAYS;
- $maxscore = 100;
- if (isset($lineitem->scoreConstraints)) {
- $sc = $lineitem->scoreConstraints;
- if (isset($sc->totalMaximum)) {
- $maxscore = $sc->totalMaximum;
- } else if (isset($sc->normalMaximum)) {
- $maxscore = $sc->normalMaximum;
- }
- }
- $config->grade_modgrade_point = $maxscore;
- $config->lineitemresourceid = '';
- $config->lineitemtag = '';
- if (isset($lineitem->assignedActivity) && isset($lineitem->assignedActivity->activityId)) {
- $config->lineitemresourceid = $lineitem->assignedActivity->activityId ? : '';
- }
- if (isset($lineitem->tag)) {
- $config->lineitemtag = $lineitem->tag ? : '';
- }
- }
- }
- }
- $config->instructorchoicesendname = LTI_SETTING_NEVER;
- $config->instructorchoicesendemailaddr = LTI_SETTING_NEVER;
- $config->launchcontainer = LTI_LAUNCH_CONTAINER_DEFAULT;
- if (isset($item->placementAdvice->presentationDocumentTarget)) {
- if ($item->placementAdvice->presentationDocumentTarget === 'window') {
- $config->launchcontainer = LTI_LAUNCH_CONTAINER_WINDOW;
- } else if ($item->placementAdvice->presentationDocumentTarget === 'frame') {
- $config->launchcontainer = LTI_LAUNCH_CONTAINER_EMBED_NO_BLOCKS;
- } else if ($item->placementAdvice->presentationDocumentTarget === 'iframe') {
- $config->launchcontainer = LTI_LAUNCH_CONTAINER_EMBED;
+ $multiple = [];
+ foreach ($items as $item) {
+ $multiple[] = content_item_to_form($tool, $typeconfig, $item);
}
+ $config = new stdClass();
+ $config->multiple = $multiple;
}
- if (isset($item->custom)) {
- $customparameters = [];
- foreach ($item->custom as $key => $value) {
- $customparameters[] = "{$key}={$value}";
- }
- $config->instructorcustomparameters = implode("\n", $customparameters);
- }
- $config->contentitemjson = json_encode($item);
}
return $config;
}
$newitem->text = $item->html;
unset($newitem->html);
}
- if (isset($item->presentation)) {
+ if (isset($item->iframe)) {
+ // DeepLinking allows multiple options to be declared as supported.
+ // We favor iframe over new window if both are specified.
+ $newitem->placementAdvice = new stdClass();
+ $newitem->placementAdvice->presentationDocumentTarget = 'iframe';
+ if (isset($item->iframe->width)) {
+ $newitem->placementAdvice->displayWidth = $item->iframe->width;
+ }
+ if (isset($item->iframe->height)) {
+ $newitem->placementAdvice->displayHeight = $item->iframe->height;
+ }
+ unset($newitem->iframe);
+ unset($newitem->window);
+ } else if (isset($item->window)) {
+ $newitem->placementAdvice = new stdClass();
+ $newitem->placementAdvice->presentationDocumentTarget = 'window';
+ if (isset($item->window->targetName)) {
+ $newitem->placementAdvice->windowTarget = $item->window->targetName;
+ }
+ if (isset($item->window->width)) {
+ $newitem->placementAdvice->displayWidth = $item->window->width;
+ }
+ if (isset($item->window->height)) {
+ $newitem->placementAdvice->displayHeight = $item->window->height;
+ }
+ unset($newitem->window);
+ } else if (isset($item->presentation)) {
+ // This may have been part of an early draft but is not in the final spec
+ // so keeping it around for now in case it's actually been used.
$newitem->placementAdvice = new stdClass();
if (isset($item->presentation->documentTarget)) {
$newitem->placementAdvice->presentationDocumentTarget = $item->presentation->documentTarget;
$claim = LTI_JWT_CLAIM_PREFIX;
if (array_key_exists($key, $claimmapping)) {
$mapping = $claimmapping[$key];
+ $type = $mapping["type"] ?? "string";
if ($mapping['isarray']) {
$value = explode(',', $value);
sort($value);
+ } else if ($type == 'boolean') {
+ $value = isset($value) && ($value == 'true');
}
if (!empty($mapping['suffix'])) {
$claim .= "-{$mapping['suffix']}";
$this->assertEquals('frame,iframe,window', $params['accept_presentation_document_targets']);
$this->assertEquals($returnurl->out(false), $params['content_item_return_url']);
$this->assertEquals('false', $params['accept_unsigned']);
- $this->assertEquals('false', $params['accept_multiple']);
+ $this->assertEquals('true', $params['accept_multiple']);
$this->assertEquals('false', $params['accept_copy_advice']);
$this->assertEquals('false', $params['auto_create']);
$this->assertEquals($type->name, $params['title']);
'suffix' => 'dl',
'group' => 'deep_linking_settings',
'claim' => 'accept_copy_advice',
- 'isarray' => false
+ 'isarray' => false,
+ 'type' => 'boolean'
],
'accept_media_types' => [
'suffix' => 'dl',
'suffix' => 'dl',
'group' => 'deep_linking_settings',
'claim' => 'accept_multiple',
- 'isarray' => false
+ 'isarray' => false,
+ 'type' => 'boolean'
],
'accept_presentation_document_targets' => [
'suffix' => 'dl',
'suffix' => 'dl',
'group' => 'deep_linking_settings',
'claim' => 'accept_unsigned',
- 'isarray' => false
+ 'isarray' => false,
+ 'type' => 'boolean'
],
'auto_create' => [
'suffix' => 'dl',
'group' => 'deep_linking_settings',
'claim' => 'auto_create',
- 'isarray' => false
+ 'isarray' => false,
+ 'type' => 'boolean'
],
'can_confirm' => [
'suffix' => 'dl',
'group' => 'deep_linking_settings',
'claim' => 'can_confirm',
- 'isarray' => false
+ 'isarray' => false,
+ 'type' => 'boolean'
],
'content_item_return_url' => [
'suffix' => 'dl',
'tool_consumer_info_product_family_code' => [
'suffix' => '',
'group' => 'tool_platform',
- 'claim' => 'family_code',
+ 'claim' => 'product_family_code',
'isarray' => false
],
'tool_consumer_info_version' => [
'isarray' => false
],
'lis_outcome_service_url' => [
- 'suffix' => 'bos',
- 'group' => 'basicoutcomesservice',
+ 'suffix' => 'bo',
+ 'group' => 'basicoutcome',
'claim' => 'lis_outcome_service_url',
'isarray' => false
],
'lis_result_sourcedid' => [
- 'suffix' => 'bos',
- 'group' => 'basicoutcomesservice',
+ 'suffix' => 'bo',
+ 'group' => 'basicoutcome',
'claim' => 'lis_result_sourcedid',
'isarray' => false
],
*/
public function test_lti_verify_jwt_signature_no_public_key() {
$this->resetAfterTest();
-
$this->setAdminUser();
// Create a tool type, associated with that proxy.
'url' => 'http://example.com/messages/launch',
'title' => 'Test title',
'text' => 'Test text',
- 'frame' => []
+ 'iframe' => []
+ ];
+ $contentitems[] = [
+ 'type' => 'ltiResourceLink',
+ 'url' => 'http://example.com/messages/launch2',
+ 'title' => 'Test title2',
+ 'text' => 'Test text2',
+ 'iframe' => [
+ 'height' => 200,
+ 'width' => 300
+ ],
+ 'window' => []
+ ];
+ $contentitems[] = [
+ 'type' => 'ltiResourceLink',
+ 'url' => 'http://example.com/messages/launch3',
+ 'title' => 'Test title3',
+ 'text' => 'Test text3',
+ 'window' => [
+ 'targetName' => 'test-win',
+ 'height' => 400
+ ]
];
$contentitems = json_encode($contentitems);
$objgraph->url = 'http://example.com/messages/launch';
$objgraph->title = 'Test title';
$objgraph->text = 'Test text';
- $objgraph->frame = [];
+ $objgraph->placementAdvice = new stdClass();
+ $objgraph->placementAdvice->presentationDocumentTarget = 'iframe';
$objgraph->{$strtype} = 'LtiLinkItem';
$objgraph->mediaType = 'application\/vnd.ims.lti.v1.ltilink';
+ $objgraph2 = new stdClass();
+ $objgraph2->url = 'http://example.com/messages/launch2';
+ $objgraph2->title = 'Test title2';
+ $objgraph2->text = 'Test text2';
+ $objgraph2->placementAdvice = new stdClass();
+ $objgraph2->placementAdvice->presentationDocumentTarget = 'iframe';
+ $objgraph2->placementAdvice->displayHeight = 200;
+ $objgraph2->placementAdvice->displayWidth = 300;
+ $objgraph2->{$strtype} = 'LtiLinkItem';
+ $objgraph2->mediaType = 'application\/vnd.ims.lti.v1.ltilink';
+
+ $objgraph3 = new stdClass();
+ $objgraph3->url = 'http://example.com/messages/launch3';
+ $objgraph3->title = 'Test title3';
+ $objgraph3->text = 'Test text3';
+ $objgraph3->placementAdvice = new stdClass();
+ $objgraph3->placementAdvice->presentationDocumentTarget = 'window';
+ $objgraph3->placementAdvice->displayHeight = 400;
+ $objgraph3->placementAdvice->windowTarget = 'test-win';
+ $objgraph3->{$strtype} = 'LtiLinkItem';
+ $objgraph3->mediaType = 'application\/vnd.ims.lti.v1.ltilink';
+
$expected = new stdClass();
$expected->{$strcontext} = 'http://purl.imsglobal.org/ctx/lti/v1/ContentItem';
$expected->{$strgraph} = [];
$expected->{$strgraph}[] = $objgraph;
+ $expected->{$strgraph}[] = $objgraph2;
+ $expected->{$strgraph}[] = $objgraph3;
$this->assertEquals($expected, $jsondecode);
}
+ /**
+ * Test adding a single gradable item through content item.
+ */
+ public function test_lti_tool_configuration_from_content_item_single_gradable() {
+ $this->resetAfterTest();
+ $this->setAdminUser();
+
+ $type = new stdClass();
+ $type->name = "Test tool";
+ $type->baseurl = "http://example.com";
+ $config = new stdClass();
+ $config->lti_acceptgrades = LTI_SETTING_DELEGATE;
+ $typeid = lti_add_type($type, $config);
+
+ $generator = $this->getDataGenerator()->get_plugin_generator('mod_lti');
+ $contentitems = [];
+ $contentitems[] = [
+ 'type' => 'ltiResourceLink',
+ 'url' => 'http://example.com/messages/launch',
+ 'title' => 'Test title',
+ 'lineItem' => [
+ 'resourceId' => 'r12345',
+ 'tag' => 'final',
+ 'scoreMaximum' => 10.0
+ ],
+ 'frame' => []
+ ];
+ $contentitemsjson13 = json_encode($contentitems);
+ $json11 = lti_convert_content_items($contentitemsjson13);
+
+ $config = lti_tool_configuration_from_content_item($typeid,
+ 'ContentItemSelection',
+ $type->ltiversion,
+ 'ConsumerKey',
+ $json11);
+
+ $this->assertEquals($contentitems[0]['url'], $config->toolurl);
+ $this->assertEquals(LTI_SETTING_ALWAYS, $config->instructorchoiceacceptgrades);
+ $this->assertEquals($contentitems[0]['lineItem']['tag'], $config->lineitemtag);
+ $this->assertEquals($contentitems[0]['lineItem']['resourceId'], $config->lineitemresourceid);
+ $this->assertEquals($contentitems[0]['lineItem']['scoreMaximum'], $config->grade_modgrade_point);
+ }
+
+ /**
+ * Test adding multiple gradable items through content item.
+ */
+ public function test_lti_tool_configuration_from_content_item_multiple() {
+ $this->resetAfterTest();
+ $this->setAdminUser();
+
+ $type = new stdClass();
+ $type->name = "Test tool";
+ $type->baseurl = "http://example.com";
+ $config = new stdClass();
+ $config->lti_acceptgrades = LTI_SETTING_DELEGATE;
+ $typeid = lti_add_type($type, $config);
+
+ $generator = $this->getDataGenerator()->get_plugin_generator('mod_lti');
+ $contentitems = [];
+ $contentitems[] = [
+ 'type' => 'ltiResourceLink',
+ 'url' => 'http://example.com/messages/launch',
+ 'title' => 'Test title',
+ 'text' => 'Test text',
+ 'icon' => [
+ 'url' => 'http://lti.example.com/image.jpg',
+ 'width' => 100
+ ],
+ 'frame' => []
+ ];
+ $contentitems[] = [
+ 'type' => 'ltiResourceLink',
+ 'url' => 'http://example.com/messages/launchgraded',
+ 'title' => 'Test Graded',
+ 'lineItem' => [
+ 'resourceId' => 'r12345',
+ 'tag' => 'final',
+ 'scoreMaximum' => 10.0
+ ],
+ 'frame' => []
+ ];
+ $contentitemsjson13 = json_encode($contentitems);
+ $json11 = lti_convert_content_items($contentitemsjson13);
+
+ $config = lti_tool_configuration_from_content_item($typeid,
+ 'ContentItemSelection',
+ $type->ltiversion,
+ 'ConsumerKey',
+ $json11);
+ $this->assertNotNull($config->multiple);
+ $this->assertEquals(2, count( $config->multiple ));
+ $this->assertEquals($contentitems[0]['title'], $config->multiple[0]->name);
+ $this->assertEquals($contentitems[0]['url'], $config->multiple[0]->toolurl);
+ $this->assertEquals(LTI_SETTING_NEVER, $config->multiple[0]->instructorchoiceacceptgrades);
+ $this->assertEquals($contentitems[1]['url'], $config->multiple[1]->toolurl);
+ $this->assertEquals(LTI_SETTING_ALWAYS, $config->multiple[1]->instructorchoiceacceptgrades);
+ $this->assertEquals($contentitems[1]['lineItem']['tag'], $config->multiple[1]->lineitemtag);
+ $this->assertEquals($contentitems[1]['lineItem']['resourceId'], $config->multiple[1]->lineitemresourceid);
+ $this->assertEquals($contentitems[1]['lineItem']['scoreMaximum'], $config->multiple[1]->grade_modgrade_point);
+ }
+
+ /**
+ * Test adding a single non gradable item through content item.
+ */
+ public function test_lti_tool_configuration_from_content_item_single() {
+ $this->resetAfterTest();
+ $this->setAdminUser();
+
+ $type = new stdClass();
+ $type->name = "Test tool";
+ $type->baseurl = "http://example.com";
+ $config = new stdClass();
+ $typeid = lti_add_type($type, $config);
+
+ $generator = $this->getDataGenerator()->get_plugin_generator('mod_lti');
+ $contentitems = [];
+ $contentitems[] = [
+ 'type' => 'ltiResourceLink',
+ 'url' => 'http://example.com/messages/launch',
+ 'title' => 'Test title',
+ 'text' => 'Test text',
+ 'icon' => [
+ 'url' => 'http://lti.example.com/image.jpg',
+ 'width' => 100
+ ],
+ 'frame' => []
+ ];
+ $contentitemsjson13 = json_encode($contentitems);
+ $json11 = lti_convert_content_items($contentitemsjson13);
+
+ $config = lti_tool_configuration_from_content_item($typeid,
+ 'ContentItemSelection',
+ $type->ltiversion,
+ 'ConsumerKey',
+ $json11);
+ $this->assertEquals($contentitems[0]['title'], $config->name);
+ $this->assertEquals($contentitems[0]['text'], $config->introeditor['text']);
+ $this->assertEquals($contentitems[0]['url'], $config->toolurl);
+ $this->assertEquals($contentitems[0]['icon']['url'], $config->icon);
+ $this->assertEquals(LTI_SETTING_NEVER, $config->instructorchoiceacceptgrades);
+
+ }
+
/**
* Test lti_sign_jwt().
*/