Packages
phoenix_kit
1.7.168
1.7.208
1.7.207
1.7.206
1.7.205
1.7.204
1.7.203
1.7.202
1.7.201
1.7.200
1.7.199
1.7.198
1.7.197
1.7.196
1.7.194
1.7.193
1.7.192
1.7.191
1.7.190
1.7.189
1.7.187
1.7.186
1.7.185
1.7.184
1.7.183
1.7.182
1.7.181
1.7.180
1.7.179
1.7.178
1.7.177
1.7.176
1.7.175
1.7.174
1.7.173
1.7.172
1.7.171
1.7.170
1.7.169
1.7.168
1.7.167
1.7.166
1.7.165
1.7.164
1.7.162
1.7.161
1.7.160
1.7.159
1.7.157
1.7.156
1.7.155
1.7.154
1.7.153
1.7.152
1.7.151
1.7.150
1.7.149
1.7.146
1.7.145
1.7.144
1.7.143
1.7.138
1.7.133
1.7.132
1.7.131
1.7.130
1.7.128
1.7.126
1.7.125
1.7.121
1.7.120
1.7.119
1.7.118
1.7.117
1.7.116
1.7.115
1.7.114
1.7.113
1.7.112
1.7.111
1.7.110
1.7.109
1.7.108
1.7.107
1.7.106
1.7.105
1.7.104
1.7.103
1.7.102
1.7.101
1.7.100
1.7.99
1.7.98
1.7.97
1.7.96
1.7.95
1.7.94
1.7.93
1.7.92
1.7.91
1.7.90
1.7.89
1.7.88
1.7.87
1.7.86
1.7.85
1.7.84
1.7.83
1.7.82
1.7.81
1.7.80
1.7.79
1.7.78
1.7.77
1.7.76
1.7.75
1.7.74
1.7.71
1.7.70
1.7.69
1.7.66
1.7.65
1.7.64
1.7.63
1.7.62
1.7.61
1.7.59
1.7.58
1.7.57
1.7.56
1.7.55
1.7.54
1.7.53
1.7.52
1.7.51
1.7.49
1.7.44
1.7.43
1.7.42
1.7.41
1.7.39
1.7.38
1.7.37
1.7.36
1.7.34
1.7.33
1.7.31
1.7.30
1.7.29
1.7.28
1.7.27
1.7.26
1.7.25
1.7.24
1.7.23
1.7.22
1.7.21
1.7.20
1.7.19
1.7.18
1.7.17
1.7.16
1.7.15
1.7.14
1.7.13
1.7.12
1.7.11
1.7.10
1.7.9
1.7.8
1.7.7
1.7.6
1.7.5
1.7.4
1.7.3
1.7.2
1.7.1
1.7.0
1.6.20
1.6.19
1.6.18
1.6.17
1.6.16
1.6.15
1.6.14
1.6.13
1.6.12
1.6.11
1.6.10
1.6.9
1.6.8
1.6.7
1.6.6
1.6.5
1.6.4
1.6.3
1.5.2
1.5.1
1.5.0
1.4.9
1.4.8
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.2
1.3.1
1.3.0
1.2.10
1.2.9
1.2.8
1.2.7
1.2.5
1.2.4
1.2.2
1.2.1
1.2.0
1.1.0
1.0.0
A foundation for building Elixir Phoenix apps — SaaS, social networks, ERP systems, marketplaces, and more
Current section
Files
Jump to
Current section
Files
lib/phoenix_kit/layout_config.ex
defmodule PhoenixKit.LayoutConfig do
@moduledoc """
Configuration manager for PhoenixKit layout integration.
This module provides functions to retrieve and validate layout configuration
from the application environment, with fallback to default PhoenixKit layouts.
## Configuration
Configure layouts in your application config:
# Minimal configuration - only app layout
config :phoenix_kit, layout: {MyAppWeb.Layouts, :app}
# Full configuration - both root and app layouts
config :phoenix_kit,
root_layout: {MyAppWeb.Layouts, :root},
layout: {MyAppWeb.Layouts, :app}
# With additional options
config :phoenix_kit,
layout: {MyAppWeb.Layouts, :app},
page_title_prefix: "Auth"
## Usage
iex> PhoenixKit.LayoutConfig.get_layout()
{PhoenixKitWeb.Layouts, :app}
iex> PhoenixKit.LayoutConfig.get_root_layout()
{PhoenixKitWeb.Layouts, :root}
"""
alias PhoenixKit.Config
require Logger
@default_layout {PhoenixKitWeb.Layouts, :app}
@default_root_layout {PhoenixKitWeb.Layouts, :root}
@doc """
Gets the configured app layout module and template.
Returns the configured layout tuple or falls back to default PhoenixKit layout.
## Examples
iex> Application.put_env(:phoenix_kit, :layout, {MyApp.Layouts, :app})
iex> PhoenixKit.LayoutConfig.get_layout()
{MyApp.Layouts, :app}
iex> Application.delete_env(:phoenix_kit, :layout)
iex> PhoenixKit.LayoutConfig.get_layout()
{PhoenixKitWeb.Layouts, :app}
"""
@spec get_layout() :: {module(), atom()}
def get_layout do
case Config.get(:layout, nil) do
{module, template} when is_atom(module) and is_atom(template) ->
validate_layout_module(module, template, @default_layout)
_ ->
@default_layout
end
end
@doc """
Gets the configured root layout module and template.
Returns the configured root layout tuple or falls back to default PhoenixKit root layout.
Root layout is optional and defaults to app layout if not specified.
## Examples
iex> Application.put_env(:phoenix_kit, :root_layout, {MyApp.Layouts, :root})
iex> PhoenixKit.LayoutConfig.get_root_layout()
{MyApp.Layouts, :root}
iex> Application.delete_env(:phoenix_kit, :root_layout)
iex> PhoenixKit.LayoutConfig.get_root_layout()
{PhoenixKitWeb.Layouts, :root}
"""
@spec get_root_layout() :: {module(), atom()}
def get_root_layout do
case PhoenixKit.Config.get(:root_layout, nil) do
{module, template} when is_atom(module) and is_atom(template) ->
validate_layout_module(module, template, @default_root_layout)
_ ->
# Fallback: try to use app layout's root layout, or default root layout
case get_layout() do
{layout_module, _} ->
# Try to use the same module as app layout but with :root template
validate_layout_module(layout_module, :root, @default_root_layout)
end
end
end
@doc """
Gets the configured page title prefix for authentication pages.
## Examples
iex> Application.put_env(:phoenix_kit, :page_title_prefix, "Auth")
iex> PhoenixKit.LayoutConfig.get_page_title_prefix()
"Auth"
iex> Application.delete_env(:phoenix_kit, :page_title_prefix)
iex> PhoenixKit.LayoutConfig.get_page_title_prefix()
nil
"""
@spec get_page_title_prefix() :: String.t() | nil
def get_page_title_prefix do
case PhoenixKit.Config.get(:page_title_prefix) do
{:ok, prefix} when is_binary(prefix) -> prefix
_ -> nil
end
end
@doc """
Checks if a custom layout is configured (not using default PhoenixKit layouts).
## Examples
iex> Application.put_env(:phoenix_kit, :layout, {MyApp.Layouts, :app})
iex> PhoenixKit.LayoutConfig.custom_layout?()
true
iex> Application.delete_env(:phoenix_kit, :layout)
iex> PhoenixKit.LayoutConfig.custom_layout?()
false
"""
@spec custom_layout?() :: boolean()
def custom_layout? do
get_layout() != @default_layout
end
@doc """
Gets all layout configuration as a map for debugging purposes.
## Examples
iex> PhoenixKit.LayoutConfig.get_config()
%{
layout: {PhoenixKitWeb.Layouts, :app},
root_layout: {PhoenixKitWeb.Layouts, :root},
page_title_prefix: nil,
custom_layout?: false
}
"""
@spec get_config() :: map()
def get_config do
%{
layout: get_layout(),
root_layout: get_root_layout(),
page_title_prefix: get_page_title_prefix(),
custom_layout?: custom_layout?()
}
end
# Private functions
# Helper to log warnings for missing layout modules
defp log_missing_module_warning(module, fallback) do
module_string = to_string(module)
# Skip logging for auto-generated test module names to reduce noise
is_auto_generated_test =
String.contains?(module_string, "Test") and
PhoenixKit.Config.get(:layout, nil) == nil
unless is_auto_generated_test do
Logger.warning(
"[PhoenixKit] Layout module #{inspect(module)} not found at runtime, using fallback #{inspect(fallback)}"
)
end
end
@spec should_validate_runtime_module?(module()) :: boolean()
defp should_validate_runtime_module?(module) do
# During active application runtime, validate module exists
Process.whereis(:application_controller) != nil and
Application.get_application(module) != nil
end
@spec validate_runtime_module(module(), atom(), {module(), atom()}) :: {module(), atom()}
defp validate_runtime_module(module, template, fallback) do
if Code.ensure_loaded?(module) do
{module, template}
else
log_missing_module_warning(module, fallback)
fallback
end
end
@spec validate_layout_module(module(), atom(), {module(), atom()}) :: {module(), atom()}
defp validate_layout_module(module, template, fallback) do
# For PhoenixKitWeb.Layouts, always allow (it's our own module)
if module == PhoenixKitWeb.Layouts do
{module, template}
else
# For external modules, trust that they will be available at runtime
# Skip validation during compilation phase - just return the module
if should_validate_runtime_module?(module) do
validate_runtime_module(module, template, fallback)
else
# During compilation or when module's app is not loaded, trust configuration
{module, template}
end
end
end
end