Commit d494290f authored by Frank Bergmann's avatar Frank Bergmann

- OpenACS 5.9

parent b5d4aec9
......@@ -27,7 +27,7 @@ if { $current_page_group < $last_page_group } {
}
if { $current_result_page > 0 } {
set offset [expr ($current_result_page - 1) * $limit]
set offset [expr {($current_result_page - 1) * $limit}]
set url_previous [export_vars -base search {{q $urlencoded_query} search_package_id offset num}]
} else {
set url_previous ""
......
<form method=GET action="@search_url@" class="inline-form">
<div>
<input type="text" name="q" title="#search.Enter_keywords_to_search_for#" size="16" maxlength="256">
<input type=submit value="#acs-kernel.common_search#" name=t>
<input type="submit" value="#acs-kernel.common_search#" name="t">
<br>
<a href="@advanced_search_url@">#search.Advanced_Search#</a>
</div>
......
......@@ -6,35 +6,34 @@
<pretty-plural>Search</pretty-plural>
<initial-install-p>t</initial-install-p>
<singleton-p>t</singleton-p>
<auto-mount>search</auto-mount>
<implements-subsite-p>f</implements-subsite-p>
<inherit-templates-p>t</inherit-templates-p>
<version name="5.7.0" url="http://openacs.org/repository/download/apm/search-5.7.0.apm">
<version name="5.10.0d1" url="http://openacs.org/repository/download/apm/search-5.10.0d1.apm">
<owner url="http://openacs.org">OpenACS</owner>
<release-date>2011-06-12</release-date>
<maturity>3</maturity>
<summary>Site wide search</summary>
<release-date>2013-10-01</release-date>
<vendor url="http://openacs.org">OpenACS</vendor>
<maturity>3</maturity>
<license url="http://www.gnu.org/copyleft/gpl.html">GPL version 2</license>
<description format="text/html">Site wide search implemented with service contracts, currently supports postgres via the tsearch2 driver (OpenFTS still support but deprecated).</description>
<license>GPL version 2</license>
<maturity>3</maturity>
<provides url="search" version="5.7.0"/>
<requires url="acs-service-contract" version="5.7.0"/>
<provides url="search" version="5.10.0d1"/>
<requires url="acs-service-contract" version="5.10.0d1"/>
<callbacks>
<callback type="after-instantiate" proc="search::install::after_instantiate"/>
<callback type="after-instantiate" proc="search::install::after_instantiate"/>
</callbacks>
<parameters>
<parameter datatype="number" min_n_values="1" max_n_values="1" name="FtsEngineDriver" default="tsearch2-driver" description="Which search engine driver to use? You should enter the name of the related binding (e.g. openfts-driver, swish-driver,...)"/>
<parameter datatype="number" min_n_values="1" max_n_values="1" name="PagesPerGroup" default="10" description="Number of pages in a page group"/>
<parameter datatype="number" min_n_values="1" max_n_values="1" name="LimitDefault" default="10" description="Default limit value"/>
<parameter datatype="number" min_n_values="1" max_n_values="1" name="SearchIndexerInterval" default="31" description="Interval in seconds for the search indexer to sweep for new or updated items."/>
<parameter datatype="string" min_n_values="1" max_n_values="1" name="SearchTheWeb" default="http://av.com/sites/search/web?q=%s AltaVista http://msxml.excite.com/info.xcite/search/web/%s Excite http://www.google.com/search?q=%s Google http://hotbot.com/?MT=%s HotBot http://search.yahoo.com/search?p=%s Yahoo!" description="Search the Web (e.g. Google)"/>
<parameter datatype="string" min_n_values="1" max_n_values="1" name="Symbol2Interval" default="m3 {3 month ago} m6 {6 month ago} y1 {1 year ago}" description="Translate symbol to date interval."/>
<parameter datatype="number" min_n_values="1" max_n_values="1" name="SubsiteSearchP" default="0" description="If mounted in a subsite should the search be restricted to items in the subsite by default. Requires that package_id in acs_objects be properly populated."/>
<parameter datatype="number" min_n_values="1" max_n_values="1" name="Syndicate" default="0" description="Should syndication data be stored when indexing for search."/>
<parameter scope="instance" datatype="number" min_n_values="1" max_n_values="1" name="FtsEngineDriver" default="tsearch2-driver" description="Which search engine driver to use? You should enter the name of the related binding (e.g. openfts-driver, swish-driver,...)"/>
<parameter scope="instance" datatype="number" min_n_values="1" max_n_values="1" name="LimitDefault" default="10" description="Default limit value"/>
<parameter scope="instance" datatype="number" min_n_values="1" max_n_values="1" name="PagesPerGroup" default="10" description="Number of pages in a page group"/>
<parameter scope="instance" datatype="number" min_n_values="1" max_n_values="1" name="SearchIndexerInterval" default="31" description="Interval in seconds for the search indexer to sweep for new or updated items."/>
<parameter scope="instance" datatype="string" min_n_values="1" max_n_values="1" name="SearchTheWeb" default="http://www.ask.com/web?q=%s Ask.com http://www.bing.com/search?q=%s Bing https://duckduckgo.com/?q=%s DuckDuckGo https://www.google.com/search?q=%s Google https://twitter.com/search?q=%s Twitter http://search.yahoo.com/search?p=%s Yahoo!" description="Search the Web (e.g. Google)"/>
<parameter scope="instance" datatype="number" min_n_values="1" max_n_values="1" name="SubsiteSearchP" default="0" description="If mounted in a subsite should the search be restricted to items in the subsite by default. Requires that package_id in acs_objects be properly populated."/>
<parameter scope="instance" datatype="string" min_n_values="1" max_n_values="1" name="Symbol2Interval" default="m3 {3 month ago} m6 {6 month ago} y1 {1 year ago}" description="Translate symbol to date interval."/>
<parameter scope="instance" datatype="number" min_n_values="1" max_n_values="1" name="Syndicate" default="0" description="Should syndication data be stored when indexing for search."/>
</parameters>
</version>
</package>
......@@ -2,12 +2,17 @@
--
-- @cvs-id $Id$
create or replace function search_observer__enqueue(integer,varchar)
returns integer as '
declare
p_object_id alias for $1;
p_event alias for $2;
begin
--
-- procedure search_observer__enqueue/2
--
CREATE OR REPLACE FUNCTION search_observer__enqueue(
p_object_id integer,
p_event varchar
) RETURNS integer AS $$
DECLARE
BEGIN
insert into search_observer_queue (
object_id,
event
......@@ -18,26 +23,33 @@ begin
return 0;
end;' language 'plpgsql';
END;
$$ LANGUAGE plpgsql;
select define_function_args('search_observer__enqueue','object_id,event');
create or replace function search_observer__dequeue(integer,timestamptz,varchar)
returns integer as '
declare
p_object_id alias for $1;
p_event_date alias for $2;
p_event alias for $3;
begin
--
-- procedure search_observer__dequeue/3
--
CREATE OR REPLACE FUNCTION search_observer__dequeue(
p_object_id integer,
p_event_date timestamptz,
p_event varchar
) RETURNS integer AS $$
DECLARE
BEGIN
delete from search_observer_queue
where object_id = p_object_id
and event = p_event
and to_char(event_date,''yyyy-mm-dd hh24:mi:ss.us-tz'') = to_char(p_event_date,''yyyy-mm-dd hh24:mi:ss.us-tz'');
and to_char(event_date,'yyyy-mm-dd hh24:mi:ss.us-tz') = to_char(p_event_date,'yyyy-mm-dd hh24:mi:ss.us-tz');
return 0;
end;' language 'plpgsql';
END;
$$ LANGUAGE plpgsql;
select define_function_args('search_observer__dequeue','object_id,event_date,event');
create table search_observer_queue (
object_id integer,
object_id integer not null
references acs_objects(object_id) on delete cascade,
event_date timestamptz default current_timestamp,
event varchar(6)
constraint search_observer_queue_event_ck
check (event in ('INSERT','DELETE','UPDATE'))
);
......@@ -9,13 +9,21 @@
drop function search_observer__dequeue(integer,timestamp with time zone,varchar);
create function search_observer__dequeue(integer,timestamp with time zone,varchar)
returns integer as '
declare
p_object_id alias for $1;
p_event_date alias for $2;
p_event alias for $3;
begin
-- added
select define_function_args('search_observer__dequeue','object_id,event_date,event');
--
-- procedure search_observer__dequeue/3
--
CREATE OR REPLACE FUNCTION search_observer__dequeue(
p_object_id integer,
p_event_date timestamp with time zone,
p_event varchar
) RETURNS integer AS $$
DECLARE
BEGIN
delete from search_observer_queue
where object_id = p_object_id
......@@ -24,7 +32,8 @@ begin
return 0;
end;' language 'plpgsql';
END;
$$ LANGUAGE plpgsql;
--
......
......@@ -22,38 +22,54 @@ ad_proc -public search::convert::binary_to_text {
@creation-date 2005-06-25
} {
set tmp_filename [ns_tmpnam]
set tmp_filename [ad_tmpnam]
set result ""
switch $mime_type {
{application/msword} -
{application/vnd.ms-word} {
application/msword -
application/vnd.ms-word {
set convert_command {catdoc $filename >$tmp_filename}
}
{application/msexcel} -
{application/vnd.ms-excel} {
application/msexcel -
application/vnd.ms-excel {
set convert_command {xls2csv $filename >$tmp_filename}
}
{application/mspowerpoint} -
{application/vnd.ms-powerpoint} {
set convert_command {ppthtml $filename >$tmp_filename}
application/mspowerpoint -
application/vnd.ms-powerpoint {
set convert_command {catppt $filename >$tmp_filename}
}
{application/pdf} {
application/pdf {
set convert_command {pdftotext $filename $tmp_filename}
}
{application/vnd.oasis.opendocument.text} -
{application/vnd.oasis.opendocument.text-template} -
{application/vnd.oasis.opendocument.text-web} -
{application/vnd.oasis.opendocument.text-master} -
{application/vnd.oasis.opendocument.presentation} -
{application/vnd.oasis.opendocument.presentation-template} -
{application/vnd.oasis.opendocument.spreadsheet} -
{application/vnd.oasis.opendocument.spreadsheet-template} {
application/vnd.oasis.opendocument.text -
application/vnd.oasis.opendocument.text-template -
application/vnd.oasis.opendocument.text-web -
application/vnd.oasis.opendocument.text-master -
application/vnd.oasis.opendocument.presentation -
application/vnd.oasis.opendocument.presentation-template -
application/vnd.oasis.opendocument.spreadsheet -
application/vnd.oasis.opendocument.spreadsheet-template {
set convert_command {unzip -p $filename content.xml >$tmp_filename}
}
{text/html} {
return [catch {[ns_striphtml $filename]} error]
text/html {
file delete $tmp_filename
#
# Reading the whole content into memory is not necessarily
# the best when dealing with huge files. However, for
# html-files this is probably ok.
#
return [ns_striphtml [template::util::read_file $filename]]
}
text/plain {
file delete $tmp_filename
#
# Reading the whole content into memory is not necessarily
# the best when dealing with huge files. However, for
# txt-files this is probably ok.
#
return [template::util::read_file $filename]
}
default {
# If there's nothing implemented for a particular mime type
# we'll just index filename and pathname
......
......@@ -121,7 +121,7 @@ ad_proc -private search::indexer {} {
}
}
foreach {object_id event_date event} $row { break }
lassign $row object_id event_date event
array unset datasource
switch -- $event {
UPDATE -
......@@ -130,8 +130,9 @@ ad_proc -private search::indexer {} {
if {![info exists seen($object_id)]} {
set object_type [acs_object_type $object_id]
ns_log debug "\n-----DB-----\n SEARCH INDEX object type = '${object_type}' \n------------\n "
if {[callback::impl_exists -callback search::datasource -impl $object_type] \
|| [acs_sc_binding_exists_p FtsContentProvider $object_type]} {
if {[callback::impl_exists -callback search::datasource -impl $object_type]
|| [acs_sc_binding_exists_p FtsContentProvider $object_type]} {
array set datasource {mime {} storage_type {} keywords {}}
if {[catch {
# check if a callback exists, if not fall
......@@ -140,24 +141,41 @@ ad_proc -private search::indexer {} {
#ns_log notice "\n-----DB-----\n SEARCH INDEX callback datasource exists for object_type '${object_type}'\n------------\n "
array set datasource [lindex [callback -impl $object_type search::datasource -object_id $object_id] 0]
} else {
array set datasource [acs_sc_call FtsContentProvider datasource [list $object_id] $object_type]
#ns_log notice "invoke contract [list acs_sc::invoke -contract FtsContentProvider -operation datasource -call_args [list $object_id] -impl $object_type]"
array set datasource [acs_sc::invoke -contract FtsContentProvider \
-operation datasource \
-call_args [list $object_id] \
-impl $object_type]
}
search::content_get txt $datasource(content) $datasource(mime) $datasource(storage_type) $object_id
if {[callback::impl_exists -callback search::index -impl $driver]} {
if {![info exists datasource(package_id)]} {
set datasource(package_id) ""
}
# set datasource(community_id) [search::dotlrn::get_community_id -package_id $datasource(package_id)]
# set datasource(community_id) [search::dotlrn::get_community_id -package_id $datasource(package_id)]
if {![info exists datasource(relevant_date)]} {
set datasource(relevant_date) ""
}
callback -impl $driver search::index -object_id $object_id -content $txt -title $datasource(title) -keywords $datasource(keywords) -package_id $datasource(package_id) -community_id $datasource(community_id) -relevant_date $datasource(relevant_date) -datasource datasource
#ns_log notice "callback invoke search::index"
callback -impl $driver search::index \
-object_id $object_id \
-content $txt \
-title $datasource(title) \
-keywords $datasource(keywords) \
-package_id $datasource(package_id) \
-community_id $datasource(community_id) \
-relevant_date $datasource(relevant_date) \
-datasource datasource
} else {
acs_sc_call FtsEngineDriver \
[ad_decode $event UPDATE update_index index] \
[list $datasource(object_id) $txt $datasource(title) $datasource(keywords)] $driver
#ns_log notice "acs_sc::invoke FtsEngineDriver"
set r [acs_sc::invoke \
-contract FtsEngineDriver \
-operation [ad_decode $event UPDATE update_index index] \
-call_args [list $datasource(object_id) $txt $datasource(title) $datasource(keywords)] \
-impl $driver]
}
} errMsg]} {
ns_log Error "search::indexer: error getting datasource for $object_id $object_type: $errMsg\n[ad_print_stack_trace]\n"
......@@ -179,7 +197,7 @@ ad_proc -private search::indexer {} {
}
DELETE {
if {[catch {
acs_sc_call FtsEngineDriver unindex [list $object_id] $driver
set r [acs_sc::invoke -contract FtsEngineDriver -operation unindex -call_args [list $object_id] -impl $driver]
} errMsg]} {
ns_log Error "search::indexer: error unindexing $object_id [acs_object_type $object_id]: $errMsg\n[ad_print_stack_trace]\n"
} else {
......@@ -227,8 +245,8 @@ ad_proc -private search::content_get {
holds the lob_id if storage_type=lob
} {
upvar $_txt txt
set txt ""
set passing_style string
# lob and file are not currently implemented
switch $storage_type {
......@@ -237,16 +255,18 @@ ad_proc -private search::content_get {
}
file {
set data [cr_fs_path][db_string get_filename "select content from cr_revisions where revision_id=:object_id"]
set passing_style file
}
lob {
set data [db_blob_get get_lob_data {}]
}
}
search::content_filter txt data $mime
search::content_filter -passing_style $passing_style txt data $mime
}
ad_proc -private search::content_filter {
{-passing_style string}
_txt
_data
mime
......@@ -256,13 +276,33 @@ ad_proc -private search::content_filter {
upvar $_txt txt
upvar $_data data
switch -glob -- $mime {
{text/*} {
set txt $data
}
default {
set txt [search::convert::binary_to_text -filename $data -mime_type $mime]
}
#ns_log notice "---search::content_filter $mime data=[string length $data] <$passing_style>"
if {$passing_style eq "string"} {
if {[string match text/* $mime]} {
if {$mime eq "text/html"} {
set txt [ns_striphtml $data]
} else {
set txt $data
}
return
}
#
# Write content to a file and let the filter below extract the
# words for the index from the file.
#
set tmp_filename [ad_tmpnam]
set f [open $tmp_filename w]
puts $f $data
close $f
set data $tmp_filename
}
set txt [search::convert::binary_to_text -filename $data -mime_type $mime]
#ns_log notice "search::content_filter txt len [string length $txt]"
if {[info exists tmp_filename]} {
file delete $tmp_filename
}
}
......
<master>
<property name="title">#search.Advanced_Search#</property>
<property name="doc(title)">#search.Advanced_Search#</property>
<property name="context">"advanced search"</property>
<div>
<form method=GET action=search>
<p>
<input type=text name=q size=41 maxlength=256 value="@q@">
<input type=submit value="Search" name=t>
<input type="text" name="q" size="41" maxlength="256" value="@q@">
<input type="submit" value="Search" name="t">
</p>
<p>
<label for="dfs">#search.Date_Range#</label>
......
......@@ -112,25 +112,28 @@ how that part looks like for <code>note</code>.
<code><pre>
create function notes__itrg ()
returns opaque as '
returns opaque as $$
begin
perform search_observer__enqueue(new.note_id,''INSERT'');
perform search_observer__enqueue(new.note_id,'INSERT');
return new;
end;' language 'plpgsql';
end;
$$ language plpgsql;
create function notes__dtrg ()
returns opaque as '
returns opaque as $$
begin
perform search_observer__enqueue(old.note_id,''DELETE'');
perform search_observer__enqueue(old.note_id,'DELETE');
return old;
end;' language 'plpgsql';
end;
$$ language plpgsql;
create function notes__utrg ()
returns opaque as '
returns opaque as $$
begin
perform search_observer__enqueue(old.note_id,''UPDATE'');
perform search_observer__enqueue(old.note_id,'UPDATE');
return old;
end;' language 'plpgsql';
end;
$$ language plpgsql;
create trigger notes__itrg after insert on notes
......
<master>
<property name="title">#search.Search#</property>
<property name="doc(title)">#search.Search#</property>
<div style="text-align:center">
<form method=GET action=search>
<div><small><a href=advanced-search>#search.Advanced_Search#</a></small></div>
<div><small><a href="advanced-search">#search.Advanced_Search#</a></small></div>
<div>
<input type=text name=q size=80 maxlength=256>
<input type="text" name="q" size="80" maxlength="256">
<br>
<input type=submit value="#search.Search#" name=t>
<input type=submit value="#search.Feeling_Lucky#" name=t>
<input type="submit" value="#search.Search#" name="t">
<input type="submit" value="#search.Feeling_Lucky#" name="t">
</div>
</form>
</div>
<master>
<property name="context">Results</property>
<property name="context">@context;literal@</property>
<property name="doc(title)">@page_title;literal@</property>
<if @empty_p@ true>
<p class="hint">#search.lt_You_must_specify_some#</p>
<if @and_queries_notice_p@ eq 1>
<font color="6f6f6f">
#search.The#
[<a href="help/basics#and">#search.details#</a>]<br>
</font>
</if>
<if @nstopwords@ eq 1>
<font color="6f6f6f">
#search.lt_bstopwordsb_is_a_very#
[<a href="help/basics#stopwords">#search.details#</a>]<br>
</font>
</if>
<if @nstopwords@ gt 1>
<font color="6f6f6f">
#search.lt_The_following_words_a# <b>@stopwords@</b>.
[<a href="help/basics#stopwords">#search.details#</a>]<br>
</font>
</if>
<else>
<if @and_queries_notice_p@ eq 1>
<font color="6f6f6f">
#search.The#
[<a href=help/basics#and>#search.details#</a>]<br>
</font>
</if>
<if @nstopwords@ eq 1>
<font color="6f6f6f">
#search.lt_bstopwordsb_is_a_very#
[<a href=help/basics#stopwords>#search.details#</a>]<br>
</font>
</if>
<if @nstopwords@ gt 1>
<font color="6f6f6f">
#search.lt_The_following_words_a# <b>@stopwords@</b>.
[<a href=help/basics#stopwords>#search.details#</a>]<br>
</font>
</if>
<if @count@ eq 0>
<if @count@ eq 0>
Your search - <b>@query@</b> - did not match any content.
<br>#search.lt_No_pages_were_found_c#<b>@query@</b>".
<br><br>#search.Suggestions#
......@@ -33,70 +30,69 @@
<li>#search.lt_Try_different_keyword#
<li>#search.lt_Try_more_general_keyw#
<if @nquery@ gt 2>
<li>#search.Try_fewer_keywords#
<li>#search.Try_fewer_keywords#</li>
</if>
</ul>
</if>
<else>
<div id="search-info">
<p class="subtitle">#search.Searched_for_query#</p>
<p class="times">
#search.Results# <strong>@low@-@high@</strong> #search.of_about# <strong>@count@</strong>#search.________Search_took# <strong>@elapsed@</strong> #search.seconds#
</p>
</div>
<div id="search-results">
<ol style="counter-reset:item @offset@">
<multiple name="searchresult">
<li>
<a href="@searchresult.url_one@" class="result-title">
<if @searchresult.title_summary@ nil>#search.Untitled#</if>
<else>@searchresult.title_summary;noquote@</else>
</a>
<if @searchresult.txt_summary@ not nil>
<div class="result-text">@searchresult.txt_summary;noquote@</div>
</if>
<div class="result-url">@searchresult.url_one@</div>
</li>
</multiple>
</ol>
</div>
</else>
</if>
<else>
<div id="search-info">
<p class="subtitle">#search.Searched_for_query#</p>
<p class="times">
#search.Results# <strong>@low@-@high@</strong> #search.of_about# <strong>@count@</strong>#search.________Search_took# <strong>@elapsed@</strong> #search.seconds#
</p>
</div>
<div id="search-results">
<ol style="counter-reset:item @offset@">
<multiple name="searchresult">
<li>
<a href="@searchresult.url_one@" class="result-title">
<if @searchresult.title_summary@ nil>#search.Untitled#</if>
<else>@searchresult.title_summary;noquote@</else>
</a>
<if @searchresult.txt_summary@ not nil>
<div class="result-text">@searchresult.txt_summary;noquote@</div>
</if>
<div class="result-url">@searchresult.url_one@</div>
</li>
</multiple>
</ol>
</div>
</else>
<include src="/packages/search/lib/navbar" &="urlencoded_query"
paginator_class="list-paginator-bottom" count="@result.count@" &="low" &="high"
<include src="/packages/search/lib/navbar" &="urlencoded_query"
paginator_class="list-paginator-bottom" count="@result.count;literal@" &="low" &="high"
&="offset" &="num" &="search_package_id">
<if @count@ gt 0>
<div style="text-align:center">
<form method="get" action="search">
<div>
<input type="text" name="q" size="60" maxlength="256" value="@query@">
<input type="submit" value="#search.Search#">
</div>
</form>
<if @t@ eq "Search">
<i>#search.lt_Tip_In_most_browsers_#</i>
</if>
</div>
<div style="text-align:center">
<form method="get" action="search">
<div>
<input type="text" name="q" size="60" maxlength="256" value="@query@">
<input type="submit" value="#search.Search#">
</div>
</form>
<if @t@ eq "Search">
<i>#search.lt_Tip_In_most_browsers_#</i>
</if>
</div>
<if @stw@ not nil>
<p style="text-align:center;font-size=-1">#search.lt_Try_your_query_on_stw#</p>
</if>
<if @stw@ not nil>
<p style="text-align:center;font-size=-1">#search.lt_Try_your_query_on_stw#</p>
</if>
</if>
</else>
<if @and_queries_notice_p@ eq 1>
<p class="hint">#search.and_not_needed# [<a href="help/basics#and">#search.details#</a>]</p>
<p class="hint">#search.and_not_needed# [<a href="help/basics#and">#search.details#</a>]</p>
</if>
<if @nstopwords@ eq 1>
<p class="hint">#search.lt_bstopwordsb_is_a_very# [<a href="help/basics#stopwords">#search.details#</a>]</p>
<p class="hint">#search.lt_bstopwordsb_is_a_very# [<a href="help/basics#stopwords">#search.details#</a>]</p>
</if>
<if @nstopwords@ gt 1>
<p class="hint">#search.lt_The_following_words_a# [<a href="help/basics#stopwords">#search.details#</a>]</p>
<p class="hint">#search.lt_The_following_words_a# [<a href="help/basics#stopwords">#search.details#</a>]</p>
</if>
<if @debug_p@>
<p>#search.Searched_for_query#</p>
<p>#search.Results_count#</p>
<p>#search.Searched_for_query#</p>
<p>#search.Results_count#</p>
</if>
......@@ -5,16 +5,16 @@ ad_page_contract {
} {
q:trim
{t:trim ""}
{offset:integer 0}
{num:integer 0}
{dfs:trim ""}
{dts:trim ""}
{search_package_id ""}
{offset:naturalnum 0}
{num:naturalnum 0}
{dfs:word,trim ""}
{dts:word,trim ""}
{search_package_id:naturalnum ""}
{scope ""}
{object_type ""}
{object_type:token ""}
} -validate {
keywords_p {
if {![exists_and_not_null q]} {
if {![info exists q] || $q eq ""} {
ad_complain "#search.lt_You_must_specify_some#"
}
}
......@@ -27,7 +27,7 @@ set package_id [ad_conn package_id]
set package_url [ad_conn package_url]
set package_url_with_extras $package_url
set context results
set context Results
set context_base_url $package_url
# Do we want debugging information at the end of the page
......@@ -39,28 +39,14 @@ if {[callback::impl_exists -impl $driver -callback search::driver_info]} {
array set info [lindex [callback -impl $driver search::driver_info] 0]
# array set info [list package_key intermedia-driver version 1 automatic_and_queries_p 1 stopwords_p 1]
} else {
array set info [acs_sc_call FtsEngineDriver info [list] $driver]
array set info [acs_sc::invoke -contract FtsEngineDriver -operation info -call_args [list] -impl $driver]
}
if { [array get info] eq "" } {
ReturnHeaders
ns_write "[_ search.lt_FtsEngineDriver_not_a]"
ns_return 200 text/html [_ search.lt_FtsEngineDriver_not_a]
ad_script_abort
}
if {[string trim $q] eq ""} {
set query {}
set empty_p 1
set url_advanced_search "advanced-search"
ad_return_template
# FIXME DAVEB I don't understand why I can't call ad_script_abort here instead of return....
# if I call ad_script_abort the adp is never rendered
return
} else {
set empty_p 0
}
if { $num <= 0} {
set limit [parameter::get -package_id $package_id -parameter LimitDefault]
} else {
......@@ -89,13 +75,14 @@ if { $dts ne "" } {
#set q [string tolower $q]
set urlencoded_query [ad_urlencode $q]
if { $offset < 0 } { set offset 0 }
set params [list $q $offset $limit $user_id $df]
if {$search_package_id eq "" && [parameter::get -package_id $package_id -parameter SubsiteSearchP -default 1]
&& [subsite::main_site_id] != [ad_conn subsite_id]} {
# We are in a subsite and SubsiteSearchP is true
lappend params [concat [ad_conn subsite_id] [subsite::util::packages -node_id [ad_conn node_id]]]
} else {
set subsite_packages [concat [ad_conn subsite_id] [subsite::util::packages -node_id [ad_conn node_id]]]
lappend params $subsite_packages
set search_package_id $subsite_packages
} elseif {$search_package_id ne ""} {
lappend params $search_package_id
}
......@@ -115,11 +102,14 @@ if {"this" ne $scope } {
if {[callback::impl_exists -impl $driver -callback search::search]} {
# DAVEB TODO Add subsite to the callback def?
# FIXME do this in the intermedia driver!
# set final_query_string [db_string final_query_select "select site_wide_search.im_convert(:q) from dual"]
# set final_query_string [db_string final_query_select "select site_wide_search.im_convert(:q) from dual"]
array set result [lindex [callback -impl $driver search::search -query $q -offset $offset -limit $limit -user_id $user_id -df $df -extra_args [list package_ids $search_package_id object_type $object_type]] 0]
array set result [lindex [callback -impl $driver search::search -query $q -offset $offset -limit $limit \
-user_id $user_id -df $df \
-extra_args [list package_ids $search_package_id object_type $object_type]] 0]
} else {
array set result [acs_sc_call FtsEngineDriver search $params $driver]
array set result [acs_sc::invoke -contract FtsEngineDriver -operation search \
-call_args $params -impl $driver]
}
set tend [clock clicks -milliseconds]
......@@ -129,18 +119,26 @@ if { $t eq [_ search.Feeling_Lucky] && $result(count) > 0} {
if {[callback::impl_exists -impl $object_type -callback search::url]} {
set url [callback -impl $object_type search::url -object_id $object_id]
} else {
set url [acs_sc_call FtsContentProvider url [list $object_id] $object_type]
set url [acs_sc::invoke -contract FtsContentProvider -operation url \
-call_args [list $object_id] -impl $object_type]
}
ad_returnredirect $url
ad_script_abort
}
set elapsed [format "%.02f" [expr {double(abs($tend - $t0)) / 1000.0}]]
#
# $count is the number of results to be displayed, while
# $result(count) is the total number of results (without taking
# permissions into account)
#
set count [llength $result(ids)]
if { $offset >= $result(count) } { set offset [expr {($result(count) / $limit) * $limit}] }
set low [expr {$offset + 1}]
set high [expr {$offset + $limit}]
if { $high > $result(count) } { set high $result(count) }
if { $info(automatic_and_queries_p) && ([lsearch -exact $q and] > 0) } {
if { $info(automatic_and_queries_p) && "and" in $q } {
set and_queries_notice_p 1
} else {
set and_queries_notice_p 0
......@@ -150,38 +148,35 @@ set url_advanced_search ""
append url_advanced_search "advanced-search?q=$urlencoded_query"
if { $num > 0 } { append url_advanced_search "&num=$num" }
set query $q
set nquery [llength [split $q]]
set stopwords $result(stopwords)
set nstopwords [llength $result(stopwords)]
set count $result(count)
template::multirow create searchresult title_summary txt_summary url_one object_id
for { set __i 0 } { $__i < [expr {$high - $low +1}] } { incr __i } {
foreach object_id $result(ids) {
if {[catch {
set object_id [lindex $result(ids) $__i]
if {$object_id eq ""} {
ns_log warning "Search object_id is empty, this should never happen query was '${q}'"
continue
}
set object_type [acs_object_type $object_id]
if {[callback::impl_exists -impl $object_type -callback search::datasource]} {
array set datasource [lindex [callback -impl $object_type search::datasource -object_id $object_id] 0]
set url_one [lindex [callback -impl $object_type search::url -object_id $object_id] 0]
} else {
ns_log warning "SEARCH search/www/search.tcl callback::datasource::$object_type not found"
array set datasource [acs_sc_call FtsContentProvider datasource [list $object_id] $object_type]
set url_one [acs_sc_call FtsContentProvider url [list $object_id] $object_type]
#ns_log warning "SEARCH search/www/search.tcl callback::datasource::$object_type not found"
array set datasource [acs_sc::invoke -contract FtsContentProvider -operation datasource \
-call_args [list $object_id] -impl $object_type]
set url_one [acs_sc::invoke -contract FtsContentProvider -operation url \
-call_args [list $object_id] -impl $object_type]
}
search::content_get txt $datasource(content) $datasource(mime) $datasource(storage_type) $object_id
if {[callback::impl_exists -impl $driver -callback search::summary]} {
set title_summary [lindex [callback -impl $driver search::summary -query $q -text $datasource(title)] 0]
set txt_summary [lindex [callback -impl $driver search::summary -query $q -text $txt] 0]
} else {
set title_summary [acs_sc_call FtsEngineDriver summary [list $q $datasource(title)] $driver]
set txt_summary [acs_sc_call FtsEngineDriver summary [list $q $txt] $driver]
set title_summary [acs_sc::invoke -contract FtsEngineDriver -operation summary \
-call_args [list $q $datasource(title)] -impl $driver]
set txt_summary [acs_sc::invoke -contract FtsEngineDriver -operation summary \
-call_args [list $q $txt] -impl $driver]
}
} errmsg]} {
ns_log error "search.tcl object_id $object_id object_type $object_type error $errmsg"
......@@ -191,7 +186,7 @@ for { set __i 0 } { $__i < [expr {$high - $low +1}] } { incr __i } {
}
set search_the_web [parameter::get -package_id $package_id -parameter SearchTheWeb]
if {[llength $search_the_web]} {
if {$search_the_web ne ""} {
set stw ""
foreach {url site} $search_the_web {
append stw "<a href=\"[format $url $urlencoded_query]\">$site</a> "
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment