diff --git a/examples/demo/demo-safe.ecf b/examples/demo/demo-safe.ecf index 1c12f20..8f28c4b 100644 --- a/examples/demo/demo-safe.ecf +++ b/examples/demo/demo-safe.ecf @@ -19,6 +19,7 @@ + diff --git a/examples/demo/install_modules.bat b/examples/demo/install_modules.bat index 1880e20..8e578be 100644 --- a/examples/demo/install_modules.bat +++ b/examples/demo/install_modules.bat @@ -10,3 +10,4 @@ set ROC_CMS_DIR=%~dp0 %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\recent_changes --dir %ROC_CMS_DIR% +%ROC_CMD% install --module ..\..\modules\feed_aggregator --dir %ROC_CMS_DIR% diff --git a/examples/demo/site/config/cms.ini b/examples/demo/site/config/cms.ini index cf32a1c..9a90715 100644 --- a/examples/demo/site/config/cms.ini +++ b/examples/demo/site/config/cms.ini @@ -33,6 +33,9 @@ openid=on [blocks] #navigation.region=sidebar_first +feed__bertrandmeyer.region=content +feed__eiffelroom.region=content +feed__bertrandmeyer.condition=is_front [admin] # CMS Installation, are accessible by "all", "none" or uppon "permission". (default is none) diff --git a/examples/demo/src/ewf_roc_server_execution.e b/examples/demo/src/ewf_roc_server_execution.e index 40c16c4..db4dbf7 100644 --- a/examples/demo/src/ewf_roc_server_execution.e +++ b/examples/demo/src/ewf_roc_server_execution.e @@ -82,6 +82,9 @@ feature -- CMS setup create {CMS_RECENT_CHANGES_MODULE} m.make a_setup.register_module (m) + -- Recent changes + create {FEED_AGGREGATOR_MODULE} m.make + a_setup.register_module (m) -- Miscellanious create {CMS_DEBUG_MODULE} m.make diff --git a/modules/feed_aggregator/feed_aggregation.e b/modules/feed_aggregator/feed_aggregation.e new file mode 100644 index 0000000..1688089 --- /dev/null +++ b/modules/feed_aggregator/feed_aggregation.e @@ -0,0 +1,42 @@ +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) + end + +feature -- Access + + name: IMMUTABLE_STRING_32 + -- Associated name. + + description: detachable IMMUTABLE_STRING_32 + -- Optional description. + + locations: LIST [READABLE_STRING_8] + -- List of feed location aggregated into current. + +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 + +end diff --git a/modules/feed_aggregator/feed_aggregator-safe.ecf b/modules/feed_aggregator/feed_aggregator-safe.ecf new file mode 100644 index 0000000..6baa236 --- /dev/null +++ b/modules/feed_aggregator/feed_aggregator-safe.ecf @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/modules/feed_aggregator/feed_aggregator_api.e b/modules/feed_aggregator/feed_aggregator_api.e new file mode 100644 index 0000000..3928a77 --- /dev/null +++ b/modules/feed_aggregator/feed_aggregator_api.e @@ -0,0 +1,39 @@ +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 + do + create Result.make (2) + create agg.make ("Blog from Bertrand Meyer") + agg.locations.force ("https://bertrandmeyer.com/category/computer-science/feed/") + Result.force (agg, "bertrandmeyer") + + create agg.make ("Eiffel Room") + agg.locations.force ("https://room.eiffel.com/recent_changes/feed") + Result.force (agg, "eiffelroom") + 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 + +end diff --git a/modules/feed_aggregator/feed_aggregator_module.e b/modules/feed_aggregator/feed_aggregator_module.e new file mode 100644 index 0000000..c510cb8 --- /dev/null +++ b/modules/feed_aggregator/feed_aggregator_module.e @@ -0,0 +1,146 @@ +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 + +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) + -- + 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) + -- + 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) + 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) + 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] + do + create res.make (5) + if attached feed_aggregator_api as l_feed_api then + across + l_feed_api.aggregations as ic + loop + res.force ("feed__" + ic.key) + end + 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 + i: INTEGER + s: READABLE_STRING_8 + b: CMS_CONTENT_BLOCK + l_content: STRING + 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 l_feed_api.aggregation (s) as l_agg then + create l_content.make_empty + if attached l_agg.description as l_desc then + l_content.append_string_general (l_desc) + l_content.append_character ('%N') + l_content.append_character ('%N') + end + across + l_agg.locations as ic + loop + l_content.append ("%T-" + ic.item) + l_content.append_character ('%N') + end + create b.make (a_block_id, l_agg.name, l_content, Void) + a_response.add_block (b, Void) + end + end + end + +feature -- Hook + + response_alter (a_response: CMS_RESPONSE) + do +-- a_response.add_additional_head_line ("[ +-- +-- ]", True) + end + +end diff --git a/package.iron b/package.iron index fd2052a..be2ec6b 100644 --- a/package.iron +++ b/package.iron @@ -1,4 +1,4 @@ -package ROC_cms +package ROC project cms = "cms-safe.ecf" @@ -19,6 +19,21 @@ project basic_auth = "modules/basic_auth/basic_auth.ecf" node = "modules/node/node-safe.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 title: ROC CMS @@ -27,5 +42,6 @@ note license: Eiffel Forum v2 copyright: Jocelyn Fiat, Javier Velilla, Eiffel Software link[source]: "Github" https://github.com/EiffelWebFramework/ROC.git +-- link[doc]: "Documentation" http:// end diff --git a/src/kernel/content/block/condition/cms_block_condition.e b/src/kernel/content/block/condition/cms_block_condition.e new file mode 100644 index 0000000..4c4c7a5 --- /dev/null +++ b/src/kernel/content/block/condition/cms_block_condition.e @@ -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 diff --git a/src/kernel/content/block/condition/cms_block_expression_condition.e b/src/kernel/content/block/condition/cms_block_expression_condition.e new file mode 100644 index 0000000..72e5be5 --- /dev/null +++ b/src/kernel/content/block/condition/cms_block_expression_condition.e @@ -0,0 +1,46 @@ +note + description: "Condition for block to be displayed." + date: "$Date$" + revision: "$Revision$" + +class + CMS_BLOCK_EXPRESSION_CONDITION + +inherit + CMS_BLOCK_CONDITION + +create + make + +feature {NONE} -- Initialization + + make (a_exp: READABLE_STRING_8) + do + expression := a_exp + end + +feature -- Access + + description: READABLE_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 + do + if expression.same_string ("is_front") then + Result := res.is_front + elseif expression.starts_with ("path=") then + 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 diff --git a/src/kernel/content/cms_block.e b/src/kernel/content/cms_block.e index 94d4ed1..0bbf1aa 100644 --- a/src/kernel/content/cms_block.e +++ b/src/kernel/content/cms_block.e @@ -39,6 +39,9 @@ feature -- Status report deferred end + conditions: detachable LIST [CMS_BLOCK_CONDITION] + -- Optional block condition to be enabled. + feature -- Element change add_css_class (a_class: READABLE_STRING_8)