diff --git a/examples/demo/demo-safe.ecf b/examples/demo/demo-safe.ecf
index d1cf5a9..b8c67db 100644
--- a/examples/demo/demo-safe.ecf
+++ b/examples/demo/demo-safe.ecf
@@ -29,16 +29,16 @@
+
-
-
+
diff --git a/examples/demo/src/demo_cms_execution.e b/examples/demo/src/demo_cms_execution.e
index bf3e1ae..a3286d9 100644
--- a/examples/demo/src/demo_cms_execution.e
+++ b/examples/demo/src/demo_cms_execution.e
@@ -66,6 +66,10 @@ feature -- CMS modules
a_setup.register_module (m)
create {CMS_BLOG_MODULE} m.make
+ a_setup.register_module (m)
+
+ -- Taxonomy
+ create {CMS_TAXONOMY_MODULE} m.make
a_setup.register_module (m)
-- Recent changes
diff --git a/modules/taxonomy/cms_taxonomy_api.e b/modules/taxonomy/cms_taxonomy_api.e
new file mode 100644
index 0000000..578f589
--- /dev/null
+++ b/modules/taxonomy/cms_taxonomy_api.e
@@ -0,0 +1,84 @@
+note
+ description: "[
+ API to handle taxonomy vocabularies and terms.
+ ]"
+ date: "$Date$"
+ revision: "$Revision$"
+
+class
+ CMS_TAXONOMY_API
+
+inherit
+ CMS_MODULE_API
+ redefine
+ initialize
+ end
+
+ REFACTORING_HELPER
+
+create
+ make
+
+feature {NONE} -- Initialization
+
+ initialize
+ --
+ do
+ Precursor
+
+ -- Create the node storage for type blog
+ if attached {CMS_STORAGE_SQL_I} storage as l_storage_sql then
+ create {CMS_TAXONOMY_STORAGE_SQL} taxonomy_storage.make (l_storage_sql)
+ else
+ create {CMS_TAXONOMY_STORAGE_NULL} taxonomy_storage.make
+ end
+ end
+
+feature {CMS_MODULE} -- Access nodes storage.
+
+ taxonomy_storage: CMS_TAXONOMY_STORAGE_I
+
+feature -- Access node
+
+ vocabulary_count: INTEGER_64
+ -- Number of vocabulary.
+ do
+ Result := taxonomy_storage.vocabulary_count
+ end
+
+ vocabularies (a_limit: NATURAL_32; a_offset: NATURAL_32): LIST [CMS_VOCABULARY]
+ -- List of vocabularies ordered by weight and limited by limit and offset.
+ do
+ Result := taxonomy_storage.vocabularies (a_limit, a_offset)
+ end
+
+ vocabulary (a_id: INTEGER): detachable CMS_VOCABULARY
+ -- Vocabulary associated with id `a_id'.
+ require
+ valid_id: a_id > 0
+ do
+ Result := taxonomy_storage.vocabulary (a_id)
+ end
+
+ term_count_from_vocabulary (a_vocab: CMS_VOCABULARY): INTEGER_64
+ -- Number of terms from vocabulary `a_vocab'.
+ require
+ has_id: a_vocab.has_id
+ do
+ Result := taxonomy_storage.term_count_from_vocabulary (a_vocab)
+ end
+
+ terms (a_vocab: CMS_VOCABULARY; a_limit: NATURAL_32; a_offset: NATURAL_32): LIST [CMS_TERM]
+ -- List of terms ordered by weight and limited by limit and offset.
+ require
+ has_id: a_vocab.has_id
+ do
+ Result := taxonomy_storage.terms (a_vocab, a_limit, a_offset)
+ end
+
+ term_by_id (a_tid: INTEGER): detachable CMS_TERM
+ do
+ Result := taxonomy_storage.term_by_id (a_tid)
+ end
+
+end
diff --git a/modules/taxonomy/cms_taxonomy_module.e b/modules/taxonomy/cms_taxonomy_module.e
new file mode 100644
index 0000000..ace013b
--- /dev/null
+++ b/modules/taxonomy/cms_taxonomy_module.e
@@ -0,0 +1,161 @@
+note
+ description: "[
+ Taxonomy module managing vocabularies and terms.
+ ]"
+ date: "$Date: 2015-05-22 15:13:00 +0100 (lun., 18 mai 2015) $"
+ revision: "$Revision 96616$"
+
+class
+ CMS_TAXONOMY_MODULE
+
+inherit
+ CMS_MODULE
+ rename
+ module_api as taxonomy_api
+ redefine
+ register_hooks,
+ initialize,
+ install,
+ uninstall,
+ taxonomy_api
+ end
+
+ CMS_HOOK_MENU_SYSTEM_ALTER
+
+ CMS_HOOK_RESPONSE_ALTER
+
+create
+ make
+
+feature {NONE} -- Initialization
+
+ make
+ do
+ version := "1.0"
+ description := "Taxonomy solution"
+ package := "core"
+-- add_dependency ({CMS_NODE_MODULE})
+ end
+
+feature -- Access
+
+ name: STRING = "taxonomy"
+
+feature {CMS_API} -- Module Initialization
+
+ initialize (api: CMS_API)
+ --
+ do
+ Precursor (api)
+ create taxonomy_api.make (api)
+ end
+
+feature {CMS_API} -- Module management
+
+ install (api: CMS_API)
+ local
+ sql: STRING
+ do
+ -- Schema
+ if attached {CMS_STORAGE_SQL_I} api.storage as l_sql_storage then
+ if not l_sql_storage.sql_table_exists ("taxonomy_term") then
+ sql := "[
+CREATE TABLE taxonomy_term (
+ `tid` INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT UNIQUE,
+ `text` VARCHAR(255) NOT NULL,
+ `weight` INTEGER,
+ `description` TEXT,
+ `langcode` VARCHAR(12)
+);
+CREATE TABLE taxonomy_hierarchy (
+ `tid` INTEGER NOT NULL,
+ `parent` INTEGER,
+ CONSTRAINT PK_tid_parent PRIMARY KEY (tid,parent)
+);
+ ]"
+ l_sql_storage.sql_execute_script (sql, Void)
+ if l_sql_storage.has_error then
+ api.logger.put_error ("Could not initialize database for taxonomy module", generating_type)
+ end
+ end
+ Precursor (api)
+ end
+ end
+
+ uninstall (api: CMS_API)
+ -- (export status {CMS_API})
+ local
+ sql: STRING
+ do
+ if attached {CMS_STORAGE_SQL_I} api.storage as l_sql_storage then
+ sql := "[
+DROP TABLE IF EXISTS taxonomy_term;
+DROP TABLE IF EXISTS taxonomy_hierarchy;
+ ]"
+ l_sql_storage.sql_execute_script (sql, Void)
+ if l_sql_storage.has_error then
+ api.logger.put_error ("Could not remove database for taxonomy module", generating_type)
+ end
+ end
+ Precursor (api)
+ end
+
+feature {CMS_API} -- Access: API
+
+ taxonomy_api: detachable CMS_TAXONOMY_API
+ --
+
+feature -- Access: router
+
+ setup_router (a_router: WSF_ROUTER; a_api: CMS_API)
+ --
+ do
+ if attached taxonomy_api as l_taxonomy_api then
+ configure_web (a_api, l_taxonomy_api, a_router)
+ else
+ -- Issue with api/dependencies,
+ -- thus Current module should not be used!
+ -- thus no url mapping
+ end
+ end
+
+ configure_web (a_api: CMS_API; a_taxonomy_api: CMS_TAXONOMY_API; a_router: WSF_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)
+ end
+
+feature -- Hooks
+
+ register_hooks (a_response: CMS_RESPONSE)
+ do
+ a_response.hooks.subscribe_to_menu_system_alter_hook (Current)
+ a_response.hooks.subscribe_to_response_alter_hook (Current)
+ end
+
+ response_alter (a_response: CMS_RESPONSE)
+ do
+ a_response.add_style (a_response.url ("/module/" + name + "/files/css/taxonomy.css", Void), Void)
+ end
+
+ menu_system_alter (a_menu_system: CMS_MENU_SYSTEM; a_response: CMS_RESPONSE)
+ do
+ -- Add the link to the taxonomy to the main menu
+-- create lnk.make ("Taxonomy", "taxonomy/")
+-- a_menu_system.primary_menu.extend (lnk)
+ end
+
+end
diff --git a/modules/taxonomy/cms_term.e b/modules/taxonomy/cms_term.e
new file mode 100644
index 0000000..659f869
--- /dev/null
+++ b/modules/taxonomy/cms_term.e
@@ -0,0 +1,99 @@
+note
+ description: "[
+ Taxonomy vocabulary term.
+ ]"
+ date: "$Date$"
+ revision: "$Revision$"
+
+class
+ CMS_TERM
+
+inherit
+ COMPARABLE
+
+create
+ make
+
+feature {NONE} -- Initialization
+
+ make (a_id: INTEGER; a_text: READABLE_STRING_GENERAL)
+ do
+ id := a_id
+ set_text (a_text)
+ end
+
+feature -- Access
+
+ id: INTEGER
+ -- Associated term id.
+
+ text: IMMUTABLE_STRING_32
+ -- Text for the term.
+
+ description: detachable IMMUTABLE_STRING_32
+ -- Optional description.
+
+ parent_id: INTEGER
+ -- Optional parent term id.
+
+ weight: INTEGER
+ -- Associated weight for ordering.
+
+feature -- Status report
+
+ has_id: BOOLEAN
+ -- Has valid id?
+ do
+ Result := id > 0
+ end
+
+feature -- Comparison
+
+ is_less alias "<" (other: like Current): BOOLEAN
+ -- Is current object less than `other'?
+ do
+ if weight = other.weight then
+ if text.same_string (other.text) then
+ Result := id < other.id
+ else
+ Result := text < other.text
+ end
+ else
+ Result := weight < other.weight
+ end
+ end
+
+feature -- Element change
+
+ set_id (a_id: INTEGER)
+ do
+ id := a_id
+ end
+
+ set_text (a_text: READABLE_STRING_GENERAL)
+ do
+ create text.make_from_string_general (a_text)
+ end
+
+ set_weight (w: like weight)
+ do
+ weight := w
+ end
+
+ set_description (a_description: READABLE_STRING_GENERAL)
+ do
+ create description.make_from_string_general (a_description)
+ end
+
+ set_parent (a_parent: CMS_TERM)
+ do
+ parent_id := a_parent.id
+ end
+
+ set_parent_id (a_parent_id: INTEGER)
+ do
+ parent_id := a_parent_id
+ end
+
+end
+
diff --git a/modules/taxonomy/cms_vocabulary.e b/modules/taxonomy/cms_vocabulary.e
new file mode 100644
index 0000000..e9cb979
--- /dev/null
+++ b/modules/taxonomy/cms_vocabulary.e
@@ -0,0 +1,63 @@
+note
+ description: "[
+ Taxonomy vocabulary.
+ ]"
+ date: "$Date$"
+ revision: "$Revision$"
+
+class
+ CMS_VOCABULARY
+
+create
+ make,
+ make_from_term
+
+feature {NONE} -- Initialization
+
+ make (a_tid: INTEGER; a_name: READABLE_STRING_GENERAL)
+ do
+ id := a_tid
+ set_name (a_name)
+ create {ARRAYED_LIST [CMS_TERM]} items.make (0)
+ end
+
+ make_from_term (a_term: CMS_TERM)
+ do
+ make (a_term.id, a_term.text)
+ description := a_term.description
+ end
+
+feature -- Access
+
+ id: INTEGER
+
+ name: IMMUTABLE_STRING_32
+
+ description: detachable READABLE_STRING_32
+
+ items: LIST [CMS_TERM]
+ -- Collection of terms.
+
+ has_id: BOOLEAN
+ do
+ Result := id > 0
+ end
+
+feature -- Element change
+
+ set_name (a_name: READABLE_STRING_GENERAL)
+ do
+ create name.make_from_string_general (a_name)
+ end
+
+ sort
+ -- Sort `items'
+ local
+ l_sorter: QUICK_SORTER [CMS_TERM]
+ do
+ create l_sorter.make (create {COMPARABLE_COMPARATOR [CMS_TERM]})
+ l_sorter.sort (items)
+ end
+
+end
+
diff --git a/modules/taxonomy/handler/taxonomy_handler.e b/modules/taxonomy/handler/taxonomy_handler.e
new file mode 100644
index 0000000..bef7d11
--- /dev/null
+++ b/modules/taxonomy/handler/taxonomy_handler.e
@@ -0,0 +1,81 @@
+note
+ description: "[
+ Request handler related to
+ /taxonomy
+ /taxonomy/{vocabulary}
+ /taxonomy/{vocabulary}/{term}
+ ]"
+ date: "$Date$"
+ revision: "$revision$"
+
+class
+ TAXONOMY_HANDLER
+
+inherit
+ CMS_MODULE_HANDLER [CMS_TAXONOMY_API]
+ rename
+ module_api as taxonomy_api
+ end
+
+ WSF_URI_HANDLER
+ rename
+ execute as uri_execute,
+ new_mapping as new_uri_mapping
+ end
+
+ WSF_URI_TEMPLATE_HANDLER
+ rename
+ execute as uri_template_execute,
+ new_mapping as new_uri_template_mapping
+ select
+ new_uri_template_mapping
+ end
+
+ WSF_RESOURCE_HANDLER_HELPER
+ redefine
+ do_get
+ end
+
+ REFACTORING_HELPER
+
+ CMS_API_ACCESS
+
+create
+ make
+
+feature -- execute
+
+ execute (req: WSF_REQUEST; res: WSF_RESPONSE)
+ -- Execute request handler for any kind of mapping.
+ do
+ execute_methods (req, res)
+ end
+
+ uri_execute (req: WSF_REQUEST; res: WSF_RESPONSE)
+ -- Execute request handler for URI mapping.
+ do
+ execute (req, res)
+ end
+
+ uri_template_execute (req: WSF_REQUEST; res: WSF_RESPONSE)
+ -- Execute request handler for URI-template mapping.
+ do
+ execute (req, res)
+ end
+
+feature -- HTTP Methods
+
+ do_get (req: WSF_REQUEST; res: WSF_RESPONSE)
+ --
+ local
+ l_page: CMS_RESPONSE
+ do
+ -- Read page number from path parameter.
+
+ -- 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
+ end
+
+end
diff --git a/modules/taxonomy/persistence/cms_taxonomy_storage_i.e b/modules/taxonomy/persistence/cms_taxonomy_storage_i.e
new file mode 100644
index 0000000..cc3e6ef
--- /dev/null
+++ b/modules/taxonomy/persistence/cms_taxonomy_storage_i.e
@@ -0,0 +1,64 @@
+note
+ description: "[
+ Interface for accessing taxonomy data from storage.
+ ]"
+ date: "$Date$"
+ revision: "$Revision$"
+
+deferred class
+ CMS_TAXONOMY_STORAGE_I
+
+feature -- Error Handling
+
+ error_handler: ERROR_HANDLER
+ -- Error handler.
+ deferred
+ end
+
+feature -- Access
+
+ vocabulary_count: INTEGER_64
+ -- Count of vocabularies.
+ deferred
+ end
+
+ vocabularies (limit: NATURAL_32; offset: NATURAL_32): LIST [CMS_VOCABULARY]
+ -- List of vocabularies ordered by weight from offset to offset + limit.
+ deferred
+ end
+
+ vocabulary (a_id: INTEGER): detachable CMS_VOCABULARY
+ -- Vocabulary by id `a_id'.
+ require
+ valid_id: a_id > 0
+ deferred
+ end
+
+ terms_count: INTEGER_64
+ -- Number of terms.
+ deferred
+ end
+
+ term_by_id (tid: INTEGER): detachable CMS_TERM
+ -- Term associated with id `tid'.
+ deferred
+ ensure
+ Result /= Void implies Result.id = tid
+ end
+
+ term_count_from_vocabulary (a_vocab: CMS_VOCABULARY): INTEGER_64
+ -- Number of terms from vocabulary `a_vocab'.
+ require
+ has_id: a_vocab.has_id
+ deferred
+ end
+
+ terms (a_vocab: CMS_VOCABULARY; limit: NATURAL_32; offset: NATURAL_32): LIST [CMS_TERM]
+ -- List of terms from vocabulary `a_vocab' ordered by weight from offset to offset + limit.
+ require
+ has_id: a_vocab.has_id
+ deferred
+ end
+
+
+end
diff --git a/modules/taxonomy/persistence/cms_taxonomy_storage_null.e b/modules/taxonomy/persistence/cms_taxonomy_storage_null.e
new file mode 100644
index 0000000..5795d4a
--- /dev/null
+++ b/modules/taxonomy/persistence/cms_taxonomy_storage_null.e
@@ -0,0 +1,67 @@
+note
+ description: "Summary description for {CMS_TAXONOMY_STORAGE_NULL}."
+ date: "$Date$"
+ revision: "$Revision$"
+
+class
+ CMS_TAXONOMY_STORAGE_NULL
+
+inherit
+ CMS_TAXONOMY_STORAGE_I
+
+create
+ make
+
+feature {NONE} -- Initialization
+
+ make
+ -- Initialize `Current'.
+ do
+ create error_handler.make
+ end
+
+feature -- Error Handling
+
+ error_handler: ERROR_HANDLER
+ -- Error handler.
+
+feature -- Access
+
+ vocabulary_count: INTEGER_64
+ -- Count of vocabularies.
+ do
+ end
+
+ term_count_from_vocabulary (a_vocab: CMS_VOCABULARY): INTEGER_64
+ -- Number of terms from vocabulary `a_vocab'.
+ do
+ end
+
+ vocabularies (limit: NATURAL_32; offset: NATURAL_32): LIST [CMS_VOCABULARY]
+ -- List of vocabularies ordered by weight from offset to offset + limit.
+ do
+ create {ARRAYED_LIST [CMS_VOCABULARY]} Result.make (0)
+ end
+
+ vocabulary (a_id: INTEGER): detachable CMS_VOCABULARY
+ -- Vocabulary by id `a_id'.
+ do
+ end
+
+ terms_count: INTEGER_64
+ -- Number of terms.
+ do
+ end
+
+ term_by_id (tid: INTEGER): detachable CMS_TERM
+ -- Term associated with id `tid'.
+ do
+ end
+
+ terms (a_vocab: CMS_VOCABULARY; limit: NATURAL_32; offset: NATURAL_32): LIST [CMS_TERM]
+ -- List of terms from vocabulary `a_vocab' ordered by weight from offset to offset + limit.
+ do
+ create {ARRAYED_LIST [CMS_TERM]} Result.make (0)
+ end
+
+end
diff --git a/modules/taxonomy/persistence/cms_taxonomy_storage_sql.e b/modules/taxonomy/persistence/cms_taxonomy_storage_sql.e
new file mode 100644
index 0000000..da06ddf
--- /dev/null
+++ b/modules/taxonomy/persistence/cms_taxonomy_storage_sql.e
@@ -0,0 +1,273 @@
+note
+ description: "[
+ Implementation of taxonomy storage using a SQL database.
+ ]"
+ date: "$Date$"
+ revision: "$Revision$"
+
+class
+ CMS_TAXONOMY_STORAGE_SQL
+
+inherit
+ CMS_TAXONOMY_STORAGE_I
+
+ CMS_PROXY_STORAGE_SQL
+
+create
+ make
+
+feature -- Access
+
+ vocabulary_count: INTEGER_64
+ -- Count of vocabularies.
+ do
+ error_handler.reset
+ sql_query (sql_select_vocabularies_count, Void)
+ if not has_error and not sql_after then
+ Result := sql_read_integer_64 (1)
+ end
+ sql_finalize
+ end
+
+ vocabularies (limit: NATURAL_32; offset: NATURAL_32): LIST [CMS_VOCABULARY]
+ -- List of vocabularies ordered by weight from offset to offset + limit.
+ do
+ create {ARRAYED_LIST [CMS_VOCABULARY]} Result.make (0)
+ end
+
+ vocabulary (a_tid: INTEGER): detachable CMS_VOCABULARY
+ -- Vocabulary by id `a_tid'.
+ do
+ if attached term_by_id (a_tid) as t then
+ create Result.make_from_term (t)
+ end
+ end
+
+ term_count_from_vocabulary (a_vocab: CMS_VOCABULARY): INTEGER_64
+ -- Number of terms from vocabulary `a_vocab'.
+ local
+ l_parameters: STRING_TABLE [detachable ANY]
+ do
+ error_handler.reset
+ create l_parameters.make (1)
+ l_parameters.put (a_vocab.id, "parent_tid")
+ sql_query (sql_select_vocabulary_terms_count, Void)
+ if not has_error and not sql_after then
+ Result := sql_read_integer_64 (1)
+ end
+ sql_finalize
+ end
+
+ terms (a_vocab: CMS_VOCABULARY; limit: NATURAL_32; offset: NATURAL_32): LIST [CMS_TERM]
+ -- List of terms from vocabulary `a_vocab' ordered by weight from offset to offset + limit.
+ local
+ l_parameters: STRING_TABLE [detachable ANY]
+ do
+ create {ARRAYED_LIST [CMS_TERM]} Result.make (0)
+ error_handler.reset
+
+ create l_parameters.make (1)
+ l_parameters.put (a_vocab.id, "parent_tid")
+ from
+ sql_query (sql_select_terms, l_parameters)
+ sql_start
+ until
+ sql_after
+ loop
+ if attached fetch_term as l_term then
+ Result.force (l_term)
+ end
+ sql_forth
+ end
+ sql_finalize
+ end
+
+ terms_count: INTEGER_64
+ -- Number of terms.
+ do
+ error_handler.reset
+ sql_query (sql_select_terms_count, Void)
+ if not has_error and not sql_after then
+ Result := sql_read_integer_64 (1)
+ end
+ sql_finalize
+ end
+
+ term_by_id (a_tid: INTEGER): detachable CMS_TERM
+ local
+ l_parameters: STRING_TABLE [detachable ANY]
+ do
+ error_handler.reset
+
+ create l_parameters.make (1)
+ l_parameters.put (a_tid, "tid")
+ sql_query (sql_select_term, l_parameters)
+ sql_start
+ if not has_error and not sql_after then
+ Result := fetch_term
+ end
+ sql_finalize
+ end
+
+feature -- Store
+
+ save_term (t: CMS_TERM)
+ do
+ end
+
+-- blogs_count: INTEGER_64
+-- --
+-- do
+-- error_handler.reset
+-- write_information_log (generator + ".blogs_count")
+-- sql_query (sql_select_blog_count, Void)
+-- if not has_error and not sql_after then
+-- Result := sql_read_integer_64 (1)
+-- end
+-- sql_finalize
+-- end
+
+-- blogs_count_from_user (a_user: CMS_USER) : INTEGER_64
+-- --
+-- local
+-- l_parameters: STRING_TABLE [detachable ANY]
+-- do
+-- error_handler.reset
+-- write_information_log (generator + ".blogs_count_from_user")
+-- create l_parameters.make (2)
+-- l_parameters.put (a_user.id, "user")
+-- sql_query (sql_select_blog_count_from_user, l_parameters)
+-- if not has_error and not sql_after then
+-- Result := sql_read_integer_64 (1)
+-- end
+-- sql_finalize
+-- end
+
+-- blogs: LIST [CMS_NODE]
+-- --
+-- do
+-- create {ARRAYED_LIST [CMS_NODE]} Result.make (0)
+
+-- error_handler.reset
+-- write_information_log (generator + ".blogs")
+
+-- from
+-- sql_query (sql_select_blogs_order_created_desc, Void)
+-- 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
+
+-- blogs_limited (a_limit: NATURAL_32; a_offset: NATURAL_32): LIST [CMS_NODE]
+-- --
+-- local
+-- l_parameters: STRING_TABLE [detachable ANY]
+-- do
+-- create {ARRAYED_LIST [CMS_NODE]} Result.make (0)
+
+-- error_handler.reset
+-- write_information_log (generator + ".blogs_limited")
+
+-- from
+-- create l_parameters.make (2)
+-- l_parameters.put (a_limit, "limit")
+-- l_parameters.put (a_offset, "offset")
+-- sql_query (sql_blogs_limited, 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
+
+-- blogs_from_user_limited (a_user: CMS_USER; a_limit: NATURAL_32; a_offset: NATURAL_32): LIST [CMS_NODE]
+-- --
+-- local
+-- l_parameters: STRING_TABLE [detachable ANY]
+-- do
+-- create {ARRAYED_LIST [CMS_NODE]} Result.make (0)
+
+-- error_handler.reset
+-- write_information_log (generator + ".blogs_from_user_limited")
+
+-- from
+-- create l_parameters.make (2)
+-- l_parameters.put (a_limit, "limit")
+-- l_parameters.put (a_offset, "offset")
+-- l_parameters.put (a_user.id, "user")
+-- sql_query (sql_blogs_from_user_limited, 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
+
+feature {NONE} -- Queries
+
+ fetch_term: detachable CMS_TERM
+ local
+ tid: INTEGER
+ l_text: detachable READABLE_STRING_32
+ do
+ tid := sql_read_integer_32 (1)
+ l_text := sql_read_string_32 (2)
+ if tid > 0 and l_text /= Void then
+ create Result.make (tid, l_text)
+ Result.set_weight (sql_read_integer_32 (3))
+ if attached sql_read_string_32 (4) as l_desc then
+ Result.set_description (l_desc)
+ end
+ end
+ end
+
+ sql_select_terms_count: STRING = "SELECT count(*) FROM taxonomy_term ;"
+ -- Number of terms.
+
+ sql_select_vocabularies_count: STRING = "SELECT count(*) FROM taxonomy_term INNER JOIN taxonomy_hierarchy ON taxonomy_term.tid = taxonomy_hierarchy.tid WHERE taxonomy_hierarchy.parent = 0;"
+ -- Number of terms without parent.
+
+ sql_select_vocabulary_terms_count: STRING = "SELECT count(*) FROM taxonomy_term INNER JOIN taxonomy_hierarchy ON taxonomy_term.tid = taxonomy_hierarchy.tid WHERE taxonomy_hierarchy.parent = :parent_tid;"
+ -- Number of terms under :parent_tid.
+
+ sql_select_vocabularies: STRING = "SELECT taxonomy_term.tid, taxonomy_term.text, taxonomy_term.weight, taxonomy_term.description FROM taxonomy_term INNER JOIN taxonomy_hierarchy ON taxonomy_term.tid = taxonomy_hierarchy.tid WHERE taxonomy_hierarchy.parent = 0;"
+ -- Terms without parent.
+
+ sql_select_terms: STRING = "SELECT taxonomy_term.tid, taxonomy_term.text, taxonomy_term.weight, taxonomy_term.description FROM taxonomy_term INNER JOIN taxonomy_hierarchy ON taxonomy_term.tid = taxonomy_hierarchy.tid WHERE taxonomy_hierarchy.parent = :parent_tid;"
+ -- Terms under :parent_tid.
+
+ sql_select_term: STRING = "SELECT tid, text, weight, description FROM taxonomy_term WHERE tid = :tid;"
+ -- Term with tid :tid .
+
+-- sql_select_blog_count_from_user: STRING = "SELECT count(*) FROM nodes WHERE status != -1 AND type = %"blog%" AND author = :user ;"
+-- -- Nodes count (Published and not Published)
+-- --| note: {CMS_NODE_API}.trashed = -1
+
+-- sql_select_blogs_order_created_desc: STRING = "SELECT * FROM nodes WHERE status != -1 AND type = %"blog%" ORDER BY created DESC;"
+-- -- SQL Query to retrieve all nodes that are from the type "blog" ordered by descending creation date.
+
+-- sql_blogs_limited: STRING = "SELECT * FROM nodes WHERE status != -1 AND type = %"blog%" ORDER BY created DESC LIMIT :limit OFFSET :offset ;"
+-- --- SQL Query to retrieve all node of type "blog" limited by limit and starting at offset
+
+-- sql_blogs_from_user_limited: STRING = "SELECT * FROM nodes WHERE status != -1 AND type = %"blog%" AND author = :user ORDER BY created DESC LIMIT :limit OFFSET :offset ;"
+-- --- SQL Query to retrieve all node of type "blog" from author with id limited by limit + offset
+
+
+end
diff --git a/modules/taxonomy/site/files/scss/taxonomy.scss b/modules/taxonomy/site/files/scss/taxonomy.scss
new file mode 100644
index 0000000..e69de29
diff --git a/modules/taxonomy/taxonomy-safe.ecf b/modules/taxonomy/taxonomy-safe.ecf
new file mode 100644
index 0000000..e4813e9
--- /dev/null
+++ b/modules/taxonomy/taxonomy-safe.ecf
@@ -0,0 +1,26 @@
+
+
+
+
+
+ /.git$
+ /EIFGENs$
+ /.svn$
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+