Contents

Chapter 7. Importing From Another Subscription System

Mapping Profiles developer

A mapping profile is a JSON file that tells the wizard which source tables hold the users, products, prices and access, and how to read each field. The profiles offered under Quick start are the files in administrator/components/com_paddlesubs/presets/import/; add a source system by adding a profile, not code. Save this mapping in the mapping editor downloads the same format, so a mapping made in the wizard can become a preset.

A profile has a name, a source_id (the default Name for this source), a description, four table mappings (users, products, prices and access, each with its table without prefix, its key column and its fields), defaults for currency (one Paddle takes) and tax_category, and options such as create_missing_users. Nothing is assumed about how a source spreads the four over its tables: akeebasubs.json reads products and prices from the same table, a level being a product with one price, and paddlesubs.json reads several prices per product. The products mapping can also say "only": {"column": "enabled", "values": ["1"]}: only products whose column holds one of the values are imported, and access to the prices of the others is counted as skipped. The other mappings can't. A price's duration is a number, or a length with its unit (30d, 1 month, ISO 8601 P1Y), and its duration_unit any usual spelling of a day, week, month, year or quarter.

Each field is read in exactly one way:

"column": "email"

The value of a column.

"constant": "month"

The same value for every row.

"template": "{first_name} {last_name}"

Columns put together into text.

"rules": [{"when": {"forever": "1"}, "then": "1"}], "default": "0"

The first rule whose columns match decides the value.

A column can be refined with "json_path" (a path into a JSON column, with * for any key, and "pick": "first" or "last"), "map" (translate values, such as {"non_recurring_forever": "1"}), "default" (for a value the map doesn't know), and "transforms": trim, lower, upper, int, bool, zero_date_null (treat 0000-00-00 as no date), unix_time (read a number of seconds since 1970 as a UTC date; 0 is no date) and {"far_future_null": "2037-12-31"} (treat a date on or after this as no end).

The user fields are email (required), name, username, password_hash, blocked and registered_at. The product fields are name (required) and description. The price fields are product (required: the value of the products table's key), name, amount, currency, recurring, duration, duration_unit (day, week, month or year; days when not read), lifetime and ends_on. recurring, lifetime and ends_on suggest the billing type of a price the import creates. The access fields are user (required: the value of the users table's key), price (required: the value of the prices table's key), published, publish_up (required) and publish_down. published is true for access the source gives, or a state by number: 3 for paid access waiting for its start (pending when its window hasn't opened, else unpublished), -2 for trashed. The AkeebaSubs preset reads it with rules: 1 when enabled is 1, else 3 when state is C; the PaddleSubs preset reads the source's published column as it is. Published access whose window hasn't started is imported pending. What the catalog step decided is saved with an import as map (source price key to local price id, or null to leave it out).

Everything read from a dump is treated as untrusted: only table definitions and inserts into the temporary tables are ever run.