Extension:Cargo/SMW migration guide

Overview
It is possible to migrate templates in a wiki from Semantic MediaWiki to Cargo, or, if one desires, from Cargo to Semantic MediaWiki.

The basic process to perform this on an existing Semantic MediaWiki-based site is to install Cargo as an extension, alongside Semantic MediaWiki. Then, templates can be gradually converted to use #cargo_declare and #cargo_store. In fact, it is recommended during the transition process for templates to declare and store their data in both Cargo and Semantic MediaWiki. This allows semantic queries to be converted to their Cargo equivalents without breaking site functionality. (In principle, this same process could be used to gradually convert a Cargo-based site to Semantic MediaWiki.) Once the transition is complete, templates can be modified again to not store data in Semantic MediaWiki (or alternatively, Cargo) at all. At this point, the extension you are not using can be uninstalled.

The following examples assume that Cargo is installed alongside SMW and demonstrates how templates can be modified to use Cargo.

For a more high-level overview of how Cargo differs from SMW, see Cargo and Semantic MediaWiki.

The original template
Let's take as an example a relatively simple infobox-style template of the kind seen in many Semantic MediaWiki-based wikis. This one is called "Country" and it stores basic (and somewhat random) information about a country. Here are the contents of its page, located at "Template:Country":

This is the "Country" template.

This template displays a table with two columns and three rows. The first column simply holds headers, while the second column holds the data: in the first row, a single value (the date founded); in the second row, a comma-separated list of values; and in the third row, an aggregating query.

From property pages to #cargo_declare
To store data, the Semantic MediaWiki approach is to divide data storage among two types of pages: the template page and property pages. The property pages set the type and potentially other details of the data storage, while the template stores the data. In Cargo, on the other hand, these two actions are both done in the template page, using the functions #cargo_declare and #cargo_store, respectively.

So in order to figure out what the #cargo_declare call should look like, we need to know all the SMW properties that this template currently makes use of, and what is contained in the page for each of those properties.

In this case, the template stores data with two properties, "Has date founded" and "Has official language". Going to the pages for those properties, let's say that we see the following at "Property:Has_date_founded":

This is a property of type Has type::Date.

...while "Property:Has_official_language" contains this text:

This is a property of type Has type::Page.

These are very simple declarations, that just set the type. So we know that we need our #cargo_declare function to declare two fields, of type "Date" and "Page", respectively. (There is not exactly a one-to-one mapping between SMW and Cargo types, although it's close. The big differences are the addition of "Datetime" and "Wikitext" types within Cargo, and the split of SMW's "Number" type into separate "Integer" and "Float" types in Cargo.)

What should the fields be called? Here the properties are called "Has date founded" and "Has official language", fitting the usual convention of making property names be verb phrases; but the properties could also have been called any number of things, including just "Date founded" and "Official language". For Cargo, the standard convention is to just go with a simple field name, so let's call them "Date_founded" and "Official_languages". The latter is pluralized because it can hold a list, while both names have underscores instead of spaces because Cargo does not allow spaces in field names.

Cargo makes use of tables, so that every piece of data is stored as a field within a table, not as a standalone property like SMW. So we will need to pick a name for the table. The simplest approach here is to go with the name of the category, i.e. "Countries".

Now we know the name of the table we want, and the names and types of all the fields - in this case, a field called "Date_founded" of type "Date" and a field called "Official_languages", which holds a comma-separated list of values of type "Text". So the resulting #cargo_declare call would be:

From property tags to #cargo_store
Now on to the storage. In Cargo, all the data is stored in one #cargo_store call; as opposed to SMW, where storage is usually done inline. (SMW's #set can in fact store all the data in one place, but this is rarely done.) In this template, there are two properties that were being stored. Given that we already know the table name ("Countries"), this call is straightforward to put together. It should look like:

No special handling is needed for fields that hold lists because this is already taken care of in #cargo_declare.

From #ask to #cargo_query
Not all SMW-based templates contain a call to #ask, but some do - usually in order to display an aggregated list of pages that have some property pointing to the current page. (This "list" can be a simple list, or can have a more involved display, like a map, timeline, etc.) The #ask query in this example template looks like:

We need to translate this to a #cargo_query call - on the assumption that the setting of the cities data has also been migrated to Cargo, or will be soon in the future. Just as with the above, the "Is in country" property needs to be migrated elsewhere into a Cargo table and field. Let's say that the property has been migrated (perhaps in a template called "City") into a table and field called "Cities" and "Country", respectively. In that case, the corresponding #cargo_query call would be:

Aside from the different syntax, note several key differences between the two query languages:
 * In #ask queries, specifying the category is optional. In #cargo_query, the table (which is usually the equivalent of the category) is mandatory.
 * In #cargo_query, unlike #ask, text values within queries need to be enclosed within quotation marks.
 * You can't see it in this example, but querying on fields that can hold a list of values is different. In #ask queries, all properties point to a single value, so it doesn't matter whether a template field holds one value or a list of values. In #cargo_query, on the other hand, it does matter - and fields that hold a list of values need to be queried using either "HOLDS" or "HOLDS LIKE". (The equivalent operators for fields that can only hold a single value are "=", as we see here, and "LIKE".)

For those used to writing SMW queries, these differences will probably take a little time to get used to.

The #ask and #cargo_query calls in this example are both simple queries, that simply display a list of page names based on a simple "filter". They have no specified format, no list of fields to display ("printouts", in SMW's parlance), and no other complicating factors. However, they are the kind of simple aggregating queries that often show up in templates. If your wiki has more complex SMW queries that need translating - and most likely it does - please consult the page "Querying data" for the full syntax of #cargo_query.

Putting it all together
If you migrate a template from Semantic MediaWiki to Cargo, you can choose to keep the existing SMW property tags within that template, or remove them - unless you are removing SMW entirely from your wiki, in which case you will of course need to remove the tags. In this case, let's remove the SMW tags. We'll keep the table-based display as it was before, add in #cargo_declare and #cargo_store in the appropriate places, and replace #ask with #cargo_query. The complete template now looks like:

This is the "Country" template.

Forms
There is a good chance that you also have forms defined, using the Semantic Forms extension, for editing pages that call these templates. Assuming your forms are defined in a straightforward manner, there is a reasonable chance that you will not need to modify these forms at all; as of version 3.1, SF makes use of Cargo data and metadata. If any issues do come up, please consult the Semantic Forms documentation.

There is one way in which the presence of Semantic Forms could affect the template itself, not just the form for it. The "City" template defines one or more links to pages representing languages. It could be that these language pages all use a form for editing their structured data. If a "city" page links to a nonexistent "language" page, you might want the resulting red link to link to the form for creating that language page. The old way to do this in Semantic Forms (before version 3.0) was to set a "default form" for the property. So the text at the page "Property:Has_official_language" might look like:

This is a property of type Has type::Page. It uses the form Has default form::Language.

This approach is deprecated, but it still works when using Semantic MediaWiki. However, with Cargo it does not work, so you will have to use the recommended approach, which is the parser function #formredlink. It takes the place of a regular link, and links to the form for creating a page if the page does not exist, and shows a regular link to the page otherwise. So the relevant line of the "City" template would change from this:



...to this:



From "special properties" to _pageData
This is not related to the main example, but SMW stores various special properties for each page, like "Creation date"; these can be helpful to query in some cases. Cargo offers similar storage of such data, using the _pageData table. To create this table, see Storing page data.