From bb25a8b12e1572ed3f9494c91309a36987c388e7 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Fri, 3 Mar 2017 13:16:04 +0100 Subject: [PATCH] Added feed ordered by publication on /nodes/{type}/feed. --- modules/node/cms_node_api.e | 6 + modules/node/cms_node_module.e | 1 + modules/node/handler/nodes_handler.e | 118 +++++++++++++++--- modules/node/node-safe.ecf | 1 + modules/node/node.ecf | 1 + modules/node/persistence/cms_node_storage_i.e | 8 ++ .../node/persistence/cms_node_storage_null.e | 6 + .../node/persistence/cms_node_storage_sql.e | 32 +++++ 8 files changed, 157 insertions(+), 16 deletions(-) diff --git a/modules/node/cms_node_api.e b/modules/node/cms_node_api.e index 47517d8..1804e4b 100644 --- a/modules/node/cms_node_api.e +++ b/modules/node/cms_node_api.e @@ -190,6 +190,12 @@ feature -- Access: Node Result := node_storage.recent_nodes_of_type (a_content_type, params.offset.to_integer_32, params.size.to_integer_32) end + recent_published_nodes_of_type (a_content_type: CMS_CONTENT_TYPE; params: CMS_DATA_QUERY_PARAMETERS): ITERABLE [CMS_NODE] + -- Most recent published `a_content_type` nodes according to `params.offset' and `params.size', and order by publication_date. + do + Result := node_storage.recent_published_nodes_of_type (a_content_type, params.offset.to_integer_32, params.size.to_integer_32) + end + recent_node_changes_before (params: CMS_DATA_QUERY_PARAMETERS; a_date: DATE_TIME): ITERABLE [CMS_NODE] -- List of recent changes, before `a_date', according to `params' settings. do diff --git a/modules/node/cms_node_module.e b/modules/node/cms_node_module.e index d541063..386f820 100644 --- a/modules/node/cms_node_module.e +++ b/modules/node/cms_node_module.e @@ -196,6 +196,7 @@ feature -- Access: router create l_uri_mapping.make_trailing_slash_ignored ("/nodes", l_nodes_handler) a_router.map (l_uri_mapping, a_router.methods_get) a_router.handle ("/nodes/{type}", l_nodes_handler, a_router.methods_get) + a_router.handle ("/nodes/{type}/feed", l_nodes_handler, a_router.methods_get) -- Trash create l_trash_handler.make (a_api, a_node_api) diff --git a/modules/node/handler/nodes_handler.e b/modules/node/handler/nodes_handler.e index f9a5131..4cbddc7 100644 --- a/modules/node/handler/nodes_handler.e +++ b/modules/node/handler/nodes_handler.e @@ -55,10 +55,100 @@ feature -- HTTP Methods do_get (req: WSF_REQUEST; res: WSF_RESPONSE) -- + local + l_content_type: detachable CMS_CONTENT_TYPE + do + if attached {WSF_STRING} req.path_parameter ("type") as p_node_type and then attached api.content_type (p_node_type.value) as ct then + l_content_type := api.content_type (p_node_type.value) + end + if l_content_type /= Void and then req.path_info.ends_with_general ("/feed") then + do_nodes_feed (l_content_type, req, res) + else + do_nodes_html (l_content_type, req, res) + end + end + + do_nodes_feed (a_content_type: CMS_CONTENT_TYPE; req: WSF_REQUEST; res: WSF_RESPONSE) + local + l_feed: FEED + l_feed_item: FEED_ITEM + l_params: CMS_DATA_QUERY_PARAMETERS + n: CMS_NODE + pg, nb: NATURAL_64 + l_size: NATURAL_64 + l_exhausted: BOOLEAN + lnk: FEED_LINK + mesg: CMS_CUSTOM_RESPONSE_MESSAGE + l_payload: STRING + do + create l_feed.make (a_content_type.name) + l_feed.set_date (create {DATE_TIME}.make_now_utc) + + if attached {WSF_STRING} req.query_parameter ("size") as p_size and then p_size.is_integer then + l_size := p_size.integer_value.to_natural_64 + else + l_size := 25 + end + + from + nb := 0 + pg := 0 + until + nb = l_size or l_exhausted + loop + create l_params.make (1 + (pg * 25), 25) + if attached node_api.recent_published_nodes_of_type (a_content_type, l_params) as lst then + l_exhausted := True + across + lst as ic + until + nb = l_size + loop + l_exhausted := False + n := ic.item + if n.is_published then + create l_feed_item.make (n.title) + if attached n.author as u then + l_feed_item.set_author (create {FEED_AUTHOR}.make (api.user_api.user_display_name (u))) + end + l_feed_item.set_date (n.publication_date) + create lnk.make (req.absolute_script_url ("/" + node_api.node_link (n).location)) + l_feed_item.links.force (lnk, "") + if attached n.summary as l_summary and then not l_summary.is_whitespace then + l_feed_item.set_description (l_summary) + -- elseif attached n.content as l_content then + -- l_feed_item.set_content (l_content, Void) + end + if attached {CMS_TAXONOMY_API} api.module_api ({CMS_TAXONOMY_MODULE}) as l_taxonomy_api then + if attached l_taxonomy_api.terms_of_content (n, Void) as coll then + across + coll as coll_ic + loop + l_feed_item.set_category (coll_ic.item.text) + end + end + end + nb := nb + 1 + l_feed.extend (l_feed_item) + end + end + else + l_exhausted := True + end + pg := pg + 1 + end + + create l_payload.make (2_048) + l_feed.accept (create {ATOM_FEED_GENERATOR}.make (l_payload)) + create mesg.make ({HTTP_STATUS_CODE}.ok) + mesg.set_payload (l_payload) + res.send (mesg) + end + + do_nodes_html (a_content_type: detachable CMS_CONTENT_TYPE; req: WSF_REQUEST; res: WSF_RESPONSE) local l_response: CMS_RESPONSE s: STRING - l_content_type: detachable CMS_CONTENT_TYPE n: CMS_NODE lnk: CMS_LOCAL_LINK l_page_helper: CMS_PAGINATION_GENERATOR @@ -68,13 +158,9 @@ feature -- HTTP Methods l_include_trashed: BOOLEAN lst: detachable ITERABLE [CMS_NODE] do - -- At the moment the template are hardcoded, but we can - -- get them from the configuration file and load them into - -- the setup class. - if attached {WSF_STRING} req.path_parameter ("type") as p_node_type and then attached api.content_type (p_node_type.value) as ct then - l_content_type := api.content_type (p_node_type.value) - end - + -- At the moment the template are hardcoded, but we can + -- get them from the configuration file and load them into + -- the setup class. create {GENERIC_VIEW_CMS_RESPONSE} l_response.make (req, res, api) create s.make_empty @@ -83,7 +169,7 @@ feature -- HTTP Methods loop if attached {CMS_NODE_TYPE [CMS_NODE]} ic.item as l_note_type then create lnk.make (l_note_type.name, "nodes/" + l_note_type.name) - if l_note_type = l_content_type then + if l_note_type = a_content_type then lnk.set_is_active (True) end l_response.add_to_primary_tabs (lnk) @@ -91,14 +177,14 @@ feature -- HTTP Methods end create s_pager.make_empty - if l_content_type /= Void then - l_count := node_api.nodes_of_type_count (l_content_type) + if a_content_type /= Void then + l_count := node_api.nodes_of_type_count (a_content_type) if l_count > 1 then - l_response.set_title ("Listing " + l_count.out + " " + l_content_type.name + " nodes") + l_response.set_title ("Listing " + l_count.out + " " + a_content_type.name + " nodes") else - l_response.set_title ("Listing " + l_count.out + " " + l_content_type.name + " node") + l_response.set_title ("Listing " + l_count.out + " " + a_content_type.name + " node") end - create l_page_helper.make ("nodes/" + l_content_type.name + "/?page={page}&size={size}", l_count, 25) -- FIXME: Make this default page size a global CMS settings + create l_page_helper.make ("nodes/" + a_content_type.name + "/?page={page}&size={size}", l_count, 25) -- FIXME: Make this default page size a global CMS settings else l_count := node_api.nodes_count if l_count > 1 then @@ -117,8 +203,8 @@ feature -- HTTP Methods end end - if l_content_type /= Void then - lst := node_api.recent_nodes_of_type (l_content_type, create {CMS_DATA_QUERY_PARAMETERS}.make (l_page_helper.current_page_offset, l_page_helper.page_size)) + if a_content_type /= Void then + lst := node_api.recent_nodes_of_type (a_content_type, create {CMS_DATA_QUERY_PARAMETERS}.make (l_page_helper.current_page_offset, l_page_helper.page_size)) else lst := node_api.recent_nodes (create {CMS_DATA_QUERY_PARAMETERS}.make (l_page_helper.current_page_offset, l_page_helper.page_size)) end diff --git a/modules/node/node-safe.ecf b/modules/node/node-safe.ecf index 713054f..10924ad 100644 --- a/modules/node/node-safe.ecf +++ b/modules/node/node-safe.ecf @@ -18,6 +18,7 @@ + diff --git a/modules/node/node.ecf b/modules/node/node.ecf index aa2908d..b7b0a6e 100644 --- a/modules/node/node.ecf +++ b/modules/node/node.ecf @@ -17,6 +17,7 @@ + diff --git a/modules/node/persistence/cms_node_storage_i.e b/modules/node/persistence/cms_node_storage_i.e index 53fa89a..bd6d430 100644 --- a/modules/node/persistence/cms_node_storage_i.e +++ b/modules/node/persistence/cms_node_storage_i.e @@ -107,6 +107,14 @@ feature -- Access across Result as ic all ic.item.is_typed_as (a_node_type.name) end end + recent_published_nodes_of_type (a_node_type: CMS_CONTENT_TYPE; a_lower: INTEGER; a_count: INTEGER): ITERABLE [CMS_NODE] + -- Recent published `a_count` nodes of type `a_node_type` with an offset of `lower` + deferred + ensure + expected_type: across Result as ic all ic.item.is_typed_as (a_node_type.name) end + published: across Result as ic all ic.item.is_published end + end + recent_node_changes_before (a_lower: INTEGER; a_count: INTEGER; a_date: DATE_TIME): LIST [CMS_NODE] -- List of recent changes, before `a_date', according to `params' settings. deferred diff --git a/modules/node/persistence/cms_node_storage_null.e b/modules/node/persistence/cms_node_storage_null.e index 978dc06..16f48c4 100644 --- a/modules/node/persistence/cms_node_storage_null.e +++ b/modules/node/persistence/cms_node_storage_null.e @@ -65,6 +65,12 @@ feature -- Access: node create {ARRAYED_LIST [CMS_NODE]} Result.make (0) end + recent_published_nodes_of_type (a_node_type: CMS_CONTENT_TYPE; a_lower: INTEGER; a_count: INTEGER): LIST [CMS_NODE] + -- + do + create {ARRAYED_LIST [CMS_NODE]} Result.make (0) + end + recent_node_changes_before (a_lower: INTEGER; a_count: INTEGER; a_date: DATE_TIME): LIST [CMS_NODE] -- List of recent changes, before `a_date', according to `params' settings. do diff --git a/modules/node/persistence/cms_node_storage_sql.e b/modules/node/persistence/cms_node_storage_sql.e index 33b817f..512b664 100644 --- a/modules/node/persistence/cms_node_storage_sql.e +++ b/modules/node/persistence/cms_node_storage_sql.e @@ -187,6 +187,32 @@ feature -- Access sql_finalize end + recent_published_nodes_of_type (a_node_type: CMS_CONTENT_TYPE; a_lower: INTEGER; a_count: INTEGER): LIST [CMS_NODE] + -- + local + l_parameters: STRING_TABLE [detachable ANY] + do + create {ARRAYED_LIST [CMS_NODE]} Result.make (0) + error_handler.reset + from + create l_parameters.make (4) + l_parameters.put (a_node_type.name, "node_type") + l_parameters.put (a_count, "size") + l_parameters.put (a_lower, "offset") + l_parameters.put ({CMS_NODE_API}.published, "status") + sql_query (sql_select_recent_published_nodes_of_type, l_parameters) + sql_start + until + sql_after + loop + if attached fetch_node as l_node then + Result.force (l_node) + end + sql_forth + end + sql_finalize + end + recent_node_changes_before (a_lower: INTEGER; a_count: INTEGER; a_date: DATE_TIME): LIST [CMS_NODE] -- List of recent changes, before `a_date', according to `params' settings. local @@ -580,6 +606,12 @@ feature {NONE} -- Queries nodes Result := sql_select_all_from_nodes + " WHERE type=:node_type ORDER BY changed DESC, publish DESC LIMIT :size OFFSET :offset ;" end + sql_select_recent_published_nodes_of_type: STRING + -- published nodes order by publication_date. + once + Result := sql_select_all_from_nodes + " WHERE type=:node_type AND status=:status ORDER BY publish DESC, changed DESC LIMIT :size OFFSET :offset ;" + end + sql_select_recent_node_changes_before: STRING -- once