-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathREADME
509 lines (441 loc) · 24.4 KB
/
README
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
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/5.0.5/RT/CustomField.html> – called
the "conditioned by custom field
<https://docs.bestpractical.com/rt/5.0.5/RT/CustomField.html>"
throughout this documentation – conditioned by the value of another
custom field
<https://docs.bestpractical.com/rt/5.0.5/RT/CustomField.html> – the
"condition custom field
<https://docs.bestpractical.com/rt/5.0.5/RT/CustomField.html>" – for the
same object, which can be anything that can have custom fields (ticket
<https://docs.bestpractical.com/rt/5.0.5/RT/Ticket.html>, queue
<https://docs.bestpractical.com/rt/5.0.5/RT/Queue.html>, user
<https://docs.bestpractical.com/rt/5.0.5/RT/User.html>, group
<https://docs.bestpractical.com/rt/5.0.5/RT/Group.html>, article
<https://docs.bestpractical.com/rt/5.0.5/RT/Article.html> or asset
<https://docs.bestpractical.com/rt/5.0.5/RT/Asset.html>).
The condition can be setup on the Admin page for editing the conditioned
by custom field
<https://docs.bestpractical.com/rt/5.0.5/RT/CustomField.html>. From
version 0.99, any custom field
<https://docs.bestpractical.com/rt/5.0.5/RT/CustomField.html> can be
chosen as the condition custom field
<https://docs.bestpractical.com/rt/5.0.5/RT/CustomField.html> (whereas
for earlier version, only Select custom fields
<https://docs.bestpractical.com/rt/5.0.5/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/5.0.5/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/5.0.5/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/5.0.5/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/5.0.5/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/5.0.5/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/5.0.5/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/5.0.5/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/5.0.5/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/5.0.5/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/5.0.5/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/5.0.5/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/5.0.5/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/5.0.5/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/5.0.5/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/5.0.5/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/5.0.5/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/5.0.5/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/5.0.5/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/5.0.5/RT/CustomField.html> are not
eligible as condition custom fields
<https://docs.bestpractical.com/rt/5.0.5/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/5.0.5/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/5.0.5/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/5.0.5/RT/ObjectCustomField.html> for
this object.
If a custom field
<https://docs.bestpractical.com/rt/5.0.5/RT/CustomField.html> is based
on another (parent) custom field
<https://docs.bestpractical.com/rt/5.0.5/RT/CustomField.html> which is
conditioned by, this (child) custom field
<https://docs.bestpractical.com/rt/5.0.5/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/5.0.5/RT/CustomField.html> should
have a lower sort order than the child custom field
<https://docs.bestpractical.com/rt/5.0.5/RT/CustomField.html>.
From version 0.07, the condition can be multivalued, that is: the
conditioned custom field
<https://docs.bestpractical.com/rt/5.0.5/RT/CustomField.html> can be
displayed/edited if the condition custom field
<https://docs.bestpractical.com/rt/5.0.5/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/5.0.5/RT/CustomField.html> can be a
select custom field with values defined by CustomFieldValues
<https://docs.bestpractical.com/rt/5.0.5/RT/CustomFieldValues.html> or
an external custom field
<https://docs.bestpractical.com/rt/5.0.5/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/5.0.5/RT/CustomField.html>, assuming
the default condition operator is is.
From version 1.13, HTML custom fields
<https://docs.bestpractical.com/rt/5.0.5/RT/CustomField.html> introduced
in RT 5.0.3 can be defined as condition CustomField
<https://docs.bestpractical.com/rt/5.0.5/RT/CustomField.html>.
RT VERSION
Works with RT 4.2 or greater
INSTALLATION
perl Makefile.PL
make
make install
May need root permissions
Patch your RT
ConditionalCustomFields still requires a small patch to add
necessary Callbacks on versions of RT superior to 4.2.3.
The patch has now been integrated by BestPractical and will be
included in future RT releases strictly greater than 5.0.5. In other
words patching is still needed on versions of RT up to 5.0.5, but
not necessary for versions of RT greater than 5.0.5.
For RT 4.2, apply the included patch:
cd /opt/rt4 # Your location may be different
patch -p1 < /download/dir/RT-Extension-ConditionalCustomFields/patches/4.2-add-callbacks-to-extend-customfields-capabilities.patch
For RT 4.4.1, apply the included patch:
cd /opt/rt4 # Your location may be different
patch -p1 < /download/dir/RT-Extension-ConditionalCustomFields/patches/4.4.1-add-callbacks-to-extend-customfields-capabilities.patch
For RT 4.4.2 or greater, apply the included patch:
cd /opt/rt4 # Your location may be different
patch -p1 < /download/dir/RT-Extension-ConditionalCustomFields/patches/4.4.2-add-callbacks-to-extend-customfields-capabilities.patch
For RT 5.0.0 to 5.0.5, apply the included patch:
cd /opt/rt5 # Your location may be different
patch -p1 < /download/dir/RT-Extension-ConditionalCustomFields/patches/5.0-add-callbacks-to-extend-customfields-capabilities.patch
Edit your /opt/rt5/etc/RT_SiteConfig.pm
If you are using RT 4.2 or greater, add this line:
Plugin('RT::Extension::ConditionalCustomFields');
For RT 4.0, add this line:
Set(@Plugins, qw(RT::Extension::ConditionalCustomFields));
or add RT::Extension::ConditionalCustomFields to your existing
@Plugins line.
Clear your mason cache
rm -rf /opt/rt5/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/rt5/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/5.0.5/RT/CustomField.html>, an
operator and one or more values, along with the following methods, to
conditioned by CustomField
<https://docs.bestpractical.com/rt/5.0.5/RT/CustomField.html> objects:
SetConditionedBy CF, OP, VALUE
Set the ConditionedBy property for this CustomField
<https://docs.bestpractical.com/rt/5.0.5/RT/CustomField.html> object to
CustomField
<https://docs.bestpractical.com/rt/5.0.5/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/5.0.5/RT/CustomField.html> object or
the id of an existing CustomField
<https://docs.bestpractical.com/rt/5.0.5/RT/CustomField.html> object, or
the name of an unambiguous existing CustomField
<https://docs.bestpractical.com/rt/5.0.5/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/5.0.5/RT/CustomField.html> or between
operator). Current user should have SeeCustomField and ModifyCustomField
rights for this conditioned by CustomField
<https://docs.bestpractical.com/rt/5.0.5/RT/CustomField.html> and
SeeCustomField right for the condition CustomField
<https://docs.bestpractical.com/rt/5.0.5/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/5.0.5/RT/CustomField.html> object as
a hash with keys CF containing the id of the condition CustomField
<https://docs.bestpractical.com/rt/5.0.5/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/5.0.5/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/5.0.5/RT/CustomField.html> nor one of
its ancestor is conditioned by the CF condition CustomField
<https://docs.bestpractical.com/rt/5.0.5/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/5.0.5/RT/CustomField.html> and the
condition CustomField
<https://docs.bestpractical.com/rt/5.0.5/RT/CustomField.html> which this
CustomField
<https://docs.bestpractical.com/rt/5.0.5/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/5.0.5/RT/CustomField.html> object,
then for the CustomField
<https://docs.bestpractical.com/rt/5.0.5/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/5.0.5/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/5.0.5/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/5.0.5/RT/CustomField.html>, named
Condition and three conditioned by CustomFields
<https://docs.bestpractical.com/rt/5.0.5/RT/CustomField.html>.
CustomField
<https://docs.bestpractical.com/rt/5.0.5/RT/CustomField.html> Condition
should have the value Passed, for CustomField
<https://docs.bestpractical.com/rt/5.0.5/RT/CustomField.html>
Conditioned with cf name and value to be displayed or edited.
CustomField
<https://docs.bestpractical.com/rt/5.0.5/RT/CustomField.html> Condition
should not have the value Failed for CustomField
<https://docs.bestpractical.com/rt/5.0.5/RT/CustomField.html>
Conditioned with cf id and value to be displayed or edited. CustomField
<https://docs.bestpractical.com/rt/5.0.5/RT/CustomField.html> Condition
should have one of the values Passed or Schrödingerized for CustomField
<https://docs.bestpractical.com/rt/5.0.5/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/5.0.5/RT/CustomField.html> that
this new CustomField
<https://docs.bestpractical.com/rt/5.0.5/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/5.0.5/RT/CustomField.html>. This
implies that the condition CustomField
<https://docs.bestpractical.com/rt/5.0.5/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/5.0.5/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 fairly complete test suite. As for
every RT extention
<https://docs.bestpractical.com/rt/5.0.5/writing_extensions.html#Tests>,
to run it, you will need a installed RT, set up in development mode
<https://docs.bestpractical.com/rt/5.0.5/hacking.html#Test-suite>. But,
since ConditionalCustomFields operates dynamically to show or hide
custom fields
<https://docs.bestpractical.com/rt/5.0.5/RT/CustomField.html>, most of
its magic happens in Javascript. Therefore, the test suite requires a
scriptable headless browser with Javascript capabilities. So you also
need to install PhantomJS <http://phantomjs.org/>, along with
WWW::Mechanize::PhantomJS and Selenium::Remote::Driver.
It should be noted that with version 0.99, the number of cases to test
has exponentially expanded. Not only any object which can have custom
fields (ticket <https://docs.bestpractical.com/rt/5.0.5/RT/Ticket.html>,
queue <https://docs.bestpractical.com/rt/5.0.5/RT/Queue.html>, user
<https://docs.bestpractical.com/rt/5.0.5/RT/User.html>, group
<https://docs.bestpractical.com/rt/5.0.5/RT/Group.html>, article
<https://docs.bestpractical.com/rt/5.0.5/RT/Article.html> or asset
<https://docs.bestpractical.com/rt/5.0.5/RT/Asset.html>) should be
tested. But also, any type of custom fields
<https://docs.bestpractical.com/rt/5.0.5/RT/CustomField.html> (Select,
Freeform, Text, Wikitext, Image, Binary, Combobox, Autocomplete, Date,
DateTime and IPAddress) should be tested both for condition custom field
<https://docs.bestpractical.com/rt/5.0.5/RT/CustomField.html> and
conditioned by custom field
<https://docs.bestpractical.com/rt/5.0.5/RT/CustomField.html>. And this
both for Single and Multiple versions (when available) of each type of
custom fields
<https://docs.bestpractical.com/rt/5.0.5/RT/CustomField.html>. Select
custom fields
<https://docs.bestpractical.com/rt/5.0.5/RT/CustomField.html> should
also be tested for each render type (Select box, List, Dropdown and also
Chosen when the number of values is greater than ten). Adding to these
required unitary tests, some special cases should also be included, for
instance when a condition custom field
<https://docs.bestpractical.com/rt/5.0.5/RT/CustomField.html> is in turn
conditioned by another condition custom field
<https://docs.bestpractical.com/rt/5.0.5/RT/CustomField.html>, or when a
condition custom field
<https://docs.bestpractical.com/rt/5.0.5/RT/CustomField.html> is not
applied to a queue
<https://docs.bestpractical.com/rt/5.0.5/RT/Queue.html>, etc.
Eventually, the test suite includes 1929 unitary tests and 64 test
files. Nevertheless some special cases may have been left over, so
you're encourage to fill a bug report, so they can be fixed.
AUTHOR
Gérald Sédrati <[email protected]>
REPOSITORY
<https://github.com/gibus/RT-Extension-ConditionalCustomFields>
BUGS
All bugs should be reported via email to
<mailto:[email protected]>
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-2023 by Gérald Sédrati, Easter-Eggs
This is free software, licensed under:
The GNU General Public License, Version 3, June 2007