Modifications pour le document Macros de résultats Livetable

Modifié par Florent Charton le 2026/03/13 11:03

Depuis la version 4.1
modifié par Florent Charton
sur 2026/01/08 10:56
Commentaire de modification : Install extension [org.xwiki.platform:xwiki-platform-livetable-ui/17.4.8]
À la version 6.1
modifié par Florent Charton
sur 2026/03/13 11:03
Commentaire de modification : Install extension [org.xwiki.platform:xwiki-platform-livetable-ui/17.10.4]

Résumé

Détails

Propriétés de la Page
Contenu
... ... @@ -37,9 +37,10 @@
37 37   #foreach($colname in $collist)
38 38   ## If a classname is defined and the class field corresponding to the column name,
39 39   ## we check the type of the field and skip it if it's Password.
40 - #if ($className != '' && $class.get($colname))
41 - #set ($isPasswordType = $class.get($colname).classType == 'Password')
42 - #set ($isEmailType = $class.get($colname).classType == 'Email')
40 + #livetable_getPropertyClassAndType($colname)
41 + #if ($propType != '')
42 + #set ($isPasswordType = $propClass.get($colname).classType == 'Password')
43 + #set ($isEmailType = $propClass.get($colname).classType == 'Email')
43 43   #set ($emailObfuscated = $services.mail.general.shouldObfuscate())
44 44   #if (!($isPasswordType || ($isEmailType && $emailObfuscated)))
45 45   #livetable_addColumnToQuery($colname)
... ... @@ -692,6 +692,19 @@
692 692   #elseif ($colName == 'doc.date' || $colName == 'doc.creationDate' || $colName == 'doc.contentUpdateDate')
693 693   #livetable_getTableAlias($colName)
694 694   #livetable_filterDateProperty()
696 + #elseif ($colName == 'doc.hidden' || $colName == 'doc.minorEdit1' || $colName == 'doc.enforceRequiredRights')
697 + ## Boolean document fields need special handling to work across all databases
698 + ## (HSQLDB/PostgreSQL use true/false, MySQL/MariaDB/Oracle use 1/0).
699 + ## Support both true/false and 1/0 as Live Data uses the former while LiveTable uses the latter.
700 + #set ($booleanValue = ($filterValue.toLowerCase() == 'true' || $filterValue == '1'))
701 + ## No need to clean the column name since it's only one of the given values.
702 + #if ($whereParams.entrySet())
703 + #set ($whereSql = "${whereSql} and $colName = :${colName.replace('.', '_')}_filter")
704 + #set ($discard = $whereParams.put("${colName.replace('.', '_')}_filter", $booleanValue))
705 + #else
706 + #set ($whereSql = "${whereSql} and $colName = ?")
707 + #set ($discard = $whereParams.add($booleanValue))
708 + #end
695 695   #else
696 696   #set ($safeColName = $colName.replaceAll('[^a-zA-Z0-9_.]', '').replace('_', '.'))
697 697   #if ($whereParams.entrySet())
... ... @@ -884,34 +884,79 @@
884 884   *#
885 885  #macro (livetable_filterDBStringListProperty)
886 886   ## Perform exact matching by default if no match type is specified.
887 - ## Note that for DBStringList properties we take into account only the first match type, even if multiple filter
888 - ## values are specified. Basically the first match type is used for all filter values.
901 + ## For DBStringList properties we still apply a single match type to all non-empty values, but we also allow
902 + ## combining the special "empty" match type with other match types.
889 889   #livetable_getMatchTypes($colname $filterValues.size() 'exact')
890 - #if ($matchType == 'partial' || $matchType == 'prefix')
891 - ## We need to join with the list of values in order to be able to use the LIKE operator.
892 - #set ($matchTarget = "${safe_tableAlias}_item")
893 - #if ($whereParams.entrySet())
894 - #set ($paramPrefix = "${safe_tableAlias}_item_")
904 + #livetable_getJoinOperator($colname)
905 +
906 + ## Collect non-empty filter values (those whose match type is not 'empty').
907 + #set ($nonEmptyValues = [])
908 + #set ($hasEmpty = false)
909 + #set ($matchType = 'invalid')
910 + #foreach ($filterValue in $filterValues)
911 + #if ($matchTypes.get($foreach.index) == 'empty')
912 + #set ($hasEmpty = true)
913 + ## When we want to match empty values, we can't have other match types than exact for non-empty values as for
914 + ## other match types, we need to join with the list of values, which is not compatible with checking for
915 + ## emptiness.
916 + #set ($matchType = 'exact')
917 + #elseif ("$!filterValue" != '')
918 + #set ($discard = $nonEmptyValues.add($filterValue))
919 + ## Store the first non-empty match type.
920 + #if ($matchType == 'invalid')
921 + #set ($matchType = $matchTypes.get($foreach.index))
922 + #end
923 + #end
924 + #end
925 +
926 + ## 1) Apply the non-empty constraints.
927 + #if (!$nonEmptyValues.isEmpty())
928 + #if ($matchType == 'partial' || $matchType == 'prefix')
929 + ## We need to join with the list of values in order to be able to use the LIKE operator.
930 + #set ($matchTarget = "${safe_tableAlias}_item")
931 + #if ($whereParams.entrySet())
932 + #set ($paramPrefix = "${safe_tableAlias}_item_")
933 + #else
934 + #set ($paramPrefix = $NULL)
935 + #end
936 + #set ($joinPos = $mathtool.add($fromSql.lastIndexOf(" $safe_tableAlias"), $mathtool.add($safe_tableAlias.length(), 1)))
937 + #set ($fromSql = "$fromSql.substring(0, $joinPos) join ${safe_tableAlias}.list as $matchTarget $fromSql.substring($joinPos)")
895 895   #else
896 - #set ($paramPrefix = $NULL)
939 + ## Fall-back on exact matching even if the match type is specified, when its value is not supported.
940 + #set ($matchType = 'exact')
941 + #set ($matchTarget = "${safe_tableAlias}.list")
942 + #if ($whereParams.entrySet())
943 + #set ($paramPrefix = "${safe_tableAlias}_list_")
944 + #else
945 + #set ($paramPrefix = $NULL)
946 + #end
897 897   #end
898 - #set ($joinPos = $mathtool.add($fromSql.lastIndexOf(" $safe_tableAlias"), $mathtool.add($safe_tableAlias.length(), 1)))
899 - #set ($fromSql = "$fromSql.substring(0, $joinPos) join ${safe_tableAlias}.list as $matchTarget $fromSql.substring($joinPos)")
900 - #else
901 - ## Fall-back on exact matching even if the match type is specified, when its value is not supported.
902 - #set ($matchType = 'exact')
903 - #set ($matchTarget = "${safe_tableAlias}.list")
904 - #if ($whereParams.entrySet())
905 - #set ($paramPrefix = "${safe_tableAlias}_list_")
948 +
949 + #set ($filterQuery = "#livetable_getFilterQuery($matchTarget $matchType true $nonEmptyValues.size() $paramPrefix $NULL)")
950 + #if (!$hasEmpty)
951 + ## Only non-empty values are used, combine directly with the existing constraints, otherwise, they will be
952 + ## combined later together with the empty constraint.
953 + #set ($whereSql = "$whereSql and ($filterQuery.trim())")
954 + #end
955 + #foreach ($filterValue in $nonEmptyValues)
956 + #livetable_addFilterParam($filterValue $matchType $whereParams "${paramPrefix}${foreach.count}")
957 + #end
958 + #end
959 +
960 + ## 2) Optionally add a single constraint if any match type is 'empty'.
961 + #if ($hasEmpty)
962 + ## "empty" means that there is no list item stored for this property on the filtered object.
963 + ## The proper way to check for that would be "${safe_tableAlias}.list IS EMPTY", but JSQL cannot parse "IS EMPTY"
964 + ## which means that we cannot use it without programming right.
965 + #set ($emptyConstraint = "size(${safe_tableAlias}.list) = 0")
966 + #if ($nonEmptyValues.isEmpty())
967 + ## Only 'empty' is used, combine with the existing constraints.
968 + #set ($whereSql = "${whereSql} and ${emptyConstraint}")
906 906   #else
907 - #set ($paramPrefix = $NULL)
970 + ## Combine non-empty group and empty condition using the join operator.
971 + #set ($whereSql = "${whereSql} and ($filterQuery.trim() ${joinOperator} ${emptyConstraint})")
908 908   #end
909 909   #end
910 - #set ($filterQuery = "#livetable_getFilterQuery($matchTarget $matchType true $filterValues.size() $paramPrefix $NULL)")
911 - #set ($whereSql = "$whereSql and ($filterQuery.trim())")
912 - #foreach ($filterValue in $filterValues)
913 - #livetable_addFilterParam($filterValue $matchType $whereParams "${paramPrefix}${foreach.count}")
914 - #end
915 915  #end
916 916  
917 917  
... ... @@ -1006,9 +1006,9 @@
1006 1006   #if ($matchType == 'partial' || $matchType == 'prefix')
1007 1007   #livetable_repeatParams("upper($column) like upper(?)", " $joinOperator ", $valueCount, $paramPrefix, $paramOffset)
1008 1008   #elseif($matchType == 'empty')
1009 - ## Check if the value of the column is like the empty parameter (which is often the empty string), or if the value
1068 + ## Check if the value of the column is like the empty parameter (which is often the empty string), or if the value
1010 1010   ## of the column is null (to be compliant with Oracle which stores the empty string as a NULL value).
1011 - #livetable_repeatParams("($column like ? or $column is null)", " $joinOperator ", $valueCount, $paramPrefix,
1070 + #livetable_repeatParams("($column like ? or $column is null)", " $joinOperator ", $valueCount, $paramPrefix,
1012 1012   $paramOffset)
1013 1013   #elseif ($isList)
1014 1014   #livetable_repeatParams("? in elements($column)", " $joinOperator ", $valueCount, $paramPrefix, $paramOffset)