Extension:JsonConfig

The JsonConfig extension allows other extensions to store their configuration data as a JSON blob in a wiki page.

Available features and usage patterns

 * You may use JsonConfig to store data in a number of ways:


 * in a single configuration page, e.g. a number of settings for your extension in Config:MyExtSettings (  is the default namespace associated with the JsonConfig extension);


 * in a set of pages with similar structure residing in their own namespace, e.g. IP addresses of known proxies or event log schemas named "Proxy:Opera", or schemas named 1>meta:Schema:AccountCreation|Schema:AccountCreation


 * using it only for pages whose titles match a regex pattern, e.g. Config:Proxy:Opera or Config:Opera.proxy. This avoids filling a wiki with lots of namespaces, one for each content model.


 * You may provide a content class to do data validation (beyond valid JSON) and normalization.


 * You may provide a view class to customize HTML display.


 * You can store data:


 * "one-per-wiki", "one-per-cluster", or even one per some "family" (different structure of the caching key for shared memcached);


 * in a public or private wiki and accessed with credentials;


 * in a separate cluster, and do remote notification when changed.

Current

 * Commons tabular data sets
 * Commons map data sets
 * Dashiki dashboard configurations
 * Others?

Past

 * Wikipedia Zero operator configurations (see Extension:ZeroBanner)

This variable defines profiles for each type of configuration pages.   is an associative array of arrays, with each sub-array having zero or more of the following parameters. By default, JsonConfig uses the string key as the model ID that this profile represents, but in case you want to reuse the same model ID in more than one profile, you can override it with the   parameter.

This variable defines which custom content class will handle which Model ID. More than one Model ID may be handled by the same content class. All content classes must derive from the  </> class; if the modelID maps to <tvar|2> </>, then the default <tvar|1> </> class handles the model ID.

Example:

If you implement a separate class to do HTML rendering, you can specify your config model as an array with an extra <tvar|1> </> class:

Hello World
The simplest case is a single configuration page without any validation, stored locally on each wiki. Just add these settings to <tvar|1>LocalSettings.php</>

The above enables namespace "Config" on the local wiki, but only allows the "Config:MySettings" page to be created, not any other page in that namespace. You can store well-formed JSON data in the page.

To read the MySettings data in PHP, use a <tvar|1> </> object to access the page, then request its content:

Multiple configs shared in a cluster
Lets say we decide to store the trusted proxies' IPs as "Config:Proxy:SomeName" pages on Meta-Wiki and share this data with the cluster.

If instead you want to dedicate a separate namespace to proxies, the parameters would change to:

Validation
Most of the time one would also want a custom content class with its own validation. JSON pages are handled by the content classes which derive from <tvar|1> </>. The content class is responsible for parsing and validating raw text. <tvar|1> </> does not do any validation beyond JSON parsing, but you may choose to derive from it and override <tvar|2> </>. Better yet, you may derive from the <tvar|1> </> class which provides a number of validation primitives, and only override <tvar|2> </>.

For the sake of this documentation, let's presume that the proxy config page describing Opera Mini servers has this format:

Here is the content class to validate that data.

Customizing behavior on the storage wiki
You may also want to customize viewing and page creation on the storage wiki (Meta-Wiki in the above example). There are two ways to do this: inside your <tvar|1> </>-derived class, or via a separate "view" class that derives from <tvar|2> </>. The second approach is preferable as it cleanly separates the architecture and the view class need only exist in the storage wiki (e.g. Meta-Wiki), not on all the wikis that use the data.

To override default value in <tvar|1> </>-derived class, override the constructor and set the <tvar|2> </> value to the new default if it came in as NULL before passing it to the parent constructor. To override the HTML generation, override <tvar|1> </>.

With the recommended way, create a view class that derives from <tvar|1> </> or a more feature-rich <tvar|2> </>. For <tvar|1> </>, you will need to implement <tvar|2> </> and <tvar|3> </>. By default, the view is implemented by the <tvar|1> </> class, which can also be used as a customizable base if you just need minor adjustments to the way it looks.

Best practices

 * Extensions that use JsonConfig should add their configurations to the <tvar|1> </> and <tvar|2> </> in the main extension file.
 * If you share config data among multiple wikis, document the key name used in <tvar|1> </>, and initialize the 'store' / 'remote' section in <tvar|2> </>. This is better than introducing a number of global variables that duplicate the config functionality.  See for example Wikimedia's configuration of the 1>Special:MyLanguage/Extension:Graph</>|Graph extension across multiple wikis (although that uses complex multi-wiki setup rather than simple config variables).

Implemented features

 * JSON parsing converts JSON text into either an array or an object
 * Visualization shows JSON as an easy to view table rather than code, with some extra highlighting. For example if the value is not provided and a default is used, it is shown in gray, or when the value is the same as default, it shows as purple.  For example, see this and this.
 * 1>Special:MyLanguage/Extension:CodeEditor</>|Code Editor simplifies JSON editing
 * Custom Validation performs complex checks such as checking that the value is in the proper format or that a user ID exists.
 * MemCached caching stores json blobs in memcached under custom keys and expiration policies, and resets them on save.
 * Flagged Revisions support allows configurations to be marked as "reviewed" before going into production
 * Localization of most basic interface elements has been done in many languages, and it would reduce translation work if most common messages would be done just once in one place.

Unimplemented nice-to-haves
These features would be desirable to more than one type of configs:
 * Schema validator - Validate against JSON Schema, as most extensions might not need complex validation rules, or might want to combine schema plus extra validation.
 * Custom editor - Zero team has been thinking about implementing a more complex editor, possibly based on JSON Schema.
 * API query support - Allow config pages to be returned as regular API results in all formats - json/xml/... instead of text blobs:
 * Localization - it would be good to be able to show localized descriptions for each configuration key
 * Localization - it would be good to be able to show localized descriptions for each configuration key

External access
The stored configuration data may frequently be needed by some external agent such as JavaScript, bot, or other programs. JavaScript could use either JSONP to access needed data by calling standard <tvar|1> </> API, or we could develop a forwarding service if CORS is unavailable. Extension authors may choose to add their own API modules to provide domain-specific information. Lastly, the <tvar|1> </> Query API parameter would return JSON data as part of the API result, not as a text blob that <tvar|2> </> would return.