A Configuration array snippet is the basic building block of a Cliqon system. The array snippet is expressed in plain text TOML format and is stored within a Cliqon system as either database record or a physical config file (a file with a .cfg extension). A developer will tend to have a set of the original development configuration files to hand when developing a new system but will copy or transfer these to the database before publishing a production system.


When Cliqon configuration files or records are parsed by the Config or Toml Classes, multi-dimensional arrays are produced. These arrays are used by every element of a Cliqon system database access strings, forms, reports and display screens.


Cliqon configuration records can operate at up to three levels. We call the three levels, Services, Collections and Models. Configuration records cascade from the general to the specific. Like CSS Style commands the child values augment or override the parent values.


The concept of a service configuration record describes a facility such as a Datagrid, Datalist, Calendar, an administrative or main web site Menu, a Report or Siteupdate.


The concept of a collection record describes a Cliqon table or database schema. It contains information about the fields of the table and array snippets for any services that the table might need to enter, manipulate, process and display data.


The concept of a model record describes a table type schema. It contains specific information about how a particular service is configured for a given tabletype.


Although the way that Cliqon is divided into Collections and Models is explained in greater detail in the next sections, it is important to summarise the distinction here so that the two paragraphs above make sense. Most older frameworks and traditional web applications utilise a database table schema for every possible activity in the system. Displayed is a schema for a modern Wordpress. Whilst it has been refined over the years, it still treats Posts and Comments as discrete tables. Cliqon does not have such a division. As a general statement, the seven tables of a basic or standard Cliqon system are grouped into two – front-facing: dbitem and dbarchive, administrative: dbcollection, dbsession, dblog, dbuser and dbindex. Alternativel, one can group them by purpose – single or multi purpose. Tables dbcollection, dbitem are multi-purpose and the rest are single purpose. When we use the concept of multi-purpose, we mean that the table contains different models or table types. The dbitem table contains models for news, sections, components, library, events, image references, and useful links. There are a series of columns which specified tasks such as placing the records of a given menu subtree into an order or providing access control parameters for the record. As a general rule the multi-lingual content for any record is stored in JSON format in one field / column.


We contend that using this mechanism to define table data makes a Cliqon system extremely flexible. An additional column of content can be configured in a configuration record and because Cliqon uses an ORM, the new data field will automatically be included after the cache has been deleted and the new process first used.    

TOML

The letters TOML stands for Tom’s Obvious, Minimal Language. It has been developed by Tom Preston-Werner (former CEO of Github). For more information please visit https://github.com/toml-lang/toml/.


TOML aims to be a minimal configuration file format that's easy to read due to obvious semantics. TOML is designed to map unambiguously to a hash table. TOML should be easy to parse into data structures in a wide variety of languages. In some ways TOML is very similar to JSON: simple, well-specified, and maps easily to ubiquitous data types. JSON is great for serializing data that will mostly be read and written by computer programs. Where TOML differs from JSON is its emphasis on being easy for humans to read and write. Comments are a good example: they serve no purpose when data is being sent from one program to another, but are very helpful in a configuration file that may be edited by hand.


Cliqon includes two Classes for handling TOML files. We provide a standard 3rd party Toml Class and we also have a modified version for the use of Cliqon, which is the Config Class.

The Basics


The basic form is key = value


# Comments start with hash or a semi-colon ;

foo = "strings are in quotes and are always UTF8 with escape codes: \n \u00E9"


bar = """multi-line strings

use three quotes"""


baz = 'literal\strings\use\single\quotes'


bat = '''multiline\literals\use

three\quotes'''


int = 5 # integers are just numbers

float = 5.0 # floats have a decimal point with numbers on both sides


date = 2006-05-27T07:32:00Z # dates are ISO 8601 full zulu form


bool = true # good old true and false

Lists

Lists (arrays) are signified with brackets and delimited with commas. Only primitives are allowed in this form, though you may have nested lists. The format is forgiving, ignoring whitespace and newlines, and yes, the last comma is optional (thank you!):


foo = [ "bar", "baz"

       "bat"

]


nums = [ 1, 2, ]


nested = [[ "a", "b"], [1, 2]]

Arrays and Tables

Foo and bar are keys in the table called table_name. Tables have to be at the end of the config file. Why? because there’s no end delimiter. All keys under a table declaration are associated with that table, until a new table is declared or the end of the file. So declaring two tables looks like this:


# some config above

[table1]

foo = 1

bar = 2


[table2]

       foo = 1

       baz = 2


The declaration of table2 defines where table1 ends. Note that you can indent the values if you want, or not. TOML doesn’t care.


If you want nested tables, you can do that, too. It looks like this:


[table1]

       foo = "bar"


[table1.nested_table]

       baz = "bat"


nested_table is defined as a value in table1 because its name starts with table1.. Again, the table goes until the next table definition, so baz="bat" is a value in table1.nested_table. You can indent the nested table to make it more obvious, but again, all whitespace is optional:


[table1]

       foo = "bar"


       [table1.nested_table]

               baz = "bat"


This is equivalent to the JSON:


{

       "table1" : {

               "foo" : "bar",

               "nested_table" : {

                       "baz" : "bat"

               }

       }

}


Having to retype the parent table name for each sub-table is kind of annoying, but I do like that it is very explicit. It also means that ordering and indenting and delimiters don’t matter. You don’t have to declare parent tables if they’re empty, so you can do something like this:


[foo.bar.baz]

bat = "hi"


Which is the equivalent to this JSON:


{

       "foo" : {

               "bar" : {

                       "baz" : {

                               "bat" : "hi"

                       }

               }

       }

}

Array of elements in a table

The last thing is arrays of tables, which are declared with double brackets thusly:


[[comments]]

author = "Nate"

text = "Great Article!"


[[comments]]

author = "Anonymous"

text = "Love it!"


This is equivalent to the JSON:


{

       "comments" : [

               {

                       "author" : "Nate",

                       "text" : Great Article!"

               },

               {

                       "author" : "Anonymous",

                       "text" : Love It!"

               }

       ]

}


Arrays of tables inside another table get combined in the way you’d expect, like [[table1.array]].


TOML is very permissive here. Because all tables have very explicitly defined parentage, the order they’re defined in doesn’t matter. You can have tables (and entries in an array of tables) in whatever order you want. This is totally acceptable:


[[comments]]

author = "Anonymous"

text = "Love it!"


[foo.bar.baz]

bat = "hi"


[foo.bar]

howdy = "neighbour"


[[comments]]

author = "Anonymous"

text = "Love it!"


Of course, it generally makes sense to actually order things in a more organized fashion, but it’s nice that you can’t shoot yourself in the foot if you reorder things “incorrectly”.

Using Cliqon configuration records

In the previous sections we have described what Cliqon configuration files are, what they are used for and that they are plain text and written in TOML format.


The content of a generated array is usually consumed by a Cliqon facility. We divide Cliqon facilities into three groups:


  • data input – the process of entering information into a Cliqon system using forms and data import routines
  • data manipulation – a standard Cliqon system when used to manage the content for a presentational website, does not do a great deal of data manipulation, but when Cliqon is used as a eCommerce system, then the processing of stock, orders and invoicing would constitute data-manipulation
  • data-output – the processes of retrieving information from the system in the form of displays, reports and downloads


Most of these activities are made available by the processing of a PHP script in a Class and its Methods. Most standard Cliqon derived classes are stored in two subdirectories - /framework/app and /framework/core. As an example, most of the functions related to the Administration system exist as methods within the Admin Class, which is in /framework/app. However for completeness of explanation, it should be noted that obvious shared functions such as responding to a Posted form, is undertaken by a Core function, in this case Method::postForm() within Class Db, which is located in /framework/core.


The Core Class entitled Model and the method contained therein, called stdModel(), is the primary vehicle for consuming configuration files and this Method will be found throughout most Classes and Methods of the system. The stdModel method, takes three arguments – the name of the service, the name of the collection and finally, the name of the model. The Method attempts to read a Cached version of the configuration first, then the three sources of configuration information from the database and if database record is absent, then a configuration file from the file system. If no Cached version existed, one is created at this time.


Finally, we state that stdModel takes 3 arguments. This is true but within the Method, the array snippet entitled “common” is read from every file / record.


Cascading

If you understand how the three elements of the Model can be made to cascade, one over the other, then please ignore this explanation. However the process of cascade is so fundamental to the operation of a web site that it bears repetition.


Cliqon provides Class → Config and inside it a Method entitled cfgReadString() which takes a string of characters in TOML format derived by some mechanism – read from a file on the file system or read from a database record.


When we callMethod stdModel(), we include three arguments – Service, Collection, Model. The Model may be an empty string. So arguments might look like $args = datagrid, dbcollection, string or $args = datagrid, dbuser, ‘’.


Method stdModel() will return an array which will contain a multi-dimensional array consisting of the following sections:


common => [

       key1 => value3,

       key2 => value2,

],

service => [

       key1 => value1,

       key2 => value3,

]



The Services record provided:


service => [

       key1 => value1

]


The Collection record provided:


common => [

       key1 => value1

],

service => [

       key2 => value3,

]


The Model record provided:


common => [

       key1 => value3,

       key2 => value2,

]


Inside Method stdModel(), Cliqon uses function() array_replace_recursive. This is a standard PHP function which W3Schools desxcribes as:


If a key from array1 exists in array2, values from array1 will be replaced by the values from array2. If the key only exists in array1, it will be left as it is. If a key exist in array2 and not in array1, it will be created in array1. If multiple arrays are used, values from later arrays will overwrite the previous ones.


Thanks to the Javascript library PHPJS, array_replace_recursive also exists as function in the Cliqon javascript library and is used extensively in the definition of popup windows and alerts.


Created with the Personal Edition of HelpNDoc: Create help files for the Qt Help Framework