Implemented CMS storage for user and nodes.
Implemented role and permission storage.
Introduced the CMS_PARTIAL_NODE and CMS_PARTIAL_USER.
Added support for node storage extension
- storage of data specific to each node content type,
- in addition to the core CMS_NODE)
- For now, only implemented for SQL storage.
Note: in current version, CMS_PAGE support is hard coded in the core,
(as opposed to be only supported by the node module.)
Commented/removed for now, the Web API code to update node summary, title, via REST request.
This commit is contained in:
@@ -21,8 +21,6 @@ feature -- Basic operations
|
||||
local
|
||||
l_auth: HTTP_AUTHORIZATION
|
||||
do
|
||||
-- We can inherit from SHARED_LOGGER and write
|
||||
-- write_debug_log ...
|
||||
api.logger.put_debug (generator + ".execute ", Void)
|
||||
create l_auth.make (req.http_authorization)
|
||||
if attached req.raw_header_data as l_raw_data then
|
||||
|
||||
@@ -7,7 +7,6 @@ deferred class
|
||||
CMS_MODULE
|
||||
|
||||
inherit
|
||||
|
||||
REFACTORING_HELPER
|
||||
|
||||
feature -- Access
|
||||
@@ -27,6 +26,39 @@ feature -- Access
|
||||
version: STRING
|
||||
-- Version od the module?
|
||||
|
||||
feature {CMS_API} -- Module Initialization
|
||||
|
||||
initialize (api: CMS_API)
|
||||
-- Initialize Current module with `api'.
|
||||
require
|
||||
is_enabled: is_enabled
|
||||
do
|
||||
-- Redefine to process specific module initialization.
|
||||
end
|
||||
|
||||
feature {CMS_API} -- Module management
|
||||
|
||||
is_installed (api: CMS_API): BOOLEAN
|
||||
-- Is Current module installed?
|
||||
do
|
||||
Result := is_enabled
|
||||
-- FIXME: implement proper installation status.
|
||||
end
|
||||
|
||||
install (api: CMS_API)
|
||||
require
|
||||
is_not_installed: not is_installed (api)
|
||||
do
|
||||
-- Not Yet Supported
|
||||
end
|
||||
|
||||
uninstall (api: CMS_API)
|
||||
require
|
||||
is_installed: is_installed (api)
|
||||
do
|
||||
-- Not Yet Supported
|
||||
end
|
||||
|
||||
feature -- Router
|
||||
|
||||
router (a_api: CMS_API): WSF_ROUTER
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
note
|
||||
description: "Summary description for {CMS_NODE_API}."
|
||||
author: ""
|
||||
description: "[
|
||||
API to manage CMS Nodes
|
||||
]"
|
||||
date: "$Date: 2015-02-13 13:08:13 +0100 (ven., 13 févr. 2015) $"
|
||||
revision: "$Revision: 96616 $"
|
||||
|
||||
@@ -9,12 +10,55 @@ class
|
||||
|
||||
inherit
|
||||
CMS_MODULE_API
|
||||
redefine
|
||||
initialize
|
||||
end
|
||||
|
||||
REFACTORING_HELPER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
initialize
|
||||
-- <Precursor>
|
||||
do
|
||||
Precursor
|
||||
initialize_content_types
|
||||
end
|
||||
|
||||
initialize_content_types
|
||||
-- Initialize content type system.
|
||||
do
|
||||
create content_types.make (1)
|
||||
add_content_type (create {CMS_PAGE_CONTENT_TYPE})
|
||||
end
|
||||
|
||||
feature -- Content type
|
||||
|
||||
content_types: ARRAYED_LIST [CMS_CONTENT_TYPE]
|
||||
-- Available content types
|
||||
|
||||
add_content_type (a_type: CMS_CONTENT_TYPE)
|
||||
do
|
||||
content_types.force (a_type)
|
||||
end
|
||||
|
||||
content_type (a_name: READABLE_STRING_GENERAL): detachable CMS_CONTENT_TYPE
|
||||
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 -- Access: Node
|
||||
|
||||
nodes_count: INTEGER_64
|
||||
@@ -40,7 +84,37 @@ feature -- Access: Node
|
||||
debug ("refactor_fixme")
|
||||
fixme ("Check preconditions")
|
||||
end
|
||||
Result := storage.node_by_id (a_id)
|
||||
Result := full_node (storage.node_by_id (a_id))
|
||||
end
|
||||
|
||||
full_node (a_node: detachable CMS_NODE): detachable CMS_NODE
|
||||
-- If `a_node' is partial, return the full node from `a_node',
|
||||
-- otherwise return directly `a_node'.
|
||||
do
|
||||
if attached {CMS_PARTIAL_NODE} a_node as l_partial_node then
|
||||
if attached content_type (l_partial_node.content_type) as ct then
|
||||
Result := ct.new_node (l_partial_node)
|
||||
storage.fill_node (Result)
|
||||
else
|
||||
Result := l_partial_node
|
||||
end
|
||||
else
|
||||
Result := a_node
|
||||
end
|
||||
|
||||
-- Update partial user if needed.
|
||||
if
|
||||
Result /= Void and then
|
||||
attached {CMS_PARTIAL_USER} Result.author as l_partial_author
|
||||
then
|
||||
if attached cms_api.user_api.user_by_id (l_partial_author.id) as l_author then
|
||||
Result.set_author (l_author)
|
||||
else
|
||||
check
|
||||
valid_author_id: False
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Change: Node
|
||||
@@ -67,32 +141,32 @@ feature -- Change: Node
|
||||
storage.update_node (a_node)
|
||||
end
|
||||
|
||||
update_node_title (a_user_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_title: READABLE_STRING_32)
|
||||
-- Update node title, with user identified by `a_id', with node id `a_node_id' and a new title `a_title'.
|
||||
do
|
||||
debug ("refactor_fixme")
|
||||
fixme ("Check preconditions")
|
||||
end
|
||||
storage.update_node_title (a_user_id, a_node_id, a_title)
|
||||
end
|
||||
-- update_node_title (a_user_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_title: READABLE_STRING_32)
|
||||
-- -- Update node title, with user identified by `a_id', with node id `a_node_id' and a new title `a_title'.
|
||||
-- do
|
||||
-- debug ("refactor_fixme")
|
||||
-- fixme ("Check preconditions")
|
||||
-- end
|
||||
-- storage.update_node_title (a_user_id, a_node_id, a_title)
|
||||
-- end
|
||||
|
||||
update_node_summary (a_user_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_summary: READABLE_STRING_32)
|
||||
-- Update node summary, with user identified by `a_user_id', with node id `a_node_id' and a new summary `a_summary'.
|
||||
do
|
||||
debug ("refactor_fixme")
|
||||
fixme ("Check preconditions")
|
||||
end
|
||||
storage.update_node_summary (a_user_id, a_node_id, a_summary)
|
||||
end
|
||||
-- update_node_summary (a_user_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_summary: READABLE_STRING_32)
|
||||
-- -- Update node summary, with user identified by `a_user_id', with node id `a_node_id' and a new summary `a_summary'.
|
||||
-- do
|
||||
-- debug ("refactor_fixme")
|
||||
-- fixme ("Check preconditions")
|
||||
-- end
|
||||
-- storage.update_node_summary (a_user_id, a_node_id, a_summary)
|
||||
-- end
|
||||
|
||||
update_node_content (a_user_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_content: READABLE_STRING_32)
|
||||
-- Update node content, with user identified by `a_user_id', with node id `a_node_id' and a new content `a_content'.
|
||||
do
|
||||
debug ("refactor_fixme")
|
||||
fixme ("Check preconditions")
|
||||
end
|
||||
storage.update_node_content (a_user_id, a_node_id, a_content)
|
||||
end
|
||||
-- update_node_content (a_user_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_content: READABLE_STRING_32)
|
||||
-- -- Update node content, with user identified by `a_user_id', with node id `a_node_id' and a new content `a_content'.
|
||||
-- do
|
||||
-- debug ("refactor_fixme")
|
||||
-- fixme ("Check preconditions")
|
||||
-- end
|
||||
-- storage.update_node_content (a_user_id, a_node_id, a_content)
|
||||
-- end
|
||||
|
||||
|
||||
end
|
||||
|
||||
95
src/modules/node/content_type/cms_page.e
Normal file
95
src/modules/node/content_type/cms_page.e
Normal file
@@ -0,0 +1,95 @@
|
||||
note
|
||||
description: "A page node."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_PAGE
|
||||
|
||||
inherit
|
||||
CMS_NODE
|
||||
redefine
|
||||
make_empty,
|
||||
import_node
|
||||
end
|
||||
|
||||
create
|
||||
make_empty,
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make_empty
|
||||
do
|
||||
Precursor
|
||||
end
|
||||
|
||||
feature {CMS_CONTENT_TYPE} -- Conversion
|
||||
|
||||
import_node (a_node: CMS_NODE)
|
||||
-- <Precursor>
|
||||
do
|
||||
Precursor (a_node)
|
||||
if attached {CMS_PAGE} a_node as l_page then
|
||||
set_parent (l_page)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
content_type: READABLE_STRING_8
|
||||
once
|
||||
Result := {CMS_PAGE_CONTENT_TYPE}.name
|
||||
end
|
||||
|
||||
feature -- Access: content
|
||||
|
||||
summary: detachable READABLE_STRING_8
|
||||
-- A short summary of the node.
|
||||
|
||||
content: detachable READABLE_STRING_8
|
||||
-- Content of the node.
|
||||
|
||||
format: detachable READABLE_STRING_8
|
||||
-- Format associated with `content' and `summary'.
|
||||
-- For example: text, mediawiki, html, etc
|
||||
|
||||
parent: detachable CMS_PAGE
|
||||
-- Eventual parent page.
|
||||
--| Used to describe a book structure.
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_content (a_content: like content; a_summary: like summary; a_format: like format)
|
||||
do
|
||||
content := a_content
|
||||
summary := a_summary
|
||||
format := a_format
|
||||
end
|
||||
|
||||
set_parent (a_page: detachable CMS_PAGE)
|
||||
-- Set `parent' to `a_page'
|
||||
require
|
||||
Current_is_not_parent_of_a_page: not is_parent_of (a_page)
|
||||
do
|
||||
parent := a_page
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
is_parent_of (a_page: detachable CMS_PAGE): BOOLEAN
|
||||
-- Is Current page, a parent of `a_page' ?
|
||||
do
|
||||
if
|
||||
a_page /= Void and then
|
||||
attached a_page.parent as l_parent
|
||||
then
|
||||
if l_parent.same_node (a_page) then
|
||||
Result := True
|
||||
else
|
||||
Result := is_parent_of (l_parent)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
32
src/modules/node/content_type/cms_page_content_type.e
Normal file
32
src/modules/node/content_type/cms_page_content_type.e
Normal file
@@ -0,0 +1,32 @@
|
||||
note
|
||||
description: "Summary description for {CMS_PAGE_CONTENT_TYPE}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_PAGE_CONTENT_TYPE
|
||||
|
||||
inherit
|
||||
CMS_CONTENT_TYPE
|
||||
|
||||
feature -- Access
|
||||
|
||||
name: STRING = "page"
|
||||
-- Internal name.
|
||||
|
||||
title: STRING_32 = "Page"
|
||||
-- Human readable name.
|
||||
|
||||
feature -- Factory
|
||||
|
||||
new_node (a_partial_node: detachable CMS_NODE): CMS_PAGE
|
||||
-- New node based on partial `a_partial_node', or from none.
|
||||
do
|
||||
create Result.make_empty
|
||||
if a_partial_node /= Void then
|
||||
Result.import_node (a_partial_node)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
17
src/modules/node/content_type/cms_partial_page.e
Normal file
17
src/modules/node/content_type/cms_partial_page.e
Normal file
@@ -0,0 +1,17 @@
|
||||
note
|
||||
description: "Summary description for {CMS_PARTIAL_PAGE}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_PARTIAL_PAGE
|
||||
|
||||
inherit
|
||||
CMS_PAGE
|
||||
|
||||
create
|
||||
make_empty,
|
||||
make
|
||||
|
||||
end
|
||||
240
src/modules/node/handler/experimental/node_resource_handler.e
Normal file
240
src/modules/node/handler/experimental/node_resource_handler.e
Normal file
@@ -0,0 +1,240 @@
|
||||
note
|
||||
description: "Node handler for the API."
|
||||
date: "$Date: 2015-02-13 13:08:13 +0100 (ven., 13 févr. 2015) $"
|
||||
revision: "$Revision: 96616 $"
|
||||
|
||||
class
|
||||
NODE_RESOURCE_HANDLER
|
||||
|
||||
inherit
|
||||
CMS_NODE_HANDLER
|
||||
|
||||
WSF_URI_HANDLER
|
||||
rename
|
||||
execute as uri_execute,
|
||||
new_mapping as new_uri_mapping
|
||||
end
|
||||
|
||||
WSF_URI_TEMPLATE_HANDLER
|
||||
rename
|
||||
execute as uri_template_execute,
|
||||
new_mapping as new_uri_template_mapping
|
||||
select
|
||||
new_uri_template_mapping
|
||||
end
|
||||
|
||||
WSF_RESOURCE_HANDLER_HELPER
|
||||
redefine
|
||||
do_get,
|
||||
do_post,
|
||||
do_put,
|
||||
do_delete
|
||||
end
|
||||
|
||||
REFACTORING_HELPER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- execute
|
||||
|
||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute request handler
|
||||
do
|
||||
execute_methods (req, res)
|
||||
end
|
||||
|
||||
uri_execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute request handler
|
||||
do
|
||||
execute (req, res)
|
||||
end
|
||||
|
||||
uri_template_execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute request handler
|
||||
do
|
||||
execute (req, res)
|
||||
end
|
||||
|
||||
feature -- HTTP Methods
|
||||
|
||||
do_get (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- <Precursor>
|
||||
local
|
||||
l_page: CMS_RESPONSE
|
||||
do
|
||||
-- Existing node
|
||||
if attached {WSF_STRING} req.path_parameter ("id") as l_id then
|
||||
if
|
||||
l_id.is_integer and then
|
||||
attached node_api.node (l_id.value.to_integer_64) as l_node
|
||||
then
|
||||
-- FIXME: there is a mix between CMS interface and API interface here.
|
||||
create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)
|
||||
l_page.add_variable (l_node, "node")
|
||||
l_page.execute
|
||||
else
|
||||
do_error (req, res, l_id)
|
||||
end
|
||||
else
|
||||
-- Factory
|
||||
new_node (req, res)
|
||||
end
|
||||
end
|
||||
|
||||
do_post (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- <Precursor>
|
||||
local
|
||||
u_node: CMS_NODE
|
||||
do
|
||||
to_implement ("Check user permissions!!!")
|
||||
if attached current_user (req) as l_user then
|
||||
if attached {WSF_STRING} req.path_parameter ("id") as l_id then
|
||||
if
|
||||
l_id.is_integer and then
|
||||
attached node_api.node (l_id.value.to_integer_64) as l_node
|
||||
then
|
||||
if attached {WSF_STRING} req.form_parameter ("method") as l_method then
|
||||
if l_method.is_case_insensitive_equal ("DELETE") then
|
||||
do_delete (req, res)
|
||||
elseif l_method.is_case_insensitive_equal ("PUT") then
|
||||
do_put (req, res)
|
||||
else
|
||||
(create {INTERNAL_SERVER_ERROR_CMS_RESPONSE}.make (req, res, api)).execute
|
||||
end
|
||||
end
|
||||
else
|
||||
do_error (req, res, l_id)
|
||||
end
|
||||
else
|
||||
-- New node
|
||||
-- FIXME !!!
|
||||
if attached {WSF_STRING} req.form_parameter ("type") as p_type then
|
||||
if attached node_api.content_type (p_type.value) as ct then
|
||||
end
|
||||
create {CMS_PARTIAL_NODE} u_node.make_empty (p_type.url_encoded_value)
|
||||
else
|
||||
create {CMS_PARTIAL_NODE} u_node.make_empty ("")
|
||||
end
|
||||
|
||||
update_node_from_data_form (req, u_node)
|
||||
u_node.set_author (l_user)
|
||||
node_api.new_node (u_node)
|
||||
redirect_to (req.absolute_script_url (""), res)
|
||||
end
|
||||
else
|
||||
send_access_denied (res)
|
||||
end
|
||||
end
|
||||
|
||||
do_put (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- <Precursor>
|
||||
do
|
||||
|
||||
if attached current_user (req) as l_user then
|
||||
if attached {WSF_STRING} req.path_parameter ("id") as l_id then
|
||||
if
|
||||
l_id.is_integer and then
|
||||
attached node_api.node (l_id.value.to_integer_64) as l_node
|
||||
then
|
||||
update_node_from_data_form (req, l_node)
|
||||
l_node.set_author (l_user)
|
||||
node_api.update_node (l_node)
|
||||
redirect_to (req.absolute_script_url (""), res)
|
||||
else
|
||||
do_error (req, res, l_id)
|
||||
end
|
||||
else
|
||||
(create {INTERNAL_SERVER_ERROR_CMS_RESPONSE}.make (req, res, api)).execute
|
||||
end
|
||||
else
|
||||
send_access_denied (res)
|
||||
end
|
||||
end
|
||||
|
||||
do_delete (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- <Precursor>
|
||||
do
|
||||
if attached current_user_name (req) then
|
||||
if attached {WSF_STRING} req.path_parameter ("id") as l_id then
|
||||
if
|
||||
l_id.is_integer and then
|
||||
attached node_api.node (l_id.integer_value) as l_node
|
||||
then
|
||||
node_api.delete_node (l_node)
|
||||
res.send (create {CMS_REDIRECTION_RESPONSE_MESSAGE}.make (req.absolute_script_url ("")))
|
||||
else
|
||||
do_error (req, res, l_id)
|
||||
end
|
||||
else
|
||||
(create {INTERNAL_SERVER_ERROR_CMS_RESPONSE}.make (req, res, api)).execute
|
||||
end
|
||||
else
|
||||
send_access_denied (res)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Error
|
||||
|
||||
do_error (req: WSF_REQUEST; res: WSF_RESPONSE; a_id: WSF_STRING)
|
||||
-- Handling error.
|
||||
local
|
||||
l_page: CMS_RESPONSE
|
||||
do
|
||||
create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)
|
||||
l_page.add_variable (req.absolute_script_url (req.path_info), "request")
|
||||
if a_id.is_integer then
|
||||
-- resource not found
|
||||
l_page.add_variable ("404", "code")
|
||||
l_page.set_status_code (404)
|
||||
else
|
||||
-- bad request
|
||||
l_page.add_variable ("400", "code")
|
||||
l_page.set_status_code (400)
|
||||
end
|
||||
l_page.execute
|
||||
end
|
||||
|
||||
feature {NONE} -- Node
|
||||
|
||||
new_node (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
local
|
||||
l_page: CMS_RESPONSE
|
||||
do
|
||||
if api.user_has_permission (current_user (req), "create node") then
|
||||
create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)
|
||||
l_page.execute
|
||||
else
|
||||
send_access_denied (res)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- {NONE} Form data
|
||||
|
||||
update_node_from_data_form (req: WSF_REQUEST; a_node: CMS_NODE)
|
||||
-- Extract request form data and build a object
|
||||
-- Node
|
||||
local
|
||||
l_title: detachable READABLE_STRING_32
|
||||
l_summary, l_content, l_format: detachable READABLE_STRING_8
|
||||
do
|
||||
if attached {WSF_STRING} req.form_parameter ("title") as p_title then
|
||||
l_title := p_title.value
|
||||
a_node.set_title (l_title)
|
||||
end
|
||||
if attached {WSF_STRING} req.form_parameter ("summary") as p_summary then
|
||||
l_summary := html_encoded (p_summary.value)
|
||||
end
|
||||
if attached {WSF_STRING} req.form_parameter ("content") as p_content then
|
||||
l_content := html_encoded (p_content.value)
|
||||
end
|
||||
if attached {WSF_STRING} req.form_parameter ("format") as p_format then
|
||||
l_format := p_format.url_encoded_value
|
||||
end
|
||||
if l_format = Void then
|
||||
l_format := a_node.format
|
||||
end
|
||||
a_node.set_content (l_content, l_summary, l_format)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,75 @@
|
||||
note
|
||||
description: "Request handler related to /nodes."
|
||||
date: "$Date: 2015-02-13 13:08:13 +0100 (ven., 13 févr. 2015) $"
|
||||
revision: "$Revision: 96616 $"
|
||||
|
||||
class
|
||||
NODE_RESOURCES_HANDLER
|
||||
|
||||
inherit
|
||||
CMS_NODE_HANDLER
|
||||
|
||||
WSF_URI_HANDLER
|
||||
rename
|
||||
new_mapping as new_uri_mapping
|
||||
end
|
||||
|
||||
WSF_RESOURCE_HANDLER_HELPER
|
||||
redefine
|
||||
do_get
|
||||
end
|
||||
|
||||
REFACTORING_HELPER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- execute
|
||||
|
||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute request handler
|
||||
do
|
||||
execute_methods (req, res)
|
||||
end
|
||||
|
||||
feature -- HTTP Methods
|
||||
|
||||
do_get (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- <Precursor>
|
||||
local
|
||||
l_page: CMS_RESPONSE
|
||||
s: STRING
|
||||
do
|
||||
-- At the moment the template is hardcoded, but we can
|
||||
-- get them from the configuration file and load them into
|
||||
-- the setup class.
|
||||
|
||||
create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)
|
||||
l_page.add_variable (node_api.nodes, "nodes")
|
||||
|
||||
|
||||
-- NOTE: for development purposes we have the following hardcode output.
|
||||
create s.make_from_string ("<p>Nodes:</p>")
|
||||
if attached node_api.nodes as lst then
|
||||
across
|
||||
lst as ic
|
||||
loop
|
||||
s.append ("<li>")
|
||||
s.append ("<a href=%"")
|
||||
s.append (req.script_url ("/node/" + ic.item.id.out))
|
||||
s.append ("%">")
|
||||
s.append (api.html_encoded (ic.item.title))
|
||||
s.append (" (")
|
||||
s.append (ic.item.id.out)
|
||||
s.append (")")
|
||||
s.append ("</a>")
|
||||
s.append ("</li>%N")
|
||||
end
|
||||
end
|
||||
|
||||
l_page.set_main_content (s)
|
||||
l_page.add_block (create {CMS_CONTENT_BLOCK}.make ("nodes_warning", Void, "/nodes/ is not yet fully implemented<br/>", Void), "highlighted")
|
||||
l_page.execute
|
||||
end
|
||||
|
||||
end
|
||||
@@ -62,15 +62,51 @@ feature -- HTTP Methods
|
||||
-- <Precursor>
|
||||
local
|
||||
l_page: CMS_RESPONSE
|
||||
s: STRING
|
||||
hdate: HTTP_DATE
|
||||
do
|
||||
-- Existing node
|
||||
if attached {WSF_STRING} req.path_parameter ("id") as l_id then
|
||||
if
|
||||
l_id.is_integer and then
|
||||
attached node_api.node (l_id.value.to_integer_64) as l_node
|
||||
attached {CMS_NODE} node_api.node (l_id.value.to_integer_64) as l_node
|
||||
then
|
||||
-- FIXME: there is a mix between CMS interface and API interface here.
|
||||
create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)
|
||||
l_page.add_variable (l_node, "node")
|
||||
|
||||
create s.make_empty
|
||||
s.append ("<h1 class=%"title%">")
|
||||
s.append (html_encoded (l_node.title))
|
||||
s.append ("</h1>")
|
||||
s.append ("<div class=%"info%"> ")
|
||||
if attached l_node.author as l_author then
|
||||
s.append (" by ")
|
||||
s.append (l_author.name)
|
||||
end
|
||||
if attached l_node.modification_date as l_modified then
|
||||
s.append (" (modified: ")
|
||||
create hdate.make_from_date_time (l_modified)
|
||||
s.append (hdate.yyyy_mmm_dd_string)
|
||||
s.append (")")
|
||||
end
|
||||
s.append ("</div>")
|
||||
if attached l_node.content as l_content then
|
||||
s.append ("<p class=%"content%">")
|
||||
s.append (api.formats.item (l_node.format).formatted_output (l_content))
|
||||
s.append ("</p>")
|
||||
end
|
||||
if attached {CMS_PAGE} l_node as l_node_page then
|
||||
if attached l_node_page.parent as l_parent_node then
|
||||
s.append ("<div>Parent page is ")
|
||||
s.append ("<a href=%"/node/" + l_parent_node.id.out + "%">")
|
||||
s.append (l_parent_node.title)
|
||||
s.append (" (#")
|
||||
s.append (l_parent_node.id.out)
|
||||
s.append (")</a></div>")
|
||||
end
|
||||
end
|
||||
l_page.set_main_content (s)
|
||||
l_page.execute
|
||||
else
|
||||
do_error (req, res, l_id)
|
||||
@@ -107,7 +143,15 @@ feature -- HTTP Methods
|
||||
end
|
||||
else
|
||||
-- New node
|
||||
create u_node.make ("", "", "")
|
||||
-- FIXME !!!
|
||||
if attached {WSF_STRING} req.form_parameter ("type") as p_type then
|
||||
if attached node_api.content_type (p_type.value) as ct then
|
||||
end
|
||||
create {CMS_PARTIAL_NODE} u_node.make_empty (p_type.url_encoded_value)
|
||||
else
|
||||
create {CMS_PARTIAL_NODE} u_node.make_empty ("")
|
||||
end
|
||||
|
||||
update_node_from_data_form (req, u_node)
|
||||
u_node.set_author (l_user)
|
||||
node_api.new_node (u_node)
|
||||
@@ -192,7 +236,7 @@ feature {NONE} -- Node
|
||||
local
|
||||
l_page: CMS_RESPONSE
|
||||
do
|
||||
if attached current_user_name (req) then
|
||||
if api.user_has_permission (current_user (req), "create node") then
|
||||
create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)
|
||||
l_page.execute
|
||||
else
|
||||
@@ -205,16 +249,27 @@ feature -- {NONE} Form data
|
||||
update_node_from_data_form (req: WSF_REQUEST; a_node: CMS_NODE)
|
||||
-- Extract request form data and build a object
|
||||
-- Node
|
||||
local
|
||||
l_title: detachable READABLE_STRING_32
|
||||
l_summary, l_content, l_format: detachable READABLE_STRING_8
|
||||
do
|
||||
if attached {WSF_STRING} req.form_parameter ("title") as l_title then
|
||||
a_node.set_title (l_title.value)
|
||||
if attached {WSF_STRING} req.form_parameter ("title") as p_title then
|
||||
l_title := p_title.value
|
||||
a_node.set_title (l_title)
|
||||
end
|
||||
if attached {WSF_STRING} req.form_parameter ("summary") as l_summary then
|
||||
a_node.set_summary (l_summary.value)
|
||||
if attached {WSF_STRING} req.form_parameter ("summary") as p_summary then
|
||||
l_summary := html_encoded (p_summary.value)
|
||||
end
|
||||
if attached {WSF_STRING} req.form_parameter ("content") as l_content then
|
||||
a_node.set_content (l_content.value)
|
||||
if attached {WSF_STRING} req.form_parameter ("content") as p_content then
|
||||
l_content := html_encoded (p_content.value)
|
||||
end
|
||||
if attached {WSF_STRING} req.form_parameter ("format") as p_format then
|
||||
l_format := p_format.url_encoded_value
|
||||
end
|
||||
if l_format = Void then
|
||||
l_format := a_node.format
|
||||
end
|
||||
a_node.set_content (l_content, l_summary, l_format)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -39,8 +39,7 @@ feature -- HTTP Methods
|
||||
local
|
||||
l_page: CMS_RESPONSE
|
||||
s: STRING
|
||||
l_user: CMS_USER
|
||||
l_node: CMS_NODE
|
||||
n: CMS_NODE
|
||||
do
|
||||
-- At the moment the template is hardcoded, but we can
|
||||
-- get them from the configuration file and load them into
|
||||
@@ -53,20 +52,23 @@ feature -- HTTP Methods
|
||||
-- NOTE: for development purposes we have the following hardcode output.
|
||||
create s.make_from_string ("<p>Nodes:</p>")
|
||||
if attached node_api.nodes as lst then
|
||||
s.append ("<ul class=%"cms-nodes%">%N")
|
||||
across
|
||||
lst as ic
|
||||
loop
|
||||
s.append ("<li>")
|
||||
n := ic.item
|
||||
s.append ("<li class=%"cms_type_"+ n.content_type +"%">")
|
||||
s.append ("<a href=%"")
|
||||
s.append (req.script_url ("/node/" + ic.item.id.out))
|
||||
s.append (req.script_url ("/node/" + n.id.out))
|
||||
s.append ("%">")
|
||||
s.append (api.html_encoded (ic.item.title))
|
||||
s.append (api.html_encoded (n.title))
|
||||
s.append (" (")
|
||||
s.append (ic.item.id.out)
|
||||
s.append (n.id.out)
|
||||
s.append (")")
|
||||
s.append ("</a>")
|
||||
s.append ("</li>%N")
|
||||
end
|
||||
s.append ("</ul>%N")
|
||||
end
|
||||
|
||||
l_page.set_main_content (s)
|
||||
|
||||
@@ -10,14 +10,16 @@ inherit
|
||||
|
||||
CMS_MODULE
|
||||
redefine
|
||||
register_hooks
|
||||
register_hooks,
|
||||
initialize,
|
||||
is_installed,
|
||||
install
|
||||
end
|
||||
|
||||
CMS_HOOK_MENU_SYSTEM_ALTER
|
||||
|
||||
CMS_HOOK_BLOCK
|
||||
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
@@ -36,6 +38,59 @@ feature {NONE} -- Initialization
|
||||
config: CMS_SETUP
|
||||
-- Node configuration.
|
||||
|
||||
feature {CMS_API} -- Module Initialization
|
||||
|
||||
initialize (api: CMS_API)
|
||||
-- <Precursor>
|
||||
do
|
||||
Precursor (api)
|
||||
if attached {CMS_NODE_STORAGE_SQL} api.storage as l_sql_storage then
|
||||
l_sql_storage.register_node_storage_extension (create {CMS_NODE_STORAGE_SQL_PAGE_EXTENSION}.make (l_sql_storage))
|
||||
else
|
||||
-- FIXME: maybe provide a default solution based on file system, when no SQL storage is available.
|
||||
end
|
||||
end
|
||||
|
||||
feature {CMS_API} -- Module management
|
||||
|
||||
is_installed (api: CMS_API): BOOLEAN
|
||||
-- Is Current module installed?
|
||||
do
|
||||
if attached {CMS_STORAGE_SQL} api.storage as l_sql_storage then
|
||||
Result := l_sql_storage.sql_table_exists ("nodes") and
|
||||
l_sql_storage.sql_table_exists ("page_nodes")
|
||||
end
|
||||
end
|
||||
|
||||
install (api: CMS_API)
|
||||
local
|
||||
p1,p2: CMS_PAGE
|
||||
ct: CMS_PAGE_CONTENT_TYPE
|
||||
do
|
||||
-- Schema
|
||||
if attached {CMS_STORAGE_SQL} api.storage as l_sql_storage then
|
||||
l_sql_storage.sql_execute_file_script (api.setup.layout.path.extended ("scripts").extended (name).appended_with_extension ("sql"))
|
||||
end
|
||||
|
||||
-- Data
|
||||
-- FIXME: for test purpose, remove later
|
||||
if attached api.user_api.user_by_id (1) as u then
|
||||
create ct
|
||||
p1 := ct.new_node (Void)
|
||||
p1.set_title ("Welcome")
|
||||
p1.set_content ("Welcome, you are using the ROC Eiffel CMS", "Welcome Eiffel ROC user", Void) -- Use default format
|
||||
p1.set_author (u)
|
||||
api.storage.save_node (p1)
|
||||
|
||||
p2 := ct.new_node (Void)
|
||||
p2.set_title ("A new page example")
|
||||
p2.set_content ("This is the content of a page", "This is a new page", Void) -- Use default format
|
||||
p2.set_author (u)
|
||||
p2.set_parent (p1)
|
||||
api.storage.save_node (p2)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Access: router
|
||||
|
||||
router (a_api: CMS_API): WSF_ROUTER
|
||||
@@ -44,87 +99,119 @@ feature -- Access: router
|
||||
l_node_api: CMS_NODE_API
|
||||
do
|
||||
create l_node_api.make (a_api)
|
||||
create Result.make (5)
|
||||
configure_api_node (a_api, l_node_api, Result)
|
||||
configure_api_nodes (a_api, l_node_api, Result)
|
||||
configure_api_node_title (a_api, l_node_api, Result)
|
||||
configure_api_node_summary (a_api, l_node_api, Result)
|
||||
configure_api_node_content (a_api, l_node_api, Result)
|
||||
create Result.make (2)
|
||||
configure_cms (a_api, l_node_api, Result)
|
||||
-- configure_api (a_api, l_node_api, Result)
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation: routes
|
||||
|
||||
configure_api_node (a_api: CMS_API; a_node_api: CMS_NODE_API; a_router: WSF_ROUTER)
|
||||
configure_cms (a_api: CMS_API; a_node_api: CMS_NODE_API; a_router: WSF_ROUTER)
|
||||
local
|
||||
l_node_handler: NODE_HANDLER
|
||||
l_methods: WSF_REQUEST_METHODS
|
||||
do
|
||||
create l_node_handler.make (a_api, a_node_api)
|
||||
create l_methods
|
||||
l_methods.enable_get
|
||||
l_methods.enable_post
|
||||
l_methods.enable_put
|
||||
a_router.handle_with_request_methods ("/node", l_node_handler, l_methods)
|
||||
|
||||
create l_node_handler.make (a_api, a_node_api)
|
||||
create l_methods
|
||||
l_methods.enable_get
|
||||
l_methods.enable_post
|
||||
l_methods.enable_put
|
||||
l_methods.enable_delete
|
||||
a_router.handle_with_request_methods ("/node/{id}", l_node_handler, l_methods)
|
||||
-- a_router.handle_with_request_methods ("/nodes/", create {WSF_URI_AGENT_HANDLER}.make (agent do_get_nodes (?,?, a_api, a_node_api)), a_router.methods_get)
|
||||
end
|
||||
|
||||
configure_api_nodes (a_api: CMS_API; a_node_api: CMS_NODE_API; a_router: WSF_ROUTER)
|
||||
local
|
||||
l_edit_node_handler: NODE_HANDLER
|
||||
l_new_node_handler: NODE_HANDLER
|
||||
l_nodes_handler: NODES_HANDLER
|
||||
l_methods: WSF_REQUEST_METHODS
|
||||
do
|
||||
create l_node_handler.make (a_api, a_node_api)
|
||||
create l_methods
|
||||
l_methods.enable_get
|
||||
l_methods.enable_post
|
||||
l_methods.lock
|
||||
a_router.handle_with_request_methods ("/node", l_node_handler, l_methods)
|
||||
|
||||
create l_new_node_handler.make (a_api, a_node_api)
|
||||
a_router.handle_with_request_methods ("/node/new/{type}", create {WSF_URI_AGENT_HANDLER}.make (agent do_get_node_creation_by_type (?,?, "type", a_node_api)), a_router.methods_get)
|
||||
a_router.handle_with_request_methods ("/node/new", create {WSF_URI_AGENT_HANDLER}.make (agent do_get_node_creation_selection (?,?, a_api)), a_router.methods_get)
|
||||
|
||||
create l_edit_node_handler.make (a_api, a_node_api)
|
||||
a_router.handle_with_request_methods ("/node/{id}/edit", l_edit_node_handler, a_router.methods_get_post)
|
||||
|
||||
create l_node_handler.make (a_api, a_node_api)
|
||||
a_router.handle_with_request_methods ("/node/{id}", l_node_handler, a_router.methods_get_put_delete + a_router.methods_get_post)
|
||||
|
||||
-- Nodes
|
||||
create l_nodes_handler.make (a_api, a_node_api)
|
||||
create l_methods
|
||||
l_methods.enable_get
|
||||
a_router.handle_with_request_methods ("/nodes", l_nodes_handler, l_methods)
|
||||
end
|
||||
|
||||
configure_api_node_summary (a_api: CMS_API; a_node_api: CMS_NODE_API; a_router: WSF_ROUTER)
|
||||
local
|
||||
l_report_handler: NODE_SUMMARY_HANDLER
|
||||
l_methods: WSF_REQUEST_METHODS
|
||||
do
|
||||
create l_report_handler.make (a_api, a_node_api)
|
||||
create l_methods
|
||||
l_methods.enable_get
|
||||
l_methods.enable_post
|
||||
l_methods.enable_put
|
||||
a_router.handle_with_request_methods ("/node/{id}/field/summary", l_report_handler, l_methods)
|
||||
end
|
||||
-- configure_api (a_api: CMS_API; a_node_api: CMS_NODE_API; a_router: WSF_ROUTER)
|
||||
-- do
|
||||
-- configure_api_node (a_api, a_node_api, a_router)
|
||||
-- configure_api_nodes (a_api, a_node_api, a_router)
|
||||
-- configure_api_node_title (a_api, a_node_api, a_router)
|
||||
-- configure_api_node_summary (a_api, a_node_api, a_router)
|
||||
-- configure_api_node_content (a_api, a_node_api, a_router)
|
||||
-- end
|
||||
|
||||
configure_api_node_title (a_api: CMS_API; a_node_api: CMS_NODE_API; a_router: WSF_ROUTER)
|
||||
local
|
||||
l_report_handler: NODE_TITLE_HANDLER
|
||||
l_methods: WSF_REQUEST_METHODS
|
||||
do
|
||||
create l_report_handler.make (a_api, a_node_api)
|
||||
create l_methods
|
||||
l_methods.enable_get
|
||||
l_methods.enable_post
|
||||
l_methods.enable_put
|
||||
a_router.handle_with_request_methods ("/node/{id}/field/title", l_report_handler, l_methods)
|
||||
end
|
||||
feature {NONE} -- Implementation: routes
|
||||
|
||||
configure_api_node_content (a_api: CMS_API; a_node_api: CMS_NODE_API; a_router: WSF_ROUTER)
|
||||
local
|
||||
l_report_handler: NODE_CONTENT_HANDLER
|
||||
l_methods: WSF_REQUEST_METHODS
|
||||
do
|
||||
create l_report_handler.make (a_api, a_node_api)
|
||||
create l_methods
|
||||
l_methods.enable_get
|
||||
l_methods.enable_post
|
||||
l_methods.enable_put
|
||||
a_router.handle_with_request_methods ("/node/{id}/field/content", l_report_handler, l_methods)
|
||||
end
|
||||
-- configure_api_node (a_api: CMS_API; a_node_api: CMS_NODE_API; a_router: WSF_ROUTER)
|
||||
-- local
|
||||
-- l_node_handler: NODE_RESOURCE_HANDLER
|
||||
-- l_methods: WSF_REQUEST_METHODS
|
||||
-- do
|
||||
-- create l_node_handler.make (a_api, a_node_api)
|
||||
-- create l_methods
|
||||
-- l_methods.enable_get
|
||||
-- l_methods.enable_post
|
||||
-- l_methods.lock
|
||||
-- a_router.handle_with_request_methods ("/api/node", l_node_handler, l_methods)
|
||||
|
||||
-- create l_node_handler.make (a_api, a_node_api)
|
||||
-- a_router.handle_with_request_methods ("/api/node/{id}", l_node_handler, a_router.methods_get_put_delete + a_router.methods_get_post)
|
||||
-- end
|
||||
|
||||
-- configure_api_nodes (a_api: CMS_API; a_node_api: CMS_NODE_API; a_router: WSF_ROUTER)
|
||||
-- local
|
||||
-- l_nodes_handler: NODE_RESOURCES_HANDLER
|
||||
-- l_methods: WSF_REQUEST_METHODS
|
||||
-- do
|
||||
-- create l_nodes_handler.make (a_api, a_node_api)
|
||||
-- create l_methods
|
||||
-- l_methods.enable_get
|
||||
-- a_router.handle_with_request_methods ("/api/nodes", l_nodes_handler, l_methods)
|
||||
-- end
|
||||
|
||||
-- configure_api_node_summary (a_api: CMS_API; a_node_api: CMS_NODE_API; a_router: WSF_ROUTER)
|
||||
-- local
|
||||
-- l_report_handler: NODE_SUMMARY_HANDLER
|
||||
-- l_methods: WSF_REQUEST_METHODS
|
||||
-- do
|
||||
-- create l_report_handler.make (a_api, a_node_api)
|
||||
-- create l_methods
|
||||
-- l_methods.enable_get
|
||||
-- l_methods.enable_post
|
||||
-- l_methods.enable_put
|
||||
-- a_router.handle_with_request_methods ("/node/{id}/field/summary", l_report_handler, l_methods)
|
||||
-- end
|
||||
|
||||
-- configure_api_node_title (a_api: CMS_API; a_node_api: CMS_NODE_API; a_router: WSF_ROUTER)
|
||||
-- local
|
||||
-- l_report_handler: NODE_TITLE_HANDLER
|
||||
-- l_methods: WSF_REQUEST_METHODS
|
||||
-- do
|
||||
-- create l_report_handler.make (a_api, a_node_api)
|
||||
-- create l_methods
|
||||
-- l_methods.enable_get
|
||||
-- l_methods.enable_post
|
||||
-- l_methods.enable_put
|
||||
-- a_router.handle_with_request_methods ("/node/{id}/field/title", l_report_handler, l_methods)
|
||||
-- end
|
||||
|
||||
-- configure_api_node_content (a_api: CMS_API; a_node_api: CMS_NODE_API; a_router: WSF_ROUTER)
|
||||
-- local
|
||||
-- l_report_handler: NODE_CONTENT_HANDLER
|
||||
-- l_methods: WSF_REQUEST_METHODS
|
||||
-- do
|
||||
-- create l_report_handler.make (a_api, a_node_api)
|
||||
-- create l_methods
|
||||
-- l_methods.enable_get
|
||||
-- l_methods.enable_post
|
||||
-- l_methods.enable_put
|
||||
-- a_router.handle_with_request_methods ("/node/{id}/field/content", l_report_handler, l_methods)
|
||||
-- end
|
||||
|
||||
feature -- Hooks
|
||||
|
||||
@@ -156,4 +243,30 @@ feature -- Hooks
|
||||
a_menu_system.primary_menu.extend (lnk)
|
||||
end
|
||||
|
||||
feature -- Handler
|
||||
|
||||
do_get_node_creation_selection (req: WSF_REQUEST; res: WSF_RESPONSE; a_api: CMS_API)
|
||||
local
|
||||
l_page: NOT_IMPLEMENTED_ERROR_CMS_RESPONSE
|
||||
do
|
||||
create l_page.make (req, res, a_api)
|
||||
l_page.execute
|
||||
end
|
||||
|
||||
do_get_node_creation_by_type (req: WSF_REQUEST; res: WSF_RESPONSE; a_type_varname: READABLE_STRING_8; a_node_api: CMS_NODE_API)
|
||||
local
|
||||
l_page: NOT_IMPLEMENTED_ERROR_CMS_RESPONSE
|
||||
l_node: detachable CMS_NODE
|
||||
do
|
||||
create l_page.make (req, res, a_node_api.cms_api)
|
||||
if
|
||||
attached {WSF_STRING} req.path_parameter (a_type_varname) as p_type and then
|
||||
attached a_node_api.content_type (p_type.value) as ct
|
||||
then
|
||||
l_node := ct.new_node (Void)
|
||||
l_page.set_main_content (l_node.out)
|
||||
end
|
||||
l_page.execute
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user