1468 lines
39 KiB
Plaintext
1468 lines
39 KiB
Plaintext
note
|
|
description: "API for a CMS"
|
|
date: "$Date$"
|
|
revision: "$Revision$"
|
|
|
|
class
|
|
CMS_API
|
|
|
|
inherit
|
|
CMS_HOOK_EXPORT
|
|
CMS_API_EXPORT_IMP
|
|
|
|
CMS_HOOK_IMPORT
|
|
CMS_API_IMPORT_IMP
|
|
|
|
CMS_ENCODERS
|
|
|
|
CMS_URL_UTILITIES
|
|
|
|
REFACTORING_HELPER
|
|
|
|
create
|
|
make
|
|
|
|
feature {NONE} -- Initialize
|
|
|
|
make (a_setup: CMS_SETUP; req: WSF_REQUEST)
|
|
-- Create the API service with a setup `a_setup'
|
|
-- and request `req'.
|
|
do
|
|
request := req
|
|
setup := a_setup
|
|
create error_handler.make
|
|
create {CMS_ENV_LOGGER} logger.make
|
|
create hooks.make
|
|
initialize
|
|
ensure
|
|
setup_set: setup = a_setup
|
|
error_handler_set: not error_handler.has_error
|
|
end
|
|
|
|
initialize
|
|
-- Initialize the persitent layer.
|
|
local
|
|
l_module: CMS_MODULE
|
|
l_enabled_modules: CMS_MODULE_COLLECTION
|
|
l_uninstalled_mods: detachable ARRAYED_LIST [CMS_MODULE]
|
|
s: IMMUTABLE_STRING_8
|
|
do
|
|
-- Initialize site_url
|
|
initialize_site_url
|
|
|
|
-- Administration backend
|
|
s := setup.administration_base_path
|
|
administration_base_path_location := s.shared_substring (2, s.count)
|
|
|
|
-- Initialize contents.
|
|
initialize_content_types
|
|
|
|
-- Initialize filters and formats.
|
|
initialize_content_filters_and_formats
|
|
|
|
-- Initialize storage.
|
|
if attached setup.storage (error_handler) as l_storage then
|
|
storage := l_storage
|
|
else
|
|
create {CMS_STORAGE_NULL} storage
|
|
end
|
|
|
|
-- Keep enable modules list.
|
|
create l_enabled_modules.make (setup.modules.count)
|
|
enabled_modules := l_enabled_modules
|
|
setup.fill_enabled_modules (Current)
|
|
|
|
-- Complete storage setup.
|
|
storage.set_api (Current)
|
|
|
|
-- Initialize enabled modules.
|
|
across
|
|
l_enabled_modules as ic
|
|
loop
|
|
l_module := ic.item
|
|
-- FIXME: should we initialize first, and then install
|
|
-- or the reverse, or merge installation and initialization
|
|
-- and leave the responsability to the module to know
|
|
-- if this is installed or not...
|
|
if attached {CMS_CORE_MODULE} l_module as l_core_module then
|
|
if not l_core_module.is_installed (Current) then
|
|
l_core_module.install (Current)
|
|
end
|
|
end
|
|
-- if not l_module.is_installed (Current) then
|
|
-- l_module.install (Current)
|
|
-- end
|
|
if l_module.is_installed (Current) then
|
|
l_module.initialize (Current)
|
|
else
|
|
if l_uninstalled_mods = Void then
|
|
create l_uninstalled_mods.make (1)
|
|
end
|
|
l_uninstalled_mods.force (l_module)
|
|
end
|
|
end
|
|
if l_uninstalled_mods /= Void then
|
|
across
|
|
l_uninstalled_mods as ic
|
|
loop
|
|
l_enabled_modules.remove (ic.item)
|
|
end
|
|
end
|
|
|
|
-- hooks initialization, is done after site/admin switch.
|
|
-- See `initialize_execution`
|
|
end
|
|
|
|
initialize_site_url
|
|
-- Initialize site and base url.
|
|
local
|
|
l_base_url: detachable READABLE_STRING_8
|
|
l_url: detachable STRING_8
|
|
i,j: INTEGER
|
|
do
|
|
--| WARNING: do not use `absolute_url' and `url', since it relies on site_url and base_url.
|
|
if attached setup.site_url as l_site_url and then not l_site_url.is_empty then
|
|
create l_url.make_from_string (l_site_url)
|
|
else
|
|
l_url := request.absolute_script_url ("/")
|
|
end
|
|
check is_not_empty: not l_url.is_empty end
|
|
if l_url [l_url.count] /= '/' then
|
|
l_url.append_character ('/')
|
|
end
|
|
site_url := l_url
|
|
i := l_url.substring_index ("://", 1)
|
|
if i > 0 then
|
|
j := l_url.index_of ('/', i + 3)
|
|
if j > 0 then
|
|
l_base_url := l_url.substring (j, l_url.count)
|
|
end
|
|
end
|
|
if l_base_url /= Void then
|
|
base_url := l_base_url
|
|
if l_base_url.ends_with_general ("/") then
|
|
create base_path.make_from_string (l_base_url)
|
|
else
|
|
create base_path.make_from_string (l_base_url + "/")
|
|
end
|
|
else
|
|
create base_path.make_from_string ("/")
|
|
end
|
|
ensure
|
|
site_url_set: site_url /= Void
|
|
site_url_ends_with_slash: site_url.ends_with_general ("/")
|
|
base_path_set: base_path /= Void and then base_path.ends_with_general ("/")
|
|
end
|
|
|
|
initialize_content_types
|
|
-- Initialize content types.
|
|
do
|
|
create content_types.make (1)
|
|
create content_type_webform_managers.make (1)
|
|
end
|
|
|
|
initialize_content_filters_and_formats
|
|
-- Initialize content filters and formats.
|
|
local
|
|
l_filters: like content_filters
|
|
do
|
|
-- Initialize built-in content filters
|
|
create l_filters.make (4)
|
|
content_filters := l_filters
|
|
l_filters.extend (create {HTML_TO_TEXT_CONTENT_FILTER})
|
|
l_filters.extend (create {LINE_BREAK_TO_HTML_CONTENT_FILTER})
|
|
l_filters.extend (create {URL_CONTENT_FILTER})
|
|
l_filters.extend (create {HTML_CONTENT_FILTER})
|
|
|
|
|
|
-- Initialize built-in formats
|
|
create formats.make (4)
|
|
end
|
|
|
|
setup_formats
|
|
-- Initialize content filters and formats.
|
|
local
|
|
l_formats: like formats
|
|
do
|
|
load_formats
|
|
l_formats := formats
|
|
if l_formats.count = 0 then
|
|
-- Setup built-in formats
|
|
|
|
-- plain_text: html_to_text + line_break_converter
|
|
l_formats.extend (new_format ("plain_text", "Plain text", <<{HTML_TO_TEXT_CONTENT_FILTER}.name, {LINE_BREAK_TO_HTML_CONTENT_FILTER}.name>>))
|
|
|
|
-- full_html: url
|
|
l_formats.extend (new_format ("full_html", "Full HTML", <<{URL_CONTENT_FILTER}.name>>))
|
|
|
|
-- filtered_html: url + html_filter + line_break_converter
|
|
l_formats.extend (new_format ("filtered_html", "Filtered HTML", <<{URL_CONTENT_FILTER}.name, {HTML_CONTENT_FILTER}.name, {LINE_BREAK_TO_HTML_CONTENT_FILTER}.name>>))
|
|
|
|
-- CMS Editor!
|
|
l_formats.extend (new_format ("cms_editor", "CMS HTML content", Void))
|
|
|
|
save_formats
|
|
end
|
|
end
|
|
|
|
feature {CMS_API_ACCESS} -- CMS Formats management
|
|
|
|
load_formats
|
|
local
|
|
f: CMS_FORMAT
|
|
jp: JSON_PARSER
|
|
s: STRING_32
|
|
l_name, l_title: READABLE_STRING_8
|
|
do
|
|
formats.wipe_out
|
|
if
|
|
attached storage.custom_value ("cms.formats", "api-formats") as v_formats and then
|
|
v_formats.is_valid_as_string_8
|
|
then
|
|
create jp.make_with_string (v_formats.to_string_8)
|
|
jp.parse_content
|
|
if jp.is_parsed and then jp.is_valid and then attached jp.parsed_json_object as j_formats then
|
|
-- { "plain_text": { "title": "Plain text", "filters": "plain_text+foobar+toto"}, ...}
|
|
across
|
|
j_formats as ic
|
|
loop
|
|
if attached {JSON_OBJECT} ic.item as j_format then
|
|
l_name := ic.key.unescaped_string_8
|
|
if attached {JSON_STRING} j_format.item ("title") as j_title then
|
|
l_title := j_title.unescaped_string_8
|
|
else
|
|
l_title := l_name
|
|
end
|
|
if attached {JSON_STRING} j_format.item ("filters") as j_filters then
|
|
s := j_filters.unescaped_string_32
|
|
f := new_format (l_name, l_title, s.split ('+'))
|
|
else
|
|
f := new_format (l_name, l_title, Void)
|
|
end
|
|
formats.extend (f)
|
|
if attached {JSON_STRING} j_format.item ("types") as j_types then
|
|
s := j_types.unescaped_string_32
|
|
across
|
|
s.split ('+') as s_ic
|
|
loop
|
|
if attached content_type (s_ic.item) as ct then
|
|
ct.extend_format (f)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
save_formats
|
|
-- Save `formats`.
|
|
local
|
|
f: CMS_FORMAT
|
|
j,ji: JSON_OBJECT
|
|
s: STRING_32
|
|
ct: CMS_CONTENT_TYPE
|
|
do
|
|
-- { "plain_text": { "title": "Plain text", "filters": "plain_text+foobar+toto"}, ...}
|
|
create j.make_empty
|
|
across
|
|
formats as ic
|
|
loop
|
|
f := ic.item
|
|
create ji.make
|
|
ji.put_string (f.title, "title")
|
|
|
|
create s.make_empty
|
|
across
|
|
f.filters as f_ic
|
|
loop
|
|
if not s.is_empty then
|
|
s.append ("+")
|
|
end
|
|
s.append_string_general (f_ic.item.name)
|
|
end
|
|
ji.put_string (s, "filters")
|
|
|
|
create s.make_empty
|
|
across
|
|
content_types as ct_ic
|
|
loop
|
|
ct := ct_ic.item
|
|
if ct.has_format (f.name) then
|
|
if not s.is_empty then
|
|
s.append ("+")
|
|
end
|
|
s.append_string_general (ct.name)
|
|
end
|
|
end
|
|
ji.put_string (s, "types")
|
|
|
|
j.put (ji, f.name)
|
|
end
|
|
storage.set_custom_value ("cms.formats", j.representation, "api-formats")
|
|
end
|
|
|
|
feature -- Execution initialization
|
|
|
|
initialize_execution
|
|
do
|
|
setup_hooks
|
|
setup_formats
|
|
end
|
|
|
|
feature {CMS_ACCESS} -- Module management
|
|
|
|
install_all_modules
|
|
-- Install CMS or uninstalled module which are enabled.
|
|
local
|
|
l_module: CMS_MODULE
|
|
do
|
|
across
|
|
setup.modules as ic
|
|
loop
|
|
l_module := ic.item
|
|
-- FIXME: should we initialize first, and then install
|
|
-- or the reverse, or merge installation and initialization
|
|
-- and leave the responsability to the module to know
|
|
-- if this is installed or not...
|
|
if l_module.is_enabled and not l_module.is_installed (Current) then
|
|
install_module (l_module)
|
|
end
|
|
end
|
|
end
|
|
|
|
installed_module_version (m: CMS_MODULE): detachable READABLE_STRING_32
|
|
require
|
|
module_installed: is_module_installed (m)
|
|
do
|
|
Result := m.installed_version (Current)
|
|
end
|
|
|
|
install_module (m: CMS_MODULE)
|
|
-- Install module `m'.
|
|
require
|
|
module_not_installed: not is_module_installed (m)
|
|
do
|
|
m.install (Current)
|
|
if m.is_enabled then
|
|
m.initialize (Current)
|
|
end
|
|
end
|
|
|
|
uninstall_module (m: CMS_MODULE)
|
|
-- Uninstall module `m'.
|
|
require
|
|
module_installed: is_module_installed (m)
|
|
do
|
|
m.uninstall (Current)
|
|
end
|
|
|
|
enable_module (m: CMS_MODULE)
|
|
-- Enable module `m'.
|
|
do
|
|
m.update_status_in_storage (True, Current)
|
|
ensure
|
|
module_enabled: is_module_enabled (m)
|
|
end
|
|
|
|
disable_module (m: CMS_MODULE)
|
|
-- Disable module `m'.
|
|
do
|
|
m.update_status_in_storage (False, Current)
|
|
ensure
|
|
module_disabled: not is_module_enabled (m)
|
|
end
|
|
|
|
feature -- Access
|
|
|
|
setup: CMS_SETUP
|
|
-- CMS setup.
|
|
|
|
logger: CMS_LOGGER
|
|
-- Logger
|
|
|
|
storage: CMS_STORAGE
|
|
-- Default persistence storage.
|
|
|
|
feature -- Access: url
|
|
|
|
base_url: detachable IMMUTABLE_STRING_8
|
|
-- Base url if any.
|
|
--| Usually it is Void, but it could be
|
|
--| /project/demo/
|
|
|
|
base_path: IMMUTABLE_STRING_8
|
|
-- Base path, default to "/"
|
|
|
|
site_url: IMMUTABLE_STRING_8
|
|
-- Site url
|
|
|
|
is_administration_request (req: WSF_REQUEST): BOOLEAN
|
|
do
|
|
Result := req.percent_encoded_path_info.starts_with_general (setup.administration_base_path)
|
|
end
|
|
|
|
administration_path (a_relative_path: detachable READABLE_STRING_8): STRING_8
|
|
do
|
|
create Result.make_from_string (setup.administration_base_path)
|
|
if a_relative_path /= Void then
|
|
if a_relative_path.is_empty then
|
|
Result.append_character ('/')
|
|
else
|
|
if a_relative_path[1] /= '/' then
|
|
Result.append_character ('/')
|
|
end
|
|
Result.append (a_relative_path)
|
|
end
|
|
end
|
|
end
|
|
|
|
administration_path_location (a_relative_location: detachable READABLE_STRING_8): STRING_8
|
|
require
|
|
no_first_slash: a_relative_location = Void or else not a_relative_location.starts_with_general ("/")
|
|
do
|
|
create Result.make_from_string (administration_base_path_location)
|
|
if a_relative_location /= Void then
|
|
if a_relative_location.is_empty then
|
|
Result.append_character ('/')
|
|
else
|
|
if a_relative_location[1] /= '/' then
|
|
Result.append_character ('/')
|
|
end
|
|
Result.append (a_relative_location)
|
|
end
|
|
end
|
|
end
|
|
|
|
feature {NONE} -- Url implementation.
|
|
|
|
administration_base_path_location: IMMUTABLE_STRING_8
|
|
-- Administration path without first slash!
|
|
|
|
feature -- CMS links
|
|
|
|
administration_link (a_title: READABLE_STRING_GENERAL; a_relative_location: detachable READABLE_STRING_8): CMS_LOCAL_LINK
|
|
require
|
|
no_first_slash: a_relative_location = Void or else not a_relative_location.starts_with_general ("/")
|
|
do
|
|
Result := local_link (a_title, administration_path_location (a_relative_location))
|
|
end
|
|
|
|
local_link (a_title: READABLE_STRING_GENERAL; a_location: READABLE_STRING_8): CMS_LOCAL_LINK
|
|
do
|
|
create Result.make (a_title, a_location)
|
|
end
|
|
|
|
user_local_link (u: CMS_USER; a_opt_title: detachable READABLE_STRING_GENERAL): CMS_LOCAL_LINK
|
|
do
|
|
if a_opt_title /= Void then
|
|
create Result.make (a_opt_title, user_url (u))
|
|
else
|
|
create Result.make (user_display_name (u), user_url (u))
|
|
end
|
|
end
|
|
|
|
user_html_link (u: CMS_USER): STRING
|
|
require
|
|
u_with_name: not u.name.is_whitespace
|
|
do
|
|
Result := link (user_display_name (u), "user/" + u.id.out, Void)
|
|
end
|
|
|
|
feature -- Helpers: URLs
|
|
|
|
location_absolute_url (a_location: READABLE_STRING_8; opts: detachable CMS_API_OPTIONS): STRING
|
|
-- Absolute URL for `a_location'.
|
|
--| Options `opts' could be
|
|
--| - absolute: True|False => return absolute url
|
|
--| - query: string => append "?query"
|
|
--| - fragment: string => append "#fragment"
|
|
do
|
|
Result := absolute_url (a_location, opts)
|
|
end
|
|
|
|
location_url (a_location: READABLE_STRING_8; opts: detachable CMS_API_OPTIONS): STRING
|
|
-- URL for `a_location'.
|
|
--| Options `opts' could be
|
|
--| - absolute: True|False => return absolute url
|
|
--| - query: string => append "?query"
|
|
--| - fragment: string => append "#fragment"
|
|
do
|
|
Result := url (a_location, opts)
|
|
end
|
|
|
|
user_url (u: CMS_USER): like url
|
|
require
|
|
u_with_id: u.has_id
|
|
do
|
|
Result := location_url ("user/" + u.id.out, Void)
|
|
end
|
|
|
|
feature -- Helpers: html links
|
|
|
|
user_display_name (u: CMS_USER): READABLE_STRING_32
|
|
do
|
|
Result := user_api.user_display_name (u)
|
|
end
|
|
|
|
feature -- Settings
|
|
|
|
switch_to_site_mode
|
|
do
|
|
if is_administration_mode then
|
|
setup.set_site_mode
|
|
is_administration_mode := False
|
|
end
|
|
end
|
|
|
|
switch_to_administration_mode
|
|
do
|
|
if not is_administration_mode then
|
|
setup.set_administration_mode
|
|
is_administration_mode := True
|
|
end
|
|
end
|
|
|
|
is_administration_mode: BOOLEAN
|
|
-- Is administration mode?
|
|
|
|
is_debug: BOOLEAN
|
|
-- Is debug mode enabled?
|
|
do
|
|
Result := setup.is_debug
|
|
end
|
|
|
|
feature {NONE} -- Access: request
|
|
|
|
request: WSF_REQUEST
|
|
-- Associated http request.
|
|
--| note: here for the sole purpose of CMS_API.
|
|
|
|
feature -- Content
|
|
|
|
content_types: ARRAYED_LIST [CMS_CONTENT_TYPE]
|
|
-- Available content types
|
|
|
|
add_content_type (a_type: CMS_CONTENT_TYPE)
|
|
-- Register content type `a_type'.
|
|
do
|
|
content_types.force (a_type)
|
|
end
|
|
|
|
content_type (a_name: READABLE_STRING_GENERAL): detachable CMS_CONTENT_TYPE
|
|
-- Content type named `a_named' if any.
|
|
do
|
|
across
|
|
content_types as ic
|
|
until
|
|
Result /= Void
|
|
loop
|
|
Result := ic.item
|
|
if not a_name.is_case_insensitive_equal (Result.name) then
|
|
Result := Void
|
|
end
|
|
end
|
|
end
|
|
|
|
feature -- Content type webform
|
|
|
|
content_type_webform_managers: ARRAYED_LIST [CMS_CONTENT_TYPE_WEBFORM_MANAGER [CMS_CONTENT]]
|
|
-- Available content types
|
|
|
|
add_content_type_webform_manager (a_manager: CMS_CONTENT_TYPE_WEBFORM_MANAGER [CMS_CONTENT])
|
|
-- Register webform manager `a_manager'.
|
|
do
|
|
content_type_webform_managers.force (a_manager)
|
|
end
|
|
|
|
content_type_webform_manager (a_content_type: CMS_CONTENT_TYPE): detachable CMS_CONTENT_TYPE_WEBFORM_MANAGER [CMS_CONTENT]
|
|
-- Web form manager for content type `a_content_type' if any.
|
|
do
|
|
Result := content_type_webform_manager_by_name (a_content_type.name)
|
|
end
|
|
|
|
content_type_webform_manager_by_name (a_content_type_name: READABLE_STRING_GENERAL): detachable CMS_CONTENT_TYPE_WEBFORM_MANAGER [CMS_CONTENT]
|
|
-- Web form manager for content type named `a_content_type_name' if any.
|
|
do
|
|
across
|
|
content_type_webform_managers as ic
|
|
until
|
|
Result /= Void
|
|
loop
|
|
Result := ic.item
|
|
if not a_content_type_name.is_case_insensitive_equal (Result.name) then
|
|
Result := Void
|
|
end
|
|
end
|
|
end
|
|
|
|
feature -- Filters and Formats
|
|
|
|
content_filters: CMS_CONTENT_FILTERS
|
|
-- Available content filters.
|
|
|
|
formats: CMS_FORMATS
|
|
-- Available content formats.
|
|
|
|
format (a_format_name: detachable READABLE_STRING_GENERAL): detachable CMS_FORMAT
|
|
-- Content format name `a_format_name' if any.
|
|
do
|
|
Result := formats.item (a_format_name)
|
|
end
|
|
|
|
new_format (a_name: READABLE_STRING_8; a_title: READABLE_STRING_8; a_filter_names: detachable ITERABLE [READABLE_STRING_GENERAL]): CMS_FORMAT
|
|
-- New cms content format named `a_name`, with `a_title`, and composed from `a_filter_names`.
|
|
do
|
|
create Result.make (a_name, a_title)
|
|
if a_filter_names /= Void then
|
|
across
|
|
a_filter_names as ic
|
|
loop
|
|
if attached content_filters.item (ic.item) as f then
|
|
Result.add_filter (f)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
feature -- Status Report
|
|
|
|
has_error: BOOLEAN
|
|
-- Has error?
|
|
do
|
|
Result := error_handler.has_error
|
|
end
|
|
|
|
string_representation_of_errors: STRING_32
|
|
-- String representation of all error(s).
|
|
do
|
|
Result := error_handler.as_string_representation
|
|
end
|
|
|
|
feature -- Logging
|
|
|
|
logs (a_category: detachable READABLE_STRING_8; a_lower: INTEGER; a_count: INTEGER): LIST [CMS_LOG]
|
|
-- List of recent logs from `a_lower' to `a_lower+a_count'.
|
|
-- If `a_category' is set, filter to return only associated logs.
|
|
-- If `a_count' <= 0 then, return all logs.
|
|
do
|
|
Result := storage.logs (a_category, a_lower, a_count)
|
|
end
|
|
|
|
log (a_category: READABLE_STRING_8; a_message: READABLE_STRING_8; a_level: INTEGER; a_link: detachable CMS_LINK)
|
|
local
|
|
l_log: CMS_LOG
|
|
m: STRING
|
|
do
|
|
create l_log.make (a_category, a_message, a_level, Void)
|
|
if a_link /= Void then
|
|
l_log.set_link (a_link)
|
|
end
|
|
storage.save_log (l_log)
|
|
|
|
create m.make_from_string ("[" + a_category + "] ")
|
|
m.append (a_message)
|
|
if a_link /= Void then
|
|
m.append (" [" + url_encoded (a_link.title) + "]("+ a_link.location +")")
|
|
end
|
|
|
|
inspect a_level
|
|
when {CMS_LOG}.level_emergency then
|
|
logger.put_alert (m, Void)
|
|
when {CMS_LOG}.level_alert then
|
|
logger.put_alert (m, Void)
|
|
when {CMS_LOG}.level_critical then
|
|
logger.put_critical (m, Void)
|
|
when {CMS_LOG}.level_error then
|
|
logger.put_error (m, Void)
|
|
when {CMS_LOG}.level_warning then
|
|
logger.put_warning (m, Void)
|
|
when {CMS_LOG}.level_notice then
|
|
logger.put_information (m, Void)
|
|
when {CMS_LOG}.level_info then
|
|
logger.put_information (m, Void)
|
|
when {CMS_LOG}.level_debug then
|
|
logger.put_debug (m, Void)
|
|
else
|
|
logger.put_debug (m, Void)
|
|
end
|
|
end
|
|
|
|
feature -- Internationalization (i18n)
|
|
|
|
translation (a_text: READABLE_STRING_GENERAL; opts: detachable CMS_API_OPTIONS): STRING_32
|
|
-- Translated text `a_text' according to expected context (lang, ...)
|
|
-- and adapt according to options eventually set by `opts'.
|
|
do
|
|
to_implement ("Implement i18n support [2015-may]")
|
|
Result := a_text.as_string_32
|
|
end
|
|
|
|
formatted_string (a_text: READABLE_STRING_GENERAL; args: TUPLE): STRING_32
|
|
-- Format `a_text' using arguments `args'.
|
|
--| ex: formatted_string ("hello $1, see page $title.", ["bob", "contact"] -> "hello bob, see page contact"
|
|
local
|
|
l_formatter: CMS_STRING_FORMATTER
|
|
do
|
|
create l_formatter
|
|
Result := l_formatter.formatted_string (a_text, args)
|
|
end
|
|
|
|
formatted_date_time_ago (dt: DATE_TIME): STRING_32
|
|
-- Output date `dt` using time ago duration.
|
|
local
|
|
ago: DATE_TIME_AGO_CONVERTER
|
|
do
|
|
create ago.make
|
|
create Result.make (10)
|
|
Result.append_string_general (ago.smart_date_duration (dt))
|
|
end
|
|
|
|
formatted_date_time_yyyy_mm_dd (dt: DATE_TIME): STRING_8
|
|
-- Output date `dt` using YYYY-MM-DD
|
|
local
|
|
i: INTEGER
|
|
do
|
|
create Result.make (10)
|
|
Result.append_integer (dt.year)
|
|
Result.append_character ('-')
|
|
i := dt.month
|
|
if i <= 9 then
|
|
Result.append_character ('0')
|
|
end
|
|
Result.append_integer (i)
|
|
Result.append_character ('-')
|
|
i := dt.day
|
|
if i <= 9 then
|
|
Result.append_character ('0')
|
|
end
|
|
Result.append_integer (i)
|
|
end
|
|
|
|
formatted_date_time_yyyy_mm_dd__hh_min_ss (dt: DATE_TIME): STRING_8
|
|
-- Output date `dt` using YYYY-MM-DD h:min:sec
|
|
local
|
|
i: INTEGER
|
|
do
|
|
create Result.make (19)
|
|
Result.append (formatted_date_time_yyyy_mm_dd (dt))
|
|
Result.append_character (' ')
|
|
i := dt.hour
|
|
if i <= 9 then
|
|
Result.append_character ('0')
|
|
end
|
|
Result.append_integer (i)
|
|
Result.append_character (':')
|
|
i := dt.minute
|
|
if i <= 9 then
|
|
Result.append_character ('0')
|
|
end
|
|
Result.append_integer (i)
|
|
Result.append_character (':')
|
|
i := dt.second
|
|
if i <= 9 then
|
|
Result.append_character ('0')
|
|
end
|
|
Result.append_integer (i)
|
|
|
|
end
|
|
|
|
feature -- Emails
|
|
|
|
new_email (a_to_address: READABLE_STRING_8; a_subject: READABLE_STRING_8; a_content: READABLE_STRING_8): CMS_EMAIL
|
|
-- New email object.
|
|
local
|
|
l_subject: READABLE_STRING_8
|
|
do
|
|
l_subject := a_subject
|
|
if attached setup.site_email_subject_prefix as l_prefix then
|
|
if not l_subject.starts_with (l_prefix) then
|
|
l_subject := l_prefix + l_subject
|
|
end
|
|
end
|
|
create Result.make (setup.site_email, a_to_address, l_subject, a_content)
|
|
end
|
|
|
|
process_email (e: CMS_EMAIL)
|
|
-- Process email `e'.
|
|
do
|
|
log ("mailer", "Send email %"" + e.subject + "%"%N" + e.header, {CMS_LOG}.level_notice, Void)
|
|
reset_error
|
|
prepare_email (e)
|
|
setup.mailer.safe_process_email (e)
|
|
if setup.mailer.has_error then
|
|
error_handler.add_custom_error (0, "Mailer error", "Error occurred while processing email.")
|
|
else
|
|
e.set_is_sent (True)
|
|
end
|
|
end
|
|
|
|
process_emails (lst: ITERABLE [CMS_EMAIL])
|
|
-- Process collection of email `lst'.
|
|
do
|
|
across
|
|
lst as ic
|
|
loop
|
|
process_email (ic.item)
|
|
end
|
|
end
|
|
|
|
feature {NONE} -- Emails implementation
|
|
|
|
prepare_email (e: CMS_EMAIL)
|
|
-- Prepare email `e', and update parameters if needed.
|
|
local
|
|
l_sender, l_from: READABLE_STRING_8
|
|
do
|
|
l_sender := setup.site_email
|
|
l_from := e.from_address
|
|
if not l_sender.is_case_insensitive_equal_general (l_from) then
|
|
e.set_from_address (l_sender)
|
|
if not e.has_header ("Return-Path") then
|
|
e.add_header_line ("Return-path: " + l_from)
|
|
end
|
|
if e.reply_to_address = Void then
|
|
e.set_reply_to_address (l_from)
|
|
else
|
|
--| As a Reply-To address is already set,
|
|
--| ignore previous from address.
|
|
end
|
|
end
|
|
end
|
|
|
|
feature -- Permissions system
|
|
|
|
has_permission (a_permission: detachable READABLE_STRING_GENERAL): BOOLEAN
|
|
-- Anonymous or user `user' has permission for `a_permission'?
|
|
--| `a_permission' could be for instance "create page".
|
|
do
|
|
Result := user_has_permission (user, a_permission)
|
|
end
|
|
|
|
has_permissions (a_permission_list: ITERABLE [READABLE_STRING_GENERAL]): BOOLEAN
|
|
-- Anonymous or user `user' has any of the permissions `a_permission_list`?
|
|
do
|
|
Result := user_has_permissions (user, a_permission_list)
|
|
end
|
|
|
|
user_has_permission (a_user: detachable CMS_USER; a_permission: detachable READABLE_STRING_GENERAL): BOOLEAN
|
|
-- Anonymous or user `a_user' has permission for `a_permission'?
|
|
--| `a_permission' could be for instance "create page".
|
|
do
|
|
Result := user_api.user_has_permission (a_user, a_permission)
|
|
end
|
|
|
|
user_has_permissions (a_user: detachable CMS_USER; a_permission_list: ITERABLE [READABLE_STRING_GENERAL]): BOOLEAN
|
|
-- Does `a_user' has any of the permissions `a_permission_list' ?
|
|
do
|
|
across
|
|
a_permission_list as ic
|
|
until
|
|
Result
|
|
loop
|
|
Result := user_has_permission (a_user, ic.item)
|
|
end
|
|
end
|
|
|
|
feature -- Query: module
|
|
|
|
is_module_installed (a_module: CMS_MODULE): BOOLEAN
|
|
-- Is `a_module' installed?
|
|
do
|
|
Result := a_module.is_installed (Current)
|
|
end
|
|
|
|
is_module_enabled (a_module: CMS_MODULE): BOOLEAN
|
|
do
|
|
Result := a_module.is_enabled or a_module.is_enabled_in_storage (Current)
|
|
end
|
|
|
|
enabled_modules: CMS_MODULE_COLLECTION
|
|
|
|
module (a_type: TYPE [CMS_MODULE]): detachable CMS_MODULE
|
|
-- Enabled module typed `a_type', if any.
|
|
--| usage: if attached module ({FOO_MODULE}) as mod then ...
|
|
do
|
|
Result := installed_module (a_type)
|
|
if Result /= Void and then not Result.is_enabled then
|
|
Result := Void
|
|
end
|
|
ensure
|
|
Result /= Void implies (Result.is_enabled) -- and a_type.is_conforming_to (Result.generating_type))
|
|
end
|
|
|
|
installed_module (a_type: TYPE [CMS_MODULE]): detachable CMS_MODULE
|
|
-- Module typed `a_type', if any.
|
|
-- It may not be enabled!
|
|
--| usage: if attached module ({FOO_MODULE}) as mod then ...
|
|
do
|
|
Result := setup.modules.item (a_type)
|
|
ensure
|
|
--FIXME Result /= Void implies (Result.is_enabled) -- and a_type.is_conforming_to (Result.generating_type))
|
|
end
|
|
|
|
module_api (a_type: TYPE [CMS_MODULE]): detachable CMS_MODULE_API
|
|
-- Enabled module API associated with module typed `a_type'.
|
|
do
|
|
if attached module (a_type) as mod then
|
|
if mod.is_enabled then
|
|
if not mod.is_initialized then
|
|
mod.initialize (Current)
|
|
end
|
|
Result := mod.module_api
|
|
end
|
|
end
|
|
end
|
|
|
|
module_by_name (a_name: READABLE_STRING_GENERAL): detachable CMS_MODULE
|
|
-- Enabled module named `a_name', if any.
|
|
do
|
|
across
|
|
setup.modules as ic
|
|
until
|
|
Result /= Void
|
|
loop
|
|
Result := ic.item
|
|
if
|
|
not Result.is_enabled
|
|
or else not Result.name.is_case_insensitive_equal_general (a_name)
|
|
then
|
|
Result := Void
|
|
end
|
|
end
|
|
ensure
|
|
Result /= Void implies (Result.is_enabled and Result.name.is_case_insensitive_equal_general (a_name))
|
|
end
|
|
|
|
module_api_by_name (a_name: READABLE_STRING_GENERAL): detachable CMS_MODULE_API
|
|
-- Enabled module API associated with module named `a_name'.
|
|
do
|
|
if attached module_by_name (a_name) as mod then
|
|
Result := mod.module_api
|
|
end
|
|
end
|
|
|
|
feature -- Hooks
|
|
|
|
hooks: CMS_HOOK_CORE_MANAGER
|
|
-- Manager handling hook subscriptions.
|
|
|
|
feature {CMS_EXECUTION} -- Hooks
|
|
|
|
setup_hooks
|
|
-- Set up CMS hooks.
|
|
--| Each module has to opportunity to subscribe to various hooks.
|
|
local
|
|
l_module: detachable CMS_MODULE
|
|
l_hooks: like hooks
|
|
do
|
|
l_hooks := hooks
|
|
setup_core_hooks (l_hooks)
|
|
across
|
|
enabled_modules as ic
|
|
loop
|
|
l_module := ic.item
|
|
if is_administration_mode then
|
|
if attached {CMS_ADMINISTRABLE} l_module as adm then
|
|
l_module := adm.module_administration
|
|
else
|
|
l_module := Void
|
|
end
|
|
end
|
|
if l_module /= Void then
|
|
if attached {CMS_HOOK_AUTO_REGISTER} l_module as l_auto then
|
|
l_auto.auto_subscribe_to_hooks (l_hooks)
|
|
end
|
|
l_module.setup_hooks (l_hooks)
|
|
end
|
|
end
|
|
end
|
|
|
|
feature {NONE} -- Access: API
|
|
|
|
cms_api: CMS_API
|
|
do
|
|
Result := Current
|
|
end
|
|
|
|
feature -- Access: API
|
|
|
|
user_api: CMS_USER_API
|
|
-- API to access user related data.
|
|
local
|
|
l_api: like internal_user_api
|
|
do
|
|
l_api := internal_user_api
|
|
if l_api = Void then
|
|
create l_api.make (Current)
|
|
internal_user_api := l_api
|
|
end
|
|
Result := l_api
|
|
end
|
|
|
|
feature -- Hooks
|
|
|
|
setup_core_hooks (a_hooks: CMS_HOOK_CORE_MANAGER)
|
|
-- Register hooks associated with the cms core.
|
|
do
|
|
if is_administration_mode then
|
|
a_hooks.subscribe_to_export_hook (Current)
|
|
a_hooks.subscribe_to_import_hook (Current)
|
|
end
|
|
end
|
|
|
|
feature -- Path aliases
|
|
|
|
is_valid_path_alias (a_alias: READABLE_STRING_8): BOOLEAN
|
|
do
|
|
Result := a_alias.is_empty or else not a_alias.starts_with_general ("/")
|
|
end
|
|
|
|
set_path_alias (a_source, a_alias: READABLE_STRING_8; a_keep_previous: BOOLEAN)
|
|
-- Set `a_alias' as alias of `a_source',
|
|
-- and eventually unset previous alias if any.
|
|
require
|
|
valid_alias: is_valid_path_alias (a_alias)
|
|
local
|
|
l_continue: BOOLEAN
|
|
do
|
|
if attached storage.path_alias (a_source) as l_existing_alias then
|
|
if a_alias.same_string (l_existing_alias) then
|
|
-- Already aliased as expected
|
|
else
|
|
-- New alias
|
|
if a_keep_previous then
|
|
l_continue := True
|
|
else
|
|
storage.replace_path_alias (a_source, l_existing_alias, a_alias)
|
|
end
|
|
end
|
|
elseif a_alias.is_whitespace then
|
|
-- Ignore
|
|
elseif a_source.same_string (a_alias) then
|
|
-- No need for alias
|
|
else
|
|
l_continue := True
|
|
end
|
|
if l_continue then
|
|
storage.set_path_alias (a_source, a_alias)
|
|
end
|
|
end
|
|
|
|
unset_path_alias (a_source: READABLE_STRING_8; a_alias: READABLE_STRING_8)
|
|
do
|
|
storage.unset_path_alias (a_source, a_alias)
|
|
end
|
|
|
|
location_alias (a_source: READABLE_STRING_8): READABLE_STRING_8
|
|
-- Location alias associated with `a_source' or the source itself.
|
|
do
|
|
Result := a_source
|
|
if attached storage.path_alias (Result) as l_path then
|
|
Result := l_path
|
|
if Result.starts_with ("/") then
|
|
Result := Result.substring (2, Result.count)
|
|
end
|
|
end
|
|
end
|
|
|
|
path_alias (a_source: READABLE_STRING_8): READABLE_STRING_8
|
|
-- Path alias associated with `a_source' or the source itself.
|
|
do
|
|
Result := a_source
|
|
if attached storage.path_alias (Result) as l_path then
|
|
Result := "/" + l_path
|
|
end
|
|
end
|
|
|
|
source_of_path_alias (a_alias: READABLE_STRING_8): detachable READABLE_STRING_8
|
|
-- Resolved path for alias `a_alias'.
|
|
--| the CMS supports aliases for path, and then this function simply returns
|
|
--| the effective target path/url for this `a_alias'.
|
|
--| For instance: articles/2015/may/this-is-an-article can be an alias to node/123
|
|
--| This function will return "node/123".
|
|
--| If the alias is bad (i.e does not alias real path), then this function
|
|
--| returns Void.
|
|
do
|
|
if attached storage.source_of_path_alias (a_alias) as l_source_path then
|
|
Result := l_source_path
|
|
end
|
|
end
|
|
|
|
feature -- Element Change: Error
|
|
|
|
reset_error
|
|
-- Reset error handler.
|
|
do
|
|
error_handler.reset
|
|
end
|
|
|
|
feature {NONE}-- Implementation
|
|
|
|
error_handler: ERROR_HANDLER
|
|
-- Error handler.
|
|
|
|
internal_user_api: detachable like user_api
|
|
-- Cached value for `user_api`.
|
|
|
|
feature -- Environment/ theme
|
|
|
|
site_location: PATH
|
|
-- CMS site location.
|
|
do
|
|
Result := setup.site_location
|
|
end
|
|
|
|
temp_location: PATH
|
|
-- CMS temp folder location.
|
|
do
|
|
Result := setup.temp_location
|
|
end
|
|
|
|
files_location: PATH
|
|
-- CMS public files location.
|
|
do
|
|
Result := setup.files_location
|
|
end
|
|
|
|
files_path: STRING_8
|
|
do
|
|
create Result.make_from_string (base_path)
|
|
Result.append ("files/")
|
|
ensure
|
|
ends_with_slash: Result.ends_with ("/")
|
|
end
|
|
|
|
cache_location: PATH
|
|
-- CMS internal cache location.
|
|
do
|
|
Result := setup.cache_location
|
|
end
|
|
|
|
theme_location: PATH
|
|
-- Active theme location.
|
|
do
|
|
Result := setup.theme_location
|
|
end
|
|
|
|
theme_name: READABLE_STRING_32
|
|
do
|
|
Result := setup.theme_name
|
|
end
|
|
|
|
theme_path: STRING_8
|
|
-- URL path to the theme.
|
|
do
|
|
Result := theme_path_for (theme_name)
|
|
ensure
|
|
ends_with_slash: Result.ends_with ("/")
|
|
end
|
|
|
|
theme_assets_location: PATH
|
|
-- assets (js, css, images, etc).
|
|
do
|
|
-- Check how to get this path from the CMS_THEME information.
|
|
Result := theme_location.extended ("assets")
|
|
end
|
|
|
|
feature -- Theming path helpers
|
|
|
|
theme_location_for (a_theme_name: READABLE_STRING_GENERAL): PATH
|
|
do
|
|
Result := setup.theme_location_for (a_theme_name)
|
|
end
|
|
|
|
theme_path_for (a_theme_name: READABLE_STRING_GENERAL): STRING_8
|
|
-- URL path to the theme `a_theme_name`.
|
|
do
|
|
create Result.make_from_string (base_path)
|
|
Result.append ("theme/")
|
|
Result.append (url_encoded (a_theme_name))
|
|
Result.append_character ('/')
|
|
ensure
|
|
ends_with_slash: Result.ends_with ("/")
|
|
end
|
|
|
|
theme_assets_location_for (a_theme_name: READABLE_STRING_GENERAL): PATH
|
|
do
|
|
Result := theme_location_for (a_theme_name).extended ("assets")
|
|
end
|
|
|
|
feature -- Environment/ module
|
|
|
|
module_configuration (a_module: CMS_MODULE; a_name: detachable READABLE_STRING_GENERAL): detachable CONFIG_READER
|
|
do
|
|
Result := module_configuration_by_name (a_module.name, a_name)
|
|
end
|
|
|
|
module_configuration_by_name (a_module_name: READABLE_STRING_GENERAL; a_name: detachable READABLE_STRING_GENERAL): detachable CONFIG_READER
|
|
-- Configuration reader for `a_module', and if `a_name' is set, using name `a_name'.
|
|
local
|
|
p: detachable PATH
|
|
do
|
|
-- Search first in site/config/modules/$module_name/($app|$module_name).(json|ini)
|
|
-- if none, look as sub configuration if $app /= Void
|
|
-- and then in site/modules/$module_name/config/($app|$module_name).(json|ini)
|
|
-- and if non in sub config if $app /= Void
|
|
p := site_location.extended ("config").extended ("modules").extended (a_module_name)
|
|
Result := module_configuration_by_name_in_location (a_module_name, p, a_name)
|
|
if Result = Void then
|
|
p := module_location_by_name (a_module_name).extended ("config")
|
|
Result := module_configuration_by_name_in_location (a_module_name, p, a_name)
|
|
end
|
|
end
|
|
|
|
module_configuration_by_name_in_location (a_module_name: READABLE_STRING_GENERAL; a_dir: PATH; a_name: detachable READABLE_STRING_GENERAL): detachable CONFIG_READER
|
|
-- Configuration reader from "$a_dir/($a_module_name|$a_name).(json|ini)" location.
|
|
local
|
|
p: PATH
|
|
l_path: PATH
|
|
ut: FILE_UTILITIES
|
|
do
|
|
if a_name = Void then
|
|
p := a_dir.extended (a_module_name)
|
|
else
|
|
p := a_dir.extended (a_name)
|
|
end
|
|
l_path := p.appended_with_extension ("json")
|
|
if ut.file_path_exists (l_path) then
|
|
create {JSON_CONFIG} Result.make_from_file (l_path)
|
|
else
|
|
l_path := p.appended_with_extension ("ini")
|
|
if ut.file_path_exists (l_path) then
|
|
create {INI_CONFIG} Result.make_from_file (l_path)
|
|
end
|
|
end
|
|
if Result = Void then
|
|
if
|
|
a_name /= Void and then
|
|
attached {CONFIG_READER} module_configuration_by_name_in_location (a_module_name, a_dir, Void) as cfg
|
|
then
|
|
-- Use sub config from default.
|
|
Result := cfg.sub_config (a_name)
|
|
end
|
|
elseif Result.has_error then
|
|
log ("modules", "module configuration has error %"" + p.utf_8_name + "%"", {CMS_LOG}.level_error, Void)
|
|
end
|
|
end
|
|
|
|
modules_location: PATH
|
|
-- Directory containing cms modules.
|
|
do
|
|
Result := setup.modules_location
|
|
end
|
|
|
|
module_location (a_module: CMS_MODULE): PATH
|
|
-- Location associated with `a_module'.
|
|
do
|
|
Result := module_location_by_name (a_module.name)
|
|
end
|
|
|
|
module_location_by_name (a_module_name: READABLE_STRING_GENERAL): PATH
|
|
-- Location associated with `a_module_name'.
|
|
do
|
|
Result := modules_location.extended (a_module_name)
|
|
end
|
|
|
|
module_resource_location (a_module: CMS_MODULE; a_resource: PATH): PATH
|
|
-- Location of resource `a_resource' for `a_module'.
|
|
do
|
|
--| site/modules/$modname/$a_resource
|
|
Result := module_resource_location_by_name (a_module.name, a_resource)
|
|
end
|
|
|
|
module_resource_location_by_name (a_module_name: READABLE_STRING_GENERAL; a_resource: PATH): PATH
|
|
-- Location of resource `a_resource' for `a_module'.
|
|
do
|
|
--| site/modules/$modname/$a_resource
|
|
Result := module_location_by_name (a_module_name).extended_path (a_resource)
|
|
end
|
|
|
|
feature -- Environment/ modules and theme
|
|
|
|
module_theme_resource_location (a_module: CMS_MODULE; a_resource: PATH): detachable PATH
|
|
-- Theme resource location of `a_resource' for module `a_module', if exists.
|
|
-- By default, located under the module location folder, but could be overriden
|
|
-- from files located under modules subfolder of active `theme_location'.
|
|
--| First search in themes/$theme/modules/$a_module.name/$a_resource,
|
|
--| and if not found then search in
|
|
--| modules/$a_module_name/$a_resource.
|
|
local
|
|
ut: FILE_UTILITIES
|
|
do
|
|
-- Check first in selected theme folder.
|
|
Result := module_theme_location (a_module).extended_path (a_resource)
|
|
if not ut.file_path_exists (Result) then
|
|
-- And if not found, look into site/modules/$a_module.name/.... folders.
|
|
Result := module_resource_location (a_module, a_resource)
|
|
if not ut.file_path_exists (Result) then
|
|
Result := Void
|
|
end
|
|
end
|
|
end
|
|
|
|
module_theme_resource_location_by_name (a_module_name: READABLE_STRING_GENERAL; a_resource: PATH): detachable PATH
|
|
-- Theme resource location of `a_resource' for module named `a_module_name', if exists.
|
|
-- By default, located under the module location folder, but could be overriden
|
|
-- from files located under modules subfolder of active `theme_location'.
|
|
--| First search in themes/$theme/modules/$a_module.name/$a_resource,
|
|
--| and if not found then search in
|
|
--| modules/$a_module_name/$a_resource.
|
|
local
|
|
ut: FILE_UTILITIES
|
|
do
|
|
-- Check first in selected theme folder.
|
|
Result := module_theme_location_by_name (a_module_name).extended_path (a_resource)
|
|
if not ut.file_path_exists (Result) then
|
|
-- And if not found, look into site/modules/$a_module.name/.... folders.
|
|
Result := module_resource_location_by_name (a_module_name, a_resource)
|
|
if not ut.file_path_exists (Result) then
|
|
Result := Void
|
|
end
|
|
end
|
|
end
|
|
|
|
module_theme_location (a_module: CMS_MODULE): PATH
|
|
-- Location for overriden files associated with `a_module_name'.
|
|
do
|
|
Result := module_theme_location_by_name (a_module.name)
|
|
end
|
|
|
|
module_theme_location_by_name (a_module_name: READABLE_STRING_GENERAL): PATH
|
|
-- Location for overriden files associated with `a_module_name'.
|
|
do
|
|
Result := theme_location.extended ("modules").extended (a_module_name)
|
|
end
|
|
|
|
feature -- Access: active user
|
|
|
|
user_is_authenticated: BOOLEAN
|
|
-- Is user authenticated?
|
|
do
|
|
Result := user /= Void
|
|
ensure
|
|
Result implies user /= Void
|
|
end
|
|
|
|
user: detachable CMS_USER
|
|
-- Current user or Void in case of visitor.
|
|
note
|
|
EIS: "eiffel:?class=CMS_BASIC_AUTH_FILTER&feature=execute"
|
|
do
|
|
Result := current_user (request)
|
|
end
|
|
|
|
set_user (a_user: CMS_USER)
|
|
-- Set `a_user' as current `user'.
|
|
require
|
|
a_user_attached: a_user /= Void
|
|
do
|
|
set_current_user (request, a_user)
|
|
end
|
|
|
|
unset_user
|
|
-- Unset `user'.
|
|
do
|
|
unset_current_user (request)
|
|
end
|
|
|
|
record_user_login (a_user: CMS_USER)
|
|
-- Record login event for `a_user'.
|
|
require
|
|
user_has_id: a_user.has_id
|
|
do
|
|
a_user.set_last_login_date_now
|
|
user_api.update_user (a_user)
|
|
end
|
|
|
|
feature -- Site builtin variables
|
|
|
|
builtin_variables: STRING_TABLE [detachable ANY]
|
|
-- Builtin variables , value indexed by name.
|
|
do
|
|
create Result.make (7)
|
|
|
|
Result["site_url"] := site_url
|
|
Result["site_email"] := setup.site_email
|
|
Result["site_name"] := setup.site_name
|
|
if attached user as l_user then
|
|
Result["active_user"] := l_user
|
|
Result["user"] := l_user.name
|
|
Result["user_id"] := l_user.id
|
|
Result["user_profile_name"] := user_api.user_display_name (l_user)
|
|
end
|
|
end
|
|
|
|
feature -- Request utilities
|
|
|
|
execution_variable (a_name: READABLE_STRING_GENERAL): detachable ANY
|
|
-- Execution variable related to `a_name'
|
|
require
|
|
a_name_valid: a_name /= Void and then not a_name.is_empty
|
|
do
|
|
Result := request.execution_variable (a_name)
|
|
end
|
|
|
|
set_execution_variable (a_name: READABLE_STRING_GENERAL; a_value: detachable ANY)
|
|
do
|
|
request.set_execution_variable (a_name, a_value)
|
|
ensure
|
|
param_set: execution_variable (a_name) = a_value
|
|
end
|
|
|
|
unset_execution_variable (a_name: READABLE_STRING_GENERAL)
|
|
do
|
|
request.unset_execution_variable (a_name)
|
|
ensure
|
|
param_unset: execution_variable (a_name) = Void
|
|
end
|
|
|
|
|
|
feature {CMS_API_ACCESS, CMS_RESPONSE, CMS_MODULE} -- Request utilities
|
|
|
|
current_user (req: WSF_REQUEST): detachable CMS_USER
|
|
-- Current user or Void in case of Guest user.
|
|
do
|
|
check req = request end
|
|
if attached {CMS_USER} execution_variable (cms_execution_variable_name ("user")) as l_user then
|
|
Result := l_user
|
|
end
|
|
end
|
|
|
|
set_current_user (req: WSF_REQUEST; a_user: CMS_USER)
|
|
-- Set `a_user' as `current_user'.
|
|
do
|
|
check req = request end
|
|
set_execution_variable (cms_execution_variable_name ("user"), a_user)
|
|
ensure
|
|
user_set: current_user (req) ~ a_user
|
|
end
|
|
|
|
unset_current_user (req: WSF_REQUEST)
|
|
-- Unset current user.
|
|
do
|
|
check req = request end
|
|
req.unset_execution_variable (cms_execution_variable_name ("user"))
|
|
ensure
|
|
user_unset: current_user (req) = Void
|
|
end
|
|
|
|
feature {NONE} -- Implementation: current user
|
|
|
|
cms_execution_variable_name (a_name: READABLE_STRING_GENERAL): READABLE_STRING_GENERAL
|
|
-- Execution variable name for `a_name'.
|
|
local
|
|
s32: STRING_32
|
|
do
|
|
create s32.make_from_string_general (once "_roccms_.")
|
|
s32.append_string_general (a_name)
|
|
Result := s32
|
|
end
|
|
|
|
note
|
|
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
|
end
|
|
|