From eb70af6f19d7998841094c3234a0fafeadcd74b2 Mon Sep 17 00:00:00 2001 From: jvelilla Date: Tue, 8 Sep 2015 18:16:18 -0300 Subject: [PATCH] CMS_NODE_API.available_parents_for_node - Fixed comment. - added check to know if there are potencial cycles - added postcondition to ensure the list of potencial parent will not produce a cycle. CMS_PAGE_NODE_TYPE_WEBFORM_MANAGER.update_node - Updated code to handle unassing parent from a node when the user - submit a -1 value. NODE_FORM_RESPONSE.edit_form_validation - Added validation for node_parent, check if the input is valid and then - if exist a valid node in the list of available parents for the current node. Signed-off-by: jvelilla --- modules/node/cms_node_api.e | 53 +++++++++++++- .../cms_page_node_type_webform_manager.e | 6 ++ modules/node/handler/node_form_response.e | 69 +++++++++++-------- modules/node/handler/node_handler.e | 2 +- .../node/persistence/cms_node_storage_sql.e | 2 +- 5 files changed, 98 insertions(+), 34 deletions(-) diff --git a/modules/node/cms_node_api.e b/modules/node/cms_node_api.e index 7a969e5..a0a0762 100644 --- a/modules/node/cms_node_api.e +++ b/modules/node/cms_node_api.e @@ -329,9 +329,58 @@ feature -- Access: Node available_parents_for_node (a_node: CMS_NODE): LIST [CMS_NODE] - -- Given the node `a_node', return the list of possible parent nodes + -- List of possible parents nodes for node `a_node'. + -- Ensure the list of possible parent nodes does not allow a potential cycle. do - Result := node_storage.available_parents_for_node(a_node) + create {ARRAYED_LIST[CMS_NODE]}Result.make (0) + across node_storage.available_parents_for_node(a_node) as ic loop + if not has_cycle (a_node, ic.item) then + Result.force (ic.item) + end + end + + ensure + not_cycle: Result.for_all (agent not_cycle (a_node, ?)) + end + +feature {NONE} -- Implementation + + not_cycle (a_node: CMS_NODE; a_parent: CMS_NODE): BOOLEAN + do + Result := not has_cycle (a_node, a_parent) + end + + has_cycle (a_node: CMS_NODE; a_parent: CMS_NODE): BOOLEAN + -- Check if adding the node `a_parent' as parent of node `a_node' form a cycle. + local + l_flag: BOOLEAN + l_item: detachable CMS_PAGE + do + Result := False + if + attached {CMS_PAGE} a_node as l_page and then + attached {CMS_PAGE} full_node (a_parent) as l_page_parent + then + l_page.set_parent (l_page_parent) + from + l_item := l_page_parent + until + l_flag or else Result + loop + if attached l_item and then attached {CMS_PAGE} node (l_item.id) as l_parent then + if l_parent.id = l_page.id then + Result := True + else + l_item := l_parent.parent + end + else + l_flag := True + end + end + -- Set parent to void. + l_page.set_parent (Void) + end + end feature -- Permission Scope: Node diff --git a/modules/node/handler/cms_page_node_type_webform_manager.e b/modules/node/handler/cms_page_node_type_webform_manager.e index 9f68f71..eb009ab 100644 --- a/modules/node/handler/cms_page_node_type_webform_manager.e +++ b/modules/node/handler/cms_page_node_type_webform_manager.e @@ -36,6 +36,12 @@ feature -- Forms ... attached {CMS_PAGE} a_response.node_api.node (i_parent_node) as l_parent_page then l_node_page.set_parent (l_parent_page) + elseif attached {CMS_PAGE} a_node as l_node_page and then + attached fd.integer_item ("select_parent_node") as i_parent_node and then + i_parent_node = -1 + then + -- Set parent to Void + l_node_page.set_parent (Void) end end diff --git a/modules/node/handler/node_form_response.e b/modules/node/handler/node_form_response.e index e8e54a1..8b30fcf 100644 --- a/modules/node/handler/node_form_response.e +++ b/modules/node/handler/node_form_response.e @@ -233,6 +233,7 @@ feature -- Form local l_preview: BOOLEAN l_format: detachable CONTENT_FORMAT + l_selected: BOOLEAN do l_preview := attached {WSF_STRING} fd.item ("op") as l_op and then l_op.same_string ("Preview") if l_preview then @@ -254,6 +255,32 @@ feature -- Form end b.append ("") end + + if + attached fd.integer_item ("select_parent_node") as s_parent_node and then + s_parent_node.to_integer_64 > 0 and then + attached node_api.node (s_parent_node) as l_parent_node and then + attached node_api.node (node_id_path_parameter (request)) as l_node + then + across node_api.available_parents_for_node (l_node) as ic until l_selected loop + if l_parent_node.same_node (ic.item) then + l_selected := True + end + end + if not l_selected then + fd.report_invalid_field ("select_parent_node", "Invalid node id " + s_parent_node.out) + end + elseif + attached fd.integer_item ("select_parent_node") as s_parent_node and then + (s_parent_node = -1 or else s_parent_node = 0) + then + -- -1 is Used to unassing a parent node + -- 0 is not taken into account, any other input value is considered invalid. + else + fd.report_invalid_field ("select_parent_node", "Invalid node id") + end + + end edit_form_submit (fd: WSF_FORM_DATA; a_node: detachable CMS_NODE; a_type: CMS_NODE_TYPE [CMS_NODE]; b: STRING) @@ -264,6 +291,7 @@ feature -- Form l_path_alias: detachable READABLE_STRING_8 nid: INTEGER_64 do + fixme ("Refactor code per operacion: Preview, Save") l_preview := attached {WSF_STRING} fd.item ("op") as l_op and then l_op.same_string ("Preview") if not l_preview then debug ("cms") @@ -294,7 +322,7 @@ feature -- Form fixme ("for now, publishing is not implemented, so let's assume any node saved is published.") -- FIXME l_node.mark_published - -- Save Child Page + -- Save parent id in current node. nid := node_id_path_parameter (request) if location.ends_with_general ("/add_child/page") and then nid > 0 and then attached {CMS_PAGE} l_node as l_new_page and then @@ -341,13 +369,10 @@ feature -- Form f: CMS_FORM ts: WSF_FORM_SUBMIT_INPUT th: WSF_FORM_HIDDEN_INPUT - tl: WSF_FORM_SELECT - to: WSF_FORM_SELECT_OPTION + ti: WSF_FORM_NUMBER_INPUT + l_item: CMS_NODE do create f.make (a_url, a_name) - - - create th.make ("node-id") if a_node /= Void then th.set_text_value (a_node.id.out) @@ -359,40 +384,24 @@ feature -- Form populate_form (a_node_type, f, a_node) f.extend_html_text ("
") - -- Select for nodes - create tl.make ("select_parent_node") - create to.make ("0", "NONE") - tl.add_option (to) - if attached {CMS_PAGE} a_node as l_node_page then if attached l_node_page.parent as l_parent_node then f.extend_html_text ("
Parent page is ") f.extend_html_text (node_html_link (l_parent_node, l_parent_node.title + "(#" + l_parent_node.id.out + ")")) f.extend_html_text ("
") f.extend_html_text ("Change parent to?") - if a_node /= Void then - across node_api.available_parents_for_node (a_node) as ic loop - create to.make (ic.item.id.out, node_html_link (ic.item, ic.item.title + "(#" + ic.item.id.out + ")")) - if l_parent_node.id = ic.item.id then - to.set_is_selected (True) - end - tl.add_option (to) - end - end - f.extend (tl) + create ti.make ("select_parent_node") + ti.set_label ("Parent Node") + f.extend (ti) f.extend_html_text ("
") else f.extend_html_text ("
Not has parent page ") f.extend_html_text ("
") f.extend_html_text ("Add parent to?") - if a_node /= Void then - across node_api.available_parents_for_node (a_node) as ic loop - create to.make (ic.item.id.out, node_html_link (ic.item, ic.item.title + "(#" + ic.item.id.out + ")")) - tl.add_option (to) - end - f.extend (tl) - f.extend_html_text ("
") - end + create ti.make ("select_parent_node") + ti.set_label ("Parent Node") + f.extend (ti) + f.extend_html_text ("") end end @@ -432,7 +441,7 @@ feature -- Form ts.set_default_value (translation ("Delete")) ]") f.extend (ts) - fixme ("wsf_html: add support for HTML5 input attributes!!! ") + to_implement ("Refactor code to use the new wsf_html HTML5 support") f.extend_html_text("" ) end diff --git a/modules/node/handler/node_handler.e b/modules/node/handler/node_handler.e index fa80c23..1ee1d97 100644 --- a/modules/node/handler/node_handler.e +++ b/modules/node/handler/node_handler.e @@ -103,7 +103,7 @@ feature -- HTTP Methods -- Add child node l_nid := node_id_path_parameter (req) if l_nid > 0 then - -- create a new child node with node id l_id as parent. + -- create a new child node with node id `l_id' as parent. create_new_node (req, res) else send_not_found (req, res) diff --git a/modules/node/persistence/cms_node_storage_sql.e b/modules/node/persistence/cms_node_storage_sql.e index 91c995f..8cc17af 100644 --- a/modules/node/persistence/cms_node_storage_sql.e +++ b/modules/node/persistence/cms_node_storage_sql.e @@ -482,7 +482,7 @@ feature {NONE} -- Queries Sql_last_insert_node_revision: STRING = "SELECT MAX(revision) FROM node_revisions;" Sql_last_insert_node_revision_for_nid: STRING = "SELECT MAX(revision) FROM node_revisions WHERE nid=:nid;" - sql_select_available_parents_for_node : STRING = "SELECT pn_1.nid, pn_1.revision, pn_1.type, title, summary, content, format, author, publish, created, changed, status FROM nodes pn_1 LEFT JOIN page_nodes pn_2 ON pn_1.nid = pn_2.nid AND pn_1.nid != :nid WHERE pn_2.parent != :nid AND pn_1.status != -1;" + sql_select_available_parents_for_node : STRING = "SELECT pn_1.nid, pn_1.revision, pn_1.type, title, summary, content, format, author, publish, created, changed, status FROM nodes pn_1 LEFT JOIN page_nodes pn_2 ON pn_1.nid = pn_2.nid AND pn_1.nid != :nid WHERE pn_2.parent != :nid AND pn_1.status != -1 GROUP BY pn_1.nid, pn_1.revision;" feature {NONE} -- Sql Queries: USER_ROLES collaborators, author