- now, the CMS_PAGE_MODULE has to be declared in the related CMS_SETUP via CMS_EXECUTION. (See demo for example) Improved the export facilities. Implemented blog and page export. Added import facilities. Implemented blog and page import. Improved node revision web interface (allow to edit a past revision, in order to restore it as latest revisionm i.e current). Removed specific tag from blog module, and reuse the taxonomy module for that purpose. Added WIKITEXT module that provide a WIKITEXT_FILTER, so now we can have wikitext content. - for now, no support for wiki links such as [[Foobar]].
367 lines
9.2 KiB
Plaintext
367 lines
9.2 KiB
Plaintext
note
|
|
description: "[
|
|
API to manage CMS Nodes
|
|
]"
|
|
date: "$Date: 2015-02-13 13:08:13 +0100 (ven., 13 févr. 2015) $"
|
|
revision: "$Revision: 96616 $"
|
|
|
|
class
|
|
CMS_NODE_API
|
|
|
|
inherit
|
|
CMS_MODULE_API
|
|
|
|
REFACTORING_HELPER
|
|
|
|
create {CMS_NODE_MODULE}
|
|
make_with_storage
|
|
|
|
feature {NONE} -- Initialization
|
|
|
|
make_with_storage (a_api: CMS_API; a_node_storage: CMS_NODE_STORAGE_I)
|
|
do
|
|
node_storage := a_node_storage
|
|
make (a_api)
|
|
-- error_handler.add_synchronization (a_node_storage.error_handler)
|
|
end
|
|
|
|
feature {CMS_MODULE} -- Access nodes storage.
|
|
|
|
node_storage: CMS_NODE_STORAGE_I
|
|
|
|
feature -- Content type
|
|
|
|
add_node_type (a_type: CMS_NODE_TYPE [CMS_NODE])
|
|
-- Register node content type `a_type'.
|
|
do
|
|
cms_api.add_content_type (a_type)
|
|
end
|
|
|
|
node_types: ARRAYED_LIST [attached like node_type]
|
|
-- Node content types.
|
|
do
|
|
create Result.make (cms_api.content_types.count)
|
|
across
|
|
cms_api.content_types as ic
|
|
loop
|
|
if attached {like node_type} ic.item as l_node_type then
|
|
Result.extend (l_node_type)
|
|
end
|
|
end
|
|
end
|
|
|
|
node_type (a_name: READABLE_STRING_GENERAL): detachable CMS_NODE_TYPE [CMS_NODE]
|
|
-- Content type named `a_named' if any.
|
|
do
|
|
across
|
|
cms_api.content_types as ic
|
|
until
|
|
Result /= Void
|
|
loop
|
|
if
|
|
attached {like node_type} ic.item as l_node_type and then
|
|
a_name.is_case_insensitive_equal (l_node_type.name)
|
|
then
|
|
Result := l_node_type
|
|
end
|
|
end
|
|
end
|
|
|
|
node_type_for (a_node: CMS_NODE): like node_type
|
|
-- Content type for node `a_node' if any.
|
|
local
|
|
l_type_name: READABLE_STRING_8
|
|
do
|
|
l_type_name := a_node.content_type
|
|
Result := node_type (l_type_name)
|
|
end
|
|
|
|
feature -- Content type webform
|
|
|
|
content_type_webform_managers: ARRAYED_LIST [CMS_CONTENT_TYPE_WEBFORM_MANAGER [CMS_CONTENT]]
|
|
-- Available content types
|
|
do
|
|
Result := cms_api.content_type_webform_managers
|
|
end
|
|
|
|
add_node_type_webform_manager (a_manager: CMS_NODE_TYPE_WEBFORM_MANAGER [CMS_NODE])
|
|
-- Register webform manager `a_manager'.
|
|
do
|
|
cms_api.add_content_type_webform_manager (a_manager)
|
|
end
|
|
|
|
node_type_webform_manager (a_node_type: CMS_CONTENT_TYPE): detachable CMS_NODE_TYPE_WEBFORM_MANAGER_I [CMS_NODE]
|
|
-- Web form manager for node type `a_node_type' if any.
|
|
local
|
|
l_type_name: READABLE_STRING_GENERAL
|
|
do
|
|
l_type_name := a_node_type.name
|
|
across
|
|
content_type_webform_managers as ic
|
|
until
|
|
Result /= Void
|
|
loop
|
|
if
|
|
attached {like node_type_webform_manager} ic.item as l_manager and then
|
|
l_type_name.is_case_insensitive_equal (l_manager.name)
|
|
then
|
|
Result := l_manager
|
|
end
|
|
end
|
|
end
|
|
|
|
feature -- URL
|
|
|
|
new_content_path (ct: detachable CMS_CONTENT_TYPE): STRING
|
|
-- URI path for new content of type `ct'
|
|
-- or URI of path for selection of new content possibilities if ct is Void.
|
|
do
|
|
if ct /= Void then
|
|
Result := "node/add/" + ct.name
|
|
else
|
|
Result := "node/"
|
|
end
|
|
end
|
|
|
|
node_link (a_node: CMS_NODE): CMS_LOCAL_LINK
|
|
-- CMS link for node `a_node'.
|
|
require
|
|
a_node.has_id
|
|
do
|
|
create Result.make (a_node.title, cms_api.location_alias (node_path (a_node)))
|
|
end
|
|
|
|
node_path (a_node: CMS_NODE): STRING
|
|
-- URI path for node `a_node'.
|
|
-- using the /node/{nid} url.
|
|
require
|
|
a_node.has_id
|
|
do
|
|
Result := "node/" + a_node.id.out
|
|
end
|
|
|
|
nodes_path: STRING
|
|
-- URI path for list of nodes.
|
|
do
|
|
Result := "nodes"
|
|
end
|
|
|
|
feature -- Access: Node
|
|
|
|
nodes_count: NATURAL_64
|
|
do
|
|
Result := node_storage.nodes_count
|
|
end
|
|
|
|
nodes: LIST [CMS_NODE]
|
|
-- List of nodes.
|
|
do
|
|
Result := node_storage.nodes
|
|
end
|
|
|
|
node_revisions (a_node: CMS_NODE): LIST [CMS_NODE]
|
|
-- List of revisions for node `a_node'.
|
|
do
|
|
Result := node_storage.node_revisions (a_node)
|
|
Result := full_nodes (Result)
|
|
end
|
|
|
|
trashed_nodes (a_user: detachable CMS_USER): LIST [CMS_NODE]
|
|
-- List of nodes with status in {CMS_NODE_API}.trashed.
|
|
-- if `a_user' is set, return nodes related to this user.
|
|
do
|
|
Result := node_storage.trashed_nodes (a_user)
|
|
end
|
|
|
|
recent_nodes (params: CMS_DATA_QUERY_PARAMETERS): ITERABLE [CMS_NODE]
|
|
-- List of most recent nodes according to `params.offset' and `params.size'.
|
|
do
|
|
Result := node_storage.recent_nodes (params.offset.to_integer_32, params.size.to_integer_32)
|
|
end
|
|
|
|
recent_node_changes_before (params: CMS_DATA_QUERY_PARAMETERS; a_date: DATE_TIME): ITERABLE [CMS_NODE]
|
|
-- List of recent changes, before `a_date', according to `params' settings.
|
|
do
|
|
Result := node_storage.recent_node_changes_before (params.offset.to_integer_32, params.size.to_integer_32, a_date)
|
|
end
|
|
|
|
node (a_id: INTEGER_64): detachable CMS_NODE
|
|
-- Node by ID.
|
|
do
|
|
debug ("refactor_fixme")
|
|
fixme ("Check preconditions")
|
|
end
|
|
Result := safe_full_node (node_storage.node_by_id (a_id))
|
|
end
|
|
|
|
revision_node (a_node_id: INTEGER_64; a_revision_id: INTEGER_64): detachable CMS_NODE
|
|
do
|
|
Result := safe_full_node (node_storage.node_by_id_and_revision (a_node_id, a_revision_id))
|
|
end
|
|
|
|
safe_full_node (a_node: detachable CMS_NODE): detachable CMS_NODE
|
|
do
|
|
if a_node /= Void then
|
|
Result := full_node (a_node)
|
|
end
|
|
end
|
|
|
|
full_node (a_node: CMS_NODE): CMS_NODE
|
|
-- If `a_node' is partial, return the full node from `a_node',
|
|
-- otherwise return directly `a_node'.
|
|
require
|
|
a_node_set: a_node /= Void
|
|
do
|
|
if attached {CMS_PARTIAL_NODE} a_node as l_partial_node then
|
|
if attached node_type_for (l_partial_node) as ct then
|
|
Result := ct.new_node (l_partial_node)
|
|
node_storage.fill_node (Result)
|
|
else
|
|
Result := l_partial_node
|
|
end
|
|
-- Update link with aliasing.
|
|
if Result /= Void and then Result.has_id then
|
|
Result.set_link (node_link (Result))
|
|
end
|
|
else
|
|
Result := a_node
|
|
if Result.has_id and Result.link = Void then
|
|
Result.set_link (node_link (Result))
|
|
end
|
|
end
|
|
check has_link: Result.has_id implies attached Result.link as lnk and then lnk.location.same_string (node_link (Result).location) 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
|
|
|
|
full_nodes (a_nodes: LIST [CMS_NODE]): LIST [CMS_NODE]
|
|
-- Convert list of nodes into a list of nodes when possible.
|
|
do
|
|
create {ARRAYED_LIST [CMS_NODE]} Result.make (a_nodes.count)
|
|
|
|
across
|
|
a_nodes as ic
|
|
loop
|
|
if attached full_node (ic.item) as l_full then
|
|
Result.force (l_full)
|
|
end
|
|
end
|
|
end
|
|
|
|
is_author_of_node (u: CMS_USER; a_node: CMS_NODE): BOOLEAN
|
|
-- Is the user `u' owner of the node `n'.
|
|
do
|
|
Result := u.same_as (a_node.author)
|
|
end
|
|
|
|
nodes_of_type (a_node_type: CMS_CONTENT_TYPE): LIST [CMS_NODE]
|
|
-- List of nodes of type `a_node_type'.
|
|
do
|
|
Result := node_storage.nodes_of_type (a_node_type)
|
|
ensure
|
|
expected_type: across Result as ic all ic.item.content_type.same_string (a_node_type.name) end
|
|
end
|
|
|
|
nodes_of_type_with_title (a_node_type: CMS_CONTENT_TYPE; a_title: READABLE_STRING_GENERAL): LIST [CMS_NODE]
|
|
do
|
|
Result := node_storage.nodes_of_type_with_title (a_node_type, a_title)
|
|
end
|
|
|
|
feature -- Permission Scope: Node
|
|
|
|
has_permission_for_action_on_node (a_action: READABLE_STRING_8; a_node: CMS_NODE; a_user: detachable CMS_USER; ): BOOLEAN
|
|
-- Has permission to execute action `a_action' on node `a_node', by eventual user `a_user'?
|
|
local
|
|
l_type_name: READABLE_STRING_8
|
|
do
|
|
l_type_name := a_node.content_type
|
|
Result := cms_api.user_has_permission (a_user, a_action + " any " + l_type_name)
|
|
if not Result and a_user /= Void then
|
|
if is_author_of_node (a_user, a_node) then
|
|
Result := cms_api.user_has_permission (a_user, a_action + " own " + l_type_name)
|
|
end
|
|
end
|
|
end
|
|
|
|
feature -- Change: Node
|
|
|
|
save_node (a_node: CMS_NODE)
|
|
-- Save `a_node'.
|
|
do
|
|
reset_error
|
|
node_storage.save_node (a_node)
|
|
error_handler.append (node_storage.error_handler)
|
|
end
|
|
|
|
new_node (a_node: CMS_NODE)
|
|
-- Add a new node `a_node'
|
|
require
|
|
no_id: not a_node.has_id
|
|
do
|
|
reset_error
|
|
node_storage.new_node (a_node)
|
|
error_handler.append (node_storage.error_handler)
|
|
end
|
|
|
|
delete_node (a_node: CMS_NODE)
|
|
-- Delete `a_node'.
|
|
--! remove the node from the storage.
|
|
do
|
|
reset_error
|
|
if a_node.has_id then
|
|
node_storage.delete_node (a_node)
|
|
error_handler.append (node_storage.error_handler)
|
|
end
|
|
end
|
|
|
|
update_node (a_node: CMS_NODE)
|
|
-- Update node `a_node' data.
|
|
do
|
|
reset_error
|
|
node_storage.update_node (a_node)
|
|
error_handler.append (node_storage.error_handler)
|
|
end
|
|
|
|
trash_node (a_node: CMS_NODE)
|
|
-- Trash node `a_node'.
|
|
-- Soft delete
|
|
do
|
|
reset_error
|
|
node_storage.trash_node (a_node)
|
|
error_handler.append (node_storage.error_handler)
|
|
end
|
|
|
|
restore_node (a_node: CMS_NODE)
|
|
-- Restore node `a_node'.
|
|
-- From {CMS_NODE_API}.trashed to {CMS_NODE_API}.not_published.
|
|
do
|
|
reset_error
|
|
node_storage.restore_node (a_node)
|
|
error_handler.append (node_storage.error_handler)
|
|
end
|
|
|
|
feature -- Node status
|
|
|
|
Not_published: INTEGER = 0
|
|
-- The node is not published.
|
|
|
|
Published: INTEGER = 1
|
|
-- The node is published.
|
|
|
|
Trashed: INTEGER = -1
|
|
-- The node is trashed (soft delete), ready to be deleted/destroyed from storage.
|
|
|
|
end
|