Skip to content

fix: SCORM block files survive OLX roundtrip and course rerun#116

Merged
Syed-Ali-Abbas-568 merged 3 commits into
overhangio:masterfrom
Syed-Ali-Abbas-568:syed-ali/olx-roundtrip-spike
Jun 3, 2026
Merged

fix: SCORM block files survive OLX roundtrip and course rerun#116
Syed-Ali-Abbas-568 merged 3 commits into
overhangio:masterfrom
Syed-Ali-Abbas-568:syed-ali/olx-roundtrip-spike

Conversation

@Syed-Ali-Abbas-568
Copy link
Copy Markdown
Collaborator

Summary

Fixes #108 (SCORM block 404s after OLX export/import) and extends the same fix to course rerun.

When an author uploads a SCORM zip, the block extracts it into default_storage and discards the original zip. The block's metadata is persisted in the modulestore, but the underlying files aren't tracked by anything else. As a result:

  • OLX export+import: imported blocks render 404 because metadata survives the roundtrip but files don't.
  • Course rerun: the cloned block points at a new extract_folder_path (keyed to the rerun course's usage_id), while files remain at the source course's path. Same 404 symptom.

Approach

Two complementary hooks, both implemented inside the XBlock — no openedx-platform changes required:

  1. OLX export/import. Override add_xml_to_node to bundle a fresh re-zip of the extracted SCORM tree into the export tarball at scorm/<url_name>/package.zip, and override parse_xml to re-extract on import. parse_xml temporarily re-keys scope_ids.usage_id to the target course's coordinates during extraction so files land where the rendered block will look for them (otherwise extract uses the source course's hash and the rendered block 404s).

  2. Course rerun. Rerun bypasses OLX entirely (store.clone_course operates at the modulestore level — neither add_xml_to_node nor parse_xml fires). Added a lazy _rehydrate_extract_folder_if_missing helper that runs on first render. If files are missing but the block knows its SHA1, it scans scorm_location() for another bucket containing the same SHA1 directory and copies the tree in. Self-healing, no signal handlers, no Django app conversion.

Wired into index_page_url and assets_proxy. A per-instance _extract_folder_verified flag ensures the search only runs once per block instance.

What this fixes

  • New exports bundle the SCORM zip and roundtrip cleanly through import.
  • Course reruns work on first render of the rerun block.
  • Reruns and imports that were already broken before this code deploys self-heal on first render, as long as another course on the same instance has the same package.

What this does not fix

  • Importing an OLX tarball that was exported before this code merges — the tarball has no scorm_package_path attribute, so the import-time rehydrate doesn't fire. If no other course on the destination instance has the same package, the block requires a re-upload. (Re-export of the same course on this code produces a self-contained tarball that works anywhere.)

Builds on #71

#71 introduced the usage_id-hashed extract_folder_base_path. The re-keying trick in parse_xml depends on that hash being deterministic. This PR closes the export/import and rerun caveats listed in #71's description.

Co-Authored-By: Claude noreply@anthropic.com

@ahmed-arb ahmed-arb moved this from Pending Triage to In review in Tutor project management May 19, 2026
Comment thread openedxscorm/scormxblock.py Outdated
cur = stack.pop()
try:
dirs, files = self.storage.listdir(cur)
except (FileNotFoundError, NotImplementedError):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not understand the need for a NotImplementedError. What method are we expecting to not be implemented?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes i have removed it.

if not self.package_meta or not self.index_page_path:
return ""

self._rehydrate_extract_folder_if_missing()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The index_page_url method is called in the student_view meaning it is called every time someone opens a scorm unit in the LMS.

For this reason, I don't think it is optimal that we should be calling a rehydrate method that is only required once after a course import.

Is there a way to call this only once per xblock after a course import?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have cached its so rehydrate does not run everytime.

Copy link
Copy Markdown
Contributor

@Danyal-Faheem Danyal-Faheem left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Thank you for bearing with my incessant commenting 🙇.

@Syed-Ali-Abbas-568 Syed-Ali-Abbas-568 merged commit b5ad947 into overhangio:master Jun 3, 2026
@github-project-automation github-project-automation Bot moved this from In review to Done in Tutor project management Jun 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Development

Successfully merging this pull request may close these issues.

Export/Import and the SCORM XBlock

4 participants