From 44d14c41001d0bb5d1ebd3142aabccc60e511483 Mon Sep 17 00:00:00 2001 From: jvelilla Date: Wed, 13 May 2015 12:27:02 -0300 Subject: [PATCH 01/27] delete with tabs --- .../handler/cms_node_type_webform_manager.e | 11 ++++++++++ modules/node/handler/node_form_response.e | 20 +++++++++---------- modules/node/node_module.e | 3 +++ 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/modules/node/handler/cms_node_type_webform_manager.e b/modules/node/handler/cms_node_type_webform_manager.e index 88161a4..5c99396 100644 --- a/modules/node/handler/cms_node_type_webform_manager.e +++ b/modules/node/handler/cms_node_type_webform_manager.e @@ -167,6 +167,17 @@ feature -- Output lnk.set_weight (2) a_response.add_to_primary_tabs (lnk) + if + a_node /= Void and then + a_node.id > 0 and then + attached node_api.node_type_for (a_node) as l_type and then + a_response.has_permission ("delete " + node_api.permission_scope (a_response.current_user (a_response.request), a_node) + " " + l_type.name) + then + create lnk.make ("Delete", node_api.node_path (a_node) + "/delete") + lnk.set_weight (3) + a_response.add_to_primary_tabs (lnk) + end + create s.make_empty s.append ("
") if attached a_node.author as l_author then diff --git a/modules/node/handler/node_form_response.e b/modules/node/handler/node_form_response.e index 8ade0b6..c39c5c0 100644 --- a/modules/node/handler/node_form_response.e +++ b/modules/node/handler/node_form_response.e @@ -61,13 +61,13 @@ feature -- Execution -- FIXME: Hack for now set_title (l_node.title) add_to_menu (create {CMS_LOCAL_LINK}.make ("View", node_url (l_node)), primary_tabs) + add_to_menu (create {CMS_LOCAL_LINK}.make ("Delete", "/node/" + l_node.id.out + "/delete"), primary_tabs) add_to_menu (create {CMS_LOCAL_LINK}.make ("Edit", "/node/" + l_node.id.out + "/edit"), primary_tabs) - b.append (html_encoded (l_type.title) + " saved") else set_title ("Edit " + html_encoded (l_type.title) + " #" + l_node.id.out) - add_to_menu (create {CMS_LOCAL_LINK}.make ("View", node_url (l_node)), primary_tabs) + add_to_menu (create {CMS_LOCAL_LINK}.make ("Delete", "/node/" + l_node.id.out + "/delete"), primary_tabs) add_to_menu (create {CMS_LOCAL_LINK}.make ("Edit", "/node/" + l_node.id.out + "/edit"), primary_tabs) f.append_to_html (wsf_theme, b) @@ -228,14 +228,14 @@ feature -- Form ts.set_default_value ("Preview") f.extend (ts) - if a_node /= Void and then a_node.id > 0 and then has_permission ("delete " + a_name) then - create ts.make ("op") - ts.set_default_value ("Delete") - fixme ("[ - ts.set_default_value (i18n ("Delete"))i18n or other name such as "translated" or "translation - ]") - f.extend (ts) - end +-- if a_node /= Void and then a_node.id > 0 and then has_permission ("delete " + a_name) then +-- create ts.make ("op") +-- ts.set_default_value ("Delete") +-- fixme ("[ +-- ts.set_default_value (i18n ("Delete"))i18n or other name such as "translated" or "translation +-- ]") +-- f.extend (ts) +-- end Result := f end diff --git a/modules/node/node_module.e b/modules/node/node_module.e index ba6ca2d..2a5272b 100644 --- a/modules/node/node_module.e +++ b/modules/node/node_module.e @@ -177,6 +177,9 @@ feature -- Hooks create lnk.make ("List of nodes", a_response.url ("/nodes", Void)) a_menu_system.primary_menu.extend (lnk) + create lnk.make ("Trash nodes", a_response.url ("/trash", Void)) + a_menu_system.primary_menu.extend (lnk) + create lnk.make ("Create ..", a_response.url ("/node/", Void)) a_menu_system.primary_menu.extend (lnk) end From 57bf5ad0dce2f55da3ec08c67305db540d654524 Mon Sep 17 00:00:00 2001 From: jvelilla Date: Wed, 13 May 2015 15:17:19 -0300 Subject: [PATCH 02/27] Added delete option as a tab only if the current user has permissions to delete the current resource --- .../handler/cms_node_type_webform_manager.e | 2 +- modules/node/handler/node_form_response.e | 51 +++++++++++++++++-- modules/node/handler/node_handler.e | 10 ++-- modules/node/node_module.e | 1 + 4 files changed, 57 insertions(+), 7 deletions(-) diff --git a/modules/node/handler/cms_node_type_webform_manager.e b/modules/node/handler/cms_node_type_webform_manager.e index eda76d9..5d991e9 100644 --- a/modules/node/handler/cms_node_type_webform_manager.e +++ b/modules/node/handler/cms_node_type_webform_manager.e @@ -192,7 +192,7 @@ feature -- Output a_node /= Void and then a_node.id > 0 and then attached node_api.node_type_for (a_node) as l_type and then - a_response.has_permission ("delete " + node_api.permission_scope (a_response.current_user (a_response.request), a_node) + " " + l_type.name) + node_api.has_permission_for_action_on_node ("delete", a_node, a_response.current_user (a_response.request)) then create lnk.make ("Delete", node_api.node_path (a_node) + "/delete") lnk.set_weight (3) diff --git a/modules/node/handler/node_form_response.e b/modules/node/handler/node_form_response.e index 40b14dd..598a09b 100644 --- a/modules/node/handler/node_form_response.e +++ b/modules/node/handler/node_form_response.e @@ -48,7 +48,11 @@ feature -- Execution attached node_api.node (nid) as l_node then if attached node_api.node_type_for (l_node) as l_type then - if node_api.has_permission_for_action_on_node ("edit", l_node, current_user (request)) then + fixme ("refactor: process_edit, process_create porcess edit") + if + request.path_info.ends_with_general ("/edit") and then + node_api.has_permission_for_action_on_node ("edit", l_node, current_user (request)) + then f := new_edit_form (l_node, url (request.path_info, Void), "edit-" + l_type.name, l_type) invoke_form_alter (f, fd) if request.is_post_request_method then @@ -71,6 +75,30 @@ feature -- Execution set_title (formatted_string (translation ("Edit $1 #$2", Void), [l_type.title, l_node.id])) f.append_to_html (wsf_theme, b) end + elseif + request.path_info.ends_with_general ("/delete") and then + node_api.has_permission_for_action_on_node ("delete", l_node, current_user (request)) + then + f := new_delete_form (l_node, url (request.path_info, Void), "delete-" + l_type.name, l_type) + invoke_form_alter (f, fd) + if request.is_post_request_method then + f.process (Current) + fd := f.last_data + end + if l_node.has_id then + add_to_menu (create {CMS_LOCAL_LINK}.make (translation ("View", Void), node_url (l_node)), primary_tabs) + add_to_menu (create {CMS_LOCAL_LINK}.make (translation ("Edit", Void), "/node/" + l_node.id.out + "/edit"), primary_tabs) + add_to_menu (create {CMS_LOCAL_LINK}.make ("Delete", "/node/" + l_node.id.out + "/delete"), primary_tabs) + end + + if attached redirection as l_location then + -- FIXME: Hack for now + set_title (l_node.title) + b.append (html_encoded (l_type.title) + " deleted") + else + set_title (formatted_string (translation ("Delete $1 #$2", Void), [l_type.title, l_node.id])) + f.append_to_html (wsf_theme, b) + end else b.append ("

") b.append (translation ("Access denied", Void)) @@ -244,10 +272,25 @@ feature -- Form ts.set_default_value ("Preview") f.extend (ts) + 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'. + local + f: CMS_FORM + ts: WSF_FORM_SUBMIT_INPUT + do + create f.make (a_url, a_name) + + f.extend_html_text ("
") + f.extend_html_text ("Are you sure you want to delete?") + + -- TODO check if we need to check for has_permissions!! if a_node /= Void and then - a_node.id > 0 and then - has_permission ("delete " + a_name) + a_node.id > 0 then create ts.make ("op") ts.set_default_value ("Delete") @@ -255,6 +298,8 @@ feature -- Form ts.set_default_value (translation ("Delete")) ]") f.extend (ts) + fixme ("wsf_html: add support for HTML5 input attributes!!! ") + f.extend_html_text("" ) end Result := f diff --git a/modules/node/handler/node_handler.e b/modules/node/handler/node_handler.e index de50f39..5ef662d 100644 --- a/modules/node/handler/node_handler.e +++ b/modules/node/handler/node_handler.e @@ -89,6 +89,10 @@ feature -- HTTP Methods check valid_url: req.path_info.starts_with_general ("/node/") end create edit_response.make (req, res, api, node_api) edit_response.execute + elseif req.path_info.ends_with_general ("/delete") then + check valid_url: req.path_info.starts_with_general ("/node/") end + create edit_response.make (req, res, api, node_api) + edit_response.execute else -- Display existing node l_nid := node_id_path_parameter (req) @@ -116,14 +120,14 @@ feature -- HTTP Methods do fixme ("Refactor code: extract methods: edit_node and add_node") if req.path_info.ends_with_general ("/edit") then + create edit_response.make (req, res, api, node_api) + edit_response.execute + elseif req.path_info.ends_with_general ("/delete") then if attached {WSF_STRING} req.form_parameter ("op") as l_op and then l_op.value.same_string ("Delete") then do_delete (req, res) - else - create edit_response.make (req, res, api, node_api) - edit_response.execute end elseif req.path_info.starts_with_general ("/node/add/") then create edit_response.make (req, res, api, node_api) diff --git a/modules/node/node_module.e b/modules/node/node_module.e index 65b07f1..2f49c9c 100644 --- a/modules/node/node_module.e +++ b/modules/node/node_module.e @@ -135,6 +135,7 @@ feature -- Access: router a_router.handle_with_request_methods ("/node/add/{type}", l_node_handler, a_router.methods_get_post) a_router.handle_with_request_methods ("/node/{id}/edit", l_node_handler, a_router.methods_get_post) + a_router.handle_with_request_methods ("/node/{id}/delete", l_node_handler, a_router.methods_get_post) a_router.handle_with_request_methods ("/node/{id}", l_node_handler, a_router.methods_get) -- For now: no REST API handling... a_router.methods_get_put_delete + a_router.methods_get_post) From 9fbadac7aca771227a1b35968f945c4d82700b54 Mon Sep 17 00:00:00 2001 From: jvelilla Date: Thu, 14 May 2015 11:07:15 -0300 Subject: [PATCH 03/27] Added trash feature: Remove or revert a node. Added Handler to show the current trash nodes for a given user. An admin can see all the trash nodes. Updated storage to handle trash and revert nodes. --- modules/node/cms_node_api.e | 23 ++++++ .../handler/cms_node_type_webform_manager.e | 31 ++++--- modules/node/handler/node_form_response.e | 64 +++++++++++++++ modules/node/handler/node_handler.e | 72 +++++++++++++++++ modules/node/handler/trash_handler.e | 78 ++++++++++++++++++ modules/node/node_module.e | 9 +++ modules/node/persistence/cms_node_storage_i.e | 35 ++++++++ .../node/persistence/cms_node_storage_null.e | 16 ++++ .../node/persistence/cms_node_storage_sql.e | 80 ++++++++++++++++++- src/persistence/sql/cms_storage_sql_builder.e | 6 ++ 10 files changed, 401 insertions(+), 13 deletions(-) create mode 100644 modules/node/handler/trash_handler.e diff --git a/modules/node/cms_node_api.e b/modules/node/cms_node_api.e index 8f0a8d9..2e8caf4 100644 --- a/modules/node/cms_node_api.e +++ b/modules/node/cms_node_api.e @@ -212,6 +212,14 @@ feature -- Access: Node Result := node_storage.nodes end + + trash_nodes (a_user: CMS_USER): LIST [CMS_NODE] + -- List of nodes with status in {CMS_NODE_API}.trashed. + -- if the current user is admin, it will retrieve all the trashed nodes + do + Result := node_storage.trash_nodes (a_user.id) + end + recent_nodes (a_offset, a_rows: INTEGER): LIST [CMS_NODE] -- List of the `a_rows' most recent nodes starting from `a_offset'. do @@ -316,6 +324,21 @@ feature -- Change: Node node_storage.update_node (a_node) end + trash_node (a_node: CMS_NODE) + -- Trash node `a_node'. + --! remove the node from the storage. + do + node_storage.trash_node (a_node) + end + + + revert_node (a_node: CMS_NODE) + -- Revert node `a_node'. + -- From {CMS_NODE_API}.trashed to {CMS_NODE_API}.not_published. + do + node_storage.revert_node (a_node) + end + feature -- Node status diff --git a/modules/node/handler/cms_node_type_webform_manager.e b/modules/node/handler/cms_node_type_webform_manager.e index 5d991e9..fd90c12 100644 --- a/modules/node/handler/cms_node_type_webform_manager.e +++ b/modules/node/handler/cms_node_type_webform_manager.e @@ -182,21 +182,28 @@ feature -- Output a_response.add_variable (a_node, "node") create lnk.make (a_response.translation ("View", Void), a_response.node_local_link (a_node).location) lnk.set_weight (1) - - a_response.add_to_primary_tabs (lnk) - create lnk.make ("Edit", node_api.node_path (a_node) + "/edit") - lnk.set_weight (2) a_response.add_to_primary_tabs (lnk) - if - a_node /= Void and then - a_node.id > 0 and then - attached node_api.node_type_for (a_node) as l_type and then - node_api.has_permission_for_action_on_node ("delete", a_node, a_response.current_user (a_response.request)) - then - create lnk.make ("Delete", node_api.node_path (a_node) + "/delete") - lnk.set_weight (3) + if a_node.status = {CMS_NODE_API}.trashed then + create lnk.make ("Trash", node_api.node_path (a_node) + "/trash") + lnk.set_weight (2) a_response.add_to_primary_tabs (lnk) + else + -- 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) + a_response.add_to_primary_tabs (lnk) + + if + a_node /= Void and then + a_node.id > 0 and then + attached node_api.node_type_for (a_node) as l_type and then + node_api.has_permission_for_action_on_node ("delete", a_node, a_response.current_user (a_response.request)) + then + create lnk.make ("Delete", node_api.node_path (a_node) + "/delete") + lnk.set_weight (3) + a_response.add_to_primary_tabs (lnk) + end end create s.make_empty diff --git a/modules/node/handler/node_form_response.e b/modules/node/handler/node_form_response.e index 598a09b..dc57770 100644 --- a/modules/node/handler/node_form_response.e +++ b/modules/node/handler/node_form_response.e @@ -99,6 +99,29 @@ feature -- Execution set_title (formatted_string (translation ("Delete $1 #$2", Void), [l_type.title, l_node.id])) f.append_to_html (wsf_theme, b) end + elseif + request.path_info.ends_with_general ("/trash") and then + node_api.has_permission_for_action_on_node ("trash", l_node, current_user (request)) + then + f := new_trash_form (l_node, url (request.path_info, Void), "trash-" + l_type.name, l_type) + invoke_form_alter (f, fd) + if request.is_post_request_method then + f.process (Current) + fd := f.last_data + end + if l_node.has_id then + add_to_menu (create {CMS_LOCAL_LINK}.make (translation ("View", Void), node_url (l_node)), primary_tabs) + add_to_menu (create {CMS_LOCAL_LINK}.make ("Trash", "/node/" + l_node.id.out + "/trash"), primary_tabs) + end + + if attached redirection as l_location then + -- FIXME: Hack for now + set_title (l_node.title) + b.append (html_encoded (l_type.title) + " trasged") + else + set_title (formatted_string (translation ("Trash $1 #$2", Void), [l_type.title, l_node.id])) + f.append_to_html (wsf_theme, b) + end else b.append ("

") b.append (translation ("Access denied", Void)) @@ -305,6 +328,47 @@ feature -- Form Result := f end + + new_trash_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'. + local + f: CMS_FORM + ts: WSF_FORM_SUBMIT_INPUT + do + create f.make (a_url, a_name) + + f.extend_html_text ("
") + f.extend_html_text ("Are you sure you want to trash the current node?") + if + a_node /= Void and then + a_node.id > 0 + then + create ts.make ("op") + ts.set_default_value ("Trash") + fixme ("[ + ts.set_default_value (translation ("Trash")) + ]") + f.extend (ts) + end + f.extend_html_text ("
") + f.extend_html_text ("Do you want to revert the current node?") + if + a_node /= Void and then + a_node.id > 0 + then + create ts.make ("op") + ts.set_default_value ("Revert") + fixme ("[ + ts.set_default_value (translation ("Revert")) + ]") + f.extend (ts) + end + Result := f + end + + + + populate_form (a_content_type: CMS_NODE_TYPE [CMS_NODE]; a_form: WSF_FORM; a_node: detachable CMS_NODE) -- Fill the web form `a_form' with data from `a_node' if set, -- and apply this to content type `a_content_type'. diff --git a/modules/node/handler/node_handler.e b/modules/node/handler/node_handler.e index 5ef662d..83ea7e6 100644 --- a/modules/node/handler/node_handler.e +++ b/modules/node/handler/node_handler.e @@ -93,6 +93,10 @@ feature -- HTTP Methods check valid_url: req.path_info.starts_with_general ("/node/") end create edit_response.make (req, res, api, node_api) edit_response.execute + elseif req.path_info.ends_with_general ("/trash") then + check valid_url: req.path_info.starts_with_general ("/node/") end + create edit_response.make (req, res, api, node_api) + edit_response.execute else -- Display existing node l_nid := node_id_path_parameter (req) @@ -129,6 +133,18 @@ feature -- HTTP Methods then do_delete (req, res) end + elseif req.path_info.ends_with_general ("/trash") then + if + attached {WSF_STRING} req.form_parameter ("op") as l_op and then + l_op.value.same_string ("Trash") + then + do_trash (req, res) + elseif + attached {WSF_STRING} req.form_parameter ("op") as l_op and then + l_op.value.same_string ("Revert") + then + do_revert (req, res) + end elseif req.path_info.starts_with_general ("/node/add/") then create edit_response.make (req, res, api, node_api) edit_response.execute @@ -178,6 +194,62 @@ feature -- HTTP Methods send_not_implemented ("REST API not yet implemented", req, res) end +feature {NONE} -- Trash:Revert + + do_trash (req: WSF_REQUEST; res: WSF_RESPONSE) + -- Trash a node from the database. + do + if attached current_user (req) as l_user then + if attached {WSF_STRING} req.path_parameter ("id") as l_id then + if + l_id.is_integer and then + attached node_api.node (l_id.integer_value) as l_node + then + if node_api.has_permission_for_action_on_node ("trash", l_node, current_user (req)) then + node_api.trash_node (l_node) + res.send (create {CMS_REDIRECTION_RESPONSE_MESSAGE}.make (req.absolute_script_url (""))) + else + send_access_denied (req, res) + -- send_not_authorized ? + end + else + do_error (req, res, l_id) + end + else + (create {INTERNAL_SERVER_ERROR_CMS_RESPONSE}.make (req, res, api)).execute + end + else + send_access_denied (req, res) + end + end + + do_revert (req: WSF_REQUEST; res: WSF_RESPONSE) + -- Revert a node: From {CMS_NODE_API}.trashed to {CMS_NODE_API}.not_published. + do + if attached current_user (req) as l_user then + if attached {WSF_STRING} req.path_parameter ("id") as l_id then + if + l_id.is_integer and then + attached node_api.node (l_id.integer_value) as l_node + then + if node_api.has_permission_for_action_on_node ("trash", l_node, current_user (req)) then + node_api.revert_node (l_node) + res.send (create {CMS_REDIRECTION_RESPONSE_MESSAGE}.make (req.absolute_script_url (""))) + else + send_access_denied (req, res) + -- send_not_authorized ? + end + else + do_error (req, res, l_id) + end + else + (create {INTERNAL_SERVER_ERROR_CMS_RESPONSE}.make (req, res, api)).execute + end + else + send_access_denied (req, res) + end + end + feature -- Error do_error (req: WSF_REQUEST; res: WSF_RESPONSE; a_id: detachable WSF_STRING) diff --git a/modules/node/handler/trash_handler.e b/modules/node/handler/trash_handler.e new file mode 100644 index 0000000..0811073 --- /dev/null +++ b/modules/node/handler/trash_handler.e @@ -0,0 +1,78 @@ +note + description: "Request handler related to /trash " + date: "$Date$" + revision: "$Revision$" + +class + TRASH_HANDLER + + +inherit + CMS_NODE_HANDLER + + WSF_URI_HANDLER + rename + new_mapping as new_uri_mapping + end + + WSF_RESOURCE_HANDLER_HELPER + redefine + do_get + end + + REFACTORING_HELPER + +create + make + +feature -- execute + + execute (req: WSF_REQUEST; res: WSF_RESPONSE) + -- Execute request handler + do + execute_methods (req, res) + end + +feature -- HTTP Methods + + do_get (req: WSF_REQUEST; res: WSF_RESPONSE) + -- + local + l_page: CMS_RESPONSE + s: STRING + n: CMS_NODE + lnk: CMS_LOCAL_LINK + do + -- At the moment the template is hardcoded, but we can + -- get them from the configuration file and load them into + -- the setup class. + + create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api) + + if attached current_user (req) as l_user then + + l_page.add_variable (node_api.trash_nodes (l_user), "nodes") + + -- NOTE: for development purposes we have the following hardcode output. + create s.make_from_string ("

Nodes:

") + if attached node_api.trash_nodes (l_user) as lst then + s.append ("
    %N") + across + lst as ic + loop + n := ic.item + lnk := node_api.node_link (n) + s.append ("
  • ") + s.append (l_page.link (lnk.title, lnk.location, Void)) + s.append ("
  • %N") + end + s.append ("
%N") + end + + l_page.set_main_content (s) + -- l_page.add_block (create {CMS_CONTENT_BLOCK}.make ("nodes_warning", Void, "/nodes/ is not yet fully implemented
", Void), "highlighted") + l_page.execute + end + end + +end diff --git a/modules/node/node_module.e b/modules/node/node_module.e index 2f49c9c..4431205 100644 --- a/modules/node/node_module.e +++ b/modules/node/node_module.e @@ -127,6 +127,7 @@ feature -- Access: router l_node_handler: NODE_HANDLER l_nodes_handler: NODES_HANDLER l_uri_mapping: WSF_URI_MAPPING + l_trash_handler: TRASH_HANDLER do -- TODO: for now, focused only on web interface, add REST api later. [2015-April-29] create l_node_handler.make (a_api, a_node_api) @@ -136,6 +137,7 @@ feature -- Access: router a_router.handle_with_request_methods ("/node/add/{type}", l_node_handler, a_router.methods_get_post) a_router.handle_with_request_methods ("/node/{id}/edit", l_node_handler, a_router.methods_get_post) a_router.handle_with_request_methods ("/node/{id}/delete", l_node_handler, a_router.methods_get_post) + a_router.handle_with_request_methods ("/node/{id}/trash", l_node_handler, a_router.methods_get_post) a_router.handle_with_request_methods ("/node/{id}", l_node_handler, a_router.methods_get) -- For now: no REST API handling... a_router.methods_get_put_delete + a_router.methods_get_post) @@ -144,6 +146,13 @@ feature -- Access: router create l_nodes_handler.make (a_api, a_node_api) create l_uri_mapping.make_trailing_slash_ignored ("/nodes", l_nodes_handler) a_router.map_with_request_methods (l_uri_mapping, a_router.methods_get) + + --Trash + + create l_trash_handler.make (a_api, a_node_api) + create l_uri_mapping.make_trailing_slash_ignored ("/trash", l_trash_handler) + a_router.map_with_request_methods (l_uri_mapping, a_router.methods_get) + end feature -- Hooks diff --git a/modules/node/persistence/cms_node_storage_i.e b/modules/node/persistence/cms_node_storage_i.e index 6090d95..e359796 100644 --- a/modules/node/persistence/cms_node_storage_i.e +++ b/modules/node/persistence/cms_node_storage_i.e @@ -70,6 +70,11 @@ feature -- Access deferred end + trash_nodes (a_user_id: INTEGER_64): LIST [CMS_NODE] + -- List of nodes by user `a_user_id'. + deferred + end + recent_nodes (a_lower: INTEGER; a_count: INTEGER): LIST [CMS_NODE] -- List of recent `a_count' nodes with an offset of `lower'. deferred @@ -135,6 +140,36 @@ feature -- Change: Node deferred end + trash_node (a_node: CMS_NODE) + -- Trash `a_node'. + do + if a_node.has_id then + trash_node_by_id (a_node.id) + end + end + + revert_node (a_node: CMS_NODE) + -- Revert `a_node'. + do + if a_node.has_id then + revert_node_by_id (a_node.id) + end + end + + trash_node_by_id (a_id: INTEGER_64) + -- Trash node by id `a_id'. + require + valid_node_id: a_id > 0 + deferred + end + + revert_node_by_id (a_id: INTEGER_64) + -- Revert node by id `a_id'. + require + valid_node_id: a_id > 0 + deferred + end + -- update_node_title (a_user_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_title: READABLE_STRING_32) -- -- Update node title to `a_title', node identified by id `a_node_id'. -- -- The user `a_user_id' is an existing or new collaborator. diff --git a/modules/node/persistence/cms_node_storage_null.e b/modules/node/persistence/cms_node_storage_null.e index 87559af..02aaeb2 100644 --- a/modules/node/persistence/cms_node_storage_null.e +++ b/modules/node/persistence/cms_node_storage_null.e @@ -41,6 +41,12 @@ feature -- Access: node create {ARRAYED_LIST [CMS_NODE]} Result.make (0) end + trash_nodes (a_user_id: INTEGER_64): LIST [CMS_NODE] + -- List of nodes by user `a_user_id'. + do + create {ARRAYED_LIST [CMS_NODE]} Result.make (0) + end + recent_nodes (a_lower: INTEGER; a_count: INTEGER): LIST [CMS_NODE] -- List of the `a_count' most recent nodes, starting from `a_lower'. do @@ -80,6 +86,16 @@ feature -- Node do end + trash_node_by_id (a_id: INTEGER_64) + -- + do + end + + revert_node_by_id (a_id: INTEGER_64) + -- + do + end + -- update_node_title (a_user_id: like {CMS_NODE}.id; a_node_id: like {CMS_NODE}.id; a_title: READABLE_STRING_32) -- -- -- do diff --git a/modules/node/persistence/cms_node_storage_sql.e b/modules/node/persistence/cms_node_storage_sql.e index 06ecadc..971f8c8 100644 --- a/modules/node/persistence/cms_node_storage_sql.e +++ b/modules/node/persistence/cms_node_storage_sql.e @@ -59,6 +59,36 @@ feature -- Access -- end end + trash_nodes (a_user_id: INTEGER_64): LIST [CMS_NODE] + -- List of nodes. + local + l_parameters: STRING_TABLE [detachable ANY] + do + create {ARRAYED_LIST [CMS_NODE]} Result.make (0) + + error_handler.reset + write_information_log (generator + ".trash_nodes") + + from + create l_parameters.make (1) + if a_user_id > 1 then + -- Not admin user + l_parameters.put (a_user_id, "author") + sql_query (sql_select_trash_nodes_by_author, l_parameters) + else + sql_query (sql_select_trash_nodes, Void) + end + sql_start + until + sql_after + loop + if attached fetch_node as l_node then + Result.force (l_node) + end + sql_forth + end + end + recent_nodes (a_lower: INTEGER; a_count: INTEGER): LIST [CMS_NODE] -- List of recent `a_count' nodes with an offset of `lower'. local @@ -147,7 +177,7 @@ feature -- Change: Node l_time: DATE_TIME do create l_time.make_now_utc - write_information_log (generator + ".delete_node") + write_information_log (generator + ".delete_node {" + a_id.out + "}") error_handler.reset create l_parameters.make (1) @@ -157,6 +187,40 @@ feature -- Change: Node sql_change (sql_delete_node, l_parameters) end + + trash_node_by_id (a_id: INTEGER_64) + -- + local + l_parameters: STRING_TABLE [ANY] + l_time: DATE_TIME + do + create l_time.make_now_utc + write_information_log (generator + ".trash_node {" + a_id.out + "}") + + error_handler.reset + create l_parameters.make (1) + l_parameters.put (a_id, "nid") + sql_change (sql_trash_node, l_parameters) + end + + revert_node_by_id (a_id: INTEGER_64) + -- + local + l_parameters: STRING_TABLE [ANY] + l_time: DATE_TIME + do + create l_time.make_now_utc + write_information_log (generator + ".revert_node {" + a_id.out + "}") + + error_handler.reset + create l_parameters.make (1) + l_parameters.put (l_time, "changed") + l_parameters.put ({CMS_NODE_API}.not_published, "status") + l_parameters.put (a_id, "nid") + sql_change (sql_revert_node, l_parameters) + end + + feature {NONE} -- Implementation store_node (a_node: CMS_NODE) @@ -228,6 +292,14 @@ feature {NONE} -- Queries -- SQL Query to retrieve all nodes. --| note: {CMS_NODE_API}.trashed = -1 + sql_select_trash_nodes: STRING = "SELECT * FROM Nodes WHERE status = -1 ;" + -- SQL Query to retrieve all trahsed nodes. + --| note: {CMS_NODE_API}.trashed = -1 + + sql_select_trash_nodes_by_author: STRING = "SELECT * FROM Nodes WHERE status = -1 and author = :author ;" + -- SQL Query to retrieve all nodes by a given author. + --| note: {CMS_NODE_API}.trashed = -1 + sql_select_node_by_id: STRING = "SELECT nid, revision, type, title, summary, content, format, author, publish, created, changed, status FROM Nodes WHERE nid =:nid ORDER BY revision DESC, publish DESC LIMIT 1;" sql_select_recent_nodes: STRING = "SELECT nid, revision, type, title, summary, content, format, author, publish, created, changed, status FROM Nodes ORDER BY nid DESC, publish DESC LIMIT :rows OFFSET :offset ;" @@ -243,6 +315,12 @@ feature {NONE} -- Queries sql_delete_node: STRING = "UPDATE nodes SET changed=:changed, status =:status WHERE nid=:nid" -- Soft deletion with free metadata. + sql_trash_node: STRING = "DELETE FROM NODES WHERE nid=:nid" + -- Physical deletion with free metadata. + + sql_revert_node: STRING = "UPDATE nodes SET changed=:changed, status =:status WHERE nid=:nid" + -- Revert node to {CMS_NODE_API}.not_publised. + -- sql_update_node_author: STRING = "UPDATE nodes SET author=:author WHERE nid=:nid;" -- sql_update_node_title: STRING ="UPDATE nodes SET title=:title, changed=:changed, revision = revision + 1 WHERE nid=:nid;" diff --git a/src/persistence/sql/cms_storage_sql_builder.e b/src/persistence/sql/cms_storage_sql_builder.e index 6000207..a1bec3b 100644 --- a/src/persistence/sql/cms_storage_sql_builder.e +++ b/src/persistence/sql/cms_storage_sql_builder.e @@ -40,6 +40,10 @@ feature -- Initialization --| Node -- FIXME: move that initialization to node module + -- TODO: should we move the initialization to an + --! external configuration file? + --! at the moment we only have 1 admin to the whole site. + --! is that ok? l_anonymous_role.add_permission ("view any page") a_storage.save_user_role (l_anonymous_role) @@ -47,9 +51,11 @@ feature -- Initialization l_authenticated_role.add_permission ("view any page") l_authenticated_role.add_permission ("edit any page") l_authenticated_role.add_permission ("delete page") + l_authenticated_role.add_permission ("trash page") l_authenticated_role.add_permission ("view own page") l_authenticated_role.add_permission ("edit own page") l_authenticated_role.add_permission ("delete own page") + l_authenticated_role.add_permission ("trash own page") a_storage.save_user_role (l_authenticated_role) From 1c59a6598358f1edd9613caede15fccc872d2ee6 Mon Sep 17 00:00:00 2001 From: jvelilla Date: Fri, 15 May 2015 09:40:18 -0300 Subject: [PATCH 04/27] Updated code based on Jocelyn suggestions. --- modules/node/cms_node_api.e | 8 ++++---- modules/node/handler/node_handler.e | 2 +- modules/node/persistence/cms_node_storage_i.e | 12 ++++++------ modules/node/persistence/cms_node_storage_null.e | 4 ++-- modules/node/persistence/cms_node_storage_sql.e | 10 +++++----- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/modules/node/cms_node_api.e b/modules/node/cms_node_api.e index 2e8caf4..dd88fd3 100644 --- a/modules/node/cms_node_api.e +++ b/modules/node/cms_node_api.e @@ -217,7 +217,7 @@ feature -- Access: Node -- List of nodes with status in {CMS_NODE_API}.trashed. -- if the current user is admin, it will retrieve all the trashed nodes do - Result := node_storage.trash_nodes (a_user.id) + Result := node_storage.trashed_nodes (a_user.id) end recent_nodes (a_offset, a_rows: INTEGER): LIST [CMS_NODE] @@ -332,11 +332,11 @@ feature -- Change: Node end - revert_node (a_node: CMS_NODE) - -- Revert node `a_node'. + restore_node (a_node: CMS_NODE) + -- Restore node `a_node'. -- From {CMS_NODE_API}.trashed to {CMS_NODE_API}.not_published. do - node_storage.revert_node (a_node) + node_storage.restore_node (a_node) end diff --git a/modules/node/handler/node_handler.e b/modules/node/handler/node_handler.e index 83ea7e6..583170e 100644 --- a/modules/node/handler/node_handler.e +++ b/modules/node/handler/node_handler.e @@ -233,7 +233,7 @@ feature {NONE} -- Trash:Revert attached node_api.node (l_id.integer_value) as l_node then if node_api.has_permission_for_action_on_node ("trash", l_node, current_user (req)) then - node_api.revert_node (l_node) + node_api.restore_node (l_node) res.send (create {CMS_REDIRECTION_RESPONSE_MESSAGE}.make (req.absolute_script_url (""))) else send_access_denied (req, res) diff --git a/modules/node/persistence/cms_node_storage_i.e b/modules/node/persistence/cms_node_storage_i.e index e359796..5bbf8ca 100644 --- a/modules/node/persistence/cms_node_storage_i.e +++ b/modules/node/persistence/cms_node_storage_i.e @@ -70,7 +70,7 @@ feature -- Access deferred end - trash_nodes (a_user_id: INTEGER_64): LIST [CMS_NODE] + trashed_nodes (a_user_id: INTEGER_64): LIST [CMS_NODE] -- List of nodes by user `a_user_id'. deferred end @@ -148,11 +148,11 @@ feature -- Change: Node end end - revert_node (a_node: CMS_NODE) - -- Revert `a_node'. + restore_node (a_node: CMS_NODE) + -- Restore `a_node'. do if a_node.has_id then - revert_node_by_id (a_node.id) + restore_node_by_id (a_node.id) end end @@ -163,8 +163,8 @@ feature -- Change: Node deferred end - revert_node_by_id (a_id: INTEGER_64) - -- Revert node by id `a_id'. + restore_node_by_id (a_id: INTEGER_64) + -- Restore node by id `a_id'. require valid_node_id: a_id > 0 deferred diff --git a/modules/node/persistence/cms_node_storage_null.e b/modules/node/persistence/cms_node_storage_null.e index 02aaeb2..b5a9406 100644 --- a/modules/node/persistence/cms_node_storage_null.e +++ b/modules/node/persistence/cms_node_storage_null.e @@ -41,7 +41,7 @@ feature -- Access: node create {ARRAYED_LIST [CMS_NODE]} Result.make (0) end - trash_nodes (a_user_id: INTEGER_64): LIST [CMS_NODE] + trashed_nodes (a_user_id: INTEGER_64): LIST [CMS_NODE] -- List of nodes by user `a_user_id'. do create {ARRAYED_LIST [CMS_NODE]} Result.make (0) @@ -91,7 +91,7 @@ feature -- Node do end - revert_node_by_id (a_id: INTEGER_64) + restore_node_by_id (a_id: INTEGER_64) -- do end diff --git a/modules/node/persistence/cms_node_storage_sql.e b/modules/node/persistence/cms_node_storage_sql.e index 971f8c8..8575567 100644 --- a/modules/node/persistence/cms_node_storage_sql.e +++ b/modules/node/persistence/cms_node_storage_sql.e @@ -59,7 +59,7 @@ feature -- Access -- end end - trash_nodes (a_user_id: INTEGER_64): LIST [CMS_NODE] + trashed_nodes (a_user_id: INTEGER_64): LIST [CMS_NODE] -- List of nodes. local l_parameters: STRING_TABLE [detachable ANY] @@ -203,7 +203,7 @@ feature -- Change: Node sql_change (sql_trash_node, l_parameters) end - revert_node_by_id (a_id: INTEGER_64) + restore_node_by_id (a_id: INTEGER_64) -- local l_parameters: STRING_TABLE [ANY] @@ -217,7 +217,7 @@ feature -- Change: Node l_parameters.put (l_time, "changed") l_parameters.put ({CMS_NODE_API}.not_published, "status") l_parameters.put (a_id, "nid") - sql_change (sql_revert_node, l_parameters) + sql_change (sql_restore_node, l_parameters) end @@ -315,10 +315,10 @@ feature {NONE} -- Queries sql_delete_node: STRING = "UPDATE nodes SET changed=:changed, status =:status WHERE nid=:nid" -- Soft deletion with free metadata. - sql_trash_node: STRING = "DELETE FROM NODES WHERE nid=:nid" + sql_trash_node: STRING = "DELETE FROM nodes WHERE nid=:nid" -- Physical deletion with free metadata. - sql_revert_node: STRING = "UPDATE nodes SET changed=:changed, status =:status WHERE nid=:nid" + sql_restore_node: STRING = "UPDATE nodes SET changed=:changed, status =:status WHERE nid=:nid" -- Revert node to {CMS_NODE_API}.not_publised. -- sql_update_node_author: STRING = "UPDATE nodes SET author=:author WHERE nid=:nid;" From 3b90d522f92af2dfa033a630409455e1266c646b Mon Sep 17 00:00:00 2001 From: jvelilla Date: Fri, 15 May 2015 10:44:04 -0300 Subject: [PATCH 05/27] Refactor rename: using trashed_nodes instead of trash_nodes. --- modules/node/cms_node_api.e | 2 +- modules/node/handler/trash_handler.e | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/node/cms_node_api.e b/modules/node/cms_node_api.e index dd88fd3..9ae9d85 100644 --- a/modules/node/cms_node_api.e +++ b/modules/node/cms_node_api.e @@ -213,7 +213,7 @@ feature -- Access: Node end - trash_nodes (a_user: CMS_USER): LIST [CMS_NODE] + trashed_nodes (a_user: CMS_USER): LIST [CMS_NODE] -- List of nodes with status in {CMS_NODE_API}.trashed. -- if the current user is admin, it will retrieve all the trashed nodes do diff --git a/modules/node/handler/trash_handler.e b/modules/node/handler/trash_handler.e index 0811073..5f12770 100644 --- a/modules/node/handler/trash_handler.e +++ b/modules/node/handler/trash_handler.e @@ -51,11 +51,11 @@ feature -- HTTP Methods if attached current_user (req) as l_user then - l_page.add_variable (node_api.trash_nodes (l_user), "nodes") + l_page.add_variable (node_api.trashed_nodes (l_user), "nodes") -- NOTE: for development purposes we have the following hardcode output. create s.make_from_string ("

Nodes:

") - if attached node_api.trash_nodes (l_user) as lst then + if attached node_api.trashed_nodes (l_user) as lst then s.append ("
    %N") across lst as ic From 68fb21a4c1998c09b1550cb341d9be43fba8577c Mon Sep 17 00:00:00 2001 From: jvelilla Date: Fri, 15 May 2015 11:01:59 -0300 Subject: [PATCH 06/27] Fixed typo --- modules/node/handler/node_form_response.e | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/node/handler/node_form_response.e b/modules/node/handler/node_form_response.e index dc57770..3006b63 100644 --- a/modules/node/handler/node_form_response.e +++ b/modules/node/handler/node_form_response.e @@ -117,7 +117,7 @@ feature -- Execution if attached redirection as l_location then -- FIXME: Hack for now set_title (l_node.title) - b.append (html_encoded (l_type.title) + " trasged") + b.append (html_encoded (l_type.title) + " trashed") else set_title (formatted_string (translation ("Trash $1 #$2", Void), [l_type.title, l_node.id])) f.append_to_html (wsf_theme, b) From f0668e660e5d755a3f5cdfbbeeef53ca49ea3614 Mon Sep 17 00:00:00 2001 From: jvelilla Date: Fri, 15 May 2015 11:34:21 -0300 Subject: [PATCH 07/27] refactor rename NODE_HANLDER.do_restore instead of do_revert. --- modules/node/handler/node_handler.e | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/node/handler/node_handler.e b/modules/node/handler/node_handler.e index 583170e..5f71573 100644 --- a/modules/node/handler/node_handler.e +++ b/modules/node/handler/node_handler.e @@ -143,7 +143,7 @@ feature -- HTTP Methods attached {WSF_STRING} req.form_parameter ("op") as l_op and then l_op.value.same_string ("Revert") then - do_revert (req, res) + do_restore (req, res) end elseif req.path_info.starts_with_general ("/node/add/") then create edit_response.make (req, res, api, node_api) @@ -223,7 +223,7 @@ feature {NONE} -- Trash:Revert end end - do_revert (req: WSF_REQUEST; res: WSF_RESPONSE) + do_restore (req: WSF_REQUEST; res: WSF_RESPONSE) -- Revert a node: From {CMS_NODE_API}.trashed to {CMS_NODE_API}.not_published. do if attached current_user (req) as l_user then From e4e2d662b834352215013013c7c73dd4711160de Mon Sep 17 00:00:00 2001 From: jvelilla Date: Fri, 15 May 2015 13:10:12 -0300 Subject: [PATCH 08/27] Renaming revert string to restore. --- modules/node/handler/node_form_response.e | 6 +++--- modules/node/handler/node_handler.e | 6 +++--- modules/node/persistence/cms_node_storage_sql.e | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/node/handler/node_form_response.e b/modules/node/handler/node_form_response.e index 3006b63..cb20a57 100644 --- a/modules/node/handler/node_form_response.e +++ b/modules/node/handler/node_form_response.e @@ -351,15 +351,15 @@ feature -- Form f.extend (ts) end f.extend_html_text ("
    ") - f.extend_html_text ("Do you want to revert the current node?") + f.extend_html_text ("Do you want to restore the current node?") if a_node /= Void and then a_node.id > 0 then create ts.make ("op") - ts.set_default_value ("Revert") + ts.set_default_value ("Restore") fixme ("[ - ts.set_default_value (translation ("Revert")) + ts.set_default_value (translation ("Restore")) ]") f.extend (ts) end diff --git a/modules/node/handler/node_handler.e b/modules/node/handler/node_handler.e index 5f71573..88fb687 100644 --- a/modules/node/handler/node_handler.e +++ b/modules/node/handler/node_handler.e @@ -141,7 +141,7 @@ feature -- HTTP Methods do_trash (req, res) elseif attached {WSF_STRING} req.form_parameter ("op") as l_op and then - l_op.value.same_string ("Revert") + l_op.value.same_string ("Restore") then do_restore (req, res) end @@ -194,7 +194,7 @@ feature -- HTTP Methods send_not_implemented ("REST API not yet implemented", req, res) end -feature {NONE} -- Trash:Revert +feature {NONE} -- Trash:Restore do_trash (req: WSF_REQUEST; res: WSF_RESPONSE) -- Trash a node from the database. @@ -224,7 +224,7 @@ feature {NONE} -- Trash:Revert end do_restore (req: WSF_REQUEST; res: WSF_RESPONSE) - -- Revert a node: From {CMS_NODE_API}.trashed to {CMS_NODE_API}.not_published. + -- Restore a node: From {CMS_NODE_API}.trashed to {CMS_NODE_API}.not_published. do if attached current_user (req) as l_user then if attached {WSF_STRING} req.path_parameter ("id") as l_id then diff --git a/modules/node/persistence/cms_node_storage_sql.e b/modules/node/persistence/cms_node_storage_sql.e index 8575567..b409851 100644 --- a/modules/node/persistence/cms_node_storage_sql.e +++ b/modules/node/persistence/cms_node_storage_sql.e @@ -210,7 +210,7 @@ feature -- Change: Node l_time: DATE_TIME do create l_time.make_now_utc - write_information_log (generator + ".revert_node {" + a_id.out + "}") + write_information_log (generator + ".restore_node {" + a_id.out + "}") error_handler.reset create l_parameters.make (1) @@ -319,7 +319,7 @@ feature {NONE} -- Queries -- Physical deletion with free metadata. sql_restore_node: STRING = "UPDATE nodes SET changed=:changed, status =:status WHERE nid=:nid" - -- Revert node to {CMS_NODE_API}.not_publised. + -- Restore node to {CMS_NODE_API}.not_publised. -- sql_update_node_author: STRING = "UPDATE nodes SET author=:author WHERE nid=:nid;" From 51699f3bd384d4f4f1668746db11a065401fec94 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Tue, 19 May 2015 12:25:16 +0200 Subject: [PATCH 09/27] updated db schema --- examples/demo/site/scripts/core.sql | 2 +- examples/demo/site/scripts/node.sql | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/examples/demo/site/scripts/core.sql b/examples/demo/site/scripts/core.sql index 04dbec8..4a48224 100644 --- a/examples/demo/site/scripts/core.sql +++ b/examples/demo/site/scripts/core.sql @@ -15,7 +15,7 @@ CREATE TABLE "logs"( CREATE TABLE "custom_values"( "type" VARCHAR(255) NOT NULL, "name" VARCHAR(255) NOT NULL, - "value" VARCHAR(255) NOT NULL + "value" TEXT ); CREATE TABLE "path_aliases"( diff --git a/examples/demo/site/scripts/node.sql b/examples/demo/site/scripts/node.sql index d30a854..565b03f 100644 --- a/examples/demo/site/scripts/node.sql +++ b/examples/demo/site/scripts/node.sql @@ -1,18 +1,18 @@ BEGIN; -CREATE TABLE "nodes"( - "nid" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK("nid">=0), - "revision" INTEGER, - "type" TEXT NOT NULL, - "title" VARCHAR(255) NOT NULL, - "summary" TEXT, - "content" MEDIUMTEXT NOT NULL, - "format" VARCHAR(255), - "author" INTEGER, - "publish" DATETIME, - "created" DATETIME NOT NULL, - "changed" DATETIME NOT NULL, - "status" INTEGER +CREATE TABLE "nodes" ( + "nid" INTEGER NOT NULL CHECK("nid" > 0) PRIMARY KEY AUTOINCREMENT UNIQUE, + "revision" INTEGER, + "type" TEXT NOT NULL, + "title" VARCHAR(255) NOT NULL, + "summary" TEXT, + "content" TEXT NOT NULL, + "format" VARCHAR(128), + "author" INTEGER, + "publish" DATETIME, + "created" DATETIME NOT NULL, + "changed" DATETIME NOT NULL, + "status" INTEGER ); CREATE TABLE page_nodes( From 91457080fd2f16b4e2fa159c76d435df1e029ca4 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Tue, 19 May 2015 13:44:08 +0200 Subject: [PATCH 10/27] Added support for base_url (i.e the CMS can be hosted on the root, or sub folder). Local paths are relative to cms site url (i.e no starting slash). Favor CMS_RESPONSE.absolute_url and url .. instead of using directly WSF_REQUEST.absolute_script_url and script_url. Handled unicode truncation issue for logger. Code cleaning. --- examples/demo/modules/blog/cms_blog_module.e | 2 +- examples/demo/modules/demo/cms_demo_module.e | 10 ++--- library/model/src/link/cms_local_link.e | 10 +++-- modules/basic_auth/basic_auth_module.e | 4 +- modules/basic_auth/filter/basic_auth_filter.e | 3 +- modules/node/cms_node_api.e | 8 ++-- .../handler/cms_node_type_webform_manager.e | 32 ++++++++++++-- modules/node/handler/node_form_response.e | 32 +++++++++----- modules/node/handler/node_response.e | 29 ++++++++++--- modules/node/handler/node_view_response.e | 2 +- modules/node/node_module.e | 4 +- src/configuration/cms_default_setup.e | 12 ++++-- src/configuration/cms_setup.e | 2 +- src/persistence/core/cms_core_storage_i.e | 2 +- src/service/cms_api.e | 11 ++++- src/service/filter/cms_error_filter.e | 6 ++- src/service/misc/cms_request_util.e | 10 ----- src/service/misc/cms_url_utilities.e | 1 + src/service/path/cms_router.e | 16 ++++++- src/service/response/cms_response.e | 43 +++++++++++++------ .../error/bad_request_error_cms_response.e | 2 +- .../error/forbidden_error_cms_response.e | 2 +- .../internal_server_error_cms_response.e | 2 +- .../error/not_found_error_cms_response.e | 2 +- .../not_implemented_error_cms_response.e | 2 +- src/theme/cms_theme.e | 38 +++++++++++++++- src/theme/missing_theme/missing_cms_theme.e | 6 ++- src/theme/smarty_theme/smarty_cms_theme.e | 3 +- .../theme/wsf/cms_to_wsf_theme.e | 18 +++----- src/theme/wsf/wsf_cms_theme.e | 17 ++++++++ .../theme/wsf}/wsf_null_theme.e | 0 31 files changed, 237 insertions(+), 94 deletions(-) rename modules/node/handler/wsf_cms_theme.e => src/theme/wsf/cms_to_wsf_theme.e (65%) create mode 100644 src/theme/wsf/wsf_cms_theme.e rename {modules/node/handler => src/theme/wsf}/wsf_null_theme.e (100%) diff --git a/examples/demo/modules/blog/cms_blog_module.e b/examples/demo/modules/blog/cms_blog_module.e index b75fdcd..d60c35e 100644 --- a/examples/demo/modules/blog/cms_blog_module.e +++ b/examples/demo/modules/blog/cms_blog_module.e @@ -101,7 +101,7 @@ feature -- Hooks local lnk: CMS_LOCAL_LINK do - create lnk.make ("Blogs", "/blogs/") + create lnk.make ("Blogs", "blogs/") a_menu_system.primary_menu.extend (lnk) end diff --git a/examples/demo/modules/demo/cms_demo_module.e b/examples/demo/modules/demo/cms_demo_module.e index e0f1ff1..0ab359e 100644 --- a/examples/demo/modules/demo/cms_demo_module.e +++ b/examples/demo/modules/demo/cms_demo_module.e @@ -110,9 +110,9 @@ feature -- Hooks if a_block_id.is_case_insensitive_equal_general ("demo-info") then if a_response.request.request_uri.starts_with ("/demo/") then create m.make_with_title (a_block_id, "Demo", 2) - create lnk.make ("/demo/abc", a_response.url ("/demo/abc", Void)) + create lnk.make ("demo: abc", "demo/abc") m.extend (lnk) - create lnk.make ("/demo/123", a_response.url ("/demo/123", Void)) + create lnk.make ("demo: 123", "demo/123") m.extend (lnk) create mb.make (m) a_response.add_block (mb, "sidebar_second") @@ -125,7 +125,7 @@ feature -- Hooks lnk: CMS_LOCAL_LINK -- perms: detachable ARRAYED_LIST [READABLE_STRING_8] do - create lnk.make ("Demo", "/demo/") + create lnk.make ("Demo", "demo/") a_menu_system.primary_menu.extend (lnk) end @@ -137,8 +137,8 @@ feature -- Handler r: NOT_IMPLEMENTED_ERROR_CMS_RESPONSE do create r.make (req, res, a_api) - r.set_main_content ("NODE module does not yet implement %"" + req.path_info + "%" ...") - r.add_error_message ("NODE Module: not yet implemented") + r.set_main_content ("DEMO module does not yet implement %"" + req.path_info + "%" ...") + r.add_error_message ("DEMO Module: not yet implemented") r.execute end diff --git a/library/model/src/link/cms_local_link.e b/library/model/src/link/cms_local_link.e index 376ccac..146d6f7 100644 --- a/library/model/src/link/cms_local_link.e +++ b/library/model/src/link/cms_local_link.e @@ -25,8 +25,10 @@ create feature {NONE} -- Initialization - make (a_title: detachable like title; a_location: like location) + make (a_title: detachable READABLE_STRING_GENERAL; a_location: like location) -- Create current local link with optional title `a_title' and location `a_location'. + require + is_valid_local_location_argument: not a_location.starts_with_general ("/") do location := a_location set_title (a_title) @@ -71,13 +73,13 @@ feature -- Status report feature -- Element change - set_title (a_title: detachable like title) + set_title (a_title: detachable READABLE_STRING_GENERAL) -- Set `title' to `a_title' or `location'. do if a_title /= Void then - title := a_title + title := a_title.as_string_32 else - title := location + title := location.as_string_32 end end diff --git a/modules/basic_auth/basic_auth_module.e b/modules/basic_auth/basic_auth_module.e index 3efe2c2..515cac7 100644 --- a/modules/basic_auth/basic_auth_module.e +++ b/modules/basic_auth/basic_auth_module.e @@ -109,9 +109,9 @@ feature -- Hooks lnk: CMS_LOCAL_LINK do if attached a_response.current_user (a_response.request) as u then - create lnk.make (u.name + " (Logout)", "/basic_auth_logoff?destination=" + a_response.request.request_uri) + create lnk.make (u.name + " (Logout)", "basic_auth_logoff?destination=" + a_response.request.request_uri) else - create lnk.make ("Login", "/basic_auth_login?destination=" + a_response.request.request_uri) + create lnk.make ("Login", "basic_auth_login?destination=" + a_response.request.request_uri) end -- if not a_menu_system.primary_menu.has (lnk) then lnk.set_weight (99) diff --git a/modules/basic_auth/filter/basic_auth_filter.e b/modules/basic_auth/filter/basic_auth_filter.e index 59423fd..0154d04 100644 --- a/modules/basic_auth/filter/basic_auth_filter.e +++ b/modules/basic_auth/filter/basic_auth_filter.e @@ -22,11 +22,12 @@ feature -- Basic operations -- Execute the filter. local l_auth: HTTP_AUTHORIZATION + utf: UTF_CONVERTER do api.logger.put_debug (generator + ".execute ", Void) create l_auth.make (req.http_authorization) if attached req.raw_header_data as l_raw_data then - api.logger.put_debug (generator + ".execute " + l_raw_data, Void) + api.logger.put_debug (generator + ".execute " + utf.escaped_utf_32_string_to_utf_8_string_8 (l_raw_data), Void) end -- A valid user if diff --git a/modules/node/cms_node_api.e b/modules/node/cms_node_api.e index 8f0a8d9..f56f6a0 100644 --- a/modules/node/cms_node_api.e +++ b/modules/node/cms_node_api.e @@ -170,9 +170,9 @@ feature -- URL -- or URI of path for selection of new content possibilities if ct is Void. do if ct /= Void then - Result := "/node/add/" + ct.name + Result := "node/add/" + ct.name else - Result := "/node/" + Result := "node/" end end @@ -190,13 +190,13 @@ feature -- URL require a_node.has_id do - Result := "/node/" + a_node.id.out + Result := "node/" + a_node.id.out end nodes_path: STRING -- URI path for list of nodes. do - Result := "/nodes" + Result := "nodes" end feature -- Access: Node diff --git a/modules/node/handler/cms_node_type_webform_manager.e b/modules/node/handler/cms_node_type_webform_manager.e index f571c26..5af3918 100644 --- a/modules/node/handler/cms_node_type_webform_manager.e +++ b/modules/node/handler/cms_node_type_webform_manager.e @@ -9,6 +9,8 @@ deferred class inherit CMS_NODE_TYPE_WEBFORM_MANAGER_I [G] + SHARED_WSF_PERCENT_ENCODER + feature -- Forms ... populate_form (response: NODE_RESPONSE; f: CMS_FORM; a_node: detachable CMS_NODE) @@ -18,6 +20,7 @@ feature -- Forms ... ta: WSF_FORM_TEXTAREA tselect: WSF_FORM_SELECT opt: WSF_FORM_SELECT_OPTION + l_uri: detachable READABLE_STRING_8 do create ti.make ("title") ti.set_label ("Title") @@ -66,16 +69,37 @@ feature -- Forms ... f.extend (fset) - -- Path aliase + -- Path alias create ti.make ("path_alias") ti.set_label ("Path") ti.set_size (70) if a_node /= Void and then a_node.has_id then if attached a_node.link as lnk then - ti.set_text_value (lnk.location) + l_uri := lnk.location else - ti.set_text_value (response.api.path_alias (response.node_api.node_path (a_node))) + l_uri := percent_encoder.percent_decoded_string (response.api.path_alias (response.node_api.node_path (a_node))) end + ti.set_text_value (l_uri) + ti.set_description ("Optionally specify an alternative URL path by which this content can be accessed. For example, type 'about' when writing an about page. Use a relative path or the URL alias won't work.") + ti.set_validation_action (agent (fd: WSF_FORM_DATA; a_response: CMS_RESPONSE) + do + if + attached fd.string_item ("path_alias") as f_path_alias + then + if a_response.api.is_valid_path_alias (f_path_alias) then + -- Ok. + elseif f_path_alias.is_empty then + -- Ok + elseif f_path_alias.starts_with_general ("/") then + fd.report_invalid_field ("path_alias", "Path alias should not start with a slash '/' .") + elseif f_path_alias.has_substring ("://") then + fd.report_invalid_field ("path_alias", "Path alias should not be absolute url .") + else + -- TODO: implement full path alias validation + end + end + end(?, response) + ) end if attached f.fields_by_name ("title") as l_title_fields and then @@ -180,7 +204,7 @@ feature -- Output node_api := a_response.node_api a_response.add_variable (a_node, "node") - create lnk.make (a_response.translation ("View", Void), a_response.node_local_link (a_node).location) + lnk := a_response.node_local_link (a_node, a_response.translation ("View", Void)) lnk.set_weight (1) a_response.add_to_primary_tabs (lnk) diff --git a/modules/node/handler/node_form_response.e b/modules/node/handler/node_form_response.e index c01330a..9f92e28 100644 --- a/modules/node/handler/node_form_response.e +++ b/modules/node/handler/node_form_response.e @@ -26,7 +26,7 @@ feature {NONE} -- Initialization initialize do Precursor - create {WSF_CMS_THEME} wsf_theme.make (Current, theme) + create {CMS_TO_WSF_THEME} wsf_theme.make (Current, theme) end wsf_theme: WSF_THEME @@ -58,8 +58,8 @@ feature -- Execution fd := f.last_data end if l_node.has_id then - add_to_menu (create {CMS_LOCAL_LINK}.make (translation ("View", Void), node_url (l_node)), primary_tabs) - add_to_menu (create {CMS_LOCAL_LINK}.make (translation ("Edit", Void), "/node/" + l_node.id.out + "/edit"), primary_tabs) + 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) end if attached redirection as l_location then @@ -96,8 +96,8 @@ feature -- Execution set_title ("Edit " + html_encoded (l_type.title) + " #" + l_node.id.out) if l_node.has_id then - add_to_menu (create {CMS_LOCAL_LINK}.make (translation ("View", Void), node_url (l_node)), primary_tabs) - add_to_menu (create {CMS_LOCAL_LINK}.make (translation ("Edit", Void), "/node/" + l_node.id.out + "/edit"), primary_tabs) + 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) end f.append_to_html (wsf_theme, b) @@ -121,7 +121,7 @@ feature -- Execution attached ic.item as l_node_type and then has_permissions (<<"create any", "create " + l_node_type.name>>) then - b.append ("
  • " + link (l_node_type.name, "/node/add/" + l_node_type.name, Void)) + b.append ("
  • " + link (l_node_type.name, "node/add/" + l_node_type.name, Void)) if attached l_node_type.description as d then b.append ("
    " + d + "
    ") end @@ -167,6 +167,7 @@ feature -- Form l_preview: BOOLEAN l_node: detachable CMS_NODE s: STRING + l_path_alias: detachable READABLE_STRING_8 do l_preview := attached {WSF_STRING} fd.item ("op") as l_op and then l_op.same_string ("Preview") if not l_preview then @@ -198,20 +199,29 @@ feature -- Form end node_api.save_node (l_node) if attached current_user (request) as u then - api.log ("node", "User %"" + user_html_link (u) + "%" " + s + " node " + link (a_type.name +" #" + l_node.id.out, "/node/" + l_node.id.out , Void), 0, node_local_link (l_node)) + api.log ("node", + "User %"" + user_html_link (u) + "%" " + s + " node " + node_html_link (l_node, a_type.name + " #" + l_node.id.out), + 0, node_local_link (l_node, Void) + ) else - api.log ("node", "Anonymous " + s + " node " + a_type.name +" #" + l_node.id.out, 0, node_local_link (l_node)) + api.log ("node", "Anonymous " + s + " node " + a_type.name +" #" + l_node.id.out, 0, node_local_link (l_node, Void)) end add_success_message ("Node #" + l_node.id.out + " saved.") - if attached fd.string_item ("path_alias") as l_path_alias then + if + attached fd.string_item ("path_alias") as f_path_alias and then + not f_path_alias.is_empty + then + l_path_alias := percent_encoder.partial_encoded_string (f_path_alias, <<'/'>>) + -- Path alias, are always from the root of the cms. api.set_path_alias (node_api.node_path (l_node), l_path_alias, False) l_node.set_link (create {CMS_LOCAL_LINK}.make (l_node.title, l_path_alias)) else l_node.set_link (node_api.node_link (l_node)) end - - set_redirection (node_url (l_node)) + if attached l_node.link as lnk then + set_redirection (lnk.location) + end end end diff --git a/modules/node/handler/node_response.e b/modules/node/handler/node_response.e index 1bad113..6c444a5 100644 --- a/modules/node/handler/node_response.e +++ b/modules/node/handler/node_response.e @@ -53,30 +53,45 @@ feature -- Helpers feature -- Helpers: cms link - user_local_link (u: CMS_USER): CMS_LOCAL_LINK + user_local_link (u: CMS_USER; a_opt_title: detachable READABLE_STRING_GENERAL): CMS_LOCAL_LINK do - create Result.make (u.name, user_url (u)) + if a_opt_title /= Void then + create Result.make (a_opt_title, user_url (u)) + else + create Result.make (u.name, user_url (u)) + end end - node_local_link (n: CMS_NODE): CMS_LOCAL_LINK + node_local_link (n: CMS_NODE; a_opt_title: detachable READABLE_STRING_GENERAL): CMS_LOCAL_LINK do if attached n.link as lnk then Result := lnk else Result := node_api.node_link (n) end + if a_opt_title /= Void and then not Result.title.same_string_general (a_opt_title) then + create Result.make (a_opt_title, Result.location) + end end feature -- Helpers: html link user_html_link (u: CMS_USER): like link do - Result := link (u.name, "/user/" + u.id.out, Void) + Result := link (u.name, "user/" + u.id.out, Void) end - node_html_link (n: CMS_NODE): like link + node_html_link (n: CMS_NODE; a_opt_title: detachable READABLE_STRING_GENERAL): like link + local + l_title: detachable READABLE_STRING_GENERAL do - Result := link (n.title, "/node/" + n.id.out, Void) + if a_opt_title /= Void then + l_title := a_opt_title + else + l_title := n.title + end + Result := link (l_title, node_api.node_path (n), Void) + end feature -- Helpers: URL @@ -85,7 +100,7 @@ feature -- Helpers: URL require u_with_id: u.has_id do - Result := url ("/user/" + u.id.out, Void) + Result := url ("user/" + u.id.out, Void) end node_url (n: CMS_NODE): like url diff --git a/modules/node/handler/node_view_response.e b/modules/node/handler/node_view_response.e index e62a316..aac253f 100644 --- a/modules/node/handler/node_view_response.e +++ b/modules/node/handler/node_view_response.e @@ -27,7 +27,7 @@ feature {NONE} -- Initialization initialize do Precursor - create {WSF_CMS_THEME} wsf_theme.make (Current, theme) + create {CMS_TO_WSF_THEME} wsf_theme.make (Current, theme) end wsf_theme: WSF_THEME diff --git a/modules/node/node_module.e b/modules/node/node_module.e index 8df4eab..4e4e3f2 100644 --- a/modules/node/node_module.e +++ b/modules/node/node_module.e @@ -173,10 +173,10 @@ feature -- Hooks lnk: CMS_LOCAL_LINK -- perms: detachable ARRAYED_LIST [READABLE_STRING_8] do - create lnk.make ("List of nodes", a_response.url ("/nodes", Void)) + create lnk.make ("List of nodes", "nodes") a_menu_system.primary_menu.extend (lnk) - create lnk.make ("Create ..", a_response.url ("/node/", Void)) + create lnk.make ("Create ..", "node/") a_menu_system.primary_menu.extend (lnk) end diff --git a/src/configuration/cms_default_setup.e b/src/configuration/cms_default_setup.e index 9a16640..64ec4b0 100644 --- a/src/configuration/cms_default_setup.e +++ b/src/configuration/cms_default_setup.e @@ -39,17 +39,21 @@ feature {NONE} -- Initialization end configure + local + l_url: like site_url do --| Site id, used to identified a site, this could be set to a uuid, or else site_id := text_item_or_default ("site.id", "_EWF_CMS_NO_ID_") -- Site url: optional, but ending with a slash - site_url := string_8_item ("site_url") - if attached site_url as l_url and then not l_url.is_empty then - if l_url[l_url.count] /= '/' then - site_url := l_url + "/" + l_url := string_8_item ("site_url") + if l_url /= Void and then not l_url.is_empty then + if l_url [l_url.count] /= '/' then + l_url := l_url + "/" end end + site_url := l_url + -- Site name site_name := text_item_or_default ("site.name", "EWF::CMS") diff --git a/src/configuration/cms_setup.e b/src/configuration/cms_setup.e index 792f84e..1b53010 100644 --- a/src/configuration/cms_setup.e +++ b/src/configuration/cms_setup.e @@ -62,7 +62,7 @@ feature -- Access: Site -- Mainly used for internal notification. site_url: detachable READABLE_STRING_8 - -- Optional base url of the site. + -- Optional url of current CMS site. front_page_path: detachable READABLE_STRING_8 -- Optional path defining the front page. diff --git a/src/persistence/core/cms_core_storage_i.e b/src/persistence/core/cms_core_storage_i.e index 89926de..ef87eba 100644 --- a/src/persistence/core/cms_core_storage_i.e +++ b/src/persistence/core/cms_core_storage_i.e @@ -1,6 +1,6 @@ note description: "[ - Objects that ... + CMS Storage for core functionalities. ]" author: "$Author$" date: "$Date$" diff --git a/src/service/cms_api.e b/src/service/cms_api.e index 655ed43..0209c97 100644 --- a/src/service/cms_api.e +++ b/src/service/cms_api.e @@ -234,9 +234,16 @@ feature -- Query: API feature -- Path aliases + is_valid_path_alias (a_alias: READABLE_STRING_8): BOOLEAN + do + Result := a_alias.is_empty or else not a_alias.starts_with_general ("/") + end + set_path_alias (a_source, a_alias: READABLE_STRING_8; a_keep_previous: BOOLEAN) -- Set `a_alias' as alias of `a_source', -- and eventually unset previous alias if any. + require + valid_alias: is_valid_path_alias (a_alias) local l_continue: BOOLEAN do @@ -281,8 +288,8 @@ feature -- Path aliases -- Resolved path for alias `a_alias'. --| the CMS supports aliases for path, and then this function simply returns --| the effective target path/url for this `a_alias'. - --| For instance: /articles/2015/may/this-is-an-article can be an alias to /node/123 - --| This function will return "/node/123". + --| For instance: articles/2015/may/this-is-an-article can be an alias to node/123 + --| This function will return "node/123". --| If the alias is bad (i.e does not alias real path), then this function --| returns the alias itself. do diff --git a/src/service/filter/cms_error_filter.e b/src/service/filter/cms_error_filter.e index a07a3bc..0e5f457 100644 --- a/src/service/filter/cms_error_filter.e +++ b/src/service/filter/cms_error_filter.e @@ -19,15 +19,17 @@ feature -- Basic operations execute (req: WSF_REQUEST; res: WSF_RESPONSE) -- Execute the filter + local + utf: UTF_CONVERTER do fixme ("Check if it's ok to add new fetures CMS_API.has_error:BOOLEAN and CMS_API.error_description.") if not api.has_error then api.logger.put_information (generator + ".execute with req: " + req.debug_output, Void) if attached req.raw_header_data as l_header_data then - api.logger.put_debug (generator + ".execute with req header: " + l_header_data, Void) + api.logger.put_debug (generator + ".execute with req header: " + utf.escaped_utf_32_string_to_utf_8_string_8 (l_header_data), Void) end if attached req.raw_input_data as l_input_data then - api.logger.put_debug (generator + ".execute with req input: " + l_input_data, Void) + api.logger.put_debug (generator + ".execute with req input: " + utf.escaped_utf_32_string_to_utf_8_string_8 (l_input_data), Void) end execute_next (req, res) else diff --git a/src/service/misc/cms_request_util.e b/src/service/misc/cms_request_util.e index e29bc61..f49337a 100644 --- a/src/service/misc/cms_request_util.e +++ b/src/service/misc/cms_request_util.e @@ -70,14 +70,4 @@ feature -- Media Type end end -feature -- Absolute Host - - absolute_host (req: WSF_REQUEST; a_path:STRING): STRING - do - Result := req.absolute_script_url (a_path) - if Result.last_index_of ('/', Result.count) = Result.count then - Result.remove_tail (1) - end - end - end diff --git a/src/service/misc/cms_url_utilities.e b/src/service/misc/cms_url_utilities.e index 73feb92..89505a6 100644 --- a/src/service/misc/cms_url_utilities.e +++ b/src/service/misc/cms_url_utilities.e @@ -13,6 +13,7 @@ inherit feature -- Core site_url: READABLE_STRING_8 + -- Absolute site URL of Current CMS site. deferred end diff --git a/src/service/path/cms_router.e b/src/service/path/cms_router.e index fdc0452..ce1982e 100644 --- a/src/service/path/cms_router.e +++ b/src/service/path/cms_router.e @@ -31,8 +31,22 @@ feature {WSF_ROUTER_MAPPING} -- Dispatch helper path_to_dispatch (req: WSF_REQUEST): READABLE_STRING_8 -- Path used by the router, to apply url dispatching of request `req'. + local + l_path: STRING_8 do - Result := api.source_of_path_alias (Precursor (req)) + create l_path.make_from_string (Precursor (req)) + if not l_path.is_empty and l_path [1] = '/' then + l_path.remove_head (1) + end + Result := api.source_of_path_alias (l_path) + if Result.is_empty then + Result := "/" + elseif Result [1] /= '/' then + create l_path.make (Result.count + 1) + l_path.append_character ('/') + l_path.append (Result) + Result := l_path + end end end diff --git a/src/service/response/cms_response.e b/src/service/response/cms_response.e index 18d99d4..b0dc598 100644 --- a/src/service/response/cms_response.e +++ b/src/service/response/cms_response.e @@ -29,6 +29,7 @@ feature {NONE} -- Initialization initialize do + initialize_site_url get_theme create menu_system.make initialize_block_region_settings @@ -36,6 +37,27 @@ feature {NONE} -- Initialization register_hooks end + initialize_site_url + -- Initialize site and base url. + local + l_url: detachable READABLE_STRING_8 + i,j: INTEGER + do + --| WARNING: do not use `absolute_url' and `url', since it relies on site_url and base_url. + l_url := setup.site_url + if l_url = Void then + l_url := request.absolute_script_url ("/") + end + site_url := l_url + i := l_url.substring_index ("://", 1) + if i > 0 then + j := l_url.index_of ('/', i + 3) + if j > 0 then + base_url := l_url.substring (j, l_url.count) + end + end + end + register_hooks local l_module: CMS_MODULE @@ -164,15 +186,12 @@ feature -- URL utilities end site_url: READABLE_STRING_8 - do - Result := absolute_host (request, "") - end + -- Absolute site url. base_url: detachable READABLE_STRING_8 -- Base url if any. --| Usually it is Void, but it could be --| /project/demo/ - --| FIXME: for now, no way to change that. Always at the root "/" feature -- Access: CMS @@ -183,7 +202,7 @@ feature -- Access: CMS front_page_url: READABLE_STRING_8 do - Result := request.absolute_script_url ("/") + Result := absolute_url ("/", Void) end values: CMS_VALUE_TABLE @@ -806,9 +825,9 @@ feature -- Theme create l_info.make_default end if l_info.engine.is_case_insensitive_equal_general ("smarty") then - create {SMARTY_CMS_THEME} theme.make (setup, l_info) + create {SMARTY_CMS_THEME} theme.make (setup, l_info, site_url) else - create {MISSING_CMS_THEME} theme.make (setup) + create {MISSING_CMS_THEME} theme.make (setup, l_info, site_url) status_code := {HTTP_STATUS_CODE}.service_unavailable to_implement ("Check how to add the Retry-after, http://tools.ietf.org/html/rfc7231#section-6.6.4 and http://tools.ietf.org/html/rfc7231#section-7.1.3") end @@ -834,7 +853,7 @@ feature -- Generation lnk: CMS_LINK do -- Menu - create {CMS_LOCAL_LINK} lnk.make ("Home", "/") + create {CMS_LOCAL_LINK} lnk.make ("Home", "") lnk.set_weight (-10) add_to_primary_menu (lnk) invoke_menu_system_alter (menu_system) @@ -920,8 +939,8 @@ feature -- Generation end -- Variables - page.register_variable (request.absolute_script_url (""), "site_url") - page.register_variable (request.absolute_script_url (""), "host") -- Same as `site_url'. + page.register_variable (absolute_url ("", Void), "site_url") + page.register_variable (absolute_url ("", Void), "host") -- Same as `site_url'. page.register_variable (request.is_https, "is_https") if attached current_user_name (request) as l_user then page.register_variable (l_user, "user") @@ -1102,8 +1121,8 @@ feature {NONE} -- Execution -- h.put_location (l_location) response.redirect_now (l_location) else --- h.put_location (request.absolute_script_url (l_location)) - response.redirect_now (request.absolute_script_url (l_location)) +-- h.put_location (request.absolute_url (l_location, Void)) + response.redirect_now (absolute_url (l_location, Void)) end else h.put_header_object (header) diff --git a/src/service/response/error/bad_request_error_cms_response.e b/src/service/response/error/bad_request_error_cms_response.e index 4c15239..002a3c3 100644 --- a/src/service/response/error/bad_request_error_cms_response.e +++ b/src/service/response/error/bad_request_error_cms_response.e @@ -20,7 +20,7 @@ feature -- Generation custom_prepare (page: CMS_HTML_PAGE) do - page.register_variable (request.absolute_script_url (request.path_info), "request") + page.register_variable (absolute_url (request.path_info, Void), "request") page.set_status_code ({HTTP_STATUS_CODE}.bad_request) page.register_variable (page.status_code.out, "code") end diff --git a/src/service/response/error/forbidden_error_cms_response.e b/src/service/response/error/forbidden_error_cms_response.e index 5616c8b..62518e5 100644 --- a/src/service/response/error/forbidden_error_cms_response.e +++ b/src/service/response/error/forbidden_error_cms_response.e @@ -20,7 +20,7 @@ feature -- Generation custom_prepare (page: CMS_HTML_PAGE) do - page.register_variable (request.absolute_script_url (request.path_info), "request") + page.register_variable (absolute_url (request.path_info, Void), "request") page.set_status_code ({HTTP_STATUS_CODE}.forbidden) page.register_variable (page.status_code.out, "code") end diff --git a/src/service/response/error/internal_server_error_cms_response.e b/src/service/response/error/internal_server_error_cms_response.e index 43eb930..f23a871 100644 --- a/src/service/response/error/internal_server_error_cms_response.e +++ b/src/service/response/error/internal_server_error_cms_response.e @@ -20,7 +20,7 @@ feature -- Generation custom_prepare (page: CMS_HTML_PAGE) do - page.register_variable (request.absolute_script_url (request.path_info), "request") + page.register_variable (absolute_url (request.path_info, Void), "request") page.set_status_code ({HTTP_STATUS_CODE}.internal_server_error) page.register_variable (page.status_code.out, "code") end diff --git a/src/service/response/error/not_found_error_cms_response.e b/src/service/response/error/not_found_error_cms_response.e index 2f9ae36..2c7d63c 100644 --- a/src/service/response/error/not_found_error_cms_response.e +++ b/src/service/response/error/not_found_error_cms_response.e @@ -20,7 +20,7 @@ feature -- Generation custom_prepare (page: CMS_HTML_PAGE) do - page.register_variable (request.absolute_script_url (request.path_info), "request") + page.register_variable (absolute_url (request.path_info, Void), "request") page.set_status_code ({HTTP_STATUS_CODE}.not_found) page.register_variable (page.status_code.out, "code") end diff --git a/src/service/response/error/not_implemented_error_cms_response.e b/src/service/response/error/not_implemented_error_cms_response.e index 159b9b4..e46e9fd 100644 --- a/src/service/response/error/not_implemented_error_cms_response.e +++ b/src/service/response/error/not_implemented_error_cms_response.e @@ -20,7 +20,7 @@ feature -- Generation custom_prepare (page: CMS_HTML_PAGE) do - page.register_variable (request.absolute_script_url (request.path_info), "request") + page.register_variable (absolute_url (request.path_info, Void), "request") page.set_status_code ({HTTP_STATUS_CODE}.not_implemented) page.register_variable (page.status_code.out, "code") end diff --git a/src/theme/cms_theme.e b/src/theme/cms_theme.e index d90c625..f88f7e9 100644 --- a/src/theme/cms_theme.e +++ b/src/theme/cms_theme.e @@ -9,6 +9,8 @@ deferred class inherit CMS_ENCODERS + CMS_URL_UTILITIES + REFACTORING_HELPER @@ -16,6 +18,12 @@ feature {NONE} -- Access setup: CMS_SETUP + site_url: READABLE_STRING_8 assign set_site_url + -- Absolute URL for Current CMS site. + + base_url: detachable READABLE_STRING_8 + -- Optional base url of current CMS site. + feature -- Access name: STRING @@ -41,6 +49,30 @@ feature -- Status report Result := across regions as ic some a_region_name.is_case_insensitive_equal (ic.item) end end +feature -- Element change + + set_site_url (a_url: READABLE_STRING_8) + -- Set `site_url' to `a_url'. + require + a_url.ends_with_general ("/") + local + i,j: INTEGER + do + base_url := Void + if a_url[a_url.count] = '/' then + site_url := a_url + else + site_url := a_url + "/" + end + i := a_url.substring_index ("://", 1) + if i > 0 then + j := a_url.index_of ('/', i + 3) + if j > 0 then + base_url := a_url.substring (j, a_url.count) + end + end + end + feature -- Conversion menu_html (a_menu: CMS_MENU; is_horizontal: BOOLEAN; a_options: detachable CMS_HTML_OPTIONS): STRING_8 @@ -133,7 +165,11 @@ feature {NONE} -- Implementation else s.append ("
  • ") end - s.append ("" + html_encoded (lnk.title) + "") + s.append ("") + s.append (html_encoded (lnk.title)) + s.append ("") if (lnk.is_expanded or lnk.is_collapsed) and then attached lnk.children as l_children diff --git a/src/theme/missing_theme/missing_cms_theme.e b/src/theme/missing_theme/missing_cms_theme.e index b6c5ab9..bd767a5 100644 --- a/src/theme/missing_theme/missing_cms_theme.e +++ b/src/theme/missing_theme/missing_cms_theme.e @@ -18,15 +18,19 @@ create feature {NONE} -- Initialization - make (a_setup: like setup) + make (a_setup: like setup; a_info: like information; abs_site_url: READABLE_STRING_8) do setup := a_setup + information := a_info + set_site_url (abs_site_url) ensure setup_set: setup = a_setup end feature -- Access + information: CMS_THEME_INFORMATION + name: STRING = "missing theme" regions: ARRAY [STRING] diff --git a/src/theme/smarty_theme/smarty_cms_theme.e b/src/theme/smarty_theme/smarty_cms_theme.e index 5f408e4..4ff9657 100644 --- a/src/theme/smarty_theme/smarty_cms_theme.e +++ b/src/theme/smarty_theme/smarty_cms_theme.e @@ -14,7 +14,7 @@ create feature {NONE} -- Initialization - make (a_setup: like setup; a_info: like information;) + make (a_setup: like setup; a_info: like information; abs_site_url: READABLE_STRING_8) do setup := a_setup information := a_info @@ -23,6 +23,7 @@ feature {NONE} -- Initialization else templates_directory := a_setup.theme_location end + set_site_url (abs_site_url) ensure setup_set: setup = a_setup information_set: information = a_info diff --git a/modules/node/handler/wsf_cms_theme.e b/src/theme/wsf/cms_to_wsf_theme.e similarity index 65% rename from modules/node/handler/wsf_cms_theme.e rename to src/theme/wsf/cms_to_wsf_theme.e index 8ef9e3a..c3cf6cc 100644 --- a/modules/node/handler/wsf_cms_theme.e +++ b/src/theme/wsf/cms_to_wsf_theme.e @@ -1,10 +1,10 @@ note - description: "Summary description for {WSF_CMS_THEME}." + description: "Theme from the EWF framework, but dedicated for the CMS." date: "$Date$" revision: "$Revision$" class - WSF_CMS_THEME + CMS_TO_WSF_THEME inherit WSF_THEME @@ -25,13 +25,14 @@ feature -- Access request: WSF_REQUEST - response: detachable CMS_RESPONSE + response: CMS_RESPONSE cms_theme: CMS_THEME feature -- Element change set_response (a_response: CMS_RESPONSE) + -- Set `response' to `a_response'. do response := a_response end @@ -39,20 +40,15 @@ feature -- Element change feature -- Core site_url: READABLE_STRING_8 + -- CMS site url. do - if attached response as r then - Result := r.site_url - else - Result := request.absolute_script_url ("") - end + Result := response.site_url end base_url: detachable READABLE_STRING_8 -- Base url if any. do - if attached response as r then - Result := r.base_url - end + Result := response.base_url end end diff --git a/src/theme/wsf/wsf_cms_theme.e b/src/theme/wsf/wsf_cms_theme.e new file mode 100644 index 0000000..7d8d69a --- /dev/null +++ b/src/theme/wsf/wsf_cms_theme.e @@ -0,0 +1,17 @@ +note + description: "Summary description for {WSF_CMS_THEME}." + date: "$Date$" + revision: "$Revision$" + +class + WSF_CMS_THEME + +obsolete "Use CMS_TO_WSF_THEME [2015-May]" + +inherit + CMS_TO_WSF_THEME + +create + make + +end diff --git a/modules/node/handler/wsf_null_theme.e b/src/theme/wsf/wsf_null_theme.e similarity index 100% rename from modules/node/handler/wsf_null_theme.e rename to src/theme/wsf/wsf_null_theme.e From 036013a0a2b9f24557aa49334447b456716cbe5d Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Tue, 19 May 2015 22:02:56 +0200 Subject: [PATCH 11/27] Use CMS local location (i.e relative) and not url for cms local links. --- modules/node/node_module.e | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/node/node_module.e b/modules/node/node_module.e index 366b34b..e4743d5 100644 --- a/modules/node/node_module.e +++ b/modules/node/node_module.e @@ -186,10 +186,10 @@ feature -- Hooks create lnk.make ("List of nodes", "nodes") a_menu_system.primary_menu.extend (lnk) - create lnk.make ("Trash", a_response.url ("trash", Void)) + create lnk.make ("Trash", "trash") a_menu_system.primary_menu.extend (lnk) - create lnk.make ("Create ..", a_response.url ("node/", Void)) + create lnk.make ("Create ..", "node/") a_menu_system.primary_menu.extend (lnk) end From 53f3162b4aed08b547f46ae4299b5043985ac12f Mon Sep 17 00:00:00 2001 From: jvelilla Date: Tue, 19 May 2015 18:40:57 -0300 Subject: [PATCH 12/27] Inital page builder implementation to add paging support to cms_nodes. --- modules/node/handler/node_page_builder.e | 37 +++++++++++++ modules/node/handler/nodes_handler.e | 64 +++++++++++++++++++++- modules/node/handler/page_builder.e | 70 ++++++++++++++++++++++++ modules/node/node_module.e | 6 +- 4 files changed, 173 insertions(+), 4 deletions(-) create mode 100644 modules/node/handler/node_page_builder.e create mode 100644 modules/node/handler/page_builder.e diff --git a/modules/node/handler/node_page_builder.e b/modules/node/handler/node_page_builder.e new file mode 100644 index 0000000..f6f7715 --- /dev/null +++ b/modules/node/handler/node_page_builder.e @@ -0,0 +1,37 @@ +note + description: "Summary description for {NODE_PAGE_BUILDER}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + NODE_PAGE_BUILDER + +inherit + + PAGE_BUILDER [CMS_NODE] + rename + make as page_make + end +create + + make + +feature {NONE} -- Initialization + + make (a_api: CMS_API; a_module_api: CMS_NODE_API) + do + page_make (a_api, a_module_api) + limit := 5 + offset := 0 + end + +feature -- Pager + + list: LIST[CMS_NODE] + do + create {ARRAYED_LIST[CMS_NODE]}Result.make (0) + Result := node_api.recent_nodes (offset.as_integer_32, limit.as_integer_32) + end + +end diff --git a/modules/node/handler/nodes_handler.e b/modules/node/handler/nodes_handler.e index 18462d2..6f33259 100644 --- a/modules/node/handler/nodes_handler.e +++ b/modules/node/handler/nodes_handler.e @@ -41,6 +41,9 @@ feature -- HTTP Methods s: STRING n: CMS_NODE lnk: CMS_LOCAL_LINK + pager: NODE_PAGE_BUILDER + number_of_pages: INTEGER_64 + current_page: INTEGER do -- At the moment the template is hardcoded, but we can -- get them from the configuration file and load them into @@ -49,10 +52,68 @@ feature -- HTTP Methods create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api) l_page.add_variable (node_api.nodes, "nodes") + create pager.make (api, node_api) + number_of_pages := (node_api.nodes_count // pager.limit) + 1 + + -- Size:limit + if + attached {WSF_STRING} req.query_parameter ("size") as l_size and then + l_size.is_integer + then + pager.set_limit (l_size.integer_value.to_natural_32) + end + + + + --Page:offset + if + attached {WSF_STRING} req.query_parameter ("page") as ll_page and then + ll_page.is_integer + then + current_page := ll_page.integer_value + if current_page > 1 then + pager.set_offset (((current_page-1)*(pager.limit.to_integer_32)).to_natural_32) + end + else + current_page := 1 + end + + -- NOTE: for development purposes we have the following hardcode output. create s.make_from_string ("

    Nodes:

    ") - if attached node_api.nodes as lst then + + s.append ("

    Current Page:" + current_page.out + " of " + number_of_pages.out + " pages

    " ) + -- pager + s.append ("
    %N") + s.append ("
      %N") + create lnk.make ("First", "nodes/?page=1&size="+pager.limit.out) + s.append ("
    • ") + s.append (l_page.link (lnk.title, lnk.location, Void)) + s.append ("
    • ") + if (current_page - 1) > 1 then + create lnk.make ("Prev", "nodes/?page="+ (current_page-1).out +"&size="+pager.limit.out) + s.append ("
    • ") + s.append (l_page.link (lnk.title, lnk.location, Void)) + s.append ("
    • ") + end + + if (current_page + 1) < number_of_pages then + create lnk.make ("Next", "nodes/?page="+ (current_page+1).out +"&size="+pager.limit.out) + s.append ("
    • ") + s.append (l_page.link (lnk.title, lnk.location, Void)) + s.append ("
    • ") + end + create lnk.make ("Last", "nodes/?page="+ number_of_pages.out +"&size="+pager.limit.out) + s.append ("
    • ") + s.append (l_page.link (lnk.title, lnk.location, Void)) + s.append ("
    • ") + + + s.append ("
    %N") + s.append ("
    %N") + + if attached pager.list as lst then s.append ("
      %N") across lst as ic @@ -61,7 +122,6 @@ feature -- HTTP Methods lnk := node_api.node_link (n) s.append ("
    • ") s.append (l_page.link (lnk.title, lnk.location, Void)) --- s.append (l_page.link (n.title + " (#" + n.id.out + ")", node_api.node_path (n), Void)) s.append ("
    • %N") end s.append ("
    %N") diff --git a/modules/node/handler/page_builder.e b/modules/node/handler/page_builder.e new file mode 100644 index 0000000..61319c6 --- /dev/null +++ b/modules/node/handler/page_builder.e @@ -0,0 +1,70 @@ +note + description: "Generic Page Builder Interface" + date: "$Date$" + revision: "$Revision$" + +deferred class + PAGE_BUILDER [G->CMS_NODE] + +inherit + CMS_NODE_HANDLER + +feature -- Access + + set_limit (a_limit: NATURAL) + -- Set limit with `a_limit'. + do + limit := a_limit + ensure + limit_set: limit = a_limit + end + + set_offset (a_offset: NATURAL) + -- Set offset with `a_offset'. + do + offset := a_offset + ensure + limit_set: offset = a_offset + end + + set_order_by_asc (a_field: READABLE_STRING_32) + -- Pager with a order_by `a_field' asc. + do + order_by := a_field + order_ascending := True + ensure + order_by_set: attached order_by as l_order_by implies l_order_by = a_field + asc_true: order_ascending + end + + set_order_by_desc (a_field: READABLE_STRING_32) + -- Pager with a order_by `a_field' desc. + do + order_by := a_field + order_ascending := False + ensure + order_by_set: attached order_by as l_order_by implies l_order_by = a_field + asc_fasle: not order_ascending + end + +feature -- Pager + + list: LIST[G] + -- List of G with filters. + deferred + end + +feature -- Access + + limit: NATURAL + -- Number of rows per page. + + offset: NATURAL + -- rows starting from the next row to the given OFFSET. + + order_by: detachable STRING + -- field to order by + + order_ascending: BOOLEAN + -- is ascending ordering? +end diff --git a/modules/node/node_module.e b/modules/node/node_module.e index 366b34b..67fadac 100644 --- a/modules/node/node_module.e +++ b/modules/node/node_module.e @@ -186,10 +186,12 @@ feature -- Hooks create lnk.make ("List of nodes", "nodes") a_menu_system.primary_menu.extend (lnk) - create lnk.make ("Trash", a_response.url ("trash", Void)) +-- create lnk.make ("Trash", a_response.url ("trash/", Void)) + create lnk.make ("Trash", "trash") a_menu_system.primary_menu.extend (lnk) - create lnk.make ("Create ..", a_response.url ("node/", Void)) +-- create lnk.make ("Create ..", a_response.url ("node/", Void)) + create lnk.make ("Create ..", "node") a_menu_system.primary_menu.extend (lnk) end From 306b39ab7829edb48cdf18a18c7688ea6eec57ca Mon Sep 17 00:00:00 2001 From: jvelilla Date: Thu, 21 May 2015 16:46:06 -0300 Subject: [PATCH 13/27] Updated code based on Jocelyn's suggestions. --- modules/node/handler/node_page_builder.e | 25 ++++++++++++------- ...ge_builder.e => node_pagination_builder.e} | 7 ++---- 2 files changed, 18 insertions(+), 14 deletions(-) rename modules/node/handler/{page_builder.e => node_pagination_builder.e} (92%) diff --git a/modules/node/handler/node_page_builder.e b/modules/node/handler/node_page_builder.e index f6f7715..923caa2 100644 --- a/modules/node/handler/node_page_builder.e +++ b/modules/node/handler/node_page_builder.e @@ -1,6 +1,5 @@ note - description: "Summary description for {NODE_PAGE_BUILDER}." - author: "" + description: "Paginator builder for CMS nodes." date: "$Date$" revision: "$Revision$" @@ -9,28 +8,36 @@ class inherit - PAGE_BUILDER [CMS_NODE] - rename - make as page_make + NODE_PAGINATION_BUILDER [CMS_NODE] + + CMS_NODE_HANDLER + redefine + make end create - make feature {NONE} -- Initialization make (a_api: CMS_API; a_module_api: CMS_NODE_API) + -- Create an object. do - page_make (a_api, a_module_api) + Precursor (a_api, a_module_api) limit := 5 offset := 0 + ensure then + limit_set: limit = 5 + offset_set: offset = 0 end feature -- Pager - list: LIST[CMS_NODE] + list: LIST [CMS_NODE] + -- . do - create {ARRAYED_LIST[CMS_NODE]}Result.make (0) + --NOTE: the current implementation does not use + -- order by and ordering. + create {ARRAYED_LIST [CMS_NODE]} Result.make (0) Result := node_api.recent_nodes (offset.as_integer_32, limit.as_integer_32) end diff --git a/modules/node/handler/page_builder.e b/modules/node/handler/node_pagination_builder.e similarity index 92% rename from modules/node/handler/page_builder.e rename to modules/node/handler/node_pagination_builder.e index 61319c6..25fbbf8 100644 --- a/modules/node/handler/page_builder.e +++ b/modules/node/handler/node_pagination_builder.e @@ -1,13 +1,10 @@ note - description: "Generic Page Builder Interface" + description: "Generic Node Pagination Builder Interface" date: "$Date$" revision: "$Revision$" deferred class - PAGE_BUILDER [G->CMS_NODE] - -inherit - CMS_NODE_HANDLER + NODE_PAGINATION_BUILDER [G] feature -- Access From 77f52388c1a5cf9b740a3935ab0d99627f7a8278 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Fri, 22 May 2015 22:37:18 +0200 Subject: [PATCH 14/27] Improved site_url and base_url interface and initialization. Added CMS_CUSTOM_RESPONSE_MESSAGE interface to send easily simple response message. Updated CMS_RESPONSE to use CMS_CUSTOM_RESPONSE_MESSAGE --- src/service/handler/cms_handler.e | 12 ++++ src/service/response/cms_response.e | 31 +++++++-- .../message/cms_custom_response_message.e | 64 +++++++++++++++++++ src/theme/cms_theme.e | 17 ++--- 4 files changed, 109 insertions(+), 15 deletions(-) create mode 100644 src/service/response/message/cms_custom_response_message.e diff --git a/src/service/handler/cms_handler.e b/src/service/handler/cms_handler.e index 56517e4..ae2f3b9 100644 --- a/src/service/handler/cms_handler.e +++ b/src/service/handler/cms_handler.e @@ -36,6 +36,18 @@ feature -- Response helpers -- res.send (create {CMS_REDIRECTION_RESPONSE_MESSAGE}.make (a_location)) end + send_bad_request_message (res: WSF_RESPONSE) + -- Send via `res' a bad request response. + do + res.send (create {CMS_CUSTOM_RESPONSE_MESSAGE}.make ({HTTP_STATUS_CODE}.bad_request)) + end + + send_not_found_message (res: WSF_RESPONSE) + -- Send via `res' a bad request response. + do + res.send (create {CMS_CUSTOM_RESPONSE_MESSAGE}.make ({HTTP_STATUS_CODE}.not_found)) + end + send_access_denied_message (res: WSF_RESPONSE) -- Send via `res' an access denied response. do diff --git a/src/service/response/cms_response.e b/src/service/response/cms_response.e index b0dc598..0df5bf1 100644 --- a/src/service/response/cms_response.e +++ b/src/service/response/cms_response.e @@ -3,8 +3,8 @@ note Generic CMS Response. It builds the content to get process to render the output. ]" - date: "$Date: 2015-02-16 20:14:19 +0100 (lun., 16 févr. 2015) $" - revision: "$Revision: 96643 $" + date: "$Date: 2015-05-20 11:48:26 +0200 (mer., 20 mai 2015) $" + revision: "$Revision: 97327 $" deferred class CMS_RESPONSE @@ -40,14 +40,19 @@ feature {NONE} -- Initialization initialize_site_url -- Initialize site and base url. local - l_url: detachable READABLE_STRING_8 + l_url: detachable STRING_8 i,j: INTEGER do --| WARNING: do not use `absolute_url' and `url', since it relies on site_url and base_url. - l_url := setup.site_url - if l_url = Void then + if attached setup.site_url as l_site_url and then not l_site_url.is_empty then + create l_url.make_from_string (l_site_url) + else l_url := request.absolute_script_url ("/") end + check is_not_empty: not l_url.is_empty end + if l_url [l_url.count] /= '/' then + l_url.append_character ('/') + end site_url := l_url i := l_url.substring_index ("://", 1) if i > 0 then @@ -56,6 +61,9 @@ feature {NONE} -- Initialization base_url := l_url.substring (j, l_url.count) end end + ensure + site_url_set: site_url /= Void + site_url_ends_with_slash: site_url.ends_with_general ("/") end register_hooks @@ -98,6 +106,15 @@ feature -- Access redirection: detachable READABLE_STRING_8 -- Location for eventual redirection. + location: STRING_8 + -- Associated cms local location. + do + create Result.make_from_string (request.percent_encoded_path_info) + if not Result.is_empty and then Result[1] = '/' then + Result.remove_head (1) + end + end + feature -- Internationalization (i18n) translation (a_text: READABLE_STRING_GENERAL; opts: detachable CMS_API_OPTIONS): STRING_32 @@ -185,10 +202,10 @@ feature -- URL utilities end end - site_url: READABLE_STRING_8 + site_url: IMMUTABLE_STRING_8 -- Absolute site url. - base_url: detachable READABLE_STRING_8 + base_url: detachable IMMUTABLE_STRING_8 -- Base url if any. --| Usually it is Void, but it could be --| /project/demo/ diff --git a/src/service/response/message/cms_custom_response_message.e b/src/service/response/message/cms_custom_response_message.e new file mode 100644 index 0000000..7c2f435 --- /dev/null +++ b/src/service/response/message/cms_custom_response_message.e @@ -0,0 +1,64 @@ +note + description: "Custom cms response message." + date: "$Date$" + revision: "$Revision$" + +class + CMS_CUSTOM_RESPONSE_MESSAGE + +inherit + CMS_RESPONSE_MESSAGE + redefine + send_payload_to + end + +create + make + +feature {NONE} -- Initialization + + make (a_code: INTEGER) + -- Set `status_code' to `a_code'. + require + a_code_valid: a_code > 0 + do + initialize + status_code := a_code + end + +feature -- Access + + payload: detachable READABLE_STRING_8 + -- Optional payload. + +feature -- Element change + + set_status_code (a_code: INTEGER) + -- Set `status_code' to `a_code'. + require + a_code_valid: a_code > 0 + do + status_code := a_code + end + + set_payload (s: detachable READABLE_STRING_8) + -- Set `payload' to `s'. + do + if s /= Void then + payload := s + header.put_content_length (s.count) + else + end + end + +feature {WSF_RESPONSE} -- Output + + send_payload_to (res: WSF_RESPONSE) + -- Send payload data to response `res'. + do + if attached payload as s then + res.put_string (s) + end + end + +end diff --git a/src/theme/cms_theme.e b/src/theme/cms_theme.e index f88f7e9..0bc2b69 100644 --- a/src/theme/cms_theme.e +++ b/src/theme/cms_theme.e @@ -1,7 +1,7 @@ note description: "Abstract class describing a generic theme" - date: "$Date: 2015-02-16 12:52:35 +0100 (lun., 16 févr. 2015) $" - revision: "$Revision: 96630 $" + date: "$Date: 2015-05-20 11:48:26 +0200 (mer., 20 mai 2015) $" + revision: "$Revision: 97327 $" deferred class CMS_THEME @@ -18,10 +18,10 @@ feature {NONE} -- Access setup: CMS_SETUP - site_url: READABLE_STRING_8 assign set_site_url + site_url: IMMUTABLE_STRING_8 -- Absolute URL for Current CMS site. - base_url: detachable READABLE_STRING_8 + base_url: detachable IMMUTABLE_STRING_8 -- Optional base url of current CMS site. feature -- Access @@ -59,16 +59,17 @@ feature -- Element change i,j: INTEGER do base_url := Void - if a_url[a_url.count] = '/' then - site_url := a_url + if a_url [a_url.count] = '/' then + create site_url.make_from_string (a_url) else - site_url := a_url + "/" + create site_url.make_from_string (a_url + "/") end + i := a_url.substring_index ("://", 1) if i > 0 then j := a_url.index_of ('/', i + 3) if j > 0 then - base_url := a_url.substring (j, a_url.count) + create base_url.make_from_string (a_url.substring (j, a_url.count)) end end end From b77c5cd93c1a67dee8086998958f042524e9e9ef Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Fri, 22 May 2015 23:04:09 +0200 Subject: [PATCH 15/27] Added abstraction of cms storage on file system. (mostly helpers features). --- src/persistence/sql/cms_storage_fs_i.e | 107 +++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 src/persistence/sql/cms_storage_fs_i.e diff --git a/src/persistence/sql/cms_storage_fs_i.e b/src/persistence/sql/cms_storage_fs_i.e new file mode 100644 index 0000000..2cb025f --- /dev/null +++ b/src/persistence/sql/cms_storage_fs_i.e @@ -0,0 +1,107 @@ +note + description: "Interface used to implement CMS Storage based on File system." + date: "$Date: 2015-02-13 13:08:13 +0100 (ven., 13 févr. 2015) $" + revision: "$Revision: 96616 $" + +deferred class + CMS_STORAGE_FS_I + +inherit + SHARED_LOGGER + +feature {NONE} -- Initialization + + make (a_location: PATH; a_api: CMS_API) + do + location := a_location + api := a_api + create error_handler.make + end + +feature -- Access + + api: CMS_API + -- Associated CMS api. + + location: PATH + -- File system location. + +feature -- Error handler + + error_handler: ERROR_HANDLER + -- Error handler. + + has_error: BOOLEAN + -- Last operation reported error. + do + Result := error_handler.has_error + end + + reset_error + -- Reset errors. + do + error_handler.reset + end + +feature -- Helpers + + save_to_file (a_text: STRING; opt_name: detachable READABLE_STRING_GENERAL) + local + s: READABLE_STRING_GENERAL + now: DATE_TIME + fut: WSF_FILE_UTILITIES [RAW_FILE] + do + create fut + if opt_name /= Void then + s := opt_name + else + create now.make_now_utc + s := date_to_yyyymmdd_hhmmss_string (now) + end + if attached fut.new_file (location.extended (s)) as f then + f.put_string (a_text) + f.close + else + error_handler.add_custom_error (0, "saving failure", Void) + end + end + + date_to_yyyymmdd_hhmmss_string (d: DATE_TIME): STRING + local + i: INTEGER + do + create Result.make_empty + Result.append_integer (d.year) + Result.append_character ('-') + i := d.month + if i < 10 then + Result.append_integer (0) + end + Result.append_integer (i) + Result.append_character ('-') + i := d.day + if i < 10 then + Result.append_integer (0) + end + Result.append_integer (i) + Result.append_character ('_') + i := d.hour + if i < 10 then + Result.append_integer (0) + end + Result.append_integer (i) + Result.append_character ('-') + i := d.minute + if i < 10 then + Result.append_integer (0) + end + Result.append_integer (i) + Result.append_character ('-') + i := d.second + if i < 10 then + Result.append_integer (0) + end + Result.append_integer (i) + end + +end From 323ac598d0e86b5db7a886e8aeb4de7f39caeeb6 Mon Sep 17 00:00:00 2001 From: jvelilla Date: Tue, 26 May 2015 20:24:05 -0300 Subject: [PATCH 16/27] Updated code based on comments --- modules/node/handler/node_page_builder.e | 44 ------------ .../node/handler/node_pagination_builder.e | 67 ------------------- modules/node/handler/nodes_handler.e | 2 +- 3 files changed, 1 insertion(+), 112 deletions(-) delete mode 100644 modules/node/handler/node_page_builder.e delete mode 100644 modules/node/handler/node_pagination_builder.e diff --git a/modules/node/handler/node_page_builder.e b/modules/node/handler/node_page_builder.e deleted file mode 100644 index 923caa2..0000000 --- a/modules/node/handler/node_page_builder.e +++ /dev/null @@ -1,44 +0,0 @@ -note - description: "Paginator builder for CMS nodes." - date: "$Date$" - revision: "$Revision$" - -class - NODE_PAGE_BUILDER - -inherit - - NODE_PAGINATION_BUILDER [CMS_NODE] - - CMS_NODE_HANDLER - redefine - make - end -create - make - -feature {NONE} -- Initialization - - make (a_api: CMS_API; a_module_api: CMS_NODE_API) - -- Create an object. - do - Precursor (a_api, a_module_api) - limit := 5 - offset := 0 - ensure then - limit_set: limit = 5 - offset_set: offset = 0 - end - -feature -- Pager - - list: LIST [CMS_NODE] - -- . - do - --NOTE: the current implementation does not use - -- order by and ordering. - create {ARRAYED_LIST [CMS_NODE]} Result.make (0) - Result := node_api.recent_nodes (offset.as_integer_32, limit.as_integer_32) - end - -end diff --git a/modules/node/handler/node_pagination_builder.e b/modules/node/handler/node_pagination_builder.e deleted file mode 100644 index 25fbbf8..0000000 --- a/modules/node/handler/node_pagination_builder.e +++ /dev/null @@ -1,67 +0,0 @@ -note - description: "Generic Node Pagination Builder Interface" - date: "$Date$" - revision: "$Revision$" - -deferred class - NODE_PAGINATION_BUILDER [G] - -feature -- Access - - set_limit (a_limit: NATURAL) - -- Set limit with `a_limit'. - do - limit := a_limit - ensure - limit_set: limit = a_limit - end - - set_offset (a_offset: NATURAL) - -- Set offset with `a_offset'. - do - offset := a_offset - ensure - limit_set: offset = a_offset - end - - set_order_by_asc (a_field: READABLE_STRING_32) - -- Pager with a order_by `a_field' asc. - do - order_by := a_field - order_ascending := True - ensure - order_by_set: attached order_by as l_order_by implies l_order_by = a_field - asc_true: order_ascending - end - - set_order_by_desc (a_field: READABLE_STRING_32) - -- Pager with a order_by `a_field' desc. - do - order_by := a_field - order_ascending := False - ensure - order_by_set: attached order_by as l_order_by implies l_order_by = a_field - asc_fasle: not order_ascending - end - -feature -- Pager - - list: LIST[G] - -- List of G with filters. - deferred - end - -feature -- Access - - limit: NATURAL - -- Number of rows per page. - - offset: NATURAL - -- rows starting from the next row to the given OFFSET. - - order_by: detachable STRING - -- field to order by - - order_ascending: BOOLEAN - -- is ascending ordering? -end diff --git a/modules/node/handler/nodes_handler.e b/modules/node/handler/nodes_handler.e index 6f33259..53288a6 100644 --- a/modules/node/handler/nodes_handler.e +++ b/modules/node/handler/nodes_handler.e @@ -41,7 +41,7 @@ feature -- HTTP Methods s: STRING n: CMS_NODE lnk: CMS_LOCAL_LINK - pager: NODE_PAGE_BUILDER + pager: CMS_NODE_PAGINATION_BUILDER number_of_pages: INTEGER_64 current_page: INTEGER do From ad9dd01f22ce1876bd19dc68af4c0216c1eb9641 Mon Sep 17 00:00:00 2001 From: jvelilla Date: Tue, 26 May 2015 20:25:45 -0300 Subject: [PATCH 17/27] Update based on comments --- .../handler/cms_node_pagination_builder.e | 44 ++++++++++++ modules/node/handler/cms_pagination_builder.e | 67 +++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 modules/node/handler/cms_node_pagination_builder.e create mode 100644 modules/node/handler/cms_pagination_builder.e diff --git a/modules/node/handler/cms_node_pagination_builder.e b/modules/node/handler/cms_node_pagination_builder.e new file mode 100644 index 0000000..5fb641a --- /dev/null +++ b/modules/node/handler/cms_node_pagination_builder.e @@ -0,0 +1,44 @@ +note + description: "Paginator builder for CMS nodes." + date: "$Date$" + revision: "$Revision$" + +class + CMS_NODE_PAGINATION_BUILDER + +inherit + + CMS_PAGINATION_BUILDER [CMS_NODE] + + CMS_NODE_HANDLER + redefine + make + end +create + make + +feature {NONE} -- Initialization + + make (a_api: CMS_API; a_module_api: CMS_NODE_API) + -- Create an object. + do + Precursor (a_api, a_module_api) + limit := 5 + offset := 0 + ensure then + limit_set: limit = 5 + offset_set: offset = 0 + end + +feature -- Pager + + list: ITERABLE [CMS_NODE] + -- . + do + --NOTE: the current implementation does not use + -- order by and ordering. + create {ARRAYED_LIST [CMS_NODE]} Result.make (0) + Result := node_api.recent_nodes (offset.as_integer_32, limit.as_integer_32) + end + +end diff --git a/modules/node/handler/cms_pagination_builder.e b/modules/node/handler/cms_pagination_builder.e new file mode 100644 index 0000000..cd9d20f --- /dev/null +++ b/modules/node/handler/cms_pagination_builder.e @@ -0,0 +1,67 @@ +note + description: "Generic Pagination Builder Interface" + date: "$Date$" + revision: "$Revision$" + +deferred class + CMS_PAGINATION_BUILDER [G] + +feature -- Access + + set_limit (a_limit: NATURAL) + -- Set limit with `a_limit'. + do + limit := a_limit + ensure + limit_set: limit = a_limit + end + + set_offset (a_offset: NATURAL) + -- Set offset with `a_offset'. + do + offset := a_offset + ensure + limit_set: offset = a_offset + end + + set_ascending_order (a_field: READABLE_STRING_32) + -- Pager with a order_by `a_field' asc. + do + order_by := a_field + order_ascending := True + ensure + order_by_set: attached order_by as l_order_by implies l_order_by = a_field + asc_true: order_ascending + end + + set_descending_order (a_field: READABLE_STRING_32) + -- Pager with a order_by `a_field' desc. + do + order_by := a_field + order_ascending := False + ensure + order_by_set: attached order_by as l_order_by implies l_order_by = a_field + asc_fasle: not order_ascending + end + +feature -- Pager + + list: ITERABLE[G] + -- Iterable of G with filters. + deferred + end + +feature -- Access + + limit: NATURAL + -- Number of rows per page. + + offset: NATURAL + -- rows starting from the next row to the given OFFSET. + + order_by: detachable STRING + -- field to order by + + order_ascending: BOOLEAN + -- is ascending ordering? +end From 957ca96bc5a6e30037660e20f83e270bbdf140af Mon Sep 17 00:00:00 2001 From: jvelilla Date: Wed, 27 May 2015 11:26:49 -0300 Subject: [PATCH 18/27] Updated code based on comments. --- .../handler/cms_node_pagination_builder.e | 22 ++++---- modules/node/handler/cms_pagination_builder.e | 18 +++--- modules/node/handler/nodes_handler.e | 55 ++++++++++--------- 3 files changed, 50 insertions(+), 45 deletions(-) diff --git a/modules/node/handler/cms_node_pagination_builder.e b/modules/node/handler/cms_node_pagination_builder.e index 5fb641a..b19f32a 100644 --- a/modules/node/handler/cms_node_pagination_builder.e +++ b/modules/node/handler/cms_node_pagination_builder.e @@ -10,35 +10,35 @@ inherit CMS_PAGINATION_BUILDER [CMS_NODE] - CMS_NODE_HANDLER - redefine - make - end create make feature {NONE} -- Initialization - make (a_api: CMS_API; a_module_api: CMS_NODE_API) + make (a_api: CMS_NODE_API) -- Create an object. do - Precursor (a_api, a_module_api) - limit := 5 + node_api := a_api + count := 5 offset := 0 - ensure then - limit_set: limit = 5 + ensure + node_api_set: node_api = a_api + limit_set: count = 5 offset_set: offset = 0 end + node_api: CMS_NODE_API + -- CMS API. + feature -- Pager - list: ITERABLE [CMS_NODE] + items: ITERABLE [CMS_NODE] -- . do --NOTE: the current implementation does not use -- order by and ordering. create {ARRAYED_LIST [CMS_NODE]} Result.make (0) - Result := node_api.recent_nodes (offset.as_integer_32, limit.as_integer_32) + Result := node_api.recent_nodes (offset.as_integer_32, count.as_integer_32) end end diff --git a/modules/node/handler/cms_pagination_builder.e b/modules/node/handler/cms_pagination_builder.e index cd9d20f..7ca2be3 100644 --- a/modules/node/handler/cms_pagination_builder.e +++ b/modules/node/handler/cms_pagination_builder.e @@ -8,12 +8,12 @@ deferred class feature -- Access - set_limit (a_limit: NATURAL) - -- Set limit with `a_limit'. + set_count (a_count: NATURAL) + -- Set `count' with `a_count'. do - limit := a_limit + count := a_count ensure - limit_set: limit = a_limit + count_set: count = a_count end set_offset (a_offset: NATURAL) @@ -46,21 +46,21 @@ feature -- Access feature -- Pager - list: ITERABLE[G] + items: ITERABLE [G] -- Iterable of G with filters. deferred end feature -- Access - limit: NATURAL - -- Number of rows per page. + count: NATURAL + -- Number of items per page. offset: NATURAL - -- rows starting from the next row to the given OFFSET. + -- lower index of `items' pagination. order_by: detachable STRING - -- field to order by + -- field to order by. order_ascending: BOOLEAN -- is ascending ordering? diff --git a/modules/node/handler/nodes_handler.e b/modules/node/handler/nodes_handler.e index 53288a6..eddc92d 100644 --- a/modules/node/handler/nodes_handler.e +++ b/modules/node/handler/nodes_handler.e @@ -37,7 +37,7 @@ feature -- HTTP Methods do_get (req: WSF_REQUEST; res: WSF_RESPONSE) -- local - l_page: CMS_RESPONSE + l_response: CMS_RESPONSE s: STRING n: CMS_NODE lnk: CMS_LOCAL_LINK @@ -49,30 +49,30 @@ feature -- HTTP Methods -- get them from the configuration file and load them into -- the setup class. - create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api) - l_page.add_variable (node_api.nodes, "nodes") + create {GENERIC_VIEW_CMS_RESPONSE} l_response.make (req, res, api) + l_response.add_variable (node_api.nodes, "nodes") - create pager.make (api, node_api) - number_of_pages := (node_api.nodes_count // pager.limit) + 1 + create pager.make (node_api) + number_of_pages := (node_api.nodes_count // pager.count) + 1 -- Size:limit if attached {WSF_STRING} req.query_parameter ("size") as l_size and then l_size.is_integer then - pager.set_limit (l_size.integer_value.to_natural_32) + pager.set_count (l_size.integer_value.to_natural_32) end --Page:offset if - attached {WSF_STRING} req.query_parameter ("page") as ll_page and then - ll_page.is_integer + attached {WSF_STRING} req.query_parameter ("page") as l_page and then + l_page.is_integer then - current_page := ll_page.integer_value + current_page := l_page.integer_value if current_page > 1 then - pager.set_offset (((current_page-1)*(pager.limit.to_integer_32)).to_natural_32) + pager.set_offset (((current_page-1)*(pager.count.to_integer_32)).to_natural_32) end else current_page := 1 @@ -81,39 +81,44 @@ feature -- HTTP Methods -- NOTE: for development purposes we have the following hardcode output. - create s.make_from_string ("

    Nodes:

    ") + create s.make_from_string ("

    Items:

    ") + + s.append ("

    Current Page:") + s.append_integer (current_page) + s.append (" of ") + s.append_integer_64 (number_of_pages) + s.append (" pages

    ") - s.append ("

    Current Page:" + current_page.out + " of " + number_of_pages.out + " pages

    " ) -- pager s.append ("
    %N") s.append ("
      %N") - create lnk.make ("First", "nodes/?page=1&size="+pager.limit.out) + create lnk.make ("First", "nodes/?page=1&size="+pager.count.out) s.append ("
    • ") - s.append (l_page.link (lnk.title, lnk.location, Void)) + s.append (l_response.link (lnk.title, lnk.location, Void)) s.append ("
    • ") if (current_page - 1) > 1 then - create lnk.make ("Prev", "nodes/?page="+ (current_page-1).out +"&size="+pager.limit.out) + create lnk.make ("Prev", "nodes/?page="+ (current_page-1).out +"&size="+pager.count.out) s.append ("
    • ") - s.append (l_page.link (lnk.title, lnk.location, Void)) + s.append (l_response.link (lnk.title, lnk.location, Void)) s.append ("
    • ") end if (current_page + 1) < number_of_pages then - create lnk.make ("Next", "nodes/?page="+ (current_page+1).out +"&size="+pager.limit.out) + create lnk.make ("Next", "nodes/?page="+ (current_page+1).out +"&size="+pager.count.out) s.append ("
    • ") - s.append (l_page.link (lnk.title, lnk.location, Void)) + s.append (l_response.link (lnk.title, lnk.location, Void)) s.append ("
    • ") end - create lnk.make ("Last", "nodes/?page="+ number_of_pages.out +"&size="+pager.limit.out) + create lnk.make ("Last", "nodes/?page="+ number_of_pages.out +"&size="+pager.count.out) s.append ("
    • ") - s.append (l_page.link (lnk.title, lnk.location, Void)) + s.append (l_response.link (lnk.title, lnk.location, Void)) s.append ("
    • ") s.append ("
    %N") s.append ("
    %N") - if attached pager.list as lst then + if attached pager.items as lst then s.append ("
      %N") across lst as ic @@ -121,15 +126,15 @@ feature -- HTTP Methods n := ic.item lnk := node_api.node_link (n) s.append ("
    • ") - s.append (l_page.link (lnk.title, lnk.location, Void)) + s.append (l_response.link (lnk.title, lnk.location, Void)) s.append ("
    • %N") end s.append ("
    %N") end - l_page.set_main_content (s) - l_page.add_block (create {CMS_CONTENT_BLOCK}.make ("nodes_warning", Void, "/nodes/ is not yet fully implemented
    ", Void), "highlighted") - l_page.execute + l_response.set_main_content (s) + l_response.add_block (create {CMS_CONTENT_BLOCK}.make ("nodes_warning", Void, "/nodes/ is not yet fully implemented
    ", Void), "highlighted") + l_response.execute end end From f056b43ddc4aabd8aad74e53d5b61769a26bc11f Mon Sep 17 00:00:00 2001 From: jvelilla Date: Fri, 29 May 2015 09:25:28 -0300 Subject: [PATCH 19/27] Updated CMS PAGINATION with the last Jocelyn's suggestion. Added a node pagination helper, to build the html links and header related to pagination. --- modules/node/cms_node_api.e | 4 +- .../handler/cms_node_pagination_builder.e | 44 ------ .../node/handler/cms_node_pagination_helper.e | 138 ++++++++++++++++++ modules/node/handler/cms_pagination_builder.e | 28 +++- modules/node/handler/nodes_handler.e | 78 +--------- 5 files changed, 168 insertions(+), 124 deletions(-) delete mode 100644 modules/node/handler/cms_node_pagination_builder.e create mode 100644 modules/node/handler/cms_node_pagination_helper.e diff --git a/modules/node/cms_node_api.e b/modules/node/cms_node_api.e index 5f328df..b720daf 100644 --- a/modules/node/cms_node_api.e +++ b/modules/node/cms_node_api.e @@ -220,10 +220,10 @@ feature -- Access: Node Result := node_storage.trashed_nodes (a_user.id) end - recent_nodes (a_offset, a_rows: INTEGER): LIST [CMS_NODE] + recent_nodes (a_pagination: CMS_PAGINATION_BUILDER): ITERABLE [CMS_NODE] -- List of the `a_rows' most recent nodes starting from `a_offset'. do - Result := node_storage.recent_nodes (a_offset, a_rows) + Result := node_storage.recent_nodes (a_pagination.offset.to_integer_32, a_pagination.count.to_integer_32) end node (a_id: INTEGER_64): detachable CMS_NODE diff --git a/modules/node/handler/cms_node_pagination_builder.e b/modules/node/handler/cms_node_pagination_builder.e deleted file mode 100644 index b19f32a..0000000 --- a/modules/node/handler/cms_node_pagination_builder.e +++ /dev/null @@ -1,44 +0,0 @@ -note - description: "Paginator builder for CMS nodes." - date: "$Date$" - revision: "$Revision$" - -class - CMS_NODE_PAGINATION_BUILDER - -inherit - - CMS_PAGINATION_BUILDER [CMS_NODE] - -create - make - -feature {NONE} -- Initialization - - make (a_api: CMS_NODE_API) - -- Create an object. - do - node_api := a_api - count := 5 - offset := 0 - ensure - node_api_set: node_api = a_api - limit_set: count = 5 - offset_set: offset = 0 - end - - node_api: CMS_NODE_API - -- CMS API. - -feature -- Pager - - items: ITERABLE [CMS_NODE] - -- . - do - --NOTE: the current implementation does not use - -- order by and ordering. - create {ARRAYED_LIST [CMS_NODE]} Result.make (0) - Result := node_api.recent_nodes (offset.as_integer_32, count.as_integer_32) - end - -end diff --git a/modules/node/handler/cms_node_pagination_helper.e b/modules/node/handler/cms_node_pagination_helper.e new file mode 100644 index 0000000..7eb04d2 --- /dev/null +++ b/modules/node/handler/cms_node_pagination_helper.e @@ -0,0 +1,138 @@ +note + description: "Helper class to build the html pagination links and header summary" + date: "$Date$" + revision: "$Revision$" + +class + CMS_NODE_PAGINATION_HELPER + + +create + make + +feature {NONE} -- Initialization + + make (a_req: WSF_REQUEST; a_response: CMS_RESPONSE; a_nodes_count: INTEGER_64) + -- Create an object with default values. + do + make_size (a_req, a_response, a_nodes_count, 5) + end + + make_size (a_req: WSF_REQUEST; a_response: CMS_RESPONSE; a_nodes_count: INTEGER_64; a_size: NATURAL) + -- Create an object with a pages of size `a_size'. + do + req := a_req + number_of_nodes := a_nodes_count + create pager + pager.set_count (a_size) + response := a_response + process + end + + req: WSF_REQUEST + -- Current request. + + process + -- Process request query paraments to build the pager. + do + --TODO: at the moment the code looks for hardcoded parameters + -- sie and page, maybe we can parametrize these names. + -- Size:limit. + if + attached {WSF_STRING} req.query_parameter ("size") as l_size and then + l_size.is_integer + then + pager.set_count (l_size.integer_value.to_natural_32) + end + + --Page:offset + if + attached {WSF_STRING} req.query_parameter ("page") as l_page and then + l_page.is_integer + then + current_page := l_page.integer_value + if current_page > 1 then + pager.set_offset (((current_page-1)*(pager.count.to_integer_32)).to_natural_32) + end + else + current_page := 1 + end + end + +feature -- Access + + pager: CMS_PAGINATION_BUILDER + -- Paginator. + + current_page: INTEGER + -- current page. + + number_of_pages: INTEGER_64 + -- total number of pages. + do + Result := (number_of_nodes // pager.count.as_integer_32) + 1 + end + + number_of_nodes: INTEGER_64 + -- number of nodes. + + response: CMS_RESPONSE + -- cms response + +feature -- Paginator + + paging_summary: STRING + -- Header summary + -- Current page 1 of n pages. + do + create Result.make_from_string ("

    Items:

    ") + + Result.append ("

    Current Page:") + Result.append_integer (current_page) + Result.append (" of ") + Result.append_integer_64 (number_of_pages) + Result.append (" pages

    ") + end + + + build_html_node_paging: STRING + -- First, [Prev], [Next], Last. + local + s: STRING + lnk: CMS_LOCAL_LINK + + do + -- NOTE: for development purposes we have the following hardcode output. + create s.make_empty + + -- pager + s.append ("
    %N") + s.append ("
      %N") + create lnk.make ("First", "nodes/?page=1&size="+pager.count.out) + s.append ("
    • ") + s.append (response.link (lnk.title, lnk.location, Void)) + s.append ("
    • ") + if (current_page - 1) > 1 then + create lnk.make ("Prev", "nodes/?page="+ (current_page-1).out +"&size="+pager.count.out) + s.append ("
    • ") + s.append (response.link (lnk.title, lnk.location, Void)) + s.append ("
    • ") + end + + if (current_page + 1) < number_of_pages then + create lnk.make ("Next", "nodes/?page="+ (current_page+1).out +"&size="+pager.count.out) + s.append ("
    • ") + s.append (response.link (lnk.title, lnk.location, Void)) + s.append ("
    • ") + end + create lnk.make ("Last", "nodes/?page="+ number_of_pages.out +"&size="+pager.count.out) + s.append ("
    • ") + s.append (response.link (lnk.title, lnk.location, Void)) + s.append ("
    • ") + + + s.append ("
    %N") + s.append ("
    %N") + Result := s + end +end diff --git a/modules/node/handler/cms_pagination_builder.e b/modules/node/handler/cms_pagination_builder.e index 7ca2be3..9950ff7 100644 --- a/modules/node/handler/cms_pagination_builder.e +++ b/modules/node/handler/cms_pagination_builder.e @@ -3,8 +3,26 @@ note date: "$Date$" revision: "$Revision$" -deferred class - CMS_PAGINATION_BUILDER [G] +class + CMS_PAGINATION_BUILDER + +inherit + + ANY + redefine + default_create + end + +feature {NONE} -- Initialization + + default_create + do + count := 5 + offset := 0 + ensure then + limit_set: count = 5 + offset_set: offset = 0 + end feature -- Access @@ -44,12 +62,6 @@ feature -- Access asc_fasle: not order_ascending end -feature -- Pager - - items: ITERABLE [G] - -- Iterable of G with filters. - deferred - end feature -- Access diff --git a/modules/node/handler/nodes_handler.e b/modules/node/handler/nodes_handler.e index eddc92d..681ca87 100644 --- a/modules/node/handler/nodes_handler.e +++ b/modules/node/handler/nodes_handler.e @@ -41,84 +41,20 @@ feature -- HTTP Methods s: STRING n: CMS_NODE lnk: CMS_LOCAL_LINK - pager: CMS_NODE_PAGINATION_BUILDER - number_of_pages: INTEGER_64 - current_page: INTEGER + l_page_helper: CMS_NODE_PAGINATION_HELPER do -- At the moment the template is hardcoded, but we can -- get them from the configuration file and load them into -- the setup class. create {GENERIC_VIEW_CMS_RESPONSE} l_response.make (req, res, api) - l_response.add_variable (node_api.nodes, "nodes") + create l_page_helper.make (req, l_response, node_api.nodes_count) - create pager.make (node_api) - number_of_pages := (node_api.nodes_count // pager.count) + 1 + create s.make_empty + s.append (l_page_helper.paging_summary) + s.append (l_page_helper.build_html_node_paging) - -- Size:limit - if - attached {WSF_STRING} req.query_parameter ("size") as l_size and then - l_size.is_integer - then - pager.set_count (l_size.integer_value.to_natural_32) - end - - - - --Page:offset - if - attached {WSF_STRING} req.query_parameter ("page") as l_page and then - l_page.is_integer - then - current_page := l_page.integer_value - if current_page > 1 then - pager.set_offset (((current_page-1)*(pager.count.to_integer_32)).to_natural_32) - end - else - current_page := 1 - end - - - - -- NOTE: for development purposes we have the following hardcode output. - create s.make_from_string ("

    Items:

    ") - - s.append ("

    Current Page:") - s.append_integer (current_page) - s.append (" of ") - s.append_integer_64 (number_of_pages) - s.append (" pages

    ") - - -- pager - s.append ("
    %N") - s.append ("
      %N") - create lnk.make ("First", "nodes/?page=1&size="+pager.count.out) - s.append ("
    • ") - s.append (l_response.link (lnk.title, lnk.location, Void)) - s.append ("
    • ") - if (current_page - 1) > 1 then - create lnk.make ("Prev", "nodes/?page="+ (current_page-1).out +"&size="+pager.count.out) - s.append ("
    • ") - s.append (l_response.link (lnk.title, lnk.location, Void)) - s.append ("
    • ") - end - - if (current_page + 1) < number_of_pages then - create lnk.make ("Next", "nodes/?page="+ (current_page+1).out +"&size="+pager.count.out) - s.append ("
    • ") - s.append (l_response.link (lnk.title, lnk.location, Void)) - s.append ("
    • ") - end - create lnk.make ("Last", "nodes/?page="+ number_of_pages.out +"&size="+pager.count.out) - s.append ("
    • ") - s.append (l_response.link (lnk.title, lnk.location, Void)) - s.append ("
    • ") - - - s.append ("
    %N") - s.append ("
    %N") - - if attached pager.items as lst then + if attached node_api.recent_nodes (l_page_helper.pager) as lst then s.append ("
      %N") across lst as ic @@ -132,6 +68,8 @@ feature -- HTTP Methods s.append ("
    %N") end + s.append (l_page_helper.build_html_node_paging) + l_response.set_main_content (s) l_response.add_block (create {CMS_CONTENT_BLOCK}.make ("nodes_warning", Void, "/nodes/ is not yet fully implemented
    ", Void), "highlighted") l_response.execute From 70d53b3ef1b0e62664586cfd80881529b6178c95 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Fri, 29 May 2015 19:20:31 +0200 Subject: [PATCH 20/27] Provide a default CMS_MODULE.is_installed: BOOLEAN implementation based on storage of custom value. Now use CMS_MODULE.is_initialized: BOOLEAN as precondition of many routines. Instantiation of node storage is now done in NODE_MODULE and not any more in CMS_NODE_API. CMS_NODE_API can be instantiated only by NODE_MODULE. --- examples/demo/modules/blog/cms_blog_module.e | 9 +-- modules/node/cms_node_api.e | 18 +++--- modules/node/node_module.e | 55 ++++++++++++------- modules/node/persistence/cms_node_storage_i.e | 29 +--------- package.iron | 31 +++++++++++ src/service/cms_api.e | 9 ++- src/service/cms_module.e | 23 ++++++-- src/service/cms_module_api.e | 1 - 8 files changed, 105 insertions(+), 70 deletions(-) create mode 100644 package.iron diff --git a/examples/demo/modules/blog/cms_blog_module.e b/examples/demo/modules/blog/cms_blog_module.e index d60c35e..37148db 100644 --- a/examples/demo/modules/blog/cms_blog_module.e +++ b/examples/demo/modules/blog/cms_blog_module.e @@ -11,7 +11,6 @@ inherit redefine register_hooks, initialize, - is_installed, install end @@ -53,12 +52,6 @@ feature {CMS_API} -- Module Initialization feature {CMS_API} -- Module management - is_installed (api: CMS_API): BOOLEAN - -- Is Current module installed? - do - Result := attached api.storage.custom_value ("is_initialized", "module-" + name) as v and then v.is_case_insensitive_equal_general ("yes") - end - install (api: CMS_API) local sql: STRING @@ -78,7 +71,7 @@ CREATE TABLE "blog_post_nodes"( api.logger.put_error ("Could not initialize database for blog module", generating_type) end end - api.storage.set_custom_value ("is_initialized", "module-" + name, "yes") + Precursor (api) end end diff --git a/modules/node/cms_node_api.e b/modules/node/cms_node_api.e index 5f328df..7681c64 100644 --- a/modules/node/cms_node_api.e +++ b/modules/node/cms_node_api.e @@ -16,20 +16,21 @@ inherit REFACTORING_HELPER -create - make +create {NODE_MODULE} + make_with_storage -feature {NONE} -- Implementation +feature {NONE} -- Initialization + + make_with_storage (a_api: CMS_API; a_node_storage: CMS_NODE_STORAGE_I) + do + node_storage := a_node_storage + make (a_api) + end initialize -- do Precursor - if attached {CMS_STORAGE_SQL_I} storage as l_storage_sql then - create {CMS_NODE_STORAGE_SQL} node_storage.make (l_storage_sql) - else - create {CMS_NODE_STORAGE_NULL} node_storage.make - end initialize_node_types end @@ -212,7 +213,6 @@ feature -- Access: Node Result := node_storage.nodes end - trashed_nodes (a_user: CMS_USER): LIST [CMS_NODE] -- List of nodes with status in {CMS_NODE_API}.trashed. -- if the current user is admin, it will retrieve all the trashed nodes diff --git a/modules/node/node_module.e b/modules/node/node_module.e index e4743d5..ada3124 100644 --- a/modules/node/node_module.e +++ b/modules/node/node_module.e @@ -9,14 +9,12 @@ class inherit CMS_MODULE - rename - module_api as node_api redefine register_hooks, initialize, is_installed, install, - node_api + module_api end CMS_HOOK_MENU_SYSTEM_ALTER @@ -43,15 +41,26 @@ feature {NONE} -- Initialization feature {CMS_API} -- Module Initialization - initialize (api: CMS_API) + initialize (a_api: CMS_API) -- local p1,p2: CMS_PAGE ct: CMS_PAGE_NODE_TYPE l_node_api: like node_api + l_node_storage: CMS_NODE_STORAGE_I do - Precursor (api) - create l_node_api.make (api) + Precursor (a_api) + + -- Storage initialization + if attached {CMS_STORAGE_SQL_I} a_api.storage as l_storage_sql then + create {CMS_NODE_STORAGE_SQL} l_node_storage.make (l_storage_sql) + else + -- FIXME: in case of NULL storage, should Current be disabled? + create {CMS_NODE_STORAGE_NULL} l_node_storage.make + end + + -- Node API initialization + create l_node_api.make_with_storage (a_api, l_node_storage) node_api := l_node_api -- Add support for CMS_PAGE, which requires a storage extension to store the optional "parent" id. @@ -61,7 +70,7 @@ feature {CMS_API} -- Module Initialization -- FIXME: the following code is mostly for test purpose/initialization, remove later if l_sql_node_storage.sql_table_items_count ("page_nodes") = 0 then - if attached api.user_api.user_by_id (1) as u then + if attached a_api.user_api.user_by_id (1) as u then create ct p1 := ct.new_node (Void) p1.set_title ("Welcome") @@ -81,29 +90,42 @@ feature {CMS_API} -- Module Initialization -- FIXME: maybe provide a default solution based on file system, when no SQL storage is available. -- IDEA: we could also have generic extension to node system, that handle generic addition field. end + ensure then + node_api_set: node_api /= Void end feature {CMS_API} -- Module management - is_installed (api: CMS_API): BOOLEAN + is_installed (a_api: CMS_API): BOOLEAN -- Is Current module installed? do - if attached {CMS_STORAGE_SQL_I} api.storage as l_sql_storage then + if attached {CMS_STORAGE_SQL_I} a_api.storage as l_sql_storage then Result := l_sql_storage.sql_table_exists ("nodes") and l_sql_storage.sql_table_exists ("page_nodes") end end - install (api: CMS_API) + install (a_api: CMS_API) do -- Schema - if attached {CMS_STORAGE_SQL_I} api.storage as l_sql_storage then - l_sql_storage.sql_execute_file_script (api.setup.environment.path.extended ("scripts").extended (name).appended_with_extension ("sql")) + if attached {CMS_STORAGE_SQL_I} a_api.storage as l_sql_storage then + l_sql_storage.sql_execute_file_script (a_api.setup.environment.path.extended ("scripts").extended (name).appended_with_extension ("sql")) end end feature {CMS_API} -- Access: API + module_api: detachable CMS_MODULE_API + -- + do + if attached node_api as l_api then + Result := l_api + else + -- Current is initialized, so node_api should be set. + check has_node_api: False end + end + end + node_api: detachable CMS_NODE_API -- @@ -111,15 +133,10 @@ feature -- Access: router setup_router (a_router: WSF_ROUTER; a_api: CMS_API) -- - local - l_node_api: like node_api do - l_node_api := node_api - if l_node_api = Void then - create l_node_api.make (a_api) - node_api := l_node_api + if attached node_api as l_node_api then + configure_web (a_api, l_node_api, a_router) end - configure_web (a_api, l_node_api, a_router) end configure_web (a_api: CMS_API; a_node_api: CMS_NODE_API; a_router: WSF_ROUTER) diff --git a/modules/node/persistence/cms_node_storage_i.e b/modules/node/persistence/cms_node_storage_i.e index 5bbf8ca..e24fe27 100644 --- a/modules/node/persistence/cms_node_storage_i.e +++ b/modules/node/persistence/cms_node_storage_i.e @@ -113,7 +113,7 @@ feature -- Change: Node valid_user: attached a_node.author as l_author and then l_author.id > 0 deferred ensure - has_id: a_node.has_id + has_id: not error_handler.has_error implies a_node.has_id end update_node (a_node: CMS_NODE) @@ -170,33 +170,6 @@ feature -- Change: Node deferred end --- update_node_title (a_user_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_title: READABLE_STRING_32) --- -- Update node title to `a_title', node identified by id `a_node_id'. --- -- The user `a_user_id' is an existing or new collaborator. --- require --- valid_node_id: a_node_id > 0 --- valid_user_id: a_user_id > 0 --- deferred --- end - --- update_node_summary (a_user_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_summary: READABLE_STRING_32) --- -- Update node summary to `a_summary', node identified by id `a_node_id'. --- -- The user `a_user_id' is an existing or new collaborator. --- require --- valid_id: a_node_id > 0 --- valid_user_id: a_user_id > 0 --- deferred --- end - --- update_node_content (a_user_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_content: READABLE_STRING_32) --- -- Update node content to `a_content', node identified by id `a_node_id'. --- -- The user `a_user_id' is an existing or new collaborator. --- require --- valid_id: a_node_id > 0 --- valid_user_id: a_user_id > 0 --- deferred --- end - feature -- Helpers fill_node (a_node: CMS_NODE) diff --git a/package.iron b/package.iron new file mode 100644 index 0000000..fd2052a --- /dev/null +++ b/package.iron @@ -0,0 +1,31 @@ +package ROC_cms + +project + cms = "cms-safe.ecf" + cms = "cms.ecf" + app_env = "library/app_env/app_env-safe.ecf" + app_env = "library/app_env/app_env.ecf" + config = "library/configuration/config-safe.ecf" + config = "library/configuration/config.ecf" + app_env = "library/layout/layout-safe.ecf" + app_env = "library/layout/layout.ecf" + cms_model = "library/model/cms_model-safe.ecf" + cms_model = "library/model/cms_model.ecf" + persistence_mysql = "library/persistence/mysql/persistence_mysql-safe.ecf" + persistence_mysql = "library/persistence/mysql/persistence_mysql.ecf" + persistence_sqlite = "library/persistence/sqlite/persistence_sqlite-safe.ecf" + persistence_sqlite = "library/persistence/sqlite/persistence_sqlite.ecf" + basic_auth = "modules/basic_auth/basic_auth-safe.ecf" + basic_auth = "modules/basic_auth/basic_auth.ecf" + node = "modules/node/node-safe.ecf" + node = "modules/node/node.ecf" + +note + title: ROC CMS + description: CMS written with Eiffel + tags: cms, web, rest, api + license: Eiffel Forum v2 + copyright: Jocelyn Fiat, Javier Velilla, Eiffel Software + link[source]: "Github" https://github.com/EiffelWebFramework/ROC.git + +end diff --git a/src/service/cms_api.e b/src/service/cms_api.e index 0209c97..cba319d 100644 --- a/src/service/cms_api.e +++ b/src/service/cms_api.e @@ -158,6 +158,8 @@ feature -- Query: module t := a_type.name if t.starts_with ("!") then t.remove_head (1) + elseif t.starts_with ("?") then + t.remove_head (1) end across setup.modules as ic @@ -186,7 +188,12 @@ feature -- Query: module -- Enabled module API associated with module typed `a_type'. do if attached module (a_type) as mod then - Result := mod.module_api + if mod.is_enabled then + if not mod.is_initialized then + mod.initialize (Current) + end + Result := mod.module_api + end end end diff --git a/src/service/cms_module.e b/src/service/cms_module.e index adc48c6..7502704 100644 --- a/src/service/cms_module.e +++ b/src/service/cms_module.e @@ -32,42 +32,57 @@ feature {CMS_API} -- Module Initialization -- Initialize Current module with `api'. require is_enabled: is_enabled + is_not_initialized: not is_initialized do -- Redefine to process specific module initialization. + is_initialized := True + ensure + is_initialized: is_initialized end +feature -- Status + + is_initialized: BOOLEAN + -- Is Current module initialized? + feature {CMS_API} -- Access: API module_api: detachable CMS_MODULE_API -- Eventual module api. + require + is_initialized: is_initialized + do + -- No API by default. + end feature {CMS_API} -- Module management is_installed (api: CMS_API): BOOLEAN -- Is Current module installed? do - Result := is_enabled - -- FIXME: implement proper installation status. + Result := attached api.storage.custom_value ("is_initialized", "module-" + name) as v and then v.is_case_insensitive_equal_general ("yes") end install (api: CMS_API) require is_not_installed: not is_installed (api) do - -- Not Yet Supported + api.storage.set_custom_value ("is_initialized", "module-" + name, "yes") end uninstall (api: CMS_API) require is_installed: is_installed (api) do - -- Not Yet Supported + api.storage.set_custom_value ("is_initialized", "module-" + name, "no") end feature -- Router setup_router (a_router: WSF_ROUTER; a_api: CMS_API) -- Setup url dispatching for Current module. + require + is_initialized: is_initialized deferred end diff --git a/src/service/cms_module_api.e b/src/service/cms_module_api.e index e10c0c1..bd97ce9 100644 --- a/src/service/cms_module_api.e +++ b/src/service/cms_module_api.e @@ -1,6 +1,5 @@ note description: "Summary description for {CMS_MODULE_API}." - author: "" date: "$Date: 2015-02-13 14:54:27 +0100 (ven., 13 févr. 2015) $" revision: "$Revision: 96620 $" From af8f410684a909403de4b431901298337c19088c Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Tue, 2 Jun 2015 15:39:08 +0200 Subject: [PATCH 21/27] Updated the CMS pagination component. Harmonized count type to NATURAL_64 for recent_nodes (more to do later). Fix get is active code. --- cms-safe.ecf | 1 + cms.ecf | 1 + examples/demo/site/scripts/node.sql | 2 +- modules/node/cms_node_api.e | 4 +- .../node/handler/cms_node_pagination_helper.e | 161 ---------- modules/node/handler/nodes_handler.e | 39 ++- modules/node/persistence/cms_node_storage_i.e | 7 +- .../node/persistence/cms_node_storage_null.e | 2 +- .../node/persistence/cms_node_storage_sql.e | 14 +- src/kernel/form/cms_lower_upper_pager.e | 15 + .../cms_data_query_parameters.e} | 45 ++- src/persistence/sql/cms_storage_sql_i.e | 15 + src/service/cms_api_options.e | 6 + src/service/response/cms_response.e | 3 + src/support/cms_pagination.e | 50 --- src/support/cms_pagination_generator.e | 287 ++++++++++++++++++ 16 files changed, 417 insertions(+), 235 deletions(-) delete mode 100644 modules/node/handler/cms_node_pagination_helper.e create mode 100644 src/kernel/form/cms_lower_upper_pager.e rename src/{support/cms_ordered_pagination.e => persistence/cms_data_query_parameters.e} (61%) delete mode 100644 src/support/cms_pagination.e create mode 100644 src/support/cms_pagination_generator.e diff --git a/cms-safe.ecf b/cms-safe.ecf index 91fdb85..d1c2b3c 100644 --- a/cms-safe.ecf +++ b/cms-safe.ecf @@ -24,6 +24,7 @@ + diff --git a/cms.ecf b/cms.ecf index f642c2a..4b9f7d6 100644 --- a/cms.ecf +++ b/cms.ecf @@ -24,6 +24,7 @@ + diff --git a/examples/demo/site/scripts/node.sql b/examples/demo/site/scripts/node.sql index 565b03f..0c99eef 100644 --- a/examples/demo/site/scripts/node.sql +++ b/examples/demo/site/scripts/node.sql @@ -6,7 +6,7 @@ CREATE TABLE "nodes" ( "type" TEXT NOT NULL, "title" VARCHAR(255) NOT NULL, "summary" TEXT, - "content" TEXT NOT NULL, + "content" TEXT, "format" VARCHAR(128), "author" INTEGER, "publish" DATETIME, diff --git a/modules/node/cms_node_api.e b/modules/node/cms_node_api.e index 8de31a4..5e606a7 100644 --- a/modules/node/cms_node_api.e +++ b/modules/node/cms_node_api.e @@ -202,7 +202,7 @@ feature -- URL feature -- Access: Node - nodes_count: INTEGER_64 + nodes_count: NATURAL_64 do Result := node_storage.nodes_count end @@ -220,7 +220,7 @@ feature -- Access: Node Result := node_storage.trashed_nodes (a_user.id) end - recent_nodes (a_pagination: CMS_PAGINATION): ITERABLE [CMS_NODE] + recent_nodes (a_pagination: CMS_DATA_QUERY_PARAMETERS): ITERABLE [CMS_NODE] -- List of the `a_rows' most recent nodes starting from `a_offset'. do Result := node_storage.recent_nodes (a_pagination.offset.to_integer_32, a_pagination.size.to_integer_32) diff --git a/modules/node/handler/cms_node_pagination_helper.e b/modules/node/handler/cms_node_pagination_helper.e deleted file mode 100644 index c3b48ed..0000000 --- a/modules/node/handler/cms_node_pagination_helper.e +++ /dev/null @@ -1,161 +0,0 @@ -note - description: "Helper class to build the html pagination links and header summary" - date: "$Date$" - revision: "$Revision$" - -class - CMS_NODE_PAGINATION_HELPER - -create - make - -feature {NONE} -- Initialization - - make (a_resource: READABLE_STRING_8; req: WSF_REQUEST; a_response: CMS_RESPONSE; a_nodes_count: INTEGER_64) - -- Create an object with default values. - do - make_size (a_resource, req, a_response, a_nodes_count, 5) - end - - make_size (a_resource: READABLE_STRING_8; req: WSF_REQUEST; a_response: CMS_RESPONSE; a_nodes_count: INTEGER_64; a_page_size: NATURAL) - -- Create an object with a pages of size `a_page_size'. - do - create resource.make_from_string (a_resource) - number_of_nodes := a_nodes_count - create pager.make (0, a_page_size) - response := a_response - process (req) - end - - process (req: WSF_REQUEST) - -- Process request query paraments to build the pager. - do - --TODO: at the moment the code looks for hardcoded parameters - -- size and page, maybe we can parametrize these names. - -- Size:limit. - if - attached {WSF_STRING} req.query_parameter ("size") as l_size and then - attached l_size.value as l_value and then - l_value.is_natural - then - pager.set_size (l_value.to_natural_32) - end - - --Page:offset - if - attached {WSF_STRING} req.query_parameter ("page") as l_page and then - l_page.is_integer - then - current_page := l_page.integer_value - if current_page > 1 then - pager.set_offset ((current_page - 1).to_natural_32 * pager.size) - end - else - current_page := 1 - end - end - -feature -- Access - - pager: CMS_PAGINATION - -- Paginator. - - resource: IMMUTABLE_STRING_8 - - current_page: INTEGER - -- current page. - - number_of_pages: INTEGER_64 - -- total number of pages. - do - Result := (number_of_nodes // pager.size.as_integer_32) + 1 - end - - number_of_nodes: INTEGER_64 - -- number of nodes. - - response: CMS_RESPONSE - -- cms response - -feature -- Parameters - - page_parameter: STRING = "page" - - size_parameter: STRING = "size" - -feature -- Paginator - - append_pagination_summary_to (a_output: STRING) - -- Header summary - -- Current page 1 of n pages. - do - a_output.append ("

    Items:

    ") - - a_output.append ("

    Current Page:") - a_output.append_integer (current_page) - a_output.append (" of ") - a_output.append_integer_64 (number_of_pages) - a_output.append (" pages

    ") - end - - append_html_pager_to (a_output: STRING) - -- Append html pager to `a_output'. - -- note: First, [Prev], [Next], Last. - local - lnk: CMS_LOCAL_LINK - s: STRING - do - -- NOTE: for development purposes we have the following hardcode output. - -- pager - a_output.append ("
      %N") - create s.make_from_string (resource) - append_query_parameters_to (s, "1", pager.size.out) - create lnk.make ("First", s) - a_output.append ("
    • ") - a_output.append (response.link (lnk.title, lnk.location, Void)) - a_output.append ("
    • ") - if (current_page - 1) > 1 then - create s.make_from_string (resource) - append_query_parameters_to (s, (current_page - 1).out, pager.size.out) - - create lnk.make ("Prev", s) - a_output.append ("
    • ") - a_output.append (response.link (lnk.title, lnk.location, Void)) - a_output.append ("
    • ") - end - - if (current_page + 1) < number_of_pages then - create s.make_from_string (resource) - append_query_parameters_to (s, (current_page + 1).out, pager.size.out) - create lnk.make ("Next", s) - a_output.append ("
    • ") - a_output.append (response.link (lnk.title, lnk.location, Void)) - a_output.append ("
    • ") - end - create s.make_from_string (resource) - append_query_parameters_to (s, number_of_pages.out, pager.size.out) - create lnk.make ("Last", s) - a_output.append ("
    • ") - a_output.append (response.link (lnk.title, lnk.location, Void)) - a_output.append ("
    • ") - - a_output.append ("
    %N") - end - - append_query_parameters_to (s: STRING; a_page: STRING; a_size: STRING) - do - if s.has ('?') then - s.append ("&") - else - s.append ("?") - end - s.append (page_parameter) - s.append_character ('=') - s.append (a_page) - s.append_character ('&') - s.append (size_parameter) - s.append_character ('=') - s.append (a_size) - end - -end diff --git a/modules/node/handler/nodes_handler.e b/modules/node/handler/nodes_handler.e index 58839cb..974a17d 100644 --- a/modules/node/handler/nodes_handler.e +++ b/modules/node/handler/nodes_handler.e @@ -41,20 +41,36 @@ feature -- HTTP Methods s: STRING n: CMS_NODE lnk: CMS_LOCAL_LINK - l_page_helper: CMS_NODE_PAGINATION_HELPER + l_page_helper: CMS_PAGINATION_GENERATOR + s_pager: STRING + l_count: NATURAL_64 do - -- At the moment the template is hardcoded, but we can + -- At the moment the template are hardcoded, but we can -- get them from the configuration file and load them into -- the setup class. + l_count := node_api.nodes_count + create {GENERIC_VIEW_CMS_RESPONSE} l_response.make (req, res, api) - create l_page_helper.make ("nodes/", req, l_response, node_api.nodes_count) create s.make_empty - l_page_helper.append_pagination_summary_to (s) - l_page_helper.append_html_pager_to (s) + if l_count > 1 then + l_response.set_title ("Listing " + l_count.out + " nodes") + else + l_response.set_title ("Listing " + l_count.out + " node") + end - if attached node_api.recent_nodes (l_page_helper.pager) as lst then + create s_pager.make_empty + create l_page_helper.make ("nodes/?page={page}&size={size}", node_api.nodes_count, 25) -- FIXME: Make this default page size a global CMS settings + l_page_helper.get_setting_from_request (req) + if l_page_helper.pages_count > 1 then + l_page_helper.append_to_html (l_response, s_pager) + if l_page_helper.page_size > 20 then + s.append (s_pager) + end + end + + if attached node_api.recent_nodes (l_page_helper.query_parameters) as lst then s.append ("
      %N") across lst as ic @@ -63,14 +79,21 @@ feature -- HTTP Methods lnk := node_api.node_link (n) s.append ("
    • ") s.append (l_response.link (lnk.title, lnk.location, Void)) + debug + if attached node_api.content_type (n.content_type) as ct then + s.append ("") + s.append (html_encoded (ct.title)) + s.append ("") + end + end s.append ("
    • %N") end s.append ("
    %N") end - l_page_helper.append_html_pager_to (s) + -- Again the pager at the bottom, if needed + s.append (s_pager) l_response.set_main_content (s) - l_response.add_block (create {CMS_CONTENT_BLOCK}.make ("nodes_warning", Void, "/nodes/ is not yet fully implemented
    ", Void), "highlighted") l_response.execute end diff --git a/modules/node/persistence/cms_node_storage_i.e b/modules/node/persistence/cms_node_storage_i.e index e24fe27..970c2bf 100644 --- a/modules/node/persistence/cms_node_storage_i.e +++ b/modules/node/persistence/cms_node_storage_i.e @@ -43,6 +43,8 @@ feature {NONE} -- Implementation extended_store (a_node: CMS_NODE) -- Store extended data from `a_node'. + require + not error_handler.has_error do if attached node_storage_extension (a_node) as ext then ext.store_node (a_node) @@ -51,16 +53,17 @@ feature {NONE} -- Implementation extended_load (a_node: CMS_NODE) -- Load extended data into `a_node'. + require + not error_handler.has_error do if attached node_storage_extension (a_node) as ext then ext.load_node (a_node) end end - feature -- Access - nodes_count: INTEGER_64 + nodes_count: NATURAL_64 -- Count of nodes. deferred end diff --git a/modules/node/persistence/cms_node_storage_null.e b/modules/node/persistence/cms_node_storage_null.e index b5a9406..0bb571e 100644 --- a/modules/node/persistence/cms_node_storage_null.e +++ b/modules/node/persistence/cms_node_storage_null.e @@ -30,7 +30,7 @@ feature -- Error Handling feature -- Access: node - nodes_count: INTEGER_64 + nodes_count: NATURAL_64 -- Count of nodes. do end diff --git a/modules/node/persistence/cms_node_storage_sql.e b/modules/node/persistence/cms_node_storage_sql.e index b409851..188c56e 100644 --- a/modules/node/persistence/cms_node_storage_sql.e +++ b/modules/node/persistence/cms_node_storage_sql.e @@ -22,14 +22,14 @@ create feature -- Access - nodes_count: INTEGER_64 + nodes_count: NATURAL_64 -- Number of items nodes. do error_handler.reset write_information_log (generator + ".nodes_count") sql_query (sql_select_nodes_count, Void) if sql_rows_count = 1 then - Result := sql_read_integer_64 (1) + Result := sql_read_natural_64 (1) end end @@ -267,8 +267,14 @@ feature {NONE} -- Implementation a_node.set_revision (1) -- New object. end end - extended_store (a_node) - sql_commit_transaction + if not error_handler.has_error then + extended_store (a_node) + end + if error_handler.has_error then + sql_rollback_transaction + else + sql_commit_transaction + end end feature -- Helpers diff --git a/src/kernel/form/cms_lower_upper_pager.e b/src/kernel/form/cms_lower_upper_pager.e new file mode 100644 index 0000000..f46e19b --- /dev/null +++ b/src/kernel/form/cms_lower_upper_pager.e @@ -0,0 +1,15 @@ +note + description: "Pager widget for ROC CMS." + date: "$Date$" + revision: "$Revision$" + +class + CMS_LOWER_UPPER_PAGER + +inherit + WSF_WIDGET_PAGER + +create + make + +end diff --git a/src/support/cms_ordered_pagination.e b/src/persistence/cms_data_query_parameters.e similarity index 61% rename from src/support/cms_ordered_pagination.e rename to src/persistence/cms_data_query_parameters.e index 42c5f3c..a333797 100644 --- a/src/support/cms_ordered_pagination.e +++ b/src/persistence/cms_data_query_parameters.e @@ -1,19 +1,36 @@ note - description: "Pagination parameters with order capability" + description: "[ + Parameters associated with data query. + It could be query over http, or storage. + ]" date: "$Date$" revision: "$Revision$" class - CMS_ORDERED_PAGINATION - -inherit - CMS_PAGINATION + CMS_DATA_QUERY_PARAMETERS create make - + +feature {NONE} -- Initialization + + make (a_offset: NATURAL; a_size: NATURAL) + do + offset := a_offset + size := a_size + ensure + size_set: size = a_size + offset_set: offset = a_offset + end + feature -- Access + size: NATURAL assign set_size + -- Number of items per page. + + offset: NATURAL assign set_offset + -- lower index of `items' pagination. + order_by: detachable READABLE_STRING_8 -- field to order by. @@ -22,6 +39,22 @@ feature -- Access feature -- Element change + set_size (a_size: NATURAL) + -- Set `size' with `a_size'. + do + size := a_size + ensure + size_set: size = a_size + end + + set_offset (a_offset: NATURAL) + -- Set offset with `a_offset'. + do + offset := a_offset + ensure + limit_set: offset = a_offset + end + set_ascending_order_by_field (a_field: detachable READABLE_STRING_8) -- Pager with a order_by `a_field' asc. do diff --git a/src/persistence/sql/cms_storage_sql_i.e b/src/persistence/sql/cms_storage_sql_i.e index 7e91029..8f38ab0 100644 --- a/src/persistence/sql/cms_storage_sql_i.e +++ b/src/persistence/sql/cms_storage_sql_i.e @@ -217,6 +217,21 @@ feature -- Access deferred end + sql_read_natural_64 (a_index: INTEGER): NATURAL_64 + -- Retrieved value at `a_index' position in `item'. + local + l_item: like sql_item + do + l_item := sql_item (a_index) + if attached {NATURAL_64} l_item as i then + Result := i + elseif attached {NATURAL_64_REF} l_item as l_value then + Result := l_value.item + else + Result := sql_read_integer_64 (a_index).to_natural_64 + end + end + sql_read_integer_64 (a_index: INTEGER): INTEGER_64 -- Retrieved value at `a_index' position in `item'. local diff --git a/src/service/cms_api_options.e b/src/service/cms_api_options.e index 2ce3f29..ec00e2a 100644 --- a/src/service/cms_api_options.e +++ b/src/service/cms_api_options.e @@ -14,4 +14,10 @@ create make, make_from_manifest +convert + make_from_manifest ({ ARRAY [TUPLE [key: STRING; value: detachable ANY]], + ARRAY [TUPLE [STRING_8, ARRAY [TUPLE [STRING_8, STRING_32]]]], + ARRAY [TUPLE [STRING_8, ARRAY [TUPLE [STRING_8, STRING_8]]]] + }) + end diff --git a/src/service/response/cms_response.e b/src/service/response/cms_response.e index 0df5bf1..ca409a9 100644 --- a/src/service/response/cms_response.e +++ b/src/service/response/cms_response.e @@ -1065,6 +1065,9 @@ feature -- Generation l_is_active: BOOLEAN do create qs.make_from_string (request.percent_encoded_path_info) + if qs.starts_with ("/") then + qs.remove_head (1) + end l_is_active := qs.same_string (a_lnk.location) if not l_is_active then if attached request.query_string as l_query_string and then not l_query_string.is_empty then diff --git a/src/support/cms_pagination.e b/src/support/cms_pagination.e deleted file mode 100644 index 72fc688..0000000 --- a/src/support/cms_pagination.e +++ /dev/null @@ -1,50 +0,0 @@ -note - description: "Pagination parameters" - date: "$Date$" - revision: "$Revision$" - -class - CMS_PAGINATION - -create - make - -feature {NONE} -- Initialization - - make (a_offset: NATURAL; a_size: NATURAL) - do - offset := a_offset - size := a_size - ensure - size_set: size = a_size - offset_set: offset = a_offset - end - -feature -- Access - - size: NATURAL assign set_size - -- Number of items per page. - - offset: NATURAL assign set_offset - -- lower index of `items' pagination. - -feature -- Element change - - set_size (a_size: NATURAL) - -- Set `size' with `a_size'. - do - size := a_size - ensure - size_set: size = a_size - end - - set_offset (a_offset: NATURAL) - -- Set offset with `a_offset'. - do - offset := a_offset - ensure - limit_set: offset = a_offset - end - - -end diff --git a/src/support/cms_pagination_generator.e b/src/support/cms_pagination_generator.e new file mode 100644 index 0000000..ef2019c --- /dev/null +++ b/src/support/cms_pagination_generator.e @@ -0,0 +1,287 @@ +note + description: "Pagination class to generate html pagination links and header summary." + date: "$Date$" + revision: "$Revision$" + +class + CMS_PAGINATION_GENERATOR + +create + make + +feature {NONE} -- Initialization + + make (a_resource: READABLE_STRING_8; a_count: NATURAL_64; a_page_size: NATURAL) + -- Create an object with a pages of size `a_page_size'. + -- If `a_page_size' is zero, use default pagination size. + require + a_page_size > 0 + do + create query_parameters.make (0, 25) + + create resource.make (a_resource) + set_page_size (a_page_size) + set_upper (a_count) + set_current_page_index (1) + + maximum_ith_page_links := 7 + page_parameter_id := "page" + size_parameter_id := "size" + set_first_text_id ("<<") + set_prev_text_id ("<") + set_next_text_id (">") + set_last_text_id (">>") + end + +feature -- Access + + resource: URI_TEMPLATE + -- Resource associated with current pager. + + page_size: NATURAL + -- Number of items per page. + do + Result := query_parameters.size + end + + upper: NATURAL_64 + -- number of items. + -- if zero, no upper limit. + + current_page_index: INTEGER + -- Current page index. + + query_parameters: CMS_DATA_QUERY_PARAMETERS + -- Parameter for the associated query/resource. + +feature -- Status report + + has_upper_limit: BOOLEAN + -- Upper limit known? + do + Result := upper > 0 + end + + pages_count: INTEGER + -- Number of pages. + -- If upper is + require + has_upper_limit: has_upper_limit + do + Result := (upper // page_size.as_natural_64).to_integer_32 + if upper \\ page_size.to_natural_64 > 0 then + Result := Result + 1 + end + end + +feature -- Parameters + + page_parameter_id: STRING + -- Parameter id for page value. + + size_parameter_id: STRING + -- Parameter id for size value. + + maximum_ith_page_links: INTEGER + -- Maximum number of numeric ith page link. + -- ex: max = 6 gives "1 2 3 4 5 6 ... > >>". + + label_first: IMMUTABLE_STRING_32 + label_previous: IMMUTABLE_STRING_32 + label_next: IMMUTABLE_STRING_32 + label_last: IMMUTABLE_STRING_32 + +feature -- Element change + + set_page_size (a_size: NATURAL) + -- Set `page_size' to `a_size'. + do + query_parameters.set_size (a_size) + end + + set_upper (a_upper: NATURAL_64) + -- Set pages count, or upper limit `upper' to `a_size'. + do + upper := a_upper + end + + set_current_page_index (a_page_index: like current_page_index) + -- Set Current page index to `a_page_index'. + do + current_page_index := a_page_index + if a_page_index > 1 then + query_parameters.set_offset ((a_page_index - 1).to_natural_32 * page_size) + else + query_parameters.set_offset (0) + end + end + + set_page_parameter_id (a_id: READABLE_STRING_8) + -- Set "page" query parameter to `a_id'. + do + page_parameter_id := a_id + end + + set_size_parameter_id (a_id: READABLE_STRING_8) + -- Set "size" query parameter to `a_id'. + do + size_parameter_id := a_id + end + + get_setting_from_request (req: WSF_REQUEST) + -- Get various pager related settings from request `req' query paramenters. + -- Using `page_parameter_id' and `size_parameter_id' value for parameter names. + do + -- Size + if + attached {WSF_STRING} req.query_parameter (size_parameter_id) as l_size and then + attached l_size.value as l_value and then + l_value.is_natural + then + set_page_size (l_value.to_natural_32) + else + -- Keep default size + end + + -- Page + if + attached {WSF_STRING} req.query_parameter (page_parameter_id) as l_page and then + l_page.is_integer + then + set_current_page_index (l_page.integer_value) + else + set_current_page_index (1) + end + end + + set_first_text_id (s: READABLE_STRING_GENERAL) + -- Set label for "First" link to `s'. + -- default: "<<" + do + create label_first.make_from_string_general (s) + end + + set_prev_text_id (s: READABLE_STRING_GENERAL) + -- Set label for "Prev" link to `s'. + -- default: "<" + do + create label_previous.make_from_string_general (s) + end + + set_next_text_id (s: READABLE_STRING_GENERAL) + -- Set label for "Next" link to `s'. + -- default: ">" + do + create label_next.make_from_string_general (s) + end + + set_last_text_id (s: READABLE_STRING_GENERAL) + -- Set label for "Last" link to `s'. + -- default: ">>" + do + create label_last.make_from_string_general (s) + end + + set_maximum_ith_page_links (nb: INTEGER) + -- Set `maximum_ith_page_links' to `nb'. + do + maximum_ith_page_links := nb + end + +feature -- Conversion + + pagination_links: ARRAYED_LIST [CMS_LOCAL_LINK] + -- CMS local links related to Current paginations. + local + lnk: CMS_LOCAL_LINK + tb: HASH_TABLE [detachable ANY, STRING_8] + curr, max: INTEGER + i,j: INTEGER + do + create Result.make (maximum_ith_page_links) + + curr := current_page_index + if has_upper_limit then + max := pages_count + else + max := curr + page_size.to_integer_32 + end + + create tb.make (2) + tb.force (page_size, size_parameter_id) + tb.force (1, page_parameter_id) + if curr > 1 then + create lnk.make (label_first, resource.expanded_string (tb)) + Result.force (lnk) + end + + if curr > 1 then + tb.force (curr - 1, "page") + create lnk.make (label_previous, resource.expanded_string (tb)) + Result.force (lnk) + end + from + if curr >= maximum_ith_page_links // 2 then + i := curr - (maximum_ith_page_links // 2) + else + i := 1 + end + j := 0 + until + j >= maximum_ith_page_links or (has_upper_limit and then i > max) + loop + tb.force (i, "page") + create lnk.make (i.out, resource.expanded_string (tb)) + lnk.set_is_active (i = curr) + Result.force (lnk) + j := j + 1 + i := i + 1 + end + if not has_upper_limit or else i < max then + tb.force (i, "page") + create lnk.make ("...", resource.expanded_string (tb)) + Result.force (lnk) + end + + if curr < max then + tb.force (curr + 1, "page") + create lnk.make (label_next, resource.expanded_string (tb)) + Result.force (lnk) + end + + if upper > 0 and curr /= max then + tb.force (max, "page") + create lnk.make (label_last, resource.expanded_string (tb)) + Result.force (lnk) + end + end + +feature -- Convertion + + append_to_html (a_response: CMS_RESPONSE; a_output: STRING) + -- Append html pager to `a_output' in the context of `a_response'. + -- note: First, [Prev], [Next], Last. + local + lnk: CMS_LOCAL_LINK + do + a_output.append ("
      %N") + across + pagination_links as ic + loop + lnk := ic.item + if lnk.is_active then + a_output.append ("
    • ") + elseif lnk.title.same_string (label_previous) then + a_output.append ("
    • ") + elseif lnk.title.same_string (label_next) then + a_output.append ("
    • ") + else + a_output.append ("
    • ") + end + a_output.append (a_response.link (lnk.title, lnk.location, Void)) + a_output.append ("
    • ") + end + a_output.append ("
    ") + end + +end From b8cfff487a015a20121f4cf28f70ab3a8590c72c Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Tue, 2 Jun 2015 15:56:27 +0200 Subject: [PATCH 22/27] Removed dependency from pagination to cms_data_query_parameters TODO: review and fix any NATURAL_64 truncation. --- modules/node/cms_node_api.e | 4 ++-- modules/node/handler/nodes_handler.e | 4 ++-- src/persistence/cms_data_query_parameters.e | 6 +++--- src/support/cms_pagination_generator.e | 23 +++++++++------------ 4 files changed, 17 insertions(+), 20 deletions(-) diff --git a/modules/node/cms_node_api.e b/modules/node/cms_node_api.e index 5e606a7..88bb82d 100644 --- a/modules/node/cms_node_api.e +++ b/modules/node/cms_node_api.e @@ -220,10 +220,10 @@ feature -- Access: Node Result := node_storage.trashed_nodes (a_user.id) end - recent_nodes (a_pagination: CMS_DATA_QUERY_PARAMETERS): ITERABLE [CMS_NODE] + recent_nodes (params: CMS_DATA_QUERY_PARAMETERS): ITERABLE [CMS_NODE] -- List of the `a_rows' most recent nodes starting from `a_offset'. do - Result := node_storage.recent_nodes (a_pagination.offset.to_integer_32, a_pagination.size.to_integer_32) + Result := node_storage.recent_nodes (params.offset.to_integer_32, params.size.to_integer_32) end node (a_id: INTEGER_64): detachable CMS_NODE diff --git a/modules/node/handler/nodes_handler.e b/modules/node/handler/nodes_handler.e index 974a17d..289514b 100644 --- a/modules/node/handler/nodes_handler.e +++ b/modules/node/handler/nodes_handler.e @@ -65,12 +65,12 @@ feature -- HTTP Methods l_page_helper.get_setting_from_request (req) if l_page_helper.pages_count > 1 then l_page_helper.append_to_html (l_response, s_pager) - if l_page_helper.page_size > 20 then + if l_page_helper.page_size > 25 then s.append (s_pager) end end - if attached node_api.recent_nodes (l_page_helper.query_parameters) as lst then + if attached node_api.recent_nodes (create {CMS_DATA_QUERY_PARAMETERS}.make (l_page_helper.current_page_offset, l_page_helper.page_size)) as lst then s.append ("
      %N") across lst as ic diff --git a/src/persistence/cms_data_query_parameters.e b/src/persistence/cms_data_query_parameters.e index a333797..f8c7475 100644 --- a/src/persistence/cms_data_query_parameters.e +++ b/src/persistence/cms_data_query_parameters.e @@ -14,7 +14,7 @@ create feature {NONE} -- Initialization - make (a_offset: NATURAL; a_size: NATURAL) + make (a_offset: NATURAL_64; a_size: NATURAL) do offset := a_offset size := a_size @@ -28,7 +28,7 @@ feature -- Access size: NATURAL assign set_size -- Number of items per page. - offset: NATURAL assign set_offset + offset: NATURAL_64 assign set_offset -- lower index of `items' pagination. order_by: detachable READABLE_STRING_8 @@ -47,7 +47,7 @@ feature -- Element change size_set: size = a_size end - set_offset (a_offset: NATURAL) + set_offset (a_offset: NATURAL_64) -- Set offset with `a_offset'. do offset := a_offset diff --git a/src/support/cms_pagination_generator.e b/src/support/cms_pagination_generator.e index ef2019c..64ee463 100644 --- a/src/support/cms_pagination_generator.e +++ b/src/support/cms_pagination_generator.e @@ -17,8 +17,6 @@ feature {NONE} -- Initialization require a_page_size > 0 do - create query_parameters.make (0, 25) - create resource.make (a_resource) set_page_size (a_page_size) set_upper (a_count) @@ -40,9 +38,6 @@ feature -- Access page_size: NATURAL -- Number of items per page. - do - Result := query_parameters.size - end upper: NATURAL_64 -- number of items. @@ -51,8 +46,15 @@ feature -- Access current_page_index: INTEGER -- Current page index. - query_parameters: CMS_DATA_QUERY_PARAMETERS - -- Parameter for the associated query/resource. + current_page_offset: NATURAL_64 + -- Lower index - 1 for current page. + do + if current_page_index > 1 then + Result := (current_page_index - 1).to_natural_32 * page_size + else + Result := 0 + end + end feature -- Status report @@ -96,7 +98,7 @@ feature -- Element change set_page_size (a_size: NATURAL) -- Set `page_size' to `a_size'. do - query_parameters.set_size (a_size) + page_size := a_size end set_upper (a_upper: NATURAL_64) @@ -109,11 +111,6 @@ feature -- Element change -- Set Current page index to `a_page_index'. do current_page_index := a_page_index - if a_page_index > 1 then - query_parameters.set_offset ((a_page_index - 1).to_natural_32 * page_size) - else - query_parameters.set_offset (0) - end end set_page_parameter_id (a_id: READABLE_STRING_8) From 5578a9e622c1b40918e95c78aad3b6e67206bc8a Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Tue, 9 Jun 2015 19:42:37 +0200 Subject: [PATCH 23/27] Adapted ROC CMS to concurrent EWF. Revisited the shared logger to reduced number of useless calls. --- examples/demo/demo-safe.ecf | 133 ++++---- .../demo/launcher/any/application_launcher.e | 4 +- .../launcher/any/application_launcher_i.e | 59 ++-- .../launcher/default/application_launcher.e | 4 +- .../launcher/default/application_launcher_i.e | 8 +- .../config/application_configuration.json | 3 +- .../site/themes/bootstrap/assets/favicon.ico | Bin 0 -> 994 bytes examples/demo/site/themes/bootstrap/page.tpl | 8 +- examples/demo/src/ewf_roc_server.e | 97 +----- examples/demo/src/ewf_roc_server_execution.e | 81 +++++ .../src/configuration/logger_configuration.e | 13 + library/app_env/src/logger/logger.e | 99 ++++-- library/app_env/src/logger/shared_logger.e | 69 ++++- .../store/cms_storage_store_sql.e | 9 + .../sqlite/src/cms_storage_sqlite_builder.e | 21 +- modules/basic_auth/filter/basic_auth_filter.e | 7 +- modules/node/handler/nodes_handler.e | 2 +- modules/node/handler/trash_handler.e | 6 +- src/persistence/cms_storage.e | 7 + src/persistence/cms_storage_null.e | 7 + src/service/cms_execution.e | 286 ++++++++++++++++++ src/service/filter/cms_error_filter.e | 4 +- tools/install.bat | 71 +++++ 23 files changed, 768 insertions(+), 230 deletions(-) create mode 100644 examples/demo/site/themes/bootstrap/assets/favicon.ico create mode 100644 examples/demo/src/ewf_roc_server_execution.e create mode 100644 src/service/cms_execution.e create mode 100644 tools/install.bat diff --git a/examples/demo/demo-safe.ecf b/examples/demo/demo-safe.ecf index c760a4f..3c64fa1 100644 --- a/examples/demo/demo-safe.ecf +++ b/examples/demo/demo-safe.ecf @@ -1,58 +1,81 @@ - Example/demo for Eiffel ROC CMS library - - - /EIFGENs$ - /CVS$ - /.svn$ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Example/demo for Eiffel ROC CMS library + + + /EIFGENs$ + /CVS$ + /.svn$ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/demo/launcher/any/application_launcher.e b/examples/demo/launcher/any/application_launcher.e index 0ef505c..bb184d0 100644 --- a/examples/demo/launcher/any/application_launcher.e +++ b/examples/demo/launcher/any/application_launcher.e @@ -8,10 +8,10 @@ note revision: "$Revision: 36 $" class - APPLICATION_LAUNCHER + APPLICATION_LAUNCHER [G -> WSF_EXECUTION create make end] inherit - APPLICATION_LAUNCHER_I + APPLICATION_LAUNCHER_I [G] feature -- Custom diff --git a/examples/demo/launcher/any/application_launcher_i.e b/examples/demo/launcher/any/application_launcher_i.e index 0744c80..026d12f 100644 --- a/examples/demo/launcher/any/application_launcher_i.e +++ b/examples/demo/launcher/any/application_launcher_i.e @@ -10,24 +10,28 @@ note revision: "$Revision: 36 $" deferred class - APPLICATION_LAUNCHER_I + APPLICATION_LAUNCHER_I [G -> WSF_EXECUTION create make end] inherit SHARED_EXECUTION_ENVIRONMENT feature -- Execution - launch (a_service: WSF_SERVICE; opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) + launch (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) local nature: like launcher_nature do nature := launcher_nature - if nature = Void or else nature = nature_nino then - launch_nino (a_service, opts) + if nature = Void then + launch_standalone (opts) + elseif nature = nature_standalone then + launch_standalone (opts) + elseif nature = nature_nino then + launch_nino (opts) elseif nature = nature_cgi then - launch_cgi (a_service, opts) + launch_cgi (opts) elseif nature = nature_libfcgi then - launch_libfcgi (a_service, opts) + launch_libfcgi (opts) else -- bye bye (create {EXCEPTIONS}).die (-1) @@ -43,14 +47,16 @@ feature {NONE} -- Access --| and we could use WSF_DEFAULT_SERVICE_LAUNCHER to configure this at compilation time. local p: PATH - l_entry_name: READABLE_STRING_32 ext: detachable READABLE_STRING_32 do create p.make_from_string (execution_environment.arguments.command_name) if attached p.entry as l_entry then - ext := l_entry.extension + ext := l_entry.extension end if ext /= Void then + if ext.same_string (nature_standalone) then + Result := nature_standalone + end if ext.same_string (nature_nino) then Result := nature_nino end @@ -61,39 +67,58 @@ feature {NONE} -- Access Result := nature_libfcgi end end + Result := default_nature + end + +feature {NONE} -- standalone + + nature_standalone: STRING = "standalone" + + launch_standalone (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) + local + launcher: WSF_STANDALONE_SERVICE_LAUNCHER [G] + do + create launcher.make_and_launch (opts) end feature {NONE} -- nino nature_nino: STRING = "nino" - launch_nino (a_service: WSF_SERVICE; opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) + launch_nino (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) local - launcher: WSF_NINO_SERVICE_LAUNCHER + launcher: WSF_NINO_SERVICE_LAUNCHER [G] do - create launcher.make_and_launch (a_service, opts) + create launcher.make_and_launch (opts) end feature {NONE} -- cgi nature_cgi: STRING = "cgi" - launch_cgi (a_service: WSF_SERVICE; opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) + launch_cgi (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) local - launcher: WSF_CGI_SERVICE_LAUNCHER + launcher: WSF_CGI_SERVICE_LAUNCHER [G] do - create launcher.make_and_launch (a_service, opts) + create launcher.make_and_launch (opts) end feature {NONE} -- libfcgi nature_libfcgi: STRING = "libfcgi" - launch_libfcgi (a_service: WSF_SERVICE; opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) + launch_libfcgi (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) local - launcher: WSF_LIBFCGI_SERVICE_LAUNCHER + launcher: WSF_LIBFCGI_SERVICE_LAUNCHER [G] do - create launcher.make_and_launch (a_service, opts) + create launcher.make_and_launch (opts) + end + +feature -- Default + + default_nature: STRING + do + Result := nature_standalone end diff --git a/examples/demo/launcher/default/application_launcher.e b/examples/demo/launcher/default/application_launcher.e index 0ef505c..bb184d0 100644 --- a/examples/demo/launcher/default/application_launcher.e +++ b/examples/demo/launcher/default/application_launcher.e @@ -8,10 +8,10 @@ note revision: "$Revision: 36 $" class - APPLICATION_LAUNCHER + APPLICATION_LAUNCHER [G -> WSF_EXECUTION create make end] inherit - APPLICATION_LAUNCHER_I + APPLICATION_LAUNCHER_I [G] feature -- Custom diff --git a/examples/demo/launcher/default/application_launcher_i.e b/examples/demo/launcher/default/application_launcher_i.e index e665189..4d91129 100644 --- a/examples/demo/launcher/default/application_launcher_i.e +++ b/examples/demo/launcher/default/application_launcher_i.e @@ -10,15 +10,15 @@ note revision: "$Revision: 96596 $" deferred class - APPLICATION_LAUNCHER_I + APPLICATION_LAUNCHER_I [G -> WSF_EXECUTION create make end] feature -- Execution - launch (a_service: WSF_SERVICE; opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) + launch (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) local - launcher: WSF_DEFAULT_SERVICE_LAUNCHER + launcher: WSF_DEFAULT_SERVICE_LAUNCHER [G] do - create {WSF_DEFAULT_SERVICE_LAUNCHER} launcher.make_and_launch (a_service, opts) + create launcher.make_and_launch (opts) end end diff --git a/examples/demo/site/config/application_configuration.json b/examples/demo/site/config/application_configuration.json index 52dbb4b..0ccf9d5 100644 --- a/examples/demo/site/config/application_configuration.json +++ b/examples/demo/site/config/application_configuration.json @@ -23,7 +23,8 @@ "server": "localhost" }, "logger": { - "level":"debug", + "level":"error", + "type":"stderr", "backup_count":"4" }, "server": { diff --git a/examples/demo/site/themes/bootstrap/assets/favicon.ico b/examples/demo/site/themes/bootstrap/assets/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..a41a15974bacf503bd3fb2873f0c436cf07efeff GIT binary patch literal 994 zcmV<810DPT0096203aX$0096X0L%jb02TlM0EtjeM-2)Z3IG5A4M|8uQUCw|AOHXW zAP5Ek0047(dh`GQ1CvQaK~z}7?blhTR#g-S@Smuenr1x|(Fo>TH;2$NOCK`H1`RR_ zi3-vz6eAj-!GsDbx)n(e(WFrrjgk#QWncvvl;l7qN!GQLk|fNs^m=;vAK2V9zWa5d z9@?@6a2cjyQ+V{nbbO27yZRA5un6nXjtY-r5Z=nT z81wNBCUzzB6LB{#!9IM4DVT{JcoB2(6Gle3cHD=9xU%%X~C` zEcTwR)z@sBf(x)4{jdzJ5d=15JSpQuti&OB5C^9>ZTHXdNmTm~wqY37SkNresZ%IsN&b#gMnS~fL>v|BEk&7tvJ89dlpuqCE(PplgxW1pxlTf(`$EH zhpY1P%{T>z;TJrNBN7)@;8@($jOteg)n6B?-xmg>f`Q3-<8-_QE^?6vD`E7W%*sJp0 zt(n)~Ul7?HpYDNAi}jrt8~|2$8&_xkF)m6l8q`_lgOb6j0BuZc{z|-{DiYAb;(J%r zJvrw-jG6j&R)E(-@R0&&HIo^I%3BIEEe{3;;GN?9^8JO>zia0P!BcTUUeUYQUliZ& z9z3i{rW=kYlB|9x&M)iC%X=ni49Uf6KYdrg)-$i2og$>(|ER!0dt$*~eEUGHchuM# z+ifa(8}h^-VuSz`x`^Eq1Gn_MMb>cW z{F+V6rS-Trhr3u QJOBUy07*qoM6N<$f+ - - - - + + + + diff --git a/examples/demo/src/ewf_roc_server.e b/examples/demo/src/ewf_roc_server.e index d284825..1bfdcab 100644 --- a/examples/demo/src/ewf_roc_server.e +++ b/examples/demo/src/ewf_roc_server.e @@ -16,11 +16,6 @@ inherit initialize end - WSF_SERVICE - redefine - execute - end - REFACTORING_HELPER SHARED_EXECUTION_ENVIRONMENT @@ -40,37 +35,26 @@ feature {NONE} -- Initialization initialize -- Initialize current service. + local + env: CMS_ENVIRONMENT do - -- Launcher Precursor create {WSF_SERVICE_LAUNCHER_OPTIONS_FROM_INI} service_options.make_from_file ("demo.ini") - - -- CMS - initialize_cms - end - -feature -- Service - - cms_service: CMS_SERVICE - -- cms service. - - execute (req: WSF_REQUEST; res: WSF_RESPONSE) - do - cms_service.execute (req, res) + create env.make_default + initialize_logger (env) end feature {NONE} -- Launch operation - launcher: APPLICATION_LAUNCHER + launcher: APPLICATION_LAUNCHER [EWF_ROC_SERVER_EXECUTION] - launch (a_service: WSF_SERVICE; opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) + launch (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) local l_retry: BOOLEAN l_message: STRING do if not l_retry then - write_debug_log (generator + ".launch") - launcher.launch (a_service, opts) + launcher.launch (opts) else -- error hanling. create l_message.make (1024) @@ -89,77 +73,12 @@ feature {NONE} -- Launch operation l_message.append ("The application crash without available information") l_message.append ("%N%N") end - -- notify shutdown - write_debug_log (generator + ".launch shutdown") + -- send email shutdown end rescue l_retry := True retry end -feature -- CMS Initialization - - initialize_cms - local - l_setup: CMS_DEFAULT_SETUP - utf: UTF_CONVERTER - cms_env: CMS_ENVIRONMENT - do - -- Application Environment initialization - if attached execution_environment.arguments.separate_character_option_value ('d') as l_dir then - create cms_env.make_with_directory_name (l_dir) - else - create cms_env.make_default - end - initialize_logger (cms_env) - - -- CMS Setup - write_debug_log (generator + ".initialize_cms / SETUP based directory=%"" + utf.escaped_utf_32_string_to_utf_8_string_8 (cms_env.path.name) + "%"") - create l_setup.make (cms_env) - - -- CMS - write_debug_log (generator + ".initialize_cms / CMS") - setup_storage (l_setup) - setup_modules (l_setup) - create cms_service.make (l_setup) - end - -feature -- CMS setup - - setup_modules (a_setup: CMS_SETUP) - -- Setup additional modules. - local - m: CMS_MODULE - do - create {NODE_MODULE} m.make (a_setup) - m.enable - a_setup.register_module (m) - - create {BASIC_AUTH_MODULE} m.make - if not a_setup.module_with_same_type_registered (m) then - m.enable - a_setup.register_module (m) - end - - create {CMS_DEBUG_MODULE} m.make - m.enable - a_setup.register_module (m) - - create {CMS_DEMO_MODULE} m.make - m.enable - a_setup.register_module (m) - - create {CMS_BLOG_MODULE} m.make - m.enable - a_setup.register_module (m) - end - - setup_storage (a_setup: CMS_SETUP) - -- Setup storage by declaring storage builder. - do --- a_setup.storage_drivers.force (create {CMS_STORAGE_MYSQL_BUILDER}.make, "mysql") - a_setup.storage_drivers.force (create {CMS_STORAGE_SQLITE_BUILDER}.make, "sqlite") - end - end diff --git a/examples/demo/src/ewf_roc_server_execution.e b/examples/demo/src/ewf_roc_server_execution.e new file mode 100644 index 0000000..4256ef5 --- /dev/null +++ b/examples/demo/src/ewf_roc_server_execution.e @@ -0,0 +1,81 @@ +note + description: "Summary description for {EWF_ROC_SERVER_EXECUTION}." + date: "$Date$" + revision: "$Revision$" + +class + EWF_ROC_SERVER_EXECUTION + +inherit + CMS_EXECUTION + redefine + initialize + end + + REFACTORING_HELPER + + SHARED_LOGGER + +create + make + +feature {NONE} -- Initialization + + initialize + do + Precursor + end + + initial_cms_setup: CMS_DEFAULT_SETUP + -- CMS setup. + local + l_env: CMS_ENVIRONMENT + do + if attached execution_environment.arguments.separate_character_option_value ('d') as l_dir then + create l_env.make_with_directory_name (l_dir) + else + create l_env.make_default + end + create Result.make (l_env) + end + +feature -- CMS setup + + setup_storage (a_setup: CMS_SETUP) + do + debug ("refactor_fixme") + to_implement ("To implement custom storage") + end +-- a_setup.storage_drivers.force (create {CMS_STORAGE_MYSQL_BUILDER}.make, "mysql") + a_setup.storage_drivers.force (create {CMS_STORAGE_SQLITE_BUILDER}.make, "sqlite") + end + + setup_modules (a_setup: CMS_SETUP) + -- Setup additional modules. + local + m: CMS_MODULE + do + create {NODE_MODULE} m.make (a_setup) + m.enable + a_setup.register_module (m) + + create {BASIC_AUTH_MODULE} m.make + if not a_setup.module_with_same_type_registered (m) then + m.enable + a_setup.register_module (m) + end + + create {CMS_DEBUG_MODULE} m.make + m.enable + a_setup.register_module (m) + + create {CMS_DEMO_MODULE} m.make + m.enable + a_setup.register_module (m) + + create {CMS_BLOG_MODULE} m.make + m.enable + a_setup.register_module (m) + end + +end diff --git a/library/app_env/src/configuration/logger_configuration.e b/library/app_env/src/configuration/logger_configuration.e index ad41aa4..d66e89c 100644 --- a/library/app_env/src/configuration/logger_configuration.e +++ b/library/app_env/src/configuration/logger_configuration.e @@ -30,6 +30,7 @@ feature -- Initialization backup_count := 4 level := Log_debug location := Void + type := {STRING_32} "null" ensure then backup_count_set: backup_count = 4 level_set: level = Log_debug @@ -48,6 +49,9 @@ feature -- Access level: INTEGER -- Logger level. + type: IMMUTABLE_STRING_32 + -- Type of logging. + feature -- Element Change set_location (a_location: detachable PATH) @@ -65,6 +69,15 @@ feature -- Element Change set_location (create {PATH}.make_from_string (a_location)) end + set_type_with_string (a_type: detachable READABLE_STRING_GENERAL) + do + if a_type /= Void and then not a_type.is_whitespace then + create type.make_from_string_general (a_type) + else + create type.make_from_string_general ("null") + end + end + set_backup_count (a_backup: NATURAL) -- Set backup_count to `a_backup'. do diff --git a/library/app_env/src/logger/logger.e b/library/app_env/src/logger/logger.e index 2a77068..2fc0857 100644 --- a/library/app_env/src/logger/logger.e +++ b/library/app_env/src/logger/logger.e @@ -32,7 +32,7 @@ feature {NONE} -- Initialization create log.make end - make_with_environment (app: APPLICATION_ENVIRONMENT) + make_with_environment (app: separate APPLICATION_ENVIRONMENT) -- Initialize a logger object with an application environment `app'. do make @@ -49,7 +49,7 @@ feature {NONE} -- Initialization feature -- Change - apply_environment (app: APPLICATION_ENVIRONMENT) + apply_environment (app: separate APPLICATION_ENVIRONMENT) do initialize_logger (app, log) end @@ -58,75 +58,107 @@ feature {NONE} -- Internal log: LOGGING_FACILITY +feature -- Settings + + level: INTEGER + feature -- Logging + put_debug (a_message: separate READABLE_STRING_8) + -- Put message `a_message' to the log at debug level. + do + if level >= log_debug then + log.write_debug (create {STRING}.make_from_separate (a_message)) + end + end + put_information (a_message: separate READABLE_STRING_8) -- Put message `a_message' to the log at information level. do - log.write_information (create {STRING}.make_from_separate (a_message)) - end - - put_error (a_message: separate READABLE_STRING_8) - -- Put message `a_message' to the log at error level. - do - log.write_error (create {STRING}.make_from_separate (a_message)) + if level >= log_information then + log.write_information (create {STRING}.make_from_separate (a_message)) + end end put_warning (a_message: separate READABLE_STRING_8) -- Put message `a_message' to the log at warning level. do - log.write_warning (create {STRING}.make_from_separate (a_message)) + if level >= log_warning then + log.write_warning (create {STRING}.make_from_separate (a_message)) + end + end + + put_error (a_message: separate READABLE_STRING_8) + -- Put message `a_message' to the log at error level. + do + if level >= log_error then + log.write_error (create {STRING}.make_from_separate (a_message)) + end end put_critical (a_message: separate READABLE_STRING_8) -- Put message `a_message' to the log at critical level. do - log.write_critical (create {STRING}.make_from_separate (a_message)) + if level >= log_critical then + log.write_critical (create {STRING}.make_from_separate (a_message)) + end end put_alert (a_message: separate READABLE_STRING_8) -- Put message `a_message' to the log at alert level. do - log.write_alert (create {STRING}.make_from_separate (a_message)) - end - - put_debug (a_message: separate READABLE_STRING_8) - -- Put message `a_message' to the log at debug level. - do - log.write_debug (create {STRING}.make_from_separate (a_message)) + if level >= log_alert then + log.write_alert (create {STRING}.make_from_separate (a_message)) + end end feature {NONE} -- Implementation - initialize_logger (app: APPLICATION_ENVIRONMENT; a_log: like log) + initialize_logger (app: separate APPLICATION_ENVIRONMENT; a_log: like log) local l_log_writer_file: LOG_ROLLING_WRITER_FILE - l_log_writer: LOG_WRITER + l_log_writer: detachable LOG_WRITER l_logs_path: detachable PATH l_logger_config: LOGGER_CONFIGURATION ut: FILE_UTILITIES + p: PATH + l_name: IMMUTABLE_STRING_32 do - l_logger_config := new_logger_level_configuration (app.application_config_path) - l_logs_path := l_logger_config.location - if l_logs_path = Void then - l_logs_path := app.logs_path + create l_name.make_from_separate (app.name) + create p.make_from_separate (app.application_config_path) +-- l_name := app.name +-- p := app.application_config_path + + l_logger_config := new_logger_level_configuration (p) + if l_logger_config.type.is_case_insensitive_equal_general ("file") then + l_logs_path := l_logger_config.location + if l_logs_path = Void then + create l_logs_path.make_from_separate (app.logs_path) + end + if ut.directory_path_exists (l_logs_path) then + create l_log_writer_file.make_at_location (l_logs_path.extended (l_name).appended_with_extension ("log")) + l_log_writer_file.set_max_file_size ({NATURAL_64} 1024 * 1204) + l_log_writer_file.set_max_backup_count (l_logger_config.backup_count) + l_log_writer := l_log_writer_file + else + -- Should we create the directory anyway ? + end + elseif l_logger_config.type.is_case_insensitive_equal_general ("stderr") then + create {LOG_WRITER_STDERR} l_log_writer end - if ut.directory_path_exists (l_logs_path) then - create l_log_writer_file.make_at_location (l_logs_path.extended (app.name).appended_with_extension ("log")) - l_log_writer_file.set_max_file_size ({NATURAL_64} 1024 * 1204) - l_log_writer_file.set_max_backup_count (l_logger_config.backup_count) - l_log_writer := l_log_writer_file - else - -- Should we create the directory anyway ? + if l_log_writer = Void then create {LOG_WRITER_NULL} l_log_writer + set_logger_level (l_log_writer, log_notice) + else + set_logger_level (l_log_writer, 0) -- None end - set_logger_level (l_log_writer, l_logger_config.level) a_log.register_log_writer (l_log_writer) end set_logger_level (a_log_writer: LOG_WRITER; a_priority: INTEGER) -- Setup the logger level based on `a_priority' do + level := a_priority if a_priority = log_debug then a_log_writer.enable_debug_log_level elseif a_priority = Log_emergency then @@ -167,6 +199,9 @@ feature {NONE} -- Implementation attached l_parser.parsed_json_object as jv and then attached {JSON_OBJECT} jv.item ("logger") as l_logger then + if attached {JSON_STRING} l_logger.item ("type") as l_type then + Result.set_type_with_string (l_type.item) + end if attached {JSON_STRING} l_logger.item ("location") as l_location then Result.set_location_with_string (l_location.item) end diff --git a/library/app_env/src/logger/shared_logger.e b/library/app_env/src/logger/shared_logger.e index 1c05aba..625f07d 100644 --- a/library/app_env/src/logger/shared_logger.e +++ b/library/app_env/src/logger/shared_logger.e @@ -35,72 +35,113 @@ feature -- Logging write_debug_log (m: READABLE_STRING_8) do - write_debug_log_to (m, logger) +-- write_debug_log_to (m, logger) end write_information_log (m: READABLE_STRING_8) do - write_information_log_to (m, logger) +-- write_information_log_to (m, logger) end write_warning_log (m: READABLE_STRING_8) do - write_warning_log_to (m, logger) +-- write_warning_log_to (m, logger) end write_error_log (m: READABLE_STRING_8) do - write_error_log_to (m, logger) +-- write_error_log_to (m, logger) end write_critical_log (m: READABLE_STRING_8) do - write_critical_log_to (m, logger) +-- write_critical_log_to (m, logger) end write_alert_log (m: READABLE_STRING_8) do - write_alert_log_to (m, logger) +-- write_alert_log_to (m, logger) end feature {NONE} -- Logger: separate implementation write_debug_log_to (m: READABLE_STRING_8; a_log: like logger) + local + retried: BOOLEAN do - a_log.put_debug (m) + if not retried then + a_log.put_debug (m) + end + rescue + retried := True + retry end write_information_log_to (m: READABLE_STRING_8; a_log: like logger) + local + retried: BOOLEAN do - a_log.put_information (m) + if not retried then + a_log.put_information (m) + end + rescue + retried := True + retry end write_warning_log_to (m: READABLE_STRING_8; a_log: like logger) + local + retried: BOOLEAN do - a_log.put_warning (m) + if not retried then + a_log.put_warning (m) + end + rescue + retried := True + retry end write_error_log_to (m: READABLE_STRING_8; a_log: like logger) + local + retried: BOOLEAN do - a_log.put_error (m) + if not retried then + a_log.put_error (m) + end + rescue + retried := True + retry end write_critical_log_to (m: READABLE_STRING_8; a_log: like logger) + local + retried: BOOLEAN do - a_log.put_critical (m) + if not retried then + a_log.put_critical (m) + end + rescue + retried := True + retry end write_alert_log_to (m: READABLE_STRING_8; a_log: like logger) + local + retried: BOOLEAN do - a_log.put_alert (m) + if not retried then + a_log.put_alert (m) + end + rescue + retried := True + retry end - feature {NONE} -- Implementation initialize_logger (app: APPLICATION_ENVIRONMENT) local - l_logger: LOGGER + l_logger: separate LOGGER do create l_logger.make_with_environment (app) set_logger_to (l_logger, logger_cell) diff --git a/library/persistence/implementation/store/cms_storage_store_sql.e b/library/persistence/implementation/store/cms_storage_store_sql.e index acfec12..0a36c52 100644 --- a/library/persistence/implementation/store/cms_storage_store_sql.e +++ b/library/persistence/implementation/store/cms_storage_store_sql.e @@ -32,6 +32,15 @@ feature -- Status report Result := connection.is_connected end +feature -- Basic operation + + close + -- + -- Disconnect from SQL database. + do + connection.disconnect + end + feature {NONE} -- Implementation db_handler: DATABASE_HANDLER diff --git a/library/persistence/sqlite/src/cms_storage_sqlite_builder.e b/library/persistence/sqlite/src/cms_storage_sqlite_builder.e index f59beee..f48a77f 100644 --- a/library/persistence/sqlite/src/cms_storage_sqlite_builder.e +++ b/library/persistence/sqlite/src/cms_storage_sqlite_builder.e @@ -29,15 +29,25 @@ feature -- Factory storage (a_setup: CMS_SETUP): detachable CMS_STORAGE_SQLITE local s: STRING - conn: DATABASE_CONNECTION + conn: detachable DATABASE_CONNECTION do - if attached (create {APPLICATION_JSON_CONFIGURATION_HELPER}).new_database_configuration (a_setup.environment.application_config_path) as l_database_config then + if + attached (create {APPLICATION_JSON_CONFIGURATION_HELPER}).new_database_configuration (a_setup.environment.application_config_path) as l_database_config + then s := "Driver=SQLite3 ODBC Driver;Database=" if attached l_database_config.database_name as db_name then s.append (db_name) end s.append (";LongNames=0;Timeout=1000;NoTXN=0;SyncPragma=NORMAL;StepAPI=0;") - create {DATABASE_CONNECTION_ODBC} conn.login_with_connection_string (s) + if attached reuseable_connection.item as d then + if s.same_string (d.name) then + conn := d.connection + end + end + if conn = Void or else not conn.is_connected then + create {DATABASE_CONNECTION_ODBC} conn.login_with_connection_string (s) + reuseable_connection.replace ([s, conn]) + end if conn.is_connected then create Result.make (conn) set_map_zero_null_value (False) --| This way we map 0 to 0, instead of Null as default. @@ -50,4 +60,9 @@ feature -- Factory end end + reuseable_connection: CELL [detachable TUPLE [name: STRING; connection: DATABASE_CONNECTION]] + once + create Result.put (Void) + end + end diff --git a/modules/basic_auth/filter/basic_auth_filter.e b/modules/basic_auth/filter/basic_auth_filter.e index 0154d04..f2b3b40 100644 --- a/modules/basic_auth/filter/basic_auth_filter.e +++ b/modules/basic_auth/filter/basic_auth_filter.e @@ -22,12 +22,13 @@ feature -- Basic operations -- Execute the filter. local l_auth: HTTP_AUTHORIZATION - utf: UTF_CONVERTER do api.logger.put_debug (generator + ".execute ", Void) create l_auth.make (req.http_authorization) - if attached req.raw_header_data as l_raw_data then - api.logger.put_debug (generator + ".execute " + utf.escaped_utf_32_string_to_utf_8_string_8 (l_raw_data), Void) + debug + if attached req.raw_header_data as l_raw_data then + api.logger.put_debug (generator + ".execute " + (create {UTF_CONVERTER}).escaped_utf_32_string_to_utf_8_string_8 (l_raw_data), Void) + end end -- A valid user if diff --git a/modules/node/handler/nodes_handler.e b/modules/node/handler/nodes_handler.e index 289514b..e6f317c 100644 --- a/modules/node/handler/nodes_handler.e +++ b/modules/node/handler/nodes_handler.e @@ -63,7 +63,7 @@ feature -- HTTP Methods create s_pager.make_empty create l_page_helper.make ("nodes/?page={page}&size={size}", node_api.nodes_count, 25) -- FIXME: Make this default page size a global CMS settings l_page_helper.get_setting_from_request (req) - if l_page_helper.pages_count > 1 then + if l_page_helper.has_upper_limit and then l_page_helper.pages_count > 1 then l_page_helper.append_to_html (l_response, s_pager) if l_page_helper.page_size > 25 then s.append (s_pager) diff --git a/modules/node/handler/trash_handler.e b/modules/node/handler/trash_handler.e index 5f12770..36af87d 100644 --- a/modules/node/handler/trash_handler.e +++ b/modules/node/handler/trash_handler.e @@ -47,9 +47,8 @@ feature -- HTTP Methods -- get them from the configuration file and load them into -- the setup class. - create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api) - if attached current_user (req) as l_user then + create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api) l_page.add_variable (node_api.trashed_nodes (l_user), "nodes") @@ -72,6 +71,9 @@ feature -- HTTP Methods l_page.set_main_content (s) -- l_page.add_block (create {CMS_CONTENT_BLOCK}.make ("nodes_warning", Void, "/nodes/ is not yet fully implemented
      ", Void), "highlighted") l_page.execute + else + create {FORBIDDEN_ERROR_CMS_RESPONSE} l_page.make (req, res, api) + l_page.execute end end diff --git a/src/persistence/cms_storage.e b/src/persistence/cms_storage.e index e3e880e..c45d9c1 100644 --- a/src/persistence/cms_storage.e +++ b/src/persistence/cms_storage.e @@ -39,6 +39,13 @@ feature -- Status report deferred end +feature -- Basic operation + + close + -- Close/disconnect current storage. + deferred + end + feature -- Error Handling error_handler: ERROR_HANDLER diff --git a/src/persistence/cms_storage_null.e b/src/persistence/cms_storage_null.e index 17028e6..1b12b3b 100644 --- a/src/persistence/cms_storage_null.e +++ b/src/persistence/cms_storage_null.e @@ -45,6 +45,13 @@ feature -- Status report Result := True end +feature -- Basic operation + + close + -- + do + end + feature -- URL aliases set_path_alias (a_source: READABLE_STRING_8; a_alias: READABLE_STRING_8) diff --git a/src/service/cms_execution.e b/src/service/cms_execution.e new file mode 100644 index 0000000..823ec8e --- /dev/null +++ b/src/service/cms_execution.e @@ -0,0 +1,286 @@ +note + description: "[ + This class implements the CMS service + + It could be used to implement the main EWF service, or + even for a specific handler. + ]" + +deferred class + CMS_EXECUTION + +inherit + WSF_FILTERED_ROUTED_SKELETON_EXECUTION + undefine + requires_proxy + redefine + create_router, router, + execute_default, + filter_execute, + initialize + end + + WSF_NO_PROXY_POLICY + + WSF_URI_HELPER_FOR_ROUTED_EXECUTION + + WSF_URI_TEMPLATE_HELPER_FOR_ROUTED_EXECUTION + + REFACTORING_HELPER + + SHARED_LOGGER + +--create +-- make + +feature {NONE} -- Initialization + + initialize + -- Build a CMS service with `a_api' + local + l_setup: CMS_SETUP + do + l_setup := initial_cms_setup + setup_storage (l_setup) + setup_modules (l_setup) + create api.make (l_setup) + modules := setup.enabled_modules + + initialize_cms + Precursor + end + + initialize_cms + do + write_debug_log (generator + ".initialize_cms") + + -- CMS Initialization + + -- initialize_router + -- initialize_filter: expanded here, for void-safety concern. + create_filter + initialize_router + setup_filter + end + + initialize_modules + -- Intialize modules and keep only enabled modules. + do + modules := setup.enabled_modules + ensure + only_enabled_modules: across modules as ic all ic.item.is_enabled end + end + +feature -- Factory + + initial_cms_setup: CMS_SETUP + deferred + end + +feature -- Access + + api: CMS_API + -- API service. + + setup: CMS_SETUP + -- CMS Setup. + do + Result := api.setup + end + + modules: CMS_MODULE_COLLECTION + -- Configurator of possible modules. + +feature -- CMS setup + + setup_modules (a_setup: CMS_SETUP) + -- Setup additional modules. + deferred + end + + setup_storage (a_setup: CMS_SETUP) + deferred + end + +feature -- Settings: router + + router: CMS_ROUTER + -- + + create_router + -- Create `router'. + do + create router.make (api, 30) + end + + setup_router + -- + local + l_api: like api + l_router: like router + do + api.logger.put_debug (generator + ".setup_router", Void) + -- Configure root of api handler. + + l_router := router + configure_api_root (l_router) + + -- Include routes from modules. + l_api := api + across + modules as ic + loop + ic.item.setup_router (l_router, l_api) + end + -- Configure files handler. + configure_api_file_handler (l_router) + end + + configure_api_root (a_router: WSF_ROUTER) + local + l_root_handler: CMS_ROOT_HANDLER + l_methods: WSF_REQUEST_METHODS + do + api.logger.put_debug (generator + ".configure_api_root", Void) + create l_root_handler.make (api) + create l_methods + l_methods.enable_get + a_router.handle_with_request_methods ("/", l_root_handler, l_methods) + a_router.handle_with_request_methods ("", l_root_handler, l_methods) + map_uri_agent_with_request_methods ("/favicon.ico", agent handle_favicon, a_router.methods_head_get) + end + + configure_api_file_handler (a_router: WSF_ROUTER) + local + fhdl: WSF_FILE_SYSTEM_HANDLER + do + api.logger.put_information (generator + ".configure_api_file_handler", Void) + + create fhdl.make_hidden_with_path (setup.theme_assets_location) + fhdl.disable_index + fhdl.set_not_found_handler (agent (ia_uri: READABLE_STRING_8; ia_req: WSF_REQUEST; ia_res: WSF_RESPONSE) + do + execute_default (ia_req, ia_res) + end) + a_router.handle_with_request_methods ("/theme/", fhdl, router.methods_GET) + + + create fhdl.make_hidden_with_path (setup.environment.www_path) + fhdl.disable_index + fhdl.set_not_found_handler (agent (ia_uri: READABLE_STRING_8; ia_req: WSF_REQUEST; ia_res: WSF_RESPONSE) + do + execute_default (ia_req, ia_res) + end) + a_router.handle_with_request_methods ("/", fhdl, router.methods_GET) + end + +feature -- Execute Filter + + filter_execute (req: WSF_REQUEST; res: WSF_RESPONSE) + -- Execute the filter. + do + res.put_header_line ("Date: " + (create {HTTP_DATE}.make_now_utc).string) + res.put_header_line ("X-EWF-Server: CMS_v1.0") + Precursor (req, res) + end + +feature -- Filters + + create_filter + -- Create `filter'. + local + f, l_filter: detachable WSF_FILTER + l_module: CMS_MODULE + l_api: like api + do + api.logger.put_debug (generator + ".create_filter", Void) + l_filter := Void + + -- Maintenance + create {WSF_MAINTENANCE_FILTER} f + f.set_next (l_filter) + l_filter := f + +-- -- Error Filter +-- create {CMS_ERROR_FILTER} f.make (api) +-- f.set_next (l_filter) +-- l_filter := f + + -- Include filters from modules + l_api := api + across + modules as ic + loop + l_module := ic.item + if + l_module.is_enabled and then + attached l_module.filters (l_api) as l_m_filters + then + across l_m_filters as f_ic loop + f := f_ic.item + f.set_next (l_filter) + l_filter := f + end + end + end + + filter := l_filter + end + + setup_filter + -- Setup `filter'. + local + f: WSF_FILTER + do + api.logger.put_debug (generator + ".setup_filter", Void) + + from + f := filter + until + not attached f.next as l_next + loop + f := l_next + end + f.set_next (Current) + end + +feature -- Execution + + handle_favicon (req: WSF_REQUEST; res: WSF_RESPONSE) + local + ut: FILE_UTILITIES + p: PATH + r: NOT_FOUND_ERROR_CMS_RESPONSE + f: WSF_FILE_RESPONSE + do + p := api.setup.theme_assets_location.extended ("favicon.ico") + if ut.file_path_exists (p) then + create f.make_with_path (p) + res.send (f) + else + create r.make (req, res, api) + r.execute + end + end + + execute_default (req: WSF_REQUEST; res: WSF_RESPONSE) + -- Default request handler if no other are relevant + local + r: NOT_FOUND_ERROR_CMS_RESPONSE + do + to_implement ("Default response for CMS_SERVICE") + create r.make (req, res, api) + r.execute + end + +note + copyright: "2011-2014, Jocelyn Fiat, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/src/service/filter/cms_error_filter.e b/src/service/filter/cms_error_filter.e index 0e5f457..ce85041 100644 --- a/src/service/filter/cms_error_filter.e +++ b/src/service/filter/cms_error_filter.e @@ -22,7 +22,9 @@ feature -- Basic operations local utf: UTF_CONVERTER do - fixme ("Check if it's ok to add new fetures CMS_API.has_error:BOOLEAN and CMS_API.error_description.") + debug ("refactor_fixme") + fixme ("Check if it's ok to add new features CMS_API.has_error:BOOLEAN and CMS_API.error_description.") + end if not api.has_error then api.logger.put_information (generator + ".execute with req: " + req.debug_output, Void) if attached req.raw_header_data as l_header_data then diff --git a/tools/install.bat b/tools/install.bat new file mode 100644 index 0000000..88a7c22 --- /dev/null +++ b/tools/install.bat @@ -0,0 +1,71 @@ +@echo off +setlocal +set TMP_EXCLUDE=%~dp0.install_ROC-copydir-exclude +set COPYCMD= xcopy /EXCLUDE:%TMP_EXCLUDE% /I /E /Y +set TMP_DIR=%~dp0.. +set SAFE_RMDIR=rd /q/s + +echo EIFGENs > %TMP_EXCLUDE% +echo .git >> %TMP_EXCLUDE% +echo .svn >> %TMP_EXCLUDE% + +set TMP_TARGET_DIR=%1 +if -%TMP_TARGET_DIR%- == -- goto ask_target_dir +goto start + +:ask_target_dir +echo Please provide a installation directory (target library) +if -%ISE_LIBRARY%- == -- set ISE_LIBRARY=%EIFFEL_LIBRARY% +if -%ISE_LIBRARY%- == -- set ISE_LIBRARY=%ISE_EIFFEL% +if -%EIFFEL_LIBRARY%- == -- set EIFFEL_LIBRARY=%ISE_LIBRARY% +echo 1: using $EIFFEL_LIBRARY=%EIFFEL_LIBRARY% +echo 2: using $ISE_LIBRARY=%ISE_LIBRARY% +echo 3: using current directory=%CD%\ewf +CHOICE /C 123q /M " > selection:" +if .%ERRORLEVEL%. == .1. goto use_eiffel_library +if .%ERRORLEVEL%. == .2. goto use_ise_library +if .%ERRORLEVEL%. == .3. goto use_current_dir +echo No target directory were specified, you can pass it using the command line +echo Usage: install_ewf {target_directory} +echo Bye ... +goto end + +:use_eiffel_library +if -%EIFFEL_LIBRARY%- == -- goto use_ise_library +set TMP_TARGET_DIR=%EIFFEL_LIBRARY% +goto start + +:use_ise_library +if -%ISE_LIBRARY%- == -- goto use_current_dir +set TMP_TARGET_DIR=%ISE_LIBRARY% +goto start + +:use_current_dir +set TMP_TARGET_DIR=%CD%\ewf +goto start + +:start +set TMP_CONTRIB_DIR=%TMP_TARGET_DIR%\contrib +set TMP_UNSTABLE_DIR=%TMP_TARGET_DIR%\unstable + +echo Install ROC as CMS ewf +%SAFE_RMDIR% %TMP_UNSTABLE_DIR%\library\cms\library +%SAFE_RMDIR% %TMP_UNSTABLE_DIR%\library\cms\src +%SAFE_RMDIR% %TMP_UNSTABLE_DIR%\library\cms\doc +%SAFE_RMDIR% %TMP_UNSTABLE_DIR%\library\cms\modules +%SAFE_RMDIR% %TMP_UNSTABLE_DIR%\library\cms\examples + +%COPYCMD% %TMP_DIR%\library %TMP_UNSTABLE_DIR%\library\web\cms\library +%COPYCMD% %TMP_DIR%\src %TMP_UNSTABLE_DIR%\library\web\cms\src +%COPYCMD% %TMP_DIR%\doc %TMP_UNSTABLE_DIR%\library\web\cms\doc +%COPYCMD% %TMP_DIR%\modules %TMP_UNSTABLE_DIR%\library\web\cms\modules +%COPYCMD% %TMP_DIR%\examples %TMP_UNSTABLE_DIR%\library\web\cms\examples + +copy %TMP_DIR%\cms.ecf %TMP_UNSTABLE_DIR%\cms.ecf +copy %TMP_DIR%\cms-safe.ecf %TMP_UNSTABLE_DIR%\cms-safe.ecf +copy %TMP_DIR%\README.md %TMP_UNSTABLE_DIR%\README.md +copy %TMP_DIR%\package.iron %TMP_UNSTABLE_DIR%\package.iron + +:end +del %TMP_EXCLUDE% + From 53a602d33c869fd17afac5625eb6cf215ec343f3 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Wed, 10 Jun 2015 09:43:04 +0200 Subject: [PATCH 24/27] Removed CMS_SERVICE Updated install.bat script --- src/service/cms_service.e | 279 -------------------------------------- tools/install.bat | 8 +- 2 files changed, 4 insertions(+), 283 deletions(-) delete mode 100644 src/service/cms_service.e diff --git a/src/service/cms_service.e b/src/service/cms_service.e deleted file mode 100644 index 918d0ef..0000000 --- a/src/service/cms_service.e +++ /dev/null @@ -1,279 +0,0 @@ -note - description: "[ - This class implements the CMS service - - It could be used to implement the main EWF service, or - even for a specific handler. - ]" - -class - CMS_SERVICE - -inherit - WSF_ROUTED_SKELETON_SERVICE - rename - execute as execute_service - undefine - requires_proxy - redefine - execute_default, - create_router, - router - end - - WSF_FILTERED_SERVICE - - WSF_FILTER - rename - execute as execute_filter - end - - WSF_NO_PROXY_POLICY - - WSF_URI_HELPER_FOR_ROUTED_SERVICE - - WSF_URI_TEMPLATE_HELPER_FOR_ROUTED_SERVICE - - REFACTORING_HELPER - - SHARED_LOGGER - -create - make - -feature {NONE} -- Initialization - - make (a_setup: CMS_SETUP) - -- Build a CMS service with `a_api' - do - create api.make (a_setup) - initialize - end - - initialize - -- Initialize various parts of the CMS service. - do - initialize_modules - initialize_users - initialize_mailer - -- initialize_router - -- initialize_filter: expanded here, for void-safety concern. - create_filter - initialize_router - setup_filter - end - - initialize_modules - -- Intialize modules and keep only enabled modules. - do - modules := setup.enabled_modules - ensure - only_enabled_modules: across modules as ic all ic.item.is_enabled end - end - - initialize_users - -- Initialize users. - do - end - - initialize_mailer - -- Initialize mailer engine. - do - to_implement ("To Implement mailer") - end - -feature -- Settings: router - - router: CMS_ROUTER - - create_router - -- Create `router'. - do - create router.make (api, 30) - end - - setup_router - -- - local - l_api: like api - l_router: like router - do - api.logger.put_debug (generator + ".setup_router", Void) - -- Configure root of api handler. - - l_router := router - configure_api_root (l_router) - - -- Include routes from modules. - l_api := api - across - modules as ic - loop - ic.item.setup_router (l_router, l_api) - end - -- Configure files handler. - configure_api_file_handler (l_router) - end - - configure_api_root (a_router: WSF_ROUTER) - local - l_root_handler: CMS_ROOT_HANDLER - l_methods: WSF_REQUEST_METHODS - do - api.logger.put_debug (generator + ".configure_api_root", Void) - create l_root_handler.make (api) - create l_methods - l_methods.enable_get - a_router.handle_with_request_methods ("/", l_root_handler, l_methods) - a_router.handle_with_request_methods ("", l_root_handler, l_methods) - map_uri_agent_with_request_methods ("/favicon.ico", agent handle_favicon, a_router.methods_head_get) - end - - configure_api_file_handler (a_router: WSF_ROUTER) - local - fhdl: WSF_FILE_SYSTEM_HANDLER - do - api.logger.put_information (generator + ".configure_api_file_handler", Void) - - create fhdl.make_hidden_with_path (setup.theme_assets_location) - fhdl.disable_index - fhdl.set_not_found_handler (agent (ia_uri: READABLE_STRING_8; ia_req: WSF_REQUEST; ia_res: WSF_RESPONSE) - do - execute_default (ia_req, ia_res) - end) - a_router.handle_with_request_methods ("/theme/", fhdl, router.methods_GET) - - - create fhdl.make_hidden_with_path (setup.environment.www_path) - fhdl.disable_index - fhdl.set_not_found_handler (agent (ia_uri: READABLE_STRING_8; ia_req: WSF_REQUEST; ia_res: WSF_RESPONSE) - do - execute_default (ia_req, ia_res) - end) - a_router.handle_with_request_methods ("/", fhdl, router.methods_GET) - end - -feature -- Execute Filter - - execute_filter (req: WSF_REQUEST; res: WSF_RESPONSE) - -- Execute the filter. - do - res.put_header_line ("Date: " + (create {HTTP_DATE}.make_now_utc).string) - res.put_header_line ("X-EWF-Server: CMS_v1.0") - execute_service (req, res) - end - -feature -- Filters - - create_filter - -- Create `filter'. - local - f, l_filter: detachable WSF_FILTER - l_module: CMS_MODULE - l_api: like api - do - api.logger.put_debug (generator + ".create_filter", Void) - l_filter := Void - - -- Maintenance - create {WSF_MAINTENANCE_FILTER} f - f.set_next (l_filter) - l_filter := f - - -- Error Filter - create {CMS_ERROR_FILTER} f.make (api) - f.set_next (l_filter) - l_filter := f - - -- Include filters from modules - l_api := api - across - modules as ic - loop - l_module := ic.item - if - l_module.is_enabled and then - attached l_module.filters (l_api) as l_m_filters - then - across l_m_filters as f_ic loop - f := f_ic.item - f.set_next (l_filter) - l_filter := f - end - end - end - - filter := l_filter - end - - setup_filter - -- Setup `filter'. - local - f: WSF_FILTER - do - api.logger.put_debug (generator + ".setup_filter", Void) - - from - f := filter - until - not attached f.next as l_next - loop - f := l_next - end - f.set_next (Current) - end - -feature -- Access - - api: CMS_API - -- API service. - - setup: CMS_SETUP - -- CMS setup. - do - Result := api.setup - end - - modules: CMS_MODULE_COLLECTION - -- Configurator of possible modules. - -feature -- Execution - - handle_favicon (req: WSF_REQUEST; res: WSF_RESPONSE) - local - ut: FILE_UTILITIES - p: PATH - r: NOT_FOUND_ERROR_CMS_RESPONSE - f: WSF_FILE_RESPONSE - do - p := api.setup.theme_assets_location.extended ("favicon.ico") - if ut.file_path_exists (p) then - create f.make_with_path (p) - res.send (f) - else - create r.make (req, res, api) - r.execute - end - end - - execute_default (req: WSF_REQUEST; res: WSF_RESPONSE) - -- Default request handler if no other are relevant - local - r: NOT_FOUND_ERROR_CMS_RESPONSE - do - to_implement ("Default response for CMS_SERVICE") - create r.make (req, res, api) - r.execute - end - -note - copyright: "2011-2014, Jocelyn Fiat, Eiffel Software and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" - source: "[ - Eiffel Software - 5949 Hollister Ave., Goleta, CA 93117 USA - Telephone 805-685-1006, Fax 805-685-6869 - Website http://www.eiffel.com - Customer support http://support.eiffel.com - ]" -end diff --git a/tools/install.bat b/tools/install.bat index 88a7c22..5770228 100644 --- a/tools/install.bat +++ b/tools/install.bat @@ -61,10 +61,10 @@ echo Install ROC as CMS ewf %COPYCMD% %TMP_DIR%\modules %TMP_UNSTABLE_DIR%\library\web\cms\modules %COPYCMD% %TMP_DIR%\examples %TMP_UNSTABLE_DIR%\library\web\cms\examples -copy %TMP_DIR%\cms.ecf %TMP_UNSTABLE_DIR%\cms.ecf -copy %TMP_DIR%\cms-safe.ecf %TMP_UNSTABLE_DIR%\cms-safe.ecf -copy %TMP_DIR%\README.md %TMP_UNSTABLE_DIR%\README.md -copy %TMP_DIR%\package.iron %TMP_UNSTABLE_DIR%\package.iron +copy %TMP_DIR%\cms.ecf %TMP_UNSTABLE_DIR%\library\web\cms\cms.ecf +copy %TMP_DIR%\cms-safe.ecf %TMP_UNSTABLE_DIR%\library\web\cms\cms-safe.ecf +copy %TMP_DIR%\README.md %TMP_UNSTABLE_DIR%\library\web\cms\README.md +copy %TMP_DIR%\package.iron %TMP_UNSTABLE_DIR%\library\web\cms\package.iron :end del %TMP_EXCLUDE% From 0b8bee3404611f3d97d05fa1fb9daecf198bd6bf Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Wed, 10 Jun 2015 11:06:58 +0200 Subject: [PATCH 25/27] favor EiffelThread for now, while waiting for SCOOP to be fully ready. --- examples/demo/demo-safe.ecf | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/examples/demo/demo-safe.ecf b/examples/demo/demo-safe.ecf index 3c64fa1..f8bee78 100644 --- a/examples/demo/demo-safe.ecf +++ b/examples/demo/demo-safe.ecf @@ -10,7 +10,7 @@ - + @@ -25,7 +25,7 @@ - + @@ -38,7 +38,7 @@ - + @@ -50,9 +50,6 @@ - From 0fc1cb68ad962b47b5f95e4152f445655f53acc8 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Wed, 10 Jun 2015 18:39:41 +0200 Subject: [PATCH 26/27] Apply recent changes from EWF v1 --- src/modules/cms_debug_module.e | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/cms_debug_module.e b/src/modules/cms_debug_module.e index 9b51d1b..3a25a35 100644 --- a/src/modules/cms_debug_module.e +++ b/src/modules/cms_debug_module.e @@ -39,7 +39,7 @@ feature -- Router setup_router (a_router: WSF_ROUTER; a_api: CMS_API) -- do - a_router.handle ("/debug/", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_debug (a_api, ?, ?))) + a_router.handle ("/debug/", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_debug (a_api, ?, ?)), Void) end feature -- Hooks configuration From 21800e71d339991bad9d27236d4815caabe4dae5 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Thu, 11 Jun 2015 23:03:34 +0200 Subject: [PATCH 27/27] Removed obsolete calls. Updated code to make it clear what is the resource, and what is the associated module resource path. --- src/hooks/cms_hook_block_helper.e | 7 ++++--- src/service/cms_execution.e | 10 +++++----- src/service/response/cms_response.e | 2 ++ 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/hooks/cms_hook_block_helper.e b/src/hooks/cms_hook_block_helper.e index b36e12e..c0da7de 100644 --- a/src/hooks/cms_hook_block_helper.e +++ b/src/hooks/cms_hook_block_helper.e @@ -12,11 +12,12 @@ feature -- Factory template_block (a_module: CMS_MODULE; a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE): detachable CMS_SMARTY_TEMPLATE_BLOCK -- Smarty content block for `a_block_id' in the context of `a_module' and `a_response'. local + res: PATH p: detachable PATH do - create p.make_from_string ("templates") - p := p.extended ("block_").appended (a_block_id).appended_with_extension ("tpl") - p := a_response.module_resource_path (a_module, p) + create res.make_from_string ("templates") + res := res.extended ("block_").appended (a_block_id).appended_with_extension ("tpl") + p := a_response.module_resource_path (a_module, res) if p /= Void then if attached p.entry as e then create Result.make (a_block_id, Void, p.parent, e) diff --git a/src/service/cms_execution.e b/src/service/cms_execution.e index 823ec8e..2160cb6 100644 --- a/src/service/cms_execution.e +++ b/src/service/cms_execution.e @@ -145,9 +145,9 @@ feature -- Settings: router create l_root_handler.make (api) create l_methods l_methods.enable_get - a_router.handle_with_request_methods ("/", l_root_handler, l_methods) - a_router.handle_with_request_methods ("", l_root_handler, l_methods) - map_uri_agent_with_request_methods ("/favicon.ico", agent handle_favicon, a_router.methods_head_get) + a_router.handle ("/", l_root_handler, l_methods) + a_router.handle ("", l_root_handler, l_methods) + map_uri_agent ("/favicon.ico", agent handle_favicon, a_router.methods_head_get) end configure_api_file_handler (a_router: WSF_ROUTER) @@ -162,7 +162,7 @@ feature -- Settings: router do execute_default (ia_req, ia_res) end) - a_router.handle_with_request_methods ("/theme/", fhdl, router.methods_GET) + a_router.handle ("/theme/", fhdl, router.methods_GET) create fhdl.make_hidden_with_path (setup.environment.www_path) @@ -171,7 +171,7 @@ feature -- Settings: router do execute_default (ia_req, ia_res) end) - a_router.handle_with_request_methods ("/", fhdl, router.methods_GET) + a_router.handle ("/", fhdl, router.methods_GET) end feature -- Execute Filter diff --git a/src/service/response/cms_response.e b/src/service/response/cms_response.e index ca409a9..234a0c8 100644 --- a/src/service/response/cms_response.e +++ b/src/service/response/cms_response.e @@ -160,9 +160,11 @@ feature -- Module rp: PATH ut: FILE_UTILITIES do + -- Check first in selected theme folder. rp := module_assets_theme_location (a_module) Result := rp.extended_path (a_resource) if not ut.file_path_exists (Result) then + -- And if not found, look into site/modules/$a_module.name/.... folders. rp := module_assets_location (a_module) Result := rp.extended_path (a_resource) if not ut.file_path_exists (Result) then