1 module Rakka.Resource.PageEntity
7 import Control.Arrow.ArrowIO
8 import Control.Arrow.ArrowIf
9 import Control.Arrow.ArrowList
10 import Control.Monad.Trans
13 import Network.HTTP.Lucu
14 import Network.HTTP.Lucu.Utils
15 import Network.URI hiding (path)
16 import Rakka.Environment
20 import Rakka.SystemConfig
21 import Rakka.Wiki.Engine
22 import System.FilePath
23 import Text.XML.HXT.Arrow.WriteDocument
24 import Text.XML.HXT.Arrow.XmlArrow
25 import Text.XML.HXT.Arrow.XmlIOStateArrow
26 import Text.XML.HXT.Arrow.XmlNodeSet
27 import Text.XML.HXT.DOM.TypeDefs
28 import Text.XML.HXT.DOM.XmlKeywords
31 fallbackPageEntity :: Environment -> [String] -> IO (Maybe ResourceDef)
32 fallbackPageEntity env path
33 | null path = return Nothing
34 | null $ head path = return Nothing
35 | isLower $ head $ head path = return Nothing -- 先頭の文字が小文字であってはならない
37 = return $ Just $ ResourceDef {
38 resUsesNativeThread = False
40 , resGet = Just $ handleGet env (toPageName path)
43 , resPut = Just $ handlePut env (toPageName path)
47 toPageName :: [String] -> PageName
48 toPageName = decodePageName . dropExtension . joinWith "/"
51 handleGet :: Environment -> PageName -> Resource ()
53 = runIdempotentA $ proc ()
54 -> do pageM <- getPageA (envStorage env) -< (name, Nothing)
57 -> handlePageNotFound env -< name
59 Just redir@(Redirection _ _ _ _ _)
60 -> handleRedirect env -< redir
62 Just entity@(Entity _ _ _ _ _ _ _ _ _ _ _ _ _ _ _)
63 -> handleGetEntity env -< entity
67 Location: http://example.org/Destination.html#Redirect:Source
69 handleRedirect :: (ArrowXml a, ArrowIO a) => Environment -> a Page (Resource ())
72 -> returnA -< do mType <- getEntityType
74 MIMEType "application" "xhtml+xml" _
75 -> do BaseURI baseURI <- getSysConf (envSysConf env)
76 let uri = mkPageFragmentURI
79 ("Redirect:" ++ redirName redir)
82 MIMEType "text" "xml" _
83 -> do setContentType mType
84 [resultStr] <- liftIO $ runX ( setErrorMsgHandler False fail
90 writeDocumentToString [ (a_indent, v_1) ]
94 _ -> fail ("internal error: getEntityType returned " ++ show mType)
97 handleGetEntity :: (ArrowXml a, ArrowChoice a, ArrowIO a) => Environment -> a Page (Resource ())
100 -> do tree <- xmlizePage -< page
101 returnA -< do -- text/x-rakka の場合は、内容が動的に生成され
102 -- てゐる可能性があるので、ETag も
103 -- Last-Modified も返す事が出來ない。
104 case entityType page of
105 MIMEType "text" "x-rakka" _
107 _ -> case entityRevision page of
108 0 -> foundTimeStamp (entityLastMod page) -- 0 はデフォルトページ
109 rev -> foundEntity (strongETag $ show rev) (entityLastMod page)
111 outputXmlPage tree (entityToXHTML env)
114 entityToXHTML :: (ArrowXml a, ArrowChoice a, ArrowIO a) => Environment -> a XmlTree XmlTree
117 -> do SiteName siteName <- getSysConfA (envSysConf env) -< ()
118 BaseURI baseURI <- getSysConfA (envSysConf env) -< ()
119 StyleSheet styleSheet <- getSysConfA (envSysConf env) -< ()
121 name <- (getXPathTreesInDoc "/page/@name/text()" >>> getText) -< page
123 let cssHref = [uriToString id (mkObjectURI baseURI styleSheet) ""]
124 scriptSrc = [uriToString id (baseURI { uriPath = uriPath baseURI </> "js" }) ""]
126 pageTitle <- listA (readSubPage env) -< (name, Just page, "PageTitle")
127 leftSideBar <- listA (readSubPage env) -< (name, Just page, "SideBar/Left")
128 rightSideBar <- listA (readSubPage env) -< (name, Just page, "SideBar/Right")
129 pageBody <- listA (makeMainXHTML (envStorage env) (envSysConf env) (envInterpTable env)) -< page
133 += sattr "xmlns" "http://www.w3.org/1999/xhtml"
134 += ( getXPathTreesInDoc "/page/@lang"
136 qattr (QN "xml" "lang" "")
137 ( getXPathTreesInDoc "/page/@lang/text()" )
143 += getXPathTreesInDoc "/page/@name/text()"
148 += sattr "rel" "stylesheet"
149 += sattr "type" "text/css"
150 += attr "href" (arr id >>> mkText)
152 += ( constL scriptSrc
155 += sattr "type" "text/javascript"
156 += attr "src" (arr id >>> mkText)
161 += sattr "class" "header"
164 += sattr "class" "center"
166 += sattr "class" "title"
170 += sattr "class" "body"
175 += sattr "class" "footer"
178 += sattr "class" "left sideBar"
180 += sattr "class" "content"
181 += constL leftSideBar
185 += sattr "class" "right sideBar"
187 += sattr "class" "content"
188 += constL rightSideBar
195 readSubPage :: (ArrowXml a, ArrowChoice a, ArrowIO a) =>
197 -> a (PageName, Maybe XmlTree, PageName) XmlTree
199 = proc (mainPageName, mainPage, subPageName) ->
200 do subPage <- getPageA (envStorage env) >>> arr fromJust >>> xmlizePage -< (subPageName, Nothing)
201 subXHTML <- makeSubXHTML (envStorage env) (envSysConf env) (envInterpTable env)
202 -< (mainPageName, mainPage, subPage)
207 <pageNotFound name="Foo/Bar" />
209 handlePageNotFound :: (ArrowXml a, ArrowChoice a, ArrowIO a) => Environment -> a PageName (Resource ())
210 handlePageNotFound env
212 -> do tree <- ( eelem "/"
213 += ( eelem "pageNotFound"
214 += attr "name" (arr id >>> mkText)
217 returnA -< do setStatus NotFound
218 outputXmlPage tree (notFoundToXHTML env)
221 notFoundToXHTML :: (ArrowXml a, ArrowChoice a, ArrowIO a) => Environment -> a XmlTree XmlTree
224 -> do SiteName siteName <- getSysConfA (envSysConf env) -< ()
225 BaseURI baseURI <- getSysConfA (envSysConf env) -< ()
226 StyleSheet styleSheet <- getSysConfA (envSysConf env) -< ()
228 name <- (getXPathTreesInDoc "/pageNotFound/@name/text()" >>> getText) -< pageNotFound
230 let cssHref = [uriToString id (mkObjectURI baseURI styleSheet) ""]
231 scriptSrc = [uriToString id (baseURI { uriPath = uriPath baseURI </> "js" }) ""]
233 pageTitle <- listA (readSubPage env) -< (name, Nothing, "PageTitle")
234 leftSideBar <- listA (readSubPage env) -< (name, Nothing, "SideBar/Left")
235 rightSideBar <- listA (readSubPage env) -< (name, Nothing, "SideBar/Right")
239 += sattr "xmlns" "http://www.w3.org/1999/xhtml"
244 += getXPathTreesInDoc "/pageNotFound/@name/text()"
249 += sattr "rel" "stylesheet"
250 += sattr "type" "text/css"
251 += attr "href" (arr id >>> mkText)
253 += ( constL scriptSrc
256 += sattr "type" "text/javascript"
257 += attr "src" (arr id >>> mkText)
262 += sattr "class" "header"
265 += sattr "class" "center"
267 += sattr "class" "title"
271 += sattr "class" "body"
272 += txt "404 Not Found (FIXME)" -- FIXME
276 += sattr "class" "footer"
279 += sattr "class" "left sideBar"
281 += sattr "class" "content"
282 += constL leftSideBar
286 += sattr "class" "right sideBar"
288 += sattr "class" "content"
289 += constL rightSideBar
296 handlePut :: Environment -> PageName -> Resource ()
298 = runXmlA env "rakka-page-1.0.rng" $ proc tree
299 -> do page <- parseXmlizedPage -< (name, tree)
300 status <- putPageA (envStorage env) -< page
301 returnA -< setStatus status