Compare commits
5 Commits
eiffelstud
...
es_rev9797
| Author | SHA1 | Date | |
|---|---|---|---|
| ed24eb7c94 | |||
| 43d6b4a197 | |||
| dffd06e331 | |||
| 463105f29f | |||
| abebd00a4f |
@@ -19,6 +19,7 @@
|
|||||||
<library name="cms_blog_module" location="..\..\modules\blog\cms_blog_module-safe.ecf" readonly="false"/>
|
<library name="cms_blog_module" location="..\..\modules\blog\cms_blog_module-safe.ecf" readonly="false"/>
|
||||||
<library name="cms_demo_module" location="modules\demo\cms_demo_module-safe.ecf" readonly="false"/>
|
<library name="cms_demo_module" location="modules\demo\cms_demo_module-safe.ecf" readonly="false"/>
|
||||||
<library name="cms_email_service" location="..\..\library\email\email-safe.ecf" readonly="false"/>
|
<library name="cms_email_service" location="..\..\library\email\email-safe.ecf" readonly="false"/>
|
||||||
|
<library name="cms_feed_aggregator_module" location="..\..\modules\feed_aggregator\feed_aggregator-safe.ecf" readonly="false"/>
|
||||||
<library name="cms_model" location="..\..\library\model\cms_model-safe.ecf" readonly="false"/>
|
<library name="cms_model" location="..\..\library\model\cms_model-safe.ecf" readonly="false"/>
|
||||||
<library name="cms_node_module" location="..\..\modules\node\node-safe.ecf" readonly="false"/>
|
<library name="cms_node_module" location="..\..\modules\node\node-safe.ecf" readonly="false"/>
|
||||||
<library name="cms_oauth_20_module" location="..\..\modules\oauth20\oauth20-safe.ecf" readonly="false"/>
|
<library name="cms_oauth_20_module" location="..\..\modules\oauth20\oauth20-safe.ecf" readonly="false"/>
|
||||||
|
|||||||
@@ -10,3 +10,4 @@ set ROC_CMS_DIR=%~dp0
|
|||||||
%ROC_CMD% install --module ..\..\modules\oauth20 --dir %ROC_CMS_DIR%
|
%ROC_CMD% install --module ..\..\modules\oauth20 --dir %ROC_CMS_DIR%
|
||||||
%ROC_CMD% install --module ..\..\modules\openid --dir %ROC_CMS_DIR%
|
%ROC_CMD% install --module ..\..\modules\openid --dir %ROC_CMS_DIR%
|
||||||
%ROC_CMD% install --module ..\..\modules\recent_changes --dir %ROC_CMS_DIR%
|
%ROC_CMD% install --module ..\..\modules\recent_changes --dir %ROC_CMS_DIR%
|
||||||
|
%ROC_CMD% install --module ..\..\modules\feed_aggregator --dir %ROC_CMS_DIR%
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ feature -- Hooks
|
|||||||
|
|
||||||
block_list: ITERABLE [like {CMS_BLOCK}.name]
|
block_list: ITERABLE [like {CMS_BLOCK}.name]
|
||||||
do
|
do
|
||||||
Result := <<"demo-info">>
|
Result := <<"?demo-info">>
|
||||||
end
|
end
|
||||||
|
|
||||||
get_block_view (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE)
|
get_block_view (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE)
|
||||||
@@ -103,8 +103,8 @@ feature -- Hooks
|
|||||||
m: CMS_MENU
|
m: CMS_MENU
|
||||||
lnk: CMS_LOCAL_LINK
|
lnk: CMS_LOCAL_LINK
|
||||||
do
|
do
|
||||||
if a_block_id.is_case_insensitive_equal_general ("demo-info") then
|
if a_block_id.same_string ("demo-info") then
|
||||||
if a_response.request.request_uri.starts_with ("/demo/") then
|
if a_response.location.starts_with_general ("demo/") then
|
||||||
create m.make_with_title (a_block_id, "Demo", 2)
|
create m.make_with_title (a_block_id, "Demo", 2)
|
||||||
create lnk.make ("demo: abc", "demo/abc")
|
create lnk.make ("demo: abc", "demo/abc")
|
||||||
m.extend (lnk)
|
m.extend (lnk)
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ smtp=localhost:25
|
|||||||
# Default is "on"
|
# Default is "on"
|
||||||
# for each module, this can be overwritten with
|
# for each module, this can be overwritten with
|
||||||
# module_name= on or off
|
# module_name= on or off
|
||||||
*=off
|
*=all
|
||||||
admin=on
|
admin=on
|
||||||
auth=on
|
auth=on
|
||||||
basic_auth=on
|
basic_auth=on
|
||||||
@@ -33,6 +33,17 @@ openid=on
|
|||||||
|
|
||||||
[blocks]
|
[blocks]
|
||||||
#navigation.region=sidebar_first
|
#navigation.region=sidebar_first
|
||||||
|
feed.eiffel.region=feed_eiffel
|
||||||
|
feed.eiffel.condition=is_front
|
||||||
|
|
||||||
|
feed.forum.region=feed_forum
|
||||||
|
feed.forum.condition=is_front
|
||||||
|
|
||||||
|
feed.stackoverflow.region=feed_stackoverflow
|
||||||
|
feed.stackoverflow.condition=is_front
|
||||||
|
|
||||||
|
#management.condition=is_front
|
||||||
|
#navigation.condition=is_front
|
||||||
|
|
||||||
[admin]
|
[admin]
|
||||||
# CMS Installation, are accessible by "all", "none" or uppon "permission". (default is none)
|
# CMS Installation, are accessible by "all", "none" or uppon "permission". (default is none)
|
||||||
|
|||||||
28
examples/demo/site/config/modules/feed_aggregator/feeds.json
Normal file
28
examples/demo/site/config/modules/feed_aggregator/feeds.json
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"ids": ["eiffel", "forum"],
|
||||||
|
"feeds": {
|
||||||
|
"eiffel": {
|
||||||
|
"title": "Eiffel related posts.",
|
||||||
|
"expiration": "21600",
|
||||||
|
"size": 10,
|
||||||
|
"locations": [
|
||||||
|
"https://bertrandmeyer.com/feed/",
|
||||||
|
"https://room.eiffel.com/blog/feed",
|
||||||
|
"https://room.eiffel.com/article/feed",
|
||||||
|
"https://room.eiffel.com/library/feed"
|
||||||
|
]
|
||||||
|
, "categories": ["Eiffel"]
|
||||||
|
,"option_description": "enabled"
|
||||||
|
},
|
||||||
|
"forum": {
|
||||||
|
"title": "Eiffel Forum",
|
||||||
|
"expiration": "21600",
|
||||||
|
"size": 10,
|
||||||
|
"locations": [
|
||||||
|
"https://groups.google.com/forum/feed/eiffel-users/msgs/atom.xml?num=15".
|
||||||
|
"http://stackoverflow.com/feeds/tag?tagnames=eiffel&sort=newest"
|
||||||
|
]
|
||||||
|
,"option_description": "enabled"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
div.feed ul {
|
||||||
|
list-style: none;
|
||||||
|
position: relative;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
width: 99%;
|
||||||
|
}
|
||||||
|
div.feed li {
|
||||||
|
/* border-top: solid 1px #ddd; */
|
||||||
|
padding: 0;
|
||||||
|
margin: 0 0 5px 0;
|
||||||
|
}
|
||||||
|
div.feed li a {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
div.feed li .date {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: small;
|
||||||
|
}
|
||||||
|
div.feed li .category {
|
||||||
|
margin-left: 20px;
|
||||||
|
font-size: 8px;
|
||||||
|
height: 9px;
|
||||||
|
overflow: hidden;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
div.feed li .description {
|
||||||
|
margin-left: 20px;
|
||||||
|
font-size: small;
|
||||||
|
height: 18px;
|
||||||
|
overflow: hidden;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
div.feed li:hover {
|
||||||
|
margin-bottom: 23px;
|
||||||
|
}
|
||||||
|
div.feed li:hover .description {
|
||||||
|
padding: 5px;
|
||||||
|
position: absolute;
|
||||||
|
height: auto;
|
||||||
|
overflow-y: scroll;
|
||||||
|
overflow-x: scroll;
|
||||||
|
color: #000;
|
||||||
|
background-color: #fff;
|
||||||
|
border: solid 1px #000;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
div.feed li:hover:last-child {
|
||||||
|
margin-bottom: 28px;
|
||||||
|
}
|
||||||
|
div.feed li .description::after {
|
||||||
|
content: "...";
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
div.feed {
|
||||||
|
ul {
|
||||||
|
list-style: none;
|
||||||
|
position: relative;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
width: 99%;
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
/* border-top: solid 1px #ddd; */
|
||||||
|
padding: 0;
|
||||||
|
margin: 0 0 5px 0;
|
||||||
|
|
||||||
|
a {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.date {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: small;
|
||||||
|
}
|
||||||
|
.category {
|
||||||
|
margin-left: 20px;
|
||||||
|
font-size: 8px;
|
||||||
|
height: 9px;
|
||||||
|
overflow: hidden;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
.description {
|
||||||
|
margin-left: 20px;
|
||||||
|
font-size: small;
|
||||||
|
height: 18px;
|
||||||
|
overflow: hidden;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
margin-bottom: 23px;
|
||||||
|
.description {
|
||||||
|
padding: 5px;
|
||||||
|
position: absolute;
|
||||||
|
height: auto;
|
||||||
|
overflow-y: scroll;
|
||||||
|
overflow-x: scroll;
|
||||||
|
color: #000;
|
||||||
|
background-color: #fff;
|
||||||
|
border: solid 1px #000;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 28px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.description::after { content: "..."; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -62,9 +62,15 @@
|
|||||||
<!-- Main Content Section -->
|
<!-- Main Content Section -->
|
||||||
{unless isempty="$page_title"}<h1 class="page-title">{$page_title/}</h1>{/unless}
|
{unless isempty="$page_title"}<h1 class="page-title">{$page_title/}</h1>{/unless}
|
||||||
{$page.region_content/}
|
{$page.region_content/}
|
||||||
|
{if condition="$page.is_front"}
|
||||||
|
{if isset="$page.region_feed_eiffel"}
|
||||||
|
<div class="column" style="width: 45%; float: left">{$page.region_feed_eiffel/}</div>
|
||||||
|
{/if}
|
||||||
|
{if isset="$page.region_feed_forum"}
|
||||||
|
<div class="column" style="width: 45%; float: left">{$page.region_feed_forum/}</div>
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -82,6 +82,9 @@ feature -- CMS setup
|
|||||||
create {CMS_RECENT_CHANGES_MODULE} m.make
|
create {CMS_RECENT_CHANGES_MODULE} m.make
|
||||||
a_setup.register_module (m)
|
a_setup.register_module (m)
|
||||||
|
|
||||||
|
-- Recent changes
|
||||||
|
create {FEED_AGGREGATOR_MODULE} m.make
|
||||||
|
a_setup.register_module (m)
|
||||||
|
|
||||||
-- Miscellanious
|
-- Miscellanious
|
||||||
create {CMS_DEBUG_MODULE} m.make
|
create {CMS_DEBUG_MODULE} m.make
|
||||||
|
|||||||
@@ -33,11 +33,53 @@ feature -- Query
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
resolved_text_list_item (k: READABLE_STRING_GENERAL): detachable LIST [READABLE_STRING_32]
|
||||||
|
-- List of String item associated with key `k',
|
||||||
|
-- and expanded values to resolved variables ${varname}.
|
||||||
|
do
|
||||||
|
if attached text_list_item (k) as lst then
|
||||||
|
from
|
||||||
|
lst.start
|
||||||
|
until
|
||||||
|
lst.after
|
||||||
|
loop
|
||||||
|
lst.replace (resolved_expression (lst.item))
|
||||||
|
lst.forth
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
resolved_text_table_item (k: READABLE_STRING_GENERAL): detachable STRING_TABLE [READABLE_STRING_32]
|
||||||
|
-- Table of String item associated with key `k',
|
||||||
|
-- and expanded values to resolved variables ${varname}.
|
||||||
|
do
|
||||||
|
if attached text_table_item (k) as tb then
|
||||||
|
from
|
||||||
|
tb.start
|
||||||
|
until
|
||||||
|
tb.after
|
||||||
|
loop
|
||||||
|
tb.replace (resolved_expression (tb.item_for_iteration), tb.key_for_iteration)
|
||||||
|
tb.forth
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
text_item (k: READABLE_STRING_GENERAL): detachable READABLE_STRING_32
|
text_item (k: READABLE_STRING_GENERAL): detachable READABLE_STRING_32
|
||||||
-- String item associated with key `k'.
|
-- String item associated with key `k'.
|
||||||
deferred
|
deferred
|
||||||
end
|
end
|
||||||
|
|
||||||
|
text_list_item (k: READABLE_STRING_GENERAL): detachable LIST [READABLE_STRING_32]
|
||||||
|
-- List of String item associated with key `k'.
|
||||||
|
deferred
|
||||||
|
end
|
||||||
|
|
||||||
|
text_table_item (k: READABLE_STRING_GENERAL): detachable STRING_TABLE [READABLE_STRING_32]
|
||||||
|
-- Table of String item associated with key `k'.
|
||||||
|
deferred
|
||||||
|
end
|
||||||
|
|
||||||
integer_item (k: READABLE_STRING_GENERAL): INTEGER
|
integer_item (k: READABLE_STRING_GENERAL): INTEGER
|
||||||
-- Integer item associated with key `k'.
|
-- Integer item associated with key `k'.
|
||||||
deferred
|
deferred
|
||||||
@@ -109,7 +151,7 @@ feature -- Duplication
|
|||||||
end
|
end
|
||||||
|
|
||||||
note
|
note
|
||||||
copyright: "2011-2014, Jocelyn Fiat, Eiffel Software and others"
|
copyright: "2011-2015, Jocelyn Fiat, Eiffel Software and others"
|
||||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
source: "[
|
source: "[
|
||||||
Eiffel Software
|
Eiffel Software
|
||||||
|
|||||||
@@ -119,14 +119,47 @@ feature -- Access: Config Reader
|
|||||||
|
|
||||||
text_item (k: READABLE_STRING_GENERAL): detachable READABLE_STRING_32
|
text_item (k: READABLE_STRING_GENERAL): detachable READABLE_STRING_32
|
||||||
-- String item associated with key `k'.
|
-- String item associated with key `k'.
|
||||||
local
|
|
||||||
obj: like item
|
|
||||||
do
|
do
|
||||||
obj := item (k)
|
Result := value_to_string_32 (item (k))
|
||||||
if attached {READABLE_STRING_32} obj as s32 then
|
end
|
||||||
Result := s32
|
|
||||||
elseif attached {READABLE_STRING_8} obj as s then
|
text_list_item (k: READABLE_STRING_GENERAL): detachable LIST [READABLE_STRING_32]
|
||||||
Result := utf.utf_8_string_8_to_escaped_string_32 (s)
|
-- List of String item associated with key `k'.
|
||||||
|
do
|
||||||
|
if attached {LIST [READABLE_STRING_8]} item (k) as l_list then
|
||||||
|
create {ARRAYED_LIST [READABLE_STRING_32]} Result.make (l_list.count)
|
||||||
|
Result.compare_objects
|
||||||
|
across
|
||||||
|
l_list as ic
|
||||||
|
until
|
||||||
|
Result = Void
|
||||||
|
loop
|
||||||
|
if attached value_to_string_32 (ic.item) as s32 then
|
||||||
|
Result.force (s32)
|
||||||
|
else
|
||||||
|
Result := Void
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
text_table_item (k: READABLE_STRING_GENERAL): detachable STRING_TABLE [READABLE_STRING_32]
|
||||||
|
-- Table of String item associated with key `k'.
|
||||||
|
do
|
||||||
|
if attached {STRING_TABLE [READABLE_STRING_8]} item (k) as l_list then
|
||||||
|
create {STRING_TABLE [READABLE_STRING_32]} Result.make (l_list.count)
|
||||||
|
Result.compare_objects
|
||||||
|
across
|
||||||
|
l_list as ic
|
||||||
|
until
|
||||||
|
Result = Void
|
||||||
|
loop
|
||||||
|
if attached value_to_string_32 (ic.item) as s32 then
|
||||||
|
Result.force (s32, ic.key)
|
||||||
|
else
|
||||||
|
Result := Void
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -226,6 +259,15 @@ feature -- Access
|
|||||||
|
|
||||||
feature {NONE} -- Implementation
|
feature {NONE} -- Implementation
|
||||||
|
|
||||||
|
value_to_string_32 (obj: detachable ANY): detachable STRING_32
|
||||||
|
do
|
||||||
|
if attached {READABLE_STRING_32} obj as s32 then
|
||||||
|
Result := s32
|
||||||
|
elseif attached {READABLE_STRING_8} obj as s then
|
||||||
|
Result := utf.utf_8_string_8_to_escaped_string_32 (s)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
item_from_values (a_values: STRING_TABLE [ANY]; k: READABLE_STRING_GENERAL): detachable ANY
|
item_from_values (a_values: STRING_TABLE [ANY]; k: READABLE_STRING_GENERAL): detachable ANY
|
||||||
local
|
local
|
||||||
i,j: INTEGER
|
i,j: INTEGER
|
||||||
@@ -460,7 +502,7 @@ feature {NONE} -- Implementation
|
|||||||
invariant
|
invariant
|
||||||
|
|
||||||
note
|
note
|
||||||
copyright: "2011-2014, Jocelyn Fiat, Eiffel Software and others"
|
copyright: "2011-2015, Jocelyn Fiat, Eiffel Software and others"
|
||||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
source: "[
|
source: "[
|
||||||
Eiffel Software
|
Eiffel Software
|
||||||
|
|||||||
@@ -63,10 +63,46 @@ feature -- Access: Config Reader
|
|||||||
text_item (k: READABLE_STRING_GENERAL): detachable READABLE_STRING_32
|
text_item (k: READABLE_STRING_GENERAL): detachable READABLE_STRING_32
|
||||||
-- String item associated with query `k'.
|
-- String item associated with query `k'.
|
||||||
do
|
do
|
||||||
if attached {JSON_STRING} item (k) as l_string then
|
Result := value_to_string_32 (item (k))
|
||||||
Result := l_string.unescaped_string_32
|
end
|
||||||
elseif attached {JSON_NUMBER} item (k) as l_number then
|
|
||||||
Result := l_number.item
|
text_list_item (k: READABLE_STRING_GENERAL): detachable LIST [READABLE_STRING_32]
|
||||||
|
-- List of String item associated with key `k'.
|
||||||
|
do
|
||||||
|
if attached {JSON_ARRAY} item (k) as l_array then
|
||||||
|
create {ARRAYED_LIST [READABLE_STRING_32]} Result.make (l_array.count)
|
||||||
|
Result.compare_objects
|
||||||
|
across
|
||||||
|
l_array as ic
|
||||||
|
until
|
||||||
|
Result = Void
|
||||||
|
loop
|
||||||
|
if attached value_to_string_32 (ic.item) as s32 then
|
||||||
|
Result.force (s32)
|
||||||
|
else
|
||||||
|
Result := Void
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
text_table_item (k: READABLE_STRING_GENERAL): detachable STRING_TABLE [READABLE_STRING_32]
|
||||||
|
-- Table of String item associated with key `k'.
|
||||||
|
do
|
||||||
|
if attached {JSON_OBJECT} item (k) as obj then
|
||||||
|
create {STRING_TABLE [READABLE_STRING_32]} Result.make (obj.count)
|
||||||
|
Result.compare_objects
|
||||||
|
across
|
||||||
|
obj as ic
|
||||||
|
until
|
||||||
|
Result = Void
|
||||||
|
loop
|
||||||
|
if attached value_to_string_32 (ic.item) as s32 then
|
||||||
|
Result.force (s32, ic.key.item)
|
||||||
|
else
|
||||||
|
Result := Void
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -105,6 +141,15 @@ feature -- Access
|
|||||||
|
|
||||||
feature {NONE} -- Implementation
|
feature {NONE} -- Implementation
|
||||||
|
|
||||||
|
value_to_string_32 (v: detachable ANY): detachable STRING_32
|
||||||
|
do
|
||||||
|
if attached {JSON_STRING} v as l_string then
|
||||||
|
Result := l_string.unescaped_string_32
|
||||||
|
elseif attached {JSON_NUMBER} v as l_number then
|
||||||
|
Result := l_number.item
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
object_json_value (a_object: JSON_OBJECT; a_query: READABLE_STRING_32): detachable JSON_VALUE
|
object_json_value (a_object: JSON_OBJECT; a_query: READABLE_STRING_32): detachable JSON_VALUE
|
||||||
-- Item associated with query `a_query' from object `a_object' if any.
|
-- Item associated with query `a_query' from object `a_object' if any.
|
||||||
local
|
local
|
||||||
@@ -163,7 +208,7 @@ feature {NONE} -- JSON
|
|||||||
end
|
end
|
||||||
|
|
||||||
note
|
note
|
||||||
copyright: "2011-2014, Jocelyn Fiat, Eiffel Software and others"
|
copyright: "2011-2015, Jocelyn Fiat, Eiffel Software and others"
|
||||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
source: "[
|
source: "[
|
||||||
Eiffel Software
|
Eiffel Software
|
||||||
|
|||||||
@@ -21,6 +21,18 @@ feature -- Test
|
|||||||
create {INI_CONFIG} cfg.make_from_string ("[
|
create {INI_CONFIG} cfg.make_from_string ("[
|
||||||
foo = bar
|
foo = bar
|
||||||
|
|
||||||
|
collection[] = a
|
||||||
|
collection[] = b
|
||||||
|
collection[] = c
|
||||||
|
collection[] = 1
|
||||||
|
collection[] = 2
|
||||||
|
collection[] = 3
|
||||||
|
|
||||||
|
table[a] = 1
|
||||||
|
table[b] = 2
|
||||||
|
table[c] = 3
|
||||||
|
table[d] = test
|
||||||
|
|
||||||
[first]
|
[first]
|
||||||
abc = 1
|
abc = 1
|
||||||
def = and so on
|
def = and so on
|
||||||
@@ -58,6 +70,21 @@ feature -- Test
|
|||||||
assert ("has_item (second.is)", cfg.has_item ("second.is"))
|
assert ("has_item (second.is)", cfg.has_item ("second.is"))
|
||||||
assert ("item (second.is)", attached cfg.text_item ("second.is") as v and then v.same_string_general ("2"))
|
assert ("item (second.is)", attached cfg.text_item ("second.is") as v and then v.same_string_general ("2"))
|
||||||
|
|
||||||
|
assert ("has_item (collection)", cfg.has_item ("collection"))
|
||||||
|
assert ("item (collection)", attached cfg.text_list_item ("collection") as lst and then (
|
||||||
|
lst.has ("a") and lst.has ("b") and lst.has ("c") and lst.has ("1") and lst.has ("2") and lst.has ("3")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
assert ("has_item (table)", cfg.has_item ("table"))
|
||||||
|
assert ("item (table)", attached cfg.text_table_item ("table") as tb and then (
|
||||||
|
tb.item ("a") ~ {STRING_32} "1" and
|
||||||
|
tb.item ("b") ~ {STRING_32} "2" and
|
||||||
|
tb.item ("c") ~ {STRING_32} "3" and
|
||||||
|
tb.item ("d") ~ {STRING_32} "test"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
if attached cfg.sub_config ("second") as cfg_second then
|
if attached cfg.sub_config ("second") as cfg_second then
|
||||||
assert ("has_item (is)", cfg_second.has_item ("is"))
|
assert ("has_item (is)", cfg_second.has_item ("is"))
|
||||||
assert ("item (is)", attached cfg_second.text_item ("is") as v and then v.same_string_general ("2"))
|
assert ("item (is)", attached cfg_second.text_item ("is") as v and then v.same_string_general ("2"))
|
||||||
@@ -141,7 +168,9 @@ feature -- Test
|
|||||||
"is": 2,
|
"is": 2,
|
||||||
"the": 3,
|
"the": 3,
|
||||||
"end": 4
|
"end": 4
|
||||||
}
|
},
|
||||||
|
"collection": ["a", "b", "c", 1, 2, 3],
|
||||||
|
"table": { "a": 1, "b": 2, "c": 3, "d" : "test" }
|
||||||
}
|
}
|
||||||
]")
|
]")
|
||||||
|
|
||||||
@@ -164,6 +193,21 @@ feature -- Test
|
|||||||
assert ("item (second.the)", attached cfg.text_item ("second.the") as v and then v.same_string_general ("3"))
|
assert ("item (second.the)", attached cfg.text_item ("second.the") as v and then v.same_string_general ("3"))
|
||||||
assert ("item (second.end)", attached cfg.text_item ("second.end") as v and then v.same_string_general ("4"))
|
assert ("item (second.end)", attached cfg.text_item ("second.end") as v and then v.same_string_general ("4"))
|
||||||
|
|
||||||
|
assert ("has_item (collection)", cfg.has_item ("collection"))
|
||||||
|
assert ("item (collection)", attached cfg.text_list_item ("collection") as lst and then (
|
||||||
|
lst.has ("a") and lst.has ("b") and lst.has ("c") and lst.has ("1") and lst.has ("2") and lst.has ("3")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
assert ("has_item (table)", cfg.has_item ("table"))
|
||||||
|
assert ("item (table)", attached cfg.text_table_item ("table") as tb and then (
|
||||||
|
tb.item ("a") ~ {STRING_32} "1" and
|
||||||
|
tb.item ("b") ~ {STRING_32} "2" and
|
||||||
|
tb.item ("c") ~ {STRING_32} "3" and
|
||||||
|
tb.item ("d") ~ {STRING_32} "test"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
if attached cfg.sub_config ("second") as cfg_second then
|
if attached cfg.sub_config ("second") as cfg_second then
|
||||||
assert ("has_item (is)", cfg_second.has_item ("is"))
|
assert ("has_item (is)", cfg_second.has_item ("is"))
|
||||||
assert ("item (is)", attached cfg_second.text_item ("is") as v and then v.same_string_general ("2"))
|
assert ("item (is)", attached cfg_second.text_item ("is") as v and then v.same_string_general ("2"))
|
||||||
|
|||||||
@@ -521,26 +521,26 @@ feature {NONE} -- Helpers
|
|||||||
|
|
||||||
feature {NONE} -- Block views
|
feature {NONE} -- Block views
|
||||||
|
|
||||||
get_block_view_login (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE)
|
-- get_block_view_login (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE)
|
||||||
local
|
-- local
|
||||||
-- vals: CMS_VALUE_TABLE
|
---- vals: CMS_VALUE_TABLE
|
||||||
do
|
-- do
|
||||||
if attached template_block (a_block_id, a_response) as l_tpl_block then
|
-- if attached template_block (a_block_id, a_response) as l_tpl_block then
|
||||||
-- create vals.make (1)
|
---- create vals.make (1)
|
||||||
-- -- add the variable to the block
|
---- -- add the variable to the block
|
||||||
-- value_table_alter (vals, a_response)
|
---- value_table_alter (vals, a_response)
|
||||||
-- across
|
---- across
|
||||||
-- vals as ic
|
---- vals as ic
|
||||||
-- loop
|
---- loop
|
||||||
-- l_tpl_block.set_value (ic.item, ic.key)
|
---- l_tpl_block.set_value (ic.item, ic.key)
|
||||||
|
---- end
|
||||||
|
-- a_response.put_required_block (l_tpl_block, "content")
|
||||||
|
-- else
|
||||||
|
-- debug ("cms")
|
||||||
|
-- a_response.add_warning_message ("Error with block [" + a_block_id + "]")
|
||||||
-- end
|
-- end
|
||||||
a_response.add_block (l_tpl_block, "content")
|
-- end
|
||||||
else
|
-- end
|
||||||
debug ("cms")
|
|
||||||
a_response.add_warning_message ("Error with block [" + a_block_id + "]")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
get_block_view_register (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE)
|
get_block_view_register (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE)
|
||||||
do
|
do
|
||||||
@@ -579,7 +579,6 @@ feature {NONE} -- Block views
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
get_block_view_reactivate (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE)
|
get_block_view_reactivate (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE)
|
||||||
do
|
do
|
||||||
if a_response.request.is_get_request_method then
|
if a_response.request.is_get_request_method then
|
||||||
|
|||||||
115
modules/feed_aggregator/feed_aggregation.e
Normal file
115
modules/feed_aggregator/feed_aggregation.e
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
note
|
||||||
|
description: "Feed aggregation parameters."
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
FEED_AGGREGATION
|
||||||
|
|
||||||
|
create
|
||||||
|
make
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
make (a_name: READABLE_STRING_GENERAL)
|
||||||
|
do
|
||||||
|
create name.make_from_string_general (a_name)
|
||||||
|
create {ARRAYED_LIST [READABLE_STRING_8]} locations.make (0)
|
||||||
|
expiration := 60*60
|
||||||
|
description_enabled := True
|
||||||
|
size := 10
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Access
|
||||||
|
|
||||||
|
name: IMMUTABLE_STRING_32
|
||||||
|
-- Associated name.
|
||||||
|
|
||||||
|
expiration: INTEGER
|
||||||
|
-- Suggested expiration time in seconds (default: 1 hour).
|
||||||
|
-- If negative then never expires.
|
||||||
|
|
||||||
|
size: INTEGER
|
||||||
|
-- Number of entries to display per page.
|
||||||
|
|
||||||
|
description: detachable IMMUTABLE_STRING_32
|
||||||
|
-- Optional description.
|
||||||
|
|
||||||
|
locations: LIST [READABLE_STRING_8]
|
||||||
|
-- List of feed location aggregated into current.
|
||||||
|
|
||||||
|
included_categories: detachable LIST [READABLE_STRING_32]
|
||||||
|
-- Optional categories to filter.
|
||||||
|
-- If Void, include any.
|
||||||
|
|
||||||
|
description_enabled: BOOLEAN
|
||||||
|
-- Display description?
|
||||||
|
|
||||||
|
feature -- Element change
|
||||||
|
|
||||||
|
set_description (a_desc: detachable READABLE_STRING_GENERAL)
|
||||||
|
do
|
||||||
|
if a_desc = Void then
|
||||||
|
description := Void
|
||||||
|
else
|
||||||
|
create description.make_from_string_general (a_desc)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
set_expiration (nb_seconds: INTEGER)
|
||||||
|
-- Set `expiration' to `nb_seconds'.
|
||||||
|
do
|
||||||
|
expiration := nb_seconds
|
||||||
|
end
|
||||||
|
|
||||||
|
set_size (nb: INTEGER)
|
||||||
|
-- Set `size' to `nb'.
|
||||||
|
do
|
||||||
|
size := nb
|
||||||
|
end
|
||||||
|
|
||||||
|
set_description_enabled (b: BOOLEAN)
|
||||||
|
-- Set `description_enabled' to `b'.
|
||||||
|
do
|
||||||
|
description_enabled := b
|
||||||
|
end
|
||||||
|
|
||||||
|
reset_categories
|
||||||
|
do
|
||||||
|
included_categories := Void
|
||||||
|
end
|
||||||
|
|
||||||
|
include_category (a_cat: READABLE_STRING_GENERAL)
|
||||||
|
local
|
||||||
|
lst: like included_categories
|
||||||
|
s32: STRING_32
|
||||||
|
do
|
||||||
|
lst := included_categories
|
||||||
|
if lst = Void then
|
||||||
|
create {ARRAYED_LIST [READABLE_STRING_32]} lst.make (1)
|
||||||
|
included_categories := lst
|
||||||
|
lst.compare_objects
|
||||||
|
end
|
||||||
|
s32 := a_cat.to_string_32
|
||||||
|
if not lst.has (s32) then
|
||||||
|
lst.force (s32)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Status report
|
||||||
|
|
||||||
|
is_included (e: FEED_ITEM): BOOLEAN
|
||||||
|
do
|
||||||
|
Result := True
|
||||||
|
if attached e.categories as e_cats then
|
||||||
|
if attached included_categories as lst then
|
||||||
|
Result := across lst as ic some
|
||||||
|
across e_cats as e_ic some
|
||||||
|
e_ic.item.same_string (ic.item)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
19
modules/feed_aggregator/feed_aggregator-safe.ecf
Normal file
19
modules/feed_aggregator/feed_aggregator-safe.ecf
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||||
|
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-14-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-14-0 http://www.eiffel.com/developers/xml/configuration-1-14-0.xsd" name="feed_aggregator" uuid="6A78AB37-9B07-4C42-9E24-0CA7D3C61E12" library_target="feed_aggregator">
|
||||||
|
<target name="feed_aggregator">
|
||||||
|
<root all_classes="true"/>
|
||||||
|
<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="feed" location="$ISE_LIBRARY\contrib\library\text\parser\feed\feed-safe.ecf"/>
|
||||||
|
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-safe.ecf"/>
|
||||||
|
<library name="http_client" location="$ISE_LIBRARY\contrib\library\network\http_client\http_client-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>
|
||||||
146
modules/feed_aggregator/feed_aggregator_api.e
Normal file
146
modules/feed_aggregator/feed_aggregator_api.e
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
note
|
||||||
|
description: "API for Feed aggregator module."
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
FEED_AGGREGATOR_API
|
||||||
|
|
||||||
|
inherit
|
||||||
|
CMS_MODULE_API
|
||||||
|
|
||||||
|
create
|
||||||
|
make
|
||||||
|
|
||||||
|
feature -- Access
|
||||||
|
|
||||||
|
aggregations: HASH_TABLE [FEED_AGGREGATION, STRING]
|
||||||
|
-- List of feed aggregations.
|
||||||
|
local
|
||||||
|
agg: FEED_AGGREGATION
|
||||||
|
l_feed_id: READABLE_STRING_32
|
||||||
|
l_title: detachable READABLE_STRING_GENERAL
|
||||||
|
l_location_list: detachable LIST [READABLE_STRING_32]
|
||||||
|
utf: UTF_CONVERTER
|
||||||
|
l_table: like internal_aggregations
|
||||||
|
do
|
||||||
|
l_table := internal_aggregations
|
||||||
|
if l_table /= Void then
|
||||||
|
Result := l_table
|
||||||
|
else
|
||||||
|
create Result.make (0)
|
||||||
|
internal_aggregations := Result
|
||||||
|
if attached cms_api.module_configuration_by_name ({FEED_AGGREGATOR_MODULE}.name, "feeds") as cfg then
|
||||||
|
if attached cfg.text_list_item ("ids") as l_ids then
|
||||||
|
across
|
||||||
|
l_ids as ic
|
||||||
|
loop
|
||||||
|
l_feed_id := ic.item
|
||||||
|
l_location_list := cfg.text_list_item ({STRING_32} "feeds." + l_feed_id + ".locations")
|
||||||
|
if
|
||||||
|
attached cfg.text_item ({STRING_32} "feeds." + l_feed_id + ".location") as l_location
|
||||||
|
then
|
||||||
|
if l_location_list = Void then
|
||||||
|
create {ARRAYED_LIST [READABLE_STRING_32]} l_location_list.make (1)
|
||||||
|
end
|
||||||
|
l_location_list.force (l_location)
|
||||||
|
end
|
||||||
|
if l_location_list /= Void and then not l_location_list.is_empty then
|
||||||
|
l_title := cfg.text_item ({STRING_32} "feeds." + l_feed_id + ".title")
|
||||||
|
if l_title = Void then
|
||||||
|
l_title := l_feed_id
|
||||||
|
end
|
||||||
|
create agg.make (l_title)
|
||||||
|
if attached cfg.text_item ({STRING_32} "feeds." + l_feed_id + ".expiration") as l_expiration then
|
||||||
|
if l_expiration.is_integer then
|
||||||
|
agg.set_expiration (l_expiration.to_integer)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if attached cfg.text_item ({STRING_32} "feeds." + l_feed_id + ".size") as l_size then
|
||||||
|
if l_size.is_integer then
|
||||||
|
agg.set_size (l_size.to_integer)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if attached cfg.text_item ({STRING_32} "feeds." + l_feed_id + ".option_description") as l_description_opt then
|
||||||
|
agg.set_description_enabled (not l_description_opt.is_case_insensitive_equal_general ("disabled"))
|
||||||
|
end
|
||||||
|
across
|
||||||
|
l_location_list as loc_ic
|
||||||
|
loop
|
||||||
|
agg.locations.force (utf.utf_32_string_to_utf_8_string_8 (loc_ic.item))
|
||||||
|
end
|
||||||
|
Result.force (agg, l_feed_id)
|
||||||
|
if attached cfg.text_list_item ({STRING_32} "feeds." + l_feed_id + ".categories") as l_cats then
|
||||||
|
across
|
||||||
|
l_cats as cats_ic
|
||||||
|
loop
|
||||||
|
agg.include_category (cats_ic.item)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
aggregation (a_name: READABLE_STRING_GENERAL): detachable FEED_AGGREGATION
|
||||||
|
do
|
||||||
|
if attached a_name.is_valid_as_string_8 then
|
||||||
|
Result := aggregations.item (a_name.as_string_8)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
feature {NONE} -- Access: implementation
|
||||||
|
|
||||||
|
internal_aggregations: detachable like aggregations
|
||||||
|
-- Cache value for `aggregations'.
|
||||||
|
|
||||||
|
feature -- Operation
|
||||||
|
|
||||||
|
feed (a_location: READABLE_STRING_8): detachable FEED
|
||||||
|
local
|
||||||
|
fac: FEED_DEFAULT_PARSERS
|
||||||
|
ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT
|
||||||
|
do
|
||||||
|
create fac
|
||||||
|
if attached new_http_client_session (a_location).get ("", ctx) as res then
|
||||||
|
if attached res.body as l_content then
|
||||||
|
Result := fac.feed_from_string (l_content)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
aggregation_feed (agg: FEED_AGGREGATION): detachable FEED
|
||||||
|
-- Feed from aggregation `agg'.
|
||||||
|
local
|
||||||
|
fac: FEED_DEFAULT_PARSERS
|
||||||
|
f: detachable FEED
|
||||||
|
do
|
||||||
|
create fac
|
||||||
|
across
|
||||||
|
agg.locations as ic
|
||||||
|
loop
|
||||||
|
if attached new_http_client_session (ic.item).get ("", Void).body as res then
|
||||||
|
f := fac.feed_from_string (res)
|
||||||
|
if Result /= Void then
|
||||||
|
if f /= Void then
|
||||||
|
Result := Result + f
|
||||||
|
end
|
||||||
|
else
|
||||||
|
Result := f
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
new_http_client_session (a_url: READABLE_STRING_8): HTTP_CLIENT_SESSION
|
||||||
|
local
|
||||||
|
cl: LIBCURL_HTTP_CLIENT
|
||||||
|
do
|
||||||
|
create cl.make
|
||||||
|
Result := cl.new_session (a_url)
|
||||||
|
Result.set_is_insecure (True)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
308
modules/feed_aggregator/feed_aggregator_module.e
Normal file
308
modules/feed_aggregator/feed_aggregator_module.e
Normal file
@@ -0,0 +1,308 @@
|
|||||||
|
note
|
||||||
|
description: "CMS module bringing support for feed aggregation."
|
||||||
|
date: "$Date: 2015-02-13 13:08:13 +0100 (ven., 13 févr. 2015) $"
|
||||||
|
revision: "$Revision: 96616 $"
|
||||||
|
|
||||||
|
class
|
||||||
|
FEED_AGGREGATOR_MODULE
|
||||||
|
|
||||||
|
inherit
|
||||||
|
CMS_MODULE
|
||||||
|
rename
|
||||||
|
module_api as feed_aggregator_api
|
||||||
|
redefine
|
||||||
|
initialize,
|
||||||
|
register_hooks,
|
||||||
|
permissions,
|
||||||
|
feed_aggregator_api
|
||||||
|
end
|
||||||
|
|
||||||
|
CMS_HOOK_BLOCK
|
||||||
|
|
||||||
|
CMS_HOOK_RESPONSE_ALTER
|
||||||
|
|
||||||
|
CMS_HOOK_MENU_SYSTEM_ALTER
|
||||||
|
|
||||||
|
create
|
||||||
|
make
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
make
|
||||||
|
-- Create Current module, disabled by default.
|
||||||
|
do
|
||||||
|
version := "1.0"
|
||||||
|
description := "Feed aggregation"
|
||||||
|
package := "feed"
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Access
|
||||||
|
|
||||||
|
name: STRING = "feed_aggregator"
|
||||||
|
|
||||||
|
permissions: LIST [READABLE_STRING_8]
|
||||||
|
-- List of permission ids, used by this module, and declared.
|
||||||
|
do
|
||||||
|
Result := Precursor
|
||||||
|
Result.force ("manage feed aggregator")
|
||||||
|
end
|
||||||
|
|
||||||
|
feature {CMS_API} -- Module Initialization
|
||||||
|
|
||||||
|
initialize (api: CMS_API)
|
||||||
|
-- <Precursor>
|
||||||
|
do
|
||||||
|
Precursor (api)
|
||||||
|
create feed_aggregator_api.make (api)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature {CMS_API} -- Access: API
|
||||||
|
|
||||||
|
feed_aggregator_api: detachable FEED_AGGREGATOR_API
|
||||||
|
-- Eventual module api.
|
||||||
|
|
||||||
|
feature -- Access: router
|
||||||
|
|
||||||
|
setup_router (a_router: WSF_ROUTER; a_api: CMS_API)
|
||||||
|
-- <Precursor>
|
||||||
|
local
|
||||||
|
h: WSF_URI_TEMPLATE_HANDLER
|
||||||
|
do
|
||||||
|
a_router.handle ("/admin/feed_aggregator/", create {WSF_URI_AGENT_HANDLER}.make (agent handle_feed_aggregator_admin (a_api, ?, ?)), a_router.methods_head_get_post)
|
||||||
|
create {WSF_URI_TEMPLATE_AGENT_HANDLER} h.make (agent handle_feed_aggregation (a_api, ?, ?))
|
||||||
|
a_router.handle ("/feed_aggregation/", h, a_router.methods_head_get)
|
||||||
|
a_router.handle ("/feed_aggregation/{feed_id}", h, a_router.methods_head_get)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Handle
|
||||||
|
|
||||||
|
handle_feed_aggregator_admin (a_api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
local
|
||||||
|
nyi: NOT_IMPLEMENTED_ERROR_CMS_RESPONSE
|
||||||
|
do
|
||||||
|
create nyi.make (req, res, a_api)
|
||||||
|
nyi.execute
|
||||||
|
end
|
||||||
|
|
||||||
|
handle_feed_aggregation (a_api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
local
|
||||||
|
r: CMS_RESPONSE
|
||||||
|
s: STRING
|
||||||
|
nb: INTEGER
|
||||||
|
do
|
||||||
|
if attached {WSF_STRING} req.query_parameter ("size") as p_size and then p_size.is_integer then
|
||||||
|
nb := p_size.integer_value
|
||||||
|
else
|
||||||
|
nb := -1
|
||||||
|
end
|
||||||
|
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, a_api)
|
||||||
|
if attached {WSF_STRING} req.path_parameter ("feed_id") as p_feed_id then
|
||||||
|
if attached feed_aggregation (p_feed_id.value) as l_agg then
|
||||||
|
create s.make_empty
|
||||||
|
s.append ("<h1>")
|
||||||
|
s.append (r.html_encoded (l_agg.name))
|
||||||
|
s.append ("</h1>")
|
||||||
|
if attached l_agg.included_categories as l_categories then
|
||||||
|
s.append ("<span class=%"category%">")
|
||||||
|
across
|
||||||
|
l_categories as cats_ic
|
||||||
|
loop
|
||||||
|
s.append (" [")
|
||||||
|
s.append (r.html_encoded (cats_ic.item))
|
||||||
|
s.append ("]")
|
||||||
|
end
|
||||||
|
s.append ("</span>")
|
||||||
|
end
|
||||||
|
if attached l_agg.description as l_desc and then l_desc.is_valid_as_string_8 then
|
||||||
|
s.append ("<div class=%"description%">")
|
||||||
|
s.append (l_desc.as_string_8)
|
||||||
|
s.append ("</div>")
|
||||||
|
end
|
||||||
|
s.append ("<ul>")
|
||||||
|
across
|
||||||
|
l_agg.locations as ic
|
||||||
|
loop
|
||||||
|
s.append ("<li><a href=%"")
|
||||||
|
s.append (ic.item)
|
||||||
|
s.append ("%">")
|
||||||
|
s.append (ic.item)
|
||||||
|
s.append ("</a></li>")
|
||||||
|
end
|
||||||
|
s.append ("</ul>")
|
||||||
|
|
||||||
|
if attached feed_to_html (p_feed_id.value, nb, True, r) as l_html then
|
||||||
|
s.append (l_html)
|
||||||
|
end
|
||||||
|
r.set_main_content (s)
|
||||||
|
else
|
||||||
|
create {NOT_FOUND_ERROR_CMS_RESPONSE} r.make (req, res, a_api)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if attached feed_aggregator_api as l_feed_agg_api then
|
||||||
|
create s.make_empty
|
||||||
|
across
|
||||||
|
l_feed_agg_api.aggregations as ic
|
||||||
|
loop
|
||||||
|
s.append ("<li>")
|
||||||
|
s.append (r.link (ic.key, "feed_aggregation/" + r.url_encoded (ic.key), Void))
|
||||||
|
if attached ic.item.included_categories as l_categories then
|
||||||
|
s.append ("<span class=%"category%">")
|
||||||
|
across
|
||||||
|
l_categories as cats_ic
|
||||||
|
loop
|
||||||
|
s.append (" [")
|
||||||
|
s.append (r.html_encoded (cats_ic.item))
|
||||||
|
s.append ("]")
|
||||||
|
end
|
||||||
|
s.append ("</span>")
|
||||||
|
end
|
||||||
|
if attached ic.item.description as l_desc then
|
||||||
|
if l_desc.is_valid_as_string_8 then
|
||||||
|
s.append ("<div class=%"description%">")
|
||||||
|
s.append (l_desc.as_string_8)
|
||||||
|
s.append ("</div>")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
s.append ("</li>")
|
||||||
|
end
|
||||||
|
r.set_main_content (s)
|
||||||
|
else
|
||||||
|
create {BAD_REQUEST_ERROR_CMS_RESPONSE} r.make (req, res, a_api)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
r.execute
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Hooks configuration
|
||||||
|
|
||||||
|
register_hooks (a_response: CMS_RESPONSE)
|
||||||
|
-- Module hooks configuration.
|
||||||
|
do
|
||||||
|
a_response.hooks.subscribe_to_block_hook (Current)
|
||||||
|
a_response.hooks.subscribe_to_response_alter_hook (Current)
|
||||||
|
a_response.hooks.subscribe_to_menu_system_alter_hook (Current)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Hook
|
||||||
|
|
||||||
|
block_list: ITERABLE [like {CMS_BLOCK}.name]
|
||||||
|
-- List of block names, managed by current object.
|
||||||
|
local
|
||||||
|
res: ARRAYED_LIST [like {CMS_BLOCK}.name]
|
||||||
|
l_aggs: HASH_TABLE [FEED_AGGREGATION, STRING_8]
|
||||||
|
do
|
||||||
|
if attached feed_aggregator_api as l_feed_api then
|
||||||
|
l_aggs := l_feed_api.aggregations
|
||||||
|
create res.make (l_aggs.count)
|
||||||
|
across
|
||||||
|
l_aggs as ic
|
||||||
|
loop
|
||||||
|
res.force ("?feed." + ic.key)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
create res.make (0)
|
||||||
|
end
|
||||||
|
Result := res
|
||||||
|
end
|
||||||
|
|
||||||
|
get_block_view (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE)
|
||||||
|
-- Get block object identified by `a_block_id' and associate with `a_response'.
|
||||||
|
local
|
||||||
|
s: READABLE_STRING_8
|
||||||
|
b: CMS_CONTENT_BLOCK
|
||||||
|
pref: STRING
|
||||||
|
do
|
||||||
|
if attached feed_aggregator_api as l_feed_api then
|
||||||
|
pref := "feed."
|
||||||
|
if a_block_id.starts_with (pref) then
|
||||||
|
s := a_block_id.substring (pref.count + 1, a_block_id.count)
|
||||||
|
else
|
||||||
|
s := a_block_id
|
||||||
|
end
|
||||||
|
if attached feed_to_html (s, 0, True, a_response) as l_content then
|
||||||
|
create b.make (a_block_id, Void, l_content, Void)
|
||||||
|
b.set_is_raw (True)
|
||||||
|
a_response.add_block (b, "feed_" + s)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
feed_aggregation (a_feed_id: READABLE_STRING_GENERAL): detachable FEED_AGGREGATION
|
||||||
|
do
|
||||||
|
if attached feed_aggregator_api as l_feed_api then
|
||||||
|
Result := l_feed_api.aggregation (a_feed_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
feed_to_html (a_feed_id: READABLE_STRING_GENERAL; a_count: INTEGER; with_feed_info: BOOLEAN; a_response: CMS_RESPONSE): detachable STRING
|
||||||
|
local
|
||||||
|
nb: INTEGER
|
||||||
|
i: INTEGER
|
||||||
|
e: FEED_ITEM
|
||||||
|
l_cache: CMS_FILE_STRING_8_CACHE
|
||||||
|
lnk: detachable FEED_LINK
|
||||||
|
vis: FEED_TO_XHTML_VISITOR
|
||||||
|
s: STRING
|
||||||
|
do
|
||||||
|
if attached feed_aggregator_api as l_feed_api then
|
||||||
|
if attached l_feed_api.aggregation (a_feed_id) as l_agg then
|
||||||
|
create l_cache.make (a_response.api.files_location.extended (".cache").extended (name).extended ("feed__" + a_feed_id + "__" + a_count.out + "_" + with_feed_info.out))
|
||||||
|
Result := l_cache.item
|
||||||
|
if Result = Void or l_cache.expired (Void, l_agg.expiration) then
|
||||||
|
|
||||||
|
create Result.make (1024)
|
||||||
|
Result.append ("<!-- ")
|
||||||
|
Result.append ("Updated: " + l_cache.cache_date_time.out)
|
||||||
|
Result.append (" -->")
|
||||||
|
|
||||||
|
create vis.make (Result)
|
||||||
|
if a_count = 0 then
|
||||||
|
nb := l_agg.size
|
||||||
|
else
|
||||||
|
nb := a_count
|
||||||
|
end
|
||||||
|
vis.set_limit (nb)
|
||||||
|
vis.set_description_enabled (l_agg.description_enabled)
|
||||||
|
|
||||||
|
if with_feed_info then
|
||||||
|
create s.make_empty
|
||||||
|
if attached l_agg.description as l_desc then
|
||||||
|
s.append ("<div class=%"description%">")
|
||||||
|
s.append_string_general (l_desc)
|
||||||
|
s.append ("</div>")
|
||||||
|
end
|
||||||
|
vis.set_header (s)
|
||||||
|
end
|
||||||
|
create s.make_empty
|
||||||
|
s.append_string ("<liv class=%"nav%">")
|
||||||
|
s.append_string (a_response.link ("See more ...", "feed_aggregation/" + a_response.url_encoded (a_feed_id), Void))
|
||||||
|
s.append_string ("</li>")
|
||||||
|
vis.set_footer (s)
|
||||||
|
|
||||||
|
if attached l_feed_api.aggregation_feed (l_agg) as l_feed then
|
||||||
|
l_feed.accept (vis)
|
||||||
|
end
|
||||||
|
l_cache.put (Result)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Hook
|
||||||
|
|
||||||
|
response_alter (a_response: CMS_RESPONSE)
|
||||||
|
do
|
||||||
|
a_response.add_style (a_response.url ("/module/" + name + "/files/css/feed_aggregator.css", Void), Void)
|
||||||
|
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'.
|
||||||
|
do
|
||||||
|
a_menu_system.navigation_menu.extend (create {CMS_LOCAL_LINK}.make ("Feeds", "feed_aggregation/"))
|
||||||
|
if a_response.has_permission ("manage feed aggregator") then
|
||||||
|
a_menu_system.management_menu.extend (create {CMS_LOCAL_LINK}.make ("Feeds (admin)", "admin/feed_aggregator/"))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
53
modules/feed_aggregator/site/files/css/feed_aggregator.css
Normal file
53
modules/feed_aggregator/site/files/css/feed_aggregator.css
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
div.feed ul {
|
||||||
|
list-style: none;
|
||||||
|
position: relative;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
width: 99%;
|
||||||
|
}
|
||||||
|
div.feed li {
|
||||||
|
/* border-top: solid 1px #ddd; */
|
||||||
|
padding: 0;
|
||||||
|
margin: 0 0 5px 0;
|
||||||
|
}
|
||||||
|
div.feed li a {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
div.feed li .date {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: small;
|
||||||
|
}
|
||||||
|
div.feed li .category {
|
||||||
|
margin-left: 20px;
|
||||||
|
font-size: 8px;
|
||||||
|
height: 9px;
|
||||||
|
overflow: hidden;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
div.feed li .description {
|
||||||
|
margin-left: 20px;
|
||||||
|
font-size: small;
|
||||||
|
height: 18px;
|
||||||
|
overflow: hidden;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
div.feed li:hover {
|
||||||
|
margin-bottom: 23px;
|
||||||
|
}
|
||||||
|
div.feed li:hover .description {
|
||||||
|
padding: 5px;
|
||||||
|
position: absolute;
|
||||||
|
height: auto;
|
||||||
|
overflow-y: scroll;
|
||||||
|
overflow-x: scroll;
|
||||||
|
color: #000;
|
||||||
|
background-color: #fff;
|
||||||
|
border: solid 1px #000;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
div.feed li:hover:last-child {
|
||||||
|
margin-bottom: 28px;
|
||||||
|
}
|
||||||
|
div.feed li .description::after {
|
||||||
|
content: "...";
|
||||||
|
}
|
||||||
54
modules/feed_aggregator/site/files/scss/feed_aggregator.scss
Normal file
54
modules/feed_aggregator/site/files/scss/feed_aggregator.scss
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
div.feed {
|
||||||
|
ul {
|
||||||
|
list-style: none;
|
||||||
|
position: relative;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
width: 99%;
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
/* border-top: solid 1px #ddd; */
|
||||||
|
padding: 0;
|
||||||
|
margin: 0 0 5px 0;
|
||||||
|
|
||||||
|
a {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.date {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: small;
|
||||||
|
}
|
||||||
|
.category {
|
||||||
|
margin-left: 20px;
|
||||||
|
font-size: 8px;
|
||||||
|
height: 9px;
|
||||||
|
overflow: hidden;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
.description {
|
||||||
|
margin-left: 20px;
|
||||||
|
font-size: small;
|
||||||
|
height: 18px;
|
||||||
|
overflow: hidden;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
margin-bottom: 23px;
|
||||||
|
.description {
|
||||||
|
padding: 5px;
|
||||||
|
position: absolute;
|
||||||
|
height: auto;
|
||||||
|
overflow-y: scroll;
|
||||||
|
overflow-x: scroll;
|
||||||
|
color: #000;
|
||||||
|
background-color: #fff;
|
||||||
|
border: solid 1px #000;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 28px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.description::after { content: "..."; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -244,7 +244,7 @@ feature -- Hooks
|
|||||||
block_list: ITERABLE [like {CMS_BLOCK}.name]
|
block_list: ITERABLE [like {CMS_BLOCK}.name]
|
||||||
-- <Precursor>
|
-- <Precursor>
|
||||||
do
|
do
|
||||||
Result := <<"node-info">>
|
Result := <<"?node-info">>
|
||||||
end
|
end
|
||||||
|
|
||||||
get_block_view (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE)
|
get_block_view (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
note
|
note
|
||||||
description: "CMS module that bring support for recent changes."
|
description: "CMS module that brings support for recent changes."
|
||||||
date: "$Date: 2015-02-13 13:08:13 +0100 (ven., 13 févr. 2015) $"
|
date: "$Date: 2015-02-13 13:08:13 +0100 (ven., 13 févr. 2015) $"
|
||||||
revision: "$Revision: 96616 $"
|
revision: "$Revision: 96616 $"
|
||||||
|
|
||||||
@@ -19,6 +19,8 @@ inherit
|
|||||||
|
|
||||||
CMS_HOOK_RESPONSE_ALTER
|
CMS_HOOK_RESPONSE_ALTER
|
||||||
|
|
||||||
|
CMS_HOOK_BLOCK
|
||||||
|
|
||||||
create
|
create
|
||||||
make
|
make
|
||||||
|
|
||||||
@@ -49,10 +51,132 @@ feature -- Access: router
|
|||||||
-- <Precursor>
|
-- <Precursor>
|
||||||
do
|
do
|
||||||
a_router.handle ("/recent_changes/", create {WSF_URI_AGENT_HANDLER}.make (agent handle_recent_changes (a_api, ?, ?)), a_router.methods_head_get)
|
a_router.handle ("/recent_changes/", create {WSF_URI_AGENT_HANDLER}.make (agent handle_recent_changes (a_api, ?, ?)), a_router.methods_head_get)
|
||||||
|
a_router.handle ("/recent_changes/feed", create {WSF_URI_AGENT_HANDLER}.make (agent handle_recent_changes_feed (a_api, ?, ?)), a_router.methods_head_get)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Hook
|
||||||
|
|
||||||
|
block_list: ITERABLE [like {CMS_BLOCK}.name]
|
||||||
|
-- List of block names, managed by current object.
|
||||||
|
-- If prefixed by "?", condition will be check
|
||||||
|
-- to determine if it should be displayed (and computed) or not.
|
||||||
|
do
|
||||||
|
Result := <<"?recent_changes">>
|
||||||
|
end
|
||||||
|
|
||||||
|
get_block_view (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE)
|
||||||
|
-- Get block object identified by `a_block_id' and associate with `a_response'.
|
||||||
|
local
|
||||||
|
b: CMS_CONTENT_BLOCK
|
||||||
|
s, l_content: STRING
|
||||||
|
gen: FEED_TO_XHTML_VISITOR
|
||||||
|
do
|
||||||
|
if a_block_id.same_string_general ("recent_changes") then
|
||||||
|
create l_content.make (1024)
|
||||||
|
create gen.make (l_content)
|
||||||
|
|
||||||
|
create s.make_empty
|
||||||
|
s.append_string ("<liv class=%"nav%">")
|
||||||
|
s.append_string (a_response.link ("See more ...", "recent_changes/", Void))
|
||||||
|
s.append_string ("</li>")
|
||||||
|
gen.set_footer (s)
|
||||||
|
|
||||||
|
recent_changes_feed (a_response, 10, Void).accept (gen)
|
||||||
|
|
||||||
|
create b.make (a_block_id, Void, l_content, Void)
|
||||||
|
a_response.put_block (b, Void, False)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
recent_changes_feed (a_response: CMS_RESPONSE; a_size: NATURAL_32; a_source: detachable READABLE_STRING_8): FEED
|
||||||
|
local
|
||||||
|
l_changes: CMS_RECENT_CHANGE_CONTAINER
|
||||||
|
ch: CMS_RECENT_CHANGE_ITEM
|
||||||
|
l_user: detachable CMS_USER
|
||||||
|
l_feed: FEED
|
||||||
|
l_feed_item: FEED_ITEM
|
||||||
|
lnk: FEED_LINK
|
||||||
|
nb: NATURAL_32
|
||||||
|
do
|
||||||
|
l_user := Void -- Public access for the feed!
|
||||||
|
create l_changes.make (a_size, create {DATE_TIME}.make_now_utc, a_source)
|
||||||
|
if attached a_response.hooks.subscribers ({CMS_RECENT_CHANGES_HOOK}) as lst then
|
||||||
|
across
|
||||||
|
lst as ic
|
||||||
|
loop
|
||||||
|
if attached {CMS_RECENT_CHANGES_HOOK} ic.item as h then
|
||||||
|
if attached h.recent_changes_sources as h_sources then
|
||||||
|
if
|
||||||
|
a_source = Void
|
||||||
|
or else across h_sources as h_ic some h_ic.item.is_case_insensitive_equal (a_source) end
|
||||||
|
then
|
||||||
|
h.populate_recent_changes (l_changes, l_user)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
create l_feed.make ("CMS Recent changes")
|
||||||
|
l_feed.set_date (create {DATE_TIME}.make_now_utc)
|
||||||
|
nb := a_size
|
||||||
|
across
|
||||||
|
l_changes as ic
|
||||||
|
until
|
||||||
|
nb = 0
|
||||||
|
loop
|
||||||
|
ch := ic.item
|
||||||
|
create l_feed_item.make (ch.link.title)
|
||||||
|
l_feed_item.set_date (ch.date)
|
||||||
|
l_feed_item.set_description (ch.information)
|
||||||
|
l_feed_item.set_category (ch.source)
|
||||||
|
create lnk.make (a_response.absolute_url (ch.link.location, Void))
|
||||||
|
l_feed_item.links.force (lnk, "")
|
||||||
|
l_feed.extend (l_feed_item)
|
||||||
|
nb := nb - 1
|
||||||
|
end
|
||||||
|
l_feed.sort
|
||||||
|
Result := l_feed
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Handler
|
feature -- Handler
|
||||||
|
|
||||||
|
handle_recent_changes_feed (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
|
local
|
||||||
|
r: CMS_RESPONSE
|
||||||
|
htdate: HTTP_DATE
|
||||||
|
l_content: STRING
|
||||||
|
l_until_date: detachable DATE_TIME
|
||||||
|
l_until_date_timestamp: INTEGER_64
|
||||||
|
l_filter_source: detachable READABLE_STRING_8
|
||||||
|
l_size: NATURAL_32
|
||||||
|
mesg: CMS_CUSTOM_RESPONSE_MESSAGE
|
||||||
|
do
|
||||||
|
if attached {WSF_STRING} req.query_parameter ("date") as p_until_date then
|
||||||
|
l_until_date_timestamp := p_until_date.value.to_integer_64
|
||||||
|
create htdate.make_from_timestamp (l_until_date_timestamp)
|
||||||
|
l_until_date := htdate.date_time
|
||||||
|
end
|
||||||
|
if attached {WSF_STRING} req.query_parameter ("source") as p_filter then
|
||||||
|
l_filter_source := p_filter.url_encoded_value
|
||||||
|
if l_filter_source.is_empty then
|
||||||
|
l_filter_source := Void
|
||||||
|
end
|
||||||
|
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_content.make (1024)
|
||||||
|
recent_changes_feed (r, l_size, l_filter_source).accept (create {ATOM_FEED_GENERATOR}.make (l_content))
|
||||||
|
create mesg.make ({HTTP_STATUS_CODE}.ok)
|
||||||
|
mesg.set_payload (l_content)
|
||||||
|
res.send (mesg)
|
||||||
|
end
|
||||||
|
|
||||||
handle_recent_changes (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE)
|
handle_recent_changes (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
local
|
local
|
||||||
r: CMS_RESPONSE
|
r: CMS_RESPONSE
|
||||||
@@ -243,7 +367,7 @@ feature -- Handler
|
|||||||
end
|
end
|
||||||
l_content.append ("<a href=%"")
|
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 (r.url (r.location, create {CMS_API_OPTIONS}.make_from_manifest (<<["query", l_query]>>)))
|
||||||
l_content.append ("%">More ...</a>")
|
l_content.append ("%">See more ...</a>")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -268,6 +392,7 @@ feature -- Hooks configuration
|
|||||||
do
|
do
|
||||||
a_response.hooks.subscribe_to_menu_system_alter_hook (Current)
|
a_response.hooks.subscribe_to_menu_system_alter_hook (Current)
|
||||||
a_response.hooks.subscribe_to_response_alter_hook (Current)
|
a_response.hooks.subscribe_to_response_alter_hook (Current)
|
||||||
|
a_response.hooks.subscribe_to_block_hook (Current)
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Hook
|
feature -- Hook
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
<library name="cms" location="..\..\cms-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_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="error" location="$ISE_LIBRARY\contrib\library\utility\general\error\error-safe.ecf"/>
|
||||||
|
<library name="feed" location="$ISE_LIBRARY\contrib\library\text\parser\feed\feed-safe.ecf"/>
|
||||||
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-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" 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_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension-safe.ecf" readonly="false"/>
|
||||||
|
|||||||
18
package.iron
18
package.iron
@@ -1,4 +1,4 @@
|
|||||||
package ROC_cms
|
package ROC
|
||||||
|
|
||||||
project
|
project
|
||||||
cms = "cms-safe.ecf"
|
cms = "cms-safe.ecf"
|
||||||
@@ -19,6 +19,21 @@ project
|
|||||||
basic_auth = "modules/basic_auth/basic_auth.ecf"
|
basic_auth = "modules/basic_auth/basic_auth.ecf"
|
||||||
node = "modules/node/node-safe.ecf"
|
node = "modules/node/node-safe.ecf"
|
||||||
node = "modules/node/node.ecf"
|
node = "modules/node/node.ecf"
|
||||||
|
demo = "examples/demo/demo-safe.ecf"
|
||||||
|
cms_demo_module = "examples/demo/modules/demo/cms_demo_module-safe.ecf"
|
||||||
|
config_tests = "library/configuration/tests/config_tests-safe.ecf"
|
||||||
|
email_service = "library/email/email-safe.ecf"
|
||||||
|
persistence_sqlite3 = "library/persistence/sqlite3/persistence_sqlite3-safe.ecf"
|
||||||
|
store_mysql = "library/persistence/store_mysql/store_mysql-safe.ecf"
|
||||||
|
persistence_store_odbc = "library/persistence/store_odbc/store_odbc-safe.ecf"
|
||||||
|
tests_store_odbc = "library/persistence/store_odbc/tests/tests-safe.ecf"
|
||||||
|
admin = "modules/admin/admin-safe.ecf"
|
||||||
|
auth_module = "modules/auth/auth-safe.ecf"
|
||||||
|
cms_blog_module = "modules/blog/cms_blog_module-safe.ecf"
|
||||||
|
feed_aggregator = "modules/feed_aggregator/feed_aggregator-safe.ecf"
|
||||||
|
oauth_module = "modules/oauth20/oauth20-safe.ecf"
|
||||||
|
openid_module = "modules/openid/openid-safe.ecf"
|
||||||
|
recent_changes = "modules/recent_changes/recent_changes-safe.ecf"
|
||||||
|
|
||||||
note
|
note
|
||||||
title: ROC CMS
|
title: ROC CMS
|
||||||
@@ -27,5 +42,6 @@ note
|
|||||||
license: Eiffel Forum v2
|
license: Eiffel Forum v2
|
||||||
copyright: Jocelyn Fiat, Javier Velilla, Eiffel Software
|
copyright: Jocelyn Fiat, Javier Velilla, Eiffel Software
|
||||||
link[source]: "Github" https://github.com/EiffelWebFramework/ROC.git
|
link[source]: "Github" https://github.com/EiffelWebFramework/ROC.git
|
||||||
|
-- link[doc]: "Documentation" http://
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
94
src/cache/cms_cache.e
vendored
Normal file
94
src/cache/cms_cache.e
vendored
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
note
|
||||||
|
description: "Abstract interface for cache of value conforming to formal {G}."
|
||||||
|
date: "$Date: 2014-12-03 16:12:08 +0100 (mer., 03 déc. 2014) $"
|
||||||
|
revision: "$Revision: 96232 $"
|
||||||
|
|
||||||
|
deferred class
|
||||||
|
CMS_CACHE [G -> ANY]
|
||||||
|
|
||||||
|
feature -- Status report
|
||||||
|
|
||||||
|
exists: BOOLEAN
|
||||||
|
-- Do associated cache file exists?
|
||||||
|
deferred
|
||||||
|
end
|
||||||
|
|
||||||
|
expired (a_reference_date: detachable DATE_TIME; a_duration_in_seconds: INTEGER): BOOLEAN
|
||||||
|
-- Is associated cached item expired?
|
||||||
|
-- If `a_reference_date' is attached, cache is expired if `a_reference' is more recent than cached item.
|
||||||
|
local
|
||||||
|
d1, d2: DATE_TIME
|
||||||
|
do
|
||||||
|
if exists then
|
||||||
|
if
|
||||||
|
a_reference_date /= Void and then
|
||||||
|
a_reference_date > cache_date_time
|
||||||
|
then
|
||||||
|
Result := True
|
||||||
|
else
|
||||||
|
if a_duration_in_seconds = -1 then
|
||||||
|
Result := False -- Never expires
|
||||||
|
elseif a_duration_in_seconds = 0 then
|
||||||
|
Result := True -- Always expires
|
||||||
|
elseif a_duration_in_seconds > 0 then
|
||||||
|
d1 := cache_date_time
|
||||||
|
d2 := current_date_time
|
||||||
|
d2.second_add (- a_duration_in_seconds) --| do not modify `cache_date_time'
|
||||||
|
Result := d2 > d1 -- cached date + duration is older than current date
|
||||||
|
else
|
||||||
|
-- Invalid expiration value
|
||||||
|
-- thus always expired.
|
||||||
|
Result := True
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
Result := True
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Access
|
||||||
|
|
||||||
|
item: detachable G
|
||||||
|
-- Value from the cache.
|
||||||
|
deferred
|
||||||
|
end
|
||||||
|
|
||||||
|
cache_date_time: DATE_TIME
|
||||||
|
-- Date time for current cache if exists.
|
||||||
|
-- Note: it may be UTC or not , depending on cache type.
|
||||||
|
deferred
|
||||||
|
end
|
||||||
|
|
||||||
|
cache_duration_in_seconds: INTEGER_64
|
||||||
|
-- Number of seconds since cache was set.
|
||||||
|
require
|
||||||
|
exists: exists
|
||||||
|
local
|
||||||
|
d1, d2: DATE_TIME
|
||||||
|
do
|
||||||
|
d1 := cache_date_time
|
||||||
|
d2 := current_date_time
|
||||||
|
Result := d2.relative_duration (d1).seconds_count
|
||||||
|
end
|
||||||
|
|
||||||
|
current_date_time: DATE_TIME
|
||||||
|
-- Current date time for relative duration with cache_date_time.
|
||||||
|
deferred
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Element change
|
||||||
|
|
||||||
|
delete
|
||||||
|
-- Remove cache.
|
||||||
|
deferred
|
||||||
|
end
|
||||||
|
|
||||||
|
put (g: G)
|
||||||
|
-- Put `g' into cache.
|
||||||
|
deferred
|
||||||
|
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
|
||||||
150
src/cache/cms_file_cache.e
vendored
Normal file
150
src/cache/cms_file_cache.e
vendored
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
note
|
||||||
|
description: "Cache using a local file."
|
||||||
|
date: "$Date: 2015-09-24 18:24:06 +0200 (jeu., 24 sept. 2015) $"
|
||||||
|
revision: "$Revision: 97926 $"
|
||||||
|
|
||||||
|
deferred class
|
||||||
|
CMS_FILE_CACHE [G -> ANY]
|
||||||
|
|
||||||
|
inherit
|
||||||
|
CMS_CACHE [G]
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
make (a_cache_filename: PATH)
|
||||||
|
do
|
||||||
|
path := a_cache_filename
|
||||||
|
end
|
||||||
|
|
||||||
|
path: PATH
|
||||||
|
|
||||||
|
feature -- Status report
|
||||||
|
|
||||||
|
exists: BOOLEAN
|
||||||
|
-- Do associated cache file exists?
|
||||||
|
local
|
||||||
|
ut: FILE_UTILITIES
|
||||||
|
do
|
||||||
|
Result := ut.file_path_exists (path)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Access
|
||||||
|
|
||||||
|
cache_date_time: DATE_TIME
|
||||||
|
-- <Precursor>
|
||||||
|
local
|
||||||
|
f: RAW_FILE
|
||||||
|
do
|
||||||
|
create f.make_with_path (path)
|
||||||
|
if f.exists then
|
||||||
|
Result := utc_file_date_time (f)
|
||||||
|
else
|
||||||
|
create Result.make_now_utc
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
current_date_time: DATE_TIME
|
||||||
|
-- <Precursor>
|
||||||
|
do
|
||||||
|
-- UTC, since `cache_date_time' is UTC!
|
||||||
|
create Result.make_now_utc
|
||||||
|
end
|
||||||
|
|
||||||
|
file_size: INTEGER
|
||||||
|
-- Associated file size.
|
||||||
|
require
|
||||||
|
exists: exists
|
||||||
|
local
|
||||||
|
f: RAW_FILE
|
||||||
|
do
|
||||||
|
create f.make_with_path (path)
|
||||||
|
if f.exists and then f.is_access_readable then
|
||||||
|
Result := f.count
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
item: detachable G
|
||||||
|
local
|
||||||
|
f: RAW_FILE
|
||||||
|
retried: BOOLEAN
|
||||||
|
do
|
||||||
|
if not retried then
|
||||||
|
create f.make_with_path (path)
|
||||||
|
if f.exists and then f.is_access_readable then
|
||||||
|
f.open_read
|
||||||
|
Result := file_to_item (f)
|
||||||
|
f.close
|
||||||
|
end
|
||||||
|
end
|
||||||
|
rescue
|
||||||
|
retried := True
|
||||||
|
retry
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Element change
|
||||||
|
|
||||||
|
delete
|
||||||
|
-- <Precursor>
|
||||||
|
local
|
||||||
|
f: RAW_FILE
|
||||||
|
retried: BOOLEAN
|
||||||
|
do
|
||||||
|
if not retried then
|
||||||
|
create f.make_with_path (path)
|
||||||
|
-- Create recursively parent directory if it does not exists.
|
||||||
|
if f.exists and then f.is_access_writable then
|
||||||
|
f.delete
|
||||||
|
end
|
||||||
|
end
|
||||||
|
rescue
|
||||||
|
retried := True
|
||||||
|
retry
|
||||||
|
end
|
||||||
|
|
||||||
|
put (g: G)
|
||||||
|
-- <Precursor>
|
||||||
|
local
|
||||||
|
f: RAW_FILE
|
||||||
|
d: DIRECTORY
|
||||||
|
do
|
||||||
|
create f.make_with_path (path)
|
||||||
|
-- Create recursively parent directory if it does not exists.
|
||||||
|
create d.make_with_path (path.parent)
|
||||||
|
if not d.exists then
|
||||||
|
d.recursive_create_dir
|
||||||
|
end
|
||||||
|
if not f.exists or else f.is_access_writable then
|
||||||
|
f.open_write
|
||||||
|
item_to_file (g, f)
|
||||||
|
f.close
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Helpers
|
||||||
|
|
||||||
|
utc_file_date_time (f: FILE): DATE_TIME
|
||||||
|
-- Last change date for file `f'.
|
||||||
|
require
|
||||||
|
f.exists
|
||||||
|
do
|
||||||
|
create Result.make_from_epoch (f.date.as_integer_32)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature {NONE} -- Implementation
|
||||||
|
|
||||||
|
file_to_item (f: FILE): detachable G
|
||||||
|
require
|
||||||
|
is_open_write: f.is_open_read
|
||||||
|
deferred
|
||||||
|
end
|
||||||
|
|
||||||
|
item_to_file (g: G; f: FILE)
|
||||||
|
require
|
||||||
|
is_open_write: f.is_open_write
|
||||||
|
deferred
|
||||||
|
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
|
||||||
49
src/cache/cms_file_object_cache.e
vendored
Normal file
49
src/cache/cms_file_object_cache.e
vendored
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
note
|
||||||
|
description: "Cache for value conforming to formal {G}, and implemented using local file."
|
||||||
|
date: "$Date: 2014-10-30 12:13:25 +0100 (jeu., 30 oct. 2014) $"
|
||||||
|
revision: "$Revision: 96016 $"
|
||||||
|
|
||||||
|
class
|
||||||
|
CMS_FILE_OBJECT_CACHE [G -> ANY]
|
||||||
|
|
||||||
|
inherit
|
||||||
|
CMS_FILE_CACHE [G]
|
||||||
|
|
||||||
|
SED_STORABLE_FACILITIES
|
||||||
|
|
||||||
|
create
|
||||||
|
make
|
||||||
|
|
||||||
|
feature {NONE} -- Implementation
|
||||||
|
|
||||||
|
file_to_item (f: FILE): detachable G
|
||||||
|
local
|
||||||
|
retried: BOOLEAN
|
||||||
|
l_reader: SED_MEDIUM_READER_WRITER
|
||||||
|
l_void: detachable G
|
||||||
|
do
|
||||||
|
if retried then
|
||||||
|
Result := l_void
|
||||||
|
else
|
||||||
|
create l_reader.make_for_reading (f)
|
||||||
|
if attached {G} retrieved (l_reader, True) as l_data then
|
||||||
|
Result := l_data
|
||||||
|
end
|
||||||
|
end
|
||||||
|
rescue
|
||||||
|
retried := True
|
||||||
|
retry
|
||||||
|
end
|
||||||
|
|
||||||
|
item_to_file (a_data: G; f: FILE)
|
||||||
|
local
|
||||||
|
l_writer: SED_MEDIUM_READER_WRITER
|
||||||
|
do
|
||||||
|
create l_writer.make_for_writing (f)
|
||||||
|
basic_store (a_data, l_writer, True)
|
||||||
|
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
src/cache/cms_file_string_8_cache.e
vendored
Normal file
69
src/cache/cms_file_string_8_cache.e
vendored
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
note
|
||||||
|
description: "Cache system for STRING_8 value."
|
||||||
|
date: "$Date: 2014-10-30 12:13:25 +0100 (jeu., 30 oct. 2014) $"
|
||||||
|
revision: "$Revision: 96016 $"
|
||||||
|
|
||||||
|
class
|
||||||
|
CMS_FILE_STRING_8_CACHE
|
||||||
|
|
||||||
|
inherit
|
||||||
|
CMS_FILE_CACHE [STRING]
|
||||||
|
|
||||||
|
create
|
||||||
|
make
|
||||||
|
|
||||||
|
feature -- Access
|
||||||
|
|
||||||
|
append_to (a_output: STRING)
|
||||||
|
-- Append `item' to `a_output'.
|
||||||
|
local
|
||||||
|
f: RAW_FILE
|
||||||
|
retried: BOOLEAN
|
||||||
|
do
|
||||||
|
if not retried then
|
||||||
|
create f.make_with_path (path)
|
||||||
|
if f.exists and then f.is_access_readable then
|
||||||
|
f.open_read
|
||||||
|
if attached file_to_item (f) as s then
|
||||||
|
a_output.append (s)
|
||||||
|
end
|
||||||
|
f.close
|
||||||
|
end
|
||||||
|
end
|
||||||
|
rescue
|
||||||
|
retried := True
|
||||||
|
retry
|
||||||
|
end
|
||||||
|
|
||||||
|
feature {NONE} -- Implementation
|
||||||
|
|
||||||
|
file_to_item (f: FILE): detachable STRING
|
||||||
|
local
|
||||||
|
retried: BOOLEAN
|
||||||
|
do
|
||||||
|
if retried then
|
||||||
|
Result := Void
|
||||||
|
else
|
||||||
|
from
|
||||||
|
create Result.make_empty
|
||||||
|
until
|
||||||
|
f.exhausted or f.end_of_file
|
||||||
|
loop
|
||||||
|
f.read_stream_thread_aware (1_024)
|
||||||
|
Result.append (f.last_string)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
rescue
|
||||||
|
retried := True
|
||||||
|
retry
|
||||||
|
end
|
||||||
|
|
||||||
|
item_to_file (a_data: STRING; f: FILE)
|
||||||
|
do
|
||||||
|
f.put_string (a_data)
|
||||||
|
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
|
||||||
61
src/cache/cms_memory_cache.e
vendored
Normal file
61
src/cache/cms_memory_cache.e
vendored
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
note
|
||||||
|
description: "Cache relying on memory."
|
||||||
|
date: "$Date: 2014-12-03 16:57:00 +0100 (mer., 03 déc. 2014) $"
|
||||||
|
revision: "$Revision: 96234 $"
|
||||||
|
|
||||||
|
deferred class
|
||||||
|
CMS_MEMORY_CACHE [G -> ANY]
|
||||||
|
|
||||||
|
inherit
|
||||||
|
CMS_CACHE [G]
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
make
|
||||||
|
do
|
||||||
|
cache_date_time := current_date_time
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
feature -- Status report
|
||||||
|
|
||||||
|
exists: BOOLEAN
|
||||||
|
-- Do associated cache memory exists?
|
||||||
|
do
|
||||||
|
Result := item /= Void
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Access
|
||||||
|
|
||||||
|
cache_date_time: DATE_TIME
|
||||||
|
|
||||||
|
current_date_time: DATE_TIME
|
||||||
|
-- <Precursor>
|
||||||
|
do
|
||||||
|
create Result.make_now_utc
|
||||||
|
end
|
||||||
|
|
||||||
|
item: detachable G
|
||||||
|
|
||||||
|
feature -- Element change
|
||||||
|
|
||||||
|
delete
|
||||||
|
-- <Precursor>
|
||||||
|
local
|
||||||
|
l_default: detachable G
|
||||||
|
do
|
||||||
|
item := l_default
|
||||||
|
cache_date_time := current_date_time
|
||||||
|
end
|
||||||
|
|
||||||
|
put (g: G)
|
||||||
|
-- <Precursor>
|
||||||
|
do
|
||||||
|
item := g
|
||||||
|
cache_date_time := current_date_time
|
||||||
|
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
|
||||||
@@ -68,6 +68,18 @@ feature -- Access
|
|||||||
Result := configuration.resolved_text_item (a_name)
|
Result := configuration.resolved_text_item (a_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
text_list_item (a_name: READABLE_STRING_GENERAL): detachable LIST [READABLE_STRING_32]
|
||||||
|
-- Configuration values associated with `a_name', if any.
|
||||||
|
do
|
||||||
|
Result := configuration.text_list_item (a_name)
|
||||||
|
end
|
||||||
|
|
||||||
|
text_table_item (a_name: READABLE_STRING_GENERAL): detachable STRING_TABLE [READABLE_STRING_32]
|
||||||
|
-- Configuration indexed values associated with `a_name', if any.
|
||||||
|
do
|
||||||
|
Result := configuration.text_table_item (a_name)
|
||||||
|
end
|
||||||
|
|
||||||
string_8_item (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_8
|
string_8_item (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_8
|
||||||
-- String 8 configuration value associated with `a_name', if any.
|
-- String 8 configuration value associated with `a_name', if any.
|
||||||
local
|
local
|
||||||
|
|||||||
@@ -196,6 +196,16 @@ feature -- Query
|
|||||||
deferred
|
deferred
|
||||||
end
|
end
|
||||||
|
|
||||||
|
text_list_item (a_name: READABLE_STRING_GENERAL): detachable LIST [READABLE_STRING_32]
|
||||||
|
-- Configuration values associated with `a_name', if any.
|
||||||
|
deferred
|
||||||
|
end
|
||||||
|
|
||||||
|
text_table_item (a_name: READABLE_STRING_GENERAL): detachable STRING_TABLE [READABLE_STRING_32]
|
||||||
|
-- Configuration indexed values associated with `a_name', if any.
|
||||||
|
deferred
|
||||||
|
end
|
||||||
|
|
||||||
text_item_or_default (a_name: READABLE_STRING_GENERAL; a_default_value: READABLE_STRING_GENERAL): READABLE_STRING_32
|
text_item_or_default (a_name: READABLE_STRING_GENERAL; a_default_value: READABLE_STRING_GENERAL): READABLE_STRING_32
|
||||||
-- `text_item' associated with `a_name' or if none, `a_default_value'.
|
-- `text_item' associated with `a_name' or if none, `a_default_value'.
|
||||||
do
|
do
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ feature -- Hook
|
|||||||
|
|
||||||
block_list: ITERABLE [like {CMS_BLOCK}.name]
|
block_list: ITERABLE [like {CMS_BLOCK}.name]
|
||||||
-- List of block names, managed by current object.
|
-- List of block names, managed by current object.
|
||||||
|
-- If prefixed by "?", condition will be check
|
||||||
|
-- to determine if it should be displayed (and computed) or not.
|
||||||
deferred
|
deferred
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -23,4 +25,7 @@ feature -- Hook
|
|||||||
deferred
|
deferred
|
||||||
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
|
end
|
||||||
|
|||||||
@@ -138,6 +138,11 @@ feature -- Hook: block
|
|||||||
|
|
||||||
invoke_block (a_response: CMS_RESPONSE)
|
invoke_block (a_response: CMS_RESPONSE)
|
||||||
-- Invoke block hook for response `a_response' in order to get block from modules.
|
-- Invoke block hook for response `a_response' in order to get block from modules.
|
||||||
|
local
|
||||||
|
bl: READABLE_STRING_8
|
||||||
|
bl_optional: BOOLEAN
|
||||||
|
l_ok: BOOLEAN
|
||||||
|
l_block_cache: detachable TUPLE [block: CMS_CACHE_BLOCK; region: READABLE_STRING_8; expired: BOOLEAN]
|
||||||
do
|
do
|
||||||
if attached subscribers ({CMS_HOOK_BLOCK}) as lst then
|
if attached subscribers ({CMS_HOOK_BLOCK}) as lst then
|
||||||
across
|
across
|
||||||
@@ -147,7 +152,25 @@ feature -- Hook: block
|
|||||||
across
|
across
|
||||||
h.block_list as blst
|
h.block_list as blst
|
||||||
loop
|
loop
|
||||||
h.get_block_view (blst.item, a_response)
|
l_ok := False
|
||||||
|
bl := blst.item
|
||||||
|
bl_optional := bl.count > 0 and bl[1] = '?'
|
||||||
|
if bl_optional then
|
||||||
|
bl := bl.substring (2, bl.count)
|
||||||
|
if a_response.is_block_included (bl, False) then
|
||||||
|
l_ok := True
|
||||||
|
end
|
||||||
|
else
|
||||||
|
l_ok := True
|
||||||
|
end
|
||||||
|
if l_ok then
|
||||||
|
l_block_cache := a_response.block_cache (bl)
|
||||||
|
if l_block_cache /= Void and then not l_block_cache.expired then
|
||||||
|
a_response.add_block (l_block_cache.block, l_block_cache.region)
|
||||||
|
else
|
||||||
|
h.get_block_view (bl, a_response)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
24
src/kernel/content/block/condition/cms_block_condition.e
Normal file
24
src/kernel/content/block/condition/cms_block_condition.e
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
note
|
||||||
|
description: "Condition for block to be displayed."
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
deferred class
|
||||||
|
CMS_BLOCK_CONDITION
|
||||||
|
|
||||||
|
feature -- Access
|
||||||
|
|
||||||
|
description: READABLE_STRING_32
|
||||||
|
deferred
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Evaluation
|
||||||
|
|
||||||
|
satisfied_for_response (res: CMS_RESPONSE): BOOLEAN
|
||||||
|
deferred
|
||||||
|
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
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
note
|
||||||
|
description: "Condition for block to be displayed."
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
CMS_BLOCK_EXPRESSION_CONDITION
|
||||||
|
|
||||||
|
inherit
|
||||||
|
CMS_BLOCK_CONDITION
|
||||||
|
|
||||||
|
create
|
||||||
|
make,
|
||||||
|
make_none
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
make (a_exp: READABLE_STRING_8)
|
||||||
|
do
|
||||||
|
expression := a_exp
|
||||||
|
end
|
||||||
|
|
||||||
|
make_none
|
||||||
|
do
|
||||||
|
make ("<none>")
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Access
|
||||||
|
|
||||||
|
description: STRING_32
|
||||||
|
do
|
||||||
|
create Result.make_from_string_general ("Expression: %"")
|
||||||
|
Result.append_string_general (expression)
|
||||||
|
Result.append_character ('%"')
|
||||||
|
end
|
||||||
|
|
||||||
|
expression: STRING
|
||||||
|
|
||||||
|
feature -- Evaluation
|
||||||
|
|
||||||
|
satisfied_for_response (res: CMS_RESPONSE): BOOLEAN
|
||||||
|
local
|
||||||
|
exp: like expression
|
||||||
|
do
|
||||||
|
exp := expression
|
||||||
|
if exp.same_string ("is_front") then
|
||||||
|
Result := res.is_front
|
||||||
|
elseif exp.same_string ("*") then
|
||||||
|
Result := True
|
||||||
|
elseif exp.same_string ("<none>") then
|
||||||
|
Result := False
|
||||||
|
elseif exp.starts_with ("path:") then
|
||||||
|
Result := res.location.same_string (exp.substring (6, exp.count))
|
||||||
|
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
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
note
|
||||||
|
description: "Condition for block to be displayed based on location."
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
CMS_BLOCK_LOCATION_CONDITION
|
||||||
|
|
||||||
|
inherit
|
||||||
|
CMS_BLOCK_CONDITION
|
||||||
|
|
||||||
|
create
|
||||||
|
make_with_location
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
make_with_location (a_location: READABLE_STRING_8)
|
||||||
|
do
|
||||||
|
location := a_location
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Access
|
||||||
|
|
||||||
|
description: STRING_32
|
||||||
|
do
|
||||||
|
create Result.make_from_string_general ("Location: %"")
|
||||||
|
Result.append_string_general (location)
|
||||||
|
Result.append_character ('%"')
|
||||||
|
end
|
||||||
|
|
||||||
|
location: STRING
|
||||||
|
|
||||||
|
feature -- Evaluation
|
||||||
|
|
||||||
|
satisfied_for_response (res: CMS_RESPONSE): BOOLEAN
|
||||||
|
local
|
||||||
|
loc: like location
|
||||||
|
do
|
||||||
|
Result := res.location.same_string (loc)
|
||||||
|
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
|
||||||
@@ -39,6 +39,9 @@ feature -- Status report
|
|||||||
deferred
|
deferred
|
||||||
end
|
end
|
||||||
|
|
||||||
|
conditions: detachable LIST [CMS_BLOCK_CONDITION]
|
||||||
|
-- Optional block condition to be enabled.
|
||||||
|
|
||||||
feature -- Element change
|
feature -- Element change
|
||||||
|
|
||||||
add_css_class (a_class: READABLE_STRING_8)
|
add_css_class (a_class: READABLE_STRING_8)
|
||||||
@@ -67,6 +70,19 @@ feature -- Element change
|
|||||||
opts.remove_css_class (a_class)
|
opts.remove_css_class (a_class)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
add_condition (a_condition: CMS_BLOCK_CONDITION)
|
||||||
|
-- Add condition `a_condition'.
|
||||||
|
local
|
||||||
|
l_conditions: like conditions
|
||||||
|
do
|
||||||
|
l_conditions := conditions
|
||||||
|
if l_conditions = Void then
|
||||||
|
create {ARRAYED_LIST [CMS_BLOCK_CONDITION]} l_conditions.make (1)
|
||||||
|
conditions := l_conditions
|
||||||
|
end
|
||||||
|
l_conditions.force (a_condition)
|
||||||
|
end
|
||||||
|
|
||||||
feature -- Conversion
|
feature -- Conversion
|
||||||
|
|
||||||
to_html (a_theme: CMS_THEME): STRING_8
|
to_html (a_theme: CMS_THEME): STRING_8
|
||||||
|
|||||||
99
src/kernel/content/cms_cache_block.e
Normal file
99
src/kernel/content/cms_cache_block.e
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
note
|
||||||
|
description: "[
|
||||||
|
CMS_BLOCK implemented with a `cache'
|
||||||
|
as caching solution.
|
||||||
|
]"
|
||||||
|
date: "$Date: 2014-11-18 10:13:13 +0100 (mar., 18 nov. 2014) $"
|
||||||
|
revision: "$Revision: 96110 $"
|
||||||
|
|
||||||
|
class
|
||||||
|
CMS_CACHE_BLOCK
|
||||||
|
|
||||||
|
inherit
|
||||||
|
CMS_BLOCK
|
||||||
|
|
||||||
|
create
|
||||||
|
make
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
make (a_name: like name; a_cache: like cache)
|
||||||
|
require
|
||||||
|
a_name_not_blank: not a_name.is_whitespace
|
||||||
|
do
|
||||||
|
is_enabled := True
|
||||||
|
name := a_name
|
||||||
|
cache := a_cache
|
||||||
|
set_is_raw (True)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Access
|
||||||
|
|
||||||
|
name: READABLE_STRING_8
|
||||||
|
-- <Precursor>
|
||||||
|
|
||||||
|
title: detachable READABLE_STRING_32
|
||||||
|
-- <Precursor>
|
||||||
|
|
||||||
|
cache: CMS_CACHE [READABLE_STRING_8]
|
||||||
|
-- Cache content.
|
||||||
|
|
||||||
|
feature -- Status report
|
||||||
|
|
||||||
|
is_empty: BOOLEAN
|
||||||
|
-- Is current block empty?
|
||||||
|
do
|
||||||
|
Result := is_raw and not cache.exists
|
||||||
|
end
|
||||||
|
|
||||||
|
is_raw: BOOLEAN assign set_is_raw
|
||||||
|
-- Is raw?
|
||||||
|
-- If True, do not get wrapped it with block specific div
|
||||||
|
|
||||||
|
feature -- Element change
|
||||||
|
|
||||||
|
set_is_raw (b: BOOLEAN)
|
||||||
|
do
|
||||||
|
is_raw := b
|
||||||
|
end
|
||||||
|
|
||||||
|
set_name (n: like name)
|
||||||
|
-- Set `name' to `n'.
|
||||||
|
require
|
||||||
|
not n.is_whitespace
|
||||||
|
do
|
||||||
|
name := n
|
||||||
|
end
|
||||||
|
|
||||||
|
set_title (a_title: like title)
|
||||||
|
-- Set `title' to `a_title'.
|
||||||
|
do
|
||||||
|
title := a_title
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Conversion
|
||||||
|
|
||||||
|
to_html (a_theme: CMS_THEME): STRING_8
|
||||||
|
do
|
||||||
|
debug
|
||||||
|
print ("REUSE CACHE for [" + name + "]!!!%N")
|
||||||
|
end
|
||||||
|
-- Why in this particular case theme is not used to generate the content?
|
||||||
|
if attached cache.item as l_content then
|
||||||
|
Result := l_content
|
||||||
|
else
|
||||||
|
Result := ""
|
||||||
|
check exists: False 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)"
|
||||||
|
source: "[
|
||||||
|
Eiffel Software
|
||||||
|
5949 Hollister Ave., Goleta, CA 93117 USA
|
||||||
|
Telephone 805-685-1006, Fax 805-685-6869
|
||||||
|
Website http://www.eiffel.com
|
||||||
|
Customer support http://support.eiffel.com
|
||||||
|
]"
|
||||||
|
end
|
||||||
@@ -58,7 +58,7 @@ feature -- Hooks
|
|||||||
|
|
||||||
block_list: ITERABLE [like {CMS_BLOCK}.name]
|
block_list: ITERABLE [like {CMS_BLOCK}.name]
|
||||||
do
|
do
|
||||||
Result := <<"debug-info">>
|
Result := <<"?debug-info">>
|
||||||
end
|
end
|
||||||
|
|
||||||
get_block_view (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE)
|
get_block_view (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE)
|
||||||
@@ -67,14 +67,13 @@ feature -- Hooks
|
|||||||
dbg: WSF_DEBUG_INFORMATION
|
dbg: WSF_DEBUG_INFORMATION
|
||||||
s: STRING
|
s: STRING
|
||||||
do
|
do
|
||||||
if a_response.theme.has_region ("debug") then
|
create dbg.make
|
||||||
create dbg.make
|
create s.make_empty
|
||||||
create s.make_empty
|
dbg.append_information_to (a_response.request, a_response.response, s)
|
||||||
dbg.append_information_to (a_response.request, a_response.response, s)
|
append_info_to ("Storage", a_response.api.storage.generator, a_response, s)
|
||||||
append_info_to ("Storage", a_response.api.storage.generator, a_response, s)
|
create b.make ("debug-info", "Debug", s, a_response.formats.plain_text)
|
||||||
create b.make ("debug-info", "Debug", s, a_response.formats.plain_text)
|
b.add_condition (create {CMS_BLOCK_EXPRESSION_CONDITION}.make_none)
|
||||||
a_response.add_block (b, "footer")
|
a_response.add_block (b, "footer")
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Handler
|
feature -- Handler
|
||||||
|
|||||||
@@ -423,6 +423,59 @@ feature -- Blocks initialization
|
|||||||
Result := setup.text_item_or_default ("blocks." + a_block_id + ".region", a_default_region)
|
Result := setup.text_item_or_default ("blocks." + a_block_id + ".region", a_default_region)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
block_conditions (a_block_id: READABLE_STRING_8): detachable ARRAYED_LIST [CMS_BLOCK_EXPRESSION_CONDITION]
|
||||||
|
-- Condition associated with `a_block_id' in configuration, if any.
|
||||||
|
do
|
||||||
|
if attached setup.text_item ("blocks." + a_block_id + ".condition") as s then
|
||||||
|
create Result.make (1)
|
||||||
|
Result.force (create {CMS_BLOCK_EXPRESSION_CONDITION}.make (s))
|
||||||
|
end
|
||||||
|
if attached setup.text_list_item ("blocks." + a_block_id + ".conditions") as lst then
|
||||||
|
if Result = Void then
|
||||||
|
create Result.make (lst.count)
|
||||||
|
across
|
||||||
|
lst as ic
|
||||||
|
loop
|
||||||
|
Result.force (create {CMS_BLOCK_EXPRESSION_CONDITION}.make (ic.item))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
is_block_included (a_block_id: READABLE_STRING_8; dft: BOOLEAN): BOOLEAN
|
||||||
|
-- Is block `a_block_id' included in current response?
|
||||||
|
-- If no preference, return `dft'.
|
||||||
|
do
|
||||||
|
if attached block_conditions (a_block_id) as l_conditions then
|
||||||
|
Result := across l_conditions as ic some ic.item.satisfied_for_response (Current) end
|
||||||
|
else
|
||||||
|
Result := dft
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
block_cache (a_block_id: READABLE_STRING_8): detachable TUPLE [block: CMS_CACHE_BLOCK; region: READABLE_STRING_8; expired: BOOLEAN]
|
||||||
|
-- Cached version of block `a_block_id'.
|
||||||
|
local
|
||||||
|
l_cache: CMS_FILE_STRING_8_CACHE
|
||||||
|
do
|
||||||
|
if
|
||||||
|
attached setup.text_item ("blocks." + a_block_id + ".expiration") as nb_secs and then
|
||||||
|
nb_secs.is_integer
|
||||||
|
then
|
||||||
|
if attached block_region_preference (a_block_id, "none") as l_region and then not l_region.same_string_general ("none") then
|
||||||
|
create l_cache.make (api.files_location.extended (".cache").extended ("blocks").extended (a_block_id).appended_with_extension ("html"))
|
||||||
|
if
|
||||||
|
l_cache.exists and then
|
||||||
|
not l_cache.expired (Void, nb_secs.to_integer)
|
||||||
|
then
|
||||||
|
Result := [create {CMS_CACHE_BLOCK} .make (a_block_id, l_cache), l_region, False]
|
||||||
|
else
|
||||||
|
Result := [create {CMS_CACHE_BLOCK} .make (a_block_id, l_cache), l_region, True]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
feature -- Blocks regions
|
feature -- Blocks regions
|
||||||
|
|
||||||
regions: STRING_TABLE [CMS_BLOCK_REGION]
|
regions: STRING_TABLE [CMS_BLOCK_REGION]
|
||||||
@@ -459,8 +512,23 @@ feature -- Blocks regions
|
|||||||
|
|
||||||
feature -- Blocks
|
feature -- Blocks
|
||||||
|
|
||||||
|
put_block (b: CMS_BLOCK; a_default_region: detachable READABLE_STRING_8; is_block_included_by_default: BOOLEAN)
|
||||||
|
-- Add block `b' to associated region or `a_default_region' if provided
|
||||||
|
-- and check optional associated condition.
|
||||||
|
-- If no condition then use `is_block_included_by_default' to
|
||||||
|
-- decide if block is included or not.
|
||||||
|
local
|
||||||
|
l_region: detachable like block_region
|
||||||
|
do
|
||||||
|
if is_block_included (b.name, is_block_included_by_default) then
|
||||||
|
l_region := block_region (b, a_default_region)
|
||||||
|
l_region.extend (b)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
add_block (b: CMS_BLOCK; a_default_region: detachable READABLE_STRING_8)
|
add_block (b: CMS_BLOCK; a_default_region: detachable READABLE_STRING_8)
|
||||||
-- Add block `b' to associated region or `a_default_region' if provided.
|
-- Add block `b' to associated region or `a_default_region' if provided.
|
||||||
|
-- WARNING: ignore any block condition! USE WITH CARE!
|
||||||
local
|
local
|
||||||
l_region: detachable like block_region
|
l_region: detachable like block_region
|
||||||
do
|
do
|
||||||
@@ -473,29 +541,29 @@ feature -- Blocks
|
|||||||
debug ("refactor_fixme")
|
debug ("refactor_fixme")
|
||||||
fixme ("find a way to have this in configuration or database, and allow different order")
|
fixme ("find a way to have this in configuration or database, and allow different order")
|
||||||
end
|
end
|
||||||
add_block (top_header_block, "top")
|
put_block (top_header_block, "top", True)
|
||||||
add_block (header_block, "header")
|
put_block (header_block, "header", True)
|
||||||
if attached message_block as m then
|
if attached message_block as m then
|
||||||
add_block (m, "content")
|
put_block (m, "content", True)
|
||||||
end
|
end
|
||||||
if attached primary_tabs_block as m then
|
if attached primary_tabs_block as m then
|
||||||
add_block (m, "content")
|
put_block (m, "content", True)
|
||||||
end
|
end
|
||||||
add_block (content_block, "content")
|
add_block (content_block, "content") -- Can not be disabled!
|
||||||
|
|
||||||
if attached management_menu_block as l_block then
|
if attached management_menu_block as l_block then
|
||||||
add_block (l_block, "sidebar_first")
|
put_block (l_block, "sidebar_first", True)
|
||||||
end
|
end
|
||||||
if attached navigation_menu_block as l_block then
|
if attached navigation_menu_block as l_block then
|
||||||
add_block (l_block, "sidebar_first")
|
put_block (l_block, "sidebar_first", True)
|
||||||
end
|
end
|
||||||
if attached user_menu_block as l_block then
|
if attached user_menu_block as l_block then
|
||||||
add_block (l_block, "sidebar_second")
|
put_block (l_block, "sidebar_second", True)
|
||||||
end
|
end
|
||||||
|
|
||||||
hooks.invoke_block (Current)
|
hooks.invoke_block (Current)
|
||||||
debug ("cms")
|
debug ("cms")
|
||||||
add_block (create {CMS_CONTENT_BLOCK}.make ("made_with", Void, "Made with <a href=%"http://www.eiffel.com/%">EWF</a>", Void), "footer")
|
put_block (create {CMS_CONTENT_BLOCK}.make ("made_with", Void, "Made with <a href=%"https://www.eiffel.org/%">EWF</a>", Void), "footer", True)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -741,6 +809,7 @@ feature -- Generation
|
|||||||
l_region: CMS_BLOCK_REGION
|
l_region: CMS_BLOCK_REGION
|
||||||
l_menu_list_prepared: ARRAYED_LIST [CMS_LINK_COMPOSITE]
|
l_menu_list_prepared: ARRAYED_LIST [CMS_LINK_COMPOSITE]
|
||||||
l_empty_blocks: detachable ARRAYED_LIST [CMS_BLOCK]
|
l_empty_blocks: detachable ARRAYED_LIST [CMS_BLOCK]
|
||||||
|
l_block_html: STRING
|
||||||
do
|
do
|
||||||
-- Menu
|
-- Menu
|
||||||
create {CMS_LOCAL_LINK} lnk.make ("Home", "")
|
create {CMS_LOCAL_LINK} lnk.make ("Home", "")
|
||||||
@@ -839,7 +908,13 @@ feature -- Generation
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
page.add_to_region (theme.block_html (ic.item), reg_ic.item.name)
|
l_block_html := theme.block_html (ic.item)
|
||||||
|
if attached {CMS_CACHE_BLOCK} ic.item then
|
||||||
|
|
||||||
|
elseif attached block_cache (ic.item.name) as l_cache_block then
|
||||||
|
l_cache_block.block.cache.put (l_block_html)
|
||||||
|
end
|
||||||
|
page.add_to_region (l_block_html, reg_ic.item.name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user