Skip to content

Commit

Permalink
Added logger field to ControllerContext and added mapContext
Browse files Browse the repository at this point in the history
  • Loading branch information
mpscholten committed Feb 27, 2024
1 parent 4c85cf9 commit f89a7f5
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 11 deletions.
17 changes: 8 additions & 9 deletions IHP/Controller/Context.hs
Original file line number Diff line number Diff line change
Expand Up @@ -47,28 +47,30 @@ import IHP.Log.Types
-- - @action ..@: The action itself.
-- - Freezing: Before rendering the response, the container is frozen. Frozen means that all previously mutable fields become immutable.
-- - View Rendering: The frozen container is now used inside the view and layout to display information such as the current user or flash messages
data ControllerContext = ControllerContext { requestContext :: RequestContext, customFieldsRef :: IORef TypeMap.TMap }
| FrozenControllerContext { requestContext :: RequestContext, customFields :: TypeMap.TMap }
data ControllerContext = ControllerContext { requestContext :: RequestContext, customFieldsRef :: IORef TypeMap.TMap, logger :: Logger }
| FrozenControllerContext { requestContext :: RequestContext, customFields :: TypeMap.TMap, logger :: Logger }

newControllerContext :: (?requestContext :: RequestContext) => IO ControllerContext
newControllerContext = do
customFieldsRef <- newIORef TypeMap.empty
pure ControllerContext { requestContext = ?requestContext, customFieldsRef }
pure ControllerContext { requestContext = ?requestContext, customFieldsRef, logger = ?requestContext.frameworkConfig.logger }
{-# INLINABLE newControllerContext #-}

-- | After freezing a container you can access its values from pure non-IO code by using 'fromFronzenContext'
--
-- Calls to 'putContext' will throw an exception after it's frozen.
freeze :: ControllerContext -> IO ControllerContext
freeze ControllerContext { requestContext, customFieldsRef } = FrozenControllerContext requestContext <$> readIORef customFieldsRef
freeze ControllerContext { requestContext, customFieldsRef, logger } = do
customFields <- readIORef customFieldsRef
pure FrozenControllerContext { requestContext, customFields, logger }
freeze frozen = pure frozen
{-# INLINABLE freeze #-}

-- | Returns a unfrozen version of the controller context that can be modified again
--
-- This is used together with 'freeze' by e.g. AutoRefresh to make a immutable copy of the current controller context state
unfreeze :: ControllerContext -> IO ControllerContext
unfreeze FrozenControllerContext { requestContext, customFields } = do
unfreeze FrozenControllerContext { requestContext, customFields, logger } = do
customFieldsRef <- newIORef customFields
pure ControllerContext { .. }
unfreeze ControllerContext {} = error "Cannot call unfreeze on a controller context that is not frozen"
Expand Down Expand Up @@ -135,7 +137,4 @@ newtype ActionType = ActionType Typeable.TypeRep

instance HasField "frameworkConfig" ControllerContext FrameworkConfig where
getField controllerContext = controllerContext.requestContext.frameworkConfig
{-# INLINABLE getField #-}

instance HasField "logger" ControllerContext Logger where
getField controllerContext = controllerContext.frameworkConfig.logger
{-# INLINABLE getField #-}
6 changes: 5 additions & 1 deletion IHP/ControllerSupport.hs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ class InitControllerContext application where
initContext = pure ()
{-# INLINABLE initContext #-}

mapContext :: (?modelContext :: ModelContext, ?requestContext :: RequestContext, ?applicationContext :: ApplicationContext, ?context :: ControllerContext) => ControllerContext -> ControllerContext
mapContext context = context
{-# INLINABLE mapContext #-}

{-# INLINE runAction #-}
runAction :: forall controller. (Controller controller, ?context :: ControllerContext, ?modelContext :: ModelContext, ?applicationContext :: ApplicationContext, ?requestContext :: RequestContext) => controller -> IO ResponseReceived
runAction controller = do
Expand Down Expand Up @@ -123,7 +127,7 @@ newContextForAction contextSetter controller = do
let respond = ?context.requestContext.respond
in respond response
Nothing -> ErrorController.displayException exception controller " while calling initContext"
Right _ -> pure $ Right ?context
Right _ -> pure $ Right (mapContext @application ?context)

{-# INLINE runActionWithNewContext #-}
runActionWithNewContext :: forall application controller. (Controller controller, ?applicationContext :: ApplicationContext, ?context :: RequestContext, InitControllerContext application, ?application :: application, Typeable application, Typeable controller) => controller -> IO ResponseReceived
Expand Down
2 changes: 1 addition & 1 deletion IHP/RouterSupport.hs
Original file line number Diff line number Diff line change
Expand Up @@ -955,7 +955,7 @@ routeParam :: (?context::RequestContext, ParamReader paramType) => ByteString ->
routeParam paramName =
let requestContext = ?context
in
let ?context = FrozenControllerContext { requestContext = requestContext, customFields = mempty }
let ?context = FrozenControllerContext { requestContext = requestContext, customFields = mempty, logger = requestContext.frameworkConfig.logger }
in param paramName

-- | Display a better error when the user missed to pass an argument to an action.
Expand Down

0 comments on commit f89a7f5

Please sign in to comment.