Files
EWF/draft/application/cms/src/cms_execution.e
2013-03-01 12:55:26 +01:00

714 lines
15 KiB
Plaintext

note
description: "[
This is the execution of the cms handler request
It builds the content to get process to render the output
]"
deferred class
CMS_EXECUTION
inherit
CMS_COMMON_API
feature {NONE} -- Initialization
make (req: WSF_REQUEST; res: WSF_RESPONSE; a_service: like service)
do
status_code := {HTTP_STATUS_CODE}.ok
service := a_service
request := req
response := res
create header.make
initialize
end
initialize
do
is_front := service.is_front_page (request)
has_js := True -- by default it is true, check cookie to see if this is not supported.
if attached request.cookie ("has_js") as c_has_js then
has_js := c_has_js.same_string ("0")
end
get_theme
controller := service.session_controller (request)
create menu_system.make
create blocks.make (3)
if attached {like message} session_item (pending_messages_session_item_name) as m then
message := m
end
remove_session_item (pending_messages_session_item_name)
end
feature -- Access
service: CMS_SERVICE
request: WSF_REQUEST
feature {CMS_SESSION_CONTROLER} -- Access: restricted
response: WSF_RESPONSE
controller: CMS_SESSION_CONTROLER
pending_messages_session_item_name: STRING = "cms.pending_messages"
-- Session item name to get the pending messages.
feature -- Access: CMS
site_name: STRING_32
do
Result := service.site_name
end
front_page_url: READABLE_STRING_8
do
Result := url ("/", Void)
end
feature -- Permission
frozen has_permissions (lst: detachable ITERABLE [READABLE_STRING_8]): BOOLEAN
do
if lst = Void then
Result := True
else
Result := across lst as c all has_permission (c.item) end
end
end
frozen has_permission (s: detachable READABLE_STRING_8): BOOLEAN
-- Anonymous or Current `user' has permission for `s'
--| `s' could be "create page",
local
u: detachable CMS_USER
do
if s = Void then
Result := True
else
if s.same_string ("authenticated") then
Result := authenticated
else
u := user
if u /= Void and then u.is_admin then
Result := True
else
Result := service.user_has_permission (u, s)
end
end
end
end
feature -- Status
is_front: BOOLEAN
has_js: BOOLEAN
-- Client has javascript enabled?
-- FIXME: not yet implemented
is_mobile: BOOLEAN
-- Is Client on mobile device?
-- FIXME: not yet implemented
feature -- Theme
theme: CMS_THEME
get_theme
do
create {DEFAULT_CMS_THEME} theme.make (service)
end
feature -- Access: User
authenticated: BOOLEAN
do
Result := user /= Void
end
user: detachable CMS_USER
do
if attached {CMS_USER} session_item ("user") as u then
Result := u
end
end
last_user_access_date: detachable DATE_TIME
do
if attached {DATE_TIME} session_item ("last_access") as dt then
Result := dt
end
end
feature -- Element change: user
login (u: attached like user; req: WSF_REQUEST)
do
controller.start_session (req)
u.set_last_login_date_now
storage.save_user (u)
set_user (u)
init_last_user_access_date
log ("user", "user %"" + u.name + "%" signed in.", 0, user_local_link (u))
end
logout (req: WSF_REQUEST)
require
authenticated
do
if attached user as u then
log ("user", "user %"" + u.name + "%" signed out.", 0, user_local_link (u))
end
set_user (Void)
controller.start_session (req)
end
feature -- Logging
log (a_category: READABLE_STRING_8; a_message: READABLE_STRING_8; a_level: INTEGER; a_link: detachable CMS_LINK)
local
l_log: CMS_LOG
do
create l_log.make (a_category, a_message, a_level, Void)
if a_link /= Void then
l_log.set_link (a_link)
end
l_log.set_info (request.http_user_agent)
service.storage.save_log (l_log)
end
feature -- Menu
menu_system: CMS_MENU_SYSTEM
main_menu: CMS_MENU
do
Result := menu_system.main_menu
end
management_menu: CMS_MENU
do
Result := menu_system.management_menu
end
navigation_menu: CMS_MENU
do
Result := menu_system.navigation_menu
end
user_menu: CMS_MENU
do
Result := menu_system.user_menu
end
primary_tabs: CMS_MENU
do
Result := menu_system.primary_tabs
end
feature -- Menu: change
add_to_main_menu (lnk: CMS_LINK)
do
if attached {CMS_LOCAL_LINK} lnk as l_local then
l_local.get_is_active (request)
end
main_menu.extend (lnk)
end
add_to_menu (lnk: CMS_LINK; m: CMS_MENU)
do
if attached {CMS_LOCAL_LINK} lnk as l_local then
l_local.get_is_active (request)
end
m.extend (lnk)
end
feature -- Message
add_message (a_msg: READABLE_STRING_8; a_category: detachable READABLE_STRING_8)
local
m: like message
do
m := message
if m = Void then
create m.make (a_msg.count + 9)
message := m
end
if a_category /= Void then
m.append ("<li class=%""+ a_category +"%">")
else
m.append ("<li>")
end
m.append (a_msg + "</li>")
end
add_notice_message (a_msg: READABLE_STRING_8)
do
add_message (a_msg, "notice")
end
add_warning_message (a_msg: READABLE_STRING_8)
do
add_message (a_msg, "warning")
end
add_error_message (a_msg: READABLE_STRING_8)
do
add_message (a_msg, "error")
end
add_success_message (a_msg: READABLE_STRING_8)
do
add_message (a_msg, "success")
end
report_form_errors (fd: CMS_FORM_DATA)
require
has_error: not fd.is_valid
do
if attached fd.errors as errs then
across
errs as err
loop
if attached err.item as e then
if attached e.field as l_field then
if attached e.message as e_msg then
add_error_message (e_msg) --"Field [" + l_field.name + "] is invalid. " + e_msg)
else
add_error_message ("Field [" + l_field.name + "] is invalid.")
end
elseif attached e.message as e_msg then
add_error_message (e_msg)
end
end
end
end
end
message: detachable STRING_8
feature -- Blocks
formats: CMS_FORMATS
once
create Result
end
blocks: ARRAYED_LIST [TUPLE [block: CMS_BLOCK; name: READABLE_STRING_8; region: READABLE_STRING_8]]
add_block (b: CMS_BLOCK; a_region: detachable READABLE_STRING_8)
do
if a_region /= Void then
blocks.extend ([b, b.name, a_region])
elseif attached block_region (b) as l_region then
blocks.extend ([b, b.name, l_region])
end
end
block_region (b: CMS_BLOCK): detachable READABLE_STRING_8
local
l_name: READABLE_STRING_8
do
l_name := b.name
if l_name.starts_with ("footer") then
Result := "footer"
elseif l_name.starts_with ("management") then
Result := "first_sidebar"
elseif l_name.starts_with ("navigation") then
Result := "first_sidebar"
elseif l_name.starts_with ("user") then
Result := "first_sidebar"
else
Result := "first_sidebar"
end
-- FIXME: let the user choose ...
end
get_blocks
local
b: CMS_CONTENT_BLOCK
s: STRING_8
m: CMS_MENU
do
m := management_menu
if not m.is_empty then
add_block (create {CMS_MENU_BLOCK}.make (m), Void)
end
m := navigation_menu
if not m.is_empty then
add_block (create {CMS_MENU_BLOCK}.make (m), Void)
end
m := user_menu
if not m.is_empty then
add_block (create {CMS_MENU_BLOCK}.make (m), Void)
end
-- create s.make_empty
-- s.append ("This site demonstrates a first implementation of CMS using EWF.%N")
-- create b.make ("about", "About", s, formats.plain_text)
-- add_block (b, "second_sidebar")
create s.make_empty
s.append ("Made with <a href=%"http://www.eiffel.com/%">EWF</a>")
create b.make ("made_with", Void, s, formats.full_html)
add_block (b, "footer")
service.hook_block_view (Current)
end
feature -- Access
status_code: INTEGER
header: WSF_HEADER
title: detachable READABLE_STRING_32
-- HTML>head>title value
page_title: detachable READABLE_STRING_32
-- Page title
additional_page_head_lines: detachable LIST [READABLE_STRING_8]
-- HTML>head>...extra lines
main_content: detachable STRING_8
redirection: detachable READABLE_STRING_8
feature -- Generation
prepare_menu_system (a_menu_system: CMS_MENU_SYSTEM)
do
across
a_menu_system as c
loop
prepare_links (c.item)
end
end
prepare_links (a_menu: CMS_LINK_COMPOSITE)
local
to_remove: ARRAYED_LIST [CMS_LINK]
do
create to_remove.make (0)
across
a_menu as c
loop
if attached {CMS_LOCAL_LINK} c.item as lm then
if attached lm.permission_arguments as perms and then not has_permissions (perms) then
to_remove.force (lm)
else
-- if lm.permission_arguments is Void , this is permitted
lm.get_is_active (request)
if attached {CMS_LINK_COMPOSITE} lm as comp then
prepare_links (comp)
end
end
elseif attached {CMS_LINK_COMPOSITE} c.item as comp then
prepare_links (comp)
end
end
across
to_remove as c
loop
a_menu.remove (c.item)
end
end
prepare (page: CMS_HTML_PAGE)
local
s: STRING_8
do
if attached additional_page_head_lines as l_head_lines then
across
l_head_lines as hl
loop
page.head_lines.force (hl.item)
end
end
add_to_main_menu (create {CMS_LOCAL_LINK}.make ("Home", "/"))
service.call_menu_alter_hooks (menu_system, Current)
prepare_menu_system (menu_system)
get_blocks
if attached title as l_title then
page.set_title (l_title)
else
page.set_title ("CMS::" + request.path_info)
end
page.add_to_header_region (top_header_region)
page.add_to_header_region (header_region)
if attached message as m and then not m.is_empty then
page.add_to_content_region ("<div id=%"message%">" + m + "</div>")
end
page.add_to_content_region ("<a id=%"main-content%"></a>%N")
if attached page_title as l_page_title then
page.add_to_content_region ("<h1 id=%"page-title%" class=%"title%">"+ l_page_title +"</h1>%N")
end
if attached primary_tabs as tabs_menu and then not tabs_menu.is_empty then
page.add_to_content_region (theme.menu_html (tabs_menu, True))
end
page.add_to_content_region (content_region)
-- blocks
across
blocks as c
loop
if attached c.item as b_info then
create s.make_from_string ("<div class=%"block%" id=%"" + b_info.name + "%">")
if attached b_info.block.title as l_title then
s.append ("<div class=%"title%">" + html_encoded (l_title) + "</div>")
end
s.append ("<div class=%"inside%">")
s.append (b_info.block.to_html (theme))
s.append ("</div>")
s.append ("</div>")
page.add_to_region (s, b_info.region)
end
end
end
logo_location: STRING
do
Result := url ("/theme/logo.png", Void)
end
top_header_region: STRING_8
do
Result := "<a href=%""+ url ("/", Void) +"%"><img id=%"logo%" src=%"" + logo_location + "%"/></a><div id=%"title%">" + html_encoded (site_name) + "</div>"
Result.append ("<div id=%"menu-bar%">")
Result.append (theme.menu_html (main_menu, True))
Result.append ("</div>")
end
header_region: STRING_8
do
Result := ""
end
content_region: STRING_8
do
if attached main_content as l_content then
Result := l_content
else
Result := ""
debug
Result := "No Content"
end
end
end
feature -- Head customization
add_additional_head_line (s: READABLE_STRING_8; a_allow_duplication: BOOLEAN)
local
lst: like additional_page_head_lines
do
lst := additional_page_head_lines
if lst = Void then
create {ARRAYED_LIST [like additional_page_head_lines.item]} lst.make (1)
additional_page_head_lines := lst
end
if a_allow_duplication or else across lst as c all not c.item.same_string (s) end then
lst.extend (s)
end
end
add_style (a_href: STRING; a_media: detachable STRING)
local
s: STRING_8
do
s := "<link rel=%"stylesheet%" href=%""+ a_href + "%" type=%"text/css%""
if a_media /= Void then
s.append (" media=%""+ a_media + "%"")
end
s.append ("/>")
add_additional_head_line (s, False)
end
add_javascript_url (a_src: STRING)
local
s: STRING_8
do
s := "<script type=%"text/javascript%" src=%"" + a_src + "%"></script>"
add_additional_head_line (s, False)
end
add_javascript_content (a_script: STRING)
local
s: STRING_8
do
s := "<script type=%"text/javascript%">%N" + a_script + "%N</script>"
add_additional_head_line (s, True)
end
feature -- Element change
set_title (t: like title)
do
title := t
set_page_title (t)
end
set_page_title (t: like page_title)
do
page_title := t
end
set_main_content (s: like main_content)
do
main_content := s
end
set_redirection (a_url: like redirection)
do
if a_url /= Void and then a_url.same_string (request.path_info) and request.is_get_request_method then
redirection := Void
else
redirection := a_url
end
end
feature -- Execution
execute
do
begin
process
terminate
end
feature {NONE} -- Execution
begin
do
end
process
deferred
end
frozen terminate
local
cms_page: CMS_HTML_PAGE
page: CMS_HTML_PAGE_RESPONSE
do
create cms_page.make
prepare (cms_page)
create page.make (theme.page_html (cms_page))
if attached redirection as l_redirection then
if attached message as m then
set_session_item ("cms.pending_messages", m)
end
page.set_status_code ({HTTP_STATUS_CODE}.found)
page.header.put_location (l_redirection)
else
page.set_status_code (status_code)
end
controller.session_commit (page, Current)
response.send (page)
on_terminated
end
on_terminated
do
end
feature {NONE} -- Implementation
set_user (u: like user)
do
set_session_item ("user", u)
end
init_last_user_access_date
do
set_session_item ("last_access", (create {DATE_TIME}.make_now_utc))
end
session_item (k: READABLE_STRING_GENERAL): detachable ANY
do
Result := controller.session.item (k)
end
set_session_item (k: READABLE_STRING_GENERAL; v: detachable ANY)
do
controller.session.remember (v, k)
end
remove_session_item (k: READABLE_STRING_GENERAL)
do
controller.session.forget (k)
end
feature -- Storage
storage: CMS_STORAGE
do
Result := service.storage
end
feature -- Helper: output
user_local_link (u: CMS_USER): CMS_LINK
do
create {CMS_LOCAL_LINK} Result.make (u.name, user_url (u))
end
node_local_link (n: CMS_NODE): CMS_LINK
do
create {CMS_LOCAL_LINK} Result.make (n.title, node_url (n))
end
truncated_string (s: READABLE_STRING_8; nb: INTEGER; a_ellipsis: detachable READABLE_STRING_8): STRING_8
-- Truncated string `s' to `nb' character
require
a_ellipsis /= Void implies a_ellipsis.count < nb
local
f: CMS_NO_HTML_FILTER
do
if s.count <= nb then
Result := s.string
else
create f
create Result.make_from_string (s)
f.filter (Result)
if Result.count > nb then
if a_ellipsis /= Void and then not a_ellipsis.is_empty then
Result.keep_head (nb - a_ellipsis.count)
Result.append (a_ellipsis)
else
Result.keep_head (nb - 3)
Result.append ("...")
end
end
end
end
feature -- Helper: request
non_empty_string_path_parameter (a_name: READABLE_STRING_GENERAL): detachable STRING
do
if
attached {WSF_STRING} request.path_parameter (a_name) as p and then
not p.is_empty
then
Result := p.value
end
end
invariant
end