diff --git a/modules/node/cms_node_api.e b/modules/node/cms_node_api.e index a0a0762..ab2f96a 100644 --- a/modules/node/cms_node_api.e +++ b/modules/node/cms_node_api.e @@ -281,14 +281,17 @@ feature -- Access: Node else Result := l_partial_node end + -- Update link with aliasing. + if Result /= Void and then Result.has_id then + Result.set_link (node_link (Result)) + end else Result := a_node + if Result.has_id and Result.link = Void then + Result.set_link (node_link (Result)) + end end - - -- Update link with aliasing. - if a_node /= Void and then a_node.has_id then - a_node.set_link (node_link (a_node)) - end + check has_link: Result.has_id implies attached Result.link as lnk and then lnk.location.same_string (node_link (Result).location) end -- Update partial user if needed. if @@ -327,60 +330,47 @@ feature -- Access: Node end end +feature -- Access: page/book outline + + children (a_node: CMS_NODE): detachable LIST [CMS_NODE] + -- Children of node `a_node'. + -- note: this is the partial version of the nodes. + do + Result := node_storage.children (a_node) + end available_parents_for_node (a_node: CMS_NODE): LIST [CMS_NODE] - -- List of possible parents nodes for node `a_node'. - -- Ensure the list of possible parent nodes does not allow a potential cycle. + -- Potential parent nodes for node `a_node'. + -- Ensure no cycle exists. do - 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 + create {ARRAYED_LIST [CMS_NODE]} Result.make (0) + across node_storage.available_parents_for_node (a_node) as ic loop + check distinct: not a_node.same_node (ic.item) end + if not is_node_a_parent_of (a_node, ic.item) then Result.force (ic.item) end end - ensure - not_cycle: Result.for_all (agent not_cycle (a_node, ?)) + no_cycle: across Result as c all not is_node_a_parent_of (a_node, c.item) end end feature {NONE} -- Implementation - not_cycle (a_node: CMS_NODE; a_parent: CMS_NODE): BOOLEAN + is_node_a_parent_of (a_node: CMS_NODE; a_child: CMS_NODE): BOOLEAN + -- Is `a_node' a direct or indirect parent of node `a_child'? + require + distinct_nodes: not a_node.same_node (a_child) 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 + attached {CMS_PAGE} full_node (a_child) as l_child_page and then + attached l_child_page.parent as l_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) + if l_parent.same_node (l_child_page) then + Result := True + else + Result := is_node_a_parent_of (a_node, l_parent) + end end - end feature -- Permission Scope: Node diff --git a/modules/node/cms_node_module.e b/modules/node/cms_node_module.e index 6ea424f..9636d47 100644 --- a/modules/node/cms_node_module.e +++ b/modules/node/cms_node_module.e @@ -170,6 +170,8 @@ feature -- Access Result.force ("trash own " + l_type_name) Result.force ("restore own " + l_type_name) + Result.force ("view unpublished " + l_type_name) + Result.force ("view revisions own " + l_type_name) end end diff --git a/modules/node/content/cms_node.e b/modules/node/content/cms_node.e index ab96c69..696d011 100644 --- a/modules/node/content/cms_node.e +++ b/modules/node/content/cms_node.e @@ -10,7 +10,7 @@ deferred class CMS_NODE inherit - + DEBUG_OUTPUT REFACTORING_HELPER feature{NONE} -- Initialization @@ -166,6 +166,23 @@ feature -- Access: menu link: detachable CMS_LOCAL_LINK -- Associated menu link. +feature -- Status report + + debug_output: STRING_32 + -- + do + 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 ('%"') + end + feature -- Element change set_content (a_content: like content; a_summary: like summary; a_format: like format) diff --git a/modules/node/handler/cms_node_type_webform_manager.e b/modules/node/handler/cms_node_type_webform_manager.e index 16e5639..dac05b6 100644 --- a/modules/node/handler/cms_node_type_webform_manager.e +++ b/modules/node/handler/cms_node_type_webform_manager.e @@ -277,7 +277,7 @@ feature -- Output create lnk.make ("Trash", node_api.node_path (a_node) + "/trash") lnk.set_weight (2) a_response.add_to_primary_tabs (lnk) - elseif a_node /= Void and then a_node.has_id then + elseif a_node.has_id then -- Node in {{CMS_NODE_API}.published} or {CMS_NODE_API}.not_published} status. create lnk.make ("Edit", node_api.node_path (a_node) + "/edit") lnk.set_weight (2) 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 eb009ab..808d76a 100644 --- a/modules/node/handler/cms_page_node_type_webform_manager.e +++ b/modules/node/handler/cms_page_node_type_webform_manager.e @@ -11,6 +11,8 @@ inherit redefine content_type, append_html_output_to, + populate_form, + new_node, update_node end @@ -24,159 +26,112 @@ feature -- Access feature -- Forms ... + populate_form (response: NODE_RESPONSE; f: CMS_FORM; a_node: detachable CMS_NODE) + local + ti: WSF_FORM_NUMBER_INPUT + l_parent_id, nid: INTEGER_64 + do + Precursor (response, f, a_node) + + if attached {CMS_PAGE} a_node as l_page then + create ti.make ("select_parent_node") + + if attached l_page.parent as l_parent_node then + l_parent_id := l_parent_node.id + f.extend_html_text ("
Currently, the parent page is ") + f.extend_html_text (response.node_html_link (l_parent_node, l_parent_node.title)) + f.extend_html_text ("
") + ti.set_label ("Change parent") + ti.set_description ("Select a new parent ...") + else + ti.set_label ("Select parent") + ti.set_description ("Select a parent ...") + end + ti.set_validation_action (agent parent_validation (response, ?)) + f.extend (ti) + + if response.location.ends_with_general ("/add_child/page") then + nid := response.node_id_path_parameter (response.request) + l_parent_id := nid + end + if l_parent_id > 0 then + ti.set_default_value (l_parent_id.out) + end + end + end update_node (a_response: NODE_RESPONSE; fd: WSF_FORM_DATA; a_node: CMS_NODE) -- + local + l_parent_id: INTEGER_64 do Precursor (a_response, fd, a_node) - if - 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 > 0 and then - 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) + if attached {CMS_PAGE} a_node as l_page then + if attached fd.integer_item ("select_parent_node") as i_parent_node then + l_parent_id := i_parent_node.to_integer_64 + end + if + l_parent_id > 0 and then + attached {CMS_PAGE} a_response.node_api.node (l_parent_id) as l_parent_page + then + l_page.set_parent (l_parent_page) + elseif l_parent_id = -1 then + -- Set parent to Void + l_page.set_parent (Void) + end end - end --- fill_edit_form (response: NODE_RESPONSE; f: CMS_FORM; a_node: detachable CMS_NODE) --- local --- ti: WSF_FORM_TEXT_INPUT --- fset: WSF_FORM_FIELD_SET --- ta: WSF_FORM_TEXTAREA --- tselect: WSF_FORM_SELECT --- opt: WSF_FORM_SELECT_OPTION --- do --- create ti.make ("title") --- ti.set_label ("Title") --- ti.set_size (70) --- if a_node /= Void then --- ti.set_text_value (a_node.title) --- end --- ti.set_is_required (True) --- f.extend (ti) --- f.extend_html_text ("
") + new_node (response: NODE_RESPONSE; fd: WSF_FORM_DATA; a_node: detachable like new_node): like content_type.new_node + -- + do + Result := Precursor (response, fd, a_node) + if attached fd.integer_item ("select_parent_node") as l_parent_id then + if l_parent_id = -1 then + Result.set_parent (Void) + elseif attached {CMS_PAGE} response.node_api.node (l_parent_id) as l_parent then + Result.set_parent (l_parent) + end + end + end --- create ta.make ("body") --- ta.set_rows (10) --- ta.set_cols (70) --- if a_node /= Void then --- ta.set_text_value (a_node.content) --- end ----- ta.set_label ("Body") --- ta.set_description ("This is the main content") --- ta.set_is_required (False) - --- create fset.make --- fset.set_legend ("Body") --- fset.extend (ta) - --- fset.extend_html_text ("
") - --- create tselect.make ("format") --- tselect.set_label ("Body's format") --- tselect.set_is_required (True) --- across --- content_type.available_formats as c --- loop --- create opt.make (c.item.name, c.item.title) --- if attached c.item.html_help as f_help then --- opt.set_description ("
    " + f_help + "
") --- end --- tselect.add_option (opt) --- end --- if a_node /= Void and then attached a_node.format as l_format then --- tselect.set_text_by_value (l_format) --- end - --- fset.extend (tselect) - --- f.extend (fset) - --- end - --- change_node (response: NODE_RESPONSE; fd: WSF_FORM_DATA; a_node: like new_node) --- local --- b: detachable READABLE_STRING_8 --- f: detachable CONTENT_FORMAT --- do --- if attached fd.integer_item ("id") as l_id and then l_id > 0 then --- check a_node.id = l_id end --- end --- if attached fd.string_item ("title") as l_title then --- a_node.set_title (l_title) --- end - --- if attached fd.string_item ("body") as l_body then --- b := l_body --- end --- if attached fd.string_item ("format") as s_format and then attached response.api.format (s_format) as f_format then --- f := f_format --- elseif a_node /= Void and then attached a_node.format as s_format and then attached response.api.format (s_format) as f_format then --- f := f_format --- else --- f := response.api.formats.default_format --- end --- if b /= Void then --- a_node.set_content (b, Void, f.name) -- FIXME: summary --- end --- end - --- new_node (response: NODE_RESPONSE; fd: WSF_FORM_DATA; a_node: detachable like new_node): CMS_PAGE --- -- --- local --- b: detachable READABLE_STRING_8 --- f: detachable CONTENT_FORMAT --- l_node: detachable like new_node --- do --- l_node := a_node --- if attached fd.integer_item ("id") as l_id and then l_id > 0 then --- if l_node /= Void then --- check l_node.id = l_id end --- else --- if attached {like new_node} response.node_api.node (l_id) as n then --- l_node := n --- else --- -- FIXME: Error --- end --- end --- end --- if attached fd.string_item ("title") as l_title then --- if l_node = Void then --- l_node := content_type.new_node (Void) --- l_node.set_title (l_title) --- else --- l_node.set_title (l_title) --- end --- else --- if l_node = Void then --- l_node := content_type.new_node_with_title ("...", Void) --- end --- end --- l_node.set_author (response.user) - --- if attached fd.string_item ("body") as l_body then --- b := l_body --- end --- if attached fd.string_item ("format") as s_format and then attached response.api.format (s_format) as f_format then --- f := f_format --- elseif a_node /= Void and then attached a_node.format as s_format and then attached response.api.format (s_format) as f_format then --- f := f_format --- else --- f := response.api.formats.default_format --- end --- if b /= Void then --- l_node.set_content (b, Void, f.name) --- end --- Result := l_node --- end + parent_validation (a_response: NODE_RESPONSE; fd: WSF_FORM_DATA) + local + l_selected: BOOLEAN + node_api: CMS_NODE_API + l_parent_id: INTEGER_64 + do + node_api := a_response.node_api + if attached fd.integer_item ("select_parent_node") as s_parent_node then + l_parent_id := s_parent_node.to_integer_64 + else + l_parent_id := 0 + end + if + l_parent_id > 0 and then + attached node_api.node (a_response.node_id_path_parameter (a_response.request)) as l_node + then + if not a_response.location.ends_with_general ("/add_child/page") then + across + node_api.available_parents_for_node (l_node) as ic + until + l_selected + loop + if ic.item.id = l_parent_id then + l_selected := True + end + end + if not l_selected then + fd.report_invalid_field ("select_parent_node", "Invalid node id " + l_parent_id.out) + end + end + elseif l_parent_id = -1 or else l_parent_id = 0 then + -- -1 is Used to unassign 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 feature -- Output @@ -184,8 +139,20 @@ feature -- Output -- local s: STRING + node_api: CMS_NODE_API + lnk: CMS_LOCAL_LINK do + node_api := a_response.node_api Precursor (a_node, a_response) + + if a_node.has_id and then not a_node.is_trashed then + if node_api.has_permission_for_action_on_node ("create", a_node, a_response.user) then + create lnk.make ("Add Child", node_api.node_path (a_node) + "/add_child/page") + lnk.set_weight (3) + a_response.add_to_primary_tabs (lnk) + end + end + if attached a_response.main_content as l_main_content then s := l_main_content else @@ -193,11 +160,22 @@ feature -- Output end if attached {CMS_PAGE} a_node as l_node_page then + s.append ("
    ") if attached l_node_page.parent as l_parent_node then - s.append ("
    Parent page is ") - s.append (a_response.link (l_parent_node.title + " (#" + l_parent_node.id.out + ")", a_response.node_api.node_path (l_parent_node), Void)) - s.append ("
    ") + s.append ("
  • Go to parent page ") + s.append (a_response.link (l_parent_node.title, a_response.node_api.node_path (l_parent_node), Void)) + s.append ("
  • ") end + if attached node_api.children (a_node) as l_children then + across + l_children as ic + loop + s.append ("
  • ") + s.append (a_response.link (ic.item.title, a_response.node_api.node_path (ic.item), Void)) + s.append ("
  • ") + end + end + s.append ("
") end a_response.set_main_content (s) diff --git a/modules/node/handler/node_form_response.e b/modules/node/handler/node_form_response.e index 8b30fcf..80b039a 100644 --- a/modules/node/handler/node_form_response.e +++ b/modules/node/handler/node_form_response.e @@ -37,8 +37,6 @@ feature -- Execution -- Computed response message. local b: STRING_8 - f: like new_edit_form - fd: detachable WSF_FORM_DATA nid: INTEGER_64 do create b.make_empty @@ -67,6 +65,7 @@ feature -- Execution location.ends_with_general ("/add_child/page") and then has_permissions (<<"create any", "create " + l_type.name>>) then + -- FIXME: remove page dep from node module. create_new_node (l_type, b) else b.append ("

") @@ -128,10 +127,13 @@ feature {NONE} -- Create a new node f.process (Current) fd := f.last_data end - set_title ("Edit " + html_encoded (a_type.title) + " #" + l_node.id.out) + if l_node.has_id then + set_title ("Edit " + html_encoded (a_type.title) + " #" + l_node.id.out) add_to_menu (node_local_link (l_node, translation ("View", Void)), primary_tabs) add_to_menu (create {CMS_LOCAL_LINK}.make (translation ("Edit", Void), node_api.node_path (l_node) + "/edit"), primary_tabs) + else + set_title ("New " + html_encoded (a_type.title)) end f.append_to_html (wsf_theme, b) else @@ -233,7 +235,6 @@ 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 @@ -255,32 +256,6 @@ 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) @@ -322,15 +297,6 @@ feature -- Form fixme ("for now, publishing is not implemented, so let's assume any node saved is published.") -- FIXME l_node.mark_published - -- 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 - attached {CMS_PAGE} node_api.node (nid) as l_page - then - l_new_page.set_parent (l_page) - end - node_api.save_node (l_node) if attached user as u then api.log ("node", @@ -369,8 +335,6 @@ feature -- Form f: CMS_FORM ts: WSF_FORM_SUBMIT_INPUT th: WSF_FORM_HIDDEN_INPUT - ti: WSF_FORM_NUMBER_INPUT - l_item: CMS_NODE do create f.make (a_url, a_name) create th.make ("node-id") @@ -382,29 +346,6 @@ feature -- Form f.extend (th) populate_form (a_node_type, f, a_node) - f.extend_html_text ("
") - - 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?") - 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?") - create ti.make ("select_parent_node") - ti.set_label ("Parent Node") - f.extend (ti) - f.extend_html_text ("
") - end - end - f.extend_html_text ("
") create ts.make ("op") diff --git a/modules/node/handler/node_handler.e b/modules/node/handler/node_handler.e index 1ee1d97..03d61b2 100644 --- a/modules/node/handler/node_handler.e +++ b/modules/node/handler/node_handler.e @@ -126,24 +126,29 @@ feature -- HTTP Methods then l_node := node_api.revision_node (l_nid, l_rev) end - if - l_node /= Void and then (l_rev > 0 or else l_node.is_published) - then - create view_response.make (req, res, api, node_api) - view_response.set_node (l_node) - view_response.set_revision (l_rev) - view_response.execute - elseif - attached current_user (req) as l_user and then - l_node /= Void and then ( node_api.is_author_of_node (l_user, l_node) or else api.user_api.is_admin_user (l_user)) - then - create view_response.make (req, res, api, node_api) - view_response.set_node (l_node) - view_response.set_revision (l_rev) - view_response.execute - else - + if l_node = Void then send_not_found (req, res) + else + if + l_rev > 0 or else l_node.is_published + then + create view_response.make (req, res, api, node_api) + view_response.set_node (l_node) + view_response.set_revision (l_rev) + view_response.execute + elseif + attached current_user (req) as l_user and then + ( node_api.is_author_of_node (l_user, l_node) + or else api.user_api.user_has_permission (l_user, "view unpublished " + l_node.content_type) + ) + then + create view_response.make (req, res, api, node_api) + view_response.set_node (l_node) + view_response.set_revision (l_rev) + view_response.execute + else + send_access_denied (req, res) + end end else -- redirect_to (req.absolute_script_url ("/node/"), res) -- New node. diff --git a/modules/node/handler/node_view_response.e b/modules/node/handler/node_view_response.e index 10aa4bd..1faf51e 100644 --- a/modules/node/handler/node_view_response.e +++ b/modules/node/handler/node_view_response.e @@ -72,7 +72,6 @@ feature -- Execution attached node_api.node_type_webform_manager (l_content_type) as l_manager then l_manager.append_html_output_to (l_node, Current) - add_to_primary_tabs (create {CMS_LOCAL_LINK}.make ("Add Child", node_api.node_path (l_node) + "/add_child/page")) end elseif revision > 0 then set_main_content ("Missing revision node!") diff --git a/modules/node/persistence/cms_node_storage_i.e b/modules/node/persistence/cms_node_storage_i.e index 7be4201..688753e 100644 --- a/modules/node/persistence/cms_node_storage_i.e +++ b/modules/node/persistence/cms_node_storage_i.e @@ -117,9 +117,19 @@ feature -- Access deferred end +feature -- Access: outline + + children (a_node: CMS_NODE): detachable LIST [CMS_NODE] + -- Children of node `a_node'. + -- note: this is the partial version of the nodes. + deferred + end + available_parents_for_node (a_node: CMS_NODE): LIST [CMS_NODE] -- Given the node `a_node', return the list of possible parent nodes id deferred + ensure + a_node_excluded: across Result as ic all not a_node.same_node (ic.item) end end feature -- Change: Node diff --git a/modules/node/persistence/cms_node_storage_null.e b/modules/node/persistence/cms_node_storage_null.e index d15fe6f..497c11a 100644 --- a/modules/node/persistence/cms_node_storage_null.e +++ b/modules/node/persistence/cms_node_storage_null.e @@ -86,6 +86,13 @@ feature -- Access: node create {ARRAYED_LIST [CMS_USER]} Result.make (0) end +feature -- Access: outline + + children (a_node: CMS_NODE): detachable LIST [CMS_NODE] + -- + do + end + available_parents_for_node (a_node: CMS_NODE): LIST [CMS_NODE] -- do diff --git a/modules/node/persistence/cms_node_storage_sql.e b/modules/node/persistence/cms_node_storage_sql.e index 8cc17af..ee4d821 100644 --- a/modules/node/persistence/cms_node_storage_sql.e +++ b/modules/node/persistence/cms_node_storage_sql.e @@ -255,6 +255,32 @@ feature -- Access -- end end +feature -- Access: outline + + children (a_node: CMS_NODE): detachable 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 + ".children") + + from + create l_parameters.make (1) + l_parameters.put (a_node.id, "nid") + sql_query (sql_select_children_of_node, l_parameters) + sql_start + until + sql_after + loop + if attached fetch_node as l_node then + Result.force (l_node) + end + sql_forth + end + end available_parents_for_node (a_node: CMS_NODE): LIST [CMS_NODE] -- @@ -482,7 +508,17 @@ 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 GROUP BY pn_1.nid, pn_1.revision;" + sql_select_available_parents_for_node : STRING = "[ + SELECT node.nid, node.revision, node.type, title, summary, content, format, author, publish, created, changed, status + FROM nodes node LEFT JOIN page_nodes pn ON node.nid = pn.nid AND node.nid != :nid + WHERE node.nid != :nid AND pn.parent != :nid AND node.status != -1 GROUP BY node.nid, node.revision; + ]" + + sql_select_children_of_node: STRING = "[ + SELECT node.nid, node.revision, node.type, title, summary, content, format, author, publish, created, changed, status + FROM nodes node LEFT JOIN page_nodes pn ON node.nid = pn.nid + WHERE pn.parent = :nid AND node.status != -1 GROUP BY node.nid, node.revision; + ]" feature {NONE} -- Sql Queries: USER_ROLES collaborators, author