Switch to Map

This commit is contained in:
Michael Snoyman 2011-08-03 08:12:36 +03:00
parent f62f513c63
commit 1cd722fe40
5 changed files with 34 additions and 21 deletions

View File

@ -44,9 +44,10 @@ import Yesod.Request (reqNonce, reqWaiRequest, reqGetParams, languages)
import Network.Wai (requestMethod) import Network.Wai (requestMethod)
import Text.Hamlet (html) import Text.Hamlet (html)
import Data.Monoid (mempty) import Data.Monoid (mempty)
import Data.Maybe (listToMaybe) import Data.Maybe (listToMaybe, fromMaybe)
import Yesod.Message (RenderMessage (..)) import Yesod.Message (RenderMessage (..))
import Control.Monad.IO.Class (MonadIO, liftIO) import Control.Monad.IO.Class (MonadIO, liftIO)
import qualified Data.Map as Map
#if __GLASGOW_HASKELL__ >= 700 #if __GLASGOW_HASKELL__ >= 700
#define WHAMLET whamlet #define WHAMLET whamlet
@ -120,7 +121,7 @@ mhelper Field {..} FieldSettings {..} mdef onMissing onFound isReq = do
case mp of case mp of
Nothing -> return (FormMissing, maybe (Left "") Right mdef) Nothing -> return (FormMissing, maybe (Left "") Right mdef)
Just p -> do Just p -> do
let mvals = map snd $ filter (\(n,_) -> n == name) p let mvals = fromMaybe [] $ Map.lookup name p
emx <- lift $ fieldParse mvals emx <- lift $ fieldParse mvals
return $ case emx of return $ case emx of
Left (SomeMessage e) -> (FormFailure [renderMessage master langs e], maybe (Left "") Left (listToMaybe mvals)) Left (SomeMessage e) -> (FormFailure [renderMessage master langs e], maybe (Left "") Left (listToMaybe mvals))
@ -174,28 +175,32 @@ runFormPost form = do
case reqNonce req of case reqNonce req of
Nothing -> mempty Nothing -> mempty
Just n -> [HTML|<input type=hidden name=#{nonceKey} value=#{n}>|] Just n -> [HTML|<input type=hidden name=#{nonceKey} value=#{n}>|]
env <- if requestMethod (reqWaiRequest req) == "GET" env <- postEnv
then return Nothing
else fmap Just runRequestBody
m <- getYesod m <- getYesod
langs <- languages langs <- languages
((res, xml), enctype) <- runFormGeneric (form nonce) m langs env ((res, xml), enctype) <- runFormGeneric (form nonce) m langs env
let res' = let res' =
case (res, env) of case (res, env) of
(FormSuccess{}, Just (params, _)) (FormSuccess{}, Just (params, _))
| lookup nonceKey params /= reqNonce req -> | Map.lookup nonceKey params /= fmap return (reqNonce req) ->
FormFailure [renderMessage m langs MsgCsrfWarning] FormFailure [renderMessage m langs MsgCsrfWarning]
_ -> res _ -> res
return ((res', xml), enctype) return ((res', xml), enctype)
postEnv = do
req <- getRequest
if requestMethod (reqWaiRequest req) == "GET"
then return Nothing
else do
(p, f) <- runRequestBody
let p' = Map.unionsWith (++) $ map (\(x, y) -> Map.singleton x [y]) p
return $ Just (p', Map.fromList f)
runFormPostNoNonce :: (Html -> Form sub master (FormResult a, xml)) -> GHandler sub master ((FormResult a, xml), Enctype) runFormPostNoNonce :: (Html -> Form sub master (FormResult a, xml)) -> GHandler sub master ((FormResult a, xml), Enctype)
runFormPostNoNonce form = do runFormPostNoNonce form = do
req <- getRequest
env <- if requestMethod (reqWaiRequest req) == "GET"
then return Nothing
else fmap Just runRequestBody
langs <- languages langs <- languages
m <- getYesod m <- getYesod
env <- postEnv
runFormGeneric (form mempty) m langs env runFormGeneric (form mempty) m langs env
runFormGet :: (Html -> Form sub master a) -> GHandler sub master (a, Enctype) runFormGet :: (Html -> Form sub master a) -> GHandler sub master (a, Enctype)
@ -206,7 +211,7 @@ runFormGet form = do
let env = let env =
case lookup key gets of case lookup key gets of
Nothing -> Nothing Nothing -> Nothing
Just _ -> Just (gets, []) Just _ -> Just (Map.unionsWith (++) $ map (\(x, y) -> Map.singleton x [y]) gets, Map.empty)
langs <- languages langs <- languages
m <- getYesod m <- getYesod
runFormGeneric (form fragment) m langs env runFormGeneric (form fragment) m langs env

View File

@ -17,6 +17,8 @@ import Yesod.Request (reqGetParams, languages)
import Control.Monad (liftM) import Control.Monad (liftM)
import Yesod.Widget (GWidget) import Yesod.Widget (GWidget)
import Yesod.Message (RenderMessage (..)) import Yesod.Message (RenderMessage (..))
import qualified Data.Map as Map
import Data.Maybe (fromMaybe)
type DText = [Text] -> [Text] type DText = [Text] -> [Text]
newtype FormInput sub master a = FormInput { unFormInput :: master -> [Text] -> Env -> GGHandler sub master IO (Either DText a) } newtype FormInput sub master a = FormInput { unFormInput :: master -> [Text] -> Env -> GGHandler sub master IO (Either DText a) }
@ -35,7 +37,7 @@ instance Applicative (FormInput sub master) where
ireq :: (RenderMessage master msg, RenderMessage master FormMessage) => Field sub master a -> Text -> FormInput sub master a ireq :: (RenderMessage master msg, RenderMessage master FormMessage) => Field sub master a -> Text -> FormInput sub master a
ireq field name = FormInput $ \m l env -> do ireq field name = FormInput $ \m l env -> do
let filteredEnv = map snd $ filter (\y -> fst y == name) env let filteredEnv = fromMaybe [] $ Map.lookup name env
emx <- fieldParse field $ filteredEnv emx <- fieldParse field $ filteredEnv
return $ case emx of return $ case emx of
Left (SomeMessage e) -> Left $ (:) $ renderMessage m l e Left (SomeMessage e) -> Left $ (:) $ renderMessage m l e
@ -44,7 +46,7 @@ ireq field name = FormInput $ \m l env -> do
iopt :: RenderMessage master msg => Field sub master a -> Text -> FormInput sub master (Maybe a) iopt :: RenderMessage master msg => Field sub master a -> Text -> FormInput sub master (Maybe a)
iopt field name = FormInput $ \m l env -> do iopt field name = FormInput $ \m l env -> do
let filteredEnv = map snd $ filter (\y -> fst y == name) env let filteredEnv = fromMaybe [] $ Map.lookup name env
emx <- fieldParse field $ filteredEnv emx <- fieldParse field $ filteredEnv
return $ case emx of return $ case emx of
Left (SomeMessage e) -> Left $ (:) $ renderMessage m l e Left (SomeMessage e) -> Left $ (:) $ renderMessage m l e
@ -52,7 +54,7 @@ iopt field name = FormInput $ \m l env -> do
runInputGet :: FormInput sub master a -> GHandler sub master a runInputGet :: FormInput sub master a -> GHandler sub master a
runInputGet (FormInput f) = do runInputGet (FormInput f) = do
env <- liftM reqGetParams getRequest env <- liftM (toMap . reqGetParams) getRequest
m <- getYesod m <- getYesod
l <- languages l <- languages
emx <- liftIOHandler $ f m l env emx <- liftIOHandler $ f m l env
@ -60,9 +62,11 @@ runInputGet (FormInput f) = do
Left errs -> invalidArgs $ errs [] Left errs -> invalidArgs $ errs []
Right x -> return x Right x -> return x
toMap = Map.unionsWith (++) . map (\(x, y) -> Map.singleton x [y])
runInputPost :: FormInput sub master a -> GHandler sub master a runInputPost :: FormInput sub master a -> GHandler sub master a
runInputPost (FormInput f) = do runInputPost (FormInput f) = do
env <- liftM fst runRequestBody env <- liftM (toMap . fst) runRequestBody
m <- getYesod m <- getYesod
l <- languages l <- languages
emx <- liftIOHandler $ f m l env emx <- liftIOHandler $ f m l env

View File

@ -25,6 +25,8 @@ import Control.Monad (liftM)
import Data.Either (partitionEithers) import Data.Either (partitionEithers)
import Data.Traversable (sequenceA) import Data.Traversable (sequenceA)
import Control.Monad.IO.Class (MonadIO) import Control.Monad.IO.Class (MonadIO)
import qualified Data.Map as Map
import Data.Maybe (listToMaybe)
#if __GLASGOW_HASKELL__ >= 700 #if __GLASGOW_HASKELL__ >= 700
#define WHAMLET whamlet #define WHAMLET whamlet
@ -69,8 +71,8 @@ inputList label fixXml single mdef = formToAForm $ do
case menv of case menv of
Nothing -> map Just $ fromMaybe [] mdef Nothing -> map Just $ fromMaybe [] mdef
Just (env, _) -> Just (env, _) ->
let toAdd = maybe False (const True) $ lookup addName env let toAdd = maybe False (const True) $ Map.lookup addName env
count' = fromMaybe 0 $ lookup countName env >>= readInt count' = fromMaybe 0 $ Map.lookup countName env >>= listToMaybe >>= readInt
count = (if toAdd then 1 else 0) + count' count = (if toAdd then 1 else 0) + count'
in replicate count Nothing in replicate count Nothing
let count = length vals let count = length vals
@ -100,8 +102,8 @@ withDelete af = do
down 1 down 1
deleteName <- newFormIdent deleteName <- newFormIdent
(menv, _, _) <- ask (menv, _, _) <- ask
res <- case menv >>= lookup deleteName . fst of res <- case menv >>= Map.lookup deleteName . fst of
Just "yes" -> return $ Left [WHAMLET|<input type=hidden name=#{deleteName} value=yes>|] Just ("yes":_) -> return $ Left [WHAMLET|<input type=hidden name=#{deleteName} value=yes>|]
_ -> do _ -> do
(_, xml2) <- aFormToForm $ areq boolField FieldSettings (_, xml2) <- aFormToForm $ areq boolField FieldSettings
{ fsLabel = "Delete?" :: Text -- FIXME { fsLabel = "Delete?" :: Text -- FIXME

View File

@ -27,6 +27,7 @@ import Control.Applicative ((<$>), Applicative (..))
import Control.Monad (liftM) import Control.Monad (liftM)
import Data.String (IsString (..)) import Data.String (IsString (..))
import Yesod.Core (RenderMessage, GGHandler, GWidget) import Yesod.Core (RenderMessage, GGHandler, GWidget)
import qualified Data.Map as Map
-- | A form can produce three different results: there was no data available, -- | A form can produce three different results: there was no data available,
-- the data was invalid, or there was a successful parse. -- the data was invalid, or there was a successful parse.
@ -69,8 +70,8 @@ instance Show Ints where
show (IntSingle i) = show i show (IntSingle i) = show i
show (IntCons i is) = show i ++ ('-' : show is) show (IntCons i is) = show i ++ ('-' : show is)
type Env = [(Text, Text)] -- FIXME use a Map type Env = Map.Map Text [Text]
type FileEnv = [(Text, FileInfo)] type FileEnv = Map.Map Text FileInfo
type Lang = Text type Lang = Text
type Form sub master a = RWST (Maybe (Env, FileEnv), master, [Lang]) Enctype Ints (GGHandler sub master IO) a type Form sub master a = RWST (Maybe (Env, FileEnv), master, [Lang]) Enctype Ints (GGHandler sub master IO) a

View File

@ -30,6 +30,7 @@ library
, text >= 0.7 && < 1.0 , text >= 0.7 && < 1.0
, web-routes-quasi >= 0.7 && < 0.8 , web-routes-quasi >= 0.7 && < 0.8
, wai >= 0.4 && < 0.5 , wai >= 0.4 && < 0.5
, containers >= 0.2 && < 0.5
exposed-modules: Yesod.Form exposed-modules: Yesod.Form
Yesod.Form.Class Yesod.Form.Class
Yesod.Form.Types Yesod.Form.Types