Skip to content

Import and export the configuration

One file carries the certifications and their editions: a row per certification, and under it a row per edition. The columns are in CSV format.

The wording of the notices is a separate file — see Set up notifications.

Both an export and an import can be done from the interface or from the command line.

The rule the whole thing rests on

The file writes what it names. What it does not name stays as it is.

There is no row that says remove this, so nothing disappears because the file was silent about it:

  • an import never deletes a certification — that is done from the Manage certifications page, where the number of people it affects is shown first;
  • a certification row with no edition rows under it keeps the editions it has. A file that says nothing about a chain is not a file declaring the chain empty.

The one removal a file causes is of what it claims: a row claiming position 2 replaces whichever course holds position 2 today. That is how the course of an edition is changed, and it is a declared substitution rather than an omission somebody interpreted.

What the file cannot do

It cannot shorten a chain. To take an edition away without putting another course in its place, use the certification's Editions tab.

Export

Manage certifications → Export configuration, and pick the delimiter. The file downloads.

From the command line:

bash
php local/loop/cli/export.php --output=/tmp/configuration.csv
php local/loop/cli/export.php --output=/tmp/configuration.csv --delimiter=semicolon

An export carries every edition, including the ones LOOP recognises from the courses themselves, so the file is a complete record of the configuration. It never needs a licence: reading your own configuration out of a site whose licence has lapsed is how you keep what you configured.

A row the export cannot write is left out and said so: an edition of a course that is no longer on the site, or of a course whose short name is nothing but spaces — the file names a course by its short name, so an empty one would write a file that cannot be read back. The command line reports those on standard error, so they survive the file being redirected into a pipe. A download has nowhere to carry them, and each of them names a state the site should not be in.

Import

Manage certifications → Import configuration. Three steps: choose the file, read what it would change, confirm.

  1. Upload. The file and, if you want to force it, the delimiter. Nothing else — there is nothing to authorise on this form.
  2. Read. Everything the file would change, grouped by certification and written as sentences: validity_period "365" becomes "730", position 2 passes from course "SAFETY-2026" to course "SAFETY-2027". A file that matches the site says so and offers nothing to confirm.
  3. Confirm. Applying the file says yes to everything the page listed — renames included — and to nothing else.

If the file cannot be applied at all, the reasons are listed instead of the changes, and nothing is written — every reason, and not the first, because a reading answers in one pass. What was worth knowing beside them is listed too, a rename the file also asks for included, so the file goes back to be corrected of everything at once. Nothing on that page can be confirmed, so a warning there cannot be read as a consent. See If the import refuses your file.

From the command line, the same two steps:

bash
php local/loop/cli/import.php --file=/tmp/configuration.csv --preview
php local/loop/cli/import.php --file=/tmp/configuration.csv --execute

--preview prints the same sentences the page shows and writes nothing. A file that renames a certification needs --allow-rename: from the page the rename is in front of the person confirming it, and on a command line there is nobody to ask.

Importing writes the configuration, so it needs a working licence, like every other write.

What an import reports

Applying the file ends on a report of what was written, and the same counts go into the single Configuration imported entry in the site log — see The audit trail.

CountWhat it counts
Certifications createdThe new: rows
Certifications updatedCertification rows whose values or notices differed from the site's
Editions writtenManual editions created, and existing ones whose position or method changed
Editions replacedManual editions removed to free a position the file claims
Course marks writtenCourses whose Certification Edition field the file marked — the edition follows from the mark
Course marks removedMarks taken off a course, because another course claims that position or because the edition carrying it was replaced
Rows read and not writtenidnumber rows, which travel in the file and change nothing

A file applied a second time reports zeroes throughout: the file declares a state rather than a difference, so there is nothing left to write.

Change the course of an edition

Export, change the course_shortname on the edition row, import.

The row claims a position and a course, and both claims are honoured: whichever course held that position is replaced, and if the course you named sat at another position it is moved rather than duplicated. Swapping two courses between two positions works — declare the two rows and both changes happen together.

Add a certification and its editions in one file

A certification that does not exist yet has no number, and its editions have to be able to name it. Give it a temporary label instead — new: and a word of your choosing — and use the same label on its edition rows:

csv
certification,new:forklift,Forklift Licence,1095,60,90,"90,30",,,,,"enrolled,completed",1,,,,,
edition,new:forklift,,,,,,,,,,,,1,FORKLIFT-2026,812,manual,

Do not apply a file that creates twice

The label means nothing outside the file, so a second run creates a second certification. Export the configuration after the first run: from then on the rows carry numbers, and the file can be applied as often as you like with no effect.

Editions LOOP works out from the courses

An export carries all three kinds of edition, and an import treats them differently:

RowWhat an import does
manualWrites the edition
custom_fieldWrites CERT_<cert_id>_<order> into the course's Certification Edition field, and the edition follows from it — without waiting for the nightly synchronisation
idnumberNothing. A course's ID number belongs to whoever administers the catalogue, so the row is read and the course is left alone. If it disagrees with what the course says, the import names the course

A manual or custom_field row for a course whose ID number puts it at another position is applied — both outrank the ID number — and the import names the divergence under Worth knowing. The ID number is nobody's to correct but the catalogue's: remove that edition later and the old position comes back.

A custom_field row writes into a course, which is outside LOOP's own tables. Two consequences worth knowing before you use it:

  • an edition that exists because of a mark on a course has no actions menu on the Editions page: to remove it, clear the mark from the course;
  • the token of another certification on the same course is never touched — a course can be an edition of several certifications.

If a course already has a manual edition at that position, the manual one goes on winning, and the import says so: the mark is written as the row asks, and the edition stays manual. To change the method, remove the manual edition from the Editions page first.

A mark holds its position from the moment somebody writes it on the course, and not from the next synchronisation: a course marked an hour ago, with no edition row of its own yet, holds that position against the file just the same.

The other way round — a manual row for a position that a marked course holds — refuses the file, and so does any row for a position that a course ID number holds. In both cases the import cannot free the position without rewriting a course your file never mentions, so instead of putting two courses in one position it asks you to say where the holding course goes: give it a row of its own, at another position or at this one with another chaining method.

If the import refuses your file

One error refuses the whole file, and nothing is written. No row is ever skipped with a warning: a typo in a course short name passed over in silence would take the edition it describes with it.

The file saysWhat happens
A cert_id that does not exist hereRefused. Use new:something to create it, or correct the number
A course_shortname that resolves to nothingRefused, naming the line
A course_shortname differing from the site's only in caseRefused, naming the spelling the site holds. A course is named in the file exactly as the site holds it, which is how an export writes it
A course_id that disagrees with the short nameRefused. That is what a file written on another site looks like
A name that differs from the stored oneRefused unless renaming is allowed — from the page, by confirming; from the command line, with --allow-rename
A value in a column belonging to the other kind of rowRefused, naming the column and the line
Two rows claiming one position, or naming one course twiceRefused, with both line numbers
A position already held by a course the file says nothing about, where LOOP cannot free it — a manual row over a marked course, or any row over a course ID numberRefused, naming the course that holds the position and how it holds it. Give that course a row of its own, saying where it goes
An edition row for a certification the file never describesRefused. Add its certification row, or correct the reference
The same certification described on two rowsRefused, with both line numbers. One certification is one row, and its editions go underneath
A custom_field row on a site whose Certification Edition field has been deletedRefused: the mark would have nowhere to go, and the edition the row asks for would never appear
A notice this site has no notification template forRefused. Such a site cannot send that notice from here or from the certification page either — restore the template, or take the notice out of the notices column
A header row that is not this format'sRefused with the columns that were expected. A file in the previous format is recognised and named as such

Every message names the line to go and correct. The reliable way to build an import file is to start from an export of the same site: export, edit the rows you want to change, import that file back.