1 module Rakka.Resource.Search
6 import qualified Codec.Binary.UTF8.String as UTF8
8 import Control.Arrow.ArrowIO
9 import Control.Arrow.ArrowIf
10 import Control.Arrow.ArrowList
11 import Control.Arrow.ArrowTree
12 import Control.Monad.Trans
14 import Network.HTTP.Lucu
15 import Network.URI hiding (query, fragment)
16 import Rakka.Environment
20 import Rakka.SystemConfig
22 import Rakka.Wiki.Engine
23 import System.FilePath
24 import Text.HyperEstraier
25 import Text.XML.HXT.Arrow.Namespace
26 import Text.XML.HXT.Arrow.XmlArrow
27 import Text.XML.HXT.Arrow.XmlNodeSet
28 import Text.XML.HXT.DOM.TypeDefs
31 resSearch :: Environment -> ResourceDef
34 resUsesNativeThread = False
36 , resGet = Just $ handleSearch env
44 defaultResultsPerPage :: Int
45 defaultResultsPerPage = 20
49 <searchResult query="foo bar baz"
55 aaa <hit>foo</hit> bbb
61 handleSearch :: Environment -> Resource ()
63 = do params <- getQueryForm
65 let query = UTF8.decodeString $ fromMaybe "" $ lookup "q" params
67 $ fmap read $ lookup "from" params
68 to = fromMaybe defaultResultsPerPage
69 $ fmap read $ lookup "to" params
71 cond <- liftIO $ mkCond query from to
72 result <- searchPages (envStorage env) cond
74 let to' = min (from + length (srPages result)) to
76 runIdempotentA $ proc ()
77 -> do tree <- ( eelem "/"
78 += ( eelem "searchResult"
79 += sattr "query" query
80 += sattr "from" (show from)
81 += sattr "to" (show to')
82 += sattr "total" (show $ srTotal result)
83 += ( constL (srPages result)
89 returnA -< outputXmlPage' tree (searchResultToXHTML env)
91 mkCond :: String -> Int -> Int -> IO Condition
93 = do cond <- newCondition
96 setMax cond (to - from)
99 mkPageElem :: ArrowXml a => a HitPage XmlTree
100 mkPageElem = ( eelem "page"
101 += attr "name" (arr hpPageName >>> mkText)
108 mkSnippetTree :: ArrowXml a => a SnippetFragment XmlTree
109 mkSnippetTree = proc fragment
111 Boundary -> eelem "boundary"
112 NormalText t -> txt t
113 HighlightedWord w -> eelem "hit" += txt w
117 searchResultToXHTML :: (ArrowXml a, ArrowChoice a, ArrowIO a) => Environment -> a XmlTree XmlTree
118 searchResultToXHTML env
120 -> do SiteName siteName <- getSysConfA (envSysConf env) -< ()
121 BaseURI baseURI <- getSysConfA (envSysConf env) -< ()
122 StyleSheet styleSheet <- getSysConfA (envSysConf env) -< ()
123 GlobalLock isGLocked <- getSysConfA (envSysConf env) -< ()
125 let cssHref = [uriToString id (mkObjectURI baseURI styleSheet) ""]
126 scriptSrc = [uriToString id (baseURI { uriPath = uriPath baseURI </> "js" }) ""]
128 pageTitle <- listA (readSubPage env) -< (Nothing, Nothing, "PageTitle")
129 leftSideBar <- listA (readSubPage env) -< (Nothing, Nothing, "SideBar/Left")
130 rightSideBar <- listA (readSubPage env) -< (Nothing, Nothing, "SideBar/Right")
134 += sattr "xmlns" "http://www.w3.org/1999/xhtml"
139 += getXPathTreesInDoc "/searchResult/@query/text()"
144 += sattr "rel" "stylesheet"
145 += sattr "type" "text/css"
146 += attr "href" (arr id >>> mkText)
148 += ( constL scriptSrc
151 += sattr "type" "text/javascript"
152 += attr "src" (arr id >>> mkText)
155 += sattr "type" "text/javascript"
156 += txt ("Rakka.baseURI=\"" ++ uriToString id baseURI "" ++ "\";")
157 += txt ("Rakka.isGlobalLocked=" ++ trueOrFalse isGLocked ++ ";")
158 += txt "Rakka.isSpecialPage=true;"
163 += sattr "class" "header"
166 += sattr "class" "center"
168 += sattr "class" "title"
172 += sattr "class" "body"
174 += txt "Search Result"
177 += sattr "class" "searchStat"
178 += txt "Search result for "
180 += sattr "class" "queryString"
181 += getXPathTreesInDoc "/searchResult/@query/text()"
184 += getXPathTreesInDoc "/searchResult/@total/text()"
187 += ( getXPathTreesInDoc "/searchResult/page"
190 += sattr "class" "searchResult"
192 += attr "href" ( getAttrValue "name"
194 arr (\ x -> uriToString id (mkPageURI baseURI x) "")
198 += (getAttrValue "name" >>> mkText)
203 choiceA [ isText :-> this
204 , hasName "boundary" :-> txt " ... "
205 , hasName "hit" :-> ( eelem "span"
206 += sattr "class" "highlighted"
216 += sattr "class" "footer"
219 += sattr "class" "left sideBar"
221 += sattr "class" "content"
222 += constL leftSideBar
226 += sattr "class" "right sideBar"
228 += sattr "class" "content"
229 += constL rightSideBar
234 uniqueNamespacesFromDeclAndQNames
238 readSubPage :: (ArrowXml a, ArrowChoice a, ArrowIO a) =>
240 -> a (Maybe PageName, Maybe XmlTree, PageName) XmlTree
242 = proc (mainPageName, mainPage, subPageName) ->
243 do subPage <- getPageA (envStorage env) >>> arr fromJust >>> xmlizePage -< (subPageName, Nothing)
244 subXHTML <- makeSubXHTML (envStorage env) (envSysConf env) (envInterpTable env)
245 -< (mainPageName, mainPage, subPage)