more search related changes

This commit is contained in:
JT Smith 2006-01-22 03:31:37 +00:00
parent 9c7e8699a2
commit 66baa5cea2
8 changed files with 9 additions and 1074 deletions

View file

@ -33,8 +33,7 @@ sub addSearchEngine {
assetId varchar(22) binary not null primary key, assetId varchar(22) binary not null primary key,
title varchar(255), title varchar(255),
synopsis text, synopsis text,
startDate bigint, url varchar(255),
endDate bigint,
creationDate bigint, creationDate bigint,
revisionDate bigint, revisionDate bigint,
ownerUserId varchar(22) binary, ownerUserId varchar(22) binary,
@ -85,6 +84,9 @@ sub removeFiles {
unlink '../../lib/WebGUI/Setting.pm'; unlink '../../lib/WebGUI/Setting.pm';
unlink '../../lib/WebGUI/Grouping.pm'; unlink '../../lib/WebGUI/Grouping.pm';
unlink '../../lib/WebGUI/Asset/Wobject/IndexedSearch.pm'; unlink '../../lib/WebGUI/Asset/Wobject/IndexedSearch.pm';
unlink '../../lib/WebGUI/Help/Asset_IndexedSearch.pm';
unlink '../../lib/WebGUI/i18n/Asset_IndexedSearch.pm';
unlink '../../sbin/Hourly/IndexedSearch_buildIndex.pm';
rmtree('../../lib/WebGUI/Asset/Wobject/IndexedSearch'); rmtree('../../lib/WebGUI/Asset/Wobject/IndexedSearch');
} }

View file

@ -1,572 +0,0 @@
package WebGUI::Asset::Wobject::IndexedSearch;
use strict;
use Time::HiRes;
use WebGUI::Asset::Wobject::IndexedSearch::Search;
use WebGUI::HTMLForm;
use WebGUI::HTML;
use WebGUI::Macro;
use WebGUI::International;
use WebGUI::SQL;
use Tie::IxHash;
use WebGUI::Utility;
use WebGUI::Paginator;
use WebGUI::Asset::Wobject;
our @ISA = qw(WebGUI::Asset::Wobject);
#-------------------------------------------------------------------
sub definition {
my $class = shift;
my $session = shift; use WebGUI; WebGUI::dumpSession($session);
my $definition = shift;
my $i18n = WebGUI::International->new($session,"Asset_IndexedSearch");
push (@{$definition}, {
tableName=>'IndexedSearch',
className=>'WebGUI::Asset::Wobject::IndexedSearch',
assetName=>$i18n->get('assetName'),
properties=>{
templateId=>{
fieldType=>"template",
defaultValue=>"PBtmpl0000000000000034"
},
indexName=>{
fieldType=>'text',
defaultValue=>'default'
},
searchRoot=>{
fieldType=>'checkList',
defaultValue=>'any'
},
forceSearchRoots=>{
fieldType=>'yesNo',
defaultValue=>1
},
users=>{
fieldType=>'selectList',
defaultValue=>'any'
},
namespaces=>{
fieldType=>'selectList',
defaultValue=>'any'
},
contentTypes=>{
fieldType=>'selectList',
defaultValue=>'any'
},
paginateAfter=>{
defaultValue=>10
},
highlight=>{
defaultValue=>1
},
previewLength=>{
defaultValue=>130
},
highlight_1=>{
defaultValue=>'#ffff66'
},
highlight_2=>{
defaultValue=>'#A0FFFF'
},
highlight_3=>{
defaultValue=>'#99ff99'
},
highlight_4=>{
defaultValue=>'#ff9999'
},
highlight_5=>{
defaultValue=>'#ff66ff'
},
}
});
return $class->SUPER::definition($session, $definition);
}
#-------------------------------------------------------------------
sub getUiLevel {
return 5;
}
#-------------------------------------------------------------------
sub getEditForm {
my $self = shift;
my (@data, %indexName);
my $tabform = $self->SUPER::getEditForm();
tie my %searchRoot, 'Tie::IxHash';
# Unconditional read to catch intallation errors.
my $i18n = WebGUI::International->new($self->session,"Asset_IndexedSearch");
my $sth = $self->session->db->unconditionalRead("select distinct(indexName), indexName from IndexedSearch_docInfo");
unless ($sth->errorCode < 1) {
return "<p><b>" . $i18n->get(1) . $sth->errorMessage."</b></p>";
}
while (@data = $sth->array) {
$indexName{$data[0]} = $data[1];
}
$sth->finish;
unless(%indexName) {
return "<p><b>" . $i18n->get(2) .
"<p>" . $i18n->get(3) . "</p></b></p>";
}
# Index to use
# $tabform->getTab("properties")->radioList( -name=>'indexName',
# -options=>\%indexName,
# -label=>$i18n->get(5),
# -value=>$self->getValue("indexName"),
# -vertical=>1
# );
# NOTE: For now we're limiting each site to one index. Will allow more in the future.
$tabform->getTab("properties")->hidden(
-name=>"indexName",
-value=>"IndexedSearch_default"
);
# Page roots
#%searchRoot = ( 'any'=>$i18n->get(15),
# $session{page}{pageId}=>$i18n->get(4),
# $self->session->db->buildHash("select pageId,title from page where parentId='0' and isSystem<>1 order by title")
# );
#$tabform->getTab("properties")->checkList ( -name=>'searchRoot',
# -options=>\%searchRoot,
# -label=>$i18n->get(6),
# -value=>[ split("\n", $self->getValue("searchRoot")) ],
# -multiple=>1,
# -vertical=>1,
# );
$tabform->getTab("properties")->yesNo(
-name=>'forceSearchRoots',
-label=>$i18n->get('force search roots'),
-value=>$self->getValue("forceSearchRoots")
);
# Content of specific user
$tabform->getTab("properties")->selectList ( -name=>'users',
-options=>$self->_getUsers(),
-label=>$i18n->get(7),
-value=>[ split("\n", $self->getValue("users")) ],
-multiple=>1,
-size=>5
);
# Content in specific namespaces
$tabform->getTab("properties")->selectList ( -name=>'namespaces',
-options=>$self->_getNamespaces,
-label=>$i18n->get(8),
-value=>[ split("\n", $self->getValue("namespaces")) ],
-multiple=>1,
-size=>5
);
# Only specific content types
my $contentTypes = $self->_getContentTypes();
delete $contentTypes->{content};
$tabform->getTab("properties")->checkList ( -name=>'contentTypes',
-options=>$contentTypes,
-label=>$i18n->get(10),
-value=>[ split("\n", $self->getValue("contentTypes")) ],
-multiple=>1,
-vertical=>1,
);
$tabform->getTab("display")->template(
-value=>$self->getValue("templateId"),
-namespace=>"IndexedSearch"
);
$tabform->getTab("display")->integer ( -name=>'paginateAfter',
-label=>$i18n->get(11),
-value=>$self->getValue("paginateAfter"),
);
$tabform->getTab("display")->integer ( -name=>'previewLength',
-label=>$i18n->get(12),
-value=>$self->getValue("previewLength"),
);
$tabform->getTab("display")->yesNo ( -name=>'highlight',
-label=>$i18n->get(13),
-value=>$self->getValue("highlight"),
);
# Color picker for highlight colors
$tabform->getTab("display")->raw ( -value=>'
<script type="text/javascript" src="'.$self->session->config->get("extrasURL").'/wobject/IndexedSearch/ColorPicker2.js"></script>
<script type="text/javascript">
var cp = new ColorPicker("window");
</script>'
);
for (1..5) {
my $highlight = "highlight_$_";
$tabform->getTab("display")->text ( -name=>$highlight,
-label=>$i18n->get(14) ." $_:",
-size=>7,
-value=>$self->getValue($highlight),
-subtext=>qq{
<a href="#" onclick="cp.select($highlight,'$highlight');
return false;" name="$highlight" id="$highlight">Pick</a>}
);
}
return $tabform;
}
#-------------------------------------------------------------------
sub getIcon {
my $self = shift;
my $small = shift;
return $self->session->config->get("extrasURL").'/assets/small/search.gif' if ($small);
return $self->session->config->get("extrasURL").'/assets/search.gif';
}
#-------------------------------------------------------------------
sub view {
my $self = shift;
my (%var, @resultsLoop);
# Do some query handling
$var{exactPhrase} = $self->session->form->process("exactPhrase");
$var{allWords} = $self->session->form->process("allWords");
$var{atLeastOne} = $self->session->form->process("atLeastOne");
$var{without} = $self->session->form->process("without");
$var{query} = $self->session->form->process("query");
$var{query} .= qq/ +"$var{exactPhrase}"/ if ($var{exactPhrase});
$var{query} .= " ".join(" ",map("+".$_,split(/\s+/,$var{allWords}))) if ($var{allWords});
$var{query} .= qq{ $var{atLeastOne}} if ($var{atLeastOne});
$var{query} .= " ".join(" ",map("-".$_,split(/\s+/,$var{without}))) if ($var{without});
# Remove macro's from query
my $query = $var{query};
WebGUI::Macro::negate(\$query);
$var{query} = $query;
# Set some standard vars
my $i18n = WebGUI::International->new($self->session,"Asset_IndexedSearch");
$var{submit} = WebGUI::Form::submit($self->session,{value=>$i18n->get(16)});
$var{actionURL} = $self->getUrl;
$var{"int.search"} = $i18n->get(16);
$var{numberOfResults} = '0';
$var{"select_".$self->getValue("paginateAfter")} = "selected";
# Do the search
my $startTime = Time::HiRes::time();
my $filter = $self->_buildFilter;
my $search = WebGUI::Asset::Wobject::IndexedSearch::Search->new($self->getValue('indexName'));
$search->open;
my $results = $search->search($var{query},$filter);
$var{duration} = Time::HiRes::time() - $startTime;
$var{duration} = sprintf("%.3f", $var{duration}); # Duration rounded to 3 decimal places
# Let's see if the search returned any results
if (defined ($results)) {
$var{numberOfResults} = scalar(@$results);
# Deal with pagination
my $url = "query=".$self->session->url->escape($var{query});
map {$url .= "&users=".$self->session->url->escape($_)} $self->session->request->param('users');
map {$url .= "&namespaces=".$self->session->url->escape($_)} $self->session->request->param('namespaces');
map {$url .= "&contentTypes=".$self->session->url->escape($_)} $self->session->request->param('contentTypes');
$url .= "&paginateAfter=".$self->getValue("paginateAfter");
my $p = WebGUI::Paginator->new($self->session,$self->session->url->page($url), $self->getValue("paginateAfter"));
$p->setDataByArrayRef($results);
$var{startNr} = 1;
if($self->session->form->process("pn")) {
$var{startNr} = (($self->session->form->process("pn") - 1) * $self->getValue("paginateAfter")) + 1;
}
my @highlightColors = map { $self->getValue("highlight_$_") } (1..5);
$var{queryHighlighted} = $search->highlight($var{query}, undef, \@highlightColors);
# Get result details for this page
if($p->getPageNumber > $p->getNumberOfPages) {
$var{numberOfResults} = 0;
$var{resultsLoop} = [];
} else {
$var{resultsLoop} = $search->getDetails($p->getPageData,
highlightColors => \@highlightColors,
previewLength => $self->getValue('previewLength'),
highlight => $self->getValue('highlight')
);
# Pagination variables
$var{endNr} = $var{startNr}+(scalar(@{$var{resultsLoop}}))-1;
$p->appendTemplateVars(\%var);
}
}
# Create a loop with namespaces
$var{namespaces} = [];
my $namespaces = $self->_getNamespaces('restricted');
foreach(keys %$namespaces) {
my $selected = 0;
if (scalar $self->session->request->param('namespaces')) {
$selected = isIn($_, $self->session->request->param('namespaces'));
} else {
$selected = ($self->session->form->process("namespaces") =~ /$_/);
}
push(@{$var{namespaces}}, { value => $_, name => $namespaces->{$_}, selected => $selected });
}
# Create a loop with contentTypes
#
# And while we are busy we also create a loop with simplified contentTypes
# This means: wobject, page, wobjectDetail are masked in one option: content
$var{contentTypes} = [];
$var{contentTypesSimple} = [];
my $contentTypes = $self->_getContentTypes('restricted');
foreach(keys %$contentTypes) {
my $selected = 0;
if (scalar $self->session->request->param('contentTypes')) {
$selected = isIn($_, $self->session->request->param('contentTypes'));
} else {
$selected = ($self->session->form->process("contentTypes") =~ /$_/);
}
unless(/^content$/) { # No shortcut in the detailed contentType list
push(@{$var{contentTypes}}, { value => $_,
name => $contentTypes->{$_},
selected => $selected,
'type_'.$_ => 1 });
}
unless(/^page|wobject|wobjectDetail$/) { # No details in the simple contentType list
push(@{$var{contentTypesSimple}}, { value => $_,
name => $contentTypes->{$_},
selected => $selected,
'type_'.$_ => 1 });
}
}
# Create a loop with users
$var{users} = [];
my $users = $self->_getUsers('restricted');
foreach(keys %$users) {
my $selected = 0;
if (scalar $self->session->request->param('users')) {
$selected = isIn($_, $self->session->request->param('users'));
} else {
$selected = ($self->session->form->process("users") =~ /$_/);
}
push(@{$var{users}}, { value => $_, name => $users->{$_}, selected => $selected });
}
# Create a loop with searchable page roots
my $rootData;
my @roots = split(/\n/, $self->get('searchRoot'));
my %checked = map {$_=>1} $self->session->request->param("searchRoot");
#if (isIn('any', @roots)) {
# foreach $rootData (WebGUI::Page->getAnonymousRoot->daughters) {
# push (@{$var{searchRoots}}, {
# value => $rootData->{'pageId'},
# menuTitle => $rootData->{'menuTitle'},
# title => $rootData->{'title'},
# urlizedTitle => $rootData->{'urlizedTitle'},
# checked => $checked{$rootData->{'pageId'}},
# });
# $var{"rootPage.".$rootData->{'urlizedTitle'}.".id"} = $rootData->{'pageId'};
# $var{"rootPage.".$rootData->{'urlizedTitle'}.".checked"} = $checked{$rootData->{'pageId'}};
# }
#} else {
# foreach (@roots) {
# $rootData = WebGUI::Page->new($_);
# push (@{$var{searchRoots}}, {
# value => $rootData->get('pageId'),
# menuTitle => $rootData->get('menuTitle'),
# title => $rootData->get('title'),
# urlizedTitle => $rootData->get('urlizedTitle'),
# checked => $checked{$rootData->get('pageId')},
# });
# $var{"rootPage.".$rootData->get('urlizedTitle').".id"} = $rootData->get('pageId');
# $var{"rootPage.".$rootData->get('urlizedTitle').".checked"} = $checked{$rootData->get('pageId')};
# }
#}
$var{"anyRootPage.checked"} = $checked{'any'};
# close the search
$search->close;
return $self->processTemplate(\%var, $self->get("templateId"));
}
#-------------------------------------------------------------------
sub www_edit {
my $self = shift;
return $self->session->privilege->insufficient() unless $self->canEdit;
$self->getAdminConsole->setHelp("search add/edit", "Asset_IndexedSearch");
my $form = $self->getEditForm;
my $output = $form;
$output = $form->print unless $form =~ /^<p><b/;
my $i18n = WebGUI::International->new($self->session,"Asset_IndexedSearch");
return $self->getAdminConsole->render($output,$i18n->get("26"));
}
#-------------------------------------------------------------------
sub www_view {
my $self = shift;
return $self->SUPER::www_view(1);
}
#-------------------------------------------------------------------
sub _buildPageList {
my ($self, @userSpecifiedRoots, @roots, @allowedRoots, $pageId, @pages);
$self = shift;
@userSpecifiedRoots = $self->session->request->param("searchRoot");
if ((scalar(@userSpecifiedRoots) == 0)
|| ($self->getValue("forceSearchRoots"))
|| (isIn('any', @userSpecifiedRoots))
) {
@roots = split(/\n+/i, $self->get("searchRoot"));
} else {
@allowedRoots = split(/\n+/, $self->get("searchRoot"));
foreach (@userSpecifiedRoots) {
push (@roots, $_) if (isIn($_, @allowedRoots));
}
}
#foreach $pageId (@roots) {
# WebGUI::Page->new($pageId)->traversePreOrder(
# sub {
# push(@pages, $_[0]->get('pageId'));
# }
# );
#}
return [ @pages ];
}
#-------------------------------------------------------------------
sub _buildFilter {
my $self = shift;
my %filter = ();
# # pages
# if($self->get('searchRoot') !~ /any/i) {
# $filter{assetId} = $self->_buildPageList;
# }
# content-types
if($self->session->form->process("contentTypes") && ! isIn('any', $self->session->request->param('contentTypes'))) {
$filter{contentType} = [ $self->session->request->param('contentTypes') ];
# contentType "content" is a shortcut for "page", "wobject" and "wobjectDetail"
if (isIn('content', $self->session->request->param('contentTypes'))) {
push(@{$filter{contentType}}, qw/Asset assetDetail/);
}
} elsif ($self->getValue('contentTypes') !~ /any/i) {
$filter{contentType} = [ split(/\n/, $self->getValue('contentTypes')) ];
}
# users
if($self->session->form->process("users") && ! isIn('any', $self->session->request->param('users'))) {
$filter{ownerId} = [];
foreach my $user ($self->session->request->param('users')) {
if ($user =~ /\D/) {
$user =~ s/\*/%/g;
($user) = $self->session->db->buildArray("select userId from users where username like ".$self->session->db->quote($user));
}
push(@{$filter{ownerId}}, $self->session->db->quote($user)) if ($user =~ /^\d+$/);
}
} elsif ($self->getValue('users') !~ /any/i) {
$filter{ownerId} = [ split(/\n/, $self->getValue('users')) ];
}
# namespaces
if($self->session->form->process("namespaces") && ! isIn('any', $self->session->request->param('namespaces'))) {
$filter{namespace} = [ $self->session->request->param('namespaces') ];
} elsif ($self->getValue('namespaces') !~ /any/i) {
$filter{namespace} = [ split(/\n/, $self->getValue('namespaces')) ];
}
# delete $filter{ownerId} if it is an empty array reference
if(exists($filter{ownerId})) {
delete $filter{ownerId} unless (scalar(@{$filter{ownerId}}));
}
return \%filter;
}
#-------------------------------------------------------------------
sub _getNamespaces {
my ($self, $restricted) = @_;
my %international;
foreach my $class (@{$self->session->config->get("assets")}) {
my $load = 'use '.$class;
eval($load);
if ($@) {
$self->session->errorHandler->warn("Couldn't compile ".$class." because ".$@);
} else {
$international{$class} = eval{$class->getName()};
}
}
my $i18n = WebGUI::International->new($self->session,"Asset_IndexedSearch");
tie my %namespaces, 'Tie::IxHash';
if ($restricted and $self->get('namespaces') !~ /any/i) {
$namespaces{any} = $i18n->get(18);
foreach (split/\n/, $self->get('namespaces')) {
$namespaces{$_} = $international{$_} || ucfirst($_);
}
} else {
$namespaces{any} = $i18n->get(18);
foreach ($self->session->db->buildArray("select distinct(namespace) from IndexedSearch_docInfo order by namespace")) {
$namespaces{$_} = $international{$_} ||ucfirst($_);
}
}
return \%namespaces;
}
#-------------------------------------------------------------------
sub _getContentTypes {
my ($self, $restricted) = @_;
my $i18n = WebGUI::International->new($self->session,"Asset_IndexedSearch");
my %international = ( 'page' => $i18n->get('page'),
'wobject' => $i18n->get(19),
'wobjectDetail' => $i18n->get(20),
'content' =>$i18n->get(21),
'discussion' => $i18n->get('discussion'),
'profile' => $i18n->get(22),
'any' => $i18n->get(23),
);
tie my %contentTypes, 'Tie::IxHash';
if ($restricted and $self->get('contentTypes') !~ /any/i) {
$contentTypes{any} = $international{any};
$contentTypes{content} = $international{content}; # shortcut for page, wobject and wobjectDetail
foreach (split/\n/, $self->get('contentTypes')) {
$contentTypes{$_} = $international{$_};
}
} else {
%contentTypes = ( 'any' => $international{any},
'content' => $international{content}, # shortcut for page, wobject and wobjectDetail
);
foreach ($self->session->db->buildArray("select distinct(contentType) from IndexedSearch_docInfo order by contentType")) {
$contentTypes{$_} = $international{$_} || ucfirst($_);
}
}
return \%contentTypes;
}
#-------------------------------------------------------------------
sub _getSearchablePages {
my $self = shift;
my $searchRoot = shift;
my %pages;
my $sth = $self->session->db->read("select assetId from asset where parentId = ".$self->session->db->quote($searchRoot));
while (my %data = $sth->hash) {
$pages{$data{assetId}} = 1;
%pages = (%pages, $self->_getSearchablePages($data{assetId}) );
}
return %pages;
}
#-------------------------------------------------------------------
sub _getUsers {
my ($self, $restricted) = @_;
tie my %users, 'Tie::IxHash';
my $i18n = WebGUI::International->new($self->session,"Asset_IndexedSearch");
if ($restricted and $self->get('users') !~ /any/i) {
$users{any} = $i18n->get(25);
foreach (split/\n/, $self->get('users')) {
$users{$_} = $_;
}
} else {
%users = ( 'any' => $i18n->get(25),
$self->session->db->buildHash("select userId, username from users order by username")
);
}
return \%users;
}
1;

View file

@ -1,59 +0,0 @@
package WebGUI::Asset::Wobject::IndexedSearch::Search;
=head1 LEGAL
-------------------------------------------------------------------
WebGUI is Copyright 2001-2004 Plain Black Corporation.
-------------------------------------------------------------------
Please read the legal notices (docs/legal.txt) and the license
(docs/license.txt) that came with this distribution before using
this software.
-------------------------------------------------------------------
http://www.plainblack.com info@plainblack.com
-------------------------------------------------------------------
=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;
=head1 NAME
Package WebGUI::Wobject::IndexedSearch::Search
=head1 DESCRIPTION
Search implementation for WebGUI.
=head1 SYNOPSIS
use WebGUI::Wobject::IndexedSearch::Search;
my $search = WebGUI::Wobject::IndexedSearch::Search->new();
$search->indexDocument( { text => 'Index this text',
location => 'http://www.mysite.com/index.pl/faq#45',
languageId => 3,
namespace => 'FAQ'
});
my $hits = search->search("+foo -bar koo",{ namespace = ['Article', 'FAQ']} );
$search->close;
=head1 SEE ALSO
This package is an extension to DBIx::FullTextSearch and HTML::Highlight.
See that packages for documentation of their methods.
=head1 METHODS
These methods are available from this package:
=cut
1;

View file

@ -1,38 +0,0 @@
package WebGUI::Help::Asset_IndexedSearch;
our $HELP = {
'indexed search add/edit' => {
title => '26',
body => '27',
fields => [
],
related => [
{
tag => 'wobjects using',
namespace => 'Wobject'
},
{
tag => 'indexed search template',
namespace => 'Asset_IndexedSearch'
}
]
},
'indexed search template' => {
title => '29',
body => '28',
fields => [
],
related => [
{
tag => 'wobjects using',
namespace => 'Wobject'
},
{
tag => 'indexed search add/edit',
namespace => 'Asset_IndexedSearch'
}
]
},
};
1;

View file

@ -84,13 +84,13 @@ sub getAssets {
=head2 getResultSet ( ) =head2 getResultSet ( )
Returns a WebGUI::SQL::ResultSet object containing the search results with columns labeled "assetId", "title", "synopsis", "ownerUserId", "groupIdView", "groupIdEdit", "creationDate", "revisionDate", "startDate", "endDate", and "className". Returns a WebGUI::SQL::ResultSet object containing the search results with columns labeled "assetId", "title", "url", "synopsis", "ownerUserId", "groupIdView", "groupIdEdit", "creationDate", "revisionDate", and "className".
=cut =cut
sub getResultSet { sub getResultSet {
my $self = shift; my $self = shift;
my $query = "select assetId, title, synopsis, ownerUserId, groupIdView, groupIdEdit, creationDate, revisionDate, startDate, endDate, className my $query = "select assetId, title, url, synopsis, ownerUserId, groupIdView, groupIdEdit, creationDate, revisionDate, className
from assetIndex where isPublic=? and (".$self->{_query}.")"; from assetIndex where isPublic=? and (".$self->{_query}.")";
my $rs = $self->session->db->prepare($self->{_query}); my $rs = $self->session->db->prepare($self->{_query});
$rs->execute([$self->{_isPublic},@{$self->{_params}}]); $rs->execute([$self->{_isPublic},@{$self->{_params}}]);

View file

@ -112,9 +112,9 @@ sub create {
$url =~ s/\/|\-|\_/ /g; $url =~ s/\/|\-|\_/ /g;
my $description = WebGUI::HTML::filter($asset->get('description'), "all"); my $description = WebGUI::HTML::filter($asset->get('description'), "all");
my $keywords = join(" ",$asset->get("title"), $asset->get("menuTitle"), $asset->get("synopsis"), $url, $description); my $keywords = join(" ",$asset->get("title"), $asset->get("menuTitle"), $asset->get("synopsis"), $url, $description);
my $add = $self->session->db->prepare("insert into assetIndex (assetId, title, startDate, endDate, creationDate, revisionDate, my $add = $self->session->db->prepare("insert into assetIndex (assetId, title, url, creationDate, revisionDate,
ownerUserId, groupIdView, groupIdEdit, lineage, className, synopsis, keywords) values ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )"); ownerUserId, groupIdView, groupIdEdit, lineage, className, synopsis, keywords) values ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )");
$add->execute([$asset->getId, $asset->get("title"), $asset->get("startDate"), $asset->get("endDate"), $asset->get("creationDate"), $add->execute([$asset->getId, $asset->get("title"), $asset->get("url"), $asset->get("creationDate"),
$asset->get("revisionDate"), $asset->get("ownerUserId"), $asset->get("groupIdView"), $asset->get("groupIdEdit"), $asset->get("revisionDate"), $asset->get("ownerUserId"), $asset->get("groupIdView"), $asset->get("groupIdEdit"),
$asset->get("lineage"), $asset->get("className"), $asset->get("synopsis"), $keywords]); $asset->get("lineage"), $asset->get("className"), $asset->get("synopsis"), $keywords]);
return $self; return $self;

View file

@ -1,287 +0,0 @@
package WebGUI::i18n::English::Asset_IndexedSearch;
our $I18N = {
'11' => {
message => q|Paginate after|,
lastUpdated => 1066252409
},
'21' => {
message => q|Content|,
lastUpdated => 1066765681
},
'7' => {
message => q|Only results created by|,
lastUpdated => 1066252303
},
'26' => {
message => q|Search, Add/Edit|,
lastUpdated => 1067346336
},
'assetName' => {
message => q|Search|,
lastUpdated => 1066593262
},
'2' => {
message => q|No index created. The scheduler must run and create the index first.|,
lastUpdated => 1066252099
},
'22' => {
message => q|Profile|,
lastUpdated => 1066765844
},
'1' => {
message => q|Table Search_docInfo can't be opened.|,
lastUpdated => 1066252055
},
'18' => {
message => q|Any namespace|,
lastUpdated => 1066593420
},
'23' => {
message => q|Any Content Type|,
lastUpdated => 1066766053
},
'16' => {
message => q|Search|,
lastUpdated => 1066565087
},
'13' => {
message => q|Highlight results ?|,
lastUpdated => 1066252498
},
'29' => {
message => q|Search template|,
lastUpdated => 1070202588
},
'27' => {
message => q|
<P>The Search adds advanced search capabilities to your WebGUI site. </P>
<P><STRONG>Index to use</STRONG><BR>
The Search uses an index to retrieve it's
results from. Indexes are created with the scheduler. You can create more then one index. Choose here which index to use.</P>
<P><STRONG>Search through</STRONG><BR>
By default all pages are searched. You can
limit the search to certain page roots. Multiple choices are allowed.</P>
<P><STRONG>Only results created by</STRONG><BR>
You can limit the results to
items created by certain users. By default items from any user are returned.</P>
<P><STRONG>Only results in namespace</STRONG><BR>
By default all namespaces are
searched. You can limit the search to certain namespaces. An example of usage is
to search only in products.</P>
<P><STRONG>Only results in language</STRONG><BR>
If you have a multi-lingual
site, you can use this option to limit the search results to a certain
language.</P>
<P><STRONG>Only results of type</STRONG><BR>
You can limit the search to certain
types of content.</P>
<BLOCKQUOTE dir=ltr style="MARGIN-RIGHT: 0px">
<P align=left><EM>Discussion:</EM> Messages on the forums, discussions on
articles or USS.<BR><EM>Help:</EM> Content in the online WebGUI help
system<BR><EM>Page:</EM><STRONG> </STRONG>Page title and
synopsis<BR><EM>Profile:</EM> User Profiles<BR><EM>Wobject: </EM>Wobject Title
and Description<BR><EM>Wobject details: </EM>All other wobject data. For example
FAQ question, Calendar item, etc.</P></BLOCKQUOTE>
<P dir=ltr align=left><b>Force users to use selected roots</b><br>Enabling this option will cause the search to be over all of the selected page roots regardless of what the user entered via the search form.</b></p>
<P dir=ltr align=left><STRONG>Template<BR></STRONG>Select a template to layout
your Search. The different templates have different functionality.</P>
<P dir=ltr align=left><STRONG>Paginate after<BR></STRONG>The number of results
you'd like to display on a page.</P>
<P dir=ltr align=left><STRONG>Context preview length<BR></STRONG>The maximum
number of characters in each of the context sections. Default is 130 characters.
A negative length gives the complete body, while a preview length of null gives
no preview.</P>
<P dir=ltr align=left><STRONG>Highlight results ?<BR></STRONG>If you want to
highlight the search results in the preview you'll want to check this box.</P>
<P dir=ltr align=left><STRONG>Highlight color n<BR></STRONG>The colors that are
used to highlight the corresponding words in the query.</P>|,
lastUpdated => 1101773588
},
'25' => {
message => q|Any user|,
lastUpdated => 1066766053
},
'6' => {
message => q|Search through|,
lastUpdated => 1066252264
},
'28' => {
message => q|
<P>This is the list of template variables available for
search templates:</P>
<P><STRONG>query</STRONG><BR>
Contains the value of the <EM>query</EM> form
variable. <BR>The <EM>allWords</EM>, <EM>atLeastOne</EM>, <EM>exactPhrase</EM>
and <EM>without</EM> values are appended to this variable.</P>
<P><STRONG>queryHighlighted</STRONG><BR>
Same as <STRONG>query</STRONG> but highlighted.</P>
<P><STRONG>allWords</STRONG><BR>
Contains the value of the <EM>allWords</EM> form variable.</P>
<P><STRONG>atLeastOne</STRONG><BR>
Contains the value of the <EM>atLeastOne</EM> form variable.</P>
<P><STRONG>exactPhrase</STRONG><BR>
Contains the value of the <EM>exactPhrase</EM> form variable.</P>
<P><STRONG>without</STRONG><BR>
Contains the value of the <EM>without</EM> form variable.</P>
<P><STRONG>duration</STRONG><BR>
The duration of the search process in seconds.</P>
<P><STRONG>numberOfResults</STRONG><BR>
The number of results.</P>
<P><STRONG>startNr</STRONG><BR>
The number of the first search result on the page.</P>
<P><STRONG>endNr</STRONG><BR>
The number of the last search result on the page.</P>
<P><STRONG>submit</STRONG><BR>
A form button with the word "Search" printed on it.</P>
<P><STRONG>wid</STRONG><BR>
The wobject Id of this wobject.</P>
<P><STRONG>resultsLoop</STRONG><BR>
A loop containing the search results. Inside the loop the following template variables are available:</P>
<BLOCKQUOTE dir=ltr style="MARGIN-RIGHT: 0px">
<P><STRONG>username</STRONG><BR>
The username of the person that created this search result.</P>
<P><STRONG>ownerId</STRONG><BR>
The Id of the person that created this search result.</P>
<P><STRONG>userProfile</STRONG><BR>
An url to the profile of the creator of this search result.</P>
<P><STRONG>header</STRONG><BR>The title of the search result. (This can be the
subject of a message, the question of a FAQ, the title of an Article, etc)</P>
<P><STRONG>body</STRONG><BR>A preview of the content of the search result.</P>
<P><STRONG>namespace</STRONG><BR>The namespace in which this search result
resides.</P>
<P><STRONG>location</STRONG><BR>The URL of this search result.</P>
<P><STRONG>crumbtrail</STRONG><BR>A crumbtrail to this search result.</P>
<P><STRONG>contentType</STRONG><BR>The type of this search
result.</P></BLOCKQUOTE>
<P dir=ltr>The loops <STRONG>contentTypes</STRONG>,
<STRONG>contentTypesSimple</STRONG>, <STRONG>languages</STRONG>,
<STRONG>namespaces</STRONG> and <STRONG>users</STRONG> all look the same.
They can be used to create a select list, radio list or check list so users can
refine their search.</P>
<P dir=ltr>This template variables are available inside the loops:</P>
<BLOCKQUOTE dir=ltr style="MARGIN-RIGHT: 0px">
<P dir=ltr><STRONG>name</STRONG><BR>The (possibly internationalized) name of the
option.<BR><BR><STRONG>value<BR></STRONG>The value of the
option.<BR><BR><STRONG>selected<BR></STRONG>A conditional indicating whether
this option is selected or not.</P></BLOCKQUOTE>
<P dir=ltr><B>searchRoots</B><BR>A loop containing the available roots to search through.
<BLOCKQUOTE dir=ltr><P dir=ltr>
<b>title</b><br>The title of the pageroot.<br><br>
<b>urlizedTitle</b><br>The urlizedTitle of the pageroot.<br><br>
<b>menuTitle</b><br>The menu title of the pageroot.<br><br>
<b>value</b><br>The value you should pass as a form param.<br><br>
<b>checked</b><br>True if this pageroot is selected.<br><br>
</p></blockquote>
<p dir=ltr><b>rootPage.<i>urlizedTitle</i>.id</b><br>
This is a direct link to the value property of the rootpage identified with <i>urlizedTitle</i> that is also given by the value property of the <B>searchRoots</B> loop.</p>
<p dir=ltr><b>rootPage.<i>urlizedTitle</i>.checked</b><br>
This is a direct link to the checked property of the rootpage identified with <i>urlizedTitle</i> that is also given by the checked property of the <B>searchRoots</B> loop.</p>
<P><B>firstPage</B><BR>A link to the first page in the paginator.
<P><B>lastPage</B><BR>A link to the last page in the paginator.
<P><B>nextPage</B><BR>A link to the next page forward in the paginator.
<P><B>previousPage</B><BR>A link to the next page backward in the paginator.
<P><B>pageList</B><BR>A list of links to all the pages in the paginator.
<P><B>multiplePages</B><BR>A conditional indicating whether there is more than
one page in the paginator.
<P><B>isFirstPage</B><BR>A conditional indicating whether the visitor is viewing
the first page.
<P><B>isLastPage</B><BR>A conditional indicating whether the visitor is viewing
the last page.</P>|,
lastUpdated => 1101773812
},
'3' => {
message => q|Please refer to the documentation for more info.|,
lastUpdated => 1066252166
},
'9' => {
message => q|Only results in language|,
lastUpdated => 1066252363
},
'12' => {
message => q|Context preview length|,
lastUpdated => 1066252463
},
'15' => {
message => q|All pages|,
lastUpdated => 1066253116
},
'14' => {
message => q|Highlight color|,
lastUpdated => 1066252536
},
'20' => {
message => q|Wobject details|,
lastUpdated => 1066765556
},
'8' => {
message => q|Only results in namespace|,
lastUpdated => 1066252344
},
'4' => {
message => q|This page|,
lastUpdated => 1066252218
},
'24' => {
message => q|Any language|,
lastUpdated => 1066766053
},
'force search roots' => {
message => q|Force users to use the selected roots|,
lastUpdated => 1133844716
},
'19' => {
message => q|Wobject|,
lastUpdated => 1066765495
},
'10' => {
message => q|Only results of type|,
lastUpdated => 1066252387
},
'5' => {
message => q|Index to use|,
lastUpdated => 1066252241
},
'page' => {
message => q|Page|,
lastUpdated => 1109789907,
},
'discussion' => {
message => q|Discussion|,
lastUpdated => 1109789911,
},
};
1;

View file

@ -1,111 +0,0 @@
package Hourly::IndexedSearch_buildIndex;
#-------------------------------------------------------------------
# WebGUI is Copyright 2001-2004 Plain Black Corporation.
#-------------------------------------------------------------------
# Please read the legal notices (docs/legal.txt) and the license
# (docs/license.txt) that came with this distribution before using
# this software.
#-------------------------------------------------------------------
# http://www.plainblack.com info@plainblack.com
#-------------------------------------------------------------------
use DBI;
use strict;
use WebGUI::DateTime;
use WebGUI::Session;
use WebGUI::Utility;
use WebGUI::SQL;
use WebGUI::URL;
use WebGUI::Asset::Wobject::IndexedSearch::Search;
#-------------------------------------------------------------------
sub process {
#disabled until 6.8
return "";
my $indexName = 'IndexedSearch_default';
my $htmlFilter = 'all';
my $stopList = 'none';
my $stemmer = 'none';
my $backend = 'phrase';
my $verbose = shift;
my ($dateIndexed) = WebGUI::SQL->quickArray("select max(dateIndexed) from IndexedSearch_docInfo where indexName = ".quote($indexName));
if (WebGUI::DateTime::time()-$dateIndexed < 86400) {
print " - Recently Indexed: Skipping " if ($verbose);
return "";
}
print "\n";
undef $stopList if ($stopList eq 'none');
undef $stemmer if ($stemmer eq 'none');
my $indexInfo = getIndexerParams();
my $search = WebGUI::Asset::Wobject::IndexedSearch::Search->new($indexName);
$search->recreate('','',stemmer => $stemmer, stoplist => $stopList, backend => $backend);
my $startTime = WebGUI::DateTime::time();
foreach my $asset (keys %{$indexInfo}) {
print "Doing: $asset\n"; # DEBUG
my $sth = WebGUI::SQL->read($indexInfo->{$asset}{sql});
my $total = $sth->rows;
my $actual = 1;
while (my %data = $sth->hash) {
if ($verbose) {
print "\r\t\tIndexing $asset data ($total items) ...".
(" " x (30 - (length($asset)) - length("$total"))).
int(($actual/$total)*100)." % ";
}
my $textToIndex = "";
foreach my $field (@{$indexInfo->{$asset}{fieldsToIndex}}) {
if($field =~ /^\s*select/i) {
my $sql = eval 'sprintf("%s","'.$field.'")';
$textToIndex .= join("\n", WebGUI::SQL->buildArray($sql));
} else {
$textToIndex .= $data{$field}."\n";
}
}
$textToIndex = WebGUI::HTML::filter($textToIndex,$htmlFilter);
my $url = eval $indexInfo->{$asset}{url};
my $headerShortcut = eval 'sprintf("%s","'.$indexInfo->{$asset}{headerShortcut}.'")';
my $bodyShortcut = eval 'sprintf("%s","'.$indexInfo->{$asset}{bodyShortcut}.'")';
$search->indexDocument({
text => $textToIndex,
assetId => $data{assetId},
groupIdView => $data{groupIdView},
special_groupIdView => $data{special_groupIdView},
namespace => $asset,
location => $url,
headerShortcut => $headerShortcut,
bodyShortcut => $bodyShortcut,
contentType => $indexInfo->{$asset}{contentType},
ownerId => $data{ownerId}
});
$actual++;
}
print "\n" if ($verbose && $total);
}
print "\t\t".(($search->getDocId -1)." WebGUI items indexed in ".(time() - $startTime)." seconds.\n\t") if ($verbose);
$search->close;
}
#-------------------------------------------------------------------
sub getIndexerParams {
my $now = WebGUI::DateTime::time();
# don't add indexer parameters here. Rather edit the corresponding file in WebGUI/Asset/Wobject/*.pm
my %params;
foreach my $class (@{$session{config}{assets}}) {
my $load = 'use '.$class;
eval($load);
if ($@) {
WebGUI::ErrorHandler::warn("Couldn't compile ".$class." because ".$@);
} else {
my $assetIndexParams = eval{$class->getIndexerParams($now)};
if (ref $assetIndexParams eq 'HASH') {
%params = (%params, %{$assetIndexParams});
}
}
}
#use Data::Dumper ; die Dumper(\%params);
return \%params;
}
1;