From ecbcb6a5cba8c64dc6b5508b1276b0628275e6ee Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Thu, 3 Dec 2015 23:01:31 +0100 Subject: [PATCH] Added notion of CMS_CONTENT as ancestor of CMS_NODE. Moved CMS_CONTENT_TYPE to core library. Added basic and limited taxonomy query /taxonomy/term/{termid} . --- modules/blog/cms_blog_module.e | 2 +- modules/node/cms_node_api.e | 39 +++------- modules/node/cms_node_module.e | 6 +- modules/node/content/cms_node.e | 32 ++------ modules/node/handler/nodes_handler.e | 2 +- .../node/persistence/cms_node_storage_sql.e | 1 - .../cms_node_storage_sql_page_extension.e | 2 +- modules/taxonomy/cms_taxonomy_api.e | 10 ++- modules/taxonomy/cms_taxonomy_module.e | 14 +--- modules/taxonomy/handler/taxonomy_handler.e | 69 ++++++++++++++++-- .../persistence/cms_taxonomy_storage_i.e | 7 ++ .../persistence/cms_taxonomy_storage_null.e | 5 ++ .../persistence/cms_taxonomy_storage_sql.e | 38 ++++++++++ modules/taxonomy/taxonomy-safe.ecf | 1 + src/kernel/content/cms_content_block.e | 1 + src/service/cms_api.e | 34 +++++++++ src/service/content/cms_content.e | 66 +++++++++++++++++ .../service/content}/cms_content_type.e | 0 src/service/content/cms_partial_content.e | 73 +++++++++++++++++++ 19 files changed, 319 insertions(+), 83 deletions(-) create mode 100644 src/service/content/cms_content.e rename {modules/node => src/service/content}/cms_content_type.e (100%) create mode 100644 src/service/content/cms_partial_content.e diff --git a/modules/blog/cms_blog_module.e b/modules/blog/cms_blog_module.e index ec38c1e..31786ca 100644 --- a/modules/blog/cms_blog_module.e +++ b/modules/blog/cms_blog_module.e @@ -65,7 +65,7 @@ feature {CMS_API} -- Module Initialization loop ct.extend_format (ic.item) end - l_node_api.add_content_type (ct) + l_node_api.add_node_type (ct) l_node_api.add_content_type_webform_manager (create {CMS_BLOG_NODE_TYPE_WEBFORM_MANAGER}.make (ct)) -- Add support for CMS_BLOG, which requires a storage extension to store the optional "tags" value diff --git a/modules/node/cms_node_api.e b/modules/node/cms_node_api.e index c77e926..02c0714 100644 --- a/modules/node/cms_node_api.e +++ b/modules/node/cms_node_api.e @@ -40,8 +40,7 @@ feature {NONE} -- Initialization local ct: CMS_PAGE_NODE_TYPE do - -- Initialize content types. - create content_types.make (1) + -- Initialize node content types. create content_type_webform_managers.make (1) create ct --| For now, add all available formats to content type `ct'. @@ -50,7 +49,7 @@ feature {NONE} -- Initialization loop ct.extend_format (ic.item) end - add_content_type (ct) + add_node_type (ct) add_content_type_webform_manager (create {CMS_PAGE_NODE_TYPE_WEBFORM_MANAGER}.make (ct)) end @@ -60,15 +59,18 @@ feature {CMS_MODULE} -- Access nodes storage. feature -- Content type - content_types: ARRAYED_LIST [CMS_CONTENT_TYPE] - -- Available content types + add_node_type (a_type: CMS_NODE_TYPE [CMS_NODE]) + -- Register node content type `a_type'. + do + cms_api.add_content_type (a_type) + end node_types: ARRAYED_LIST [attached like node_type] -- Node content types. do - create Result.make (content_types.count) + create Result.make (cms_api.content_types.count) across - content_types as ic + cms_api.content_types as ic loop if attached {like node_type} ic.item as l_node_type then Result.extend (l_node_type) @@ -76,32 +78,11 @@ feature -- Content type end end - add_content_type (a_type: CMS_CONTENT_TYPE) - -- Register content type `a_type'. - do - content_types.force (a_type) - end - - content_type (a_name: READABLE_STRING_GENERAL): detachable CMS_CONTENT_TYPE - -- Content type named `a_named' if any. - do - across - content_types as ic - until - Result /= Void - loop - Result := ic.item - if not a_name.is_case_insensitive_equal (Result.name) then - Result := Void - end - end - end - node_type (a_name: READABLE_STRING_GENERAL): detachable CMS_NODE_TYPE [CMS_NODE] -- Content type named `a_named' if any. do across - content_types as ic + cms_api.content_types as ic until Result /= Void loop diff --git a/modules/node/cms_node_module.e b/modules/node/cms_node_module.e index 0ea6f2d..f67a475 100644 --- a/modules/node/cms_node_module.e +++ b/modules/node/cms_node_module.e @@ -158,7 +158,7 @@ feature -- Access if attached node_api as l_node_api then across - l_node_api.content_types as ic + l_node_api.node_types as ic loop l_type_name := ic.item.name if not l_type_name.is_whitespace then @@ -285,7 +285,7 @@ feature -- Hooks create perms.make (2) perms.force ("create any node") across - l_node_api.content_types as ic + l_node_api.node_types as ic loop perms.force ("create " + ic.item.name) end @@ -300,7 +300,7 @@ feature -- Hooks do if attached node_api as l_node_api and then - attached l_node_api.content_types as l_types and then + attached l_node_api.node_types as l_types and then not l_types.is_empty then create lst.make (l_types.count) diff --git a/modules/node/content/cms_node.e b/modules/node/content/cms_node.e index 41ab55d..f7a755c 100644 --- a/modules/node/content/cms_node.e +++ b/modules/node/content/cms_node.e @@ -10,7 +10,11 @@ deferred class CMS_NODE inherit - DEBUG_OUTPUT + CMS_CONTENT + redefine + debug_output + end + REFACTORING_HELPER feature{NONE} -- Initialization @@ -67,12 +71,6 @@ feature -- Access -- Revision value. --| Note: for now version is not supported. - content_type: READABLE_STRING_8 - -- Associated content type name. - -- Page, Article, Blog, News, etc. - deferred - end - feature -- Status reports status: INTEGER @@ -113,12 +111,6 @@ feature -- Access deferred end - format: detachable READABLE_STRING_8 - -- Format associated with `content' and `summary'. - -- For example: text, mediawiki, html, etc - deferred - end - feature -- Access: date modification_date: DATE_TIME @@ -155,12 +147,6 @@ feature -- status report valid_result: Result implies a_node.id = id end - is_typed_as (a_content_type: READABLE_STRING_GENERAL): BOOLEAN - -- Is current node of type `a_content_type' ? - do - Result := a_content_type.is_case_insensitive_equal (content_type) - end - feature -- Access: menu link: detachable CMS_LOCAL_LINK @@ -174,13 +160,7 @@ feature -- Status report create Result.make_from_string_general ("#") Result.append_integer_64 (id) Result.append_character (' ') - Result.append_character ('<') - Result.append_string_general (content_type) - Result.append_character ('>') - Result.append_character (' ') - Result.append_character ('%"') - Result.append (title) - Result.append_character ('%"') + Result.append (Precursor) end feature -- Element change diff --git a/modules/node/handler/nodes_handler.e b/modules/node/handler/nodes_handler.e index 55d9be5..b129341 100644 --- a/modules/node/handler/nodes_handler.e +++ b/modules/node/handler/nodes_handler.e @@ -96,7 +96,7 @@ feature -- HTTP Methods s.append (" (trashed)") end debug - if attached node_api.content_type (n.content_type) as ct then + if attached node_api.node_type (n.content_type) as ct then s.append ("") s.append (html_encoded (ct.title)) s.append ("") diff --git a/modules/node/persistence/cms_node_storage_sql.e b/modules/node/persistence/cms_node_storage_sql.e index 897d5e5..3047652 100644 --- a/modules/node/persistence/cms_node_storage_sql.e +++ b/modules/node/persistence/cms_node_storage_sql.e @@ -383,7 +383,6 @@ feature -- Change: Node local l_parameters: STRING_TABLE [ANY] l_time: DATE_TIME - l_sql_delete_node_aliases: STRING do sql_begin_transaction create l_time.make_now_utc diff --git a/modules/node/persistence/cms_node_storage_sql_page_extension.e b/modules/node/persistence/cms_node_storage_sql_page_extension.e index abfe110..cd0dd5e 100644 --- a/modules/node/persistence/cms_node_storage_sql_page_extension.e +++ b/modules/node/persistence/cms_node_storage_sql_page_extension.e @@ -101,7 +101,7 @@ feature -- Persistence l_parent_id /= a_node.id and then attached node_storage.node_by_id (l_parent_id) as l_parent then - if attached {CMS_PAGE_NODE_TYPE} node_api.content_type (l_parent.content_type) as l_parent_ct then + if attached {CMS_PAGE_NODE_TYPE} node_api.node_type (l_parent.content_type) as l_parent_ct then ct := l_parent_ct else create ct diff --git a/modules/taxonomy/cms_taxonomy_api.e b/modules/taxonomy/cms_taxonomy_api.e index f0b3ea7..051239b 100644 --- a/modules/taxonomy/cms_taxonomy_api.e +++ b/modules/taxonomy/cms_taxonomy_api.e @@ -103,7 +103,7 @@ feature -- Access node Result := taxonomy_storage.terms (a_vocab, a_limit, a_offset) end - term_by_id (a_tid: INTEGER): detachable CMS_TERM + term_by_id (a_tid: INTEGER_64): detachable CMS_TERM do Result := taxonomy_storage.term_by_id (a_tid) end @@ -114,6 +114,14 @@ feature -- Access node Result := taxonomy_storage.term_by_text (a_term_text, a_vocabulary) end + entities_associated_with_term (a_term: CMS_TERM): detachable LIST [TUPLE [entity: READABLE_STRING_32; type: detachable READABLE_STRING_32]] + -- Entities and related typename associated with `a_term'. + require + a_term_exists: a_term.has_id + do + Result := taxonomy_storage.entities_associated_with_term (a_term) + end + feature -- Write save_vocabulary (a_voc: CMS_VOCABULARY) diff --git a/modules/taxonomy/cms_taxonomy_module.e b/modules/taxonomy/cms_taxonomy_module.e index 77a1249..4e0091b 100644 --- a/modules/taxonomy/cms_taxonomy_module.e +++ b/modules/taxonomy/cms_taxonomy_module.e @@ -35,7 +35,7 @@ feature {NONE} -- Initialization version := "1.0" description := "Taxonomy solution" package := "core" --- add_dependency ({CMS_NODE_MODULE}) +-- put_dependency ({CMS_NODE_MODULE}, False) end feature -- Access @@ -120,19 +120,9 @@ feature -- Access: router -- Configure router mapping for web interface. local l_taxonomy_handler: TAXONOMY_HANDLER - l_uri_mapping: WSF_URI_MAPPING do create l_taxonomy_handler.make (a_api, a_taxonomy_api) - -- Let the class BLOG_HANDLER handle the requests on "/taxonomys" - create l_uri_mapping.make_trailing_slash_ignored ("/taxonomy", l_taxonomy_handler) - a_router.map (l_uri_mapping, a_router.methods_get) - - -- We can add a page number after /taxonomys/ to get older posts - a_router.handle ("/taxonomy/{vocabulary}", l_taxonomy_handler, a_router.methods_get) - - -- If a user id is given route with taxonomy user handler - --| FIXME: maybe /user/{user}/taxonomys/ would be better. - a_router.handle ("/taxonomy/{vocabulary}/{termid}", l_taxonomy_handler, a_router.methods_get) + a_router.handle ("/taxonomy/term/{termid}", l_taxonomy_handler, a_router.methods_get) end feature -- Hooks diff --git a/modules/taxonomy/handler/taxonomy_handler.e b/modules/taxonomy/handler/taxonomy_handler.e index bef7d11..81b93e3 100644 --- a/modules/taxonomy/handler/taxonomy_handler.e +++ b/modules/taxonomy/handler/taxonomy_handler.e @@ -1,9 +1,7 @@ note description: "[ Request handler related to - /taxonomy - /taxonomy/{vocabulary} - /taxonomy/{vocabulary}/{term} + /taxonomy/term/{termid} ]" date: "$Date$" revision: "$revision$" @@ -69,13 +67,68 @@ feature -- HTTP Methods -- local l_page: CMS_RESPONSE + tid: INTEGER_64 + l_typename: detachable READABLE_STRING_8 + l_entity: detachable READABLE_STRING_32 + s: STRING do - -- Read page number from path parameter. + if + attached {WSF_STRING} req.path_parameter ("termid") as p_termid and then + p_termid.is_integer + then + tid := p_termid.value.to_integer_64 + end - -- Responding with `main_content_html (l_page)'. - create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api) - l_page.set_main_content ("Not Yet Implemented -- In Progress") - l_page.execute + if tid > 0 then + if attached taxonomy_api.term_by_id (tid) as t then + -- Responding with `main_content_html (l_page)'. + create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api) + create s.make_empty + l_page.set_page_title ("Entities associated with term %"" + l_page.html_encoded (t.text) + "%":") + + if + attached taxonomy_api.entities_associated_with_term (t) as l_entity_type_lst and then + not l_entity_type_lst.is_empty + then + s.append ("%N") + else + s.append ("No entity found.") + end + l_page.set_main_content (s) + else + -- Responding with `main_content_html (l_page)'. + create {NOT_FOUND_ERROR_CMS_RESPONSE} l_page.make (req, res, api) + end + l_page.execute + else + -- Responding with `main_content_html (l_page)'. + create {BAD_REQUEST_ERROR_CMS_RESPONSE} l_page.make (req, res, api) + l_page.execute + end end end diff --git a/modules/taxonomy/persistence/cms_taxonomy_storage_i.e b/modules/taxonomy/persistence/cms_taxonomy_storage_i.e index 559d0d7..b7fa34d 100644 --- a/modules/taxonomy/persistence/cms_taxonomy_storage_i.e +++ b/modules/taxonomy/persistence/cms_taxonomy_storage_i.e @@ -80,6 +80,13 @@ feature -- Access deferred end + entities_associated_with_term (a_term: CMS_TERM): detachable LIST [TUPLE [entity: READABLE_STRING_32; type: detachable READABLE_STRING_32]] + -- Entities and related typename associated with `a_term'. + require + a_term_exists: a_term.has_id + deferred + end + feature -- Store save_vocabulary (a_voc: CMS_VOCABULARY) diff --git a/modules/taxonomy/persistence/cms_taxonomy_storage_null.e b/modules/taxonomy/persistence/cms_taxonomy_storage_null.e index bd8f05d..0e9def6 100644 --- a/modules/taxonomy/persistence/cms_taxonomy_storage_null.e +++ b/modules/taxonomy/persistence/cms_taxonomy_storage_null.e @@ -78,6 +78,11 @@ feature -- Access do end + entities_associated_with_term (a_term: CMS_TERM): detachable LIST [TUPLE [entity: READABLE_STRING_32; type: detachable READABLE_STRING_32]] + -- Entities and related typename associated with `a_term'. + do + end + feature -- Store save_vocabulary (a_voc: CMS_VOCABULARY) diff --git a/modules/taxonomy/persistence/cms_taxonomy_storage_sql.e b/modules/taxonomy/persistence/cms_taxonomy_storage_sql.e index 5ed17dc..c71e73f 100644 --- a/modules/taxonomy/persistence/cms_taxonomy_storage_sql.e +++ b/modules/taxonomy/persistence/cms_taxonomy_storage_sql.e @@ -198,6 +198,38 @@ feature -- Access end end + entities_associated_with_term (a_term: CMS_TERM): detachable LIST [TUPLE [entity: READABLE_STRING_32; type: detachable READABLE_STRING_32]] + -- Entities and related typename associated with `a_term'. + local + l_parameters: STRING_TABLE [detachable ANY] + l_typename: detachable READABLE_STRING_32 + do + error_handler.reset + + create l_parameters.make (3) + l_parameters.put (a_term.id, "tid") + sql_query (sql_select_entity_and_type_by_term, l_parameters) + + if not has_error then + create {ARRAYED_LIST [TUPLE [entity: READABLE_STRING_32; type: detachable READABLE_STRING_32]]} Result.make (0) + from + sql_start + until + sql_after or has_error + loop + if attached sql_read_string_32 (1) as l_entity then + l_typename := sql_read_string_32 (2) + if l_typename /= Void and then l_typename.is_whitespace then + l_typename := Void + end + Result.force ([l_entity, l_typename]) + end + sql_forth + end + end + sql_finalize + end + feature -- Store save_vocabulary (voc: CMS_VOCABULARY) @@ -477,6 +509,12 @@ feature {NONE} -- Queries SELECT tid FROM taxonomy_index WHERE type=:type AND entity=:entity; ]" + sql_select_entity_and_type_by_term: STRING = "[ + SELECT entity, type FROM taxonomy_index WHERE tid=:tid AND entity > 0 + ORDER BY type ASC, entity ASC + ; + ]" + sql_select_vocabulary_terms_of_entity: STRING = "[ SELECT taxonomy_index.tid FROM taxonomy_index INNER JOIN taxonomy_hierarchy ON taxonomy_index.tid=taxonomy_hierarchy.tid diff --git a/modules/taxonomy/taxonomy-safe.ecf b/modules/taxonomy/taxonomy-safe.ecf index e4813e9..e3578e2 100644 --- a/modules/taxonomy/taxonomy-safe.ecf +++ b/modules/taxonomy/taxonomy-safe.ecf @@ -16,6 +16,7 @@ + diff --git a/src/kernel/content/cms_content_block.e b/src/kernel/content/cms_content_block.e index ffc975e..8eb62d0 100644 --- a/src/kernel/content/cms_content_block.e +++ b/src/kernel/content/cms_content_block.e @@ -83,6 +83,7 @@ feature -- Conversion Result := content 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)" diff --git a/src/service/cms_api.e b/src/service/cms_api.e index 8d1b450..4ef772c 100644 --- a/src/service/cms_api.e +++ b/src/service/cms_api.e @@ -43,6 +43,8 @@ feature {NONE} -- Initialize do -- Initialize formats. initialize_formats + -- Initialize contents. + initialize_content_types -- Initialize storage. if attached setup.storage (error_handler) as l_storage then @@ -88,6 +90,12 @@ feature {NONE} -- Initialize end end + initialize_content_types + -- Initialize content types. + do + create content_types.make (1) + end + initialize_formats -- Initialize content formats. local @@ -156,6 +164,32 @@ feature -- Access storage: CMS_STORAGE -- Default persistence storage. +feature -- Content + + content_types: ARRAYED_LIST [CMS_CONTENT_TYPE] + -- Available content types + + add_content_type (a_type: CMS_CONTENT_TYPE) + -- Register content type `a_type'. + do + content_types.force (a_type) + end + + content_type (a_name: READABLE_STRING_GENERAL): detachable CMS_CONTENT_TYPE + -- Content type named `a_named' if any. + do + across + content_types as ic + until + Result /= Void + loop + Result := ic.item + if not a_name.is_case_insensitive_equal (Result.name) then + Result := Void + end + end + end + feature -- Formats formats: CMS_FORMATS diff --git a/src/service/content/cms_content.e b/src/service/content/cms_content.e new file mode 100644 index 0000000..e6c9444 --- /dev/null +++ b/src/service/content/cms_content.e @@ -0,0 +1,66 @@ +note + description: "[ + Abstract of entity managed by CMS. + ]" + date: "$Date$" + revision: "$Revision$" + +deferred class + CMS_CONTENT + +inherit + DEBUG_OUTPUT + +feature -- Access + + title: detachable READABLE_STRING_32 + -- Title associated with Current content. + deferred + end + + content_type: READABLE_STRING_8 + -- Associated content type name. + -- Page, Article, Blog, News, etc. + deferred + end + + format: detachable READABLE_STRING_8 + -- Format associated with `content' and `summary'. + -- For example: text, mediawiki, html, etc + deferred + end + + link: detachable CMS_LOCAL_LINK + -- Associated menu link. + deferred + end + +feature -- Status report + + is_typed_as (a_content_type: READABLE_STRING_GENERAL): BOOLEAN + -- Is current node of type `a_content_type' ? + do + Result := a_content_type.is_case_insensitive_equal (content_type) + end + +feature -- Status report + + debug_output: STRING_32 + -- + do + create Result.make_empty + Result.append_character ('<') + Result.append_string_general (content_type) + Result.append_character ('>') + if attached title as l_title then + Result.append_character (' ') + Result.append_character ('%"') + Result.append (l_title) + Result.append_character ('%"') + 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/modules/node/cms_content_type.e b/src/service/content/cms_content_type.e similarity index 100% rename from modules/node/cms_content_type.e rename to src/service/content/cms_content_type.e diff --git a/src/service/content/cms_partial_content.e b/src/service/content/cms_partial_content.e new file mode 100644 index 0000000..8b114b0 --- /dev/null +++ b/src/service/content/cms_partial_content.e @@ -0,0 +1,73 @@ +note + description: "[ + Instance of CMS_CONTENT representing the minimal information + for a CMS_CONTENT. + ]" + date: "$Date$" + revision: "$Revision$" + +class + CMS_PARTIAL_CONTENT + +inherit + CMS_CONTENT + +create + make_empty + +feature {NONE} -- Initialization + + make_empty (a_content_type: READABLE_STRING_8) + require + type_not_blank: not a_content_type.is_whitespace + do + content_type := a_content_type + end + +feature -- Access + + title: detachable READABLE_STRING_32 + -- Title associated with Current content. + + content_type: READABLE_STRING_8 + -- Associated content type name. + -- Page, Article, Blog, News, etc. + + format: detachable READABLE_STRING_8 + -- Format associated with `content' and `summary'. + -- For example: text, mediawiki, html, etc + + link: detachable CMS_LOCAL_LINK + -- Associated menu link. + +feature -- Element change + + set_title (a_title: detachable READABLE_STRING_GENERAL) + do + if a_title = Void then + title := Void + else + create {STRING_32} title.make_from_string_general (a_title) + end + end + + set_format (a_format: like format) + -- Assign `format' with `a_format'. + do + format := a_format + ensure + format_assigned: format = a_format + end + + set_link (a_link: like link) + -- Assign `link' with `a_link'. + do + link := a_link + ensure + link_assigned: link = a_link + 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