NAME
RT::Extension::ConditionalCustomFields - CF conditioned by the value of
another CF
DESCRIPTION
This plugin provides the ability to display/edit a custom field
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> – called
the "conditioned by custom field
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html>"
throughout this documentation – conditioned by the value of another
custom field
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> – the
"condition custom field
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html>" – for the
same object, which can be anything that can have custom fields (ticket
<https://docs.bestpractical.com/rt/6.0.2/RT/Ticket.html>, queue
<https://docs.bestpractical.com/rt/6.0.2/RT/Queue.html>, ticket
transaction
<https://docs.bestpractical.com/rt/6.0.2/RT/Transaction.html>, user
<https://docs.bestpractical.com/rt/6.0.2/RT/User.html>, group
<https://docs.bestpractical.com/rt/6.0.2/RT/Group.html>, article
<https://docs.bestpractical.com/rt/6.0.2/RT/Article.html>, class
<https://docs.bestpractical.com/rt/6.0.2/RT/Class.html> or asset
<https://docs.bestpractical.com/rt/6.0.2/RT/Asset.html>).
The condition can be setup on the Admin page for editing the conditioned
by custom field
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html>. From
version 0.99, any custom field
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> can be
chosen as the condition custom field
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> (whereas
for earlier version, only Select custom fields
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> were
eligible), and you can specify which operator is to be applied against
which value(s) for the condition to be met.
Available operators are:
* is
The condition is met if and only if the current value of the
instanciated conditioned by custom field
<https://docs.bestpractical.com/rt/6.0.2/RT/ObjectCustomField.html>
is equal to the value (or one of the values, see below for
multivalued condition) setup for this condition. With isn't operator
described below, is operator is the only one which is eligible for
selectable custom fields
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> – with
Select, Combobox or Autocomplete type –, since their values are to
be selected from a set of values. For Date and DateTime custom
fields
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html>, this
operator is named on.
* isn't
The condition is met if and only if the current value of the
instanciated conditioned by custom field
<https://docs.bestpractical.com/rt/6.0.2/RT/Queue.html> is different
from the value (or none of the values, see below for multivalued
condition) setup for this condition. With is operator described
above, isn't operator is the only one which is eligible for
selectable custom fields
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> – with
Select, Combobox or Autocomplete type –, since their values are to
be selected from a set of values. For Date and DateTime custom
fields
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html>, this
operator is named not on.
* match
The condition is met if and only if the current value of the
instanciated conditioned by custom field
<https://docs.bestpractical.com/rt/6.0.2/RT/ObjectCustomField.html>
is included in the value setup for this condition, typically if the
current value is a substring of the condition value. As said above,
selectable custom fields
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> – with
Select, Combobox or Autocomplete type are not eligible for this
operator. Also, Date and DateTime custom fields
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> are
not eligible for this operator.
* doesn't match
The condition is met if and only if the current value of the
instanciated conditioned by custom field
<https://docs.bestpractical.com/rt/6.0.2/RT/ObjectCustomField.html>
isn't included in the value setup for this condition, typically if
the current value isn't a substring of the condition value. As said
above, selectable custom fields
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> – with
Select, Combobox or Autocomplete type are not eligible for this
operator. Also, Date and DateTime custom fields
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> are
not eligible for this operator.
* less than
The condition is met if and only if the current value of the
instanciated conditioned by custom field
<https://docs.bestpractical.com/rt/6.0.2/RT/ObjectCustomField.html>
is less than or equal to the value setup for this condition. The
comparison is achieved according to some kind of natural sort order
<https://en.wikipedia.org/wiki/Natural_sort_order>, that is: number
values are compared as numbers, strings are compared alphabetically,
insensitive to case and accents (a = á, a = A). Moreover, IP
Adresses (IPv4 and IPv6) are expanded to be compared as expected. As
said above, selectable custom fields
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> – with
Select, Combobox or Autocomplete type are not eligible for this
operator.
* greater than
The condition is met if and only if the current value of the
instanciated conditioned by custom field
<https://docs.bestpractical.com/rt/6.0.2/RT/ObjectCustomField.html>
is greater than or equal to the value setup for this condition. The
comparison is achieved according to some kind of natural sort order
<https://en.wikipedia.org/wiki/Natural_sort_order>, that is: number
values are compared as numbers, strings are compared alphabetically,
insensitive to case and accents (a = á, a = A), and dates with or
without times are compared chronogically. Moreover, IP Adresses
(IPv4 and IPv6) are expanded to be compared as expected. As said
above, selectable custom fields
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> – with
Select, Combobox or Autocomplete type are not eligible for this
operator.
* between
The condition is met if and only if the current value of the
instanciated conditioned by custom field
<https://docs.bestpractical.com/rt/6.0.2/RT/ObjectCustomField.html>
is greater than or equal to the first value setup for this condition
and is less than or equal to the second value setup for this
condition. That means that when this operator is selected, two
values have to be entered. The comparison is achieved according to
some kind of natural sort order
<https://en.wikipedia.org/wiki/Natural_sort_order>, that is: number
values are compared as numbers, strings are compared alphabetically,
insensitive to case and accents (a = á, a = A), and dates with or
without times are compared chronogically. Moreover, IP Adresses
(IPv4 and IPv6) are expanded to be compared as expected. As said
above, selectable custom fields
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> – with
Select, Combobox or Autocomplete type are not eligible for this
operator.
As an exception, IPAddressRange custom fields
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> are not
eligible as condition custom fields
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html>, since
there is not really any sense in comparing two ranges of IP addresses.
IPAddress custom fields
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html>, combined
with between operator, should be sufficient for most cases checking
whether an IP address is included in a range.
If the condition custom field
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> is
selectable – with Select, Combobox or Autocomplete type – it can be
multivalued. Then, the condition for an object is met as soon as the
condition is met by at least one value of the instanciated conditioned
by custom field
<https://docs.bestpractical.com/rt/6.0.2/RT/ObjectCustomField.html> for
this object.
If a custom field
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> is based
on another (parent) custom field
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> which is
conditioned by, this (child) custom field
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> will of
course also be conditioned by (with the same condition as its parent).
Nevertheless, there is a caveheat in display mode: the order matters!
That is the parent custom field
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> should
have a lower sort order than the child custom field
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html>.
From version 0.07, the condition can be multivalued, that is: the
conditioned custom field
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> can be
displayed/edited if the condition custom field
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> has one of
these values (In other words: there is an OR bewteen the values of the
condition). The condition custom field
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> can be a
select custom field with values defined by CustomFieldValues
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomFieldValues.html> or
an external custom field
<https://docs.bestpractical.com/rt/6.0.2/extending/external_custom_field
s.html>.
*Note that version 0.07 is a complete redesign: the API described below
has changed; also, the way that ConditionedBy property is store has
changed. If you upgrade from a previous version, you have to reconfigure
the custom fields which are conditionned by.*
Version 0.99 is also a complete redesign, with API changed, but backward
compatibility with previously configured custom fields
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html>, assuming
the default condition operator is is.
From version 1.13, HTML custom fields
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> introduced
in RT 5.0.3 can be defined as condition CustomField
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html>.
RT VERSION
Works with RT 6 (use v1.x versions of this module for previous version
of RT)
INSTALLATION
export $RTHOME=/home/of/your/RT/installation/lib
This is needed if your RT installation directory is not /opt/rt6/,
as documented in
<https://docs.bestpractical.com/rt/6.0.2/extensions.html>.
perl Makefile.PL
make
make install
May need root permissions
Edit your /opt/rt6/etc/RT_SiteConfig.pm
Add this line:
Plugin('RT::Extension::ConditionalCustomFields');
Clear your mason cache
rm -rf /opt/rt6/var/mason_data/obj
Restart your webserver
CONFIGURATION
Usually, groupings of custom fields, as defined in $CustomFieldGroupings
configuration variable, is *not* enabled in SelfService. This is the
case if you use RT Core. Anyway, some RT instances could have overridden
this restriction to enable groupings of custom fields in SelfService.
In this case, you should add to your configuration file
(/opt/rt6/etc/RT_SiteConfig.pm) the following line, setting
$SelfServiceCustomFieldGroupings configuration variable to a true value:
Set($SelfServiceCustomFieldGroupings, 1);
METHODS
ConditionalCustomFields adds a ConditionedBy property, that is a
condition CustomField
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html>, an
operator and one or more values, along with the following methods, to
conditioned by CustomField
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> objects:
SetConditionedBy CF, OP, VALUE
Set the ConditionedBy property for this CustomField
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> object to
CustomField
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> CF with
operator set to OP and value set to VALUE. CF should be an existing
CustomField
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> object or
the id of an existing CustomField
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> object, or
the name of an unambiguous existing CustomField
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> object. OP
should be is, isn't, match, doesn't match, less than, greater than or
between. VALUE should be a string or an anonymous array of strings (for
selectable custom fields
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> or between
operator). Current user should have SeeCustomField and ModifyCustomField
rights for this conditioned by CustomField
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> and
SeeCustomField right for the condition CustomField
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html>. Returns
(1, 'Status message') on success and (0, 'Error Message') on failure.
ConditionedBy
Returns the current ConditionedBy property for this conditioned by
CustomField
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> object as
a hash with keys CF containing the id of the condition CustomField
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html>, op and
vals containing the condition operator as string, and the condition
value as an array of strings (so we can store several values for
selectable custom fields
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> or between
operator, but generally the vals array includes only one string). If
neither this conditioned by CustomField
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> nor one of
its ancestor is conditioned by the CF condition CustomField
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html>, that is:
if their ConditionedBy property is not (recursively) defined, returns
undef. Current user should have SeeCustomField right for both this
conditioned by CustomField
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> and the
condition CustomField
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> which this
CustomField
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> is
conditioned recursively by. *"Recursively"* means that this method will
search for a ConditionedBy property for this CustomField
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> object,
then for the CustomField
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> this one
is BasedOn, and so on until it finds an ancestor Category with a
ConditionedBy property or, the CustomField
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> which is
being looked up, is not based on any ancestor Category.
INITIALDATA
Also, ConditionalCustomFields allows to set the ConditionedBy property
when creating CustomFields
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomFields.html> from an
initialdata file, with one of the following syntaxes:
@CustomFields = (
{
Name => 'Condition',
Type => 'SelectSingle',
RenderType => 'Dropdown',
Queue => [ 'General' ],
LookupType => 'RT::Queue-RT::Ticket',
Values => [
{ Name => 'Passed', SortOrder => 0 },
{ Name => 'Failed', SortOrder => 1 },
{ Name => 'Schrödingerized', SortOrder => 2 },
],
Pattern => '(?#Mandatory).',
DefaultValues => [ 'Failed' ],
},
{
Name => 'Conditioned with cf name and value',
Type => 'FreeformSingle',
Queue => [ 'General' ],
LookupType => 'RT::Queue-RT::Ticket',
ConditionedByCF => 'Condition',
ConditionedBy => 'Passed',
},
{
Name => 'Conditioned with cf id and value',
Type => 'FreeformSingle',
Queue => [ 'General' ],
LookupType => 'RT::Queue-RT::Ticket',
ConditionedByCF => 66,
ConditionOp => "isn't",
ConditionedBy => 'Failed',
},
{
Name => 'Conditioned with multiple values',
Type => 'Freeform',
MaxValues => 1,
Queue => [ 'General' ],
LookupType => 'RT::Queue-RT::Ticket',
ConditionedByCF => 'Condition',
ConditionedBy => ['Passed', 'Schrödingerized'],
},
);
This examples creates a Select condition CustomField
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html>, named
Condition and three conditioned by CustomFields
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html>.
CustomField
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> Condition
should have the value Passed, for CustomField
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html>
Conditioned with cf name and value to be displayed or edited.
CustomField
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> Condition
should not have the value Failed for CustomField
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html>
Conditioned with cf id and value to be displayed or edited. CustomField
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> Condition
should have one of the values Passed or Schrödingerized for CustomField
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html>
Conditioned with multiple values to be displayed or edited.
Additional fields for an element of @CustomFields are:
ConditonedByCF
The condition CustomField
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> that
this new CustomField
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> should
conditioned by. It can be either the id or the Name of a previously
created CustomField
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html>. This
implies that the condition CustomField
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> should
be declared before this one in the initialdata file, or it should
already exist. When ConditionedByCF attribute is set, ConditionedBy
field should always also be set.
ConditonedBy
The value as a string of the condition CustomField
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html>
defined by the ConditionedByCF field (which is mandatory).
ConditonOp
The operator as a string to use for comparison, either is, isn't,
match, doesn't match, less than, greater than or between. This field
is optional, defaults to is.
TEST SUITE
ConditionalCustomFields comes with a test suite. As for every RT
extention
<https://docs.bestpractical.com/rt/6.0.2/writing_extensions.html#Tests>,
to run it, you will need a installed RT, set up in development mode
<https://docs.bestpractical.com/rt/6.0.2/hacking.html#Test-suite>.
But, since ConditionalCustomFields operates dynamically to show or hide
custom fields
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html>, most of
its magic happens in Javascript. Therefore, the test suite requires a
scriptable headless browser with Javascript capabilities. In previous
versions of ConditionalCustomFields, you would also need to install
PhantomJS <http://phantomjs.org/>, along with WWW::Mechanize::PhantomJS
and Selenium::Remote::Driver. Unfortunately PhantomJS
<http://phantomjs.org/> has been deprecated for years and was unable to
cope with javascript librairies, mostly bootstrap.js, used by RT 5 core,
and moreover with htmx.js used by RT 6 core. Therefore, the test suite
has been reduced to include only javascript free tests.
CAVEATS
HTML custom fields
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html> can still
be defined as condition CustomField
<https://docs.bestpractical.com/rt/6.0.2/RT/CustomField.html>. But due
to the upgrade to CKEditor 5, introduced in RT 6, changed cannot be
dynamically detected. That means that if a CF B is conditionned by an
HTML CF A, inline changes in CF A won't trigger showing or hidding CF B.
Still, these changes to CF A will affect CF B when the inline editing is
saved.
AUTHOR
Gérald Sédrati <gibus@easter-eggs.com>
REPOSITORY
<https://github.com/gibus/RT-Extension-ConditionalCustomFields>
BUGS
All bugs should be reported via email to
bug-RT-Extension-ConditionalCustomFields@rt.cpan.org
<mailto:bug-RT-Extension-ConditionalCustomFields@rt.cpan.org>
or via the web at
rt.cpan.org
<http://rt.cpan.org/Public/Dist/Display.html?Name=RT-Extension-Condition
alCustomFields>.
LICENSE AND COPYRIGHT
This software is Copyright (c) 2017-2026 by Gérald Sédrati, Easter-Eggs
This is free software, licensed under:
The GNU General Public License, Version 3, June 2007