diff --git a/data/System/DBCachePlugin.txt b/data/System/DBCachePlugin.txt
index 3742dd4..72a1074 100644
--- a/data/System/DBCachePlugin.txt
+++ b/data/System/DBCachePlugin.txt
@@ -218,6 +218,9 @@ Compute and format a statistics on the database.
| ="<search>"= | query string that defines a search, see DBCacheContrib |
| =web="..."= | the web where to search in (default: current web) |
| =field(s)="..."= | name of one or more formfields to be extracted (default: "text") |
+| =process="..."= | macro being used to post-process field values extracted from the database; macro are escaped using standard format tokens (=$percnt=, =$dollar=, etc); \
+ the result is used instead of the direct field value; when extracting multiple =fields=, specific process statements might be specified using \
+ =process_<field-name1>=, =process_<field-name2=, ... |
| =split="..."= | regex split up a field value into a list before matching each item against =pattern= |
| =pattern="..."= | regex pattern to extract keys from the formfield(s); \
note, that before the pattern is applied the field value is split up using the =split= parameter; \
@@ -273,6 +276,21 @@ Note, that the above pattern will crop away the day. Groups can be nested counti
them from left to right, outside to inside: the first group matches the
compete pattern, the second the month the third the year.
+Post-processing field values using a =process= macro comes in handy when dealing with formfields of type =date=.
+As these are stored in epoch seconds, you might decide to format them into an appropriate way before generating statistics on its base:
+
+
+%DBSTATS{
+ "form='Invoice'"
+ field="PaidDate"
+ process="$percntDATETIME{\"$value\" format=\"$month $year\"}$percnt"
+ pattern="(.*?) (\d\d\d\d)"
+...
+}%
+
+
+While the real value of a "PaidDate" formfield is stored in epoch seconds, statistics make more sense on a per month basis.
+
---+++ TOPICTITLE
derive the title of a topic from a couple of properties:
@@ -454,6 +472,9 @@ automatically from there on.
---++ Change History
%TABLE{columnwidths="7em" tablewidth="100%"}%
+| 26 Nov 2018: | added =process= parameter to =DBSTATS= to post-process field values before generating statistics; \
+ return the empty string instead of ??? when parsing an empty or zero time value; \
+ disabled dependency injection of =DBSTATS= into the page cache for performance reasons (still there for =DBQUERY=) |
| 01 Oct 2018: | rationalized handing date data |
| 28 May 2018: | remove local implementation of !TopicTitle; depend on !TopicTitlePlugin instead; \
new parameter =dateformat= for =DBQUERY=; performance improvements in =DBQUERY= |
diff --git a/lib/Foswiki/Plugins/DBCachePlugin.pm b/lib/Foswiki/Plugins/DBCachePlugin.pm
index e737377..05c8f89 100644
--- a/lib/Foswiki/Plugins/DBCachePlugin.pm
+++ b/lib/Foswiki/Plugins/DBCachePlugin.pm
@@ -25,8 +25,8 @@ use Foswiki::Plugins();
#Monitor::MonitorMethod('Foswiki::Contrib::DBCachePlugin::Core');
#Monitor::MonitorMethod('Foswiki::Contrib::DBCachePlugin::WebDB');
-our $VERSION = '12.00';
-our $RELEASE = '01 Oct 2018';
+our $VERSION = '12.10';
+our $RELEASE = '26 Nov 2018';
our $NO_PREFS_IN_TOPIC = 1;
our $SHORTDESCRIPTION = 'Lightweighted frontend to the DBCacheContrib';
diff --git a/lib/Foswiki/Plugins/DBCachePlugin/Core.pm b/lib/Foswiki/Plugins/DBCachePlugin/Core.pm
index ee6c413..be33a3d 100644
--- a/lib/Foswiki/Plugins/DBCachePlugin/Core.pm
+++ b/lib/Foswiki/Plugins/DBCachePlugin/Core.pm
@@ -208,6 +208,7 @@ sub handleDBQUERY {
my $theHideNull = Foswiki::Func::isTrue($params->{hidenull}, 0);
my $theRemote = Foswiki::Func::isTrue($params->remove('remote'), 0);
my $theNewline = $params->{newline};
+ my $theContext = $params->{context};
my $doWarnings = Foswiki::Func::isTrue($params->{warn}, 1);
$theFormat = '$topic' unless defined $theFormat;
@@ -275,7 +276,7 @@ sub handleDBQUERY {
$this->{currentWeb} = $web;
# collect hit set
- $hits = $theDB->dbQuery($theSearch, \@topicNames, $theSort, $theReverse, $theInclude, $theExclude, $hits);
+ $hits = $theDB->dbQuery($theSearch, \@topicNames, $theSort, $theReverse, $theInclude, $theExclude, $hits, $theContext);
$this->{currentWeb} = undef;
}
@@ -295,12 +296,12 @@ sub handleDBQUERY {
my $index = $hits->skip($theSkip);
my $lastWeb = '';
my $theDB;
- while (my $topicObj = $hits->next) {
+ while (my $obj = $hits->next) {
#_writeDebug("topicName=$topicName");
$index++;
- my $topicName = $topicObj->fastget("topic");
- my $web = $topicObj->fastget("web");
+ my $topicName = $obj->fastget("topic");
+ my $web = $obj->fastget("web");
$web =~ s/\//./g;
$theDB = $this->getDB($web) if !$theDB || $lastWeb ne $web;
$lastWeb = $web;
@@ -310,7 +311,7 @@ sub handleDBQUERY {
}
my $line = $theFormat;
- $line =~ s/\$pattern\((.*?)\)/_extractPattern($topicObj, $1)/ge;
+ $line =~ s/\$pattern\((.*?)\)/_extractPattern($obj, $1)/ge;
$line =~ s/\$formfield\((.*?)\)/
my $temp = $theDB->getFormField($topicName, $1);
$temp =~ s#\)#${TranslationToken}#g;
@@ -318,18 +319,18 @@ sub handleDBQUERY {
$temp/geo;
$line =~ s/\$expand\((.*?)\)/
my $temp = $1;
- $temp = $theDB->expandPath($topicObj, $temp);
+ $temp = $theDB->expandPath($obj, $temp);
$temp =~ s#\)#${TranslationToken}#g;
$temp/geo;
$line =~ s/\$html\((.*?)\)/
my $temp = $1;
- $temp = $theDB->expandPath($topicObj, $temp);
+ $temp = $theDB->expandPath($obj, $temp);
$temp =~ s#\)#${TranslationToken}#g;
$temp = Foswiki::Func::expandCommonVariables($temp, $topicName, $web);
$temp = Foswiki::Func::renderText($temp, $web, $topicName);
$temp/geo;
- $line =~ s/\$d2n\((.*?)\)/Foswiki::Contrib::DBCacheContrib::parseDate($theDB->expandPath($topicObj, $1))||0/ge;
- $line =~ s/\$formatTime\((.*?)(?:,\s*'([^']*?)')?\)/_formatTime($theDB->expandPath($topicObj, $1), $2)/ge; # single quoted
+ $line =~ s/\$d2n\((.*?)\)/Foswiki::Contrib::DBCacheContrib::parseDate($theDB->expandPath($obj, $1))||0/ge;
+ $line =~ s/\$formatTime\((.*?)(?:,\s*'([^']*?)')?\)/_formatTime($theDB->expandPath($obj, $1), $2)/ge; # single quoted
$line =~ s/\$topic/$topicName/g;
$line =~ s/\$web/$web/g;
$line =~ s/\$index/$index/g;
@@ -411,9 +412,8 @@ sub findTopicMethod {
#_writeDebug("topicTypes=$topicTypes");
+ $topicTypes =~ s/^\s+|\s+$//g;
foreach my $topicType (split(/\s*,\s*/, $topicTypes)) {
- $topicType =~ s/^\s+//o;
- $topicType =~ s/\s+$//o;
#_writeDebug(".... topicType=$topicType");
@@ -613,24 +613,24 @@ sub handleDBSTATS {
# get args
my $baseWeb = $session->{webName};
my $baseTopic = $session->{topicName};
- my $theSearch = $params->{_DEFAULT} || $params->{search} || '';
- my $thisWeb = $params->{web} || $baseWeb;
- my $thisTopic = $params->{topic} || $baseTopic;
+ my $theSearch = $params->{_DEFAULT} // $params->{search} // '';
+ my $thisWeb = $params->{web} // $baseWeb;
+ my $thisTopic = $params->{topic} // $baseTopic;
my $thisTopics = $params->{topics};
- my $thePattern = $params->{pattern} || '^(.*)$';
- my $theSplit = $params->{split} || '\s*,\s*';
- my $theHeader = $params->{header} || '';
+ my $thePattern = $params->{pattern} // '^(.*)$';
+ my $theSplit = $params->{split} // '\s*,\s*';
+ my $theHeader = $params->{header} // '';
my $theFormat = $params->{format};
- my $theFooter = $params->{footer} || '';
+ my $theFooter = $params->{footer} // '';
my $theSep = $params->{separator};
- my $theFields = $params->{fields} || $params->{field} || 'text';
- my $theSort = $params->{sort} || $params->{order} || 'alpha';
+ my $theFields = $params->{fields} // $params->{field} // 'text';
+ my $theSort = $params->{sort} // $params->{order} // 'alpha';
my $theReverse = Foswiki::Func::isTrue($params->{reverse}, 0);
- my $theLimit = $params->{limit} || 0;
+ my $theLimit = $params->{limit} // 0;
my $theHideNull = Foswiki::Func::isTrue($params->{hidenull}, 0);
my $theExclude = $params->{exclude};
my $theInclude = $params->{include};
- my $theDateFormat = $params->{dateformat} || $Foswiki::cfg{DefaultDateFormat};
+ my $theDateFormat = $params->{dateformat} // $Foswiki::cfg{DefaultDateFormat};
my $theCase = Foswiki::Func::isTrue($params->{casesensitive}, 0);
$theLimit =~ s/[^\d]//g;
@@ -685,7 +685,7 @@ sub handleDBSTATS {
my $publishDate = $topicObj->get('publishdate') || 0;
foreach my $field (split(/\s*,\s*/, $theFields)) { # loop over all fields
my $fieldValue = $topicObj->fastget($field);
- if (!$fieldValue || ref($fieldValue)) {
+ if (!defined($fieldValue) || ref($fieldValue)) {
my $topicForm = $topicObj->fastget('form');
#_writeDebug("found form $topicForm");
if ($topicForm) {
@@ -694,16 +694,23 @@ sub handleDBSTATS {
}
}
next unless $fieldValue; # unless present
- $fieldValue = _formatTime($fieldValue, $theDateFormat) if $field =~ /created(ate)?|modified|publishdate/;
+ my $command = $params->{process} // $params->{"process_".$field};
+ if (defined $command) {
+ $command = Foswiki::Func::decodeFormatTokens($command);
+ $command =~ s/\$value/$fieldValue/g;
+ $fieldValue = Foswiki::Func::expandCommonVariables($command, $topicName, $thisWeb);
+ } else {
+ $fieldValue = _formatTime($fieldValue, $theDateFormat) if $field =~ /created(ate)?|modified|publishdate/;
+ }
#_writeDebug("reading field $field found $fieldValue");
foreach my $item (split(/$theSplit/, $fieldValue)) {
while ($item =~ /$thePattern/g) { # loop over all occurrences of the pattern
my $key1 = $1;
- my $key2 = $2 || '';
- my $key3 = $3 || '';
- my $key4 = $4 || '';
- my $key5 = $5 || '';
+ my $key2 = $2 // '';
+ my $key3 = $3 // '';
+ my $key4 = $4 // '';
+ my $key5 = $5 // '';
if ($theCase) {
next if $theExclude && $key1 =~ /$theExclude/;
next if $theInclude && $key1 !~ /$theInclude/;
@@ -738,7 +745,9 @@ sub handleDBSTATS {
}
}
}
- $Foswiki::Plugins::DBCachePlugin::addDependency->($thisWeb, $topicName);
+
+ # Disabled for performance reasons: in the end all topics of a web will be added anyway
+ #$Foswiki::Plugins::DBCachePlugin::addDependency->($thisWeb, $topicName);
}
my $min = 99999999;
my $max = 0;
@@ -830,8 +839,8 @@ sub handleDBDUMP {
my $baseWeb = $session->{webName};
my $baseTopic = $session->{topicName};
- my $thisTopic = $params->{_DEFAULT} || $baseTopic;
- my $thisWeb = $params->{web} || $baseWeb;
+ my $thisTopic = $params->{_DEFAULT} // $baseTopic;
+ my $thisWeb = $params->{web} // $baseWeb;
($thisWeb, $thisTopic) = Foswiki::Func::normalizeWebTopicName($thisWeb, $thisTopic);
$Foswiki::Plugins::DBCachePlugin::addDependency->($thisWeb, $thisTopic);
@@ -861,7 +870,7 @@ sub dbDump {
my $theDB = $this->getDB($web);
return _inlineError("ERROR: DBDUMP can't find web '$web'") unless $theDB;
- my $topicObj = $theDB->fastget($topic) || '';
+ my $topicObj = $theDB->fastget($topic) // '';
unless ($topicObj) {
return _inlineError("DBCachePlugin: $web.$topic not found");
}
@@ -879,28 +888,28 @@ sub handleDBRECURSE {
my $baseWeb = $session->{webName};
my $baseTopic = $session->{topicName};
- my $thisTopic = $params->{_DEFAULT} || $params->{topic} || $baseTopic;
- my $thisWeb = $params->{web} || $baseWeb;
+ my $thisTopic = $params->{_DEFAULT} // $params->{topic} // $baseTopic;
+ my $thisWeb = $params->{web} // $baseWeb;
my $doWarnings = Foswiki::Func::isTrue($params->{warn}, 1);
($thisWeb, $thisTopic) = Foswiki::Func::normalizeWebTopicName($thisWeb, $thisTopic);
$params->{format} //= ' $indent* [[$web.$topic][$topic]]';
- $params->{single} ||= $params->{format};
+ $params->{single} //= $params->{format};
$params->{separator} //= $params->{sep} // "\n";
- $params->{header} ||= '';
- $params->{subheader} ||= '';
- $params->{singleheader} ||= $params->{header};
- $params->{footer} ||= '';
- $params->{subfooter} ||= '';
- $params->{singlefooter} ||= $params->{footer};
- $params->{hidenull} ||= 'off';
- $params->{filter} ||= 'parent=\'$name\'';
- $params->{sort} ||= $params->{order} || 'name';
- $params->{reverse} ||= 'off';
- $params->{limit} ||= 0;
- $params->{skip} ||= 0;
- $params->{depth} ||= 0;
+ $params->{header} //= '';
+ $params->{subheader} //= '';
+ $params->{singleheader} //= $params->{header};
+ $params->{footer} //= '';
+ $params->{subfooter} //= '';
+ $params->{singlefooter} //= $params->{footer};
+ $params->{hidenull} //= 'off';
+ $params->{filter} //= 'parent=\'$name\'';
+ $params->{sort} //= $params->{order} // 'name';
+ $params->{reverse} //= 'off';
+ $params->{limit} //= 0;
+ $params->{skip} //= 0;
+ $params->{depth} //= 0;
$params->{format} = '' if $params->{format} eq 'none';
$params->{single} = '' if $params->{single} eq 'none';
@@ -952,8 +961,8 @@ sub formatRecursive {
$seen ||= {};
return if $seen->{$theTopic};
$seen->{$theTopic} = 1;
- $depth ||= 0;
- $number ||= '';
+ $depth //= 0;
+ $number //= '';
return if $params->{depth} && $depth >= $params->{depth};
return if $params->{limit} && $params->{_count} >= $params->{limit};
@@ -1061,8 +1070,10 @@ sub getDB {
my ($this, $theWeb, $refresh) = @_;
$refresh = $this->{doRefresh} unless defined $refresh;
+ $refresh = 0 if $refresh && $this->{doneRefreshWeb}{$theWeb};
+ $this->{doneRefreshWeb}{$theWeb} = 1;
- #_writeDebug("called getDB($theWeb, ".($refresh||0).")");
+ _writeDebug("called getDB($theWeb, ".($refresh||0).")");
my $webKey = $this->getWebKey($theWeb);
return unless defined $webKey; # invalid webname
@@ -1082,16 +1093,17 @@ sub getDB {
$isModified = 1;
}
- if ($isModified) {
- $db = $webDB{$webKey} = $this->newDB($theWeb);
- }
-
if ($isModified || $refresh) {
+ $db = $webDB{$webKey} = $this->newDB($theWeb);
+ $db->load($refresh);
#_writeDebug("need to load again");
- my $baseWeb = $Foswiki::Plugins::SESSION->{webName};
- my $baseTopic = $Foswiki::Plugins::SESSION->{topicName};
- $db->load($refresh, $baseWeb, $baseTopic);
- $this->{doRefresh} = 0;
+
+ my $session = $Foswiki::Plugins::SESSION;
+ my $baseWeb = $session->{webName};
+ my $baseTopic = $session->{topicName};
+ if ($baseWeb eq $theWeb) {
+ $db->load($refresh, $baseWeb, $baseTopic);
+ }
}
return $db;
@@ -1128,6 +1140,8 @@ sub finish {
undef $this->{isModifiedDB};
undef $this->{dbcalls};
undef $this->{currentWeb};
+ undef $this->{doRefresh};
+ undef $this->{doneRefreshWeb};
}
###############################################################################
@@ -1240,7 +1254,7 @@ sub _dbDumpArray {
foreach my $obj (sort $array->getValues()) {
$result .= "";
if (UNIVERSAL::can($obj, "fastget")) {
- $result .= ($obj->fastget('name') || '');
+ $result .= ($obj->fastget('name') // '');
} else {
$result .= $index;
}
@@ -1306,6 +1320,7 @@ sub _expandVariables {
sub _formatTime {
my ($string, $format) = @_;
+ return "" if $string eq "" || $string eq "0";
my $epoch = Foswiki::Contrib::DBCacheContrib::parseDate($string);
return '???' unless defined($epoch) && $epoch != 0;
diff --git a/lib/Foswiki/Plugins/DBCachePlugin/Hits.pm b/lib/Foswiki/Plugins/DBCachePlugin/Hits.pm
index 5a30884..dd0fdab 100644
--- a/lib/Foswiki/Plugins/DBCachePlugin/Hits.pm
+++ b/lib/Foswiki/Plugins/DBCachePlugin/Hits.pm
@@ -45,51 +45,54 @@ sub new {
$this->{_isNumerical} = 1;
$this->{_index} = 0;
$this->{_count} = 0;
- $this->{_sortPropOfTopic} = {};
+ $this->{_sortPropOfObj} = {};
$this->{_sortIndex} = undef;
return $this;
}
sub add {
- my ($this, $topic, $obj) = @_;
+ my ($this, $name, $obj) = @_;
+ my $key = $name;
my $web = $obj->fastget("web");
- my $key = $web . "." . $topic;
+ $key = $web . "." . $key if defined $web;
+
$this->{_objects}{$key} = $obj;
# sort by name
if ($this->{sorting} =~ /^(on|name)$/) {
- $this->{_sortPropOfTopic}{$key} = $topic;
+ $this->{_sortPropOfObj}{$key} = $name;
$this->{_isNumerical} = 0;
}
# sort by create date
elsif ($this->{sorting} =~ /^created/) {
- $this->{_sortPropOfTopic}{$key} = $obj->fastget('createdate');
+ $this->{_sortPropOfObj}{$key} = $obj->fastget('createdate');
}
# sort by date
elsif ($this->{sorting} =~ /^(modified|info\.date)/) {
my $info = $obj->fastget('info');
- $this->{_sortPropOfTopic}{$key} = $info ? $info->fastget('date') : 0;
+ $this->{_sortPropOfObj}{$key} = $info ? $info->fastget('date') : 0;
}
# sort randomly
elsif ($this->{sorting} =~ /^rand(om)?$/) {
- $this->{_sortPropOfTopic}{$key} = rand();
+ $this->{_sortPropOfObj}{$key} = rand();
}
# sort by time added
elsif ($this->{sorting} =~ /^off$/i) {
- $this->{_sortPropOfTopic}{$key} = $this->{_count};
+ $this->{_sortPropOfObj}{$key} = $this->{_count};
}
# sort by property
else {
my $format = $this->{sorting};
$format =~ s/\$web/$web/g;
- $format =~ s/\$topic/$topic/g;
+ $format =~ s/\$topic/$name/g;
+ $format =~ s/\$name/$name/g;
$format =~ s/\$perce?nt/\%/g;
$format =~ s/\$nop//g;
$format =~ s/\$n/\n/g;
@@ -109,12 +112,12 @@ sub add {
$val = $epoch if defined $epoch;
}
- $this->{_sortPropOfTopic}{$key} = $val;
+ $this->{_sortPropOfObj}{$key} = $val;
- #print STDERR "key=$key, path=$path, sortProp=".$this->{_sortPropOfTopic}{$key}."\n";
+ #print STDERR "key=$key, path=$path, sortProp=".$this->{_sortPropOfObj}{$key}."\n";
$this->{_isNumerical} = 0
- if $this->{_isNumerical} && $this->{_sortPropOfTopic}{$key} && !($this->{_sortPropOfTopic}{$key} =~ /^[+-]?\d+(\.\d+)?$/);
+ if $this->{_isNumerical} && $this->{_sortPropOfObj}{$key} && !($this->{_sortPropOfObj}{$key} =~ /^[+-]?\d+(\.\d+)?$/);
}
$this->{_count}++;
@@ -143,7 +146,7 @@ sub init {
my @keys = keys %{$this->{_objects}};
- my $props = $this->{_sortPropOfTopic};
+ my $props = $this->{_sortPropOfObj};
if (scalar(@keys) > 1) {
if ($this->{_isNumerical}) {
diff --git a/lib/Foswiki/Plugins/DBCachePlugin/WebDB.pm b/lib/Foswiki/Plugins/DBCachePlugin/WebDB.pm
index f39fcee..7c10570 100644
--- a/lib/Foswiki/Plugins/DBCachePlugin/WebDB.pm
+++ b/lib/Foswiki/Plugins/DBCachePlugin/WebDB.pm
@@ -22,6 +22,7 @@ use warnings;
use Foswiki::Contrib::DBCacheContrib ();
use Foswiki::Contrib::DBCacheContrib::Search ();
+use Foswiki::Contrib::DBCacheContrib::MemMap ();
use Foswiki::Plugins::DBCachePlugin ();
use Foswiki::Plugins::DBCachePlugin::Hits ();
use Foswiki::Attrs ();
@@ -63,12 +64,12 @@ sub load {
my ($this, $refresh, $web, $topic) = @_;
$refresh ||= 0;
- writeDebug("called load() for $this->{web}, refresh=$refresh");
+ writeDebug("called load($refresh, ".($web//'undef').", ".($topic//'undef')."), refresh=$refresh");
- if ($refresh == 1 && defined($web) && defined($topic)) {
+ if ($refresh && defined($web) && defined($topic)) {
# refresh a single topic
+ $this->remove($topic);
$this->loadTopic($web, $topic);
- $refresh = 0;
}
$this->SUPER::load($refresh);
@@ -97,6 +98,7 @@ sub onReload {
# get meta object
my ($meta, $text) = Foswiki::Func::readTopic($this->{web}, $topic);
$this->cleanUpText($text);
+ $text //= "";
# SMELL: call getRevisionInfo to make sure the latest revision is loaded
# for get('TOPICINFO') further down the code
@@ -256,7 +258,7 @@ sub getNeighbourTopics {
###############################################################################
sub dbQuery {
- my ($this, $theSearch, $theTopics, $theSort, $theReverse, $theInclude, $theExclude, $hits) = @_;
+ my ($this, $theSearch, $theTopics, $theSort, $theReverse, $theInclude, $theExclude, $hits, $theContext) = @_;
# get max hit set
my @topicNames;
@@ -269,49 +271,49 @@ sub dbQuery {
@topicNames = grep(!/$theExclude/, @topicNames) if $theExclude;
# parse & fetch
- my $wikiName = Foswiki::Func::getWikiName();
my $search;
if ($theSearch) {
$search = new Foswiki::Contrib::DBCacheContrib::Search($theSearch);
}
- my $isAdmin = Foswiki::Func::isAnAdmin();
- my $webViewPermission = $isAdmin || Foswiki::Func::checkAccessPermission('VIEW', $wikiName, undef, undef, $this->{web});
-
$hits ||= Foswiki::Plugins::DBCachePlugin::Hits->new(
sorting => $theSort,
reverse => $theReverse,
);
+ my $testObj;
+ $testObj = new Foswiki::Contrib::DBCacheContrib::MemMap() if $theContext;
+
foreach my $topicName (@topicNames) {
my $topicObj = $this->fastget($topicName);
next unless $topicObj; # never
- if (!$search || $search->matches($topicObj, {webDB=>$this})) {
-
- my $topicHasPerms = 0;
- unless ($isAdmin) {
- my $prefs = $topicObj->fastget('preferences');
- if (defined($prefs)) {
- foreach my $key ($prefs->getKeys()) {
- if ($key =~ /^(ALLOW|DENY)TOPIC/) {
- $topicHasPerms = 1;
- last;
- }
- }
+ if ($theContext) { # SMELL: experimental
+ my $context = $topicObj->fastget($theContext);
+ next unless $context;
+ my $topicViewAccess = $this->_hasViewAccess($topicName, $topicObj);
+
+ foreach my $obj ($context->getValues()) {
+ my $name = $obj->fastget("name");
+
+ # init testObj
+ %{$testObj} = ();
+ while (my ($k, $v) = each %$obj) {
+ $testObj->{$k} = $v;
+ }
+ $testObj->set('web', $this->{web});
+ $testObj->set('topic', $topicName);
+ $testObj->set('topictitle', $topicObj->fastget("topictitle"));
+ $testObj->set('name', $name);
+
+ if ((!$search || $search->matches($testObj, {webDB=>$this})) && $topicViewAccess) {
+ my $key = $this->{web}.'::'.$topicName.'::'.$name;
+ my $map = new Foswiki::Contrib::DBCacheContrib::MemMap( initial=> $testObj->{keys});
+ $hits->add($key, $map);
}
}
-
- # don't check access perms on a topic that does not contain any
- # WARNING: this is hardcoded to assume Foswiki-Core permissions - anyone
- # doing pluggable Permissions need to
- # work out howto abstract this concept - or to disable it (its worth about 400mS per topic in the set. (if you're not WikiAdmin))
- if (
- $isAdmin
- || (!$topicHasPerms && $webViewPermission)
- || ($topicHasPerms && $this->checkAccessPermission('VIEW', $wikiName, $topicObj)) #Foswiki::Func::checkAccessPermission('VIEW', $wikiName, undef, $topicName, $this->{web}))
- )
- {
+ } else {
+ if ((!$search || $search->matches($topicObj, {webDB=>$this})) && $this->_hasViewAccess($topicName, $topicObj)) {
$hits->add($topicName, $topicObj);
}
}
@@ -320,6 +322,35 @@ sub dbQuery {
return $hits;
}
+sub _hasViewAccess {
+ my ($this, $topic, $obj) = @_;
+
+ my $isAdmin = Foswiki::Func::isAnAdmin();
+ my $wikiName = Foswiki::Func::getWikiName();
+ my $webViewPermission = $isAdmin || Foswiki::Func::checkAccessPermission('VIEW', $wikiName, undef, undef, $this->{web});
+
+ my $topicHasPerms = 0;
+ unless ($isAdmin) {
+ my $prefs = $obj->fastget('preferences');
+ if (defined($prefs)) {
+ foreach my $key ($prefs->getKeys()) {
+ if ($key =~ /^(ALLOW|DENY)TOPIC/) {
+ $topicHasPerms = 1;
+ last;
+ }
+ }
+ }
+ }
+
+ # don't check access perms on a topic that does not contain any
+ # WARNING: this is hardcoded to assume Foswiki-Core permissions - anyone
+ # doing pluggable Permissions need to
+ # work out howto abstract this concept - or to disable it (its worth about 400ms per topic in the set. (if you're not WikiAdmin))
+ return
+ ($isAdmin || (!$topicHasPerms && $webViewPermission) || ($topicHasPerms && $this->checkAccessPermission('VIEW', $wikiName, $obj))) ? 1 : 0;
+}
+
+
###############################################################################
sub expandPath {
my ($this, $theRoot, $thePath) = @_;
|
---|