Customizing MantisBT
Custom Fields
Overview
Different teams typically like to capture different information
as users report issues, in some cases, the data required is even
different from one project to another. Hence, MantisBT provides the
ability for managers and administrators to define custom fields as way
to extend MantisBT to deal with information that is specific to their
teams or their projects. The aim is for this to keep MantisBT native
fields to a minimum.
Following are some facts about the implementation of
custom fields in MantisBT:
Custom fields are defined system wide.
Custom fields can be linked to multiple
projects.
The sequence of displaying custom fields can be different
per project.
Custom fields must be defined by users with access level
ADMINISTRATOR.
Custom fields can be linked to projects by users with
access level MANAGER or above (by default, this can be
configurable).
Number of custom fields is not restricted.
Users can define filters that include custom fields.
Custom fields can be included in View Issues, Print
Issues, and CSV exports.
Enumeration custom fields can have a set of static
values or values that are calculated dynamically based on
a custom function.
Custom Field Definition
The definition of a custom field includes the following logical
attributes:
Caption variable name (eg: This is the value that is
supplied to lang_get() API, or displayed as-is if not found in
language file). This should not include any space or
any character that would be an invalid PHP identifier.
Custom field type (string, numeric, float,
enumeration, email, checkbox, radio, list, multi-selection list, date).
Type 'string' is used for strings of up to 255 characters.
Type 'numeric' is used for numerical integer values.
Type 'float' is used for real (float / double) numbers.
Type 'enumeration' is used when a user selects one entry from a list. The user interface for such type is a combo-box.
Type 'email' is used for storing email addresses.
Type 'checkbox' is like enumeration but the list is shown as checkboxes and the user is allowed to tick more than one selection. The default value and the possible value can contain multiple values like 'RED|YELLOW|BLUE' (without the single quote).
Type 'radio' is like enumeration but the list is shown as radio buttons and th euser is allowed to tick on of the options. The possible values can be 'RED|YELLOW|BLUE', where the default value can be 'YELLOW'. Note that the default value can't contain multiple values.
Type 'list' is like enumeration but the list is shown as a list box where the user is only allowed to select one option. The possible values can be 'RED|YELLOW|BLUE', where the default value can be 'YELLOW'. Note that the default value can't contain multiple values.
Type 'multi-selection list' is like enumeration but the list is shown as a list box where the user is allowed to select multiple options. The possible values can be 'RED|YELLOW|BLUE', where the default value can be 'RED|BLUE'. Note that in this case the default value contains multiple values.
Type 'date' is for date values. The default value can be empty, or {tomorrow}, {yesterday}, {next week}, {last week}, {+3 days}, {-2 days}.
Enumeration possible values (eg: RED|YELLOW|BLUE).
Use the pipe ('|') character to separate possible values for an
enumeration. One of the possible values can be an
empty string. The set of possible values can also be
calculated at runtime. For example, "=versions" would
automatically resolve into all the versions defined
for the current project.
Default value - see details above for a sample default value for each type.
Minimum/maximum length for the custom field value (use 0
to disable). Note that these metrics are not really relevant to custom fields that are based on an enumeration of possible values.
Regular expression to use for validating user input (use PCRE syntax).
Read Access level: Minimum access level for users to be
able to see the value of the custom field.
Write Access level: Minimum access level for users to be
able to edit the value of the custom field.
Display when reporting issues? - If this custom
field should be shown on the Report Issue page.
Display when updating issues? - If this custom
field should be shown on the Update Issue page.
Display when resolving issues? - If this custom
field should be shown when resolving an issue. For
example, a "root cause" custom field would make sense to
set when resolving the issue.
Display when closing issues? - If this custom
field should be shown when closing an issue.
Required on Report - If this custom
field is a mandatory field on the Report Issue page.
Required on Update - If this custom
field is a mandatory field on the Update Issue page.
Required on Resolve - If this custom
field is a mandatory field when resolving an issue.
Required on Close - If this custom
field is a mandatory field when closing an issue.
All custom fields are currently saved to a field of type
VARCHAR(255) in the database. However, in future releases, it is
possible to support custom fields of different types (eg: memo,
file).
If the value of a custom field for a certain defect is not found,
the default value is assumed.
Adding/Editing Custom Fields
The logged in user needs $g_manage_custom_fields_threshold
access level.
Select "Manage" from the main menu.
Select "Manage Custom Fields" from the management
menu.
In case of edit, click on the name of an existing
custom field to edit its information.
In case of adding a new one, enter the name of the
new custom field then click "New Custom Field".
Added custom fields will not show up in any of the issues
until the added custom field is linked to the appropriate
projects.
Linking/Unlinking/Ordering Existing Custom Fields in Projects
The logged in user needs to have access level that is
greater than or equal to $g_custom_field_link_threshold and
$g_manage_project_threshold.
Select "Manage" from the main menu.
Select "Manage Projects".
Select the name of the project to manage.
Scroll down to the "Custom Fields" box.
Select the field to add from the list, then click "Add
This Existing Custom Field".
To change the order of the custom fields, edit the
"Sequence" value and click update. Custom fields with smaller
values are displayed first.
To unlink a custom field, click on "Remove" link next to
the field.
Unlinking a custom field will not delete the values that are
associated with the issues for this field. These values are only
deleted if the custom field definition is removed (not unlinked!)
from the database. This is useful if you decide to re-link the
custom field. These values may also re-appear if issues are moved to
another project which has this field linked.
Moving Issues
When an issue is moved from one project to another, custom
fields that are not defined for the new project are not deleted.
These fields will re-appear with their correct values if the issue is
moved back to the original project, or if these custom fields are
linked to the new project.
Localizing Custom Field Names
It is possible to localize the label for the custom fields.
This can be as follows:
Give the custom field a valid variable name
(i.e. start with an alpha character, no spaces, etc) - For
example, we will use "my_start_date" for a custom field of
type "Date" which stores the "Start Date" for working on an
issue.
Add the localized string for "my_start_date"
- This can be done by creating custom_strings_inc.php in the
MantisBT root folder and adding the following code to it:
<?php
if ( lang_get_current() == 'german' ) {
$s_my_start_date = 'Start Date XX'; // German translation of Start Date
} else {
# Default (use your preferred language as the default)
$s_my_start_date = 'Start Date';
}
?>
If we would have decided to use start_date as the
name of the custom field, then we have used an already localized
string from MantisBT standard strings. In this case, there is no
need to create the custom_strings_inc.php or to add any strings to
it. To check for standard strings, inspect
lang/strings_english.txt.
Dynamic default values
Dynamic defaults for Date fields
Custom fields of type date can be defaulted to a specific dates or to relative dates. Typically relative dates is the scenario that makes sense in most of the cases. The format for specific dates is an integer which indicates the number of seconds since the Unix Epoch (January 1 1970 00:00:00 GMT), which is the format consumed by the PHP date() method. The relative scenario expects default values like {tomorrow}, {yesterday}, {+2 days}, {-3 days}, {next week}, etc. The curly brackets indicate that this is a logical value which is then evaluated using the PHP strtotime() function.
Dynamic values for Enumeration Custom Fields
As discussed earlier, one of the possible types of a custom
field is "enumeration". This type of custom field allows the user
to select one value from a provided list of possible values. The
standard way of defining such custom fields is to provide a '|'
separated list of possible values. However, this approach has two
limitations: the list is static, and the maximum length of the list
must be no longer than 255 characters. Hence, the need for the
ability to construct the list of possible values dynamically.
Dynamic possible values included by default
MantisBT ships with some dynamic possible values, these
include the following:
=categories - a list of categories defined
in the current project (or the project to which the issue
belongs).
=versions - a list of all versions defined
in the current project (or the project to which the issue
belongs).
=future_versions - a list of all versions that
belong to the current project with
released flag set to false.
=released_versions - a list of all versions
that belong to the current project with released flag set to
true.
The '=' before the name of the dynamic list of options is used
to tell MantisBT that this is a dynamic list, rather than a static
list with just one option.
Defining Custom Dynamic Possible Values
If the user selects =versions, the actual custom function
that is executed is custom_function_*_enum_versions(). The reason
why the "enum_" is not included is to have a fixed prefix for all
custom functions used for this purpose and protect against users
using custom functions that were not intended for this purpose.
For example, you don't want the user to use
custom_function_*_issue_delete_notify() which may be overridden
by the web master to delete associated data in other
databases.
Following is a sample custom function that is used to
populate a field with the categories belonging to the currently
selected project:
# --------------------
# Construct an enumeration for all categories for the current project.
# The enumeration will be empty if current project is ALL PROJECTS.
# Enumerations format is: "abc|lmn|xyz"
# To use this in a custom field type "=categories" in the possible values field.
function custom_function_override_enum_categories() {
$t_categories = category_get_all_rows( helper_get_current_project() );
$t_enum = array();
foreach( $t_categories as $t_category ) {
$t_enum[] = $t_category['category'];
}
$t_possible_values = implode( '|', $t_enum );
return $t_possible_values;
}
Notice the following:
The custom function doesn't take any
parameters.
The custom function returns the possible values in the
format (A|B|C).
The custom function uses the current
project.
The custom function builds on top of the already
existing APIs.
To define your own function \u201c=mine\u201d, you will have to define it
with the following signature:
# --------------------
# To use this in a custom field type "=mine" in the possible values field.
function custom_function_override_enum_mine() {
$t_enum = array();
:
$t_possible_values = implode( '|', $t_enum );
return $t_possible_values;
}
Notice "override" in the function name. This is because this method is
defined by the MantisBT adminstrator/webmaster and not part of the MantisBT source.
It is OK to override a method that doesn't exist.
As usual, when MantisBT is upgraded to future releases, the custom functions
will not be overwritten. The difference between the "default" implementation and
the "override" implementation is explained in more details in the custom
functions section.
Enumerations
Enumerations are used in MantisBT to represent a set of
possible values for an attribute. Enumerations are used for access
levels, severities, priorities, project statuses, project view
state, reproducibility, resolution, ETA, and projection. MantisBT
provides the administrator with the flexibility of altering the
values in these enumerations. The rest of this topic explains how
enumerations work, and then how they can be customised.
How enumerations work?
core/constant_inc.php defines the
constants that correspond to those in the enumeration. These are
useful to refer to these enumerations in the configs and the code.
define( 'VIEWER', 10 )
define( 'REPORTER', 25 )
define( 'UPDATER', 40 )
define( 'DEVELOPER', 55 )
define( 'MANAGER', 70 )
define( 'ADMINISTRATOR', 90 )
config_defaults_inc.php includes the defaults for the
enumerations. The configuration options that are defaulted here are
used in specifying which enumerations are active and should be used
in MantisBT. However, the strings included in the enumerations here
are just for documentation purpose, they are not shown to the user
(due to the need for localisation). Hence, if an entry in this
enumeration is not found in the corresponding localised enumeration
(i.e. 70:manager), then it will be printed to the user as @70@.
$g_access_levels_enum_string =
'10:viewer,25:reporter,40:updater,55:developer,70:manager,90:administrator';
lang/strings_german.txt provide the
localised strings (in this case, in german) for enumerations. But again, the master list is
the enumeration in the configs, the ones in the language files are
just used for finding the localised equivalent for an entry. Hence,
if a user changes the config to have only two types of users
developers and administrators, then only those will be prompted to
the users even if the enumerations in the language files still
includes the full list.
$s_access_levels_enum_string =
'10:Betrachter,25:Reporter,40:Updater,55:Entwickler,70:Manager,90:Administrator';
How can they be customised? Let say we want to remove access level
"Updater" and add access level "Senior
Developer".
The file custom_constants_inc.php is supported for the
exclusive purpose of allowing administrators to define their own
constants while maintaining a simple upgrade path for future
releases of MantisBT. Note that this file is not distributed with
MantisBT and you will need to create it if you need such
customisation. In our example, we need to define a constant for the
new access level.
define ( 'SENIOR_DEVELOPER', 60 );
In config_inc.php
// Remove Updater and add Senior Developer
$g_access_levels_enum_string =
'10:viewer,25:reporter,55:developer,60:senior_developer,70:manager,90:administrator';
// Give access to Senior developers to create/delete custom field.
$g_manage_custom_fields_threshold = SENIOR_DEVELOPER;
The file custom_strings_inc.php is introduced for a similar reason
to that of custom_constants_inc.php, which is to define custom
strings. The advantage of defining them here is to provide a simple
upgrade path, and avoid having to re-do the changes when upgrading
to the next MantisBT release. Note that you will need to create this
file if you need such customisation. The file is automatically
detected and included by MantisBT code.
# Note that we don't have to remove the Updater entry from the
localisation file if ( lang_get_current() === 'english' ) {
$s_access_levels_enum_string =
'10:Betrachter,25:Reporter,40:Updater,55:Entwickler,60:Senior
Developer,70:Manager,90:Administrator'; }
ConclusionWe have covered how enumerations work in general, and how
to customise one of them. If you are interested in customising
other enumerations, a good starting point would be to go to "MantisBT
Enum Strings" section in config_defaults_inc.php. This section
defines all enumerations that are used by MantisBT.
For versions that are older than 0.18.0, custom_*_inc.php files are
not supported, and hence you will need to change in the actual
constants / language files directly.
Email Notifications
See Email in the Configuration section.
Examples:
Notify only managers of new issues.
$g_notify_flags['new']['threshold_min'] = MANAGER;
$g_notify_flags['new']['threshold_max'] = MANAGER;
Notify Developers and managers of all project events,
except, exclude developers from the 'closed' events.
$g_default_notify_flags['threshold_min'] = DEVELOPER;
$g_default_notify_flags['threshold_max'] = MANAGER;
$g_notify_flags['closed']['threshold_max'] = MANAGER;
$g_notify_flags['closed']['threshold_max'] = MANAGER;
Exclude those who contributed issue notes from getting
messages about other changes in the issue.
$g_default_notify_flags['bugnotes'] = OFF;
Exclude those monitoring issues from seeing the 'closed'
message
$g_notify_flags['closed']['monitor'] = OFF;
Only notify developers when issue notes are added.
$g_notify_flags['bugnote']['threshold_min'] = DEVELOPER;
$g_notify_flags['bugnote']['threshold_max'] = DEVELOPER;
Notify managers of changes in sponsorship.
$g_notify_flags['sponsor']['threshold_max'] = MANAGER;
$g_notify_flags['sponsor']['threshold_max'] = MANAGER;
Notify originator and managers of changes in ownership
("Assigned To:").
$g_notify_flags['owner']['threshold_max'] = MANAGER;
$g_notify_flags['owner']['threshold_max'] = MANAGER;
$g_notify_flags['owner']['reporter'] = ON;
I'm paranoid about mail. Only send information on issues
to those involved in them. Don't send mail people already know
about. Also send new issue notifications to managers so they can
screen them.
$g_mail_receive_own = OFF;
$g_default_notify_flags =
array('reporter' => ON, 'handler' => ON, 'monitor' => ON,
'bugnotes' => ON, 'threshold_min' => NOBODY, 'threshold_max'
=> NOBODY);
$g_notify_flags['new']['threshold_min'] = MANAGER;
$g_notify_flags['new']['threshold_max'] = MANAGER;
How do I replace the $g_to_email configuration variable
to log all messages to an email logger.
You will need to create a
dummy user with the appropriate access level for the notices you
want to log. Once this user is added to projects, they will receive
mail using the appropriate rules.
Customizing Status Values
The default is no workflow, where all states
are accessible from any others. The following example can be
transferred to config_inc.php. The workflow needs to have a path
from the statuses greater than or equal to the resolved state back
to the feedback state. Otherwise, the re-open operation won't work.
$g_status_enum_workflow[NEW_]=
'10:new,20:feedback,30:acknowledged,40:confirmed,50:assigned,80:resolved';
$g_status_enum_workflow[FEEDBACK] =
'10:new,20:feedback,30:acknowledged,40:confirmed,50:assigned,80:resolved';
$g_status_enum_workflow[ACKNOWLEDGED] =
'20:feedback,30:acknowledged,40:confirmed,50:assigned,80:resolved';
$g_status_enum_workflow[CONFIRMED] =
'20:feedback,40:confirmed,50:assigned,80:resolved';
$g_status_enum_workflow[ASSIGNED] =
'20:feedback,50:assigned,80:resolved,90:closed';
$g_status_enum_workflow[RESOLVED] =
'50:assigned,80:resolved,90:closed';
$g_status_enum_workflow[CLOSED] = '50:assigned';
To add a status:
Define a constant to map the new status to.In a new file
custom_constants_inc.php in the main mantisbt directory:
<?php define ( 'TEST', 60 ); ?>
Define the language strings required. This may need to be
defined in several languages.In a new file custom_strings_inc.php
in the main mantisbt directory:
<?php if ( lang_get_current() == 'german' ) {
$s_status_enum_string =
'10:neu,20:R¸ckmeldung,30:anerkannt,40:best‰tigt,50:zugewiesen,
60:zu testen,80:behoben,90:geschlossen'; } else {
$s_status_enum_string =
'10:new,20:feedback,30:acknowledged,40:confirmed,50:assigned, 60:to
be tested,80:resolved,90:closed'; $s_to_be_tested_bug_button =
"Issue Ready to Test"; $s_to_be_tested_bug_title = "Set Issue Ready
to Test"; $s_email_notification_title_for_status_bug_to_be_tested =
"The following issue is ready TO BE TESTED."; } ?>
Define any configurations required.In the existing file
config_inc.php in the main mantisbt directory:
$g_status_enum_string =
'10:new,20:feedback,30:acknowledged,40:confirmed,50:assigned, 60:to
be tested,80:resolved,90:closed'; # Status color additions
$g_status_colors['to be tested'] = '#ACE7AE';
Add the status to any workflow defined.In config_inc.php:
$g_status_enum_workflow[NEW_]=
'10:new,20:feedback,30:acknowledged,40:confirmed,50:assigned,60:to
be tested'; $g_status_enum_workflow[FEEDBACK] =
'10:new,20:feedback,30:acknowledged,40:confirmed,50:assigned,60:to
be tested'; $g_status_enum_workflow[ACKNOWLEDGED] =
'20:feedback,30:acknowledged,40:confi rmed,50:assigned,60:to be
tested'; $g_status_enum_workflow[CONFIRMED] =
'20:feedback,40:confirmed,50:assigned,60:to be tested';
$g_status_enum_workflow[ASSIGNED] = '20:feedback,50:assigned,60:to
be tested,90:closed'; $g_status_enum_workflow[TEST] =
'10:new,20:feedback,50:assigned,60:to be
tested,80:resolved,90:closed'; $g_status_enum_workflow[RESOLVED] =
'50:assigned,60:to be tested,80:resolved,90:closed';
$g_status_enum_workflow[CLOSED] = '50:assigned,90:closed';
Custom Functions
Custom functions are used to extend the functionality of
MantisBT by integrating user writtenfunctions into the issue
processing at strategic places. This allows the system
administrator to changethe functionality without re-writing parts
of the internals of the code.
User versions of these functions are
placed in a file called custom_functions_inc.php in the
root directory of MantisBT. This is the same place that the
"config_inc.php" file modifying MantisBT defaults is placed. In normal
processing, MantisBT will look for override functions and execute
them instead of the provided default functions.
Custom functions have
names like custom_function_override_descriptive_name where
descriptive namedescribed the particular function. The specific
functions are described below. The simplest way tocreate a custom
function is to copy the default function, named
custom_function_default_descriptive_namefrom the
core/custom_function_api.php file to your override file
(custom_functions_inc.php), andrename it. The specific
functionality you need can then be coded into the override
function.
Defined Functions
custom_function_default_changelog_include_issue( $p_issue_id
) returns true or false if the issue if to be included in the
Changelogcustom_function_default_changelog_print_issue( $p_issue_id
) returns a formatted string to be included for the issue in the
Changelogcustom_function_default_checkin( $p_issue_id, $p_comment,
$p_file, $p_new_version ) registers a checkin in source control in
MantisBT custom_function_default_issue_update_validate( $p_issue_id,
$p_new_bug, $p_bug_note_text ) validate issue field settings before
an update occurs. It returns true or fails with an
error.custom_function_default_issue_update_notify( $p_issue_id )
notify after an issue has been
updatedcustom_function_default_issue_create_validate( $p_new_bug )
validate issue field settings before an issue is created. It returns
true or fails with an
error.custom_function_default_issue_create_notify( $p_issue_id )
notify after an issue has been
openedcustom_function_default_issue_delete_validate( $p_issue_id )
validate issue field settings before an issue can be deleted. It
returns true or fails with an
error.custom_function_default_issue_delete_notify( $p_issue_id )
notify after an issue has been deleted
Example Custom Function
The following function is used to validate an issue before
it is resolved.
status == RESOLVED ) {
if ( $p_bug_data->resolution == OPEN ) {
error_parameters( 'the resolution cannot be open to resolve the issue' );
trigger_error( ERROR_BUG_VALIDATE_FAILURE, ERROR );
}
$t_version_count = count( version_get_all_rows( $p_bug_data->project_id ) );
if ( ( $t_version_count > 0 ) && ( $p_bug_data->fixed_in_version == '' ) ) {
error_parameters( 'fixed in version must be set to resolve the issue' );
trigger_error( ERROR_BUG_VALIDATE_FAILURE, ERROR );
}
}
}
?>]]>
The errors will also need to be defined by adding the following to custom_constants_inc.php
define ( 'ERROR_VALIDATE_FAILURE', 2000 );
To custom_strings_inc.php
$MANTIS_ERROR['ERROR_VALIDATE_FAILURE'] = 'This change cannot be made because %s';