Added support for user, user_roles, page, blog export and import.
Added basic support for comments, for now mainly viewing comments from database (no submission forms yet). Added first simple wikitext filter (render wikitext content as xhtml). Ensure response content type is text/html with utf-8 charset.
This commit is contained in:
@@ -43,7 +43,7 @@ feature {NONE} -- Initialization
|
||||
|
||||
--| For test reasons this is 2, so we don't have to create a lot of blog entries.
|
||||
--| TODO: Set to bigger constant.
|
||||
entries_per_page := 2
|
||||
entries_per_page := 6
|
||||
|
||||
-- initialize_node_types
|
||||
end
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
<library name="base_extension" location="$ISE_LIBRARY\library\base_extension\base_extension-safe.ecf"/>
|
||||
<library name="cms" location="..\..\cms-safe.ecf" readonly="false"/>
|
||||
<library name="cms_model" location="..\..\library\model\cms_model-safe.ecf" readonly="false"/>
|
||||
<library name="cms_comments_module" location="..\..\modules\comments\comments-safe.ecf" readonly="false"/>
|
||||
<library name="cms_node_module" location="..\..\modules\node\node-safe.ecf" readonly="false"/>
|
||||
<library name="error" location="$ISE_LIBRARY\contrib\library\utility\general\error\error-safe.ecf"/>
|
||||
|
||||
|
||||
@@ -241,12 +241,11 @@ feature -- Hooks
|
||||
-- Import data identified by `a_import_id_list',
|
||||
-- or import all data if `a_import_id_list' is Void.
|
||||
local
|
||||
p: PATH
|
||||
p,fp: PATH
|
||||
d: DIRECTORY
|
||||
f: PLAIN_TEXT_FILE
|
||||
s: STRING
|
||||
jp: JSON_PARSER
|
||||
loc: STRING
|
||||
l_id: STRING_32
|
||||
l_entity: detachable CMS_BLOG
|
||||
do
|
||||
if
|
||||
attached node_api as l_node_api and then
|
||||
@@ -267,51 +266,51 @@ feature -- Hooks
|
||||
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_blog (l_node_type, j, l_node_api) as l_blog then
|
||||
if l_blog.is_published then
|
||||
if attached l_blog.author as l_author then
|
||||
if
|
||||
attached l_blog_api.blogs_by_title (l_author, l_blog.title) as l_blogs and then
|
||||
not l_blogs.is_empty
|
||||
then
|
||||
-- Blog 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
|
||||
a_import_ctx.log (l_node_type.name + " %"" + f.path.utf_8_name + "%" imported for user #" + l_author.id.out + ".")
|
||||
l_blog_api.save_blog (l_blog)
|
||||
if attached {CMS_LOCAL_LINK} l_blog.link as l_link then
|
||||
loc := l_node_api.node_path (l_blog)
|
||||
if not l_link.location.starts_with_general ("node/") then
|
||||
l_blog_api.cms_api.set_path_alias (loc, l_link.location, False)
|
||||
end
|
||||
l_id := ic.item.name
|
||||
l_id.remove_tail (ext.count + 1)
|
||||
fp := p.extended_path (ic.item)
|
||||
if attached json_object_from_location (fp) 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
|
||||
l_entity := json_to_node_blog (l_node_type, j, l_node_api)
|
||||
if l_entity /= Void then
|
||||
if l_entity.is_published then
|
||||
if l_entity.author = Void then
|
||||
-- FIXME!!!
|
||||
l_entity.set_author (l_blog_api.cms_api.user)
|
||||
a_import_ctx.log (l_node_type.name + " %"" + fp.utf_8_name + "%" WARNING (Author is unknown!)")
|
||||
end
|
||||
if attached l_entity.author as l_author then
|
||||
if
|
||||
attached l_blog_api.blogs_by_title (l_author, l_entity.title) as l_blogs and then
|
||||
not l_blogs.is_empty
|
||||
then
|
||||
-- Blog Already exists!
|
||||
-- FIXME/TODO
|
||||
l_entity := l_blogs.first
|
||||
a_import_ctx.log (l_node_type.name + " %"" + fp.utf_8_name + "%" skipped (already exists for user #" + l_author.id.out + ")!")
|
||||
else
|
||||
a_import_ctx.log (l_node_type.name + " %"" + fp.utf_8_name + "%" imported for user #" + l_author.id.out + ".")
|
||||
l_blog_api.save_blog (l_entity)
|
||||
apply_taxonomy_to_node (j, l_entity, l_blog_api.cms_api)
|
||||
if attached {CMS_LOCAL_LINK} l_entity.link as l_link then
|
||||
loc := l_node_api.node_path (l_entity)
|
||||
if not l_link.location.starts_with_general ("node/") then
|
||||
l_blog_api.cms_api.set_path_alias (loc, l_link.location, False)
|
||||
end
|
||||
end
|
||||
else
|
||||
a_import_ctx.log (l_node_type.name + " %"" + f.path.utf_8_name + "%" skipped (Author is unknown!)")
|
||||
end
|
||||
if l_entity /= Void and then l_entity.has_id then
|
||||
-- Support for comments
|
||||
import_comments_file_for_entity (p.extended (l_id).extended ("comments.json"), l_entity, l_node_api.cms_api, a_import_ctx)
|
||||
end
|
||||
else
|
||||
a_import_ctx.log (l_node_type.name + " %"" + f.path.utf_8_name + "%" skipped (Status is Not Published!)")
|
||||
a_import_ctx.log (l_node_type.name + " %"" + fp.utf_8_name + "%" skipped (Author is unknown!)")
|
||||
end
|
||||
else
|
||||
a_import_ctx.log (l_node_type.name + " %"" + fp.utf_8_name + "%" skipped (Status is Not Published!)")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
178
modules/comments/cms_comment.e
Normal file
178
modules/comments/cms_comment.e
Normal file
@@ -0,0 +1,178 @@
|
||||
note
|
||||
description: "[
|
||||
Comment object.
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_COMMENT
|
||||
|
||||
inherit
|
||||
ITERABLE [CMS_COMMENT]
|
||||
undefine
|
||||
is_equal
|
||||
end
|
||||
|
||||
COMPARABLE
|
||||
|
||||
DEBUG_OUTPUT
|
||||
undefine
|
||||
is_equal
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
-- Create Current profile.
|
||||
do
|
||||
create {ARRAYED_LIST [CMS_COMMENT]} items.make (0)
|
||||
create modification_date.make_now_utc
|
||||
creation_date := modification_date
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
id: INTEGER_64 assign set_id
|
||||
-- Unique id.
|
||||
--| Should we use NATURAL_64 instead?
|
||||
|
||||
content: detachable READABLE_STRING_32
|
||||
|
||||
format: detachable READABLE_STRING_8
|
||||
|
||||
author: detachable CMS_USER
|
||||
|
||||
author_name: detachable READABLE_STRING_32
|
||||
-- Author name if no CMS user is associated.
|
||||
|
||||
creation_date: DATE_TIME
|
||||
-- When the comment was created.
|
||||
|
||||
modification_date: DATE_TIME
|
||||
-- When the comment was updated.
|
||||
|
||||
status: INTEGER
|
||||
-- Status of Current comment.
|
||||
|
||||
parent: detachable CMS_COMMENT
|
||||
|
||||
entity: detachable CMS_CONTENT
|
||||
-- Associated content.
|
||||
|
||||
feature -- Access
|
||||
|
||||
has_id: BOOLEAN
|
||||
do
|
||||
Result := id > 0
|
||||
end
|
||||
|
||||
new_cursor: ITERATION_CURSOR [CMS_COMMENT]
|
||||
-- Fresh cursor associated with current structure
|
||||
do
|
||||
Result := items.new_cursor
|
||||
end
|
||||
|
||||
feature -- Optional
|
||||
|
||||
items: LIST [CMS_COMMENT]
|
||||
|
||||
extend (c: CMS_COMMENT)
|
||||
do
|
||||
items.extend (c)
|
||||
end
|
||||
|
||||
count: INTEGER
|
||||
do
|
||||
Result := items.count
|
||||
end
|
||||
|
||||
feature -- Comparison
|
||||
|
||||
is_less alias "<" (other: like Current): BOOLEAN
|
||||
-- Is current object less than `other'?
|
||||
do
|
||||
Result := creation_date < other.creation_date
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
debug_output: STRING_32
|
||||
-- <Precursor>
|
||||
do
|
||||
create Result.make_empty
|
||||
Result.append_character ('#')
|
||||
Result.append_integer_64 (id)
|
||||
if attached content as l_content then
|
||||
Result.append_character (' ')
|
||||
Result.append_character ('%"')
|
||||
Result.append (l_content.head (25))
|
||||
if l_content.count > 25 then
|
||||
Result.append ("...")
|
||||
end
|
||||
Result.append_character ('%"')
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Change
|
||||
|
||||
set_id (a_id: like id)
|
||||
require
|
||||
a_id_positive: a_id > 0
|
||||
do
|
||||
id := a_id
|
||||
end
|
||||
|
||||
set_content (s: like content)
|
||||
do
|
||||
content := s
|
||||
end
|
||||
|
||||
set_format (f: like format)
|
||||
do
|
||||
format := f
|
||||
end
|
||||
|
||||
set_author (u: detachable CMS_USER)
|
||||
do
|
||||
author := u
|
||||
end
|
||||
|
||||
set_author_name (n: like author_name)
|
||||
do
|
||||
author_name := n
|
||||
end
|
||||
|
||||
set_creation_date (dt: DATE_TIME)
|
||||
do
|
||||
creation_date := dt
|
||||
end
|
||||
|
||||
set_modification_date (dt: DATE_TIME)
|
||||
do
|
||||
modification_date := dt
|
||||
end
|
||||
|
||||
set_status (st: like status)
|
||||
do
|
||||
status := st
|
||||
end
|
||||
|
||||
set_parent (p: detachable CMS_COMMENT)
|
||||
do
|
||||
parent := p
|
||||
end
|
||||
|
||||
set_entity (e: like entity)
|
||||
do
|
||||
entity := e
|
||||
end
|
||||
|
||||
|
||||
;note
|
||||
copyright: "2011-2014, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
end
|
||||
207
modules/comments/cms_comments_api.e
Normal file
207
modules/comments/cms_comments_api.e
Normal file
@@ -0,0 +1,207 @@
|
||||
note
|
||||
description: "API to handle user profiles."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_COMMENTS_API
|
||||
|
||||
inherit
|
||||
CMS_MODULE_API
|
||||
redefine
|
||||
initialize
|
||||
end
|
||||
|
||||
REFACTORING_HELPER
|
||||
|
||||
create {CMS_COMMENTS_MODULE}
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
initialize
|
||||
-- Create user profile api object with api `a_api' and storage `a_storage'.
|
||||
do
|
||||
Precursor
|
||||
|
||||
if attached storage.as_sql_storage as l_storage_sql then
|
||||
create {CMS_COMMENTS_STORAGE_SQL} comments_storage.make (l_storage_sql)
|
||||
else
|
||||
create {CMS_COMMENTS_STORAGE_NULL} comments_storage.make
|
||||
end
|
||||
end
|
||||
|
||||
feature {CMS_MODULE} -- Access nodes storage.
|
||||
|
||||
comments_storage: CMS_COMMENTS_STORAGE_I
|
||||
|
||||
feature -- Access
|
||||
|
||||
comment (a_cid: INTEGER_64): detachable CMS_COMMENT
|
||||
require
|
||||
a_cid > 0
|
||||
do
|
||||
Result := comments_storage.comment (a_cid)
|
||||
if Result /= Void then
|
||||
Result := recursive_full_comment (Result)
|
||||
end
|
||||
end
|
||||
|
||||
comments_for (a_content: CMS_CONTENT): detachable LIST [CMS_COMMENT]
|
||||
-- Comments for `a_content`.
|
||||
require
|
||||
valid_content: a_content.has_identifier
|
||||
local
|
||||
l_comment, l_parent: detachable CMS_COMMENT
|
||||
|
||||
tb: HASH_TABLE [CMS_COMMENT, INTEGER_64] -- indexed by "comment id".
|
||||
do
|
||||
if
|
||||
attached comments_storage.comments_for (a_content) as l_flat_lst and then not l_flat_lst.is_empty and then
|
||||
attached full_comments (l_flat_lst) as lst
|
||||
then
|
||||
create {ARRAYED_LIST [CMS_COMMENT]} Result.make (lst.count)
|
||||
create tb.make (lst.count)
|
||||
across
|
||||
lst as ic
|
||||
loop
|
||||
l_comment := ic.item
|
||||
tb.put (l_comment, l_comment.id)
|
||||
if l_comment.parent = Void then
|
||||
Result.extend (l_comment)
|
||||
end
|
||||
end
|
||||
across
|
||||
lst as ic
|
||||
loop
|
||||
l_comment := ic.item
|
||||
l_parent := l_comment.parent
|
||||
if attached {CMS_PARTIAL_COMMENT} l_parent as l_partial then
|
||||
l_parent := tb.item (l_partial.id)
|
||||
l_comment.set_parent (l_parent)
|
||||
end
|
||||
if l_parent /= Void then
|
||||
l_parent.extend (l_comment)
|
||||
end
|
||||
end
|
||||
sort_comments (Result)
|
||||
end
|
||||
end
|
||||
|
||||
full_comment (a_comment: CMS_COMMENT): CMS_COMMENT
|
||||
-- If `a_comment' is partial, return the full object from `a_comment',
|
||||
-- otherwise return directly `a_comment'.
|
||||
require
|
||||
a_comment_set: a_comment /= Void
|
||||
local
|
||||
l_comment: detachable CMS_COMMENT
|
||||
do
|
||||
if attached {CMS_PARTIAL_COMMENT} a_comment as l_partial_comment then
|
||||
l_comment := comment (l_partial_comment.id)
|
||||
if l_comment /= Void then
|
||||
Result := l_comment
|
||||
else
|
||||
Result := l_partial_comment
|
||||
end
|
||||
else
|
||||
Result := a_comment
|
||||
end
|
||||
|
||||
-- Update partial user if needed.
|
||||
if Result /= Void then
|
||||
if 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
|
||||
end
|
||||
|
||||
full_comments (a_comments: LIST [CMS_COMMENT]): LIST [CMS_COMMENT]
|
||||
-- Convert list of potentially partial comments into a list of comments when possible.
|
||||
do
|
||||
create {ARRAYED_LIST [CMS_COMMENT]} Result.make (a_comments.count)
|
||||
across
|
||||
a_comments as ic
|
||||
loop
|
||||
Result.force (full_comment (ic.item))
|
||||
end
|
||||
end
|
||||
|
||||
recursive_full_comment (a_comment: CMS_COMMENT): CMS_COMMENT
|
||||
local
|
||||
lst: LIST [CMS_COMMENT]
|
||||
do
|
||||
Result := full_comment (a_comment)
|
||||
from
|
||||
lst := a_comment.items
|
||||
lst.start
|
||||
until
|
||||
lst.after
|
||||
loop
|
||||
lst.replace (recursive_full_comment (lst.item))
|
||||
lst.forth
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Change: profile
|
||||
|
||||
save_comment (a_comment: CMS_COMMENT)
|
||||
-- Save `a_comment`.
|
||||
do
|
||||
comments_storage.save_comment (a_comment)
|
||||
end
|
||||
|
||||
save_recursively_comment (a_comment: CMS_COMMENT)
|
||||
do
|
||||
save_comment (a_comment)
|
||||
across
|
||||
a_comment as ic
|
||||
loop
|
||||
ic.item.set_parent (a_comment)
|
||||
save_recursively_comment (ic.item)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Helper
|
||||
|
||||
has_cycle_in_comments (a_comments: ITERABLE [CMS_COMMENT]; a_known_comments: detachable LIST [CMS_COMMENT]): BOOLEAN
|
||||
local
|
||||
lst: detachable LIST [CMS_COMMENT]
|
||||
do
|
||||
lst := a_known_comments
|
||||
if lst = Void then
|
||||
create {ARRAYED_LIST [CMS_COMMENT]} lst.make (0)
|
||||
elseif across a_comments as ic some lst.has (ic.item) end then
|
||||
Result := True
|
||||
end
|
||||
if not Result then
|
||||
across
|
||||
a_comments as ic
|
||||
loop
|
||||
lst.extend (ic.item)
|
||||
Result := has_cycle_in_comments (ic.item, lst)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
sort_comments (a_items: LIST [CMS_COMMENT])
|
||||
require
|
||||
no_cycle: not has_cycle_in_comments (a_items, Void)
|
||||
local
|
||||
l_sorter: QUICK_SORTER [CMS_COMMENT]
|
||||
do
|
||||
create l_sorter.make (create {COMPARABLE_COMPARATOR [CMS_COMMENT]})
|
||||
l_sorter.sort (a_items)
|
||||
across
|
||||
a_items as ic
|
||||
loop
|
||||
sort_comments (ic.item.items)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
96
modules/comments/cms_comments_module.e
Normal file
96
modules/comments/cms_comments_module.e
Normal file
@@ -0,0 +1,96 @@
|
||||
note
|
||||
description: "[
|
||||
Comments module.
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_COMMENTS_MODULE
|
||||
|
||||
inherit
|
||||
CMS_MODULE
|
||||
rename
|
||||
module_api as comments_api
|
||||
redefine
|
||||
setup_hooks,
|
||||
initialize,
|
||||
install,
|
||||
comments_api
|
||||
end
|
||||
|
||||
CMS_HOOK_RESPONSE_ALTER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
do
|
||||
version := "1.0"
|
||||
description := "Comments"
|
||||
package := "content"
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
name: STRING = "comments"
|
||||
|
||||
feature {CMS_API} -- Module Initialization
|
||||
|
||||
initialize (api: CMS_API)
|
||||
-- <Precursor>
|
||||
do
|
||||
Precursor (api)
|
||||
create comments_api.make (api)
|
||||
end
|
||||
|
||||
feature {CMS_API} -- Module management
|
||||
|
||||
install (a_api: CMS_API)
|
||||
do
|
||||
-- Schema
|
||||
if attached a_api.storage.as_sql_storage as l_sql_storage then
|
||||
l_sql_storage.sql_execute_file_script (a_api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("install.sql")), Void)
|
||||
|
||||
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
|
||||
|
||||
comments_api: detachable CMS_COMMENTS_API
|
||||
-- <Precursor>
|
||||
|
||||
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_response_alter_hook (Current)
|
||||
-- a_hooks.subscribe_to_form_alter_hook (Current)
|
||||
end
|
||||
|
||||
-- form_alter (a_form: CMS_FORM; a_form_data: detachable WSF_FORM_DATA; a_response: CMS_RESPONSE)
|
||||
-- -- Hook execution on form `a_form' and its associated data `a_form_data',
|
||||
-- -- for related response `a_response'.
|
||||
-- do
|
||||
-- end
|
||||
|
||||
response_alter (a_response: CMS_RESPONSE)
|
||||
do
|
||||
a_response.add_style (a_response.url ("/module/" + name + "/files/css/comments.css", Void), Void)
|
||||
end
|
||||
|
||||
end
|
||||
25
modules/comments/cms_partial_comment.e
Normal file
25
modules/comments/cms_partial_comment.e
Normal file
@@ -0,0 +1,25 @@
|
||||
note
|
||||
description: "Summary description for {CMS_PARTIAL_COMMENT}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_PARTIAL_COMMENT
|
||||
|
||||
inherit
|
||||
CMS_COMMENT
|
||||
|
||||
create
|
||||
make_with_id
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make_with_id (a_cid: like id)
|
||||
do
|
||||
make
|
||||
id := a_cid
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
28
modules/comments/comments-safe.ecf
Normal file
28
modules/comments/comments-safe.ecf
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="comments_module" uuid="C1D39ECD-6993-456B-AD14-0CF94504340F" library_target="comments_module">
|
||||
<target name="comments_module">
|
||||
<root all_classes="true"/>
|
||||
<file_rule>
|
||||
<exclude>/.git$</exclude>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true">
|
||||
</option>
|
||||
<setting name="concurrency" value="scoop"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="base_extension" location="$ISE_LIBRARY\library\base_extension\base_extension-safe.ecf"/>
|
||||
<library name="cms" location="..\..\cms-safe.ecf" readonly="false"/>
|
||||
<library name="cms_model" location="..\..\library\model\cms_model-safe.ecf" readonly="false"/>
|
||||
<library name="error" location="$ISE_LIBRARY\contrib\library\utility\general\error\error-safe.ecf"/>
|
||||
|
||||
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-safe.ecf"/>
|
||||
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json-safe.ecf" readonly="false"/>
|
||||
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
|
||||
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
|
||||
<library name="wsf_html" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf_html\wsf_html-safe.ecf"/>
|
||||
<library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension-safe.ecf" readonly="false"/>
|
||||
<cluster name="src" location=".\" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
|
||||
28
modules/comments/comments.ecf
Normal file
28
modules/comments/comments.ecf
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="comments_module" uuid="C1D39ECD-6993-456B-AD14-0CF94504340F" library_target="comments_module">
|
||||
<target name="comments_module">
|
||||
<root all_classes="true"/>
|
||||
<file_rule>
|
||||
<exclude>/.git$</exclude>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" void_safety="none">
|
||||
</option>
|
||||
<setting name="concurrency" value="scoop"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
|
||||
<library name="base_extension" location="$ISE_LIBRARY\library\base_extension\base_extension.ecf"/>
|
||||
<library name="cms" location="..\..\cms.ecf" readonly="false"/>
|
||||
<library name="cms_model" location="..\..\library\model\cms_model.ecf" readonly="false"/>
|
||||
<library name="error" location="$ISE_LIBRARY\contrib\library\utility\general\error\error.ecf"/>
|
||||
|
||||
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http.ecf"/>
|
||||
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json.ecf" readonly="false"/>
|
||||
<library name="time" location="$ISE_LIBRARY\library\time\time.ecf"/>
|
||||
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf.ecf"/>
|
||||
<library name="wsf_html" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf_html\wsf_html.ecf"/>
|
||||
<library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension.ecf" readonly="false"/>
|
||||
<cluster name="src" location=".\" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
|
||||
38
modules/comments/persistence/cms_comments_storage_i.e
Normal file
38
modules/comments/persistence/cms_comments_storage_i.e
Normal file
@@ -0,0 +1,38 @@
|
||||
note
|
||||
description: "Interface for accessing comments from database."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
CMS_COMMENTS_STORAGE_I
|
||||
|
||||
feature -- Error Handling
|
||||
|
||||
error_handler: ERROR_HANDLER
|
||||
-- Error handler.
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
comment (a_cid: INTEGER_64): detachable CMS_COMMENT
|
||||
require
|
||||
a_cid > 0
|
||||
deferred
|
||||
end
|
||||
|
||||
comments_for (a_content: CMS_CONTENT): detachable LIST [CMS_COMMENT]
|
||||
-- Comments for `a_content`.
|
||||
require
|
||||
has_id: a_content.has_identifier
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Change
|
||||
|
||||
save_comment (a_comment: CMS_COMMENT)
|
||||
-- Save `a_comment`.
|
||||
deferred
|
||||
end
|
||||
|
||||
end
|
||||
46
modules/comments/persistence/cms_comments_storage_null.e
Normal file
46
modules/comments/persistence/cms_comments_storage_null.e
Normal file
@@ -0,0 +1,46 @@
|
||||
note
|
||||
description: "Summary description for {CMS_COMMENTS_STORAGE_NULL}."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_COMMENTS_STORAGE_NULL
|
||||
|
||||
inherit
|
||||
CMS_COMMENTS_STORAGE_I
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
-- Initialize `Current'.
|
||||
do
|
||||
create error_handler.make
|
||||
end
|
||||
|
||||
feature -- Error Handling
|
||||
|
||||
error_handler: ERROR_HANDLER
|
||||
-- Error handler.
|
||||
|
||||
feature -- Access
|
||||
|
||||
comment (a_cid: INTEGER_64): detachable CMS_COMMENT
|
||||
do
|
||||
end
|
||||
|
||||
comments_for (a_content: CMS_CONTENT): detachable LIST [CMS_COMMENT]
|
||||
-- Comments for `a_content`.
|
||||
do
|
||||
end
|
||||
|
||||
feature -- Change
|
||||
|
||||
save_comment (a_comment: CMS_COMMENT)
|
||||
-- Save `a_comment`.
|
||||
do
|
||||
end
|
||||
|
||||
end
|
||||
187
modules/comments/persistence/cms_comments_storage_sql.e
Normal file
187
modules/comments/persistence/cms_comments_storage_sql.e
Normal file
@@ -0,0 +1,187 @@
|
||||
note
|
||||
description: "Interface for accessing user profile contents from SQL database."
|
||||
date: "$Date: 2015-05-21 14:46:00 +0100$"
|
||||
revision: "$Revision: 96616 $"
|
||||
|
||||
class
|
||||
CMS_COMMENTS_STORAGE_SQL
|
||||
|
||||
inherit
|
||||
CMS_COMMENTS_STORAGE_I
|
||||
|
||||
CMS_PROXY_STORAGE_SQL
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Access
|
||||
|
||||
comment (a_cid: INTEGER_64): detachable CMS_COMMENT
|
||||
-- Comment with id `a_cid`.
|
||||
local
|
||||
l_parameters: STRING_TABLE [detachable ANY]
|
||||
do
|
||||
error_handler.reset
|
||||
|
||||
create l_parameters.make (1)
|
||||
l_parameters.put (a_cid, "cid")
|
||||
sql_query (sql_select_comment_by_id, l_parameters)
|
||||
sql_start
|
||||
if not has_error and not sql_after then
|
||||
Result := fetch_comment
|
||||
end
|
||||
sql_finalize
|
||||
end
|
||||
|
||||
comments_for (a_content: CMS_CONTENT): detachable LIST [CMS_COMMENT]
|
||||
-- Comments for content `a_content`.
|
||||
local
|
||||
l_parameters: STRING_TABLE [detachable ANY]
|
||||
do
|
||||
create {ARRAYED_LIST [CMS_COMMENT]} Result.make (0)
|
||||
error_handler.reset
|
||||
|
||||
create l_parameters.make (3)
|
||||
l_parameters.put (a_content.identifier, "content_id")
|
||||
from
|
||||
sql_query (sql_select_comments_for_content, l_parameters)
|
||||
sql_start
|
||||
until
|
||||
sql_after
|
||||
loop
|
||||
if attached fetch_comment as obj then
|
||||
Result.force (obj)
|
||||
end
|
||||
sql_forth
|
||||
end
|
||||
sql_finalize
|
||||
end
|
||||
|
||||
feature -- Change
|
||||
|
||||
save_comment (a_comment: CMS_COMMENT)
|
||||
-- <Precursor>
|
||||
local
|
||||
l_parameters: STRING_TABLE [detachable ANY]
|
||||
do
|
||||
error_handler.reset
|
||||
|
||||
create l_parameters.make (11)
|
||||
|
||||
l_parameters.put (a_comment.content, "content")
|
||||
l_parameters.put (a_comment.format, "format")
|
||||
if attached a_comment.author as u then
|
||||
l_parameters.put (u.id, "author")
|
||||
l_parameters.put (u.name, "author_name")
|
||||
else
|
||||
l_parameters.put (0, "author")
|
||||
if attached a_comment.author_name as l_author_name then
|
||||
l_parameters.put (l_author_name, "author_name")
|
||||
else
|
||||
l_parameters.put ("", "author_name")
|
||||
end
|
||||
end
|
||||
|
||||
l_parameters.put (a_comment.creation_date, "created")
|
||||
l_parameters.put (a_comment.modification_date, "changed")
|
||||
l_parameters.put (a_comment.status, "status")
|
||||
|
||||
if attached a_comment.parent as p then
|
||||
l_parameters.put (p.id, "parent")
|
||||
end
|
||||
|
||||
if attached a_comment.entity as l_entity then
|
||||
l_parameters.put (l_entity.identifier, "entity")
|
||||
l_parameters.put (l_entity.content_type, "entity_type")
|
||||
else
|
||||
l_parameters.put ("", "entity")
|
||||
l_parameters.put ("", "entity_type")
|
||||
end
|
||||
|
||||
sql_begin_transaction
|
||||
if a_comment.has_id then
|
||||
l_parameters.put (a_comment.id, "cid")
|
||||
sql_modify (sql_update_comment, l_parameters)
|
||||
else
|
||||
sql_insert (sql_insert_comment, l_parameters)
|
||||
if not has_error then
|
||||
a_comment.set_id (last_inserted_comment_id)
|
||||
end
|
||||
end
|
||||
if has_error then
|
||||
sql_rollback_transaction
|
||||
else
|
||||
sql_commit_transaction
|
||||
end
|
||||
sql_finalize
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
fetch_comment: detachable CMS_COMMENT
|
||||
local
|
||||
cid, uid, pid, l_entity_id: INTEGER_64
|
||||
l_entity: detachable CMS_PARTIAL_CONTENT
|
||||
do
|
||||
cid := sql_read_integer_64 (1)
|
||||
if cid > 0 then
|
||||
create Result.make
|
||||
Result.set_id (cid)
|
||||
Result.set_content (sql_read_string_32 (2))
|
||||
Result.set_format (sql_read_string (3))
|
||||
uid := sql_read_integer_64 (4)
|
||||
if uid > 0 then
|
||||
Result.set_author (create {CMS_PARTIAL_USER}.make_with_id (uid))
|
||||
end
|
||||
Result.set_author_name (sql_read_string_32 (5))
|
||||
if attached sql_read_date_time (6) as dt then
|
||||
Result.set_creation_date (dt)
|
||||
end
|
||||
if attached sql_read_date_time (7) as dt then
|
||||
Result.set_modification_date (dt)
|
||||
end
|
||||
|
||||
Result.set_status (sql_read_integer_32 (8))
|
||||
pid := sql_read_integer_64 (9)
|
||||
if pid > 0 then
|
||||
Result.set_parent (create {CMS_PARTIAL_COMMENT}.make_with_id (pid))
|
||||
end
|
||||
l_entity_id := sql_read_integer_64 (10)
|
||||
if
|
||||
attached sql_read_string (11) as l_entity_type and
|
||||
l_entity_id > 0
|
||||
then
|
||||
create l_entity.make_empty (l_entity_type)
|
||||
l_entity.set_identifier (l_entity_id.out)
|
||||
Result.set_entity (l_entity)
|
||||
end
|
||||
-- l_entity_type := sql_read_string_32 (11)
|
||||
-- if l_entity_type /= Void then
|
||||
-- Result.set_en
|
||||
-- end
|
||||
end
|
||||
end
|
||||
|
||||
last_inserted_comment_id: INTEGER_64
|
||||
-- Last insert comment id.
|
||||
do
|
||||
error_handler.reset
|
||||
sql_query (Sql_last_inserted_comment_id, Void)
|
||||
if not has_error and not sql_after then
|
||||
Result := sql_read_integer_64 (1)
|
||||
end
|
||||
sql_finalize
|
||||
end
|
||||
|
||||
feature {NONE} -- Queries
|
||||
|
||||
Sql_last_inserted_comment_id: STRING = "SELECT MAX(cid) FROM comments;"
|
||||
|
||||
sql_select_comment_by_id: STRING = "SELECT cid,content,format,author,author_name,created,changed,status,parent,entity,entity_type FROM comments WHERE cid=:cid;"
|
||||
|
||||
sql_select_comments_for_content: STRING = "SELECT cid,content,format,author,author_name,created,changed,status,parent,entity,entity_type FROM comments WHERE entity=:content_id;"
|
||||
|
||||
sql_insert_comment: STRING = "INSERT INTO comments (content,format,author,author_name,created,changed,status,parent,entity,entity_type) VALUES (:content,:format,:author,:author_name,:created,:changed,:status,:parent,:entity,:entity_type);"
|
||||
sql_update_comment: STRING = "UPDATE comments SET content=:content,format=:format,author=:author,author_name=:author_name,created=:created,changed=:changed,status=:status,parent=:parent,entity=:entity,entity_type=:entity_type WHERE cid=:cid ;"
|
||||
|
||||
end
|
||||
18
modules/comments/site/files/css/comments.css
Normal file
18
modules/comments/site/files/css/comments.css
Normal file
@@ -0,0 +1,18 @@
|
||||
div.comments-box div.title {
|
||||
font-size: x-large;
|
||||
}
|
||||
div.comments-box ul.comments {
|
||||
border-top: solid 1px #eee;
|
||||
padding: 0 0 0 20px;
|
||||
border-left: solid 5px #eee;
|
||||
list-style-type: none;
|
||||
}
|
||||
div.comments-box ul.comments li.comment {
|
||||
border-bottom: solid 1px #eee;
|
||||
}
|
||||
div.comments-box ul.comments li.comment > span.author {
|
||||
font-weight: bold;
|
||||
}
|
||||
div.comments-box ul.comments li.comment > span.info {
|
||||
font-style: italic;
|
||||
}
|
||||
17
modules/comments/site/files/scss/comments.scss
Normal file
17
modules/comments/site/files/scss/comments.scss
Normal file
@@ -0,0 +1,17 @@
|
||||
div.comments-box {
|
||||
div.title {
|
||||
font-size: x-large;
|
||||
}
|
||||
ul.comments {
|
||||
border-top: solid 1px #eee;
|
||||
padding: 0 0 0 20px;
|
||||
border-left: solid 5px #eee;
|
||||
list-style-type: none;
|
||||
li.comment {
|
||||
border-bottom: solid 1px #eee;
|
||||
&>span.author { font-weight: bold; }
|
||||
&>span.info { font-style: italic; }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
13
modules/comments/site/scripts/install.sql
Normal file
13
modules/comments/site/scripts/install.sql
Normal file
@@ -0,0 +1,13 @@
|
||||
CREATE TABLE comments(
|
||||
`cid` INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT UNIQUE,
|
||||
`content` TEXT,
|
||||
`format` VARCHAR(128),
|
||||
`author` INTEGER,
|
||||
`author_name` VARCHAR(255),
|
||||
`created` DATETIME NOT NULL,
|
||||
`changed` DATETIME NOT NULL,
|
||||
`status` INTEGER,
|
||||
`parent` INTEGER,
|
||||
`entity` VARCHAR(255), /* Associated entity */
|
||||
`entity_type` VARCHAR(255) /* Type of associated entity */
|
||||
);
|
||||
@@ -27,10 +27,6 @@ inherit
|
||||
|
||||
CMS_TAXONOMY_HOOK
|
||||
|
||||
-- CMS_HOOK_EXPORT
|
||||
|
||||
-- CMS_EXPORT_NODE_UTILITIES
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ feature -- Access
|
||||
local
|
||||
jo: JSON_OBJECT
|
||||
ja: JSON_ARRAY
|
||||
j, jterm: JSON_OBJECT
|
||||
jterm: JSON_OBJECT
|
||||
do
|
||||
create Result.make_empty
|
||||
Result.put_string (n.content_type, "type")
|
||||
|
||||
@@ -351,17 +351,83 @@ feature -- Output
|
||||
end
|
||||
a_output.append ("</p>")
|
||||
end
|
||||
elseif attached a_node.content as l_content then
|
||||
a_output.append ("<p class=%"content%">")
|
||||
if attached cms_api.format (a_node.format) as f then
|
||||
append_formatted_content_to (l_content, f, a_output)
|
||||
else
|
||||
append_formatted_content_to (l_content, cms_api.formats.default_format, a_output)
|
||||
else
|
||||
if attached a_node.content as l_content then
|
||||
a_output.append ("<p class=%"content%">")
|
||||
if attached cms_api.format (a_node.format) as f then
|
||||
append_formatted_content_to (l_content, f, a_output)
|
||||
else
|
||||
append_formatted_content_to (l_content, cms_api.formats.default_format, a_output)
|
||||
end
|
||||
a_output.append ("</p>")
|
||||
end
|
||||
a_output.append ("</p>")
|
||||
|
||||
append_comments_as_html_to (a_node, a_output, a_response)
|
||||
|
||||
end
|
||||
a_output.append ("</div>")
|
||||
end
|
||||
|
||||
append_comments_as_html_to (a_node: G; a_output: STRING; a_response: detachable CMS_RESPONSE)
|
||||
do
|
||||
if attached {CMS_COMMENTS_API} cms_api.module_api ({CMS_COMMENTS_MODULE}) as l_comments_api then
|
||||
if attached l_comments_api.comments_for (a_node) as l_comments and then not l_comments.is_empty then
|
||||
a_output.append ("<div class=%"comments-box%"><div class=%"title%">Comments</div><ul class=%"comments%">")
|
||||
across
|
||||
l_comments as ic
|
||||
loop
|
||||
append_comment_as_html_to (ic.item, a_output, a_response)
|
||||
end
|
||||
a_output.append ("</ul></div>")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
append_comment_as_html_to (a_comment: CMS_COMMENT; a_output: STRING; a_response: detachable CMS_RESPONSE)
|
||||
local
|
||||
l_ago: DATE_TIME_AGO_CONVERTER
|
||||
do
|
||||
a_output.append ("<li class=%"comment%">")
|
||||
if attached a_comment.author as l_author then
|
||||
a_output.append ("<span class=%"author%">")
|
||||
a_output.append (cms_api.html_encoded (l_author.name))
|
||||
a_output.append ("</span>")
|
||||
elseif attached a_comment.author_name as l_author_name then
|
||||
a_output.append ("<span class=%"author%">")
|
||||
a_output.append (cms_api.html_encoded (l_author_name))
|
||||
a_output.append ("</span>")
|
||||
end
|
||||
if attached a_comment.creation_date as dt then
|
||||
a_output.append (" <span class=%"info%">(")
|
||||
create l_ago.make
|
||||
a_output.append (l_ago.smart_date_duration (dt))
|
||||
a_output.append (" ")
|
||||
a_output.append (l_ago.short_date (dt))
|
||||
a_output.append (")</span>")
|
||||
end
|
||||
if attached a_comment.content as l_content then
|
||||
a_output.append ("<div class=%"content%">")
|
||||
if
|
||||
attached a_comment.format as l_format and then
|
||||
attached cms_api.format (l_format) as f
|
||||
then
|
||||
append_formatted_content_to (l_content, f, a_output)
|
||||
else
|
||||
append_formatted_content_to (l_content, cms_api.formats.default_format, a_output)
|
||||
end
|
||||
a_output.append ("</div>")
|
||||
end
|
||||
if attached a_comment.items as lst and then not lst.is_empty then
|
||||
a_output.append ("<ul class=%"comments%">")
|
||||
across
|
||||
lst as ic
|
||||
loop
|
||||
append_comment_as_html_to (ic.item, a_output, a_response)
|
||||
end
|
||||
a_output.append ("</ul>")
|
||||
end
|
||||
a_output.append ("</li>")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -21,6 +21,53 @@ feature -- Access
|
||||
Result := a_node_api.cms_api.user_api.user_by_name (a_name)
|
||||
end
|
||||
|
||||
feature -- Comments helpers
|
||||
|
||||
import_comments_file_for_entity (fn: PATH; a_entity: CMS_CONTENT; api: CMS_API; a_import_ctx: CMS_IMPORT_CONTEXT)
|
||||
local
|
||||
s: STRING
|
||||
jp: JSON_PARSER
|
||||
f: RAW_FILE
|
||||
l_comment: CMS_COMMENT
|
||||
l_log: STRING_8
|
||||
do
|
||||
if attached {CMS_COMMENTS_API} api.module_api ({CMS_COMMENTS_MODULE}) as l_comments_api then
|
||||
create f.make_with_path (fn)
|
||||
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_value as j_comments then
|
||||
if attached json_to_comments (j_comments, a_entity, l_comments_api) as l_comments then
|
||||
across
|
||||
l_comments as ic
|
||||
loop
|
||||
l_comment := ic.item
|
||||
l_comments_api.save_recursively_comment (l_comment)
|
||||
l_log := "comment #" + l_comment.id.out + " (count="+ l_comment.count.out +") %"" + f.path.utf_8_name + "%" imported"
|
||||
l_log.append (" into " + a_entity.content_type)
|
||||
if attached a_entity.identifier as l_id then
|
||||
l_log.append (" #" + l_id)
|
||||
end
|
||||
l_log.append (" .")
|
||||
a_import_ctx.log (l_log)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
feature -- Conversion
|
||||
|
||||
json_to_node (a_node_type: CMS_NODE_TYPE [CMS_NODE]; j: JSON_OBJECT; a_node_api: CMS_NODE_API): detachable CMS_NODE
|
||||
@@ -65,18 +112,36 @@ feature -- Conversion
|
||||
then
|
||||
l_node.set_link (lnk)
|
||||
end
|
||||
if attached {JSON_ARRAY} j.item ("tags") as j_tags and then j_tags.count > 0 then
|
||||
if attached {CMS_TAXONOMY_API} a_node_api.cms_api.module_api ({CMS_TAXONOMY_MODULE}) as l_taxonomy_api then
|
||||
across
|
||||
j_tags as ic
|
||||
loop
|
||||
if
|
||||
attached {JSON_OBJECT} ic.item as j_tag and then
|
||||
attached json_string_item (j_tag, "text") as l_tag_text
|
||||
then
|
||||
if attached l_taxonomy_api.term_by_text (l_tag_text, Void) as t then
|
||||
l_taxonomy_api.associate_term_with_content (t, l_node)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
apply_taxonomy_to_node (j: JSON_OBJECT; a_node: CMS_NODE; a_cms_api: CMS_API)
|
||||
require
|
||||
a_node.has_id
|
||||
local
|
||||
l_term: CMS_TERM
|
||||
do
|
||||
if attached {JSON_ARRAY} j.item ("tags") as j_tags and then j_tags.count > 0 then
|
||||
if
|
||||
attached {CMS_TAXONOMY_API} a_cms_api.module_api ({CMS_TAXONOMY_MODULE}) as l_taxonomy_api and then
|
||||
attached l_taxonomy_api.vocabularies_for_type (a_node.content_type) as l_voc_coll and then
|
||||
attached l_voc_coll.item_by_name ("Tags") as l_voc
|
||||
then
|
||||
across
|
||||
j_tags as ic
|
||||
loop
|
||||
if
|
||||
attached {JSON_OBJECT} ic.item as j_tag and then
|
||||
attached json_string_item (j_tag, "text") as l_tag_text
|
||||
then
|
||||
if attached l_taxonomy_api.term_by_text (l_tag_text, Void) as t then
|
||||
l_term := t
|
||||
else
|
||||
create l_term.make (l_tag_text)
|
||||
l_taxonomy_api.save_term (l_term, l_voc)
|
||||
end
|
||||
if l_term.has_id then
|
||||
l_taxonomy_api.associate_term_with_content (l_term, a_node)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -103,4 +168,92 @@ feature -- Conversion
|
||||
end
|
||||
end
|
||||
|
||||
json_to_comments (j: JSON_VALUE; a_entity: CMS_CONTENT; a_comments_api: CMS_COMMENTS_API): detachable LIST [CMS_COMMENT]
|
||||
do
|
||||
if attached {JSON_ARRAY} j as j_array then
|
||||
create {ARRAYED_LIST [CMS_COMMENT]} Result.make (j_array.count)
|
||||
across
|
||||
j_array as ic
|
||||
loop
|
||||
if
|
||||
attached {JSON_OBJECT} ic.item as jo and then
|
||||
attached json_to_comment (jo, a_entity, a_comments_api) as c
|
||||
then
|
||||
Result.extend (c)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
json_to_comment (j: JSON_OBJECT; a_entity: CMS_CONTENT; a_comments_api: CMS_COMMENTS_API): detachable CMS_COMMENT
|
||||
local
|
||||
l_title, l_content: detachable READABLE_STRING_32
|
||||
do
|
||||
create Result.make
|
||||
Result.set_entity (a_entity)
|
||||
if attached {JSON_STRING} j.item ("title") as j_title then
|
||||
l_title := j_title.unescaped_string_32
|
||||
if l_title.is_whitespace then
|
||||
l_title := Void
|
||||
end
|
||||
end
|
||||
|
||||
if attached {JSON_STRING} j.item ("content") as j_content then
|
||||
l_content := j_content.unescaped_string_32
|
||||
if l_content.is_whitespace then
|
||||
l_content := Void
|
||||
end
|
||||
elseif attached {JSON_STRING} j.item ("body") as j_body then
|
||||
l_content := j_body.unescaped_string_32
|
||||
if l_content.is_whitespace then
|
||||
l_content := Void
|
||||
end
|
||||
end
|
||||
|
||||
if l_content = Void then
|
||||
if l_title /= Void then
|
||||
Result.set_content (l_title)
|
||||
end
|
||||
elseif l_title = Void then
|
||||
Result.set_content (l_content)
|
||||
Result.set_format ("wikitext")
|
||||
else
|
||||
if l_content.starts_with (l_title) then
|
||||
Result.set_content (l_content)
|
||||
else
|
||||
Result.set_content (l_title + {STRING_32} "%N%N" + l_content)
|
||||
end
|
||||
Result.set_format ("wikitext")
|
||||
end
|
||||
|
||||
if attached {JSON_STRING} j.item ("format") as j_format then
|
||||
Result.set_format (j_format.unescaped_string_8)
|
||||
end
|
||||
if attached {JSON_OBJECT} j.item ("author") as j_author then
|
||||
if attached {JSON_STRING} j_author.item ("name") as j_author_name then
|
||||
if attached a_comments_api.cms_api.user_api.user_by_name (j_author_name.unescaped_string_32) as u then
|
||||
Result.set_author (u)
|
||||
Result.set_author_name (u.name)
|
||||
else
|
||||
-- User unknown!
|
||||
Result.set_author_name (j_author_name.unescaped_string_32)
|
||||
end
|
||||
end
|
||||
end
|
||||
if attached json_date_item (j, "date") as dt then
|
||||
Result.set_modification_date (dt)
|
||||
Result.set_creation_date (dt)
|
||||
end
|
||||
if
|
||||
attached j.item ("comments") as j_comments and then
|
||||
attached json_to_comments (j_comments, a_entity, a_comments_api) as lst
|
||||
then
|
||||
across
|
||||
lst as ic
|
||||
loop
|
||||
Result.extend (ic.item)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="cms" location="..\..\cms-safe.ecf"/>
|
||||
<library name="cms_model" location="..\..\library\model\cms_model-safe.ecf" readonly="false"/>
|
||||
<library name="cms_comments_module" location="..\..\modules\comments\comments-safe.ecf" readonly="false"/>
|
||||
<library name="cms_recent_changes_module" location="..\..\modules\recent_changes\recent_changes-safe.ecf" readonly="false"/>
|
||||
<library name="cms_taxonomy_module" location="..\..\modules\taxonomy\taxonomy-safe.ecf" readonly="false"/>
|
||||
<library name="error" location="$ISE_LIBRARY\contrib\library\utility\general\error\error-safe.ecf"/>
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
<exclude>/CVS$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" full_class_checking="false" void_safety="none" syntax="transitional">
|
||||
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||
<option warning="true" void_safety="none">
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
|
||||
<library name="cms" location="..\..\cms.ecf"/>
|
||||
<library name="cms_model" location="..\..\library\model\cms_model.ecf" readonly="false"/>
|
||||
<library name="cms_comments_module" location="..\..\modules\comments\comments.ecf" readonly="false"/>
|
||||
<library name="cms_recent_changes_module" location="..\..\modules\recent_changes\recent_changes.ecf" readonly="false"/>
|
||||
<library name="cms_taxonomy_module" location="..\..\modules\taxonomy\taxonomy.ecf" readonly="false"/>
|
||||
<library name="error" location="$ISE_LIBRARY\contrib\library\utility\general\error\error.ecf"/>
|
||||
|
||||
@@ -233,14 +233,13 @@ feature -- Hooks
|
||||
-- Import data identified by `a_import_id_list',
|
||||
-- or import all data if `a_import_id_list' is Void.
|
||||
local
|
||||
p: PATH
|
||||
l_id: STRING_32
|
||||
p, fp: 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.
|
||||
l_entity: detachable CMS_PAGE
|
||||
do
|
||||
if
|
||||
attached node_api as l_node_api and then
|
||||
@@ -263,65 +262,60 @@ feature -- Hooks
|
||||
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
|
||||
l_id := ic.item.name
|
||||
l_id.remove_tail (ext.count + 1)
|
||||
fp := p.extended_path (ic.item)
|
||||
if attached json_object_from_location (fp) 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
|
||||
l_entity := json_to_node_page (l_node_type, j, l_node_api)
|
||||
if l_entity /= Void then
|
||||
if l_entity.is_published then
|
||||
if l_entity.author = Void then
|
||||
-- FIXME!!!
|
||||
l_entity.set_author (l_page_api.cms_api.user)
|
||||
a_import_ctx.log (l_node_type.name + " %"" + fp.utf_8_name + "%" WARNING (Author is unknown!)")
|
||||
end
|
||||
if attached l_entity.author as l_author then
|
||||
if
|
||||
attached l_page_api.pages_with_title (l_entity.title) as l_pages and then
|
||||
not l_pages.is_empty
|
||||
then
|
||||
-- Page Already exists!
|
||||
-- FIXME/TODO
|
||||
l_entity := l_pages.first
|
||||
a_import_ctx.log (l_node_type.name + " %"" + fp.utf_8_name + "%" skipped (already exists for user #" + l_author.id.out + ")!")
|
||||
else
|
||||
if
|
||||
attached l_page_api.pages_with_title (l_page.title) as l_pages and then
|
||||
not l_pages.is_empty
|
||||
attached l_entity.parent as l_parent and then
|
||||
not l_parent.has_id
|
||||
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
|
||||
l_parentable_list.extend ([l_entity, l_parent])
|
||||
l_entity.set_parent (Void)
|
||||
end
|
||||
l_page_api.save_page (l_entity)
|
||||
apply_taxonomy_to_node (j, l_entity, l_page_api.cms_api)
|
||||
l_new_pages.force (l_entity, l_node_api.node_path (l_entity))
|
||||
a_import_ctx.log (l_node_type.name + " %"" + fp.utf_8_name + "%" imported as "+ l_entity.id.out +" for user #" + l_author.id.out + ".")
|
||||
if attached {CMS_LOCAL_LINK} l_entity.link as l_link then
|
||||
loc := l_node_api.node_path (l_entity)
|
||||
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_entity, l_link.location)
|
||||
end
|
||||
end
|
||||
else
|
||||
a_import_ctx.log (l_node_type.name + " %"" + f.path.utf_8_name + "%" skipped (Author is unknown!)")
|
||||
end
|
||||
if l_entity /= Void and then l_entity.has_id then
|
||||
-- Support for comments
|
||||
import_comments_file_for_entity (p.extended (l_id).extended ("comments.json"), l_entity, l_node_api.cms_api, a_import_ctx)
|
||||
end
|
||||
else
|
||||
a_import_ctx.log (l_node_type.name + " %"" + f.path.utf_8_name + "%" skipped (Status is Not Published!)")
|
||||
a_import_ctx.log (l_node_type.name + " %"" + fp.utf_8_name + "%" skipped (Author is unknown!)")
|
||||
end
|
||||
else
|
||||
a_import_ctx.log (l_node_type.name + " %"" + fp.utf_8_name + "%" skipped (Status is Not Published!)")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -331,14 +325,13 @@ feature -- Hooks
|
||||
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
|
||||
l_entity := ic.item.page
|
||||
update_page_parent (l_entity, ic.item.parent, l_new_pages)
|
||||
if attached l_entity.parent as l_parent then
|
||||
a_import_ctx.log (l_node_type.name + " #" + l_entity.id.out + " assigned to parent #" + l_parent.id.out)
|
||||
l_page_api.save_page (l_entity)
|
||||
else
|
||||
a_import_ctx.log (l_node_type.name + " #" + l_entity.id.out + " : unable to find parent!")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -40,10 +40,10 @@ feature -- Conversion
|
||||
if s32.is_valid_as_string_8 then
|
||||
l_wikitext := s32.as_string_8
|
||||
else
|
||||
l_wikitext := utf.utf_32_string_to_utf_8_string_8 (s32)
|
||||
l_wikitext := adapted_text (s32)
|
||||
end
|
||||
else
|
||||
l_wikitext := utf.utf_32_string_to_utf_8_string_8 (a_text)
|
||||
l_wikitext := adapted_text (a_text)
|
||||
end
|
||||
create wk.make_from_string (l_wikitext)
|
||||
if attached wk.structure as st then
|
||||
@@ -58,8 +58,19 @@ feature -- Conversion
|
||||
-- elseif attached {STRING_32} a_text as s32 then
|
||||
-- s32.wipe_out
|
||||
-- end
|
||||
a_text.append (html)
|
||||
if attached {STRING_32} a_text as a_unicode_text then
|
||||
a_text.append (utf.utf_8_string_8_to_string_32 (html))
|
||||
else
|
||||
a_text.append (html)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
adapted_text (s: READABLE_STRING_32): STRING_8
|
||||
local
|
||||
utf: UTF_CONVERTER
|
||||
do
|
||||
Result := utf.utf_32_string_to_utf_8_string_8 (s)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user