diff --git a/library/configuration/src/json_config.e b/library/configuration/src/json_config.e index 339c38f..8e3a5d9 100644 --- a/library/configuration/src/json_config.e +++ b/library/configuration/src/json_config.e @@ -148,7 +148,9 @@ feature -- Access -- `k' can be a single name such as "foo", -- or a qualified name such as "foo.bar" (assuming that "foo" is associated with a JSON object). do - if attached json_value as obj then + if k.is_empty then + Result := json_value + elseif attached json_value as obj then Result := object_json_value (obj, k.to_string_32) end end diff --git a/modules/blog/handler/blog_handler.e b/modules/blog/handler/blog_handler.e index 731a58e..d483133 100644 --- a/modules/blog/handler/blog_handler.e +++ b/modules/blog/handler/blog_handler.e @@ -156,6 +156,7 @@ feature -- HTML Output local n: CMS_NODE lnk: CMS_LOCAL_LINK + l_hide: BOOLEAN do -- Output the title. If more than one page, also output the current page number append_page_title_html_to (page, a_output) @@ -169,25 +170,42 @@ feature -- HTML Output posts as ic loop n := ic.item - lnk := blog_api.node_api.node_link (n) - a_output.append ("
  • ") + l_hide := not n.is_published + if l_hide then + if + attached api.user as u + then + if api.user_api.is_admin_user (u) then + l_hide := False + else + l_hide := not u.same_as (n.author) + end + end + end + if not l_hide then + lnk := blog_api.node_api.node_link (n) + a_output.append ("
  • ") - -- Output the creation date - append_creation_date_html_to (n, a_output) + if not n.is_published then + a_output.append ("
    This entry is not yet published!
    ") + end + -- Output the creation date + append_creation_date_html_to (n, a_output) - -- Output the author of the post - append_author_html_to (n, page, a_output) + -- Output the author of the post + append_author_html_to (n, page, a_output) - -- Output the title of the post as a link (to the detail page) - append_title_html_to (n, page, a_output) + -- Output the title of the post as a link (to the detail page) + append_title_html_to (n, page, a_output) - -- Output associated tags. - append_taxonomy_html_to (n, page, a_output) + -- Output associated tags. + append_taxonomy_html_to (n, page, a_output) - -- Output the summary of the post and a more link to the detail page - append_summary_html_to (n, page, a_output) + -- Output the summary of the post and a more link to the detail page + append_summary_html_to (n, page, a_output) - a_output.append ("
  • %N") + a_output.append ("%N") + end end -- End of post list diff --git a/modules/embedded_video/src/video_content_filter.e b/modules/embedded_video/src/video_content_filter.e index c445aed..3a28e8d 100644 --- a/modules/embedded_video/src/video_content_filter.e +++ b/modules/embedded_video/src/video_content_filter.e @@ -70,10 +70,10 @@ feature -- Settings change feature -- Conversion - filter (a_text: STRING_8) + filter (a_text: STRING_GENERAL) -- [video:url width:X height:Y] local - l_new: detachable STRING + l_new: detachable STRING_GENERAL i,p,q,diff: INTEGER do from @@ -88,7 +88,7 @@ feature -- Conversion if l_new /= Void then diff := l_new.count - (q - p + 1) i := i + diff - a_text.replace_substring (l_new, p, q) + replace_substring (a_text, l_new, p, q) else i := q + 1 end @@ -99,23 +99,23 @@ feature -- Conversion end end - to_embedded_video_code (a_text: STRING_8; a_lower, a_upper: INTEGER): detachable STRING + to_embedded_video_code (a_text: STRING_GENERAL; a_lower, a_upper: INTEGER): detachable STRING_GENERAL require a_lower < a_upper a_text.substring (a_lower, a_lower + 7).same_string ("[video:") - a_text.ends_with_general ("]") + a_text.ends_with ("]") local i,j,n: INTEGER - s,k,v: STRING_8 - l_url, l_att: STRING_8 - l_width, l_height, l_extra: detachable STRING + s,k,v: STRING_GENERAL + l_url, l_att: STRING_GENERAL + l_width, l_height, l_extra: detachable STRING_GENERAL do s := a_text.substring (a_lower + 7, a_upper - 1) s.left_adjust i := next_space_position (s, 1) if i > 0 then l_url := s.head (i - 1) - s.remove_head (i) + remove_head (s, i) s.left_adjust from n := s.count @@ -128,7 +128,7 @@ feature -- Conversion k := s.head (j - 1) k.left_adjust k.right_adjust - s.remove_head (j) + remove_head (s, j) s.left_adjust i := 1 n := s.count @@ -137,13 +137,13 @@ feature -- Conversion v := s.head (j - 1) v.left_adjust v.right_adjust - s.remove_head (j) + remove_head (s, j) s.left_adjust else v := s.substring (i, n) v.left_adjust v.right_adjust - s.wipe_out + wipe_out (s) end n := s.count i := 1 @@ -177,40 +177,46 @@ feature -- Conversion l_height := default_height.out end end - create l_att.make_empty + create {STRING_8} l_att.make_empty if l_width /= Void then if not l_att.is_empty then - l_att.append_character (' ') + append_character (l_att, ' ') end l_att.append ("width=%"") l_att.append (l_width) - l_att.append_character ('%"') + append_character (l_att, '%"') end if l_height /= Void then if not l_att.is_empty then - l_att.append_character (' ') + append_character (l_att, ' ') end l_att.append ("height=%"") l_att.append (l_height) - l_att.append_character ('%"') + append_character (l_att, '%"') end if l_extra /= Void and then not l_extra.is_empty then if not l_att.is_empty and not l_extra[1].is_space then - l_att.append_character (' ') + append_character (l_att, ' ') end l_att.append (l_extra) end - if attached template as tpl then - create Result.make_from_string (tpl) - Result.replace_substring_all ("$url", l_url) - Result.replace_substring_all ("$att", l_att) + if attached {STRING_8} a_text then + create {STRING_8} Result.make_empty else - create Result.make_from_string ("") @@ -218,7 +224,7 @@ feature -- Conversion end end - next_space_position (a_text: STRING; a_start_index: INTEGER): INTEGER + next_space_position (a_text: READABLE_STRING_GENERAL; a_start_index: INTEGER): INTEGER local n: INTEGER do @@ -235,23 +241,52 @@ feature -- Conversion end end - next_non_space_position (a_text: STRING; a_start_index: INTEGER): INTEGER - local - n: INTEGER +feature {NONE} -- Implementation + + replace_substring (a_text: STRING_GENERAL; s: READABLE_STRING_GENERAL; start_index, end_index: INTEGER_32) do - from - Result := a_start_index - n := a_text.count - until - not a_text[Result].is_space or Result > n - loop - Result := Result + 1 - end - if Result > n then - Result := 0 + if attached {STRING_8} a_text as s8 then + s8.replace_substring (s.to_string_8, start_index, end_index) + elseif attached {STRING_32} s as s32 then + s32.replace_substring (s.as_string_32, start_index, end_index) + end + end + + replace_substring_all (s: STRING_GENERAL; a_old: READABLE_STRING_8; a_new: STRING_GENERAL) + do + if attached {STRING_8} s as s8 then + s8.replace_substring_all (a_old, a_new.to_string_8) + elseif attached {STRING_32} s as s32 then + s32.replace_substring_all (a_old, a_new) + end + end + + append_character (s: STRING_GENERAL; c: CHARACTER) + do + s.append_code (c.natural_32_code) + end + + wipe_out (s: STRING_GENERAL) + do + if attached {STRING_8} s as s8 then + s8.wipe_out + elseif attached {STRING_32} s as s32 then + s32.wipe_out + else + s.keep_tail (0) + end + end + + remove_head (s: STRING_GENERAL; n: INTEGER) + do + if attached {STRING_8} s as s8 then + s8.remove_head (n) + elseif attached {STRING_32} s as s32 then + s32.remove_head (n) + else + s.keep_tail (s.count - n) end end -invariant end diff --git a/modules/embedded_video/test/test_content_filter_set.e b/modules/embedded_video/test/test_content_filter_set.e index a9073a0..6a44f4a 100644 --- a/modules/embedded_video/test/test_content_filter_set.e +++ b/modules/embedded_video/test/test_content_filter_set.e @@ -29,6 +29,30 @@ feature -- Test routines assert ("expected iframe with video", text.same_string (expected_text)) end + test_video_filter_01_multi + -- New test routine + local + f: VIDEO_CONTENT_FILTER + text: STRING + expected_text: STRING + do + text := "[ + [video:https://www.youtube.com/embed/jBMOSSnCMCk] + and [video:https://www.youtube.com/embed/jBMOSSnCMCk] + and [video:https://www.youtube.com/embed/jBMOSSnCMCk] + done + ]" + expected_text := "[ + + and + and + done + ]" + create f + f.filter (text) + assert ("expected iframe with video", text.same_string (expected_text)) + end + test_video_filter_02 -- New test routine diff --git a/modules/node/handler/cms_node_type_webform_manager_i.e b/modules/node/handler/cms_node_type_webform_manager_i.e index 78337f7..9eecd96 100644 --- a/modules/node/handler/cms_node_type_webform_manager_i.e +++ b/modules/node/handler/cms_node_type_webform_manager_i.e @@ -88,6 +88,11 @@ feature -- Output a_response.set_value (a_node, "node") a_response.set_value (a_node.content_type, "optional_content_type") create s.make_empty + if a_node.is_not_published then + a_response.add_warning_message ("This node is NOT published!") + elseif a_node.is_trashed then + a_response.add_warning_message ("This node is in the TRASH!") + end append_content_as_html_to (a_node, False, s, a_response) a_response.set_main_content (s) end diff --git a/modules/node/handler/node_form_response.e b/modules/node/handler/node_form_response.e index 2389be8..c554ef8 100644 --- a/modules/node/handler/node_form_response.e +++ b/modules/node/handler/node_form_response.e @@ -254,15 +254,25 @@ feature -- Form edit_form_submit (fd: WSF_FORM_DATA; a_node: detachable CMS_NODE; a_type: CMS_NODE_TYPE [CMS_NODE]; b: STRING) local - l_preview: BOOLEAN + l_preview, l_op_save, l_op_publish, l_op_unpublish: BOOLEAN l_node: detachable CMS_NODE s: STRING l_node_path: READABLE_STRING_8 l_path_alias, l_existing_path_alias, l_auto_path_alias: detachable READABLE_STRING_8 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") + fixme ("Refactor code per operation: Preview, Save/Publish/UnPublish") + l_preview := attached {WSF_STRING} fd.item ("op") as l_op and then l_op.same_string (preview_submit_label) if not l_preview then + l_op_save := True + if attached {WSF_STRING} fd.item ("op") as l_op then + if l_op.same_string (publish_submit_label) then + l_op_publish := True + elseif l_op.same_string (unpublish_submit_label) then + l_op_unpublish := True + else + check l_op.same_string (save_submit_label) end + end + end debug ("cms") across fd as c @@ -289,8 +299,13 @@ feature -- Form end fixme ("for now, publishing is not implemented, so let's assume any node saved is published.") -- FIXME - l_node.mark_published - + if l_op_publish then + l_node.mark_published + elseif l_op_unpublish then + l_node.mark_not_published + else + -- Default status + end node_api.save_node (l_node) if attached user as u then api.log ("node", @@ -362,6 +377,7 @@ feature -- Form f: CMS_FORM ts: WSF_FORM_SUBMIT_INPUT th: WSF_FORM_HIDDEN_INPUT + div: WSF_WIDGET_DIV do create f.make (a_url, a_name) create th.make ("node-id") @@ -375,18 +391,50 @@ feature -- Form populate_form (a_node_type, f, a_node) f.extend_html_text ("
    ") - create ts.make ("op") - ts.set_default_value ("Save") - f.extend (ts) + + create div.make + div.add_css_class ("css-editing-buttons") + f.extend (div) create ts.make ("op") - ts.set_default_value ("Preview") - f.extend (ts) + ts.set_default_value (preview_submit_label) + ts.set_description ("Preview without saving.") + div.extend (ts) + if a_node = Void then + create ts.make ("op") + ts.set_default_value (save_submit_label) + div.extend (ts) + + create ts.make ("op") + ts.set_default_value (publish_submit_label) + ts.set_description ("Save and mark published.") + div.extend (ts) + else + if a_node.is_published then + create ts.make ("op") + ts.set_default_value (save_submit_label) + ts.set_description ("Save and keep published.") + div.extend (ts) + + create ts.make ("op") + ts.set_default_value (unpublish_submit_label) + ts.set_description ("Save and mark unpublished.") + div.extend (ts) + else + create ts.make ("op") + ts.set_default_value (save_submit_label) + div.extend (ts) + + create ts.make ("op") + ts.set_default_value (publish_submit_label) + ts.set_description ("Save and mark published.") + div.extend (ts) + end + end Result := f end - new_delete_form (a_node: detachable CMS_NODE; a_url: READABLE_STRING_8; a_name: STRING; a_node_type: CMS_NODE_TYPE [CMS_NODE]): CMS_FORM -- Create a web form named `a_name' for node `a_node' (if set), using form action url `a_url', and for type of node `a_node_type'. require @@ -487,4 +535,11 @@ feature -- Form end end +feature -- Labels + + save_submit_label: STRING = "Save" + publish_submit_label: STRING = "Publish" + unpublish_submit_label: STRING = "Unpublish" + preview_submit_label: STRING = "Preview" + end diff --git a/modules/node/handler/node_handler.e b/modules/node/handler/node_handler.e index 19c3c98..f27056f 100644 --- a/modules/node/handler/node_handler.e +++ b/modules/node/handler/node_handler.e @@ -84,6 +84,8 @@ feature -- HTTP Methods l_nid, l_rev: INTEGER_64 edit_response: NODE_FORM_RESPONSE view_response: NODE_VIEW_RESPONSE + l_is_published: BOOLEAN + l_is_denied: BOOLEAN do if req.percent_encoded_path_info.ends_with ("/edit") then check valid_url: req.percent_encoded_path_info.starts_with ("/node/") end @@ -119,19 +121,26 @@ feature -- HTTP Methods l_rev := p_rev.value.to_integer_64 end l_node := node_api.node (l_nid) - if - l_node /= Void and then - l_rev > 0 and then - l_rev < l_node.revision and then - node_api.has_permission_for_action_on_node ("view revisions", l_node, api.user) - then - l_node := node_api.revision_node (l_nid, l_rev) + if l_node /= Void then + l_is_published := l_node.is_published + if + l_rev > 0 and then + l_rev < l_node.revision + then + if node_api.has_permission_for_action_on_node ("view revisions", l_node, api.user) then + l_node := node_api.revision_node (l_nid, l_rev) + else + l_is_denied := True + end + end end - if l_node = Void then + if l_is_denied then + send_access_denied (req, res) + elseif l_node = Void then send_not_found (req, res) else if - l_rev > 0 or else l_node.is_published + l_rev > 0 and l_is_published then create view_response.make (req, res, api, node_api) view_response.set_node (l_node) @@ -148,7 +157,7 @@ feature -- HTTP Methods view_response.set_revision (l_rev) view_response.execute else - send_access_denied (req, res) + send_access_denied_to_unpublished_node (req, res, l_node) end end else @@ -392,6 +401,17 @@ feature -- Error l_page.execute end + send_access_denied_to_unpublished_node (req: WSF_REQUEST; res: WSF_RESPONSE; a_node: CMS_NODE) + -- Forbidden response. + local + r: CMS_RESPONSE + do + create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api) + r.set_main_content ("This content is NOT published!") + r.execute + end + + feature {NONE} -- Node create_new_node (req: WSF_REQUEST; res: WSF_RESPONSE) diff --git a/src/service/cms_api.e b/src/service/cms_api.e index 3442596..ea5aca5 100644 --- a/src/service/cms_api.e +++ b/src/service/cms_api.e @@ -248,11 +248,8 @@ feature {CMS_API_ACCESS} -- CMS Formats management -- Save `formats`. local f: CMS_FORMAT - jp: JSON_PARSER - cfg: JSON_CONFIG j,ji: JSON_OBJECT s: STRING_32 - l_name, l_title: READABLE_STRING_8 ct: CMS_CONTENT_TYPE do -- { "plain_text": { "title": "Plain text", "filters": "plain_text+foobar+toto"}, ...}