Improved taxonomy by supporting tags, multiple terms allowed, and required kind of vocabulary for specific content type.

Updated node web form, to support taxonomy editing if allowed (specific support for CMS_VOCABULARY.is_tags: BOOLEAN).
Added notion of required or optional module dependencies.
This commit is contained in:
2015-12-03 19:24:58 +01:00
parent f1f3c126dd
commit 20dfce1396
27 changed files with 1339 additions and 84 deletions

View File

@@ -29,10 +29,28 @@ feature -- Access
sql_finalize
end
vocabularies (limit: NATURAL_32; offset: NATURAL_32): LIST [CMS_VOCABULARY]
-- List of vocabularies ordered by weight from offset to offset + limit.
vocabularies (a_limit: NATURAL_32; a_offset: NATURAL_32): CMS_VOCABULARY_COLLECTION
-- List of vocabularies ordered by weight from `a_offset' to `a_offset + a_limit'.
local
l_parameters: STRING_TABLE [detachable ANY]
do
create {ARRAYED_LIST [CMS_VOCABULARY]} Result.make (0)
create Result.make (0)
error_handler.reset
create l_parameters.make (3)
l_parameters.put (0, "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 (create {CMS_VOCABULARY}.make_from_term (l_term))
end
sql_forth
end
sql_finalize
end
vocabulary (a_tid: INTEGER_64): detachable CMS_VOCABULARY
@@ -58,18 +76,21 @@ feature -- Access
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.
terms (a_vocab: CMS_VOCABULARY; a_limit: NATURAL_32; a_offset: NATURAL_32): CMS_TERM_COLLECTION
-- List of terms from vocabulary `a_vocab' ordered by weight from `a_offset' to `a_offset + a_limit'.
local
l_parameters: STRING_TABLE [detachable ANY]
do
create {ARRAYED_LIST [CMS_TERM]} Result.make (0)
create Result.make (0)
error_handler.reset
create l_parameters.make (1)
create l_parameters.make (3)
l_parameters.put (a_vocab.id, "parent_tid")
-- l_parameters.put (a_limit, "limit")
-- l_parameters.put (a_offset, "offset")
from
sql_query (sql_select_terms, l_parameters)
-- sql_query (sql_select_terms_with_range, l_parameters)
sql_start
until
sql_after
@@ -109,9 +130,89 @@ feature -- Access
sql_finalize
end
term_by_text (a_term_text: READABLE_STRING_GENERAL; a_vocabulary: detachable CMS_VOCABULARY): detachable CMS_TERM
local
l_parameters: STRING_TABLE [detachable ANY]
do
error_handler.reset
create l_parameters.make (1)
l_parameters.put (a_term_text, "text")
if a_vocabulary /= Void then
l_parameters.put (a_vocabulary.id, "parent_tid")
sql_query (sql_select_vocabulary_term_by_text, l_parameters)
else
sql_query (sql_select_term_by_text, l_parameters)
end
sql_start
if not has_error and not sql_after then
Result := fetch_term
end
sql_finalize
end
terms_of_entity (a_type_name: READABLE_STRING_GENERAL; a_entity: READABLE_STRING_GENERAL; a_vocabulary: detachable CMS_VOCABULARY): detachable CMS_TERM_COLLECTION
-- <Precursor>
local
l_parameters: STRING_TABLE [detachable ANY]
l_tids: ARRAYED_LIST [INTEGER_64]
tid: INTEGER_64
do
error_handler.reset
create l_parameters.make (3)
l_parameters.put (a_type_name, "type")
l_parameters.put (a_entity , "entity")
if a_vocabulary /= Void then
l_parameters.put (a_vocabulary.id , "parent_tid")
sql_query (sql_select_vocabulary_terms_of_entity, l_parameters)
else
sql_query (sql_select_terms_of_entity, l_parameters)
end
create l_tids.make (0)
from
sql_start
until
sql_after or has_error
loop
tid := sql_read_integer_64 (1)
if tid > 0 then
l_tids.force (tid)
end
sql_forth
end
sql_finalize
if not l_tids.is_empty then
create Result.make (l_tids.count)
across
l_tids as ic
loop
if
ic.item > 0 and then
attached term_by_id (ic.item) as t
then
Result.force (t)
end
end
end
end
feature -- Store
save_term (t: CMS_TERM)
save_vocabulary (voc: CMS_VOCABULARY)
do
save_term (voc, create {CMS_VOCABULARY}.make_none)
across
voc.terms as ic
until
has_error
loop
save_term (ic.item, voc)
end
end
save_term (t: CMS_TERM; voc: CMS_VOCABULARY)
local
l_parameters: STRING_TABLE [detachable ANY]
do
@@ -130,6 +231,11 @@ feature -- Store
sql_insert (sql_insert_term, l_parameters)
t.set_id (last_inserted_term_id)
end
if not has_error then
l_parameters.put (t.id, "tid")
l_parameters.put (voc.id, "parent_tid")
sql_insert (sql_insert_term_in_vocabulary, l_parameters)
end
if has_error then
sql_rollback_transaction
else
@@ -138,6 +244,148 @@ feature -- Store
sql_finalize
end
associate_term_with_entity (a_term: CMS_TERM; a_type_name: READABLE_STRING_GENERAL; a_entity: READABLE_STRING_GENERAL)
-- Associate term `a_term' with `(a_type_name, a_entity)'.
local
l_parameters: STRING_TABLE [detachable ANY]
do
error_handler.reset
create l_parameters.make (3)
l_parameters.put (a_term.id, "tid")
l_parameters.put (a_entity, "entity")
l_parameters.put (a_type_name, "type")
sql_insert (sql_insert_term_index, l_parameters)
sql_finalize
end
unassociate_term_from_entity (a_term: CMS_TERM; a_type_name: READABLE_STRING_GENERAL; a_entity: READABLE_STRING_GENERAL)
-- Unassociate term `a_term' from `(a_type_name, a_entity)'.
local
l_parameters: STRING_TABLE [detachable ANY]
do
error_handler.reset
create l_parameters.make (3)
l_parameters.put (a_term.id, "tid")
l_parameters.put (a_entity, "entity")
l_parameters.put (a_type_name, "type")
sql_modify (sql_delete_term_index, l_parameters)
sql_finalize
end
feature -- Vocabulary and types
mask_is_tags: INTEGER = 0b0001 -- 1
mask_multiple_terms: INTEGER = 0b0010 -- 2
mask_is_required: INTEGER = 0b0100 -- 4
vocabularies_for_type (a_type_name: READABLE_STRING_GENERAL): detachable CMS_VOCABULARY_COLLECTION
-- <Precursor>
-- note: vocabularies are not filled with associated terms.
local
voc: detachable CMS_VOCABULARY
l_parameters: STRING_TABLE [detachable ANY]
l_data: ARRAYED_LIST [TUPLE [tid: INTEGER_64; entity: INTEGER_64]]
tid, ent: INTEGER_64
do
error_handler.reset
create l_parameters.make (3)
l_parameters.put (a_type_name, "type")
sql_query (sql_select_vocabularies_for_type, l_parameters)
create l_data.make (0)
from
sql_start
until
sql_after or has_error
loop
tid := sql_read_integer_64 (1)
if attached sql_read_string_32 (2) as s and then s.is_integer_64 then
ent := s.to_integer_64
else
ent := 0
end
if ent > 0 then
-- Vocabulary index should have 0 or negative value for `entity'!
check zero_or_negative_entity_value: False end
else
ent := - ent
if tid > 0 then
l_data.force ([tid, ent])
end
end
sql_forth
end
sql_finalize
if not l_data.is_empty then
create Result.make (l_data.count)
across
l_data as ic
loop
tid := ic.item.tid
ent := ic.item.entity
check ic.item.tid > 0 end
if
attached term_by_id (tid) as t
then
create voc.make_from_term (t)
--| 1: mask 0001: New terms allowed (i.e tags)
--| 2: mask 0010: Allow multiple tags
--| 4: mask 0100: At least one tag is required
voc.set_associated_content_type (a_type_name, ent & mask_is_tags = mask_is_tags, ent & mask_multiple_terms = mask_multiple_terms, ent & mask_is_required = mask_is_required)
Result.force (voc)
end
end
end
end
associate_vocabulary_with_type (a_voc: CMS_VOCABULARY; a_type_name: READABLE_STRING_GENERAL)
-- <Precursor>
local
l_parameters: STRING_TABLE [detachable ANY]
i: INTEGER
do
error_handler.reset
create l_parameters.make (3)
l_parameters.put (a_voc.id, "tid")
if a_voc.is_tags then
i := i | mask_is_tags
end
if a_voc.is_term_required then
i := i | mask_multiple_terms
end
if a_voc.multiple_terms_allowed then
i := i | mask_is_required
end
l_parameters.put ((- i).out, "entity")
l_parameters.put (a_type_name, "type")
sql_insert (sql_insert_term_index, l_parameters)
sql_finalize
end
unassociate_vocabulary_with_type (a_voc: CMS_VOCABULARY; a_type_name: READABLE_STRING_GENERAL)
-- <Precursor>
local
l_parameters: STRING_TABLE [detachable ANY]
do
error_handler.reset
create l_parameters.make (2)
l_parameters.put (a_voc.id, "tid")
l_parameters.put (a_type_name, "type")
sql_insert (sql_delete_vocabulary_index, l_parameters)
sql_finalize
end
feature {NONE} -- Queries
last_inserted_term_id: INTEGER_64
@@ -159,7 +407,7 @@ feature {NONE} -- Queries
tid := sql_read_integer_64 (1)
l_text := sql_read_string_32 (2)
if tid > 0 and l_text /= Void then
create Result.make (tid, l_text)
create Result.make_with_id (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)
@@ -176,27 +424,85 @@ feature {NONE} -- Queries
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;"
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
ORDER BY taxonomy_term.weight ASC ;
]"
-- Terms under :parent_tid.
sql_select_term: STRING = "SELECT tid, text, weight, description FROM taxonomy_term WHERE tid = :tid;"
sql_select_terms_with_range: 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
ORDER BY taxonomy_term.weight ASC LIMIT :limit OFFSET :offset
;
]"
-- Terms under :parent_tid, and :limit, :offset
sql_select_term: STRING = "SELECT tid, text, weight, description FROM taxonomy_term WHERE tid=:tid;"
-- Term with tid :tid .
sql_select_term_by_text: STRING = "SELECT tid, text, weight, description FROM taxonomy_term WHERE text=:text;"
-- Term with text :text .
sql_select_vocabulary_term_by_text: 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 AND taxonomy_term.text=:text
;
]"
-- Term with text :text and with parent :parent_tid
Sql_last_inserted_term_id: STRING = "SELECT MAX(tid) FROM taxonomy_term;"
sql_insert_term: STRING = "[
INSERT INTO taxonomy_terms (tid, text, weight, description, langcode)
VALUES (:tid, :text, :weight, :description, null);
INSERT INTO taxonomy_term (text, weight, description, langcode)
VALUES (:text, :weight, :description, null);
]"
sql_update_term: STRING = "[
UPDATE taxonomy_terms
UPDATE taxonomy_term
SET tid=:tid, text=:text, weight=:weight, description=:description, langcode=null
WHERE tid=:tid;
]"
sql_insert_term_in_vocabulary: STRING = "[
INSERT INTO taxonomy_hierarchy (tid, parent)
VALUES (:tid, :parent_tid);
]"
sql_select_terms_of_entity: STRING = "[
SELECT tid FROM taxonomy_index WHERE type=:type AND entity=:entity;
]"
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
WHERE taxonomy_hierarchy.parent=:parent_tid AND taxonomy_index.type=:type AND taxonomy_index.entity=:entity;
]"
sql_select_vocabularies_for_type: STRING = "[
SELECT tid, entity
FROM taxonomy_index
WHERE type=:type AND entity <= 0;
]"
sql_insert_term_index: STRING = "[
INSERT INTO taxonomy_index (tid, entity, type)
VALUES (:tid, :entity, :type);
]"
sql_delete_term_index: STRING = "[
DELETE FROM taxonomy_index WHERE tid=:tid AND entity=:entity AND type=:type
;
]"
sql_delete_vocabulary_index: STRING = "[
DELETE FROM taxonomy_index WHERE tid=:tid AND type=:type
;
]"
end