module Web.Fn.Extra.Digestive (runForm) where
import Control.Applicative ((<$>))
import Control.Arrow (second)
import Control.Concurrent.MVar (readMVar)
import Control.Monad.Trans (liftIO)
import Control.Monad.Trans.Resource
import Data.ByteString (ByteString)
import Data.Maybe (fromMaybe)
import Data.Text (Text)
import qualified Data.Text.Encoding as T
import Network.HTTP.Types.Method
import Network.Wai (Request (..))
import Network.Wai.Parse (File, FileInfo (..), fileContent,
parseRequestBody)
import Text.Digestive (Form, View, FormInput(..), Env, fromPath, postForm, getForm)
import Web.Fn hiding (File)
queryFormEnv :: [(ByteString, Maybe ByteString)] -> [File FilePath] -> Env IO
queryFormEnv qs fs = \pth ->
let qs' = map (TextInput . T.decodeUtf8 . fromMaybe "" . snd) $ filter (forSubForm pth) qs
fs' = map (FileInput . fileContent . snd) $ filter (forSubForm pth) $ filter fileNameNotEmpty fs
in return $ qs' ++ fs'
where fileNameNotEmpty (_formName, fileInfo) = Network.Wai.Parse.fileName fileInfo /= "\"\""
forSubForm pth = (==) (fromPath pth) . T.decodeUtf8 . fst
requestFormEnv :: FnRequest -> ResourceT IO (Env IO)
requestFormEnv req = do
st <- getInternalState
v <- case snd req of
Nothing -> return Nothing
Just mv -> liftIO (readMVar mv)
(query, files) <-
case v of
Nothing -> liftIO $ parseRequestBody (tempFileBackEnd' st)
(fst req)
Just (q,_) -> return q
return $ queryFormEnv (map (second Just) query ++ queryString (fst req)) files
runForm :: RequestContext ctxt =>
ctxt
-> Text
-> Form v IO a
-> ((View v, Maybe a) -> IO a1)
-> IO a1
runForm ctxt nm frm k =
runResourceT $ let r = fst (getRequest ctxt) in
if requestMethod r == methodPost
then do env <- requestFormEnv (getRequest ctxt)
r' <- liftIO $ postForm nm frm (const (return env))
liftIO $ k r'
else do r' <- (,Nothing) <$> liftIO (getForm nm frm)
liftIO $ k r'