Changelog¶
What changed in each release of Import/export, in terms of what it means for you rather than which files moved.
0.6.1 — 3 October 2026¶
A fixes-only release. It carries everything in 0.6.0 below. No setting, table or column changes, and it installs over 0.6.0, 0.5.1 or 0.1.0 as an ordinary update.
- An extra table can no longer be one of OpenCart's own. Extra tables
took any table name, so a user group holding nothing but Import/export could
write
oc_user_groupand grant itself every permission, oroc_setting. Every table any supported OpenCart release installs is now refused, whether it is typed on the form, carried by a saved mapping or arrives in an imported profile file. Extra tables are for other extensions' data, and those work as before. A saved profile that names a core table is refused when it runs, and says which table. - A mirroring job whose Missing records rule cannot be read is refused. A rule with a condition this version does not have used to be dropped, which left a sweep with no scope: a sweep of every record. It now stops with a warning and saves nothing.
- An export directory that leads into the image directory is refused however
it is spelled. A path with
..in it, or one through a symbolic link, slipped past the check and put the whole catalogue under a public URL. - A source or image URL naming this server in IPv6 dress is refused, the way
127.0.0.1and private addresses already were. - A value that cannot be stored is a row error rather than something written wrong. A CSV row that is not valid UTF-8 is reported against its row number, with the advice to save the file as UTF-8. A row whose values are too large for the plan to hold is refused rather than cut short. A rollback whose stored values cannot be read back stops and says so rather than restoring nothing.
- A failure Import/export did not expect no longer leaves a scheduled run looking as if it is still going. A database error or a bug in the middle of a scheduled import or export now closes the run as failed, with its message, under Saved profiles.
- A full disk fails the export instead of finishing it with a short file.
- Rolling back images stops if it cannot put one back. It used to report success with the old image still missing.
- A broken image says why in the plan, beside the row that named it.
- A failure email the server refused to send is written to the log, rather than counted as sent.
- The Personal Data and Remove everything held about a person screens say so when an erasure gets no answer — an expired session, a timeout — instead of leaving the button greyed out and nothing on screen.
- A bookmarked link to a draft that has since been cleared away opens the screen with a warning instead of an error page.
- Cancelling an export no longer moves the feed's
Last-Modified, and a match refused on a shared value says "records" rather than inventing a plural for anything that is not a product. - Extensions → Modules lists Import/export as Disabled, and that is expected. Nothing reads that switch, so there is nothing to turn on; the documentation used to tell you to.
0.6.0 — 29 September 2026¶
Two features, both additive. Installing it over 0.5.1 or 0.1.0 adds one column to the saved profiles, and every profile you have stays an import. Nothing becomes scheduled and no export starts until you switch one on.
- An export can be saved as a profile and run on a schedule. Fill in a job
name on the export form and press Save as profile; the profile keeps its
fields, format, filters, sort and languages. Under Saved profiles it is
listed as an export, and it takes the same hourly, daily, weekly or monthly
cycle and the same on/off switch an import does, from your store's cron or
from
preflight.php cron. Apply automatically is not offered for an export, because there is nothing to apply. Clicking its name reopens the export form holding it, and Run exports it once, by hand. - Orders, customers and coupons cannot be exported on a schedule. A scheduled export writes a fresh copy on every cycle with nobody reading it, and for those three that copy is personal data or a list of working discount codes. You are told so when you switch the schedule on, not at four in the morning. They export by hand exactly as before.
- A scheduled export keeps only its newest file. Each successful run discards the file of the same profile's previous run and keeps that job in the history; downloading it says a later run replaced it. Exports you make by hand, including with Run, are never discarded this way. A scheduled export that fails leaves the previous file where it was.
- Products can be matched on UPC, EAN, JAN, ISBN or MPN, as well as on
model and SKU. On those five, a value two or more products share is refused
as a row error, such as
ean matches 2 products; match on a field they do not share, rather than written to one of them: OpenCart 4.1 copies a product's identifiers into each of its variants, so a shared EAN is normal there. A value that becomes shared between the plan and the apply stops the job, like any other change to the store. Model and SKU keep the rule they always had: the product with the lowest identifier is the one updated. - A mirroring job matched on one of the five never removes a product that has nothing in that field, the same rule 0.5.1 brought to SKU.
- A profile file holding an export is marked as a later version, so 0.5.x refuses it by name rather than reading it as an import with no source. Import profile files are unchanged, and 0.5.x still reads them.
What the feed URL promises has changed, and only on a store that switches a
scheduled export on. Until now the feed handed out the last export somebody
had made and reviewed. It still hands out the newest finished export of that
kind of record, but on a store with a scheduled export of that kind, the newest
one may be a scheduled run's file that nobody has looked at. Scheduling is off
for every profile until you switch it on, so a store that never does keeps the
old promise exactly. The feed now also sends a Last-Modified header with when
its file was finished, so whoever fetches it can tell a stale file from a fresh
one.
0.5.1 — 29 September 2026¶
A fixes-only release. It carries everything in 0.5.0 below.
- On OpenCart 4.0.2.x, any job naming
discountsorspecialsworks now. It used to fail withUnknown column 'special', whether it was planning an import, running an export or deleting a product in a mirroring sync, because 4.0.2.x keeps specials in their own table. Import/export now reads and writes them inoc_product_specialon those releases, and inoc_product_discounton 4.1 as before. - A mirroring job no longer removes records that have nothing in the field it matches on. A product with no SKU was swept by every SKU-matched mirror, every run.
- Where two records share a model or SKU, the one with the lowest identifier is always the one updated. It was already so in practice; nothing in the query guaranteed it.
0.5.0 — 21 September 2026¶
If you are coming from 0.1.0, the first thing you will notice is the name.
Your admin screens said Preflight; they say Import/export now, which is what
the marketplace listing has called this extension since the day it was listed.
Only the name changed. The archive is still preflight.ocmod.zip, the routes,
the settings and the nine tables are spelled exactly as they were, so this
installs over 0.1.0 as an ordinary update and your jobs, profiles, plans and
journals stay where they are. Three releases' worth of other changes come with
it: 0.2.0, 0.3.0 and 0.4.0 below, each of which ships in this archive rather
than separately. 0.3.0 is the one to read.
- Import/export now runs on OpenCart 4.1.0.4, schedules included. That
release broke OpenCart's own scheduler: every scheduled task on the store,
ours and everybody else's, stops inside OpenCart's code before an extension is
reached. That is why it was not a version to install on. It is now, because
Import/export no longer needs that scheduler: one line in your server's own
crontab,
php extension/preflight/preflight.php cron, runs both scheduled passes exactly as the store's cron would, with the same runs, emails, log lines and Automatic runs list. See running the scheduled passes yourself. - On such a store Import/export says so on its own screen, names your exact release and what it has stopped, and gives you the command. It also stops printing a next-due time beside each scheduled profile there, because that was a promise the store could not keep.
- The same command is the answer on any store whose host does not call
cron.php, or where you would rather run one scheduler than two.
0.4.0 — 21 September 2026¶
- Import/export now publishes what it holds about a person, column by column, with what removes each one: all 116 columns of its nine tables, on what this holds about a person. Five of them are personal or not depending on what a job was importing, and all five are published at their worst case rather than at their average.
- Customers > Personal Data answers what Import/export holds about one person and erases them from the same screen, alongside every other extension on the store that answers the same question.
- Remove everything held about a person, linked from Import/export's own screen, is new, and it is wider than the history purge you already had. Purging history throws away every finished job's plan and journal, which are the undo. It never touched the job rows, the import labels or the source URLs, because those are not rollback data. This screen reaches them: it deletes the labels, empties the names, labels, source URLs and staff attributions on your jobs and feeds, and keeps the counts, so your import history still says what happened and no longer says anything about anybody. It itemises exactly what it will do, with a count beside each line, before you press it, and it is not reversible.
- Where your saved feeds fetch from is emptied by that screen too, which switches those feeds off until you type the URL again, the same way the provider key and the feed secret are asked for again after an update, and for the same reason.
- How long a plan and a journal are kept is now published as your setting rather than as a number, with the value a store answers until you change it and where you change it. Setting it to keep everything still keeps everything; nothing here overrides that. What changed is that the page says in full what that means rather than printing a zero.
- Nothing about your stored data changes on upgrade, and the retention window is exactly what it was.
0.3.0 — 21 September 2026¶
- Import/export will not send an order, a customer, a review or a coupon to a language model. Generation writes text from an instruction you wrote, and an instruction may name any field the row maps. A prompt about a customer resolved to that person's address, and one about an order to both addresses, the comment and the IP, and posted it to an address fixed in Import/export rather than one you chose. A job that asks to generate text for one of those four kinds of record is now refused when you save it, and says why on the screen. Nothing is lost: generation writes a description, a meta title and a meta description, and none of those four has one. It is a refusal rather than a default, and there is no setting to change it.
- Preview now shows the instruction as it would be sent, under the mapped values for each sampled row and with that row's own values already substituted in. It is the text that would leave your server, readable before any of it does; producing it sends nothing.
- The documentation says what generation sends and where. Which endpoint, which country, that the address is fixed in code rather than in a setting, what one request carries, which kinds of record are refused, and that Import/export retains nothing of what it sends. See limits on generated content.
- Nothing else changed, and an upgrade touches none of your stored data. If you had generation configured on an order, customer, review or coupon profile, it never produced anything you could keep; that profile now refuses to save until its instructions are cleared.
0.2.0 — 21 September 2026¶
- On a store with one language nothing you can see changed. Import/export still ships English and only English, so every screen reads exactly as it did. What it gains is the machinery for reading a translation of its screens once one exists: it now works out which of the languages it ships your admin should be served, rather than assuming your language code is spelled the way our directories are. With one language shipped that question has one answer, so a single-language store is not asked anything and pays nothing.
- On a store with more than one language, the settings screen gains a read-only Language section. It lists every language your store has, including any that are switched off, and, for each, which of Import/export's own translations it is served from. Today that is English for every language but English, and the section says which: not translated. There is nothing to set there and nothing to save.
- Directories Import/export creates are no longer world-writable. The folder
under your store's
image/directory that installed pictures land in, and the working directories staging and the rollback journal live in, were created with the same permissions OpenCart's own core uses, which asks for world-write. Inside the document root that is a folder anyone with an account on the server can drop a file into, and a host configured to refuse it refuses the import instead. They are now created owner-writable, which is all Import/export ever needed. On most hosts this changes nothing you could have seen: the server was already taking those permissions back. On a host that was not, directories Import/export created before this release keep the permissions they were created with. Change them yourself, or delete them and let Import/export make them again. - There is still nothing here a shopper reads, and there never will be. See Limits and guarantees for what that means for the translation figures published for this extension.
0.1.0 — 13 August 2026¶
The first public release: listed on the OpenCart Marketplace on 13 August 2026 and last updated there on 26 August 2026. There is no previous version, so nothing here is a change. This entry is the baseline every later one is measured against.
What ships is the plan-first import described on what it does: every record a file would create or change shown field by field before anything is written, apply, rollback, export, the feed URL, profiles and schedules, and the command line. It runs on OpenCart 4.0.2.0 through 4.1.0.3 and refuses to install below 4.0.2.0.
This release called itself Preflight everywhere but on the marketplace. The
listing's own name has been Import/export from the day it was created; the
extension's screens and this documentation had not caught up, and did so in
0.5.0. Nothing under the name ever moved: the archive is preflight.ocmod.zip,
the routes are extension/preflight/..., the settings are module_preflight_*
and the nine tables are oc_preflight_*. That is what makes the update to
0.5.0 an ordinary one.
What an update keeps¶
Every job, plan and journal Import/export has recorded comes through an update untouched.
Your settings come back, with the exceptions below. An update is an uninstall and then an install, and OpenCart deletes an extension's settings at the uninstall step. Import/export keeps its own copy of them and puts them back afterwards. They are one set for the whole installation rather than one per store.
These are asked for again rather than put back:
module_preflight_status— Nothing writes it and nothing reads it, so there is nothing for an update to keep.module_preflight_feed_secret— Asked for again after an update, deliberately. A credential Import/export put back would be a credential sitting in the database of somebody who removed Import/export altogether. Until you set it again the feed is off, which is the safe way round.module_preflight_ai_key— Asked for again after an update, for the same reason the feed secret is: a provider key Import/export put back would outlive the extension in a table nothing drops. Generation is off until you give it again.module_preflight_diary_verbose_until— Detailed logging comes back off after an update, the way a fresh install does. An upgrade is an uninstall and a reinstall, and putting a diagnostic window back is how a store ends up verbose months after the support exchange that asked for it ended.
A setting a release adds does not change what your store does. Its default is what Import/export did before the setting existed, so an update never asks you to go and set something to get back the behaviour you already had.
What this cannot tell you is whether a release changed how a setting behaves, as against whether it survives. Nothing derives that from the code, so it is written by hand: a release that changes an answer you relied on says so in its own entry above, as its own paragraph and never among what is new.