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.
This commit is contained in:
2015-08-12 17:30:07 +02:00
parent 7cb4c0e9f4
commit 46014da3d8
32 changed files with 869 additions and 151 deletions

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"/>

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]

View File

@@ -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;

View File

@@ -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 {

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>

View File

@@ -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

View File

@@ -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)

View File

@@ -97,8 +97,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 +117,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

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)

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

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)

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

View File

@@ -23,6 +23,8 @@ inherit
CMS_HOOK_BLOCK
CMS_RECENT_CHANGES_HOOK
create
make
@@ -222,9 +224,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)
@@ -253,13 +258,63 @@ feature -- Hooks
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)
create lnk.make ("Create ..", "node")
a_menu_system.primary_menu.extend (lnk)
a_menu_system.navigation_menu.extend (lnk)
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 := "trashed"
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

View File

@@ -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)

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

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"/>

View File

@@ -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

View File

@@ -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

View File

@@ -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.

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

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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,234 @@
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
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"
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)
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
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
-- populate_recent_changes (lst: LIST [CMS_RECENT_CHANGE_ITEM]; a_date: detachable DATE_TIME; a_limit: INTEGER)
-- do
-- end
end

View File

@@ -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>

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

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

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

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

View File

@@ -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

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
@@ -409,9 +409,9 @@ feature -- Blocks initialization
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["management"] := "sidebar_first"
l_table["navigation"] := "sidebar_first"
l_table["user"] := "sidebar_first"
l_table["bottom"] := "page_bottom"
block_region_settings := l_table
end
@@ -474,13 +474,13 @@ 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
@@ -596,132 +596,77 @@ 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
hooks: CMS_HOOK_CORE_MANAGER
-- Manager handling hook subscriptions.
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
-- 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
-- hooks.subscribe_to_value_table_alter_hook (h)
-- 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
hooks.invoke_value_table_alter (a_table, Current)
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
-- subscribe_to_response_alter_hook (h: CMS_HOOK_RESPONSE_ALTER)
-- -- Add `h' as subscriber of response alter hooks CMS_HOOK_RESPONSE_ALTER.
-- do
-- hooks.subscribe_to_response_alter_hook (h)
-- end
invoke_response_alter (a_response: CMS_RESPONSE)
-- Invoke value table alter hook for table `a_table'.
-- Invoke response alter hook for response `a_response'.
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
hooks.invoke_response_alter (a_response)
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
-- 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
-- hooks.subscribe_to_menu_system_alter_hook (h)
-- 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
hooks.invoke_menu_system_alter (menu_system, Current)
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
-- subscribe_to_menu_alter_hook (h: CMS_HOOK_MENU_ALTER)
-- -- Add `h' as subscriber of menu alter hooks CMS_HOOK_MENU_ALTER.
-- do
-- hooks.subscribe_to_menu_alter_hook (h)
-- 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
hooks.invoke_menu_alter (a_menu, Current)
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
-- subscribe_to_form_alter_hook (h: CMS_HOOK_FORM_ALTER)
-- -- Add `h' as subscriber of form alter hooks CMS_HOOK_FORM_ALTER.
-- do
-- hooks.subscribe_to_form_alter_hook (h)
-- 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
hooks.invoke_form_alter (a_form, a_form_data, Current)
end
feature -- Hook: block
@@ -729,25 +674,13 @@ 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})
hooks.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
hooks.invoke_block (Current)
end
feature -- Menu: change