Extension:Cargo/SMW migration guide

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 edit

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":

<noinclude>
This is the "Country" template.
</noinclude>
<includeonly>
{|
! Date founded
| [[Has date founded::{{{Date founded|}}}]]
|-
! Official languages
| {{#arraymap:{{{Official languages|}}}|,|x|[[Has official language::x]] }}
|-
! Cities
| {{#ask:[[Category:Cities]][[Is in country::{{PAGENAME}}]]}}
|}
[[Category:Countries]]
</includeonly>

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 edit

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, which 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", "Wikitext" and "File" 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:

{{#cargo_declare:_table=Countries|Date_founded=Date|Official_languages=List (,) of Page}}

If you have decided that you definitely want to get rid of Semantic MediaWiki on your wiki, it is probably a good idea to delete all the property pages, so that you aren't left with phantom pages (pages in a now-invalid namespace) on the wiki. If you have already uninstalled SMW, the easiest way to get rid of these pages is to re-install SMW, delete all the pages in the "Property:" namespace, then uninstall SMW again.

From property tags to #cargo_store edit

Now on to the storage. In Cargo, all the data is stored in one #cargo_store call. In this template, there are two fields/parameters being stored. Given that we already know the table name ("Countries"), this call is straightforward to put together. It should simply look like:

{{#cargo_store:_table=Countries}}

You could also explicitly specify each field, i.e.:

{{#cargo_store:_table=Countries|Date_founded={{{Date founded|}}}|Official_languages={{{Official languages|}}} }}

However, this is not necessary in this case, because the Cargo field names are the same as the template parameter names.

From #ask to #cargo_query edit

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:

{{#ask:[[Category:Cities]][[Is in country::{{PAGENAME}}]]}}

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:

{{#cargo_query:tables=Cities|where=Country = '{{PAGENAME}}'}}

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 - single quotes (i.e., apostrophes) are preferred.
  • 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 edit

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:

<noinclude>
This is the "Country" template.

{{#cargo_declare:_table=Countries|Date_founded=Date|Official_languages=List (,) of Page}}
</noinclude>
<includeonly>
{{#cargo_store:_table=Countries|Date_founded={{{Date founded|}}}|Official_languages={{{Official languages|}}} }}
{|
! Date founded
| {{{Date founded|}}}
|-
! Official languages
| {{#arraymap:{{{Official languages|}}}|,|x|[[x]] }}
|-
! Cities
| {{#cargo_query:tables=Cities|where=Country = '{{PAGENAME}}'}}
|}
[[Category:Countries]]
</includeonly>

Forms edit

There is a good chance that you also have forms defined, using the Page 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, since PF can make use of Cargo data and metadata. If any issues do come up, please consult the Page Forms documentation.

From "special properties" to _pageData edit

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 .