More sophisticated subsite support

This commit is contained in:
Michael Snoyman 2010-06-06 21:50:27 +03:00
parent 31fffcf5d4
commit 7262c30c74
6 changed files with 35 additions and 29 deletions

View File

@ -33,9 +33,5 @@ import Yesod.Handler hiding (runHandler)
import Network.Wai (Application) import Network.Wai (Application)
import Yesod.Hamlet import Yesod.Hamlet
import Data.Convertible.Text (cs) import Data.Convertible.Text (cs)
#if MIN_VERSION_transformers(0,2,0)
import "transformers" Control.Monad.IO.Class (liftIO) import "transformers" Control.Monad.IO.Class (liftIO)
#else
import "transformers" Control.Monad.Trans (liftIO)
#endif
import Web.Routes.Quasi (Routes) import Web.Routes.Quasi (Routes)

View File

@ -31,6 +31,7 @@ import Yesod.Internal
import Web.Routes.Quasi import Web.Routes.Quasi
import Language.Haskell.TH.Syntax import Language.Haskell.TH.Syntax
import Data.List (nub)
import qualified Network.Wai as W import qualified Network.Wai as W
import qualified Network.Wai.Enumerator as W import qualified Network.Wai.Enumerator as W
@ -46,7 +47,7 @@ import qualified Data.ByteString.Char8 as B
import Web.Routes (encodePathInfo) import Web.Routes (encodePathInfo)
import Control.Concurrent.MVar import Control.Concurrent.MVar
import Control.Arrow ((***)) import Control.Arrow ((***), first)
import Data.Convertible.Text (cs) import Data.Convertible.Text (cs)
import Data.Time import Data.Time
@ -76,7 +77,7 @@ import Yesod.Content
mkYesod :: String -- ^ name of the argument datatype mkYesod :: String -- ^ name of the argument datatype
-> [Resource] -> [Resource]
-> Q [Dec] -> Q [Dec]
mkYesod name = fmap (\(x, y) -> x ++ y) . mkYesodGeneral name [] False mkYesod name = fmap (\(x, y) -> x ++ y) . mkYesodGeneral name [] [] False
-- | Generates URL datatype and site function for the given 'Resource's. This -- | Generates URL datatype and site function for the given 'Resource's. This
-- is used for creating subsites, *not* sites. See 'mkYesod' for the latter. -- is used for creating subsites, *not* sites. See 'mkYesod' for the latter.
@ -84,11 +85,13 @@ mkYesod name = fmap (\(x, y) -> x ++ y) . mkYesodGeneral name [] False
-- executable by itself, but instead provides functionality to -- executable by itself, but instead provides functionality to
-- be embedded in other sites. -- be embedded in other sites.
mkYesodSub :: String -- ^ name of the argument datatype mkYesodSub :: String -- ^ name of the argument datatype
-> [Name] -- ^ a list of classes the master datatype must be an instance of -> [(String, [Name])]
-> [Resource] -> [Resource]
-> Q [Dec] -> Q [Dec]
mkYesodSub name clazzes = mkYesodSub name clazzes =
fmap (\(x, y) -> x ++ y) . mkYesodGeneral name clazzes True fmap (\(x, y) -> x ++ y) . mkYesodGeneral name' rest clazzes True
where
(name':rest) = words name
-- | Sometimes, you will want to declare your routes in one file and define -- | Sometimes, you will want to declare your routes in one file and define
-- your handlers elsewhere. For example, this is the only way to break up a -- your handlers elsewhere. For example, this is the only way to break up a
@ -96,7 +99,7 @@ mkYesodSub name clazzes =
-- 'mkYesodDispatch', do just that. -- 'mkYesodDispatch', do just that.
mkYesodData :: String -> [Resource] -> Q [Dec] mkYesodData :: String -> [Resource] -> Q [Dec]
mkYesodData name res = do mkYesodData name res = do
(x, _) <- mkYesodGeneral name [] False res (x, _) <- mkYesodGeneral name [] [] False res
let rname = mkName $ "resources" ++ name let rname = mkName $ "resources" ++ name
eres <- liftResources res eres <- liftResources res
let y = [ SigD rname $ ListT `AppT` ConT ''Resource let y = [ SigD rname $ ListT `AppT` ConT ''Resource
@ -106,7 +109,7 @@ mkYesodData name res = do
-- | See 'mkYesodData'. -- | See 'mkYesodData'.
mkYesodDispatch :: String -> [Resource] -> Q [Dec] mkYesodDispatch :: String -> [Resource] -> Q [Dec]
mkYesodDispatch name = fmap snd . mkYesodGeneral name [] False mkYesodDispatch name = fmap snd . mkYesodGeneral name [] [] False
explodeHandler :: HasReps c explodeHandler :: HasReps c
=> GHandler sub master c => GHandler sub master c
@ -120,25 +123,44 @@ explodeHandler :: HasReps c
-> YesodApp -> YesodApp
explodeHandler a b c d e f _ _ = runHandler a b (Just c) d e f explodeHandler a b c d e f _ _ = runHandler a b (Just c) d e f
mkYesodGeneral :: String -> [Name] -> Bool -> [Resource] -> Q ([Dec], [Dec]) mkYesodGeneral :: String -- ^ argument name
mkYesodGeneral name clazzes isSub res = do -> [String] -- ^ parameters for site argument
-> [(String, [Name])] -- ^ classes
-> Bool -- ^ is subsite?
-> [Resource]
-> Q ([Dec], [Dec])
mkYesodGeneral name args clazzes isSub res = do
let name' = mkName name let name' = mkName name
args' = map mkName args
arg = foldl AppT (ConT $ name') $ map VarT args'
let site = mkName $ "site" ++ name let site = mkName $ "site" ++ name
let gsbod = NormalB $ VarE site let gsbod = NormalB $ VarE site
let yes' = FunD (mkName "getSite") [Clause [] gsbod []] let yes' = FunD (mkName "getSite") [Clause [] gsbod []]
let yes = InstanceD [] (ConT ''YesodSite `AppT` ConT name') [yes'] let yes = InstanceD [] (ConT ''YesodSite `AppT` ConT name') [yes']
let clazzes' = compact
$ map (\x -> (x, [])) ("master" : args) ++
clazzes
explode <- [|explodeHandler|] explode <- [|explodeHandler|]
QuasiSiteDecs w x y z <- createQuasiSite QuasiSiteSettings QuasiSiteDecs w x y z <- createQuasiSite QuasiSiteSettings
{ crRoutes = mkName $ name ++ "Routes" { crRoutes = mkName $ name ++ "Routes"
, crApplication = ConT ''YesodApp , crApplication = ConT ''YesodApp
, crArgument = ConT $ mkName name , crArgument = arg
, crExplode = explode , crExplode = explode
, crResources = res , crResources = res
, crSite = site , crSite = site
, crMaster = if isSub then Right clazzes else Left (ConT name') , crMaster = if isSub
then Right clazzes'
else Left (ConT name')
} }
return ([w, x], (if isSub then id else (:) yes) [y, z]) return ([w, x], (if isSub then id else (:) yes) [y, z])
compact :: [(String, [a])] -> [(String, [a])]
compact [] = []
compact ((x, x'):rest) =
let ys = filter (\(y, _) -> y == x) rest
zs = filter (\(z, _) -> z /= x) rest
in (x, x' ++ concatMap snd ys) : compact zs
sessionName :: String sessionName :: String
sessionName = "_SESSION" sessionName = "_SESSION"

View File

@ -26,11 +26,7 @@ import Control.Applicative hiding (optional)
import Data.Time (Day) import Data.Time (Day)
import Data.Convertible.Text import Data.Convertible.Text
import Data.Maybe (fromMaybe) import Data.Maybe (fromMaybe)
#if MIN_VERSION_transformers(0,2,0)
import "transformers" Control.Monad.IO.Class import "transformers" Control.Monad.IO.Class
#else
import "transformers" Control.Monad.Trans
#endif
import Yesod.Internal import Yesod.Internal
import Control.Monad.Attempt import Control.Monad.Attempt

View File

@ -76,13 +76,9 @@ import Control.Exception hiding (Handler, catch)
import qualified Control.Exception as E import qualified Control.Exception as E
import Control.Applicative import Control.Applicative
#if MIN_VERSION_transformers(0,2,0)
import "transformers" Control.Monad.IO.Class import "transformers" Control.Monad.IO.Class
#else import qualified "MonadCatchIO-transformers" Control.Monad.CatchIO as C
import "transformers" Control.Monad.Trans import "MonadCatchIO-transformers" Control.Monad.CatchIO (catch)
#endif
import qualified Control.Monad.CatchIO as C
import Control.Monad.CatchIO (catch)
import Control.Monad (liftM, ap) import Control.Monad (liftM, ap)
import System.IO import System.IO

View File

@ -42,11 +42,7 @@ module Yesod.Request
import qualified Network.Wai as W import qualified Network.Wai as W
import qualified Data.ByteString.Lazy as BL import qualified Data.ByteString.Lazy as BL
#if MIN_VERSION_transformers(0,2,0)
import "transformers" Control.Monad.IO.Class import "transformers" Control.Monad.IO.Class
#else
import "transformers" Control.Monad.Trans
#endif
import Control.Monad (liftM) import Control.Monad (liftM)
import Network.Wai.Parse import Network.Wai.Parse
import Control.Monad.Instances () -- I'm missing the instance Monad ((->) r import Control.Monad.Instances () -- I'm missing the instance Monad ((->) r

View File

@ -41,7 +41,7 @@ library
convertible-text >= 0.3.0 && < 0.4, convertible-text >= 0.3.0 && < 0.4,
template-haskell >= 2.4 && < 2.5, template-haskell >= 2.4 && < 2.5,
web-routes >= 0.22 && < 0.23, web-routes >= 0.22 && < 0.23,
web-routes-quasi >= 0.3 && < 0.4, web-routes-quasi >= 0.4 && < 0.5,
hamlet >= 0.3.0 && < 0.4, hamlet >= 0.3.0 && < 0.4,
transformers >= 0.1 && < 0.3, transformers >= 0.1 && < 0.3,
clientsession >= 0.4.0 && < 0.5, clientsession >= 0.4.0 && < 0.5,