Extracted page support from cms_node_module, and add a proper CMS_PAGE_MODULE.
- 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]].
This commit is contained in:
95
modules/node/submodules/page/cms_page.e
Normal file
95
modules/node/submodules/page/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 -- 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.parent)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
content_type: READABLE_STRING_8
|
||||
once
|
||||
Result := {CMS_PAGE_NODE_TYPE}.name
|
||||
end
|
||||
|
||||
feature -- Access: content
|
||||
|
||||
summary: detachable READABLE_STRING_32
|
||||
-- A short summary of the node.
|
||||
|
||||
content: detachable READABLE_STRING_32
|
||||
-- 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
|
||||
172
modules/node/submodules/page/cms_page_api.e
Normal file
172
modules/node/submodules/page/cms_page_api.e
Normal file
@@ -0,0 +1,172 @@
|
||||
note
|
||||
description: "API to handle nodes of type page. Extends the node API."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_PAGE_API
|
||||
|
||||
inherit
|
||||
CMS_MODULE_API
|
||||
rename
|
||||
make as make_with_cms_api
|
||||
redefine
|
||||
initialize
|
||||
end
|
||||
|
||||
REFACTORING_HELPER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_api: CMS_API; a_node_api: CMS_NODE_API)
|
||||
-- (from CMS_MODULE_API)
|
||||
-- (export status {NONE})
|
||||
do
|
||||
node_api := a_node_api
|
||||
make_with_cms_api (a_api)
|
||||
end
|
||||
|
||||
initialize
|
||||
-- <Precursor>
|
||||
do
|
||||
Precursor
|
||||
|
||||
---- l_sql_node_storage.register_node_storage_extension (create {CMS_NODE_STORAGE_SQL_PAGE_EXTENSION}.make (l_node_api, l_sql_node_storage))
|
||||
|
||||
-- Create the node storage for type blog
|
||||
if attached storage.as_sql_storage as l_storage_sql then
|
||||
create {CMS_PAGE_STORAGE_SQL} page_storage.make (l_storage_sql)
|
||||
else
|
||||
create {CMS_PAGE_STORAGE_NULL} page_storage.make
|
||||
end
|
||||
|
||||
initialize_node_types
|
||||
end
|
||||
|
||||
initialize_node_types
|
||||
-- Initialize content type system.
|
||||
local
|
||||
ct: CMS_PAGE_NODE_TYPE
|
||||
do
|
||||
-- Initialize node content types.
|
||||
create ct
|
||||
page_content_type := ct
|
||||
--| For now, add all available formats to content type `ct'.
|
||||
across
|
||||
cms_api.formats as ic
|
||||
loop
|
||||
ct.extend_format (ic.item)
|
||||
end
|
||||
node_api.add_node_type (ct)
|
||||
node_api.add_node_type_webform_manager (create {CMS_PAGE_NODE_TYPE_WEBFORM_MANAGER}.make (ct, Current))
|
||||
end
|
||||
|
||||
feature {CMS_API_ACCESS, CMS_MODULE, CMS_API} -- Restricted access
|
||||
|
||||
node_api: CMS_NODE_API
|
||||
|
||||
page_content_type: CMS_PAGE_NODE_TYPE
|
||||
|
||||
feature -- Access
|
||||
|
||||
pages: LIST [CMS_PAGE]
|
||||
-- All pages.
|
||||
do
|
||||
Result := nodes_to_pages (node_api.nodes_of_type (page_content_type))
|
||||
end
|
||||
|
||||
pages_with_title (a_title: READABLE_STRING_GENERAL): LIST [CMS_PAGE]
|
||||
-- List of pages with title `a_title`.
|
||||
do
|
||||
Result := nodes_to_pages (node_api.nodes_of_type_with_title (page_content_type, a_title))
|
||||
end
|
||||
|
||||
feature -- Access: page/book outline
|
||||
|
||||
children (a_node: CMS_NODE): detachable LIST [CMS_NODE]
|
||||
-- Children of node `a_node'.
|
||||
-- note: this is the partial version of the nodes.
|
||||
do
|
||||
Result := page_storage.children (a_node)
|
||||
end
|
||||
|
||||
available_parents_for_node (a_node: CMS_NODE): LIST [CMS_NODE]
|
||||
-- Potential parent nodes for node `a_node'.
|
||||
-- Ensure no cycle exists.
|
||||
do
|
||||
create {ARRAYED_LIST [CMS_NODE]} Result.make (0)
|
||||
across page_storage.available_parents_for_node (a_node) as ic loop
|
||||
check distinct: not a_node.same_node (ic.item) end
|
||||
if not is_node_a_parent_of (a_node, ic.item) then
|
||||
Result.force (ic.item)
|
||||
end
|
||||
end
|
||||
ensure
|
||||
no_cycle: across Result as c all not is_node_a_parent_of (a_node, c.item) end
|
||||
end
|
||||
|
||||
is_node_a_parent_of (a_node: CMS_NODE; a_child: CMS_NODE): BOOLEAN
|
||||
-- Is `a_node' a direct or indirect parent of node `a_child'?
|
||||
require
|
||||
distinct_nodes: not a_node.same_node (a_child)
|
||||
do
|
||||
if
|
||||
attached {CMS_PAGE} node_api.full_node (a_child) as l_child_page and then
|
||||
attached l_child_page.parent as l_parent
|
||||
then
|
||||
if l_parent.same_node (a_node) then
|
||||
Result := True
|
||||
else
|
||||
Result := is_node_a_parent_of (a_node, l_parent)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Conversion
|
||||
|
||||
full_page_node (a_page: CMS_PAGE): CMS_PAGE
|
||||
-- If `a_page' is partial, return the full page node from `a_page',
|
||||
-- otherwise return directly `a_page'.
|
||||
require
|
||||
a_page_set: a_page /= Void
|
||||
do
|
||||
if attached {CMS_PAGE} node_api.full_node (a_page) as l_full_page then
|
||||
Result := l_full_page
|
||||
else
|
||||
Result := a_page
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Commit
|
||||
|
||||
save_page (a_page: CMS_PAGE)
|
||||
do
|
||||
node_api.save_node (a_page)
|
||||
end
|
||||
|
||||
feature {CMS_MODULE} -- Access nodes storage.
|
||||
|
||||
page_storage: CMS_PAGE_STORAGE_I
|
||||
|
||||
feature {NONE} -- Helpers
|
||||
|
||||
nodes_to_pages (a_nodes: LIST [CMS_NODE]): ARRAYED_LIST [CMS_PAGE]
|
||||
-- Convert list of nodes into a list of page when possible.
|
||||
do
|
||||
create {ARRAYED_LIST [CMS_PAGE]} Result.make (a_nodes.count)
|
||||
|
||||
if attached node_api as l_node_api then
|
||||
across
|
||||
a_nodes as ic
|
||||
loop
|
||||
if attached {CMS_PAGE} l_node_api.full_node (ic.item) as l_page then
|
||||
Result.force (l_page)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
411
modules/node/submodules/page/cms_page_module.e
Normal file
411
modules/node/submodules/page/cms_page_module.e
Normal file
@@ -0,0 +1,411 @@
|
||||
note
|
||||
description: "Node page implementation."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_PAGE_MODULE
|
||||
|
||||
inherit
|
||||
CMS_MODULE
|
||||
rename
|
||||
module_api as page_api
|
||||
redefine
|
||||
setup_hooks,
|
||||
initialize,
|
||||
install, is_installed,
|
||||
page_api
|
||||
end
|
||||
|
||||
CMS_HOOK_EXPORT
|
||||
|
||||
CMS_HOOK_IMPORT
|
||||
|
||||
CMS_EXPORT_NODE_UTILITIES
|
||||
|
||||
CMS_IMPORT_NODE_UTILITIES
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
do
|
||||
version := "1.0"
|
||||
description := "Page service"
|
||||
package := "content"
|
||||
add_dependency ({CMS_NODE_MODULE})
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
name: STRING = "page"
|
||||
|
||||
feature {CMS_API} -- Module Initialization
|
||||
|
||||
initialize (a_api: CMS_API)
|
||||
-- <Precursor>
|
||||
local
|
||||
p1,p2: CMS_PAGE
|
||||
ct: CMS_PAGE_NODE_TYPE
|
||||
do
|
||||
Precursor (a_api)
|
||||
if attached {CMS_NODE_API} a_api.module_api ({CMS_NODE_MODULE}) as l_node_api then
|
||||
node_api := l_node_api
|
||||
|
||||
create page_api.make (a_api, l_node_api)
|
||||
|
||||
-- Add support for CMS_PAGE, which requires a storage extension to store the optional "parent" id.
|
||||
-- For now, we only have extension based on SQL statement.
|
||||
if attached {CMS_NODE_STORAGE_SQL} l_node_api.node_storage as l_sql_node_storage then
|
||||
l_sql_node_storage.register_node_storage_extension (create {CMS_NODE_STORAGE_SQL_PAGE_EXTENSION}.make (l_node_api, l_sql_node_storage))
|
||||
|
||||
-- FIXME: the following code is mostly for test purpose/initialization, remove later
|
||||
if l_sql_node_storage.sql_table_items_count ("page_nodes") = 0 then
|
||||
if attached a_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", Void, Void) -- Use default format
|
||||
p1.set_author (u)
|
||||
l_sql_node_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", Void, Void) -- Use default format
|
||||
p2.set_author (u)
|
||||
p2.set_parent (p1)
|
||||
l_sql_node_storage.save_node (p2)
|
||||
end
|
||||
end
|
||||
else
|
||||
-- FIXME: maybe provide a default solution based on file system, when no SQL storage is available.
|
||||
-- IDEA: we could also have generic extension to node system, that handle generic addition field.
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
feature {CMS_API} -- Module management
|
||||
|
||||
is_installed (a_api: CMS_API): BOOLEAN
|
||||
-- Is Current module installed?
|
||||
do
|
||||
Result := Precursor (a_api)
|
||||
if Result and attached a_api.storage.as_sql_storage as l_sql_storage then
|
||||
Result := l_sql_storage.sql_table_exists ("page_nodes")
|
||||
end
|
||||
end
|
||||
|
||||
install (a_api: CMS_API)
|
||||
do
|
||||
-- Schema
|
||||
if attached a_api.storage.as_sql_storage as l_sql_storage then
|
||||
if attached a_api.module ({CMS_NODE_MODULE}) as l_node_module then
|
||||
l_sql_storage.sql_execute_file_script (a_api.module_resource_location (l_node_module, (create {PATH}.make_from_string ("scripts")).extended (name).appended_with_extension ("sql")), Void)
|
||||
end
|
||||
if l_sql_storage.has_error then
|
||||
a_api.logger.put_error ("Could not initialize database for module [" + name + "]", generating_type)
|
||||
else
|
||||
Precursor {CMS_MODULE} (a_api)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
feature {CMS_API} -- Access: API
|
||||
|
||||
page_api: detachable CMS_PAGE_API
|
||||
-- <Precursor>
|
||||
|
||||
node_api: detachable CMS_NODE_API
|
||||
|
||||
feature -- Access: router
|
||||
|
||||
setup_router (a_router: WSF_ROUTER; a_api: CMS_API)
|
||||
-- <Precursor>
|
||||
do
|
||||
end
|
||||
|
||||
feature -- Hooks
|
||||
|
||||
setup_hooks (a_hooks: CMS_HOOK_CORE_MANAGER)
|
||||
do
|
||||
a_hooks.subscribe_to_export_hook (Current)
|
||||
a_hooks.subscribe_to_import_hook (Current)
|
||||
end
|
||||
|
||||
export_to (a_export_id_list: detachable ITERABLE [READABLE_STRING_GENERAL]; a_export_ctx: CMS_EXPORT_CONTEXT; a_response: CMS_RESPONSE)
|
||||
-- Export data identified by `a_export_id_list',
|
||||
-- or export all data if `a_export_id_list' is Void.
|
||||
local
|
||||
n: CMS_PAGE
|
||||
p: PATH
|
||||
d: DIRECTORY
|
||||
f: PLAIN_TEXT_FILE
|
||||
lst: LIST [CMS_NODE]
|
||||
do
|
||||
if
|
||||
attached node_api as l_node_api and then
|
||||
attached l_node_api.node_type ("page") as l_node_type and then
|
||||
( a_export_id_list = Void
|
||||
or else across a_export_id_list as ic some ic.item.same_string (l_node_type.name) end
|
||||
)
|
||||
then
|
||||
if
|
||||
a_response.has_permissions (<<"export any node", "export " + l_node_type.name>>) and then
|
||||
attached page_api as l_page_api
|
||||
then
|
||||
lst := l_page_api.pages
|
||||
a_export_ctx.log ("Exporting " + lst.count.out + " notes of type `" + l_node_type.name + "`.")
|
||||
create d.make_with_path (a_export_ctx.location.extended ("nodes").extended (l_node_type.name))
|
||||
if d.exists then
|
||||
d.recursive_delete
|
||||
end
|
||||
across
|
||||
lst as ic
|
||||
loop
|
||||
if attached {CMS_PAGE} ic.item as l_page_node then
|
||||
n := l_page_api.full_page_node (l_page_node)
|
||||
a_export_ctx.log (n.content_type + " #" + n.id.out)
|
||||
|
||||
p := a_export_ctx.location.extended ("nodes").extended (n.content_type).extended (n.id.out).appended_with_extension ("json")
|
||||
create d.make_with_path (p.parent)
|
||||
if not d.exists then
|
||||
d.recursive_create_dir
|
||||
end
|
||||
|
||||
create f.make_with_path (p)
|
||||
if not f.exists or else f.is_access_writable then
|
||||
f.open_write
|
||||
f.put_string (json_to_string (page_node_to_json (n, l_page_api)))
|
||||
f.close
|
||||
end
|
||||
-- Revisions.
|
||||
if
|
||||
attached l_node_api.node_revisions (n) as l_revisions and then
|
||||
l_revisions.count > 1
|
||||
then
|
||||
a_export_ctx.log (n.content_type + " " + l_revisions.count.out + " revisions.")
|
||||
p := a_export_ctx.location.extended ("nodes").extended (n.content_type).extended (n.id.out)
|
||||
create d.make_with_path (p)
|
||||
if not d.exists then
|
||||
d.recursive_create_dir
|
||||
end
|
||||
across
|
||||
l_revisions as revs_ic
|
||||
loop
|
||||
if attached {CMS_PAGE} revs_ic.item as l_rev_page then
|
||||
create f.make_with_path (p.extended ("rev-" + n.revision.out).appended_with_extension ("json"))
|
||||
if not f.exists or else f.is_access_writable then
|
||||
f.open_write
|
||||
f.put_string (json_to_string (page_node_to_json (l_rev_page, l_page_api)))
|
||||
end
|
||||
f.close
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
page_node_to_json (a_page: CMS_PAGE; a_page_api: CMS_PAGE_API): JSON_OBJECT
|
||||
local
|
||||
j: JSON_OBJECT
|
||||
p: CMS_PAGE
|
||||
do
|
||||
Result := node_to_json (a_page, a_page_api.node_api)
|
||||
if attached a_page.parent as l_parent_page then
|
||||
p := a_page_api.full_page_node (l_parent_page)
|
||||
create j.make_empty
|
||||
j.put_string (p.content_type, "type")
|
||||
j.put_string (p.title, "title")
|
||||
j.put_integer (p.id, "nid")
|
||||
if attached p.link as lnk then
|
||||
j.put (link_to_json (lnk), "link")
|
||||
end
|
||||
Result.put (j, "parent")
|
||||
end
|
||||
end
|
||||
|
||||
import_from (a_import_id_list: detachable ITERABLE [READABLE_STRING_GENERAL]; a_import_ctx: CMS_IMPORT_CONTEXT; a_response: CMS_RESPONSE)
|
||||
-- Import data identified by `a_import_id_list',
|
||||
-- or import all data if `a_import_id_list' is Void.
|
||||
local
|
||||
p: PATH
|
||||
d: DIRECTORY
|
||||
f: PLAIN_TEXT_FILE
|
||||
s: STRING
|
||||
jp: JSON_PARSER
|
||||
loc: READABLE_STRING_8
|
||||
l_parentable_list: ARRAYED_LIST [TUPLE [page: CMS_PAGE; parent: CMS_PAGE]]
|
||||
l_new_pages: STRING_TABLE [CMS_PAGE] -- indexed by link location, if any.
|
||||
do
|
||||
if
|
||||
attached node_api as l_node_api and then
|
||||
attached {CMS_PAGE_NODE_TYPE} l_node_api.node_type ({CMS_PAGE_NODE_TYPE}.name) as l_node_type and then
|
||||
attached page_api as l_page_api and then
|
||||
( a_import_id_list = Void
|
||||
or else across a_import_id_list as ic some ic.item.same_string (l_node_type.name) end
|
||||
)
|
||||
then
|
||||
if
|
||||
a_response.has_permissions (<<"import any node", "import " + l_node_type.name>>)
|
||||
then
|
||||
p := a_import_ctx.location.extended ("nodes").extended (l_node_type.name)
|
||||
create d.make_with_path (p)
|
||||
if d.exists and then d.is_readable then
|
||||
create l_parentable_list.make (0)
|
||||
create l_new_pages.make (0)
|
||||
a_import_ctx.log ("Importing [" + l_node_type.name + "] items ..")
|
||||
across
|
||||
d.entries as ic
|
||||
loop
|
||||
if attached ic.item.extension as ext and then ext.same_string_general ("json") then
|
||||
create f.make_with_path (p.extended_path (ic.item))
|
||||
if f.exists and then f.is_access_readable then
|
||||
f.open_read
|
||||
from
|
||||
create s.make (0)
|
||||
until
|
||||
f.exhausted or f.end_of_file
|
||||
loop
|
||||
f.read_stream (1_024)
|
||||
s.append (f.last_string)
|
||||
end
|
||||
f.close
|
||||
create jp.make_with_string (s)
|
||||
jp.parse_content
|
||||
if jp.is_valid and then attached jp.parsed_json_object as j then
|
||||
if
|
||||
attached json_string_item (j, "type") as l_type and then
|
||||
l_type.same_string_general (l_node_type.name)
|
||||
then
|
||||
if attached json_to_node_page (l_node_type, j, l_node_api) as l_page then
|
||||
if l_page.is_published then
|
||||
if l_page.author = Void then
|
||||
-- FIXME!!!
|
||||
l_page.set_author (l_page_api.cms_api.user)
|
||||
a_import_ctx.log (l_node_type.name + " %"" + f.path.utf_8_name + "%" WARNING (Author is unknown!)")
|
||||
end
|
||||
if attached l_page.author as l_author then
|
||||
if
|
||||
attached l_page_api.pages_with_title (l_page.title) as l_pages and then
|
||||
not l_pages.is_empty
|
||||
then
|
||||
-- Page Already exists!
|
||||
-- FIXME/TODO
|
||||
a_import_ctx.log (l_node_type.name + " %"" + f.path.utf_8_name + "%" skipped (already exists for user #" + l_author.id.out + ")!")
|
||||
else
|
||||
if
|
||||
attached l_page.parent as l_parent and then
|
||||
not l_parent.has_id
|
||||
then
|
||||
l_parentable_list.extend ([l_page, l_parent])
|
||||
l_page.set_parent (Void)
|
||||
end
|
||||
l_page_api.save_page (l_page)
|
||||
l_new_pages.force (l_page, l_node_api.node_path (l_page))
|
||||
a_import_ctx.log (l_node_type.name + " %"" + f.path.utf_8_name + "%" imported as "+ l_page.id.out +" for user #" + l_author.id.out + ".")
|
||||
if attached {CMS_LOCAL_LINK} l_page.link as l_link then
|
||||
loc := l_node_api.node_path (l_page)
|
||||
if not l_link.location.starts_with_general ("node/") then
|
||||
l_page_api.cms_api.set_path_alias (loc, l_link.location, False)
|
||||
l_new_pages.force (l_page, l_link.location)
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
a_import_ctx.log (l_node_type.name + " %"" + f.path.utf_8_name + "%" skipped (Author is unknown!)")
|
||||
end
|
||||
else
|
||||
a_import_ctx.log (l_node_type.name + " %"" + f.path.utf_8_name + "%" skipped (Status is Not Published!)")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
across
|
||||
l_parentable_list as ic
|
||||
loop
|
||||
if attached ic.item.page as l_page then
|
||||
update_page_parent (l_page, ic.item.parent, l_new_pages)
|
||||
if attached l_page.parent as l_parent then
|
||||
a_import_ctx.log (l_node_type.name + " #" + l_page.id.out + " assigned to parent #" + l_parent.id.out)
|
||||
l_page_api.save_page (l_page)
|
||||
else
|
||||
a_import_ctx.log (l_node_type.name + " #" + l_page.id.out + " : unable to find parent!")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
json_to_node_page (a_node_type: CMS_PAGE_NODE_TYPE; j: JSON_OBJECT; a_node_api: CMS_NODE_API): detachable CMS_PAGE
|
||||
local
|
||||
p: detachable CMS_PAGE
|
||||
do
|
||||
if attached json_to_node (a_node_type, j, a_node_api) as l_node then
|
||||
Result := a_node_type.new_node (l_node)
|
||||
if
|
||||
attached {JSON_OBJECT} j.item ("parent") as j_parent and then
|
||||
attached json_string_item (j_parent, "title") as l_title
|
||||
then
|
||||
p := a_node_type.new_node_with_title (l_title, Void)
|
||||
if
|
||||
attached {JSON_OBJECT} j_parent.item ("link") as j_link and then
|
||||
attached json_to_local_link (j_link) as l_parent_lnk and then
|
||||
not l_parent_lnk.location.starts_with ("node/")
|
||||
then
|
||||
p.set_link (l_parent_lnk)
|
||||
else
|
||||
-- No link ..
|
||||
end
|
||||
if not Result.is_parent_of (p) then
|
||||
Result.set_parent (p)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
update_page_parent (a_page: CMS_PAGE; a_parent: CMS_PAGE; a_new_pages: STRING_TABLE [CMS_PAGE])
|
||||
require
|
||||
no_parent_set: a_page.parent = Void
|
||||
local
|
||||
lst: detachable LIST [CMS_PAGE]
|
||||
p: detachable CMS_PAGE
|
||||
do
|
||||
p := a_parent
|
||||
if attached page_api as l_page_api then
|
||||
if attached a_parent.link as l_parent_lnk then
|
||||
lst := l_page_api.pages_with_title (a_parent.title)
|
||||
across
|
||||
lst as ic
|
||||
until
|
||||
p.has_id
|
||||
loop
|
||||
if
|
||||
attached ic.item.link as lnk and then
|
||||
lnk.location.same_string_general (l_parent_lnk.location)
|
||||
then
|
||||
p := ic.item
|
||||
end
|
||||
end
|
||||
else
|
||||
lst := l_page_api.pages_with_title (a_parent.title)
|
||||
if lst.count = 1 then
|
||||
p := lst.first
|
||||
end
|
||||
end
|
||||
end
|
||||
if p.has_id then
|
||||
a_page.set_parent (p)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
46
modules/node/submodules/page/cms_page_node_type.e
Normal file
46
modules/node/submodules/page/cms_page_node_type.e
Normal file
@@ -0,0 +1,46 @@
|
||||
note
|
||||
description: "[
|
||||
Interface defining a CMS page type.
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_PAGE_NODE_TYPE
|
||||
|
||||
inherit
|
||||
CMS_NODE_TYPE [CMS_PAGE]
|
||||
|
||||
feature -- Access
|
||||
|
||||
name: STRING = "page"
|
||||
-- Internal name.
|
||||
|
||||
title: STRING_32 = "Page"
|
||||
-- Human readable name.
|
||||
|
||||
description: STRING_32 = "Use basic pages for your content, such as an 'About us' page."
|
||||
-- Optional description
|
||||
|
||||
feature -- Factory
|
||||
|
||||
new_node_with_title (a_title: READABLE_STRING_32; a_partial_node: detachable CMS_NODE): like new_node
|
||||
-- New node with `a_title' and fill from partial `a_partial_node' if set.
|
||||
do
|
||||
create Result.make (a_title)
|
||||
if a_partial_node /= Void then
|
||||
Result.import_node (a_partial_node)
|
||||
Result.set_title (a_title)
|
||||
end
|
||||
end
|
||||
|
||||
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
|
||||
31
modules/node/submodules/page/cms_page_storage_i.e
Normal file
31
modules/node/submodules/page/cms_page_storage_i.e
Normal file
@@ -0,0 +1,31 @@
|
||||
note
|
||||
description: "Summary description for {CMS_PAGE_STORAGE_I}."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
CMS_PAGE_STORAGE_I
|
||||
|
||||
feature -- Error Handling
|
||||
|
||||
error_handler: ERROR_HANDLER
|
||||
-- Error handler.
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
children (a_node: CMS_NODE): detachable LIST [CMS_NODE]
|
||||
-- Children of node `a_node'.
|
||||
-- note: this is the partial version of the nodes.
|
||||
deferred
|
||||
end
|
||||
|
||||
available_parents_for_node (a_node: CMS_NODE): LIST [CMS_NODE]
|
||||
-- Given the node `a_node', return the list of possible parent nodes id
|
||||
deferred
|
||||
ensure
|
||||
a_node_excluded: across Result as ic all not a_node.same_node (ic.item) end
|
||||
end
|
||||
|
||||
end
|
||||
31
modules/node/submodules/page/cms_page_storage_null.e
Normal file
31
modules/node/submodules/page/cms_page_storage_null.e
Normal file
@@ -0,0 +1,31 @@
|
||||
note
|
||||
description: "Summary description for {CMS_PAGE_STORAGE_NULL}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_PAGE_STORAGE_NULL
|
||||
|
||||
inherit
|
||||
CMS_NODE_STORAGE_NULL
|
||||
|
||||
CMS_PAGE_STORAGE_I
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Access
|
||||
|
||||
children (a_node: CMS_NODE): detachable LIST [CMS_NODE]
|
||||
-- <Precursor>
|
||||
do
|
||||
end
|
||||
|
||||
available_parents_for_node (a_node: CMS_NODE): LIST [CMS_NODE]
|
||||
-- <Precursor>
|
||||
do
|
||||
create {ARRAYED_LIST [CMS_NODE]} Result.make (0)
|
||||
end
|
||||
|
||||
end
|
||||
86
modules/node/submodules/page/cms_page_storage_sql.e
Normal file
86
modules/node/submodules/page/cms_page_storage_sql.e
Normal file
@@ -0,0 +1,86 @@
|
||||
note
|
||||
description: "Access to the sql database for the page module"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_PAGE_STORAGE_SQL
|
||||
|
||||
inherit
|
||||
CMS_NODE_STORAGE_SQL
|
||||
|
||||
CMS_PAGE_STORAGE_I
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Access
|
||||
|
||||
children (a_node: CMS_NODE): detachable LIST [CMS_NODE]
|
||||
-- <Precursor>
|
||||
local
|
||||
l_parameters: STRING_TABLE [detachable ANY]
|
||||
do
|
||||
create {ARRAYED_LIST [CMS_NODE]} Result.make (0)
|
||||
|
||||
error_handler.reset
|
||||
write_information_log (generator + ".children")
|
||||
|
||||
from
|
||||
create l_parameters.make (1)
|
||||
l_parameters.put (a_node.id, "nid")
|
||||
sql_query (sql_select_children_of_node, l_parameters)
|
||||
sql_start
|
||||
until
|
||||
sql_after
|
||||
loop
|
||||
if attached fetch_node as l_node then
|
||||
Result.force (l_node)
|
||||
end
|
||||
sql_forth
|
||||
end
|
||||
sql_finalize
|
||||
end
|
||||
|
||||
available_parents_for_node (a_node: CMS_NODE): LIST [CMS_NODE]
|
||||
-- <Precursor>
|
||||
local
|
||||
l_parameters: STRING_TABLE [detachable ANY]
|
||||
do
|
||||
create {ARRAYED_LIST [CMS_NODE]} Result.make (0)
|
||||
|
||||
error_handler.reset
|
||||
write_information_log (generator + ".available_parents_for_node")
|
||||
|
||||
from
|
||||
create l_parameters.make (1)
|
||||
l_parameters.put (a_node.id, "nid")
|
||||
sql_query (sql_select_available_parents_for_node, l_parameters)
|
||||
sql_start
|
||||
until
|
||||
sql_after
|
||||
loop
|
||||
if attached fetch_node as l_node then
|
||||
Result.force (l_node)
|
||||
end
|
||||
sql_forth
|
||||
end
|
||||
sql_finalize
|
||||
end
|
||||
|
||||
|
||||
feature {NONE} -- Queries
|
||||
|
||||
sql_select_available_parents_for_node : STRING = "[
|
||||
SELECT node.nid, node.revision, node.type, title, summary, content, format, author, publish, created, changed, status
|
||||
FROM nodes node LEFT JOIN page_nodes pn ON node.nid = pn.nid AND node.nid != :nid
|
||||
WHERE node.nid != :nid AND pn.parent != :nid AND node.status != -1 GROUP BY node.nid, node.revision;
|
||||
]"
|
||||
|
||||
sql_select_children_of_node: STRING = "[
|
||||
SELECT node.nid, node.revision, node.type, title, summary, content, format, author, publish, created, changed, status
|
||||
FROM nodes node LEFT JOIN page_nodes pn ON node.nid = pn.nid
|
||||
WHERE pn.parent = :nid AND node.status != -1 GROUP BY node.nid, node.revision;
|
||||
]"
|
||||
|
||||
end
|
||||
17
modules/node/submodules/page/cms_partial_page.e
Normal file
17
modules/node/submodules/page/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
|
||||
Reference in New Issue
Block a user