Import Open edX OLX course exports directly into a Totara course —
chapters, sequentials, verticals, HTML/video content, graded problems (assembled into quizzes),
and several interactive block types — without hand-converting anything. Published as the Totara
plugin local_olximport.
Status: alpha. This has been built and tested end-to-end against one real, large Open edX reference export on Totara 20, but it has not seen broad real-world use yet. Read What's missing before you rely on it for anything you can't afford to redo by hand.
Note
Platform note. This plugin is built and verified against Totara first — that's the platform it's exercised on day to day, and where new work lands first. It also happens to run unmodified on stock Moodle, since Totara is itself Moodle-derived, and that compatibility is tested and kept working (see Platform support) — but treat it as a secondary track rather than an equal target when deciding how much to lean on it.
Point it at an OLX .tar.gz archive (the format Open edX's Studio produces via
Export Course) and it builds a real course:
- Structure:
chapter→ course section,sequential→ a label marking it (with a "(graded)" suffix when applicable),vertical→ one or more pages. - Content:
htmlandvideoblocks become page content; internal/jump_to_id/links and static assets (images, PDFs, etc.) are resolved and re-hosted in the course. - Problems:
problemblocks are converted to Moodle question types (multichoice, shortanswer, numerical) and assembled into quizzes for graded sequentials. A sequential that interleaves problems with other content gets several small quizzes positioned where the problems actually occurred, not one quiz dumped at the end. Unsupported response types are imported as non-gradable "description" questions so the content isn't lost, with the gap logged in the run report. library_content(randomized problem pools) becomes a quiz section that draws random questions from an imported question category.- Interactive blocks:
lti→ mod_lti,discussion→ mod_forum,openassessment(ORA) → mod_assign with a rubric built from the block's own criteria,edx_sga(staff-graded assignment) → mod_assign.
Anything the parser recognises but doesn't convert yet is logged in the run's report rather than silently dropped — see What's missing.
- Totara 20. The primary target — every release is built and verified against it first.
- PHP 8.1+ (whatever your Totara version already requires).
- Tested against both PostgreSQL and MySQL as the site database. If you're on MySQL running in
STRICT_TRANS_TABLESmode, make sure you're on the version in this repo or later — an earlier internal build had a bug (fixed, seeupgrade.txt) where a missing default field on one activity type only surfaced under MySQL's strict mode.
Also runs on Moodle. Since Totara is Moodle-derived, this plugin runs unmodified on stock Moodle 4.1 LTS through 4.x too (
$plugin->requires = 2022112800), and that path has its own real end-to-end verification (Moodle 4.2). It is not compatible with Moodle 5.0+ —quiz_add_quiz_question()/quiz_add_random_questions(), which the quiz builder depends on, were removed there. Moodle support is kept working, but expect it to trail Totara when the two platforms diverge.
cd /path/to/your/site
git clone https://github.com/omernawaz/olx2mbz.git local/olximport
php admin/cli/upgrade.phpOr download a release tarball and extract it to local/olximport in your site root, then run the
upgrade CLI (or visit Site administration to trigger it through the web).
Grant the local/olximport:import capability (default: Manager) to whichever roles should be
allowed to run imports.
Site administration → Courses → Open edX OLX course import (or
/local/olximport/index.php directly).
Upload a .tar.gz archive, optionally override the shortname, full name, category, course
format, and visibility, and submit. The import runs as a background adhoc task — large archives
can take a while — and the page shows your recent import runs with their status. Click through to
a finished run for the full report: what was imported, what was skipped, and why.
php local/olximport/cli/import.php --file=/path/to/course.tar.gz [options]Options:
-f, --file=PATH Path to the OLX .tar.gz archive (required)
-n, --dry-run Parse the archive and print a coverage report; create nothing
-s, --shortname=NAME Course shortname to use (defaults to the OLX course/run id)
--fullname=NAME Course full name to use (defaults to the OLX course's display name)
--format=FORMAT Course format to use, e.g. topics, weeks (defaults to topics, the one
this importer's chapter/section structure is built around)
--hidden Create the course hidden from students, instead of the default visible
-v, --verbose Print extra diagnostic detail
-h, --help Print this help
Use --dry-run first on anything unfamiliar — it parses the archive and prints a coverage report
(what block types are present and whether each is supported) without creating anything.
Web-UI imports are queued as a Moodle adhoc task and picked up by your site's normal cron. On a
site where cron fires overlapping cron.php processes (the default in recent Moodle versions,
which keep a cron invocation alive for a few minutes polling for new tasks while a fresh one
starts every minute) two workers can end up racing on the same queued import. This plugin takes
its own lock per import run to keep that safe — see upgrade.txt for the details and how it's
verified, if you're curious or hit something that looks like it.
OLX block types not converted yet (imported course keeps going; each one is logged in the run report instead of silently dropped):
poll,surveyannotatablewiki(course-level)drag-and-drop-v2- Multi-dropdown / cloze (
multianswer) problems
Problem response types not auto-graded (imported as a non-gradable "description" question so the content survives, rather than lost):
customresponse,formularesponse,schematicresponse,imageresponse,annotationresponse, and any problem whose grading logic depends on a randomized Python script — these all require running arbitrary Python at grade time, which has no Moodle equivalent.
Other known gaps:
- Custom per-course CSS/JS authored directly in OLX
htmlblocks (<link>/<style>/<script>tags) is stripped, the same as Moodle's own HTML sanitiser would do to it anyway. - ORA's (
openassessment) multi-stage workflow (self-assessment, then peer-assessment, then staff override) has no Moodle equivalent — only the rubric criteria carry over; grading becomes a single manual staff pass via mod_assign. - A missing static asset referenced from a page is reported in the run log as a broken link, not silently ignored or fatal.
- Only English (
lang/en) strings exist right now. - No update-in-place / re-import: every import creates a new course. Re-running against a previously-imported archive with the same shortname will fail with "shortname already exists" by design, since there's no merge logic.
If you hit an OLX construct not listed above that still doesn't work, that's a bug, not a known gap — please open an issue.
Tests run inside a full Totara (or Moodle) install with PHPUnit already initialized
(php admin/tool/phpunit/cli/init.php), the same as any other plugin's tests:
vendor/bin/phpunit --group local_olximportA Behat feature (tests/behat/import.feature) covers the web UI end to end against a minimal
fixture archive.
The PHPUnit suite covers OLX parsing, per-block-type conversion, the vertical splitter, question
conversion, the import-run model, and the background task's concurrency/crash-recovery behaviour
(see upgrade.txt for what that last one is guarding against and how it was verified against
real, separate OS processes — a single PHPUnit run's single DB connection can't exercise that
path on its own).
- Bugs / feature requests: open a GitHub issue. Include the OLX export if you can (or a
minimal archive that reproduces it) — most failures so far have come from OLX constructs the
parser hadn't seen yet, and a real sample is worth far more than a description.
- Attach
--dry-run --verboseoutput and, for a failed run, the full import report from the run's report page.
- Attach
- Security issues: please report privately rather than as a public issue — see SECURITY.md.
- Contributions: PRs welcome, especially for the OLX block types and response types listed under What's missing. No formal contribution process yet beyond "open a PR, explain what OLX construct it handles, include a test archive/fixture if you can."
- This is currently maintained by one person in their spare time. Response times will vary — please be patient, and a well-isolated repro goes a long way.
GPL v3 or later. See LICENSE.