Extension:Cargo/Storing data

The creation of data structures, and storage of data, is done in Cargo exclusively via templates. Any template that makes use of Cargo needs to contain calls to the parser functions #cargo_declare and #cargo_store; or, more rarely, calls to #cargo_attach and #cargo_store. #cargo_declare defines the fields for a table of data, #cargo_store stores data within that table, and #cargo_attach specifies that a template stores its data to a table that has been defined elsewhere.

Declaring a table
A template that stores data in a table needs to also either declare that table, or "attach" itself to a table that is declared elsewhere. Since there is usually one table per template and vice versa, most templates that make use of Cargo will declare their own table. Declaring is done via the parser function #cargo_declare.

This function is called with the following syntax:

First, note that neither the table name nor field names can contain spaces; instead, you can use underscores, CamelCase, etc.

The field description must start with the type of the field, and in many cases it will simply be the type. The following types are predefined in Cargo:
 * Page - holds the name of a page in the wiki
 * String - holds standard, non-wikitext text
 * Text - holds standard, non-wikitext text; intended for longer values
 * Integer - holds an integer
 * Float - holds a real, i.e. non-integer, number
 * Date - holds a date without time
 * Datetime - holds a date and time
 * Boolean</tt> - holds a Boolean value, whose value should be 1 or 0, or 'yes' or 'no'
 * Coordinates</tt> - holds geographical coordinates
 * Wikitext</tt> - holds text that is meant to be parsed by the MediaWiki parser
 * Searchtext</tt> - holds text that can be searched on, using the MATCHES command
 * File</tt> - holds the name of an uploaded file or image in the wiki (similar to Page, but does not require specifying the "File:" namespace)
 * URL</tt> - holds a URL
 * Email</tt> - holds an email address

Any other type specified will simply be treated as type "String".

A field can also hold a list of any such type. To define such a list, the type value needs to look like "List (delimiter) of type". For example, to have a field called "Authors" that holds a list of string values separated by commas, you would have the following parameter in the #cargo_declare call:

|Authors=List of String

The description string can also have additional parameters; these all are enclosed within parentheses after the type identifier, and separated by semicolons. Current allowed parameters are:


 * size=</tt> - for fields of type "String" and "Text", sets the size of this field, i.e. the number of characters; for "Text", the default is 300
 * allowed values=</tt> - sets a field to be an "enumeration", i.e. having a finite set of allowed values, by defining the set of values, separated by commas. This is most commonly done for fields of type "String" or "Page".
 * link text=</tt> - for fields of type "URL", sets text that would be displayed as a link to that URL. By default the entire URL is shown.
 * hidden</tt> - takes no value. If set, the field is not listed in either Special:ViewTable or Special:Drilldown, although it is still queriable.

For example, to define a field called "Color" that has three allowed values, you could have the following declaration:

|Color=String (size=10;allowed values=Red,Blue,Yellow)


 * 1) cargo_declare also displays a link to the Special:ViewTable page for viewing the contents of this database table.

Attaching to a table
In some cases, you may want more than one template to store their data to the same Cargo table. In that case, only one of the templates should declare the table, while the others should simply "attach" themselves to that table, using the parser function #cargo_attach</tt>.

This function is called with the following syntax:

You do not actually need this call in order for a template to add rows to some table; a #cargo_store call placed anywhere, via a template or otherwise, will add a row to a table (assuming the call is valid). However, #cargo_attach lets you do the "Recreate data" action for that template - see "Creating or recreating data", below.

Storing data in a table
A template that declares a table or attaches itself to one should also store data in that table. This is done with the parser function #cargo_store</tt>. Unlike #cargo_declare</tt> and #cargo_attach</tt>, which apply to the template page itself and thus should go into the template's &lt;noinclude&gt; section, #cargo_store</tt> applies to each page that calls that template, and thus should go into the template's &lt;includeonly&gt; section.

This function is called with the following syntax:

The field names must match those in the <tt>#cargo_declare</tt> call elsewhere in the template.

The values will usually, but not always, be template parameters; but in theory they could hold anything.

Storing a recurring event
Special handling exists for storing recurring events, which are events that happen regularly, like birthdays or weekly meetings. For these, the parser function <tt>#recurring_event</tt> exists. It takes in a set of parameters for a recurring event (representing the start date, frequency etc.), and simply prints out a string holding a list of the dates for that event. It is meant to be called within <tt>#cargo_store</tt> (for a field defined as holding a list of dates), and <tt>#cargo_store</tt> will then store the data appropriately. <tt>#recurring_event</tt> is called with the following syntax:

Of these parameters, only "start=" and "unit=" are required.

By default, if no end date is set, or if the end date is too far in the future, <tt>#recurring_event</tt> stores 50 instances of the event. To change this, you can add a setting for <tt>$wgCargoRecurringEventMaxInstances</tt> in LocalSettings.php, under the inclusion of Cargo. For instance, to set the number to 100, you would add the following:

Example
You can see two templates that make use of #cargo_declare and #cargo_store here and here.

Creating or recreating a table
No data is actually generated or modified when a template page containing a #cargo_declare call is saved. Instead, the data must be created or recreated in a separate process. There are two ways to do this:

Web-based tab
From the template page, select the tab action called either "Create data" or "Recreate data". Upon selecting this action, and hitting "OK" in the page that shows up, the following will happen:


 * The existing Cargo table for that template will be dropped (if it existed before).
 * A new version of the table will be created.
 * Every page that includes a call to that template (and thus a call to #cargo_store) will have its #cargo_store call(s) "activated", in order to resave those row(s) to the table.
 * If there are any other templates that are defined as adding to that same table via #cargo_attach, they too will get their #cargo_store call(s) "activated".

The last two processes are done through MediaWiki jobs, and depending on your MediaWiki version and configuration, they may require a call to MediaWiki's runJobs.php script to occur.

If any templates contain #cargo_attach, they too will get a "Create data" or "Recreate data" tab. If this tab is selected and activated, it will not drop and recreate the database table itself; instead, it will only recreate those rows in the table that came from pages that call that template.

The ability to create/recreate data is available to users with the 'recreatecargodata' permission, which by default is given to sysops. You can give this permission to other users; for instance, to have a new user group, 'cargoadmin', with this ability, you would just need to add the following to LocalSettings.php:

Once a table exists for a template, any page that contains one or more calls to that template will have its data in that table refreshed whenever it is resaved; and new pages that contain call(s) to that template will get their data added in when the pages are created.

Command-line script
If you have access to the command line, you can also recreate the data by calling the script cargoRecreateData.php, located in Cargo's /maintenance directory. It can be called in one of two ways:
 * - recreates the data for all Cargo tables in the system
 * - recreates the data for the one specified Cargo table.

In addition, the script can be called with the  flag, which turns off all printouts.

Storing page data
You can create an additional Cargo table that holds "page data": data specific to each page in the wiki, not related to infobox data. This data can then be queried either on its own or joined with one or more "regular" Cargo tables. The table is named "_pageData", and it holds one row for every page in the wiki. You must specify the set of fields you want the table to store; by default it will only hold the five standard Cargo fields, like _pageName (see Database storage details). To include additional fields, add to the array $wgCargoPageDataColumns in LocalSettings.php, below the line that installs Cargo.

Currently there are five more fields that can be added to the _pageData table; here are the five fields, and the call to add each one:
 * <tt>_creationDate</tt> - the date the page was created:
 * <tt>_modificationDate</tt> - the date the page was last modified:
 * <tt>_creator</tt> - the username of the user who created the page:
 * <tt>_fullText</tt> - the (searchable) full text of the page:
 * <tt>_categories</tt> - the categories of the page (a list, queriable using "HOLDS"):
 * <tt>_numRevisions</tt> - the number of edits this page has had:

Once you have specified which fields you want the table to hold, go to the Cargo /maintenance directory, and make the following call to create, or recreate, the _pageData table:

If you want to get rid of this table, call the following instead:

You do not need to call the "--delete" option if you are planning to recreate the table; simply calling setCargoPageData.php will delete the previous version.

Storing file data
Similarly to page data, you can also automatically store data for each uploaded file. This data gets put in a table called "_fileData", which holds one row for each file. This table again has its own settings array, to specify which columns should be stored, called $wgCargoPageDataColumns.

There are currently three columns that can be set:
 * <tt>'_mediaType'</tt> - the media type, or MIME type, of each file, like "image/png":
 * <tt>'_path'</tt> - the directory path of the file on the wiki's server:
 * <tt>'_fullText'</tt> - the full text of the file; this is only stored for PDF files:

To store the full text of PDF files, you need to have the pdftotext utility installed on the server, and then add the following to LocalSettings.php:

pdftotext is available as part of several different packages. if you have the PdfHandler extension installed (and working), you may have pdftotext installed already.

Database storage details
When the data for a template is created or recreated, a database table is created in the Cargo database that (usually) has one column for each specified field. This table will additionally hold the following columns:


 * <tt>_pageName</tt> - holds the name of the page from which this row of values was stored.
 * <tt>_pageTitle</tt> - similar to <tt>_pageName</tt>, but leaves out the namespace, if there is one.
 * <tt>_pageNamespace</tt> - holds the numerical ID of the namespace of the page from which this row of values was stored.
 * <tt>_pageID</tt> - holds the internal MediaWiki ID for that page.
 * <tt>_ID</tt> - holds a unique ID for this row.

Storage of lists
For fields that have lists of values, the handling is more complex: a whole separate database table is created to hold all the individual values for this field. This table will get the name "MainTableName__FieldName" (e.g. "Books__Authors"), and it will have the following fields:


 * <tt>_rowID</tt> - holds the ID of the row (i.e., _ID) in the main table that this value corresponds to.
 * <tt>_value</tt> - holds the actual, individual value.

So if an "Authors" field contained three values, the "Books__Authors" table would have three rows corresponding to that one page.

There's one more complication for list fields: the corresponding field for a list field in the the database table will not actually be given that name, but will rather be called "FieldName__full", e.g. "Authors__full". This is to enable the "true" field name to serve as a "virtual" field within the #cargo_query call, to make querying on the field values table easier (see 'The "HOLDS" command').

Storage of coordinates
For fields of type 'Coordinates', like for fields that hold a list of values, no database field is created with the actual specified field name. Instead, the following three fields are created:


 * fieldName__full - holds the coordinates as written in the page
 * fieldName__lat - holds the latitude from the coordinates, as a float
 * fieldName__lon - holds the longitude from the coordinates, as a float

If the coordinates cannot be parsed, the "__full" field still gets the value, but the "__lat" and "__lon" fields are set to null.

Storage of dates
For fields of type 'Date' or 'Datetime', an extra field is created that is named "fieldName__precision". It holds an integer value representing the "precision" of each date value, i.e. whether it holds a full date, only a year, etc. The possible values are:
 * 0 - date and time (can only occur for 'Datetime' fields)
 * 1 - date only
 * 2 - year and month only
 * 3 - year only