Compare commits

...

10 Commits

Author SHA1 Message Date
jocelyn ad4f020d0e The NULL storage may look into the CMS configuration file.
This allows to run the CMS without any database.
2015-08-21 19:16:31 +02:00
jocelyn 7a13b47131 Fixed cms library compilation.
CMS_FILE_BLOCK was missing `is_empty' implementation.
2015-08-19 12:34:35 +02:00
jocelyn 923089baa1 Better js code to apply CKEditor.replace, mainly to select only textarea.name=$name.
code cleaning.
2015-08-18 19:24:18 +02:00
jocelyn cfec9dc7f8 Do not include empty blocks, this way, we avoid empty sidebars if not needed. 2015-08-18 10:58:31 +02:00
jocelyn b5e7d5d201 Require "view recent changes" permission to see the recent changes. 2015-08-17 17:40:55 +02:00
jocelyn e1bdcb965c Added permission arguments to "trash" and "Create" links.
Added blocks configuration settings via the cms.ini and "blocks" section
   ex: [blocks]
       navigation.region=sidebar_first
   This enables the site to change default block location, and even hides it easily, if the theme does not include associated region name.
2015-08-13 00:44:16 +02:00
jocelyn 0061afcbe8 use "deleted" instead of "trashed" . 2015-08-12 19:03:40 +02:00
jocelyn 6a9bc8aa42 Updated admin and recent_changes module permissions declaration. 2015-08-12 19:00:17 +02:00
jocelyn 1d7d79d69e Cleaned up hooks related code, and always go via CMS_RESPONSE.hooks 2015-08-12 17:50:23 +02:00
jocelyn 46014da3d8 Added recent_changes module.
Revisited hooks management, and added new CMS_HOOK_MANAGER.
Added admin, and other link into navigation menu that goes into first sidebar.
Fixed theme info, and template for sidebar ids.
Better css class name for cms node content.
2015-08-12 17:30:07 +02:00
48 changed files with 1040 additions and 278 deletions
+1
View File
@@ -24,6 +24,7 @@
<library name="cms_oauth_20_module" location="..\..\modules\oauth20\oauth20-safe.ecf" readonly="false"/>
<library name="cms_openid_module" location="..\..\modules\openid\openid-safe.ecf" readonly="false"/>
<library name="cms_admin_module" location="..\..\modules\admin\admin-safe.ecf" readonly="false"/>
<library name="cms_recent_changes_module" location="..\..\modules\recent_changes\recent_changes-safe.ecf" readonly="false"/>
<library name="persistence_store_odbc" location="..\..\library\persistence\store_odbc\store_odbc-safe.ecf" readonly="false"/>
<!--
<library name="persistence_store_mysql" location="..\..\library\persistence\store_mysql\store_mysql-safe.ecf" readonly="false"/>
+2 -2
View File
@@ -87,8 +87,8 @@ feature -- Hooks
register_hooks (a_response: CMS_RESPONSE)
do
a_response.subscribe_to_menu_system_alter_hook (Current)
a_response.subscribe_to_block_hook (Current)
a_response.hooks.subscribe_to_menu_system_alter_hook (Current)
a_response.hooks.subscribe_to_block_hook (Current)
end
block_list: ITERABLE [like {CMS_BLOCK}.name]
+3
View File
@@ -31,6 +31,9 @@ node=on
oauth20=on
openid=on
[blocks]
#navigation.region=sidebar_first
[admin]
# CMS Installation, are accessible by "all", "none" or uppon "permission". (default is none)
installation_access=permission
@@ -51,16 +51,24 @@ ul.horizontal li {
.sidebar {
padding: 5px;
margin: 3px;
border: solid 1px #ccc;
/* border: solid 1px #ccc; */
}
.sidebar#sidebar_first {
width: 250px;
float: left;
position: fixed;
top: 45px;
left: 0;
bottom: 0;
width: 200px;
border-right: solid 1px #ddd;
}
.sidebar#sidebar_second {
width: 250px;
float: right;
}
.sidebar + .main {
margin-left: 200px;
}
#primary-tabs ul.horizontal {
list-style-type: none;
@@ -55,15 +55,24 @@ ul.horizontal {
.sidebar {
padding: 5px;
margin: 3px;
border: solid 1px #ccc;
/* border: solid 1px #ccc; */
&#sidebar_first {
width: 250px;
float: left;
position: fixed;
top: 45px;
left: 0;
bottom: 0;
width: 200px;
border-right: solid 1px #ddd;
}
&#sidebar_second {
width: 250px;
float: right;
}
&+.main {
margin-left: 200px;
}
}
#primary-tabs {
ul.horizontal {
+1 -1
View File
@@ -49,7 +49,7 @@
{/unless}
<!-- Highlighted, Help, Content -->
<div class='span8 main'>
<div id='main' class='span8 main'>
<!-- Highlighted Section -->
{unless isempty="$page.region_highlighted"}
<div id="highlighted">{$page.region_highlighted/}</div>
@@ -8,7 +8,7 @@ regions[content] = Content
regions[highlighted] = Highlighted
regions[help] = Help
regions[footer] = Footer
regions[first_sidebar] = first sidebar
regions[second_sidebar] = second sidebar
regions[sidebar_first] = first sidebar
regions[sidebar_second] = second sidebar
regions[page_bottom] = Bottom
navigation=default_nav
navigation=default_nav
@@ -78,6 +78,11 @@ feature -- CMS setup
create {CMS_BLOG_MODULE} m.make
a_setup.register_module (m)
-- Recent changes
create {CMS_RECENT_CHANGES_MODULE} m.make
a_setup.register_module (m)
-- Miscellanious
create {CMS_DEBUG_MODULE} m.make
a_setup.register_module (m)
+4 -3
View File
@@ -90,6 +90,7 @@ feature -- Security
Result.force ("admin users")
Result.force ("admin roles")
Result.force ("admin modules")
Result.force ("install modules")
end
feature -- Hooks
@@ -97,8 +98,8 @@ feature -- Hooks
register_hooks (a_response: CMS_RESPONSE)
-- <Precursor>
do
a_response.subscribe_to_menu_system_alter_hook (Current)
a_response.subscribe_to_response_alter_hook (Current)
a_response.hooks.subscribe_to_menu_system_alter_hook (Current)
a_response.hooks.subscribe_to_response_alter_hook (Current)
end
response_alter (a_response: CMS_RESPONSE)
@@ -117,7 +118,7 @@ feature -- Hooks
-- TODO: we should probably use more side menu and less primary_menu.
create lnk.make ("Admin", "admin")
lnk.set_permission_arguments (<<"manage " + {CMS_ADMIN_MODULE}.name>>)
a_menu_system.primary_menu.extend (lnk)
a_menu_system.management_menu.extend (lnk)
end
end
@@ -84,7 +84,7 @@ feature -- Process Edit
do
create b.make_empty
f := new_edit_form (a_role, url (request.percent_encoded_path_info, Void), "edit-user")
invoke_form_alter (f, fd)
hooks.invoke_form_alter (f, fd, Current)
if request.is_post_request_method then
f.validation_actions.extend (agent edit_form_validate(?,a_role, b))
f.submit_actions.extend (agent edit_form_submit(?, a_role, b))
@@ -117,7 +117,7 @@ feature -- Process Delete
do
create b.make_empty
f := new_delete_form (a_role, url (request.percent_encoded_path_info, Void), "edit-user")
invoke_form_alter (f, fd)
hooks.invoke_form_alter (f, fd, Current)
if request.is_post_request_method then
f.process (Current)
fd := f.last_data
@@ -149,7 +149,7 @@ feature -- Process New
do
create b.make_empty
f := new_edit_form (l_role, url (request.percent_encoded_path_info, Void), "create-role")
invoke_form_alter (f, fd)
hooks.invoke_form_alter (f, fd, Current)
if request.is_post_request_method then
f.validation_actions.extend (agent new_form_validate(?, b))
f.submit_actions.extend (agent edit_form_submit(?, l_role, b))
@@ -86,7 +86,7 @@ feature -- Process Edit
do
create b.make_empty
f := new_edit_form (a_user, url (location, Void), "edit-user")
invoke_form_alter (f, fd)
hooks.invoke_form_alter (f, fd, Current)
if request.is_post_request_method then
f.submit_actions.extend (agent edit_form_submit (?, a_user, b))
f.process (Current)
@@ -118,7 +118,7 @@ feature -- Process Delete
do
create b.make_empty
f := new_delete_form (a_user, url (location, Void), "edit-user")
invoke_form_alter (f, fd)
hooks.invoke_form_alter (f, fd, Current)
if request.is_post_request_method then
f.process (Current)
fd := f.last_data
@@ -151,7 +151,7 @@ feature -- Process New
do
create b.make_empty
f := new_edit_form (l_user, url (location, Void), "create-user")
invoke_form_alter (f, fd)
hooks.invoke_form_alter (f, fd, Current)
if request.is_post_request_method then
f.validation_actions.extend (agent new_form_validate (?, b))
f.submit_actions.extend (agent edit_form_submit (?, l_user, b))
+2 -2
View File
@@ -95,8 +95,8 @@ feature -- Hooks configuration
-- Module hooks configuration.
do
auto_subscribe_to_hooks (a_response)
a_response.subscribe_to_block_hook (Current)
a_response.subscribe_to_value_table_alter_hook (Current)
a_response.hooks.subscribe_to_block_hook (Current)
a_response.hooks.subscribe_to_value_table_alter_hook (Current)
end
value_table_alter (a_value: CMS_VALUE_TABLE; a_response: CMS_RESPONSE)
+2 -2
View File
@@ -105,8 +105,8 @@ feature -- Hooks configuration
-- Module hooks configuration.
do
auto_subscribe_to_hooks (a_response)
a_response.subscribe_to_block_hook (Current)
a_response.subscribe_to_value_table_alter_hook (Current)
a_response.hooks.subscribe_to_block_hook (Current)
a_response.hooks.subscribe_to_value_table_alter_hook (Current)
end
feature -- Hooks
+2 -2
View File
@@ -151,8 +151,8 @@ feature -- Hooks
register_hooks (a_response: CMS_RESPONSE)
do
a_response.subscribe_to_menu_system_alter_hook (Current)
a_response.subscribe_to_response_alter_hook (Current)
a_response.hooks.subscribe_to_menu_system_alter_hook (Current)
a_response.hooks.subscribe_to_response_alter_hook (Current)
end
response_alter (a_response: CMS_RESPONSE)
+19 -4
View File
@@ -236,28 +236,43 @@ feature -- Access: Node
end
recent_nodes (params: CMS_DATA_QUERY_PARAMETERS): ITERABLE [CMS_NODE]
-- List of the `a_rows' most recent nodes starting from `a_offset'.
-- 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 := full_node (node_storage.node_by_id (a_id))
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 := full_node (node_storage.node_by_id_and_revision (a_node_id, a_revision_id))
Result := safe_full_node (node_storage.node_by_id_and_revision (a_node_id, a_revision_id))
end
full_node (a_node: detachable CMS_NODE): detachable CMS_NODE
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
+74 -6
View File
@@ -23,6 +23,8 @@ inherit
CMS_HOOK_BLOCK
CMS_RECENT_CHANGES_HOOK
create
make
@@ -171,6 +173,7 @@ feature -- Access
Result.force ("view revisions own " + l_type_name)
end
end
Result.force ("view trash")
end
end
@@ -222,9 +225,12 @@ feature -- Hooks
register_hooks (a_response: CMS_RESPONSE)
-- <Precursor>
do
a_response.subscribe_to_menu_system_alter_hook (Current)
a_response.subscribe_to_block_hook (Current)
a_response.subscribe_to_response_alter_hook (Current)
a_response.hooks.subscribe_to_menu_system_alter_hook (Current)
a_response.hooks.subscribe_to_block_hook (Current)
a_response.hooks.subscribe_to_response_alter_hook (Current)
-- Module specific hook, if available.
a_response.hooks.subscribe_to_hook (Current, {CMS_RECENT_CHANGES_HOOK})
end
response_alter (a_response: CMS_RESPONSE)
@@ -250,16 +256,78 @@ feature -- Hooks
menu_system_alter (a_menu_system: CMS_MENU_SYSTEM; a_response: CMS_RESPONSE)
local
lnk: CMS_LOCAL_LINK
perms: ARRAYED_LIST [READABLE_STRING_8]
do
debug
create lnk.make ("List of nodes", "nodes")
a_menu_system.primary_menu.extend (lnk)
a_menu_system.navigation_menu.extend (lnk)
end
create lnk.make ("Trash", "trash")
a_menu_system.primary_menu.extend (lnk)
a_menu_system.navigation_menu.extend (lnk)
lnk.set_permission_arguments (<<"view trash">>)
create lnk.make ("Create ..", "node")
a_menu_system.primary_menu.extend (lnk)
a_menu_system.navigation_menu.extend (lnk)
if attached node_api as l_node_api then
create perms.make (2)
perms.force ("create any node")
across
l_node_api.content_types as ic
loop
perms.force ("create " + ic.item.name)
end
lnk.set_permission_arguments (perms)
end
end
populate_recent_changes (a_changes: CMS_RECENT_CHANGE_CONTAINER; a_sources: LIST [READABLE_STRING_8])
local
params: CMS_DATA_QUERY_PARAMETERS
ch: CMS_RECENT_CHANGE_ITEM
n: CMS_NODE
l_info: STRING_8
l_src: detachable READABLE_STRING_8
l_nodes: ITERABLE [CMS_NODE]
do
create params.make (0, a_changes.limit)
if attached node_api as l_node_api then
across
l_node_api.content_types as ic
loop
a_sources.force (ic.item.name)
end
l_src := a_changes.source
if attached a_changes.date as l_date then
l_nodes := l_node_api.recent_node_changes_before (params, l_date)
else
l_nodes := l_node_api.recent_node_changes_before (params, create {DATE_TIME}.make_now_utc)
end
across l_nodes as ic loop
n := ic.item
if l_src = Void or else l_src.is_case_insensitive_equal_general (n.content_type) then
n := l_node_api.full_node (n)
create ch.make (n.content_type, create {CMS_LOCAL_LINK}.make (n.title, "node/" + n.id.out), n.modification_date)
if n.creation_date ~ n.modification_date then
l_info := "new"
if not n.is_published then
l_info.append (" (unpublished)")
end
else
if n.is_trashed then
l_info := "deleted"
else
l_info := "updated"
if not n.is_published then
l_info.append (" (unpublished)")
end
end
end
ch.set_information (l_info)
ch.set_author (n.author)
a_changes.force (ch)
end
end
end
end
end
@@ -62,14 +62,14 @@ feature -- Forms ...
sum.set_text_value (a_node.summary)
end
sum.set_label ("Summary")
sum.set_description ("This is the summary")
sum.set_description ("Text displayed in short view.")
sum.set_is_required (False)
create fset.make
-- Add summary
fset.extend (sum)
fset.extend_html_text("<br />")
fset.extend_html_text("<br/>")
-- Add content
fset.extend (ta)
@@ -300,6 +300,7 @@ feature -- Output
end
end
create s.make_empty
s.append ("<div class=%"cms-node node-" + a_node.content_type + "%">")
s.append ("<div class=%"info%"> ")
if attached a_node.author as l_author then
s.append (" by ")
@@ -339,6 +340,7 @@ feature -- Output
s.append ("</p>")
end
s.append ("</div>")
a_response.set_title (a_node.title)
a_response.set_main_content (s)
+4 -4
View File
@@ -54,7 +54,7 @@ feature -- Execution
node_api.has_permission_for_action_on_node ("edit", l_node, user)
then
f := new_edit_form (l_node, url (location, Void), "edit-" + l_type.name, l_type)
invoke_form_alter (f, fd)
hooks.invoke_form_alter (f, fd, Current)
if request.is_post_request_method then
f.validation_actions.extend (agent edit_form_validate (?, b))
f.submit_actions.extend (agent edit_form_submit (?, l_node, l_type, b))
@@ -80,7 +80,7 @@ feature -- Execution
node_api.has_permission_for_action_on_node ("delete", l_node, user)
then
f := new_delete_form (l_node, url (location, Void), "delete-" + l_type.name, l_type)
invoke_form_alter (f, fd)
hooks.invoke_form_alter (f, fd, Current)
if request.is_post_request_method then
f.process (Current)
fd := f.last_data
@@ -104,7 +104,7 @@ feature -- Execution
node_api.has_permission_for_action_on_node ("trash", l_node, user)
then
f := new_trash_form (l_node, url (location, Void), "trash-" + l_type.name, l_type)
invoke_form_alter (f, fd)
hooks.invoke_form_alter (f, fd, Current)
if request.is_post_request_method then
f.process (Current)
fd := f.last_data
@@ -137,7 +137,7 @@ feature -- Execution
if has_permissions (<<"create any", "create " + l_type.name>>) then
if attached l_type.new_node (Void) as l_node then
f := new_edit_form (l_node, url (location, Void), "edit-" + l_type.name, l_type)
invoke_form_alter (f, fd)
hooks.invoke_form_alter (f, fd, Current)
if request.is_post_request_method then
f.validation_actions.extend (agent edit_form_validate (?, b))
f.submit_actions.extend (agent edit_form_submit (?, l_node, l_type, b))
-1
View File
@@ -274,7 +274,6 @@ feature {NONE} -- Trash:Restore
r: GENERIC_VIEW_CMS_RESPONSE
b: STRING
n: CMS_NODE
l_link: CMS_LOCAL_LINK
do
if attached {WSF_STRING} req.path_parameter ("id") as l_id then
if
@@ -56,7 +56,6 @@ feature -- Execution
process
-- Computed response message.
local
b: detachable STRING_8
nid: INTEGER_64
l_node: like node
do
+1
View File
@@ -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_recent_changes_module" location="..\..\modules\recent_changes\recent_changes-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="http_authorization" location="$ISE_LIBRARY\contrib\library\web\authentication\http_authorization\http_authorization-safe.ecf" readonly="false"/>
@@ -90,6 +90,11 @@ feature -- Access
deferred
end
recent_node_changes_before (a_lower: INTEGER; a_count: INTEGER; a_date: DATE_TIME): LIST [CMS_NODE]
-- List of recent changes, before `a_date', according to `params' settings.
deferred
end
node_by_id (a_id: INTEGER_64): detachable CMS_NODE
-- Retrieve node by id `a_id', if any.
require
@@ -59,6 +59,12 @@ feature -- Access: node
create {ARRAYED_LIST [CMS_NODE]} Result.make (0)
end
recent_node_changes_before (a_lower: INTEGER; a_count: INTEGER; a_date: DATE_TIME): LIST [CMS_NODE]
-- List of recent changes, before `a_date', according to `params' settings.
do
create {ARRAYED_LIST [CMS_NODE]} Result.make (0)
end
node_by_id (a_id: INTEGER_64): detachable CMS_NODE
-- <Precursor>
do
@@ -128,7 +128,7 @@ feature -- Access
from
create l_parameters.make (2)
l_parameters.put (a_count, "rows")
l_parameters.put (a_count, "size")
l_parameters.put (a_lower, "offset")
sql_query (sql_select_recent_nodes, l_parameters)
sql_start
@@ -142,6 +142,34 @@ feature -- Access
end
end
recent_node_changes_before (a_lower: INTEGER; a_count: INTEGER; a_date: DATE_TIME): LIST [CMS_NODE]
-- List of recent changes, before `a_date', according to `params' settings.
local
l_parameters: STRING_TABLE [detachable ANY]
do
create {ARRAYED_LIST [CMS_NODE]} Result.make (0)
error_handler.reset
write_information_log (generator + ".nodes")
from
create l_parameters.make (3)
l_parameters.put (a_count, "size")
l_parameters.put (a_lower, "offset")
l_parameters.put (a_date, "date")
sql_query (sql_select_recent_node_changes_before, l_parameters)
sql_start
until
sql_after
loop
if attached fetch_node as l_node then
Result.force (l_node)
end
sql_forth
end
end
node_by_id (a_id: INTEGER_64): detachable CMS_NODE
-- Retrieve node by id `a_id', if any.
local
@@ -402,7 +430,9 @@ feature {NONE} -- Queries
sql_select_node_by_id_and_revision: STRING = "SELECT nodes.nid, node_revisions.revision, nodes.type, node_revisions.title, node_revisions.summary, node_revisions.content, node_revisions.format, node_revisions.author, nodes.publish, nodes.created, node_revisions.changed, node_revisions.status FROM nodes INNER JOIN node_revisions ON nodes.nid = node_revisions.nid WHERE nodes.nid = :nid AND node_revisions.revision = :revision ORDER BY node_revisions.revision DESC;"
sql_select_recent_nodes: STRING = "SELECT nid, revision, type, title, summary, content, format, author, publish, created, changed, status FROM nodes ORDER BY nid DESC, publish DESC LIMIT :rows OFFSET :offset ;"
sql_select_recent_nodes: STRING = "SELECT nid, revision, type, title, summary, content, format, author, publish, created, changed, status FROM nodes ORDER BY nid DESC, publish DESC LIMIT :size OFFSET :offset ;"
sql_select_recent_node_changes_before: STRING = "SELECT nid, revision, type, title, summary, content, format, author, publish, created, changed, status FROM nodes WHERE changed <= :date ORDER BY changed DESC, nid DESC LIMIT :size OFFSET :offset ;"
sql_insert_node: STRING = "INSERT INTO nodes (revision, type, title, summary, content, format, publish, created, changed, status, author) VALUES (:revision, :type, :title, :summary, :content, :format, :publish, :created, :changed, :status, :author);"
-- SQL Insert to add a new node.
+2 -2
View File
@@ -192,8 +192,8 @@ feature -- Hooks configuration
-- Module hooks configuration.
do
auto_subscribe_to_hooks (a_response)
a_response.subscribe_to_block_hook (Current)
a_response.subscribe_to_value_table_alter_hook (Current)
a_response.hooks.subscribe_to_block_hook (Current)
a_response.hooks.subscribe_to_value_table_alter_hook (Current)
end
feature -- Hooks
+2 -2
View File
@@ -170,8 +170,8 @@ feature -- Hooks configuration
-- Module hooks configuration.
do
auto_subscribe_to_hooks (a_response)
a_response.subscribe_to_block_hook (Current)
a_response.subscribe_to_value_table_alter_hook (Current)
a_response.hooks.subscribe_to_block_hook (Current)
a_response.hooks.subscribe_to_value_table_alter_hook (Current)
end
feature -- Hooks
@@ -0,0 +1,82 @@
note
description: "Container of recent change items, and associated parameters."
date: "$Date$"
revision: "$Revision$"
class
CMS_RECENT_CHANGE_CONTAINER
inherit
ITERABLE [CMS_RECENT_CHANGE_ITEM]
create
make
feature -- Initialization
make (a_limit: NATURAL_32; a_date: detachable DATE_TIME; a_source: detachable READABLE_STRING_8)
do
limit := a_limit
date := a_date
source := a_source
create items.make (a_limit.to_integer_32)
end
feature -- Settings
limit: NATURAL_32
date: detachable DATE_TIME
source: detachable READABLE_STRING_8
feature -- Access
items: ARRAYED_LIST [CMS_RECENT_CHANGE_ITEM]
-- List of recent events.
count: INTEGER
-- Number of change items.
do
Result := items.count
end
feature -- Access
new_cursor: ITERATION_CURSOR [CMS_RECENT_CHANGE_ITEM]
-- <Precursor>
do
Result := items.new_cursor
end
feature -- Change
force (a_item: CMS_RECENT_CHANGE_ITEM)
-- Add `a_item'.
do
items.force (a_item)
end
feature -- Sorting
sort
-- Sort `items' from older, to newer.
do
change_item_sorter.sort (items)
end
reverse_sort
-- Sort `items' from newer to older.
do
change_item_sorter.reverse_sort (items)
end
feature {NONE} -- Implementation
change_item_sorter: QUICK_SORTER [CMS_RECENT_CHANGE_ITEM]
-- New change item sorter.
once
create Result.make (create {COMPARABLE_COMPARATOR [CMS_RECENT_CHANGE_ITEM]})
end
end
@@ -0,0 +1,64 @@
note
description: "Information related to change event."
date: "$Date$"
revision: "$Revision$"
class
CMS_RECENT_CHANGE_ITEM
inherit
COMPARABLE
create
make
feature {NONE} -- Initialization
make (a_source: READABLE_STRING_8; lnk: CMS_LOCAL_LINK; a_date_time: DATE_TIME)
do
source := a_source
link := lnk
date := a_date_time
end
feature -- Access
link: CMS_LOCAL_LINK
-- Local link associated with the resource.
date: DATE_TIME
-- Time of the event item.
author: detachable CMS_USER
-- Optional author.
source: READABLE_STRING_8
-- Source of Current event.
information: detachable READABLE_STRING_8
-- Optional information related to Current event.
--| For instance: creation, trashed, modified, ...
feature -- Element change
set_author (u: like author)
-- Set `author' to `u'.
do
author := u
end
set_information (a_info: like information)
-- Set `information' to `a_info'.
do
information := a_info
end
feature -- Comparison
is_less alias "<" (other: like Current): BOOLEAN
-- <Precursor>
do
Result := date < other.date
end
end
@@ -0,0 +1,20 @@
note
description: "Hook provided by module {CMS_RECENT_CHANGES_MODULE}."
date: "$Date$"
revision: "$Revision$"
deferred class
CMS_RECENT_CHANGES_HOOK
inherit
CMS_HOOK
feature -- Invocation
populate_recent_changes (a_changes: CMS_RECENT_CHANGE_CONTAINER; a_sources: LIST [READABLE_STRING_8])
-- Populate recent changes inside `a_changes' according to associated parameters.
-- Also provide sources of information.
deferred
end
end
@@ -0,0 +1,242 @@
note
description: "CMS module that bring support for recent changes."
date: "$Date: 2015-02-13 13:08:13 +0100 (ven., 13 févr. 2015) $"
revision: "$Revision: 96616 $"
class
CMS_RECENT_CHANGES_MODULE
inherit
CMS_MODULE
rename
module_api as recent_changes_api
redefine
register_hooks,
permissions
end
CMS_HOOK_MENU_SYSTEM_ALTER
CMS_HOOK_RESPONSE_ALTER
create
make
feature {NONE} -- Initialization
make
-- Create Current module, disabled by default.
do
version := "1.0"
description := "Service to access recent changes"
package := "notification"
end
feature -- Access
name: STRING = "recent_changes"
permissions: LIST [READABLE_STRING_8]
-- List of permission ids, used by this module, and declared.
do
Result := Precursor
Result.force ("view recent changes")
end
feature -- Access: router
setup_router (a_router: WSF_ROUTER; a_api: CMS_API)
-- <Precursor>
do
a_router.handle ("/recent_changes/", create {WSF_URI_AGENT_HANDLER}.make (agent handle_recent_changes (a_api, ?, ?)), a_router.methods_head_get)
end
feature -- Handler
handle_recent_changes (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE)
local
r: CMS_RESPONSE
l_changes: CMS_RECENT_CHANGE_CONTAINER
l_sources: ARRAYED_LIST [READABLE_STRING_8]
dt, prev_dt: detachable DATE
ch: detachable CMS_RECENT_CHANGE_ITEM
htdate: HTTP_DATE
l_content: STRING
l_form: CMS_FORM
l_select: WSF_FORM_SELECT
l_until_date: detachable DATE_TIME
l_filter_source: detachable READABLE_STRING_8
l_size: NATURAL_32
l_query: STRING
opt: WSF_FORM_SELECT_OPTION
do
if attached {WSF_STRING} req.query_parameter ("date") as p_until_date then
create htdate.make_from_timestamp (p_until_date.value.to_integer_64)
l_until_date := htdate.date_time
-- l_until_date.second_add (-1)
end
if attached {WSF_STRING} req.query_parameter ("filter") as p_filter then
l_filter_source := p_filter.url_encoded_value
end
if attached {WSF_STRING} req.query_parameter ("size") as p_size then
l_size := p_size.integer_value.to_natural_32
end
if l_size = 0 then
l_size := 25
end
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
if r.has_permission ("view recent changes") then
create l_changes.make (l_size, l_until_date, l_filter_source)
create l_content.make (1024)
if attached r.hooks.subscribers ({CMS_RECENT_CHANGES_HOOK}) as lst then
create l_sources.make (lst.count)
across
lst as ic
loop
if attached {CMS_RECENT_CHANGES_HOOK} ic.item as h then
h.populate_recent_changes (l_changes, l_sources)
end
end
create l_form.make (req.percent_encoded_path_info, "recent-changes")
create l_select.make ("source")
l_select.set_label ("Sources")
create opt.make ("", "...")
l_select.add_option (opt)
across
l_sources as ic
loop
create opt.make (ic.item, ic.item)
if l_filter_source /= Void and then ic.item.is_case_insensitive_equal (l_filter_source) then
opt.set_is_selected (True)
end
l_select.add_option (opt)
end
l_form.extend (l_select)
l_form.extend_html_text ("<br/>")
l_form.append_to_html (create {CMS_TO_WSF_THEME}.make (r, r.theme), l_content)
end
l_changes.reverse_sort
l_content.append ("<table class=%"recent-changes%" style=%"border-spacing: 5px;%">")
l_content.append ("<thead>")
l_content.append ("<tr>")
l_content.append ("<th>Date</th>")
l_content.append ("<th>Source</th>")
l_content.append ("<th>Resource</th>")
l_content.append ("<th>User</th>")
l_content.append ("<th>Information</th>")
l_content.append ("</tr>")
l_content.append ("</thead>")
l_content.append ("<tbody>")
across
l_changes as ic
loop
ch := ic.item
dt := ch.date.date
if dt /~ prev_dt then
l_content.append ("<tr>")
l_content.append ("<td class=%"title%" colspan=%"5%">")
l_content.append (dt.formatted_out ("ddd, dd mmm yyyy"))
l_content.append ("</td>")
l_content.append ("</tr>")
end
prev_dt := dt
l_content.append ("<tr>")
l_content.append ("<td class=%"date%">")
create htdate.make_from_date_time (ch.date)
htdate.append_to_rfc1123_string (l_content)
l_content.append ("</td>")
l_content.append ("<td class=%"source%">" + ch.source + "</td>")
l_content.append ("<td class=%"resource%">")
l_content.append (r.link (ch.link.title, ch.link.location, Void))
l_content.append ("</td>")
l_content.append ("<td class=%"user%">")
if attached ch.author as u then
l_content.append (r.link (u.name, "user/" + u.id.out, Void))
end
l_content.append ("</td>")
l_content.append ("<td class=%"info%">")
if attached ch.information as l_info then
l_content.append ("<strong>" + l_info + "</strong> ")
end
l_content.append ("</td>")
l_content.append ("</tr>%N")
end
l_content.append ("</tbody>")
l_content.append ("</table>%N")
if ch /= Void then
if l_until_date /= Void then
l_content.append (" <a href=%"")
l_content.append (r.url (r.location, Void))
l_content.append ("?size=" + l_size.out + "%">&lt;&lt;</a> ")
end
if l_until_date /~ ch.date then
create htdate.make_from_date_time (ch.date)
create l_query.make_from_string ("size=" + l_size.out)
l_query.append ("&date=")
l_query.append (htdate.timestamp.out)
if l_filter_source /= Void then
l_query.append ("&filter=")
l_query.append (l_filter_source)
end
l_content.append ("<a href=%"")
l_content.append (r.url (r.location, create {CMS_API_OPTIONS}.make_from_manifest (<<["query", l_query]>>)))
l_content.append ("%">More ...</a>")
end
end
r.set_main_content (l_content)
if l_until_date = Void then
r.set_title ("Recent changes")
else
create htdate.make_from_date_time (l_until_date)
r.set_title ("Recent changes before " + htdate.string)
end
else
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api)
end
r.execute
end
feature -- Hooks configuration
register_hooks (a_response: CMS_RESPONSE)
-- Module hooks configuration.
do
a_response.hooks.subscribe_to_menu_system_alter_hook (Current)
a_response.hooks.subscribe_to_response_alter_hook (Current)
end
feature -- Hook
response_alter (a_response: CMS_RESPONSE)
do
a_response.add_additional_head_line ("[
<style>
table.recent-changes th { padding: 3px; }
table.recent-changes td { padding: 3px; border: dotted 1px #ddd; }
table.recent-changes td.date { padding-left: 15px; }
table.recent-changes td.title { font-weight: bold; }
</style>
]", True)
end
menu_system_alter (a_menu_system: CMS_MENU_SYSTEM; a_response: CMS_RESPONSE)
-- Hook execution on collection of menu contained by `a_menu_system'
-- for related response `a_response'.
local
lnk: CMS_LOCAL_LINK
do
create lnk.make ("Recent changes", "recent_changes/")
lnk.set_permission_arguments (<<"view recent changes">>)
a_menu_system.navigation_menu.extend (lnk)
end
end
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="recent_changes" uuid="1C3893A3-46FC-4E60-86AE-37CB7939BC7F" library_target="recent_changes">
<target name="recent_changes">
<root all_classes="true"/>
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="false" is_attached_by_default="true" void_safety="all" syntax="transitional">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<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="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
<library name="cms" location="..\..\cms-safe.ecf"/>
<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="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
<library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension-safe.ecf" readonly="false"/>
<library name="wsf_html" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf_html\wsf_html-safe.ecf" readonly="false"/>
<cluster name="src" location=".\" recursive="true"/>
</target>
</system>
+3
View File
@@ -8,4 +8,7 @@ note
deferred class
CMS_HOOK
note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end
+9 -6
View File
@@ -17,24 +17,27 @@ inherit
feature -- Hook
auto_subscribe_to_hooks (a_response: CMS_RESPONSE)
local
l_manager: CMS_HOOK_CORE_MANAGER
do
l_manager := a_response.hooks
if attached {CMS_HOOK_MENU_SYSTEM_ALTER} Current as h_menu_system_alter then
a_response.subscribe_to_menu_system_alter_hook (h_menu_system_alter)
l_manager.subscribe_to_menu_system_alter_hook (h_menu_system_alter)
end
if attached {CMS_HOOK_MENU_ALTER} Current as h_menu_alter then
a_response.subscribe_to_menu_alter_hook (h_menu_alter)
l_manager.subscribe_to_menu_alter_hook (h_menu_alter)
end
if attached {CMS_HOOK_BLOCK} Current as h_block then
a_response.subscribe_to_block_hook (h_block)
l_manager.subscribe_to_block_hook (h_block)
end
if attached {CMS_HOOK_FORM_ALTER} Current as h_form then
a_response.subscribe_to_form_alter_hook (h_form)
l_manager.subscribe_to_form_alter_hook (h_form)
end
if attached {CMS_HOOK_VALUE_TABLE_ALTER} Current as h_value then
a_response.subscribe_to_value_table_alter_hook (h_value)
l_manager.subscribe_to_value_table_alter_hook (h_value)
end
if attached {CMS_HOOK_RESPONSE_ALTER} Current as h_resp then
a_response.subscribe_to_response_alter_hook (h_resp)
l_manager.subscribe_to_response_alter_hook (h_resp)
end
end
+160
View File
@@ -0,0 +1,160 @@
note
description: "[
Hook manager specific for Core hooks.
- Value Table Alter
-
]"
date: "$Date$"
revision: "$Revision$"
class
CMS_HOOK_CORE_MANAGER
inherit
CMS_HOOK_MANAGER
create
make
feature -- Hook: value alter
subscribe_to_value_table_alter_hook (h: CMS_HOOK_VALUE_TABLE_ALTER)
-- Add `h' as subscriber of value table alter hooks CMS_HOOK_VALUE_TABLE_ALTER.
do
subscribe_to_hook (h, {CMS_HOOK_VALUE_TABLE_ALTER})
end
invoke_value_table_alter (a_table: CMS_VALUE_TABLE; a_response: CMS_RESPONSE)
-- Invoke value table alter hook for table `a_table'.
do
if attached subscribers ({CMS_HOOK_VALUE_TABLE_ALTER}) as lst then
across
lst as ic
loop
if attached {CMS_HOOK_VALUE_TABLE_ALTER} ic.item as h then
h.value_table_alter (a_table, a_response)
end
end
end
end
feature -- Hook: response
subscribe_to_response_alter_hook (h: CMS_HOOK_RESPONSE_ALTER)
-- Add `h' as subscriber of response alter hooks CMS_HOOK_RESPONSE_ALTER.
do
subscribe_to_hook (h, {CMS_HOOK_RESPONSE_ALTER})
end
invoke_response_alter (a_response: CMS_RESPONSE)
-- Invoke response alter hook for response `a_response'.
do
if attached subscribers ({CMS_HOOK_RESPONSE_ALTER}) as lst then
across
lst as ic
loop
if attached {CMS_HOOK_RESPONSE_ALTER} ic.item as h then
h.response_alter (a_response)
end
end
end
end
feature -- Hook: menu_system_alter
subscribe_to_menu_system_alter_hook (h: CMS_HOOK_MENU_SYSTEM_ALTER)
-- Add `h' as subscriber of menu system alter hooks CMS_HOOK_MENU_SYSTEM_ALTER.
do
subscribe_to_hook (h, {CMS_HOOK_MENU_SYSTEM_ALTER})
end
invoke_menu_system_alter (a_menu_system: CMS_MENU_SYSTEM; a_response: CMS_RESPONSE)
-- Invoke menu system alter hook for menu `a_menu_system', and response `a_response'.
do
if attached subscribers ({CMS_HOOK_MENU_SYSTEM_ALTER}) as lst then
across
lst as ic
loop
if attached {CMS_HOOK_MENU_SYSTEM_ALTER} ic.item as h then
h.menu_system_alter (a_menu_system, a_response)
end
end
end
end
feature -- Hook: menu_alter
subscribe_to_menu_alter_hook (h: CMS_HOOK_MENU_ALTER)
-- Add `h' as subscriber of menu alter hooks CMS_HOOK_MENU_ALTER.
do
subscribe_to_hook (h, {CMS_HOOK_MENU_ALTER})
end
invoke_menu_alter (a_menu: CMS_MENU; a_response: CMS_RESPONSE)
-- Invoke menu alter hook for menu `a_menu', and response `a_response'.
do
if attached subscribers ({CMS_HOOK_MENU_ALTER}) as lst then
across
lst as c
loop
if attached {CMS_HOOK_MENU_ALTER} c.item as h then
h.menu_alter (a_menu, a_response)
end
end
end
end
feature -- Hook: form_alter
subscribe_to_form_alter_hook (h: CMS_HOOK_FORM_ALTER)
-- Add `h' as subscriber of form alter hooks CMS_HOOK_FORM_ALTER,
-- and response `a_response'.
do
subscribe_to_hook (h, {CMS_HOOK_MENU_ALTER})
end
invoke_form_alter (a_form: CMS_FORM; a_form_data: detachable WSF_FORM_DATA; a_response: CMS_RESPONSE)
-- Invoke form alter hook for form `a_form' and associated data `a_form_data'
do
if attached subscribers ({CMS_HOOK_FORM_ALTER}) as lst then
across
lst as c
loop
if attached {CMS_HOOK_FORM_ALTER} c.item as h then
h.form_alter (a_form, a_form_data, a_response)
end
end
end
end
feature -- Hook: block
subscribe_to_block_hook (h: CMS_HOOK_BLOCK)
-- Add `h' as subscriber of hooks CMS_HOOK_BLOCK.
do
subscribe_to_hook (h, {CMS_HOOK_BLOCK})
end
invoke_block (a_response: CMS_RESPONSE)
-- Invoke block hook for response `a_response' in order to get block from modules.
do
if attached subscribers ({CMS_HOOK_BLOCK}) as lst then
across
lst as c
loop
if attached {CMS_HOOK_BLOCK} c.item as h then
across
h.block_list as blst
loop
h.get_block_view (blst.item, a_response)
end
end
end
end
end
note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end
+55
View File
@@ -0,0 +1,55 @@
note
description: "Hooks manager."
date: "$Date$"
revision: "$Revision$"
class
CMS_HOOK_MANAGER
create
make
feature {NONE} -- Initialization
make
do
create all_subscribers.make (0)
end
feature -- Access
subscribers (a_type: TYPE [CMS_HOOK]): detachable LIST [CMS_HOOK]
-- Subscribers of hook typed `a_type'.
do
Result := all_subscribers.item (a_type)
end
feature -- Change
subscribe_to_hook (h: CMS_HOOK; a_hook_type: TYPE [CMS_HOOK])
-- Subscribe `h' to hooks identified by `a_hook_type'.
local
lst: detachable LIST [CMS_HOOK]
do
lst := all_subscribers.item (a_hook_type)
if lst = Void then
create {ARRAYED_LIST [CMS_HOOK]} lst.make (1)
all_subscribers.force (lst, a_hook_type)
end
if not lst.has (h) then
lst.force (h)
end
end
feature {NONE} -- Implementation
all_subscribers: HASH_TABLE [LIST [CMS_HOOK], TYPE [CMS_HOOK]]
invariant
all_subscribers /= Void
note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end
+9 -1
View File
@@ -23,7 +23,12 @@ feature -- Access
html_options: detachable CMS_HTML_OPTIONS
-- Optional addition html options.
feature -- status report
feature -- Status report
is_empty: BOOLEAN
-- Is current block empty?
deferred
end
is_enabled: BOOLEAN
-- Is current block enabled?
@@ -93,4 +98,7 @@ feature -- Status report
end
end
note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end
+11 -5
View File
@@ -21,11 +21,10 @@ feature {NONE} -- Initialization
feature -- Access
name: READABLE_STRING_8
-- Block region name.
-- Block region name.
blocks: ARRAYED_LIST [CMS_BLOCK]
-- List of blocks.
-- List of blocks.
feature -- Element change
@@ -35,8 +34,15 @@ feature -- Element change
blocks.force (b)
end
;note
copyright: "2011-2014, Jocelyn Fiat, Eiffel Software and others"
remove (b: CMS_BLOCK)
require
has_block_b: blocks.has (b)
do
blocks.prune_all (b)
end
note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
+7 -1
View File
@@ -49,6 +49,12 @@ feature -- Access
feature -- Status report
is_empty: BOOLEAN
-- Is current block empty?
do
Result := is_raw and content.is_empty
end
is_raw: BOOLEAN assign set_is_raw
-- Is raw?
-- If True, do not get wrapped it with block specific div
@@ -87,7 +93,7 @@ feature -- Conversion
end
end
note
copyright: "2011-2014, Jocelyn Fiat, Eiffel Software and others"
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
+31 -5
View File
@@ -57,12 +57,39 @@ feature -- Access
root_path: detachable PATH
-- Root location for files universe.
resolved_location: PATH
-- Path of related file, taking into account `root_path' and `location'.
do
-- Process html generation
if attached root_path as l_root_path then
Result := l_root_path.extended_path (location)
else
Result := location
end
end
feature -- Status report
is_empty: BOOLEAN
-- Is current block empty?
do
Result := not exists
debug ("cms")
Result := True
end
end
is_raw: BOOLEAN
-- Is raw?
-- If True, do not get wrapped it with block specific div
exists: BOOLEAN
local
ut: FILE_UTILITIES
do
Result := ut.file_path_exists (resolved_location)
end
feature -- Element change
set_is_raw (b: BOOLEAN)
@@ -94,11 +121,7 @@ feature -- Conversion
ut: FILE_UTILITIES
do
-- Process html generation
if attached root_path as l_root_path then
p := l_root_path.extended_path (location)
else
p := location
end
p := resolved_location
if ut.file_path_exists (p) then
create f.make_with_path (p)
if f.exists and then f.is_access_readable then
@@ -145,4 +168,7 @@ feature -- Debug
end
Result.append ("%N")
end
note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end
+9
View File
@@ -31,6 +31,12 @@ feature -- Access
feature -- Status report
is_empty: BOOLEAN
-- Is current block empty?
do
Result := menu.is_empty
end
is_horizontal: BOOLEAN assign set_is_horizontal
-- Is horizontal layout for the menu?
@@ -72,4 +78,7 @@ feature -- Conversion
Result := a_theme.menu_html (menu, is_horizontal, html_options)
end
note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end
@@ -69,6 +69,9 @@ feature -- Access
feature -- Status report
is_empty: BOOLEAN = False
-- Is current block empty?
is_raw: BOOLEAN
-- Is raw?
-- If True, do not get wrapped it with block specific div
@@ -192,4 +195,7 @@ feature -- Debug
end
Result.append ("%N}")
end
note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end
+22 -20
View File
@@ -8,6 +8,7 @@ deferred class
CMS_EDITOR
feature -- Initialisation
load_assets : STRING
-- Loads all assest needed to show the editor
deferred
@@ -15,57 +16,55 @@ feature -- Initialisation
feature -- Javascript
javascript_replace_textarea (a_textarea : WSF_FORM_TEXTAREA) : STRING
javascript_replace_textarea (a_textarea : WSF_FORM_TEXTAREA): STRING
-- Javascript code that replaces a textarea with the editor. The editor instance should be saved in editor_variable
deferred
end
javascript_restore_textarea (a_textarea : WSF_FORM_TEXTAREA) : STRING
javascript_restore_textarea (a_textarea : WSF_FORM_TEXTAREA): STRING
-- Javascript code that restores a textarea
deferred
end
javascript_textarea_to_editor(a_textarea : WSF_FORM_TEXTAREA) : STRING
javascript_textarea_to_editor (a_textarea : WSF_FORM_TEXTAREA): STRING
-- Javascript code to display the textarea as a WYSIWIG editor as soon as the document is loaded
do
Result := javascript_ready(javascript_replace_textarea (a_textarea))
Result := javascript_ready (javascript_replace_textarea (a_textarea))
end
javascript_textarea_to_editor_if_selected (a_textarea : WSF_FORM_TEXTAREA; a_select_field : WSF_FORM_SELECT; a_value : STRING) : STRING
javascript_textarea_to_editor_if_selected (a_textarea: WSF_FORM_TEXTAREA; a_select_field : WSF_FORM_SELECT; a_value : STRING) : STRING
-- Javascript code to display the textarea as a WYSIWIG editor if a_select_field has a_value
local
initial_replace_code, on_select_replace_code : STRING
initial_replace_code, on_select_replace_code: STRING
do
-- Javascript that replaces the textarea if a_value is selected at load time
initial_replace_code := javascript_ready(javascript_if_selected(a_select_field, a_value, javascript_replace_textarea(a_textarea)))
initial_replace_code := javascript_ready (javascript_if_selected (a_select_field, a_value, javascript_replace_textarea (a_textarea)))
-- Javascript code that replaces the textarea as soon as value is selected at a_select_field
on_select_replace_code := javascript_ready(
javascript_init_editor_variable(a_textarea) +
javascript_on_select(a_select_field, a_value,
javascript_init_editor_variable (a_textarea) +
javascript_on_select (a_select_field, a_value,
-- If a_value is selected, replace textarea
javascript_replace_textarea(a_textarea),
javascript_replace_textarea (a_textarea),
-- Otherwise restore it
javascript_restore_textarea(a_textarea)
javascript_restore_textarea (a_textarea)
)
)
Result := initial_replace_code + " " + on_select_replace_code
end
javascript_init_editor_variable(a_textarea : WSF_FORM_TEXTAREA) : STRING
javascript_init_editor_variable (a_textarea : WSF_FORM_TEXTAREA) : STRING
-- Returns the javascript code that initializes a local variable to store the editor instance
do
Result := "var " + editor_variable(a_textarea) + "; "
Result := "var " + editor_variable (a_textarea) + "; "
end
javascript_if_selected(a_select_field : WSF_FORM_SELECT; a_value : STRING; a_code : STRING) : STRING
javascript_if_selected (a_select_field : WSF_FORM_SELECT; a_value : STRING; a_code : STRING) : STRING
-- Javascript that executes a_code if a_value is selected at a_select_field
do
Result := "if($('#" + field_id(a_select_field) + "').val() == %"" + a_value + "%"){ " + a_code + " }"
Result := "if($('#" + field_id (a_select_field) + "').val() == %"" + a_value + "%"){ " + a_code + " }"
end
javascript_ready (a_code : STRING) : STRING
@@ -77,8 +76,8 @@ feature -- Javascript
javascript_on_select (a_select_field : WSF_FORM_SELECT; a_value : STRING; a_then : STRING; a_else : STRING) : STRING
-- Javascript code that executes a_then if at the given select_field the given string value is selected, otherwise it executes a_else
do
Result := "$('#" + field_id(a_select_field) + "').change(function(){" +
javascript_if_selected(a_select_field, a_value, a_then) +
Result := "$('#" + field_id (a_select_field) + "').change(function(){" +
javascript_if_selected (a_select_field, a_value, a_then) +
"else{" +
a_else +
"}" +
@@ -100,7 +99,10 @@ feature -- Helper
editor_variable (a_textarea : WSF_FORM_TEXTAREA) : STRING
-- Returns the variable name that stores the editor instance of the given textarea
do
Result := "editor_" + a_textarea.name
Result := "cms_ckeditor_" + a_textarea.name
end
note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end
+9 -4
View File
@@ -23,15 +23,20 @@ feature -- Javascript
javascript_replace_textarea (a_textarea : WSF_FORM_TEXTAREA) : STRING
-- <Precursor>
do
-- Replaces the textarea with an editor instance. Save the instance in a variable
Result := editor_variable(a_textarea) + " = CKEDITOR.replace( '" + a_textarea.name + "' );"
-- Replaces the textarea with an editor instance. Save the instance in a variable
Result := "$(%"textarea[name="+ a_textarea.name +"]%").each(function() {"
Result.append (editor_variable (a_textarea) + " = CKEDITOR.replace(this);")
Result.append ("});")
end
javascript_restore_textarea (a_textarea : WSF_FORM_TEXTAREA) : STRING
-- <Precursor>
do
-- Replaces the textarea with an editor instance. Save the instance in a variable
Result := "if (" + editor_variable(a_textarea) + " != undefined) " + editor_variable(a_textarea) + ".destroy();"
-- Replaces the textarea with an editor instance. Save the instance in a variable
Result := "if (" + editor_variable (a_textarea) + " != undefined) " + editor_variable (a_textarea) + ".destroy();"
end
note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end
+5 -2
View File
@@ -19,7 +19,7 @@ feature -- Basic operation
prepare (a_response: CMS_RESPONSE)
do
a_response.invoke_form_alter (Current, Void)
a_response.hooks.invoke_form_alter (Current, Void, a_response)
end
process (a_response: CMS_RESPONSE)
@@ -29,7 +29,7 @@ feature -- Basic operation
on_prepared (a_response: CMS_RESPONSE; fd: WSF_FORM_DATA)
do
a_response.invoke_form_alter (Current, fd)
a_response.hooks.invoke_form_alter (Current, fd, a_response)
end
on_processed (a_response: CMS_RESPONSE; fd: WSF_FORM_DATA)
@@ -39,4 +39,7 @@ feature -- Basic operation
end
end
note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end
+7 -7
View File
@@ -24,15 +24,15 @@ feature -- Initialisation
make (a_name: like name)
-- <Precursor>
do
precursor(a_name)
Precursor (a_name)
-- By default we don't replace the textarea by an editor
editor := False;
editor_activated := False;
end
feature -- Access
editor : BOOLEAN
editor_activated : BOOLEAN
-- True if the textarea should be replaced by the editor. Default is false.
format_field : detachable WSF_FORM_SELECT
@@ -45,13 +45,13 @@ feature -- Editor
show_as_editor
-- The textarea will be replaced by a wysiwyg editor
do
editor := True
editor_activated := True
end
show_as_editor_if_selected (a_select_field : WSF_FORM_SELECT; a_value : STRING)
-- Replaces the textarea only if a_select_field has a_value (or the value gets selected)
do
editor := True
editor_activated := True
format_field := a_select_field
condition_value := a_value
end
@@ -61,8 +61,8 @@ feature -- Conversion
append_item_to_html (a_theme: WSF_THEME; a_html: STRING_8)
do
-- Add javascript to replace textarea with editor
precursor(a_theme, a_html)
if editor then
Precursor (a_theme, a_html)
if editor_activated then
a_html.append (load_assets)
a_html.append ("<script type=%"text/javascript%">");
if attached format_field as l_field and then attached condition_value as l_value then
+1 -1
View File
@@ -51,7 +51,7 @@ feature -- Hooks configuration
-- Module hooks configuration.
do
auto_subscribe_to_hooks (a_response)
a_response.subscribe_to_block_hook (Current)
a_response.hooks.subscribe_to_block_hook (Current)
end
feature -- Hooks
+12
View File
@@ -101,7 +101,19 @@ feature -- Custom
custom_value (a_name: READABLE_STRING_GENERAL; a_type: detachable READABLE_STRING_8): detachable READABLE_STRING_32
-- Data for name `a_name' and type `a_type' (or default if none).
local
s: STRING_32
do
if attached api as l_api then
create s.make_from_string_general ("custom_values")
if a_type /= Void then
s.append_character ('.')
s.append_string_general (a_type)
end
s.append_character ('.')
s.append_string_general (a_name)
Result := l_api.setup.text_item (s)
end
end
+50 -177
View File
@@ -33,7 +33,7 @@ feature {NONE} -- Initialization
get_theme
create menu_system.make
initialize_block_region_settings
create hook_subscribers.make (0)
create hooks.make
register_hooks
end
@@ -403,19 +403,26 @@ feature -- Blocks initialization
create regions.make_caseless (5)
create l_table.make_caseless (10)
l_table["top"] := "top"
l_table["header"] := "header"
l_table["highlighted"] := "highlighted"
l_table["help"] := "help"
l_table["content"] := "content"
l_table["footer"] := "footer"
l_table["management"] := "first_sidebar"
l_table["navigation"] := "first_sidebar"
l_table["user"] := "first_sidebar"
l_table["bottom"] := "page_bottom"
l_table["top"] := block_region_preference ("top", "top")
l_table["header"] := block_region_preference ("header", "header")
l_table["highlighted"] := block_region_preference ("highlighted", "highlighted")
l_table["help"] := block_region_preference ("help", "help")
l_table["content"] := block_region_preference ("content", "content")
l_table["footer"] := block_region_preference ("footer", "footer")
l_table["management"] := block_region_preference ("management", "sidebar_first")
l_table["navigation"] := block_region_preference ("navigation", "sidebar_first")
l_table["user"] := block_region_preference ("user", "sidebar_first")
l_table["bottom"] := block_region_preference ("bottom", "page_bottom")
block_region_settings := l_table
end
block_region_preference (a_block_id: READABLE_STRING_8; a_default_region: READABLE_STRING_8): READABLE_STRING_8
-- Region associated with `a_block_id' in configuration, if any.
do
Result := setup.text_item_or_default ("blocks." + a_block_id + ".region", a_default_region)
end
feature -- Blocks regions
regions: STRING_TABLE [CMS_BLOCK_REGION]
@@ -430,12 +437,15 @@ feature -- Blocks regions
do
l_region_name := block_region_settings.item (b.name)
if l_region_name = Void then
if a_default_region /= Void then
if attached setup.text_item ("blocks." + b.name + ".region") as l_setup_name then
l_region_name := l_setup_name.as_string_8 -- FIXME: potential truncated string 32.
-- Remember for later.
block_region_settings.force (l_region_name, b.name)
elseif a_default_region /= Void then
l_region_name := a_default_region
else
-- Default .. put it in same named region
-- Maybe a bad idea
l_region_name := b.name.as_lower
end
end
@@ -474,16 +484,16 @@ feature -- Blocks
add_block (content_block, "content")
if attached management_menu_block as l_block then
add_block (l_block, "first_sidebar")
add_block (l_block, "sidebar_first")
end
if attached navigation_menu_block as l_block then
add_block (l_block, "first_sidebar")
add_block (l_block, "sidebar_first")
end
if attached user_menu_block as l_block then
add_block (l_block, "first_sidebar")
add_block (l_block, "sidebar_second")
end
invoke_block
hooks.invoke_block (Current)
debug ("cms")
add_block (create {CMS_CONTENT_BLOCK}.make ("made_with", Void, "Made with <a href=%"http://www.eiffel.com/%">EWF</a>", Void), "footer")
end
@@ -596,159 +606,8 @@ feature -- Blocks
feature -- Hooks
hook_subscribers: HASH_TABLE [LIST [CMS_HOOK], TYPE [CMS_HOOK]]
-- Hook indexed by hook identifier.
subscribe_to_hook (h: CMS_HOOK; a_hook_type: TYPE [CMS_HOOK])
-- Subscribe `h' to hooks identified by `a_hook_type'.
local
lst: detachable LIST [CMS_HOOK]
do
lst := hook_subscribers.item (a_hook_type)
if lst = Void then
create {ARRAYED_LIST [CMS_HOOK]} lst.make (1)
hook_subscribers.force (lst, a_hook_type)
end
if not lst.has (h) then
lst.force (h)
end
end
feature -- Hook: value alter
subscribe_to_value_table_alter_hook (h: CMS_HOOK_VALUE_TABLE_ALTER)
-- Add `h' as subscriber of value table alter hooks CMS_HOOK_VALUE_TABLE_ALTER.
do
subscribe_to_hook (h, {CMS_HOOK_VALUE_TABLE_ALTER})
end
invoke_value_table_alter (a_table: CMS_VALUE_TABLE)
-- Invoke value table alter hook for table `a_table'.
do
if attached hook_subscribers.item ({CMS_HOOK_VALUE_TABLE_ALTER}) as lst then
across
lst as c
loop
if attached {CMS_HOOK_VALUE_TABLE_ALTER} c.item as h then
h.value_table_alter (a_table, Current)
end
end
end
end
feature -- Hook: response
subscribe_to_response_alter_hook (h: CMS_HOOK_RESPONSE_ALTER)
-- Add `h' as subscriber of response alter hooks CMS_HOOK_RESPONSE_ALTER.
do
subscribe_to_hook (h, {CMS_HOOK_RESPONSE_ALTER})
end
invoke_response_alter (a_response: CMS_RESPONSE)
-- Invoke value table alter hook for table `a_table'.
do
if attached hook_subscribers.item ({CMS_HOOK_RESPONSE_ALTER}) as lst then
across
lst as c
loop
if attached {CMS_HOOK_RESPONSE_ALTER} c.item as h then
h.response_alter (a_response)
end
end
end
end
feature -- Hook: menu_system_alter
subscribe_to_menu_system_alter_hook (h: CMS_HOOK_MENU_SYSTEM_ALTER)
-- Add `h' as subscriber of menu system alter hooks CMS_HOOK_MENU_SYSTEM_ALTER.
do
subscribe_to_hook (h, {CMS_HOOK_MENU_SYSTEM_ALTER})
end
invoke_menu_system_alter (a_menu_system: CMS_MENU_SYSTEM)
-- Invoke menu system alter hook for menu `a_menu_system'.
do
if attached hook_subscribers.item ({CMS_HOOK_MENU_SYSTEM_ALTER}) as lst then
across
lst as c
loop
if attached {CMS_HOOK_MENU_SYSTEM_ALTER} c.item as h then
h.menu_system_alter (a_menu_system, Current)
end
end
end
end
feature -- Hook: menu_alter
subscribe_to_menu_alter_hook (h: CMS_HOOK_MENU_ALTER)
-- Add `h' as subscriber of menu alter hooks CMS_HOOK_MENU_ALTER.
do
subscribe_to_hook (h, {CMS_HOOK_MENU_ALTER})
end
invoke_menu_alter (a_menu: CMS_MENU)
-- Invoke menu alter hook for menu `a_menu'.
do
if attached hook_subscribers.item ({CMS_HOOK_MENU_ALTER}) as lst then
across
lst as c
loop
if attached {CMS_HOOK_MENU_ALTER} c.item as h then
h.menu_alter (a_menu, Current)
end
end
end
end
feature -- Hook: form_alter
subscribe_to_form_alter_hook (h: CMS_HOOK_FORM_ALTER)
-- Add `h' as subscriber of form alter hooks CMS_HOOK_FORM_ALTER.
do
subscribe_to_hook (h, {CMS_HOOK_MENU_ALTER})
end
invoke_form_alter (a_form: CMS_FORM; a_form_data: detachable WSF_FORM_DATA)
-- Invoke form alter hook for form `a_form' and associated data `a_form_data'
do
if attached hook_subscribers.item ({CMS_HOOK_FORM_ALTER}) as lst then
across
lst as c
loop
if attached {CMS_HOOK_FORM_ALTER} c.item as h then
h.form_alter (a_form, a_form_data, Current)
end
end
end
end
feature -- Hook: block
subscribe_to_block_hook (h: CMS_HOOK_BLOCK)
-- Add `h' as subscriber of hooks CMS_HOOK_BLOCK.
do
subscribe_to_hook (h, {CMS_HOOK_BLOCK})
end
invoke_block
-- Invoke block hook in order to get block from modules.
do
if attached hook_subscribers.item ({CMS_HOOK_BLOCK}) as lst then
across
lst as c
loop
if attached {CMS_HOOK_BLOCK} c.item as h then
across
h.block_list as blst
loop
h.get_block_view (blst.item, Current)
end
end
end
end
end
hooks: CMS_HOOK_CORE_MANAGER
-- Manager handling hook subscriptions.
feature -- Menu: change
@@ -771,9 +630,6 @@ feature -- Menu: change
add_to_menu (lnk: CMS_LINK; m: CMS_MENU)
do
-- if attached {CMS_LOCAL_LINK} lnk as l_local then
-- l_local.get_is_active (request)
-- end
m.extend (lnk)
end
@@ -882,13 +738,15 @@ feature -- Generation
prepare (page: CMS_HTML_PAGE)
local
lnk: CMS_LINK
l_region: CMS_BLOCK_REGION
l_menu_list_prepared: ARRAYED_LIST [CMS_LINK_COMPOSITE]
l_empty_blocks: detachable ARRAYED_LIST [CMS_BLOCK]
do
-- Menu
create {CMS_LOCAL_LINK} lnk.make ("Home", "")
lnk.set_weight (-10)
add_to_primary_menu (lnk)
invoke_menu_system_alter (menu_system)
hooks.invoke_menu_system_alter (menu_system, Current)
if api.enabled_modules.count = 0 then
add_to_primary_menu (create {CMS_LOCAL_LINK}.make ("Install", "admin/install"))
@@ -900,14 +758,29 @@ feature -- Generation
across
regions as reg_ic
loop
l_region := reg_ic.item
across
reg_ic.item.blocks as ic
l_region.blocks as ic
loop
if attached {CMS_MENU_BLOCK} ic.item as l_menu_block then
l_menu_list_prepared.force (l_menu_block.menu)
prepare_links (l_menu_block.menu)
if l_menu_block.menu.is_empty then
if l_empty_blocks = Void then
create l_empty_blocks.make (1)
end
l_empty_blocks.force (l_menu_block)
end
end
end
if l_empty_blocks /= Void then
across
l_empty_blocks as ic
loop
l_region.remove (ic.item)
end
l_empty_blocks := Void
end
end
-- Prepare menu not in a block.
@@ -931,10 +804,10 @@ feature -- Generation
custom_prepare (page)
-- Cms response
invoke_response_alter (Current)
hooks.invoke_response_alter (Current)
-- Cms values
invoke_value_table_alter (values)
hooks.invoke_value_table_alter (values, Current)
-- Predefined values
page.register_variable (page, "page") -- DO NOT REMOVE