root/platform/tdiary/util/estraier-search/estraier-search.rb @ 31683

Revision 31683, 6.7 kB (checked in by hsbt, 4 years ago)

replace defout to stdout. defout is obsolete.

  • Property svn:executable set to *
Line 
1#!/usr/bin/env ruby
2# estraier-search.rb $Revision: 1.1.2.12 $
3#
4# Copyright (C) 2007 Kazuhiko <kazuhiko@fdiary.net>
5# You can redistribute it and/or modify it under GPL2.
6#
7$KCODE= 'u'
8BEGIN { $stdout.binmode }
9
10require "estraierpure"
11require "enumerator"
12require "date"
13
14if FileTest::symlink?( __FILE__ ) then
15        org_path = File::dirname( File::readlink( __FILE__ ) )
16else
17        org_path = File::dirname( __FILE__ )
18end
19$:.unshift( org_path.untaint )
20require 'tdiary'
21
22#
23# class TDiaryEstraier
24#
25module TDiary
26        class TDiaryEstraier < ::TDiary::TDiaryBase
27                MAX_PAGES = 20
28                SORT_OPTIONS = [
29                        ["score", "スコア順"],
30                        ["date", "日付順"],
31                ]
32                ORDER_OPTIONS = [
33                        ["asc", "昇順"],
34                        ["desc", "降順"],
35                ]
36                FORM_OPTIONS = [
37                        ["simple", "簡便書式"],
38                        ["normal", "通常書式"],
39                ]
40                NUM_OPTIONS = [10, 20, 30, 50, 100]
41
42                def initialize( cgi, rhtml, conf )
43                        super
44                        @host = @conf["estraier.host"] || "localhost"
45                        @port = @conf["estraier.port"] || 1978
46                        @path = @conf["estraier.path"] || "/node/"
47                        @node = @conf["estraier.node"] || "tdiary"
48                        parse_args
49                        format_form
50                        if @query.empty?
51                                @msg = '検索条件を入力して、「検索」ボタンを押してください'
52                        else
53                                search
54                        end
55                end
56
57                def load_plugins
58                        super
59                        # add a opensearch rss link
60                        @plugin.instance_variable_get('@header_procs').unshift Proc.new {
61                                cgi_url = @conf.base_url.sub(%r|/[^/]*$|, '/') + (@cgi.script_name ? _(File.basename(@cgi.script_name)) : '')
62                                %Q|\t<link rel="alternate" type="application/rss+xml" title="Search Result RSS" href="#{cgi_url}#{format_anchor(@start, @num)};type=rss">\n|
63                        }
64                        # override some plugins
65                        def @plugin.sn(number = nil); ''; end
66                        def @plugin.whats_new; ''; end
67                end
68
69                def eval_rxml
70                        require 'time'
71                        load_plugins
72                        ERB::new( File::open( "#{PATH}/skel/estraier.rxml" ){|f| f.read }.untaint ).result( binding )
73                end
74
75                private
76
77                def parse_args
78                        @query = @cgi["query"].strip
79                        @start = @cgi["start"].to_i
80                        @num = @cgi["num"].to_i
81                        if @num < 1
82                                @num = 10
83                        elsif @num > 100
84                                @num = 100
85                        end
86                        @sort = @cgi["sort"].empty? ? "score" : @cgi["sort"]
87                        @order = @cgi["order"].empty? ? "desc" : @cgi["order"]
88                        @form = @cgi["form"].empty? ? "simple" : @cgi["form"]
89                end
90
91                def search
92                        @db = EstraierPure::Node.new
93                        @db.set_url("http://#{@host}:#{@port}#{@path}#{@node}")
94                        begin
95                                t = Time.now
96                                cond = create_search_options
97                                cond.set_phrase(convert(@query))
98                                @result = @db.search(cond, 0)
99                                @secs = Time.now - t
100                        rescue
101                                @msg = "エラー: #{_($!.to_s + $@.join)}</p>"
102                        end
103                end
104
105                def format_result_item(item)
106                        @date = item.attr('@uri')
107                        if @conf["estraier.with_user_name"]
108                                @date.gsub!(/.*:/, "")
109                        end
110                        @date_str = Date.parse(@date).strftime(@conf.date_format)
111                        @last_modified = item.attr('@mdate')
112                        @title = _(item.attr('@title'))
113                        @summary = _(item.snippet).gsub(/\t.*/, "").gsub(/\n\n/, " ... ").gsub(/\n/, "")
114                        for term in @query.split
115                                @title.gsub!(Regexp.new(Regexp.quote(CGI.escapeHTML(term)), true, @encoding), "<strong>\\&</strong>")
116                                @summary.gsub!(Regexp.new(Regexp.quote(CGI.escapeHTML(term)), true, @encoding), "<strong>\\&</strong>")
117                        end
118                        query = "[SIMILAR]"
119                        item.keywords.split(/\t/).enum_slice(2).collect do |k, s|
120                                query << " WITH #{s} #{k}"
121                        end
122                        @similar = "%s?query=%s" %
123                                [_(@cgi.script_name || ""), CGI::escape(query)]
124                end
125
126                def format_links(result)
127                        page_count = (result.doc_num - 1) / @num + 1
128                        current_page = @start / @num + 1
129                        first_page = current_page - (MAX_PAGES / 2 - 1)
130                        if first_page < 1
131                                first_page = 1
132                        end
133                        last_page = first_page + MAX_PAGES - 1
134                        if last_page > page_count
135                                last_page = page_count
136                        end
137                        buf = "<p class=\"infobar\">\n"
138                        if current_page > 1
139                                buf.concat(format_link("前へ", @start - @num, @num))
140                        end
141                        if first_page > 1
142                                buf.concat("... ")
143                        end
144                        for i in first_page..last_page
145                                if i == current_page
146                                        buf.concat("#{i} ")
147                                else
148                                        buf.concat(format_link(i.to_s, (i - 1) * @num, @num))
149                                end
150                        end
151                        if last_page < page_count
152                                buf.concat("... ")
153                        end
154                        if current_page < page_count
155                                buf.concat(format_link("次へ", @start + @num, @num))
156                        end
157                        buf.concat("</p>\n")
158                        return buf
159                end
160
161                def format_anchor(start, num)
162                        return format('?query=%s;start=%d;num=%d;sort=%s;order=%s', CGI::escape(@query), start, num, _(@sort), _(@order))
163                end
164
165                def format_link(label, start, num)
166                        return format('<a href="%s%s">%s</a> ', _(@cgi.script_name ? @cgi.script_name : ""),  format_anchor(start, num), _(label))
167                end
168
169                def create_search_options
170                        cond = EstraierPure::Condition.new
171                        if @conf["estraier.with_user_name"]
172                                cond.add_attr("@uri STRBW #{@conf.user_name}:")
173                        end
174                        if @sort == "date"
175                                order = "@uri"
176                        else
177                                order = ""
178                        end
179                        if @order == "asc"
180                                order = "[SCA]" if order.empty?
181                        else
182                                unless order.empty?
183                                        order << " STRD"
184                                end
185                        end
186                        if @form == "simple"
187                                cond.set_options(EstraierPure::Condition::SIMPLE)
188                        end
189                        cond.set_order(order)
190                        return cond
191                end
192
193                def format_options(options, value)
194                        return options.collect { |val, label|
195                                if val == value
196                                        "<option value=\"#{_(val)}\" selected>#{_(label)}</option>"
197                                else
198                                        "<option value=\"#{_(val)}\">#{_(label)}</option>"
199                                end
200                        }.join("\n")
201                end
202
203                def format_form
204                        @num_options = NUM_OPTIONS.collect { |n|
205                                if n == @num
206                                        "<option value=\"#{n}\" selected>#{n}件ずつ</option>"
207                                else
208                                        "<option value=\"#{n}\">#{n}件ずつ</option>"
209                                end
210                        }.join("\n")
211                        @sort_options = format_options(SORT_OPTIONS, @sort)
212                        @order_options = format_options(ORDER_OPTIONS, @order)
213                        @form_options = format_options(FORM_OPTIONS, @form)
214                end
215
216                def _(str)
217                        CGI::escapeHTML(str)
218                end
219
220                def convert(str)
221                        @conf.to_native(str)
222                end
223        end
224end
225
226begin
227        @cgi = CGI::new
228        if ::TDiary::Config.instance_method(:initialize).arity > 0
229                # for tDiary 2.1 or later
230                conf = ::TDiary::Config::new(@cgi)
231        else
232                # for tDiary 2.0 or earlier
233                conf = ::TDiary::Config::new
234        end
235        tdiary = TDiary::TDiaryEstraier::new( @cgi, 'estraier.rhtml', conf )
236
237        head = {
238                'type' => 'text/html',
239                'Vary' => 'User-Agent'
240        }
241        if @cgi.mobile_agent? then
242                body = conf.to_mobile( tdiary.eval_rhtml( 'i.' ) )
243                head['charset'] = conf.mobile_encoding
244                head['Content-Length'] = body.size.to_s
245        else
246                if @cgi['type'] == 'rss'
247                        head['type'] = "application/xml; charset=#{conf.encoding}"
248                        body = tdiary.eval_rxml
249                else
250                        body = tdiary.eval_rhtml
251                end
252                head['charset'] = conf.encoding
253                head['Content-Length'] = body.size.to_s
254                head['Pragma'] = 'no-cache'
255                head['Cache-Control'] = 'no-cache'
256        end
257        print @cgi.header( head )
258        print body
259rescue Exception
260        if @cgi then
261                print @cgi.header( 'type' => 'text/plain' )
262        else
263                print "Content-Type: text/plain\n\n"
264        end
265        puts "#$! (#{$!.class})"
266        puts ""
267        puts $@.join( "\n" )
268end
Note: See TracBrowser for help on using the browser.