Configuration¶
All configuration in FreeField is stored in includes/userdata/config.json and
managed using the Config
class. To import the Config
class for usage in
a script, the following should be placed at the top of the script file:
require_once("../includes/lib/global.php");
__require("config");
Settings are defined in the defs.php file. An example entry may look like this:
/*
The default zoom level of the map.
*/
"map/default/zoom" => array(
"domain" => "map",
"section" => "default",
"default" => 14.0,
"option" => new FloatOption(0.0, 20.0)
),
The key of the array element is the path to the setting in the configuration file, and should be placed such that is grouped with other similar/related settings.
To retrieve a value from a setting, use
Config::get("path/to/setting")->value()
. Storing a setting is always handled
using the administration pages, and should never be saved directly from
code. For completeness of the documentation, however, it should be stated that
the function to manually save configuration is Config::set()
, taking, at
minimum, an argument that is an associative array of the form
"path/to/setting" => value
. Please see commentary for the Config::set()
function before you ever use this to learn more about how it works and the
meaning of arguments that are passed to it.
Danger
Never use ->value()
as part of output! See Security in FreeField for
information on ->valueHTML()
and other functions that should be
used instead for output in order to prevent security/XSS
vulnerabilities.
Internationalization¶
All setting strings are internationalized. Setting names are assigned the key
setting.<path>.name
, and descriptions helping the user understand the
purpose of each setting are setting.<path>.desc
, where <path>
is the
path from the key of the setting array with slashes /
converted to dots
.
and dashes -
converted to underscores _
. For example,
map/default/zoom
are assigned the internationalization tokens
setting.map.default.zoom.name
for its label and
setting.map.default.zoom.desc
for its description. Please see Internationalization
for more information.
Domains and sections¶
Every setting in FreeField has an associated domain and section under which it should be displayed. The domain is the sub-page of the administration pages where the setting should appear. That page is further denominated by various headers called sections, which are groupings of similar or related settings. For example, the setting “Zoom level,” defining the default zoom level when viewing the map, is organized under the “Defaults” section of the “Map settings” domain.
Adding new domains¶
Domains always have a label (page title) and a short description (subtitle).
These must be added to the localization files under the tokens
admin.domain.<domain>.name
and admin.domain.<domain>.desc
respectively.
There are two types of domains; standard and custom domains. Standard
domains have all their settings stored in the configuration definitions file
defs.php, and will render these on the page. Custom domains are not from
defs.php, but are instead rendered from custom output files
includes/admin/<domain>.php. For
example. the users
domain does not refer to or host any settings in
defs.php, but instead renders a list of all users of the FreeField instance in
the database. This logic is handled in users.php,
which is include
’d to the administration page upon page load. If you are
adding a new domain for usage wthin defs.php, use the standard domain type
rather than custom domain.
The domain you are adding must be listed in the Config::listDomains()
function. An example of such an entry:
// Map provider settings (e.g. map API keys)
"map" => array(
"icon" => "map",
"custom-handler" => false
),
custom-handler
should be set to true
if you are adding a custom page, or
false
if you are adding a standard domain. map
corresponds to a
FontAwesome icon that should represent the domain the administration pages
sidebar.
When adding a new domain, you must also add a domain access permission setting to defs.php to restrict access to the domain by default. This permission looks like this:
"permissions/level/admin/{$domain}/general" => array(
"domain" => "perms",
"section" => "admin",
"default" => PermissionOption::LEVEL_ADMIN,
"option" => new PermissionOption()
),
Make sure to select a default permission level that is appropriate to the types of settings you are adding.
Tip
This commit contains an example of the “Mobile” domain being added to FreeField, along with its associated functionality and settings. You can use this as a rough template on how to implement a new domain.
Adding new sections¶
Like domains, sections always have a label (section header), though a
description is optional. Labels use the internationalization token
admin.section.<domain>.<section>.name
where <domain>
is the parent
domain of the section.
Note
Sections are not added to custom-type domains - they are declared directly within the includes/admin/<domain>.php output file, but they should still follow the general internationalization conventions as other settings.
A section will have a description if, and only if, the section has an entry in
the SECTIONS_WITH_DESCRIPTIONS
array in config.php. Please see the
commentary for that array to learn how to add descriptions to sections.
When adding a new section, you must also add a section access permission setting to defs.php to restrict access to the section by default. This permission looks like this:
"permissions/level/admin/{$domain}/section/{$section}" => array(
"domain" => "perms",
"section" => "admin",
"indentation" => 1,
"default" => PermissionOption::LEVEL_ADMIN,
"option" => new PermissionOption()
),
Make sure to select a default permission level that is appropriate to the types of settings that are manageable under this section.
Options and data types¶
Every setting is of a certain option type. Available options are declared in types.php. The option type declares the type of data that is stored for the setting, and provides parsing, storage and validation functions specific to that option type. Instructions on implementing new options are available as commentary at the top of that file.
Available option types¶
This is a list of all available option types in FreeField. Please add any new options you add to this list.
StringOption
¶
For storing short strings. Can be initialized with an optional regular expressions pattern via the constructor, which, if specified, will reject all strings that do not match this pattern as invalid.
Valid initializers¶
// Accept any string:
"option" => new StringOption()
// Using regex to e.g. only accept strings without spaces:
"option" => new StringOption('^[^\s]+$')
Valid defaults¶
Any string, matching the regex if provided.
ParagraphOption
¶
For storing longer strings. Can optionally be initialized with the string
"md"
to display a live Markdown preview.
Valid initializers¶
// Plain-text paragraph input:
"option" => new ParagraphOption()
// Paragraph input with Markdown preview:
"option" => new ParagraphOption("md")
Valid defaults¶
Any string.
PasswordOption
¶
For storing passwords and other sensitive data. Stored in encrypted form in the configuration file to prevent data leakage from misconfigured HTTP servers.
Potentially unexpected behavior
This option cannot store the string oqXb_&WkMrdHtRZ_@}qBM=?WheuO6Y
. This
string is subject to change in the future. The reason is that this string is
returned in lieu of the actual string in the configuration page when echoed
to the page to give the user a visual impression that it is set to an
existing value, as it will fill the input box with black dots. If this string
is returned from the browser, it indicates that the input was not changed by
the user, and is thus discarded.
Valid initializers¶
"option" => new PasswordOption()
Valid defaults¶
An empty string.
BooleanOption
¶
For storing boolean values; displayed as a checkbox with a separate label next to it.
Attention
This option requires that an additional internationalization
token is declared for the label, i.e. setting.<path>.<label>
.
This string is displayed next to the checkbox.
Valid initializers¶
"option" => new BooleanOption()
Valid defaults¶
true
or false
.
IntegerOption
¶
For storing integers. Can be initialized with optional minimum and maximum values (both inclusive).
Valid initializers¶
// Accept any integer:
"option" => new IntegerOption()
// Accept an integer with a certain mininum value (e.g. 10):
"option" => new IntegerOption(10)
// Accept any integer up to a certain maximum value (e.g. 20):
"option" => new IntegerOption(null, 20)
// Accept any integer in a range from a minimum to a maximum value:
"option" => new IntegerOption(10, 20)
Valid defaults¶
Any integer, within the range if provided.
FloatOption
¶
Similar to IntegerOption
, but allows storing floating-point/decimal numbers.
Can be initialized with optional minimum and maximum values (both inclusive).
Valid initializers¶
// Accept any number:
"option" => new FloatOption()
// Accept a number with a certain mininum value (e.g. 10):
"option" => new FloatOption(10.0)
// Accept any number up to a certain maximum value (e.g. 20):
"option" => new FloatOption(null, 20.0)
// Accept any number in a range from a minimum to a maximum value:
"option" => new FloatOption(10.0, 20.0)
Valid defaults¶
Any floating-point/decimal number, within the range if provided.
GeofenceOption
¶
For selecting and storing references to a particular geofence, as defined by the user on the geofencing section of the administration pages; see Geofencing.
Running ->value()
on settings of this option type will return a Geofence
object instance, or null
if set to “<none>” or invalid. See geo.php for
implementation and usage details.
Valid initializers¶
"option" => new GeofenceOption()
Valid defaults¶
null
.
SelectOption
¶
For storing one value from a list of selectable valid values. Must be initialized with an array of items and an optional data type (“string” or “int”; default is “string”).
Attention
This option requires additional internationalization tokens for
each of the options in the supplied items array, i.e.
setting.<path>.option.<option>
. Internationalization can be
suppressed by passing true
to the third parameter of the
constructor of this option, though this is strongly recommended
against unless there is a legitimate need to have unlocalized
elements in the selection box.
Valid initializers¶
// Accept any item from given list of items:
"option" => new SelectOption(array("one", "two", "three"))
// Specify element data type:
"option" => new SelectOption(array(24, 48, 72), "int")
Valid defaults¶
Any element in the provided list of options, e.g. "one"
for the first example
above, or 72
for the second example.
PermissionOption
¶
For selecting a user group; see Permissions and groups for more information. Renders as a selection box of all available groups in the FreeField installation.
Valid initializers¶
"option" => new PermissionOption()
Valid defaults¶
Any one of the following:
PermissionOption::LEVEL_HOST
PermissionOption::LEVEL_ADMIN
PermissionOption::LEVEL_MODERATOR
PermissionOption::LEVEL_SUBMITTER
PermissionOption::LEVEL_REGISTERED
PermissionOption::LEVEL_READ_ONLY
PermissionOption::LEVEL_ANONYMOUS
IconSetOption
¶
For selecting an installed set of Map markers. Renders as a selection box of all available marker sets in the FreeField installation. An option for “default marker set” can be added to this selection box by passing an internationalization token as argument to the constructor to indicate a string that should be displayed to label the default option. If this is not passed, no default option is provided to the user.
A preview box is displayed for the selected icon set at all times. If a default option is selected, no preview is displayed, and an empty string will be returned from this option type.
Valid initializers¶
// Standard marker set selection box with no "Default" option:
"option" => new IconSetOption()
// Selection box with a default option denoted by an I18N display label:
"option" => new IconSetOption("setting.path_to_setting.option.default")
Valid defaults¶
A globally available icon set, i.e. only "freefield-3d-compass"
is currently
permitted.
FileOption
¶
For uploading files to FreeField as part of the configuration. Used for e.g. the favicon. Uploaded files are stored in includes/userdata/files. The path of the setting this option is used for must be passed as the first argument. An optional array of file types and extensions can be passed, along with a maximum file size.
Running ->value()
on settings of this option type will return a
FileOptionValue
object instance. This class is declared in types.php and has
the following methods:
// The following basic file-I/O functions exist:
getExtension() // Returns e.g. ".jpg"
getFilename() // Returns local filename, e.g. "path.to.setting.png"
getUploadName() // Returns origin filename, e.g. "My awesome image.png"
getPath() // Returns local file path, e.g. "/var/html/path.to.setting.png"
getMimeType() // Returns MIME type, e.g. "image/png"
getLength() // Returns file size in bytes
getUploadTime() // Returns UNIX timestamp of time and date file was last changed
// In addition, the following functions exist to provide file integrity:
getHexEncodedSHA256() // Returns hexadecimal-encoded SHA256 hash of file
getBase64EncodedSHA256() // Returns base64-encoded SHA256 hash of file
// Finally, the following functions exist to read the file:
outputWithCaching() // Sets caching headers, echoes file, then terminates
getDataURI() // Returns file as a base64-encoded data URI
Valid initializers¶
// Accept any file
"path/to/setting" => array(
/* ... other fields ... */
"option" => new FileOption(
"path/to/setting"
)
),
// Accept only image files:
"path/to/setting" => array(
/* ... other fields ... */
"option" => new FileOption(
"path/to/setting",
array(
// This array is of format MIME type => default file extension.
"image/png" => "png",
"image/gif" => "gif",
"image/jpeg" => "jpg"
)
)
),
// Accept any file up to 256 KiB:
"path/to/setting" => array(
/* ... other fields ... */
"option" => new FileOption(
"path/to/setting",
null,
256 * 1024
)
),
// Accept only image files, and only up to 256 KiB:
"path/to/setting" => array(
/* ... other fields ... */
"option" => new FileOption(
"path/to/setting",
array(
// This array is of format MIME type => default file extension.
"image/png" => "png",
"image/gif" => "gif",
"image/jpeg" => "jpg"
), 256 * 1024 // Max 256 KiB
)
),
Valid defaults¶
An array of the following format:
"default" => array(
"type" => "image/png",
"name" => "default-file-name.png",
"size" => 2044,
"sha256" => "0a330b612466ea389359db56ce93f2a5faaa89359087926335c7bcab45b539e4"
)
The default file must be placed in this directory.
The filename must match the setting path with slashes /
converted to dots
.
. The size and SHA-256 hash of the file must be included in the default
array as indicated in the example above.
ColorOption
¶
For selecting and storing an RGB color value. Displayed as a color picker, with indicators for the current values of the red, green and blue color channels for the selected color.
Valid initializers¶
"option" => new ColorOption()
Valid defaults¶
A hexadecimal color code string in the format #rrggbb
.