more oodles of changes.

This commit is contained in:
Matthew Wilson 2006-01-15 18:19:44 +00:00
parent 5473560df4
commit f2cccdff9f
27 changed files with 112 additions and 670 deletions

View file

@ -40,11 +40,11 @@ sub definition {
},
eventStartDate => {
fieldType=>"dateTime",
defaultValue=$self->session->datetime->time()
defaultValue=$session->datetime->time()
},
eventEndDate => {
fieldType=>"dateTime",
defaultValue=$self->session->datetime->time()
defaultValue=$session->datetime->time()
},
EventsCalendar_recurringId => {
fieldType=>"hidden",

View file

@ -60,8 +60,9 @@ A hash reference passed in from a subclass definition.
sub definition {
my $class = shift;
my $session = shift;
my $definition = shift;
my $i18n = WebGUI::International->new($self->session,"Asset_Image");
my $i18n = WebGUI::International->new($session,"Asset_Image");
push(@{$definition}, {
assetName=>$i18n->get('assetName'),
tableName=>'ImageAsset',
@ -69,7 +70,7 @@ sub definition {
properties=>{
thumbnailSize=>{
fieldType=>'integer',
defaultValue=>$self->session->setting->get("thumbnailSize")
defaultValue=>$session->setting->get("thumbnailSize")
},
parameters=>{
fieldType=>'textarea',
@ -77,7 +78,7 @@ sub definition {
}
}
});
return $class->SUPER::definition($definition);
return $class->SUPER::definition($session,$definition);
}

View file

@ -103,8 +103,9 @@ A hash reference passed in from a subclass definition.
sub definition {
my $class = shift;
my $session = shift;
my $definition = shift;
my $i18n = WebGUI::International->new($self->session,"Asset_ZipArchive");
my $i18n = WebGUI::International->new($session,"Asset_ZipArchive");
push(@{$definition}, {
assetName=>$i18n->get('assetName'),
tableName=>'ZipArchiveAsset',
@ -120,7 +121,7 @@ sub definition {
},
}
});
return $class->SUPER::definition($definition);
return $class->SUPER::definition($session,$definition);
}

View file

@ -16,6 +16,7 @@ use WebGUI::Asset;
use WebGUI::Asset::Template;
use WebGUI::Asset::Post::Thread;
use WebGUI::Cache;
use WebGUI::Group;
use WebGUI::HTML;
use WebGUI::HTMLForm;
use WebGUI::International;
@ -124,15 +125,15 @@ sub definition {
dateSubmitted => {
noFormPost=>1,
fieldType=>"hidden",
defaultValue=$self->session->datetime->time()
defaultValue=$session->datetime->time()
},
dateUpdated => {
fieldType=>"hidden",
defaultValue=$self->session->datetime->time()
defaultValue=$session->datetime->time()
},
username => {
fieldType=>"hidden",
defaultValue=>$self->session->form->process("visitorUsername") || $self->session->user->profileField("alias") || $self->session->user->profileField("username")
defaultValue=>$session->form->process("visitorUsername") || $session->user->profileField("alias") || $session->user->profileField("username")
},
rating => {
noFormPost=>1,
@ -611,11 +612,13 @@ Send notifications to the thread and forum subscribers that a new post has been
sub notifySubscribers {
my $self = shift;
my %subscribers;
foreach my $userId (@{$group->getUsers($self->getThread->get("subscriptionGroupId"),undef,1)}) {
my %subscribers;
my $group = WebGUI::Group->new($self->session,$self->getThread->get("subscriptionGroupId"));
foreach my $userId (@{$group->getUsers(undef,1)}) {
$subscribers{$userId} = $userId unless ($userId eq $self->get("ownerUserId"));
}
foreach my $userId (@{$group->getUsers($self->getThread->getParent->get("subscriptionGroupId"),undef,1)}) {
$group = WebGUI::Group->new($self->getThread->getParent->get("subscriptionGroupId"));
foreach my $userId (@{$group->getUsers(undef,1)}) {
$subscribers{$userId} = $userId unless ($userId eq $self->get("ownerUserId"));
}
my %lang;

View file

@ -98,6 +98,7 @@ Returns the TabForm object that will be used in generating the edit page for thi
sub getEditForm {
my $self = shift;
my $tabform = $self->SUPER::getEditForm();
my $i18n = WebGUI::International->new($session,"Asset_Snippet");
my %mimeTypes;
foreach ('text/html','text/css','text/javascript','text/plain','text/xml','application/xml') {
$mimeTypes{$_}=$_;

View file

@ -62,8 +62,8 @@ sub appendPostListTemplateVars {
"lastReply.user.isVisitor"=>$lastPost->get("ownerUserId") eq "1",
"lastReply.username"=>$lastPost->get("username"),
"lastReply.userProfile.url"=>$lastPost->WebGUI::Asset::Post::getPosterProfileUrl(),
"lastReply.dateSubmitted.human"=$self->session->datetime->epochToHuman($lastPost->get("dateSubmitted"),"%z"),
"lastReply.timeSubmitted.human"=$self->session->datetime->epochToHuman($lastPost->get("dateSubmitted"),"%Z")
"lastReply.dateSubmitted.human"=>$self->session->datetime->epochToHuman($lastPost->get("dateSubmitted"),"%z"),
"lastReply.timeSubmitted.human"=>$self->session->datetime->epochToHuman($lastPost->get("dateSubmitted"),"%Z")
);
}
}
@ -82,10 +82,10 @@ sub appendPostListTemplateVars {
"status"=>$post->getStatus,
"thumbnail"=>$post->getThumbnailUrl,
"image.url"=>$post->getImageUrl,
"dateSubmitted.human"=$self->session->datetime->epochToHuman($post->get("dateSubmitted"),"%z"),
"dateUpdated.human"=$self->session->datetime->epochToHuman($post->get("dateUpdated"),"%z"),
"timeSubmitted.human"=$self->session->datetime->epochToHuman($post->get("dateSubmitted"),"%Z"),
"timeUpdated.human"=$self->session->datetime->epochToHuman($post->get("dateUpdated"),"%Z"),
"dateSubmitted.human"=>$self->session->datetime->epochToHuman($post->get("dateSubmitted"),"%z"),
"dateUpdated.human"=>$self->session->datetime->epochToHuman($post->get("dateUpdated"),"%z"),
"timeSubmitted.human"=>$self->session->datetime->epochToHuman($post->get("dateSubmitted"),"%Z"),
"timeUpdated.human"=>$self->session->datetime->epochToHuman($post->get("dateUpdated"),"%Z"),
"userProfile.url"=>$post->getPosterProfileUrl,
"user.isVisitor"=>$post->get("ownerUserId") eq "1",
"edit.url"=>$post->getEditUrl,
@ -865,7 +865,8 @@ Subscribes a user to this collaboration system.
sub subscribe {
my $self = shift;
WebGUI::Cache->new($self->session,"wobject_".$self->getId."_".$self->session->user->profileField("userId"))->delete;
$group->addUsers([$self->session->user->profileField("userId")],[$self->get("subscriptionGroupId")]);
my $group = WebGUI::Group->new($self->session,$self->get("subscriptionGroupId"));
$group->addUsers([$self->session->user->profileField("userId")]);
}
#-------------------------------------------------------------------
@ -879,6 +880,7 @@ Unsubscribes a user from this collaboration system
sub unsubscribe {
my $self = shift;
WebGUI::Cache->new($self->session,"wobject_".$self->getId."_".$self->session->user->profileField("userId"))->delete;
my $group = WebGUI::Group->new($self->session,$self->get("subscriptionGroupId"));
$group->deleteUsers([$self->session->user->profileField("userId")],[$self->get("subscriptionGroupId")]);
}
@ -1104,6 +1106,7 @@ sub www_unsubscribe {
# format the date according to rfc 822 (for RSS export)
my @_months = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
sub _get_rfc822_date {
my $self = shift;
my ($time) = @_;
my ($year, $mon, $mday, $hour, $min, $sec) = $self->session->datetime->localtime($time);
my $month = $_months[$mon - 1];
@ -1142,7 +1145,7 @@ sub www_viewRSS {
$var{'description'} = _xml_encode($self->get("description"));
# Set some of the optional channel variables
$var{'generator'} = "WebGUI ".$WebGUI::VERSION;
$var{'lastBuildDate'} = _xml_encode(_get_rfc822_date($self->get("dateUpdated")));
$var{'lastBuildDate'} = _xml_encode($self->_get_rfc822_date($self->get("dateUpdated")));
$var{'webMaster'} = $self->session->setting->get("companyEmail");
$var{'docs'} = "http://blogs.law.harvard.edu/tech/rss";
@ -1179,7 +1182,7 @@ sub www_viewRSS {
link => $encUrl,
description => _xml_encode($post->get("synopsis")),
guid => $encUrl,
pubDate => _xml_encode(_get_rfc822_date($post->get("dateUpdated"))),
pubDate => _xml_encode($self->_get_rfc822_date($post->get("dateUpdated"))),
attachmentLoop => \@attachmentLoop,
});
$i++;

View file

@ -38,8 +38,8 @@ sub canPersonalize {
#-------------------------------------------------------------------
sub definition {
my $class = shift;
return $class->SUPER::definition($definition);
my $definition = shift;
my $session = shift;
my $definition = shift;
my %properties;
tie %properties, 'Tie::IxHash';
%properties = (
@ -65,7 +65,6 @@ sub definition {
defaultValue=>undef,
fieldType=>"checkList"
},
);
my $i18n = WebGUI::International->new($session,"Asset_Dashboard");
push(@{$definition}, {
@ -75,7 +74,7 @@ sub definition {
className=>'WebGUI::Asset::Wobject::Dashboard',
properties=>\%properties
});
return $class->SUPER::definition($session, $definition);
return $class->SUPER::definition($session, $definition);
}
#-------------------------------------------------------------------

View file

@ -27,6 +27,7 @@ our @ISA = qw(WebGUI::Asset::Wobject);
#-------------------------------------------------------------------
sub _createField {
my $self = shift;
my $data = $_[0];
my %param;
$param{name} = $data->{name};
@ -112,6 +113,7 @@ sub _tonull {
#-------------------------------------------------------------------
sub _createTabInit {
my $self = shift;
my $id = shift;
my @tabCount = $self->session->db->quickArray("select count(DataForm_tabId) from DataForm_tab where assetId=".$self->session->db->quote($id));
my $output = '<script type="text/javascript">var numberOfTabs = '.$tabCount[0].'; initTabs();</script>';
@ -395,7 +397,7 @@ sub getRecordTemplateVars {
# add Tab label, url, header and init
$var->{"addTab.label"}= $i18n->get(105);;
$var->{"addTab.url"}= $self->getUrl('func=editTab');
$var->{"tab.init"}= _createTabInit($self->getId);
$var->{"tab.init"}= $self->_createTabInit($self->getId);
$var->{"form.start"} = WebGUI::Form::formHeader($self->session,{action=>$self->getUrl})
.WebGUI::Form::hidden($self->session,{name=>"func",value=>"process"});
my @tabs;
@ -439,7 +441,7 @@ sub getRecordTemplateVars {
$value = $self->session->datetime->epochToHuman($value,"%z") if ($data{type} eq "date");
$value = $self->session->datetime->epochToHuman($value,"%z %Z") if ($data{type} eq "dateTime");
push(@fields, {
"tab.field.form" => _createField(\%data),
"tab.field.form" => $self->_createField(\%data),
"tab.field.name" => $data{name},
"tab.field.tid" => $data{DataForm_tabId},
"tab.field.value" => $value,
@ -483,7 +485,7 @@ sub getRecordTemplateVars {
$value = $self->session->datetime->epochToHuman($value,"%z") if ($data{type} eq "date");
$value = $self->session->datetime->epochToHuman($value) if ($data{type} eq "dateTime");
my %fieldProperties = (
"form" => _createField(\%data),
"form" => $self->_createField(\%data),
"name" => $data{name},
"tid" => $data{DataForm_tabId},
"inTab".$data{DataForm_tabId} => 1,

View file

@ -92,9 +92,10 @@ The number of seconds since January 1, 1970.
=cut
sub epochToArray {
my $self = shift;
my $timeZone = $self->session->user->profileField("timeZone") || "America/Chicago";
use DateTime;
return map {$_ += 0} split / /, DateTime->from_epoch( epoch =>shift, time_zone=>$timeZone)->str$self->session->datetime->time("%Y %m %d %H %M %S");
return map {$_ += 0} split / /, DateTime->from_epoch( epoch =>shift, time_zone=>$timeZone)->strftime("%Y %m %d %H %M %S");
}
@ -248,7 +249,7 @@ sub view {
$maxDate = $self->session->datetime->addToDate($minDate,0,1,0);
}
#$self->session->errorHandler->warn("calMonthStart:".$calMonthStart." calMonthEnd:".$calMonthEnd);
my @now = epochToArray($self->session->datetime->time());
my @now = $self->epochToArray($self->session->datetime->time());
my $calHasEvent = 0;
#monthcount minus i is the number of months remaining to be processed.
for (my $i=$calMonthStart;$i<=$calMonthEnd;$i++) {
@ -256,7 +257,7 @@ sub view {
my $monthHasEvent = 0;
my $thisMonth = $self->session->datetime->addToDate($minDate,0,($i-1),0);
my ($monthStart, $monthEnd) = $self->session->datetime->monthStartEnd($thisMonth);
my @thisMonthDate = epochToArray($thisMonth);
my @thisMonthDate = $self->epochToArray($thisMonth);
#Check month to see if it is in the allowed month range. End loop if it's not.
if ($thisMonth > $maxDate) {
$i = $calMonthEnd;
@ -295,7 +296,7 @@ sub view {
#cycle through each day in the event, pushing the event's day listing into the proper day.
for (my $i=$eventCycleStart; $i<=$eventCycleStop; $i++) {
#create an array for the specific day in the event.
my @date = epochToArray($self->session->datetime->addToDate($eventStartDate,0,0,$i));
my @date = $self->epochToArray($self->session->datetime->addToDate($eventStartDate,0,0,$i));
# if the event goes past the end of this month, halt the loop.
# No need to continue processing days that aren't in this month.
if ($monthEnd < ($self->session->datetime->addToDate($eventStartDate,0,0,$i) - 1)) {
@ -357,7 +358,7 @@ sub view {
});
$dayOfWeekCounter++;
}
my @date = epochToArray($thisMonth);
my @date = $self->epochToArray($thisMonth);
my @dayloop;
for (my $dayCounter=1; $dayCounter <= $daysInMonth; $dayCounter++) {
#----------------------------------------------------------------------------

View file

@ -229,7 +229,7 @@ sub view {
if($self->session->env->get("REQUEST_METHOD")=~/GET/i || $redirect != 0) { # request_method is also GET after a redirection. Just to make sure we're
# not posting the same data over and over again.
if($redirect == 0) {
foreach my $input_name (keys %{$session{form}}) {
foreach my $input_name ($self->session->request->params) {
next if ($input_name !~ /^HttpProxy_/); # Skip non proxied form var's
$input_name =~ s/^HttpProxy_//;
$proxiedUrl=$self->session->url->append($proxiedUrl,"$input_name=".$self->session->form->process('HttpProxy_'.$input_name));
@ -241,7 +241,7 @@ sub view {
my $contentType = 'application/x-www-form-urlencoded'; # default Content Type header
# Create a %formdata hash to pass key/value pairs to the POST request
foreach my $input_name (keys %{$session{form}}) {
foreach my $input_name ($self->session->request->params) {
next if ($input_name !~ /^HttpProxy_/); # Skip non proxied form var's
$input_name =~ s/^HttpProxy_//;
@ -322,9 +322,9 @@ sub view {
"<p><i>GET status line: ".$response->status_line."</i>";
}
if ($self->session->user->profileField("userId") eq '1') {
$ttl = $session{page}{cacheTimeoutVisitor};
$ttl = $self->get("cacheTimeoutVisitor");
} else {
$ttl = $session{page}{cacheTimeout};
$ttl = $self->get("cacheTimeout");
}
unless ($self->get("cacheTimeoutVisitor") <= 1 && $self->get("cacheTimeout") <= 1) {
$cachedContent->set($var{content},$ttl);

View file

@ -29,6 +29,7 @@ sub _defineUsername {
#-------------------------------------------------------------------
sub _fetchNames {
my $self = shift;
my @userIds = @_;
my %nameHash;
my $sql = "select users.username,
@ -173,7 +174,7 @@ sub view {
if (@users) {
my %nameHash;
tie %nameHash, "Tie::IxHash";
%nameHash = _fetchNames(@users);
%nameHash = $self->_fetchNames(@users);
$nameHash{""} = $i18n->get('myself');
%nameHash = WebGUI::Utility::sortHash(%nameHash);
@ -479,7 +480,7 @@ order by department, lastName, firstName, InOutBoard_statusLog.dateStamp";
$row{'dateStamp'} = $self->session->datetime->epochToHuman($data->{dateStamp});
$row{'message'} = ($data->{message}||"&nbsp;");
if (! exists $changedBy{ $data->{createdBy} }) {
my %whoChanged = _fetchNames($data->{createdBy});
my %whoChanged = $self->_fetchNames($data->{createdBy});
$changedBy{ $data->{createdBy} } = $whoChanged{ $data->{createdBy} };
}
$row{'createdBy'} = $changedBy{ $data->{createdBy} };

View file

@ -15,13 +15,13 @@ package WebGUI::Asset::Wobject::IndexedSearch::Search;
=cut
use strict;
use DBIx::FullTextSearch;
use WebGUI::SQL;
use WebGUI::HTML;
use DBIx::FullTextSearch::StopList;
use WebGUI::Utility;
use HTML::Highlight;
use WebGUI::Macro;
#use DBIx::FullTextSearch;
#use WebGUI::SQL;
#use WebGUI::HTML;
#use DBIx::FullTextSearch::StopList;
#use WebGUI::Utility;
#use HTML::Highlight;
#use WebGUI::Macro;
=head1 NAME
@ -56,574 +56,4 @@ These methods are available from this package:
=cut
#-------------------------------------------------------------------
sub _recurseCrumbTrail {
my ($sth, %data, $output);
tie %data, 'Tie::CPHash';
%data = $self->session->db->quickHash("select asset.assetId,asset.parentId,assetData.menuTitle,asset.url from asset left join assetData on asset.assetId=assetData.assetId where asset.assetId=".$self->session->db->quote($_[0])." group by assetData.assetId order by assetData.revisionDate desc");
if ($data{assetId}) {
$output .= _recurseCrumbTrail($data{parentId});
}
if ($data{assetId} ne "PBasset000000000000001" && $data{menuTitle}) {
$output .= '<a class="crumbTrail" href="'.$self->session->url->gateway($data{url})
.'">'.$data{menuTitle}.'</a> &gt; ';
}
return $output;
}
#-------------------------------------------------------------------
=head2 close ( )
Closes the DBIx::FullTextSearch session.
=cut
sub close {
my $self=shift;
$self->DESTROY();
}
#-------------------------------------------------------------------
=head2 create ( [ %options ] )
Creates a new DBIx::FullTextSearch index.
=head3 %options
Options to pass to DBIx::FullTextSearch.
The default options that are used are:
( backend => column, word_length => 20, stoplist => undef )
Please refer to the DBIx::FullTextSearch documentation for a complete list of options.
=cut
sub create {
my ($self, %options) = @_;
%options = (%{$self->{_createOptions}}, %options);
if($options{stemmer}) {
eval "use Lingua::Stem";
if ($@) {
$self->session->errorHandler->warn("IndexedSearch: Can't use stemmer: $@");
delete $options{stemmer};
}
}
if($options{stoplist}) {
if(not $self->existsTable($self->getIndexName."_".$options{stoplist}."_stoplist")) {
DBIx::FullTextSearch::StopList->create_default($self->getDbh, $self->getIndexName."_".$options{stoplist}, $options{stoplist});
}
$options{stoplist} = $self->getIndexName."_".$options{stoplist};
}
$self->{_fts} = DBIx::FullTextSearch->create($self->getDbh, $self->getIndexName, %options);
if (not defined $self->{_fts}) {
$self->session->errorHandler->error("IndexedSearch: Unable to create index.\n$DBIx::FullTextSearch::errstr");
return undef;
}
$self->{_docId} = 1;
return $self->{_fts};
}
#-------------------------------------------------------------------
=head2 existsTable ( tableName )
Returns true if tableName exists in database.
=head3 tableName
The name of table.
=cut
sub existsTable {
my ($self, $table) = @_;
return isIn($table, $self->session->db->buildArray("show tables"));
}
#-------------------------------------------------------------------
=head2 getDetails ( docIdList , [ %options ] )
Returns an array reference containing details for each docId.
=head3 docIdList
An array reference containing docIds.
=head3 previewLength
The maximum number of characters in each of the context sections. Defaults to "80".
=head3 highlight
A boolean indicating whether or not to enable highlight. Defaults to "1".
=head3 highlightColors
A reference to an array of CSS color identificators.
=cut
sub getDetails {
my ($self, $docIdList, %options) = @_;
my $docIds = $self->session->db->quoteAndJoin($docIdList);
my (@searchDetails);
my $sql = "select * from IndexedSearch_docInfo where docId in ($docIds) and indexName = ".$self->session->db->quote($self->getIndexName) ;
$sql .= " ORDER BY FIELD(docId, $docIds)"; # Maintain $docIdList order
my $sth = $self->session->db->read($sql);
while (my %data = $sth->hash) {
if ($data{ownerId}) {
($data{username}) = $self->session->db->quickArray("select username from users where userId = ".$self->session->db->quote($data{ownerId}));
$data{userProfile} = $self->session->url->page("op=viewProfile&uid=$data{ownerId}");
}
if ($data{bodyShortcut} =~ /^\s*select /i) {
$data{body} = ($self->session->db->quickArray($data{bodyShortcut}))[0];
} else {
$data{body} = $data{bodyShortcut};
}
if ($data{headerShortcut} =~ /^\s*select /i) {
$data{header} = ($self->session->db->quickArray($data{headerShortcut}))[0];
} else {
$data{header} = $data{headerShortcut};
}
delete($data{bodyShortcut});
delete($data{headerShortcut});
if($data{body}) {
$data{body} = WebGUI::Macro::filter($data{body});
$data{body} = WebGUI::HTML::filter($data{body},'all');
$data{body} = $self->preview($data{body}, $options{previewLength});
$data{body} = $self->highlight($data{body},undef, $options{highlightColors}) if ($options{highlight});
}
if($data{header}) {
$data{header} = WebGUI::Macro::filter($data{header});
$data{header} = WebGUI::HTML::filter($data{header},'all');
$data{header} = $self->highlight($data{header},undef, $options{highlightColors}) if ($options{highlight});
$data{location} = $self->session->url->gateway($data{location});
}
$data{crumbTrail} = _recurseCrumbTrail($data{assetId});
$data{crumbTrail} =~ s/\s*\&gt;\s*$//;
push(@searchDetails, \%data);
}
$sth->finish;
return \@searchDetails;
}
#-------------------------------------------------------------------
=head2 getDbh ( )
Returns the object's database handler.
=cut
sub getDbh {
my $self = shift;
return $self->{_dbh};
}
#-------------------------------------------------------------------
=head2 getDocId ( )
Returns the next docId for this object.
=cut
sub getDocId {
my $self=shift;
return $self->{_docId};
}
#-------------------------------------------------------------------
=head2 getIndexName ( )
Returns the full index name of this object.
=cut
sub getIndexName {
my $self = shift;
return $self->{_indexName};
}
#-------------------------------------------------------------------
=head2 _queryToWords ( [ query ] )
Converts a DBIx::FullTextSearch query to (\@Words, \@Wildcards) suitable to pass to HTML::Highlight
=cut
sub _queryToWords {
my ($self, $query) = @_;
my $query ||= $self->{_query};
# Return the processed words / wildcards from memory if it's cached.
if ($self->{$query."words"} && $self->{$query."wildcards"}) {
return ($self->{$query."words"}, $self->{$query."wildcards"});
}
# deal with quotes
my $inQuote=0;
my (@words, @wildcards);
foreach (split(/\"/, $query)) {
if($inQuote == 0) {
foreach (split(/\s+/, $_)) {
next if (/^AND$/i); # boolean AND
next if (/^OR$/i); # boolean OR
next if (/^NOT$/i); # boolean OR
next if (/^\-/); # exclude word
next if (/^.{0,1}$/); # at least 2 characters
if (/\*/) {
push(@wildcards, '%'); # match any character
} else {
push(@wildcards, '*'); # Also match plural of word
}
s/['"()+*]+//g; # remove query operators and quotes
push(@words, $_);
}
} else {
my $phrase = $_;
push(@words, qq/$phrase/);
push(@wildcards, undef); # Exact match
}
$inQuote = ++$inQuote % 2;
}
# Store words / wildcards in memory
$self->{$query."words"} = \@words;
$self->{$query."wildcards"} = \@wildcards;
return (\@words, \@wildcards);
}
#-------------------------------------------------------------------
=head2 highlight ( text [ , query , colors ] )
highlight words or patterns in HTML documents.
=head3 text
The text to highlight
=head3 query
A query containing the words to highlight. Defaults to the last used $search->search query.
Special case: When query contains only an asterisk '*', no highlighting is applied.
=head3 colors
A reference to an array of CSS color identificators.
=cut
sub highlight {
my ($self, $text, $query, $colors) = @_;
my $query ||= $self->{_query};
return $text if ($query =~ /^\s*\*\s*$/); # query = '*', no highlight
my ($words, $wildcards) = $self->_queryToWords($query);
my $hl = new HTML::Highlight ( words => $words,
wildcards => $wildcards,
colors => $colors
);
return $hl->highlight($text);
}
#-------------------------------------------------------------------
=head2 indexDocument ( hashRef )
Adds a document to the index.
This method doesn't store the document itself. Instead, it stores information about words
in the document in such a structured way that it makes easy and fast to look up what
documents contain certain words and return id's of the documents.
=head3 text
The text to index.
=head3 location
The location of the document. Most likely an URL.
=head3 contentType
The content type of this document.
=head3 docId
The unique Id of this document. Defaults to the next empty docId.
=head3 assetId
The assetId of the asset that holds this content. Defaults to NULL.
=head3 ownerId
The ownerId of the document. Defaults to 3.
=head3 namespace
The namespace of this document. Defaults to 'WebGUI'.
=head3 groupIdView
Id of group authorized to view this content. Defaults to '7' (everyone)
=head3 special_groupIdView
Id of group authorized to view the details of this content.
=head3 headerShortcut
An sql statement that returns the header (title, question, subject, name, whatever)
of this document.
=head3 bodyShortcut
An sql statement that returns the body (description, answer, message, whatever)
of this document.
=cut
sub indexDocument {
my ($self, $document) = @_;
$self->{_fts}->index_document($document->{docId} || $self->{_docId}, $document->{text});
my $docId = ($document->{docId} || $self->{_docId});
$self->session->db->write("insert into IndexedSearch_docInfo ( docId,
indexName,
assetId,
groupIdView,
special_groupIdView,
namespace,
location,
headerShortcut,
bodyShortcut,
contentType,
ownerId,
dateIndexed )
values ( ".
$self->session->db->quote($docId).", ".
$self->session->db->quote($self->getIndexName).", ".
$self->session->db->quote($document->{assetId}).", ".
$self->session->db->quote($document->{groupIdView} || "7").", ".
$self->session->db->quote($document->{special_groupIdView} || "7").", ".
$self->session->db->quote($document->{namespace} || 'WebGUI')." , ".
$self->session->db->quote($document->{location}).", ".
$self->session->db->quote($document->{headerShortcut})." ,".
$self->session->db->quote($document->{bodyShortcut})." ,".
$self->session->db->quote($document->{contentType})." ,".
$self->session->db->quote($document->{ownerId} || 3).",
".$self->session->datetime->time()." )"
);
$self->{_docId}++;
}
#-------------------------------------------------------------------
=head2 new ( [ indexName , dbh ] )
Constructor.
=head3 indexName
The name of the index to open. Defaults to 'default'.
=head3 $dbh
Database handler to use. Defaults to $self->session->db.
=cut
sub new {
my ($class, $indexName, $dbh) = @_;
$indexName = $indexName || 'default';
my $self = { _indexName => $indexName,
_dbh => $dbh || $self->session->db,
_createOptions => {( backend => 'column',
word_length => 20,
filter => 'map { lc $_ if ($_ !~ /\^.*;/) }'
)},
};
bless $self, $class;
}
#-------------------------------------------------------------------
=head2 open ( )
Opens an existing DBIx::FullTextSearch index.
=cut
sub open {
my ($self) = @_;
$self->{_fts} = DBIx::FullTextSearch->open($self->getDbh, $self->getIndexName);
if (not defined $self->{_fts}) {
$self->session->errorHandler->error("IndexedSearch: Unable to open index.\n$DBIx::FullTextSearch::errstr");
return undef;
}
($self->{_docId}) = $self->session->db->quickArray("select max(docId) from IndexedSearch_docInfo where indexName = ".$self->session->db->quote($self->getIndexName));
$self->{_docId}++;
return $self->{_fts};
}
#-------------------------------------------------------------------
=head2 preview ( text , [ previewLength , query ] )
Returns a context preview in which words from a search query appear in the resulting documents.
The words are always in the middle of each of the sections.
=head3 text
The text to preview
=head3 previewLength
The maximum number of characters in each of the context sections. Defaults to 80.
A preview length of "0" means no preview,
while a negative preview length returns the complete text.
=head3 query
A query containing the words to highlight. Defaults to the last used $search->search query.
=cut
sub preview {
my ($self, $text, $previewLength, $query) = @_;
$previewLength = 80 if (not defined $previewLength);
return '' unless ($previewLength);
return $text if ($previewLength < 0);
my $query ||= $self->{_query};
if(($query =~ /^\s*\*\s*$/) or not $query) { # Query is '*' or empty.
$text = WebGUI::HTML::filter($text,'all');
$text =~ s/^(.{1,$previewLength})\s+.*$/$1/s;
} else {
my ($words, $wildcards) = $self->_queryToWords($query);
my $hl = new HTML::Highlight ( words => $words,
wildcards => $wildcards
);
my $preview = join('... ',@{$hl->preview_context($text, $previewLength)});
if ($preview) {
$text = $preview;
} else {
$text = WebGUI::HTML::filter($text,'all');
$text =~ s/^(.{1,$previewLength})\s+.*$/$1/s;
}
}
$text =~ s/^(\s|&nbsp;)+//;
$text =~ s/(\s|&nbsp;)+$//;
if($text ne '') {
$text = '<STRONG>... </STRONG>'.$text if ($text !~ /^[A-Z]+/); # ... broken up at the beginning
$text .='<STRONG> ...</STRONG>' if ($text !~ /\.$/); # broken up at the end ...
}
return $text;
}
#-------------------------------------------------------------------
=head2 recreate ( [ %options ] )
Like create, but first drops the existing index. Useful when rebuilding the index.
=head3 %options
Options to pass to WebGUI::IndexedSearch->create()
=cut
sub recreate {
my ($self, %options) = @_;
$self->{_fts} = DBIx::FullTextSearch->open($self->getDbh, $self->getIndexName);
if (defined $self->{_fts}) {
$self->{_fts}->drop;
}
$self->{_fts} = $self->create($self->getIndexName, $self->getDbh, %options);
$self->session->db->write("delete from IndexedSearch_docInfo where indexName = ".$self->session->db->quote($self->getIndexName));
return $self->{_fts};
}
#-------------------------------------------------------------------
=head2 search ( query, \%filter )
Returns an array reference of docId's of documents that match the query.
If the search has no results, undef is returned.
=head3 query
user input string. Will be parsed into can-include, must-include and must-not-include words and phrases.
Special case: when query is an asterisk (*), then no full text search is done, and results are returned
using \%filter.
Examples are:
+"this is a phrase" -koo +bar foo
(foo OR baz) AND (bar OR caz)
=head3 filter
A hash reference containing filter elements.
Example:
{
language => [ 1, 3 ],
namespace => [ 'Article', 'USS' ]
}
=cut
sub search {
my ($self, $query, $filter) = @_;
$self->{_query} = $query;
my $noFtsSearch = ($query =~ /^\s*\*\s*$/); # query = '*', no full text search
my @fts_docIds = $self->{_fts}->search($query) unless $noFtsSearch ;
if(@fts_docIds || $noFtsSearch) {
my $groups = $self->session->db->quoteAndJoin($self->_getGroups);
my $docIds = $self->session->db->quoteAndJoin(\@fts_docIds);
my $sql = "select docId from IndexedSearch_docInfo where indexName = ".$self->session->db->quote($self->getIndexName);
$sql .= " and docId in ($docIds)" unless $noFtsSearch;
$sql .= " and groupIdView in ($groups)";
$sql .= " and special_groupIdView in ($groups)";
foreach my $filterElement (keys %{$filter}) {
$sql .= " AND $filterElement in (".$self->session->db->quoteAndJoin($filter->{$filterElement}).")";
}
# Keep @fts_docIds list order
$sql .= " ORDER BY FIELD(docID,$docIds)" unless $noFtsSearch;
my $filteredDocIds = $self->session->db->buildArrayRef($sql);
return $filteredDocIds if (ref $filteredDocIds eq 'ARRAY' and @{$filteredDocIds});
}
return undef;
}
#-------------------------------------------------------------------
=head2 _getGroups ( )
Returns an array reference containing all groupIds of groups the user is in.
=cut
sub _getGroups {
my @groups;
foreach my $groupId ($self->session->db->buildArray("select groupId from groups")) {
push(@groups, $groupId) if ($self->session->user->isInGroup($groupId));
}
return \@groups;
}
#-------------------------------------------------------------------
sub DESTROY {
my $self=shift;
if (ref($self->{_fts})) {
$self->{_fts}->DESTROY();
}
}
1;

View file

@ -22,7 +22,7 @@ our @ISA = qw(WebGUI::Asset::Wobject);
#-------------------------------------------------------------------
sub definition {
my $class = shift;
return $class->SUPER::definition($definition);
my $session = shift;
my $definition = shift;
my $i18n = WebGUI::International->new($session,"Asset_MessageBoard");
my %properties;
@ -45,7 +45,7 @@ sub definition {
autoGenerateForms=>1,
properties=>\%properties
});
return $class->SUPER::definition($session, $definition);
return $class->SUPER::definition($session, $definition);
}

View file

@ -33,7 +33,7 @@ sub _hasVoted {
#-------------------------------------------------------------------
sub definition {
my $class = shift;
return $class->SUPER::definition($definition);
my $session = shift;
my $definition = shift;
my $i18n = WebGUI::International->new($session,"Asset_Poll");
push(@{$definition}, {

View file

@ -92,6 +92,7 @@ sub addRevision {
#-------------------------------------------------------------------
sub definition {
my $class = shift;
my $session = shift;
my $definition = shift;
my $i18n = WebGUI::International->new($session,"Asset_Product");
push(@{$definition}, {

View file

@ -320,7 +320,7 @@ sub _processQuery {
if (defined $dbh) {
if ($query =~ /^select/i || $query =~ /^show/i || $query =~ /^describe/i) {
my $url = $self->getUrl('func=view');
foreach (keys %{$session{form}}) {
foreach ($self->session->request->params) {
unless ($_ eq "pn" || $_ eq "func" || $_ =~ /identifier/i || $_ =~ /password/i) {
$url = $self->session->url->append($url, $self->session->url->escape($_)
.'='.$self->session->url->escape($self->session->form->process($_)));

View file

@ -231,6 +231,7 @@ sub _normalize_items {
#-------------------------------------------------------------------
sub _get_rss_data {
my $self = shift;
my $url = shift;
my $cache = WebGUI::Cache->new($self->session,'url:' . $url, 'RSS');
@ -295,7 +296,7 @@ sub _get_rss_data {
#Assign dates "globally" rather than when seen in a viewed feed.
#This is important because we can "filter" now and want to ensure we keep order
#correctly as new items appear.
_assign_rss_dates($rss->{items});
$self->_assign_rss_dates($rss->{items});
#Default to an hour timeout
$cache->set(Storable::freeze($rss), 3600);
@ -310,6 +311,7 @@ sub _get_rss_data {
# whole database to keep the thing from growing too large
sub _assign_rss_dates {
my $self = shift;
my ($items) = @_;
for my $item (@{$items}) {
@ -442,7 +444,7 @@ sub _get_items {
$items = [];
for my $url (@{$urls}) {
my $rss_info=_get_rss_data($url);
my $rss_info=$self->_get_rss_data($url);
push(@rss_feeds, $rss_info) if($rss_info);
}
@ -504,7 +506,7 @@ sub view {
$var{item_loop} = $item_loop;
#Construct the title for the link.
_constructRSSHeadTitleLink(\%var,$title || $var{'channel.title'});
$self->_constructRSSHeadTitleLink(\%var,$title || $var{'channel.title'});
if ($rssObject) {
$self->_constructRSS($rssObject,\%var);
my $rss=$rssObject->as_string;
@ -525,6 +527,7 @@ sub view {
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
sub _constructRSSHeadTitleLink{
my $self = shift;
my($var,$rssTitle)=@_;
my $i18n = WebGUI::International->new($self->session,'Asset_SyndicatedContent');
my $rssFeedSuffix=$i18n->get('RSS Feed Title Suffix');

View file

@ -17,12 +17,11 @@ our @ISA = qw(WebGUI::Asset::Wobject);
#-------------------------------------------------------------------
sub _create_cache_key {
my ($wobject, $call, $param_str) = @_;
my ($self, $call, $param_str) = @_;
my $cache_key;
$cache_key = $_[0]->get('sharedCache')
? Digest::MD5::md5_hex($call, $param_str)
: Digest::MD5::md5_hex($call, $param_str, $session{'var'}{'sessionId'});
: Digest::MD5::md5_hex($call, $param_str, $self->session->getId);
$self->session->errorHandler->warn(($_[0]->get('sharedCache')?'shared':'session')
. " cache_key=$cache_key md5_hex($call, $param_str)");
return $cache_key;
@ -35,7 +34,7 @@ sub definition {
my $session = shift;
my $definition = shift;
my $httpHeaderFieldType;
if ($session{'config'}{'soapHttpHeaderOverride'}) {
if ($session->config->get('soapHttpHeaderOverride')) {
$httpHeaderFieldType = 'text';
} else {
$httpHeaderFieldType = 'hidden';
@ -81,11 +80,11 @@ my $httpHeaderFieldType;
},
proxy => {
fieldType => 'text',
defaultValue => $session{'config'}{'soapproxy'},
defaultValue => $session->config->get('soapproxy'),
},
uri => {
fieldType => 'text',
defaultValue => $session{'config'}{'soapuri'}
defaultValue => $session->config->get('soapuri')
},
decodeUtf8 => {
fieldType => "yesNo",
@ -164,7 +163,7 @@ sub getEditForm {
-hoverHelp => $i18n->get('5 description'),
-value => $self->get('params'),
);
if ($session{'config'}{'soapHttpHeaderOverride'}) {
if ($self->session->config->('soapHttpHeaderOverride')) {
$tabform->getTab("properties")->text (
-name => 'httpHeader',
-label => $i18n->get(16),
@ -246,10 +245,10 @@ sub view {
# this page, with important params
@seen{@exclude_params} = ();
for (keys %{$session{'form'}}) {
for ($session->request->params) {
unless (exists $seen{$_}) {
$query_string .= $self->session->url->escape($_) . '='
. $self->session->url->escape($session{'form'}{$_}) . ';';
. $self->session->url->escape($self->session->form->process($_)) . ';';
}
}
$url = $self->session->url->page($query_string);
@ -267,10 +266,10 @@ sub view {
}
# see if we can shortcircuit this whole process
if ((ref $session{'form'}{'disableWobjects'} && grep /^$call$/,
@{$session{'form'}{'disableWobjects'}}) ||
($session{'form'}{'disableWobjects'} && grep /^$call$/,
$session{'form'}{'disableWobjects'})) {
if ((ref $self->session->form->process('disableWobjects') && grep /^$call$/,
@{$self->session->form->process('disableWobjects')}) ||
($self->session->form->process('disableWobjects') && grep /^$call$/,
$self->session->form->process('disableWobjects'))) {
$self->session->errorHandler->warn("disabling soap call $call");
$var{'disableWobject'} = 1;
@ -279,19 +278,19 @@ sub view {
# advanced use, if you want to pass SOAP results to a single, particular
# wobject on a page
if (ref $session{'form'}{'targetWobjects'}) {
@targetWobjects = @{$session{'form'}{'targetWobjects'}};
if (ref $self->session->form->process('targetWobjects')) {
@targetWobjects = @{$self->session->form->process('targetWobjects')};
} else {
push @targetWobjects, $session{'form'}{'targetWobjects'};
push @targetWobjects, $self->session->form->process('targetWobjects');
}
# check to see if this exact query has already been cached, using either
# a cache specific to this session, or a shared global cache
if ($session{'form'}{'cache'}) {
if ($session{'form'}{'targetWobjects'}
if ($self->session->form->process('cache')) {
if ($self->session->form->process('targetWobjects')}
&& grep /^$call$/, @targetWobjects) {
$cache_key = $session{'form'}{'cache'};
$cache_key = $self->session->form->process('cache');
$self->session->errorHandler->warn("passed a cache_key for $call");
} else {
$self->session->errorHandler->warn("cache_key not applicable to $call ");
@ -304,7 +303,7 @@ sub view {
$i18n->get(4));
# passing a form param WSClient_skipCache lets us ignore even good caches
if (!$session{'form'}{'WSClient_skipCache'}) {
if (!$self->session->form->process('WSClient_skipCache')) {
@result = Storable::thaw($cache->get);
}
@ -462,26 +461,23 @@ sub view {
$var{$_} =~ s/\?/\?cache=$cache_key\;/g;
}
}
} else {
$self->session->errorHandler->debug($i18n->get(26) . $@) if $self->get('debugMode');
}
# did they request a funky http header?
if ($session{'config'}{'soapHttpHeaderOverride'} &&
if ($self->session->config->get('soapHttpHeaderOverride')} &&
$self->get("httpHeader")) {
$self->session->http->setMimeType($self->get("httpHeader"));
$self->session->errorHandler->warn("changed mimetype: " . $session{'header'}{'mimetype'});
$self->session->errorHandler->warn("changed mimetype: " . $self->get("httpHeader"));
}
# Note, we still process our template below even though it will never
# be displayed if the redirectURL is set. Not sure how important it is
# to do it this way, but it certainly is the least obtrusive to default
# webgui flow. This feature currently requires a patched WebGUI.pm file.
if ($session{'form'}{'redirectURL'}) {
$self->session->http->setRedirect($session{'form'}{'redirectURL'});
if ($self->session->form->process('redirectURL')) {
$self->session->http->setRedirect($self->session->form->process('redirectURL'));
}
$var{'results'} = \@result;