do
diff --git a/modules/taxonomy/handler/taxonomy_term_admin_handler.e b/modules/taxonomy/handler/taxonomy_term_admin_handler.e
new file mode 100644
index 0000000..9e97d36
--- /dev/null
+++ b/modules/taxonomy/handler/taxonomy_term_admin_handler.e
@@ -0,0 +1,269 @@
+note
+ description: "[
+ Request handler related to
+ /admin/taxonomy/term/{termid}
+ ]"
+ date: "$Date$"
+ revision: "$revision$"
+
+class
+ TAXONOMY_TERM_ADMIN_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,
+ do_post
+ 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_post (req: WSF_REQUEST; res: WSF_RESPONSE)
+ local
+ l_page: CMS_RESPONSE
+ tid: INTEGER_64
+ s: STRING
+ f: CMS_FORM
+ t: detachable CMS_TERM
+ l_parents: detachable CMS_VOCABULARY_COLLECTION
+ do
+ 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
+ if tid > 0 then
+ t := taxonomy_api.term_by_id (tid)
+ end
+ end
+
+ -- Responding with `main_content_html (l_page)'.
+ create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)
+ if l_page.has_permission ("admin taxonomy") then
+
+ if t = Void then
+ l_page.set_title ("New term ...")
+ create t.make ("")
+ else
+ l_page.set_title (t.text)
+ end
+ create s.make_empty
+ f := edit_form (t, l_page, req)
+ f.process (l_page)
+ if
+ attached f.last_data as fd and then
+ fd.is_valid
+ then
+ if attached fd.string_item ("op") as l_op and then l_op.same_string ("Save changes") then
+ if attached fd.string_item ("text") as l_text then
+ t.set_text (l_text)
+ l_page.set_title (t.text)
+ end
+ if attached fd.string_item ("description") as l_description then
+ t.set_description (l_description)
+ end
+ if attached fd.string_item ("weight") as l_weight and then l_weight.is_integer then
+ t.set_weight (l_weight.to_integer)
+ end
+ taxonomy_api.save_term (t, Void)
+ if taxonomy_api.has_error then
+ fd.report_error ("Term creation failed!")
+ else
+ l_page.add_success_message ("Term creation succeed.")
+ s.append ("View term: ")
+ s.append (l_page.link (t.text, "admin/taxonomy/term/" + t.id.out, Void))
+ s.append ("
")
+
+ if
+ attached fd.table_item ("vocabularies") as voc_tb and then
+ attached taxonomy_api.vocabularies (0, 0) as l_vocabularies
+ then
+ l_parents := taxonomy_api.vocabularies_for_term (t)
+ across
+ voc_tb as vid_ic
+ until
+ taxonomy_api.has_error
+ loop
+ if attached l_vocabularies.item_by_id (vid_ic.item.string_representation.to_integer_64) as v then
+ if l_parents /= Void and then attached l_parents.item_by_id (v.id) as l_v then
+ -- Already as parent!
+ l_parents.remove (l_v)
+ else
+ taxonomy_api.save_term (t, v)
+ l_vocabularies.remove (v)
+ end
+ end
+ end
+ if l_parents /= Void then
+ across
+ l_parents as v_ic
+ until
+ taxonomy_api.has_error
+ loop
+ taxonomy_api.remove_term_from_vocabulary (t, v_ic.item)
+ end
+ end
+ end
+ -- l_page.set_redirection (l_page.location)
+ end
+ else
+ fd.report_error ("Invalid form data!")
+ end
+ end
+ f.append_to_html (l_page.wsf_theme, s)
+ l_page.set_main_content (s)
+ l_page.execute
+ else
+ send_access_denied (req, res)
+ end
+ end
+
+ do_get (req: WSF_REQUEST; res: WSF_RESPONSE)
+ --
+ local
+ l_page: CMS_RESPONSE
+ tid: INTEGER_64
+ s: STRING
+ f: CMS_FORM
+ t: detachable CMS_TERM
+ do
+ 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
+ if tid > 0 then
+ t := taxonomy_api.term_by_id (tid)
+ end
+ end
+ -- Responding with `main_content_html (l_page)'.
+ create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)
+ if l_page.has_permission ("admin taxonomy") then
+ if t = Void then
+ l_page.set_title ("Create term ...")
+ create t.make ("")
+ else
+ l_page.set_title (t.text)
+ end
+ create s.make_empty
+ f := edit_form (t, l_page, req)
+ f.append_to_html (l_page.wsf_theme, s)
+ l_page.set_main_content (s)
+ l_page.execute
+ else
+ send_access_denied (req, res)
+ end
+ end
+
+ edit_form (t: CMS_TERM; a_page: CMS_RESPONSE; req: WSF_REQUEST): CMS_FORM
+ local
+ f: CMS_FORM
+ voc: detachable CMS_VOCABULARY
+ w_tf: WSF_FORM_TEXT_INPUT
+ w_txt: WSF_FORM_TEXTAREA
+ w_set: WSF_FORM_FIELD_SET
+ w_cb: WSF_FORM_CHECKBOX_INPUT
+ l_parents: detachable CMS_VOCABULARY_COLLECTION
+ do
+ create f.make (req.percent_encoded_path_info, "taxonomy")
+ if t.has_id then
+ f.extend_html_text (a_page.link ("View associated entities", "taxonomy/term/" + t.id.out, Void))
+ end
+ create w_tf.make_with_text ("text", t.text)
+ w_tf.set_is_required (True)
+ w_tf.set_label ("Text")
+ f.extend (w_tf)
+
+ create w_txt.make ("description")
+ w_txt.set_label ("Description")
+ w_txt.set_rows (3)
+ w_txt.set_cols (60)
+ if attached t.description as l_desc then
+ w_txt.set_text_value (api.html_encoded (l_desc))
+ end
+ w_txt.set_description ("Description of the terms; can be used by modules or administration.")
+ f.extend (w_txt)
+
+ create w_tf.make_with_text ("weight", t.weight.out)
+ w_tf.set_label ("Weight")
+ w_tf.set_description ("Terms are sorted in ascending order by weight.")
+ f.extend (w_tf)
+
+ if attached taxonomy_api.vocabularies (0, 0) as vocs then
+ if t.has_id then
+ l_parents := taxonomy_api.vocabularies_for_term (t)
+ end
+ create w_set.make
+ w_set.set_legend ("Associated vocabularies")
+ across
+ vocs as ic
+ loop
+ voc := ic.item
+ create w_cb.make_with_value ("vocabularies[]", ic.item.id.out)
+ w_cb.set_title (voc.name)
+ if
+ l_parents /= Void and then
+ across l_parents as p_ic some p_ic.item.id = ic.item.id end
+ then
+ w_cb.set_checked (True)
+ end
+ w_set.extend (w_cb)
+ end
+ if w_set.count > 0 then
+ f.extend (w_set)
+ end
+ end
+
+ f.extend (create {WSF_FORM_SUBMIT_INPUT}.make_with_text ("op", "Save changes"))
+ Result := f
+ end
+
+
+end
diff --git a/modules/taxonomy/handler/taxonomy_vocabulary_admin_handler.e b/modules/taxonomy/handler/taxonomy_vocabulary_admin_handler.e
new file mode 100644
index 0000000..c3ba3ac
--- /dev/null
+++ b/modules/taxonomy/handler/taxonomy_vocabulary_admin_handler.e
@@ -0,0 +1,414 @@
+note
+ description: "[
+ Request handler related to
+ /admin/taxonomy/vocabulary/
+ /admin/taxonomy/vocabulary/{vocid}
+ ]"
+ date: "$Date$"
+ revision: "$revision$"
+
+class
+ TAXONOMY_VOCABULARY_ADMIN_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,
+ do_post
+ 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_post (req: WSF_REQUEST; res: WSF_RESPONSE)
+ local
+ l_page: CMS_RESPONSE
+ voc: CMS_VOCABULARY
+ l_typename: READABLE_STRING_GENERAL
+ s: STRING
+ do
+ if not api.user_has_permission (current_user (req), "admin taxonomy") then
+ send_access_denied (req, res)
+ else
+ if attached {WSF_STRING} req.form_parameter ("op") as p_op then
+ if p_op.same_string ("New Vocabulary") then
+ if
+ attached {WSF_STRING} req.form_parameter ("vocabulary_name") as p_name and then
+ not p_name.is_empty
+ then
+ create voc.make (p_name.value)
+ taxonomy_api.save_vocabulary (voc)
+ create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)
+ if taxonomy_api.has_error then
+ l_page.add_error_message ("Vocabulary creation failed!")
+ else
+ l_page.add_success_message ("Vocabulary creation succeed!")
+ l_page.set_redirection ("admin/taxonomy/vocabulary/" + voc.id.out)
+ end
+ else
+ create {BAD_REQUEST_ERROR_CMS_RESPONSE} l_page.make (req, res, api)
+ end
+ elseif
+ p_op.same_string ("Save changes") and then
+ attached {WSF_STRING} req.path_parameter ("vocid") as p_vocid and then p_vocid.is_integer and then
+ attached taxonomy_api.vocabulary (p_vocid.value.to_integer_64) as l_vocabulary
+ then
+ create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)
+ create s.make_empty
+ l_page.add_notice_message ("Vocabulary " + l_vocabulary.id.out)
+ if attached {WSF_STRING} req.form_parameter ("name") as p_name then
+ l_vocabulary.set_name (p_name.value)
+ end
+ if attached {WSF_STRING} req.form_parameter ("description") as p_desc then
+ l_vocabulary.set_description (p_desc.value)
+ end
+ if attached {WSF_STRING} req.form_parameter ("weight") as p_weight and then p_weight.is_integer then
+ l_vocabulary.set_weight (p_weight.integer_value)
+ end
+ taxonomy_api.save_vocabulary (l_vocabulary)
+ if taxonomy_api.has_error then
+ l_page.add_error_message ("Could not save vocabulary")
+ elseif
+ attached {WSF_TABLE} req.form_parameter ("typenames") as typenames_table
+ then
+ across
+ typenames_table as ic
+ loop
+ l_typename := ic.item.string_representation
+ create voc.make_from_term (l_vocabulary)
+ voc.set_associated_content_type (l_typename, False, False, False)
+ l_page.add_notice_message ("Content type :" + api.html_encoded (l_typename))
+ if attached {WSF_TABLE} req.form_parameter ({STRING_32} "vocabulary_" + l_typename.as_string_32) as opts then
+ across
+ opts as o_ic
+ loop
+ if o_ic.item.same_string ("tags") then
+ voc.set_is_tags (True)
+ elseif o_ic.item.same_string ("multiple") then
+ voc.allow_multiple_term (True)
+ elseif o_ic.item.same_string ("required") then
+ voc.set_is_term_required (True)
+ end
+ end
+ end
+ taxonomy_api.associate_vocabulary_with_type (voc, l_typename)
+ if taxonomy_api.has_error then
+ l_page.add_error_message ("Could not save vocabulary content type associations.")
+ end
+ end
+ end
+ if not taxonomy_api.has_error then
+ l_page.add_notice_message (l_page.link ({STRING_32} "Back to vocabulary %"" + l_vocabulary.name + "%"", "admin/taxonomy/vocabulary/" + l_vocabulary.id.out, Void))
+ end
+ l_page.set_main_content (s)
+ else
+ create {NOT_IMPLEMENTED_ERROR_CMS_RESPONSE} l_page.make (req, res, api)
+ end
+ else
+ create {BAD_REQUEST_ERROR_CMS_RESPONSE} l_page.make (req, res, api)
+ end
+ l_page.execute
+ end
+ end
+
+ do_get (req: WSF_REQUEST; res: WSF_RESPONSE)
+ --
+ local
+ tid: INTEGER_64
+ do
+ if not api.user_has_permission (current_user (req), "admin taxonomy") then
+ send_access_denied (req, res)
+ else
+ if attached {WSF_STRING} req.path_parameter ("vocid") as p_vocid then
+ if p_vocid.is_integer then
+ tid := p_vocid.value.to_integer_64
+ end
+ end
+ if tid > 0 then
+ do_get_vocabulary (tid, req, res)
+ else
+ do_get_vocabularies (req, res)
+ end
+ end
+ end
+
+ do_get_vocabulary (tid: INTEGER_64; req: WSF_REQUEST; res: WSF_RESPONSE)
+ --
+ require
+ valid_tid: tid > 0
+ local
+ l_page: CMS_RESPONSE
+ s: STRING
+ l_typename: detachable READABLE_STRING_8
+ v: detachable CMS_VOCABULARY
+ l_typenames: detachable LIST [READABLE_STRING_32]
+ f: CMS_FORM
+ wtb: WSF_WIDGET_TABLE
+ wtb_row: WSF_WIDGET_TABLE_ROW
+ wtb_item: WSF_WIDGET_TABLE_ITEM
+ voc: detachable CMS_VOCABULARY
+ l_term: detachable CMS_TERM
+ tf_input: WSF_FORM_TEXT_INPUT
+ tf_text: WSF_FORM_TEXTAREA
+ tf_num: WSF_FORM_NUMBER_INPUT
+ w_set: WSF_FORM_FIELD_SET
+ w_cb: WSF_FORM_CHECKBOX_INPUT
+ sub: WSF_FORM_SUBMIT_INPUT
+ do
+ voc := taxonomy_api.vocabulary (tid)
+ if voc /= Void then
+ -- Responding with `main_content_html (l_page)'.
+ create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)
+ l_page.set_title (voc.name)
+ taxonomy_api.fill_vocabularies_with_terms (voc)
+
+ create f.make (req.percent_encoded_path_info, "taxonomy")
+
+ create tf_input.make_with_text ("name", voc.name)
+ f.extend (tf_input)
+
+ create tf_text.make ("description")
+ tf_text.set_text_value (voc.description)
+ tf_text.set_description ("Description of the vocabulary; also used as intructions to present to the user when selecting terms.")
+ tf_text.set_rows (3)
+ f.extend (tf_text)
+
+ create tf_num.make_with_text ("weight", voc.weight.out)
+ tf_num.set_label ("weight")
+ tf_num.set_description ("Items are displayed in ascending order by weight.")
+ f.extend (tf_num)
+
+ create wtb.make
+ wtb.add_css_class ("with_border")
+ create wtb_row.make (2)
+ create wtb_item.make_with_text ("Text")
+ wtb_row.set_item (wtb_item, 1)
+ create wtb_item.make_with_text ("Description")
+ wtb_row.set_item (wtb_item, 2)
+ wtb.add_head_row (wtb_row)
+ across
+ voc as ic
+ loop
+ l_term := ic.item
+
+ create wtb_row.make (3)
+ wtb.add_row (wtb_row)
+
+ create wtb_item.make_with_text (l_page.link (ic.item.text, "admin/taxonomy/term/" + l_term.id.out, Void))
+ wtb_row.set_item (wtb_item, 1)
+ if attached ic.item.description as l_desc then
+ create wtb_item.make_with_text (api.html_encoded (l_desc))
+ else
+ create wtb_item.make_with_text ("")
+ end
+ wtb_row.set_item (wtb_item, 2)
+ end
+ if wtb.body_row_count > 0 then
+ f.extend (wtb)
+ else
+ f.extend_raw_text ("No terms.")
+ end
+
+ create w_set.make
+ w_set.set_legend ("Content types")
+ f.extend (w_set)
+
+
+ l_typenames := taxonomy_api.types_associated_with_vocabulary (voc)
+ create wtb.make
+ wtb.add_css_class ("with_border")
+ create wtb_row.make (5)
+ wtb_row.set_item (create {WSF_WIDGET_TABLE_ITEM}.make_with_text ("Type"), 1)
+ create wtb_item.make_with_text ("Settings ...")
+ wtb_item.add_html_attribute ("colspan", "3")
+ wtb_row.set_item (wtb_item, 2)
+ wtb.add_head_row (wtb_row)
+
+ across
+ api.content_types as ic
+ loop
+ create wtb_row.make (4)
+ wtb.add_row (wtb_row)
+
+ l_typename := ic.item.name
+ create w_cb.make_with_value ("typenames[]", api.html_encoded (l_typename))
+ w_cb.set_title (ic.item.name)
+ wtb_row.set_item (create {WSF_WIDGET_TABLE_ITEM}.make_with_content (w_cb), 1)
+
+ v := Void
+ if
+ l_typenames /= Void and then
+ across l_typenames as tn_ic some l_typename.is_case_insensitive_equal (tn_ic.item) end
+ then
+ w_cb.set_checked (True)
+ if attached taxonomy_api.vocabularies_for_type (l_typename) as v_list then
+ across v_list as v_ic until v /= Void loop
+ if v_ic.item.id = voc.id then
+ v := v_ic.item
+ end
+ end
+ end
+ end
+ create w_cb.make_with_value ("vocabulary_" + l_typename +"[]", "tags")
+ w_cb.set_title ("Tags")
+ w_cb.set_checked (v /= Void and then v.is_tags)
+ wtb_row.set_item (create {WSF_WIDGET_TABLE_ITEM}.make_with_content (w_cb), 2)
+
+ create w_cb.make_with_value ("vocabulary_" + l_typename +"[]", "multiple")
+ w_cb.set_title ("Multiple Select")
+ w_cb.set_checked (v /= Void and then v.multiple_terms_allowed)
+ wtb_row.set_item (create {WSF_WIDGET_TABLE_ITEM}.make_with_content (w_cb), 3)
+
+ create w_cb.make_with_value ("vocabulary_" + l_typename +"[]", "required")
+ w_cb.set_title ("Required")
+ w_cb.set_checked (v /= Void and then v.is_term_required)
+ wtb_row.set_item (create {WSF_WIDGET_TABLE_ITEM}.make_with_content (w_cb), 4)
+ end
+ if wtb.body_row_count > 0 then
+ w_set.extend (wtb)
+ end
+
+ create sub.make_with_text ("op", "Save changes")
+ f.extend (sub)
+
+ create s.make_empty
+ f.append_to_html (l_page.wsf_theme, s)
+ 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
+ end
+
+ do_get_vocabularies (req: WSF_REQUEST; res: WSF_RESPONSE)
+ --
+ local
+ l_page: CMS_RESPONSE
+ s: STRING
+ l_typenames: detachable LIST [READABLE_STRING_32]
+ f: CMS_FORM
+ wtb: WSF_WIDGET_TABLE
+ wtb_row: WSF_WIDGET_TABLE_ROW
+ wtb_item: WSF_WIDGET_TABLE_ITEM
+ voc: detachable CMS_VOCABULARY
+ tf_input: WSF_FORM_TEXT_INPUT
+ w_set: WSF_FORM_FIELD_SET
+ sub: WSF_FORM_SUBMIT_INPUT
+ do
+ -- Responding with `main_content_html (l_page)'.
+ create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)
+ create wtb.make
+ wtb.add_css_class ("with_border")
+ create wtb_row.make (3)
+ create wtb_item.make_with_text ("Name")
+ wtb_row.set_item (wtb_item, 1)
+ create wtb_item.make_with_text ("Type")
+ wtb_row.set_item (wtb_item, 2)
+ create wtb_item.make_with_text ("Operations")
+ wtb_row.set_item (wtb_item, 3)
+ wtb.add_head_row (wtb_row)
+
+ if attached taxonomy_api.vocabularies (0, 0) as lst then
+ across
+ lst as ic
+ loop
+ voc := ic.item
+ create wtb_row.make (3)
+ wtb.add_row (wtb_row)
+
+ create wtb_item.make_with_text (l_page.link (ic.item.name, "admin/taxonomy/vocabulary/" + ic.item.id.out, Void))
+-- if attached ic.item.description as l_desc then
+-- s.append (" : ")
+-- s.append (api.html_encoded (l_desc))
+-- s.append ("")
+-- end
+ wtb_row.set_item (wtb_item, 1)
+ l_typenames := taxonomy_api.types_associated_with_vocabulary (voc)
+ if l_typenames /= Void then
+ create s.make_empty
+ across
+ l_typenames as types_ic
+ loop
+ if not s.is_empty then
+ s.append_character (',')
+ s.append_character (' ')
+ end
+ s.append (api.html_encoded (types_ic.item))
+ end
+ create wtb_item.make_with_text (s)
+ wtb_row.set_item (wtb_item, 2)
+ end
+
+ s := l_page.link ("edit", "admin/taxonomy/vocabulary/" + voc.id.out, Void)
+ create wtb_item.make_with_text (s)
+ wtb_row.set_item (wtb_item, 3)
+ end
+ end
+ create f.make (req.percent_encoded_path_info, "taxonomy")
+ f.set_method_post
+
+ f.extend (wtb)
+
+ create w_set.make
+ w_set.set_legend ("Create a new vocabulary")
+ create tf_input.make_with_text ("vocabulary_name", "")
+ tf_input.set_label ("Vocabulary name")
+ w_set.extend (tf_input)
+ create sub.make_with_text ("op", "New Vocabulary")
+ w_set.extend (sub)
+ f.extend (w_set)
+
+ create s.make_empty
+ f.append_to_html (l_page.wsf_theme, s)
+ l_page.set_title ("Vocabularies")
+ l_page.set_main_content (s)
+ l_page.execute
+ end
+
+end
diff --git a/modules/taxonomy/handler/taxonomy_vocabulary_handler.e b/modules/taxonomy/handler/taxonomy_vocabulary_handler.e
new file mode 100644
index 0000000..6db90f4
--- /dev/null
+++ b/modules/taxonomy/handler/taxonomy_vocabulary_handler.e
@@ -0,0 +1,129 @@
+note
+ description: "[
+ Request handler related to
+ /taxonomy/vocabulary/
+ /taxonomy/vocabulary/{vocid}
+ ]"
+ date: "$Date$"
+ revision: "$revision$"
+
+class
+ TAXONOMY_VOCABULARY_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
+ tid: INTEGER_64
+ s: STRING
+ do
+ if attached {WSF_STRING} req.path_parameter ("vocid") as p_vocid then
+ if p_vocid.is_integer then
+ tid := p_vocid.value.to_integer_64
+ end
+ end
+ if tid > 0 then
+ if attached taxonomy_api.vocabulary (tid) as voc then
+ -- Responding with `main_content_html (l_page)'.
+ create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)
+ l_page.set_title (voc.name)
+ taxonomy_api.fill_vocabularies_with_terms (voc)
+
+ create s.make_empty
+ s.append ("")
+ across
+ voc as ic
+ loop
+ s.append ("- ")
+ s.append (l_page.link (ic.item.text, "taxonomy/term/" + ic.item.id.out, Void))
+ if attached ic.item.description as l_desc then
+ s.append (" : ")
+ s.append (api.html_encoded (l_desc))
+ s.append ("")
+ end
+ s.append ("
")
+ end
+ s.append ("
")
+ 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 {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)
+ create s.make_empty
+ if attached taxonomy_api.vocabularies (0, 0) as lst then
+ s.append ("")
+ across
+ lst as ic
+ loop
+ s.append ("- ")
+ s.append (l_page.link (ic.item.name, "taxonomy/vocabulary/" + ic.item.id.out, Void))
+ s.append ("
")
+ end
+ s.append ("
")
+ else
+ s.append ("No vocabulary!")
+ end
+ l_page.set_main_content (s)
+ 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 a915ebf..cfd7132 100644
--- a/modules/taxonomy/persistence/cms_taxonomy_storage_i.e
+++ b/modules/taxonomy/persistence/cms_taxonomy_storage_i.e
@@ -41,6 +41,24 @@ feature -- Access
deferred
end
+ vocabularies_for_term (a_term: CMS_TERM): detachable CMS_VOCABULARY_COLLECTION
+ -- Vocabularies including `a_term'.
+ deferred
+ end
+
+ is_term_inside_vocabulary (a_term: CMS_TERM; a_vocab: CMS_VOCABULARY): BOOLEAN
+ -- Is `a_term' inside `a_vocab' ?
+ require
+ valid_term: a_term.has_id
+ valid_vocabulary: a_vocab.has_id
+ deferred
+ end
+
+ types_associated_with_vocabulary (a_vocab: CMS_VOCABULARY): detachable LIST [READABLE_STRING_32]
+ -- Type names associated with `a_vocab'.
+ deferred
+ end
+
terms_count: INTEGER_64
-- Number of terms.
deferred
@@ -89,20 +107,28 @@ feature -- Access
feature -- Store
- save_vocabulary (a_voc: CMS_VOCABULARY)
- -- Insert or update vocabulary `a_voc'.
+ save_vocabulary (a_voc: CMS_VOCABULARY; a_with_terms: BOOLEAN)
+ -- Insert or update vocabulary `a_voc'
+ -- and also save {CMS_VOCABULARY}.terms if `a_with_terms' is True.
deferred
ensure
not error_handler.has_error implies a_voc.has_id and then vocabulary (a_voc.id) /= Void
end
- save_term (t: CMS_TERM; voc: CMS_VOCABULARY)
- -- Insert or update term `t' as part of vocabulary `voc'.
+ save_term (t: CMS_TERM; voc: detachable CMS_VOCABULARY)
+ -- Insert or update term `t' as part of vocabulary `voc' if set.
deferred
ensure
not error_handler.has_error implies t.has_id and then term_by_id (t.id) /= Void
end
+ remove_term_from_vocabulary (t: CMS_TERM; voc: CMS_VOCABULARY)
+ -- Remove term `t' from vocabulary `voc'.
+ require
+ t_has_id: t.has_id
+ deferred
+ 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)'.
require
diff --git a/modules/taxonomy/persistence/cms_taxonomy_storage_null.e b/modules/taxonomy/persistence/cms_taxonomy_storage_null.e
index 2e663cd..f8336b6 100644
--- a/modules/taxonomy/persistence/cms_taxonomy_storage_null.e
+++ b/modules/taxonomy/persistence/cms_taxonomy_storage_null.e
@@ -53,6 +53,21 @@ feature -- Access
do
end
+ vocabularies_for_term (a_term: CMS_TERM): detachable CMS_VOCABULARY_COLLECTION
+ --
+ do
+ end
+
+ is_term_inside_vocabulary (a_term: CMS_TERM; a_vocab: CMS_VOCABULARY): BOOLEAN
+ --
+ do
+ end
+
+ types_associated_with_vocabulary (a_vocab: CMS_VOCABULARY): detachable LIST [READABLE_STRING_32]
+ --
+ do
+ end
+
terms_count: INTEGER_64
-- Number of terms.
do
@@ -85,18 +100,25 @@ feature -- Access
feature -- Store
- save_vocabulary (a_voc: CMS_VOCABULARY)
- -- Insert or update vocabulary `a_voc'.
+ save_vocabulary (a_voc: CMS_VOCABULARY; a_with_terms: BOOLEAN)
+ -- Insert or update vocabulary `a_voc'
+ -- and also save {CMS_VOCABULARY}.terms if `a_with_terms' is True.
do
error_handler.add_custom_error (-1, "not implemented", "save_vocabulary")
end
- save_term (t: CMS_TERM; voc: CMS_VOCABULARY)
+ save_term (t: CMS_TERM; voc: detachable CMS_VOCABULARY)
--
do
error_handler.add_custom_error (-1, "not implemented", "save_term")
end
+ remove_term_from_vocabulary (t: CMS_TERM; voc: CMS_VOCABULARY)
+ -- Remove term `t' from vocabulary `voc'.
+ do
+ error_handler.add_custom_error (-1, "not implemented", "remove_term_from_vocabulary")
+ end
+
associate_term_with_entity (a_term: CMS_TERM; a_type_name: READABLE_STRING_GENERAL; a_entity: READABLE_STRING_GENERAL)
do
error_handler.add_custom_error (-1, "not implemented", "associate_term_with_entity")
diff --git a/modules/taxonomy/persistence/cms_taxonomy_storage_sql.e b/modules/taxonomy/persistence/cms_taxonomy_storage_sql.e
index 7bb850b..15cad57 100644
--- a/modules/taxonomy/persistence/cms_taxonomy_storage_sql.e
+++ b/modules/taxonomy/persistence/cms_taxonomy_storage_sql.e
@@ -232,21 +232,41 @@ feature -- Access
feature -- Store
- save_vocabulary (voc: CMS_VOCABULARY)
+ save_vocabulary (voc: CMS_VOCABULARY; a_with_terms: BOOLEAN)
+ local
+ l_terms: CMS_TERM_COLLECTION
do
save_term (voc, create {CMS_VOCABULARY}.make_none)
- across
- voc.terms as ic
- until
- has_error
- loop
- save_term (ic.item, voc)
+
+ if a_with_terms then
+ l_terms := terms (voc, 0, 0)
+ across
+ voc.terms as ic
+ until
+ has_error
+ loop
+ if attached l_terms.term_by_id (ic.item.id) as t then
+ -- Already contained.
+ -- Remove from `l_terms' to leave only terms to remove.
+ l_terms.remove (t)
+ else
+ save_term (ic.item, voc)
+ end
+ end
+ across
+ l_terms as ic
+ until
+ has_error
+ loop
+ remove_term_from_vocabulary (ic.item, voc)
+ end
end
end
- save_term (t: CMS_TERM; voc: CMS_VOCABULARY)
+ save_term (t: CMS_TERM; voc: detachable CMS_VOCABULARY)
local
l_parameters: STRING_TABLE [detachable ANY]
+ l_insert_voc: BOOLEAN
do
error_handler.reset
@@ -255,6 +275,8 @@ feature -- Store
l_parameters.put (t.description, "description")
l_parameters.put (t.weight, "weight")
+ l_insert_voc := voc /= Void and then is_term_inside_vocabulary (t, voc)
+
sql_begin_transaction
if t.has_id then
l_parameters.put (t.id, "tid")
@@ -263,9 +285,18 @@ feature -- Store
sql_insert (sql_insert_term, l_parameters)
t.set_id (last_inserted_term_id)
end
- if not has_error then
+ if
+ not has_error and
+ voc /= Void and then
+ not l_insert_voc
+ then
+ l_parameters.wipe_out
l_parameters.put (t.id, "tid")
- l_parameters.put (voc.id, "parent_tid")
+ if voc.has_id then
+ l_parameters.put (voc.id, "parent_tid")
+ else
+ l_parameters.put (0, "parent_tid")
+ end
sql_insert (sql_insert_term_in_vocabulary, l_parameters)
end
if has_error then
@@ -276,6 +307,19 @@ feature -- Store
sql_finalize
end
+ remove_term_from_vocabulary (t: CMS_TERM; voc: CMS_VOCABULARY)
+ local
+ l_parameters: STRING_TABLE [detachable ANY]
+ do
+ error_handler.reset
+
+ create l_parameters.make (2)
+ l_parameters.put (t.id, "tid")
+ l_parameters.put (voc.id, "parent_tid")
+ sql_modify (sql_remove_term_from_vocabulary, l_parameters)
+ 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
@@ -376,6 +420,90 @@ feature -- Vocabulary and types
end
end
+ is_term_inside_vocabulary (a_term: CMS_TERM; a_voc: CMS_VOCABULARY): BOOLEAN
+ local
+ l_parameters: STRING_TABLE [detachable ANY]
+ do
+ error_handler.reset
+
+ create l_parameters.make (2)
+ l_parameters.put (a_term.id, "tid")
+ l_parameters.put (a_voc.id, "parent_tid")
+ sql_query (sql_select_term_in_vocabulary, l_parameters)
+ sql_start
+ if not has_error or sql_after then
+ Result := sql_read_integer_64 (1) > 0
+ end
+ sql_finalize
+ end
+
+ vocabularies_for_term (a_term: CMS_TERM): detachable CMS_VOCABULARY_COLLECTION
+ --
+ local
+ voc: detachable CMS_VOCABULARY
+ l_parameters: STRING_TABLE [detachable ANY]
+ l_parent_id: INTEGER_64
+ l_ids: ARRAYED_LIST [INTEGER_64]
+ do
+ error_handler.reset
+
+ create l_parameters.make (3)
+ l_parameters.put (a_term.id, "tid")
+ sql_query (sql_select_vocabularies_for_term, l_parameters)
+
+ create l_ids.make (1)
+ from
+ sql_start
+ until
+ sql_after or has_error
+ loop
+ l_parent_id := sql_read_integer_64 (1)
+ l_ids.force (l_parent_id)
+ sql_forth
+ end
+ sql_finalize
+
+ if l_ids.count > 0 then
+ create Result.make (1)
+ across
+ l_ids as ic
+ loop
+ voc := vocabulary (ic.item)
+ if voc /= Void then
+ Result.force (voc)
+ end
+ end
+ if Result.count = 0 then
+ Result := Void
+ end
+ end
+ end
+
+ types_associated_with_vocabulary (a_vocab: CMS_VOCABULARY): detachable LIST [READABLE_STRING_32]
+ -- Type names associated with `a_vocab'.
+ local
+ l_parameters: STRING_TABLE [detachable ANY]
+ do
+ error_handler.reset
+
+ create l_parameters.make (1)
+ l_parameters.put (a_vocab.id, "tid")
+ sql_query (sql_select_type_associated_with_vocabulary, l_parameters)
+
+ create {ARRAYED_LIST [READABLE_STRING_32]} Result.make (3)
+ from
+ sql_start
+ until
+ sql_after or has_error
+ loop
+ if attached sql_read_string_32 (1) as l_typename then
+ Result.force (l_typename)
+ end
+ sql_forth
+ end
+ sql_finalize
+ end
+
associate_vocabulary_with_type (a_voc: CMS_VOCABULARY; a_type_name: READABLE_STRING_GENERAL)
--
local
@@ -396,10 +524,17 @@ feature -- Vocabulary and types
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)
+ if
+ attached vocabularies_for_type (a_type_name) as lst and then
+ across lst as ic some a_voc.id = ic.item.id end
+ then
+ sql_modify (sql_update_term_index, l_parameters)
+ else
+ sql_insert (sql_insert_term_index, l_parameters)
+ end
+
sql_finalize
end
@@ -464,6 +599,20 @@ feature {NONE} -- Queries
]"
-- Terms under :parent_tid.
+ sql_select_vocabularies_for_term: STRING = "[
+ SELECT parent
+ FROM taxonomy_hierarchy
+ WHERE tid = :tid
+ ;
+ ]"
+
+ sql_select_term_in_vocabulary: STRING = "[
+ SELECT count(*)
+ FROM taxonomy_hierarchy
+ WHERE tid = :tid and parent = :parent_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
@@ -505,6 +654,10 @@ feature {NONE} -- Queries
VALUES (:tid, :parent_tid);
]"
+ sql_remove_term_from_vocabulary: STRING = "[
+ DELETE FROM taxonomy_hierarchy WHERE tid=:tid AND parent=:parent_tid;
+ ]"
+
sql_select_terms_of_entity: STRING = "[
SELECT tid FROM taxonomy_index WHERE type=:type AND entity=:entity;
]"
@@ -527,6 +680,19 @@ feature {NONE} -- Queries
WHERE type=:type AND entity <= 0;
]"
+ sql_select_type_associated_with_vocabulary: STRING = "[
+ SELECT type
+ FROM taxonomy_index
+ WHERE tid=:tid AND entity <= 0;
+ ]"
+
+ sql_update_term_index: STRING = "[
+ UPDATE taxonomy_index
+ SET entity=:entity
+ WHERE tid=:tid and type=:type
+ ;
+ ]"
+
sql_insert_term_index: STRING = "[
INSERT INTO taxonomy_index (tid, entity, type)
VALUES (:tid, :entity, :type);
diff --git a/modules/taxonomy/site/files/css/taxonomy.css b/modules/taxonomy/site/files/css/taxonomy.css
index 41c87fa..dd216d0 100644
--- a/modules/taxonomy/site/files/css/taxonomy.css
+++ b/modules/taxonomy/site/files/css/taxonomy.css
@@ -19,3 +19,8 @@ ul.taxonomy li:hover {
border-bottom: solid 1px #66f;
background-color: #ddf;
}
+
+table.taxonomy td {
+ border: solid 1px #ccc;
+ padding: 2px;
+}
diff --git a/modules/taxonomy/site/files/scss/taxonomy.scss b/modules/taxonomy/site/files/scss/taxonomy.scss
index f409395..2ceff02 100644
--- a/modules/taxonomy/site/files/scss/taxonomy.scss
+++ b/modules/taxonomy/site/files/scss/taxonomy.scss
@@ -19,3 +19,9 @@ ul.taxonomy {
}
}
}
+table.taxonomy {
+ td {
+ border: solid 1px #ccc;
+ padding: 2px;
+ }
+}
diff --git a/src/service/cms_api.e b/src/service/cms_api.e
index 78a6252..d3a6e4e 100644
--- a/src/service/cms_api.e
+++ b/src/service/cms_api.e
@@ -15,7 +15,7 @@ inherit
REFACTORING_HELPER
- CMS_ENCODERS
+ CMS_REQUEST_UTIL
create
make
@@ -407,7 +407,7 @@ feature {NONE} -- Hooks
l_hooks: like hooks
do
l_hooks := hooks
- register_hooks (l_hooks)
+ setup_core_hooks (l_hooks)
across
enabled_modules as ic
loop
@@ -436,7 +436,7 @@ feature -- Query: API
feature -- Hooks
- register_hooks (a_hooks: CMS_HOOK_CORE_MANAGER)
+ setup_core_hooks (a_hooks: CMS_HOOK_CORE_MANAGER)
-- Register hooks associated with the cms core.
do
a_hooks.subscribe_to_export_hook (Current)
diff --git a/src/service/response/cms_response.e b/src/service/response/cms_response.e
index 8746d00..ec7daeb 100644
--- a/src/service/response/cms_response.e
+++ b/src/service/response/cms_response.e
@@ -72,7 +72,6 @@ feature {NONE} -- Initialization
l_module: CMS_MODULE
l_enabled_modules: CMS_MODULE_COLLECTION
do
- api.register_hooks (hooks)
l_enabled_modules := api.enabled_modules
across
l_enabled_modules as ic
@@ -984,6 +983,26 @@ feature -- Theme
end
end
+feature -- Theme helpers
+
+ wsf_theme: WSF_THEME
+ -- WSF Theme from CMS `theme' for Current response.
+ local
+ t: like internal_wsf_theme
+ do
+ t := internal_wsf_theme
+ if t = Void then
+ create {CMS_TO_WSF_THEME} t.make (Current, theme)
+ internal_wsf_theme := t
+ end
+ Result := t
+ end
+
+feature {NONE} -- Theme helpers
+
+ internal_wsf_theme: detachable WSF_THEME
+ -- Once per object for `wsf_theme'.
+
feature -- Element Change
set_status_code (a_status: INTEGER)