Skip to content

Commit bc072ad

Browse files
committed
More progress towards Canvas Assignments
1 parent fe4b3f2 commit bc072ad

File tree

2 files changed

+40
-4
lines changed

2 files changed

+40
-4
lines changed

src/Util/CC.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,8 @@ public function add_lti_link($module, $title=null, $url=null, $resourceLinkId=nu
331331

332332
/**
333333
* Add a resource to the manifest.
334+
*
335+
* @return \DOMNode The created item node
334336
*/
335337
public function add_resource_item($module, $title, $type, $identifier, $file) {
336338
$this->last_file = $file;
@@ -351,7 +353,7 @@ public function add_resource_item($module, $title, $type, $identifier, $file) {
351353
array('identifier' => $this->last_identifierref, "type" => $type));
352354
$new_file = $this->add_child_ns(CC::CC_1_1_CP, $new_resource, 'file', null, array("href" => $file));
353355

354-
return $file;
356+
return $new_item;
355357
}
356358

357359
/**
@@ -524,7 +526,15 @@ function zip_add_lti_outcome_to_module($zip, $module, $title, $url, $custom=null
524526
$assignment_file = 'assignments/ASSIGNMENT_'.$assignment_fileHash.'.xml';
525527

526528
// Create assignment resource and module item
527-
$assignment_resource_id = $this->add_resource_item($module, $title, 'associatedcontent/imscc_xmlv1p1/learning-application-resource', $assignment_identifier, $assignment_file);
529+
$assignment_item = $this->add_resource_item($module, $title, 'associatedcontent/imscc_xmlv1p1/learning-application-resource', $assignment_identifier, $assignment_file);
530+
$assignment_resource_id = $assignment_identifier . "_R";
531+
532+
// Canvas requires LTI resources to be referenced in the organizations tree or they get discarded
533+
// Add a nested item under the assignment item that references the LTI resource
534+
// This ensures Canvas keeps the LTI resource when importing
535+
$lti_item = $this->add_child_ns(CC::CC_1_1_CP, $assignment_item, 'item', null,
536+
array('identifier' => $lti_identifier, "identifierref" => $lti_resource_id));
537+
$hidden_title = $this->add_child_ns(CC::CC_1_1_CP, $lti_item, 'title', '(hidden)');
528538

529539
// Generate and save Canvas assignment XML (references the LTI resource identifier)
530540
// Canvas expects resource_link_id to match the LTI resource identifier in the manifest

tests/Util/CCTest.php

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,32 @@ public function testZip() {
134134
$this->assertStringContainsString('<title>Week 2</title>', $save);
135135
$this->assertStringContainsString('<item identifier="' . $assignmentId . '" identifierref="' . $assignmentIdRef . '">', $save);
136136
$this->assertStringContainsString('<title>Quiz: Single Table SQL</title>', $save);
137+
138+
// Canvas requires LTI resources to be referenced in the organizations tree
139+
// Verify that a nested item referencing the LTI resource exists under the assignment item
140+
// The nested item should have identifierref matching an LTI resource (LT_*_R pattern)
141+
// and title "(hidden)"
142+
$this->assertStringContainsString('(hidden)', $save, 'Should contain hidden LTI item title');
143+
144+
// Verify the LTI resource exists in the manifest (created by zip_add_lti_outcome_to_module)
145+
// The LTI resource should have type "imsbasiclti_xmlv1p0" and identifier matching LT_*_R pattern
146+
$this->assertMatchesRegularExpression(
147+
'/<resource identifier="LT_[^"]+_R" type="imsbasiclti_xmlv1p0">/',
148+
$save,
149+
'Should contain LTI resource for the assignment'
150+
);
151+
152+
// Verify nested item structure: assignment item should contain a nested item
153+
// The nested item should reference the LTI resource via identifierref
154+
// Pattern: <item identifier="ASSIGNMENT_ID" identifierref="ASSIGNMENT_ID_R">...<item identifier="LT_..." identifierref="LT_..._R">
155+
$assignmentItemPattern = '<item identifier="' . preg_quote($assignmentId, '/') . '"';
156+
$nestedLtiItemPattern = '<item[^>]*identifierref="LT_[^"]+_R"';
157+
$this->assertMatchesRegularExpression(
158+
'/' . preg_quote($assignmentItemPattern, '/') . '[^>]*>.*?' . $nestedLtiItemPattern . '/s',
159+
$save,
160+
'Assignment item should contain nested LTI item with identifierref pointing to LTI resource'
161+
);
162+
137163
$this->assertStringContainsString('<item identifier="' . $topicId . '" identifierref="' . $topicIdRef . '">', $save);
138164
$this->assertStringContainsString('<title>Discuss: Single Table SQL</title>', $save);
139165
$this->assertStringContainsString('<resource identifier="' . $webLinkIdRef . '" type="imswl_xmlv1p1">', $save);
@@ -162,8 +188,8 @@ public function testZip() {
162188
$this->assertStringContainsString('<item identifier="' . $assignmentId . '">', $meta);
163189
$this->assertStringContainsString('<content_type>Assignment</content_type>', $meta);
164190
$this->assertStringContainsString('<title>Quiz: Single Table SQL</title>', $meta);
165-
// Canvas assignments use the file path as identifierref, not the _R format
166-
$this->assertStringContainsString('<identifierref>' . $assignmentFile . '</identifierref>', $meta);
191+
// Canvas assignments use the assignment resource identifier (_R format)
192+
$this->assertStringContainsString('<identifierref>' . $assignmentIdRef . '</identifierref>', $meta);
167193
$this->assertStringContainsString('<item identifier="' . $topicId . '">', $meta);
168194
$this->assertStringContainsString('<content_type>DiscussionTopic</content_type>', $meta);
169195
$this->assertStringContainsString('<title>Discuss: Single Table SQL</title>', $meta);

0 commit comments

Comments
 (0)