search completed
This commit is contained in:
parent
1f3a97235b
commit
0cd851d779
3 changed files with 195 additions and 5 deletions
|
|
@ -6,8 +6,10 @@ use Moose;
|
|||
use JSON qw( from_json to_json );
|
||||
use namespace::autoclean;
|
||||
use Scalar::Util;
|
||||
use Search::QueryParser;
|
||||
use WebGUI::Pluggable;
|
||||
use WebGUI::Macro;
|
||||
use WebGUI::Search;
|
||||
|
||||
has 'session' => (
|
||||
is => 'ro',
|
||||
|
|
@ -133,6 +135,42 @@ sub getAssetTypes {
|
|||
|
||||
return %assetList;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
=head2 getKeywordString ( keywordString )
|
||||
|
||||
Munge the keyword string from the user into something mysql will Do The
|
||||
Right Thing with
|
||||
|
||||
=cut
|
||||
|
||||
# Stolen from WebGUI::Search->search
|
||||
sub getKeywordString {
|
||||
my ( $self, $keywords ) = @_;
|
||||
|
||||
# do wildcards for people like they'd expect unless they are doing it themselves
|
||||
unless ($keywords =~ m/"|\*/) {
|
||||
# split into 'words'. Ideographic characters (such as Chinese) are
|
||||
# treated as distinct words. Everything else is space delimited.
|
||||
my @terms = grep { $_ ne q{} } split /\s+|(\p{Ideographic})/, $keywords;
|
||||
for my $term (@terms) {
|
||||
# we add padding to ideographic characters to avoid minimum word length limits on indexing
|
||||
if ($term =~ /\p{Ideographic}/) {
|
||||
$term = q{''}.$term.q{''};
|
||||
}
|
||||
$term .= q{*};
|
||||
next if WebGUI::Search->_isStopword( $term );
|
||||
next
|
||||
if $term =~ /^[+-]/;
|
||||
$term = q{+} . $term;
|
||||
}
|
||||
$keywords = join q{ }, @terms;
|
||||
}
|
||||
|
||||
return $keywords;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
=head2 getNewContentTemplateVars
|
||||
|
|
@ -260,6 +298,80 @@ sub getNewContentTemplateVars {
|
|||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 getSearchPaginator ( queryString )
|
||||
|
||||
Get a paginator for searching with the given queryString.
|
||||
|
||||
=cut
|
||||
|
||||
sub getSearchPaginator {
|
||||
my ( $self, $queryString ) = @_;
|
||||
my $session = $self->session;
|
||||
|
||||
my $sql = 'SELECT assetId FROM assetIndex JOIN asset USING (assetId) WHERE '
|
||||
. ' ( ' . $self->getSqlFromQueryString( $queryString ) . ' ) '
|
||||
;
|
||||
|
||||
my $p = WebGUI::Paginator->new( $session );
|
||||
$p->setDataByQuery( $sql );
|
||||
return $p;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 getSqlFromQueryString ( queryString )
|
||||
|
||||
Parse the query string and return a SQL boolean clause suitable to be used
|
||||
as a WHERE clause. Does not return WHERE, as you could also use it for HAVING
|
||||
|
||||
=cut
|
||||
|
||||
sub getSqlFromQueryString {
|
||||
my ( $self, $queryString ) = @_;
|
||||
|
||||
my $sqp = Search::QueryParser->new( defField => 'keywords' );
|
||||
my $query = $sqp->parse( $queryString );
|
||||
|
||||
# Recursion is recursive
|
||||
my $part = sub {
|
||||
my ( $query, $conj ) = @_;
|
||||
my @parts;
|
||||
for my $part ( @$query ) {
|
||||
if ( ref $part->{value} ) {
|
||||
push @parts, $self->getSqlFromQueryString( $_ );
|
||||
}
|
||||
elsif ( $part->{field} eq 'keywords' ) {
|
||||
push @parts, "MATCH ($part->{field}) AGAINST ('"
|
||||
. $self->getKeywordString( $part->{value} )
|
||||
. "')";
|
||||
}
|
||||
else {
|
||||
# TODO: Add op validation
|
||||
# TODO: Add field quoting
|
||||
# TODO: Add value quoting
|
||||
if ( $part->{op} eq ':' ) {
|
||||
my $value = '%' . $part->{value} . '%';
|
||||
push @parts, "$part->{field} LIKE '$value'";
|
||||
}
|
||||
else {
|
||||
push @parts, "$part->{field} $part->{op} '$part->{value}'"
|
||||
}
|
||||
}
|
||||
}
|
||||
return join " $conj ", @parts;
|
||||
};
|
||||
my $must = $query->{'+'} ? '(' . $part->( $query->{'+'}, 'AND' ) . ')' : undef;
|
||||
my $mustNot = $query->{'-'} ? 'NOT ( ' . $part->( $query->{'-'}, 'OR' ) . ')' : undef;
|
||||
my $may = $query->{''} ? $part->( $query->{''}, 'OR' ) : undef;
|
||||
|
||||
my $sql = $must . ( $must && $mustNot ? " AND " : '' ) . $mustNot
|
||||
. ( $must || $mustNot ? " OR " : '' ) . $may
|
||||
;
|
||||
return $sql;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 getTreePaginator ( $asset )
|
||||
|
||||
Get a page for the Asset Tree view. Returns a WebGUI::Paginator object
|
||||
|
|
@ -518,6 +630,64 @@ sub www_processAssetHelper {
|
|||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
=head2 www_searchAssets ( )
|
||||
|
||||
Search the asset tree for the given keywords and filters
|
||||
|
||||
=cut
|
||||
|
||||
sub www_searchAssets {
|
||||
my ( $self ) = @_;
|
||||
my $session = $self->session;
|
||||
my ( $user, $form ) = $session->quick(qw{ user form });
|
||||
|
||||
# Get the search
|
||||
my $queryString = $form->get('query');
|
||||
return to_json( {} ) unless $queryString;
|
||||
|
||||
my $i18n = WebGUI::International->new( $session, "Asset" );
|
||||
my $assetInfo = { assets => [] };
|
||||
my $p = $self->getSearchPaginator( $queryString );
|
||||
|
||||
for my $result ( @{ $p->getPageData } ) {
|
||||
my $assetId = $result->{assetId};
|
||||
my $asset = WebGUI::Asset->newById( $session, $assetId );
|
||||
|
||||
# Populate the required fields to fill in
|
||||
my %fields = (
|
||||
assetId => $asset->getId,
|
||||
url => $asset->getUrl,
|
||||
lineage => $asset->lineage,
|
||||
title => $asset->menuTitle,
|
||||
revisionDate => $asset->revisionDate,
|
||||
childCount => $asset->getChildCount,
|
||||
assetSize => $asset->assetSize,
|
||||
lockedBy => ($asset->isLockedBy ? $asset->lockedBy->username : ''),
|
||||
canEdit => $asset->canEdit && $asset->canEditIfLocked,
|
||||
helpers => $asset->getHelpers,
|
||||
);
|
||||
|
||||
$fields{ className } = {};
|
||||
# The asset icon
|
||||
$fields{ icon } = $asset->getIcon("small");
|
||||
|
||||
# The asset type (i18n name)
|
||||
$fields{ className } = $asset->getName;
|
||||
|
||||
push @{ $assetInfo->{ assets } }, \%fields;
|
||||
}
|
||||
|
||||
$assetInfo->{ totalAssets } = $p->getRowCount;
|
||||
$assetInfo->{ sort } = $session->form->get( 'orderByColumn' );
|
||||
$assetInfo->{ dir } = lc $session->form->get( 'orderByDirection' );
|
||||
|
||||
$session->http->setMimeType( 'application/json' );
|
||||
|
||||
return to_json( $assetInfo );
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
=head2 www_view ( session )
|
||||
|
||||
Show the main Admin console wrapper
|
||||
|
|
|
|||
|
|
@ -138,6 +138,10 @@ input.disabled {
|
|||
margin: 1em 8% 0;
|
||||
}
|
||||
|
||||
.searchResults table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.searchKeywords {
|
||||
display: block;
|
||||
width: 90%;
|
||||
|
|
|
|||
|
|
@ -179,6 +179,10 @@ WebGUI.Admin.prototype.editAsset
|
|||
*/
|
||||
WebGUI.Admin.prototype.gotoAsset
|
||||
= function ( url ) {
|
||||
if ( this.tabBar.get('activeIndex') > 1 ) {
|
||||
this.tabBar.selectTab( 0 );
|
||||
this.currentTab = "view";
|
||||
}
|
||||
if ( this.currentTab == "view" ) {
|
||||
window.frames[ "view" ].location.href = url;
|
||||
this.treeDirty = 1;
|
||||
|
|
@ -1268,7 +1272,7 @@ WebGUI.Admin.AssetTable.prototype.showHelperMenu
|
|||
// destroy the old helper menu!
|
||||
this.helperMenu.destroy();
|
||||
}
|
||||
this.helperMenu = new YAHOO.widget.Menu( {
|
||||
this.helperMenu = new YAHOO.widget.Menu( document.createElement('div'), {
|
||||
position : "dynamic",
|
||||
clicktohide : true,
|
||||
constraintoviewport : true,
|
||||
|
|
@ -1939,11 +1943,13 @@ WebGUI.Admin.Search
|
|||
|
||||
// Create a container for the datatable
|
||||
this.dataTableContainer = document.createElement('div');
|
||||
this.dataTableContainer.style.display = "none";
|
||||
this.dataTableContainer.className = "searchResults";
|
||||
this.dataTableContainer.id = YAHOO.util.Dom.generateId();
|
||||
this.formContainer.appendChild( this.dataTableContainer );
|
||||
|
||||
// Create a container for the paginator
|
||||
// ...
|
||||
// TODO
|
||||
WebGUI.Admin.Search.superclass.constructor.call( this, admin, {
|
||||
dataSourceUrl : '?op=admin;method=searchAssets;',
|
||||
dataTableId : this.dataTableContainer.id,
|
||||
|
|
@ -2141,9 +2147,9 @@ WebGUI.Admin.Search.prototype.buildQueryString
|
|||
WebGUI.Admin.Search.prototype.requestSearch
|
||||
= function ( ) {
|
||||
// Build the new search URL
|
||||
var searchUrl = ';keywords=' + encodeURIComponent( this.searchKeywords.value );
|
||||
var query = 'query=' + encodeURIComponent( this.searchKeywords.value );
|
||||
for ( var i = 0; i < this.filters.length; i++ ) {
|
||||
searchUrl += ';' + filter.type + '=' + filter.getValue();
|
||||
query += ' ' + encodeURIComponent( filter.type + ':' + filter.getValue() );
|
||||
}
|
||||
|
||||
var callback = {
|
||||
|
|
@ -2157,10 +2163,20 @@ WebGUI.Admin.Search.prototype.requestSearch
|
|||
this.buildQueryString(
|
||||
this.dataTable.getState(),
|
||||
this.dataTable,
|
||||
searchUrl
|
||||
query
|
||||
),
|
||||
callback
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* onDataReturnInitializeTable ( sRequest, oResponse, oPayload )
|
||||
* Initialize the table with a new response from the server
|
||||
*/
|
||||
WebGUI.Admin.Search.prototype.onDataReturnInitializeTable
|
||||
= function ( sRequest, oResponse, oPayload ) {
|
||||
this.dataTableContainer.style.display = "block";
|
||||
WebGUI.Admin.Tree.superclass.onDataReturnInitializeTable.call( this, sRequest, oResponse, oPayload );
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue