Änderungen von Dokument Live-Table Ergebnismakros
Zuletzt geändert von Daniel Herrmann am 2026/02/07 23:25
Von Version
2.1
bearbeitet von Daniel Herrmann
am 2025/09/20 09:52
am 2025/09/20 09:52
Änderungskommentar:
Install extension [org.xwiki.platform:xwiki-platform-livetable-ui/17.7.0]
Auf Version
3.1
bearbeitet von Daniel Herrmann
am 2026/02/04 20:23
am 2026/02/04 20:23
Änderungskommentar:
Install extension [org.xwiki.platform:xwiki-platform-livetable-ui/17.10.3]
Zusammenfassung
Details
- Seiteneigenschaften
-
- Inhalt
-
... ... @@ -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) ... ... @@ -557,8 +557,10 @@ 557 557 #elseif($propType == 'TextAreaClass' || $propType == 'UsersClass' || $propType == 'GroupsClass') 558 558 #set($tableName = 'LargeStringProperty') 559 559 #elseif($propType == 'StaticListClass' || $propType == 'DBListClass' || $propType == 'DBTreeListClass' || $propType == 'PageClass') 561 + ## The following logic is mirrored from ListClass and might need to be updated when the logic in ListClass changes. 560 560 #set($multiSelect = $propClass.get($colname).getProperty('multiSelect').getValue()) 561 561 #set($relationalStorage = $propClass.get($colname).getProperty('relationalStorage').getValue()) 564 + #set($largeStorage = $propClass.get($colname).getProperty('largeStorage').getValue()) 562 562 #if($multiSelect == 1) 563 563 #if($relationalStorage == 1) 564 564 #set($tableName = 'DBStringListProperty') ... ... @@ -565,6 +565,8 @@ 565 565 #else 566 566 #set($tableName = 'StringListProperty') 567 567 #end 571 + #elseif($largeStorage == 1) 572 + #set($tableName = 'LargeStringProperty') 568 568 #else 569 569 #set($tableName = 'StringProperty') 570 570 #end ... ... @@ -686,6 +686,19 @@ 686 686 #elseif ($colName == 'doc.date' || $colName == 'doc.creationDate' || $colName == 'doc.contentUpdateDate') 687 687 #livetable_getTableAlias($colName) 688 688 #livetable_filterDateProperty() 694 + #elseif ($colName == 'doc.hidden' || $colName == 'doc.minorEdit1' || $colName == 'doc.enforceRequiredRights') 695 + ## Boolean document fields need special handling to work across all databases 696 + ## (HSQLDB/PostgreSQL use true/false, MySQL/MariaDB/Oracle use 1/0). 697 + ## Support both true/false and 1/0 as Live Data uses the former while LiveTable uses the latter. 698 + #set ($booleanValue = ($filterValue.toLowerCase() == 'true' || $filterValue == '1')) 699 + ## No need to clean the column name since it's only one of the given values. 700 + #if ($whereParams.entrySet()) 701 + #set ($whereSql = "${whereSql} and $colName = :${colName.replace('.', '_')}_filter") 702 + #set ($discard = $whereParams.put("${colName.replace('.', '_')}_filter", $booleanValue)) 703 + #else 704 + #set ($whereSql = "${whereSql} and $colName = ?") 705 + #set ($discard = $whereParams.add($booleanValue)) 706 + #end 689 689 #else 690 690 #set ($safeColName = $colName.replaceAll('[^a-zA-Z0-9_.]', '').replace('_', '.')) 691 691 #if ($whereParams.entrySet()) ... ... @@ -878,34 +878,79 @@ 878 878 *# 879 879 #macro (livetable_filterDBStringListProperty) 880 880 ## Perform exact matching by default if no match type is specified. 881 - ## Note that for DBStringList properties we takeintoaccount onlythefirstmatch type,evenifmultiplefilter882 - ## valuesare specified. Basicallythefirst match type isused for allfilter values.899 + ## For DBStringList properties we still apply a single match type to all non-empty values, but we also allow 900 + ## combining the special "empty" match type with other match types. 883 883 #livetable_getMatchTypes($colname $filterValues.size() 'exact') 884 - #if ($matchType == 'partial' || $matchType == 'prefix') 885 - ## We need to join with the list of values in order to be able to use the LIKE operator. 886 - #set ($matchTarget = "${safe_tableAlias}_item") 887 - #if ($whereParams.entrySet()) 888 - #set ($paramPrefix = "${safe_tableAlias}_item_") 902 + #livetable_getJoinOperator($colname) 903 + 904 + ## Collect non-empty filter values (those whose match type is not 'empty'). 905 + #set ($nonEmptyValues = []) 906 + #set ($hasEmpty = false) 907 + #set ($matchType = 'invalid') 908 + #foreach ($filterValue in $filterValues) 909 + #if ($matchTypes.get($foreach.index) == 'empty') 910 + #set ($hasEmpty = true) 911 + ## When we want to match empty values, we can't have other match types than exact for non-empty values as for 912 + ## other match types, we need to join with the list of values, which is not compatible with checking for 913 + ## emptiness. 914 + #set ($matchType = 'exact') 915 + #elseif ("$!filterValue" != '') 916 + #set ($discard = $nonEmptyValues.add($filterValue)) 917 + ## Store the first non-empty match type. 918 + #if ($matchType == 'invalid') 919 + #set ($matchType = $matchTypes.get($foreach.index)) 920 + #end 921 + #end 922 + #end 923 + 924 + ## 1) Apply the non-empty constraints. 925 + #if (!$nonEmptyValues.isEmpty()) 926 + #if ($matchType == 'partial' || $matchType == 'prefix') 927 + ## We need to join with the list of values in order to be able to use the LIKE operator. 928 + #set ($matchTarget = "${safe_tableAlias}_item") 929 + #if ($whereParams.entrySet()) 930 + #set ($paramPrefix = "${safe_tableAlias}_item_") 931 + #else 932 + #set ($paramPrefix = $NULL) 933 + #end 934 + #set ($joinPos = $mathtool.add($fromSql.lastIndexOf(" $safe_tableAlias"), $mathtool.add($safe_tableAlias.length(), 1))) 935 + #set ($fromSql = "$fromSql.substring(0, $joinPos) join ${safe_tableAlias}.list as $matchTarget $fromSql.substring($joinPos)") 889 889 #else 890 - #set ($paramPrefix = $NULL) 937 + ## Fall-back on exact matching even if the match type is specified, when its value is not supported. 938 + #set ($matchType = 'exact') 939 + #set ($matchTarget = "${safe_tableAlias}.list") 940 + #if ($whereParams.entrySet()) 941 + #set ($paramPrefix = "${safe_tableAlias}_list_") 942 + #else 943 + #set ($paramPrefix = $NULL) 944 + #end 891 891 #end 892 - #set ($joinPos = $mathtool.add($fromSql.lastIndexOf(" $safe_tableAlias"), $mathtool.add($safe_tableAlias.length(), 1))) 893 - #set ($fromSql = "$fromSql.substring(0, $joinPos) join ${safe_tableAlias}.list as $matchTarget $fromSql.substring($joinPos)") 894 - #else 895 - ## Fall-back on exact matching even if the match type is specified, when its value is not supported. 896 - #set ($matchType = 'exact') 897 - #set ($matchTarget = "${safe_tableAlias}.list") 898 - #if ($whereParams.entrySet()) 899 - #set ($paramPrefix = "${safe_tableAlias}_list_") 946 + 947 + #set ($filterQuery = "#livetable_getFilterQuery($matchTarget $matchType true $nonEmptyValues.size() $paramPrefix $NULL)") 948 + #if (!$hasEmpty) 949 + ## Only non-empty values are used, combine directly with the existing constraints, otherwise, they will be 950 + ## combined later together with the empty constraint. 951 + #set ($whereSql = "$whereSql and ($filterQuery.trim())") 952 + #end 953 + #foreach ($filterValue in $nonEmptyValues) 954 + #livetable_addFilterParam($filterValue $matchType $whereParams "${paramPrefix}${foreach.count}") 955 + #end 956 + #end 957 + 958 + ## 2) Optionally add a single constraint if any match type is 'empty'. 959 + #if ($hasEmpty) 960 + ## "empty" means that there is no list item stored for this property on the filtered object. 961 + ## The proper way to check for that would be "${safe_tableAlias}.list IS EMPTY", but JSQL cannot parse "IS EMPTY" 962 + ## which means that we cannot use it without programming right. 963 + #set ($emptyConstraint = "size(${safe_tableAlias}.list) = 0") 964 + #if ($nonEmptyValues.isEmpty()) 965 + ## Only 'empty' is used, combine with the existing constraints. 966 + #set ($whereSql = "${whereSql} and ${emptyConstraint}") 900 900 #else 901 - #set ($paramPrefix = $NULL) 968 + ## Combine non-empty group and empty condition using the join operator. 969 + #set ($whereSql = "${whereSql} and ($filterQuery.trim() ${joinOperator} ${emptyConstraint})") 902 902 #end 903 903 #end 904 - #set ($filterQuery = "#livetable_getFilterQuery($matchTarget $matchType true $filterValues.size() $paramPrefix $NULL)") 905 - #set ($whereSql = "$whereSql and ($filterQuery.trim())") 906 - #foreach ($filterValue in $filterValues) 907 - #livetable_addFilterParam($filterValue $matchType $whereParams "${paramPrefix}${foreach.count}") 908 - #end 909 909 #end 910 910 911 911 ... ... @@ -1000,9 +1000,9 @@ 1000 1000 #if ($matchType == 'partial' || $matchType == 'prefix') 1001 1001 #livetable_repeatParams("upper($column) like upper(?)", " $joinOperator ", $valueCount, $paramPrefix, $paramOffset) 1002 1002 #elseif($matchType == 'empty') 1003 - ## Check if the value of the column is like the empty parameter (which is often the empty string), or if the value 1066 + ## Check if the value of the column is like the empty parameter (which is often the empty string), or if the value 1004 1004 ## of the column is null (to be compliant with Oracle which stores the empty string as a NULL value). 1005 - #livetable_repeatParams("($column like ? or $column is null)", " $joinOperator ", $valueCount, $paramPrefix, 1068 + #livetable_repeatParams("($column like ? or $column is null)", " $joinOperator ", $valueCount, $paramPrefix, 1006 1006 $paramOffset) 1007 1007 #elseif ($isList) 1008 1008 #livetable_repeatParams("? in elements($column)", " $joinOperator ", $valueCount, $paramPrefix, $paramOffset)