diff --git a/cms/cms-safe.ecf b/cms/cms-safe.ecf index 235bd74..e8f43fa 100644 --- a/cms/cms-safe.ecf +++ b/cms/cms-safe.ecf @@ -10,11 +10,18 @@ + + + + + + + /EIFGENs$ diff --git a/cms/src/configuration/cms_default_setup.e b/cms/src/configuration/cms_default_setup.e index e1bf624..76dcab2 100644 --- a/cms/src/configuration/cms_default_setup.e +++ b/cms/src/configuration/cms_default_setup.e @@ -26,9 +26,7 @@ feature {NONE} -- Initialization do configure create modules.make (3) - build_api_service build_mailer - initialize_modules end @@ -61,11 +59,6 @@ feature {NONE} -- Initialization -- m.enable -- modules.extend (m) - - create {BASIC_AUTH_MODULE} m.make (Current) - m.enable - modules.extend (m) - create {NODE_MODULE} m.make (Current) m.enable modules.extend (m) @@ -90,20 +83,6 @@ feature -- Access end - build_api_service - local - l_database: DATABASE_CONNECTION - do - to_implement ("Refactor database setup") - if attached (create {JSON_CONFIGURATION}).new_database_configuration (layout.application_config_path) as l_database_config then - create {DATABASE_CONNECTION_MYSQL} l_database.login_with_connection_string (l_database_config.connection_string) - create api_service.make (create {CMS_STORAGE_MYSQL}.make (l_database)) - else - create {DATABASE_CONNECTION_NULL} l_database.make_common - create api_service.make (create {CMS_STORAGE_NULL}) - end - end - build_auth_engine do to_implement ("Not implemented authentication") diff --git a/cms/src/configuration/cms_setup.e b/cms/src/configuration/cms_setup.e index f0af327..58b0e31 100644 --- a/cms/src/configuration/cms_setup.e +++ b/cms/src/configuration/cms_setup.e @@ -14,9 +14,6 @@ feature -- Access layout: CMS_LAYOUT -- CMS layout. - api_service: CMS_API_SERVICE - -- cms api service. - is_html: BOOLEAN -- api with progressive enhancements css and js, server side rendering. deferred @@ -48,6 +45,10 @@ feature -- Access: Site files_location: PATH + front_page_path: detachable READABLE_STRING_8 + -- Optional path defining the front page. + -- By default "" or "/". + feature -- Access: Theme themes_location: PATH diff --git a/cms/src/hooks/cms_hook.e b/cms/src/hooks/cms_hook.e new file mode 100644 index 0000000..83f9ac3 --- /dev/null +++ b/cms/src/hooks/cms_hook.e @@ -0,0 +1,9 @@ +note + description: "Marker interface" + date: "$Date$" + revision: "$Revision$" + +deferred class + CMS_HOOK + +end diff --git a/cms/src/hooks/cms_hook_auto_register.e b/cms/src/hooks/cms_hook_auto_register.e new file mode 100644 index 0000000..d960b6d --- /dev/null +++ b/cms/src/hooks/cms_hook_auto_register.e @@ -0,0 +1,33 @@ +note + description: "[ + Summary description for {CMS_HOOK_AUTO_REGISTER}. + When inheriting from this class, the declared hooks are automatically + registered, otherwise, each descendant has to add it to the cms service + itself. + ]" + date: "$Date: 2014-08-28 08:21:49 -0300 (ju. 28 de ago. de 2014) $" + revision: "$Revision: 95708 $" + +deferred class + CMS_HOOK_AUTO_REGISTER + +inherit + CMS_HOOK + +feature -- Hook + + hook_auto_register (a_response: CMS_RESPONSE) + do + if attached {CMS_HOOK_MENU_ALTER} Current as h_menu_alter then + a_response.add_menu_alter_hook (h_menu_alter) + end + if attached {CMS_HOOK_BLOCK} Current as h_block then + a_response.add_block_hook (h_block) + end + if attached {CMS_HOOK_FORM_ALTER} Current as h_block then + a_response.add_form_alter_hook (h_block) + end + + end + +end diff --git a/cms/src/hooks/cms_hook_block.e b/cms/src/hooks/cms_hook_block.e new file mode 100644 index 0000000..89d001c --- /dev/null +++ b/cms/src/hooks/cms_hook_block.e @@ -0,0 +1,25 @@ +note + description: "Summary description for {CMS_HOOK_BLOCK}." + author: "" + date: "$Date: 2014-08-28 08:21:49 -0300 (ju. 28 de ago. de 2014) $" + revision: "$Revision: 95708 $" + +deferred class + CMS_HOOK_BLOCK + +inherit + CMS_HOOK + +feature -- Hook + + block_list: ITERABLE [like {CMS_BLOCK}.name] + -- List of block names, managed by current object. + deferred + end + + get_block_view (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE) + -- Get block object identified by `a_block_id' and associate with `a_response'. + deferred + end + +end diff --git a/cms/src/hooks/cms_hook_form_alter.e b/cms/src/hooks/cms_hook_form_alter.e new file mode 100644 index 0000000..472979c --- /dev/null +++ b/cms/src/hooks/cms_hook_form_alter.e @@ -0,0 +1,17 @@ +note + description: "Describe how to alter a form before it's rendered" + date: "$Date: 2014-08-28 08:21:49 -0300 (ju. 28 de ago. de 2014) $" + +deferred class + CMS_HOOK_FORM_ALTER + +inherit + CMS_HOOK + +feature -- Hook + + form_alter (a_form: CMS_FORM; a_form_data: detachable WSF_FORM_DATA; a_response: CMS_RESPONSE) + deferred + end + +end diff --git a/cms/src/hooks/cms_hook_menu_alter.e b/cms/src/hooks/cms_hook_menu_alter.e new file mode 100644 index 0000000..d409662 --- /dev/null +++ b/cms/src/hooks/cms_hook_menu_alter.e @@ -0,0 +1,17 @@ +note + description: "Describe how to alter a menu before it's rendered." + date: "$Date: 2014-08-28 08:21:49 -0300 (ju. 28 de ago. de 2014) $" + +deferred class + CMS_HOOK_MENU_ALTER + +inherit + CMS_HOOK + +feature -- Hook + + menu_alter (a_menu_system: CMS_MENU_SYSTEM; a_response: CMS_RESPONSE) + deferred + end + +end diff --git a/cms/src/hooks/cms_hook_value_alter.e b/cms/src/hooks/cms_hook_value_alter.e new file mode 100644 index 0000000..0ec43b9 --- /dev/null +++ b/cms/src/hooks/cms_hook_value_alter.e @@ -0,0 +1,28 @@ +note + description: "Describe how to alter generic values before they are rendered." + date: "$Date: 2014-10-23 08:30:11 -0300 (ju. 23 de oct. de 2014) $" + revision: "$Revision: 95980 $" + +deferred class + CMS_HOOK_VALUE_ALTER + +inherit + + CMS_HOOK + +feature -- Hook + + value_alter (a_value: CMS_VALUE_TABLE; a_response: CMS_RESPONSE) + deferred + 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/cms/src/kernel/cms_common_api.e b/cms/src/kernel/cms_common_api.e new file mode 100644 index 0000000..9301ddf --- /dev/null +++ b/cms/src/kernel/cms_common_api.e @@ -0,0 +1,97 @@ +note + description: "Summary description for {WSF_CMS_COMMON_API}." + author: "" + date: "$Date: 2014-08-28 08:21:49 -0300 (ju. 28 de ago. de 2014) $" + revision: "$Revision: 95708 $" + +deferred class + CMS_COMMON_API + +inherit + WSF_API_UTILITIES + +feature {NONE} -- Access + + site_url: READABLE_STRING_8 + do + Result := "" + end + + base_url: detachable READABLE_STRING_8 + -- Base url if any. + do + end + +feature -- Access + + user_link (u: CMS_USER): like link + do + Result := link (u.name, "/user/" + u.id.out, Void) + end + + node_link (n: CMS_NODE): like link + do + Result := link (n.title, "/node/" + n.id.out, Void) + end + + user_url (u: CMS_USER): like url + do + Result := url ("/user/" + u.id.out, Void) + end + + node_url (n: CMS_NODE): like url + do + Result := url ("/node/" + n.id.out, Void) + end + +feature -- Helper + + is_empty (s: detachable READABLE_STRING_GENERAL): BOOLEAN + -- Is `s' is Void or empty ? + do + Result := s = Void or else s.is_empty + end + + unix_timestamp (dt: DATE_TIME): INTEGER_64 + do + Result := (create {HTTP_DATE_TIME_UTILITIES}).unix_time_stamp (dt) + end + + unix_timestamp_to_date_time (t: INTEGER_64): DATE_TIME + do + Result := (create {HTTP_DATE_TIME_UTILITIES}).unix_time_stamp_to_date_time (t) + end + + string_unix_timestamp_to_date_time (s: READABLE_STRING_8): DATE_TIME + do + if s.is_integer_64 then + Result := (create {HTTP_DATE_TIME_UTILITIES}).unix_time_stamp_to_date_time (s.to_integer_64) + else + Result := (create {HTTP_DATE_TIME_UTILITIES}).unix_time_stamp_to_date_time (0) + end + end + +feature {NONE} -- Implementation + + options_boolean (opts: HASH_TABLE [detachable ANY, STRING]; k: STRING; dft: BOOLEAN): BOOLEAN + do + if attached {BOOLEAN} opts.item (k) as h then + Result := h + else + Result := dft + end + end + + options_string (opts: HASH_TABLE [detachable ANY, STRING]; k: STRING): detachable STRING + do + if attached {STRING} opts.item (k) as s then + Result := s + end + end + +-- html_encoder: HTML_ENCODER +-- once ("thread") +-- create Result +-- end + +end diff --git a/cms/src/kernel/content/cms_block.e b/cms/src/kernel/content/cms_block.e new file mode 100644 index 0000000..0b67db7 --- /dev/null +++ b/cms/src/kernel/content/cms_block.e @@ -0,0 +1,28 @@ +note + description: "Summary description for {CMS_BLOCK}." + date: "$Date: 2014-08-28 08:21:49 -0300 (ju. 28 de ago. de 2014) $" + +deferred class + CMS_BLOCK + +feature -- Access + + name: READABLE_STRING_8 + deferred + end + + title: detachable READABLE_STRING_32 + deferred + end + +feature -- status report + + is_enabled: BOOLEAN + +feature -- Conversion + + to_html (a_theme: CMS_THEME): STRING_8 + deferred + end + +end diff --git a/cms/src/kernel/content/cms_block_region.e b/cms/src/kernel/content/cms_block_region.e new file mode 100644 index 0000000..baef14f --- /dev/null +++ b/cms/src/kernel/content/cms_block_region.e @@ -0,0 +1,42 @@ +note + description: "Summary description for {CMS_BLOCK_REGION}." + date: "$Date: 2014-10-30 12:55:33 -0300 (ju. 30 de oct. de 2014) $" + +class + CMS_BLOCK_REGION + +create + make + +feature {NONE} -- Initialization + + make (a_name: like name) + do + name := a_name + create blocks.make (1) + end + +feature -- Access + + name: READABLE_STRING_8 + + blocks: ARRAYED_LIST [CMS_BLOCK] + +feature -- Element change + + extend (b: CMS_BLOCK) + do + blocks.force (b) + 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/cms/src/kernel/content/cms_content_block.e b/cms/src/kernel/content/cms_content_block.e new file mode 100644 index 0000000..466c2f3 --- /dev/null +++ b/cms/src/kernel/content/cms_content_block.e @@ -0,0 +1,79 @@ +note + description: "Summary description for {CMS_CONTENT_BLOCK}." + author: "" + date: "$Date: 2014-10-30 12:55:33 -0300 (ju. 30 de oct. de 2014) $" + revision: "$Revision: 96018 $" + +class + CMS_CONTENT_BLOCK + +inherit + CMS_BLOCK + +create + make, + make_raw + +feature {NONE} -- Initialization + + make (a_name: like name; a_title: like title; a_content: like content; a_format: like format) + do + is_enabled := True + name := a_name + title := a_title + content := a_content + format := a_format + end + + make_raw (a_name: like name; a_title: like title; a_content: like content; a_format: like format) + do + make (a_name, a_title, a_content, a_format) + set_is_raw (True) + end + +feature -- Access + + name: READABLE_STRING_8 + + title: detachable READABLE_STRING_32 + + content: READABLE_STRING_8 + + format: detachable CONTENT_FORMAT + +feature -- Status report + + is_raw: BOOLEAN + -- Is raw? + -- If True, do not get wrapped it with block specific div + +feature -- Element change + + set_is_raw (b: BOOLEAN) + do + is_raw := b + end + +feature -- Conversion + + to_html (a_theme: CMS_THEME): STRING_8 + do + -- Why in this particular case theme is not used to generate the content? + + if attached format as f then + Result := f.formatted_output (content) + else + Result := content + end + 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/cms/src/kernel/content/cms_encoders.e b/cms/src/kernel/content/cms_encoders.e new file mode 100644 index 0000000..36b60fc --- /dev/null +++ b/cms/src/kernel/content/cms_encoders.e @@ -0,0 +1,35 @@ +note + description: "Summary description for {CMS_ENCODERS}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + CMS_ENCODERS + +feature -- Encoders + + url_encoded (s: detachable READABLE_STRING_GENERAL): STRING_8 + local + enc: URL_ENCODER + do + create enc + if s /= Void then + Result := enc.general_encoded_string (s) + else + create Result.make_empty + end + end + + html_encoded (s: detachable READABLE_STRING_GENERAL): STRING_8 + local + enc: HTML_ENCODER + do + create enc + if s /= Void then + Result := enc.general_encoded_string (s) + else + create Result.make_empty + end + end +end diff --git a/cms/src/kernel/content/cms_menu_block.e b/cms/src/kernel/content/cms_menu_block.e new file mode 100644 index 0000000..a7a0797 --- /dev/null +++ b/cms/src/kernel/content/cms_menu_block.e @@ -0,0 +1,41 @@ +note + description: "Summary description for {CMS_MENU_BLOCK}." + date: "$Date: 2014-08-28 08:21:49 -0300 (ju. 28 de ago. de 2014) $" + +class + CMS_MENU_BLOCK + +inherit + CMS_BLOCK + +create + make + +feature {NONE} -- Initialization + + make (a_menu: like menu) + do + is_enabled := True + menu := a_menu + name := a_menu.name + title := a_menu.title + end + +feature -- Access + + menu: CMS_MENU + + name: READABLE_STRING_8 + + title: detachable READABLE_STRING_32 + + is_horizontal: BOOLEAN + +feature -- Conversion + + to_html (a_theme: CMS_THEME): STRING_8 + do + Result := a_theme.menu_html (menu, is_horizontal) + end + +end diff --git a/cms/src/kernel/content/cms_value_table.e b/cms/src/kernel/content/cms_value_table.e new file mode 100644 index 0000000..2e5ccc9 --- /dev/null +++ b/cms/src/kernel/content/cms_value_table.e @@ -0,0 +1,89 @@ +note + description: "Summary description for {CMS_VALUE_TABLE}." + date: "$Date: 2014-10-23 08:30:11 -0300 (ju. 23 de oct. de 2014) $" + revision: "$Revision: 95980 $" + +class + CMS_VALUE_TABLE + +inherit + TABLE_ITERABLE [detachable ANY, READABLE_STRING_GENERAL] + +create + make + +feature {NONE} -- Initialization + + make (nb: INTEGER) + do + create table.make (nb) + end + +feature -- Access + + count: INTEGER + -- Number of items. + do + Result := table.count + end + + item (key: READABLE_STRING_GENERAL): detachable ANY + -- Item associated with `key', if present + -- otherwise default value of type `G'. + note + option: stable + do + Result := table.item (key) + end + + has (key: READABLE_STRING_GENERAL): BOOLEAN + -- Has item associated with key `key'? + do + Result := table.has (key) + end + + new_cursor: TABLE_ITERATION_CURSOR [detachable ANY, READABLE_STRING_GENERAL] + -- + do + Result := table.new_cursor + end + +feature -- Element change + + put (new: detachable ANY; key: READABLE_STRING_GENERAL) + -- Insert `new' with `key' if there is no other item + -- associated with the same key. + do + table.put (new, key) + end + + force (new: detachable ANY; key: READABLE_STRING_GENERAL) + -- Update table so that `new' will be the item associated + -- with `key'. + do + table.force (new, key) + end + + remove (key: READABLE_STRING_GENERAL) + do + table.remove (key) + end + +feature {NONE} -- Duplication + + table: STRING_TABLE [detachable ANY] + +invariant + table_set: table /= Void + +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/cms/src/kernel/content/format/cms_formats.e b/cms/src/kernel/content/format/cms_formats.e new file mode 100644 index 0000000..11823ae --- /dev/null +++ b/cms/src/kernel/content/format/cms_formats.e @@ -0,0 +1,64 @@ +note + description: "Summary description for {CMS_FORMATS}." + author: "" + date: "$Date: 2014-10-16 04:45:23 -0300 (ju. 16 de oct. de 2014) $" + revision: "$Revision: 95932 $" + +class + CMS_FORMATS + +feature -- Access + + format (a_name: like {CONTENT_FORMAT}.name): detachable CONTENT_FORMAT + do + across + all_formats as c + until + Result /= Void + loop + if c.item.name.same_string (a_name) then + Result := c.item + end + end + end + + all_formats: LIST [CONTENT_FORMAT] + once + create {ARRAYED_LIST [CONTENT_FORMAT]} Result.make (3) + Result.force (plain_text) + Result.force (full_html) + Result.force (filtered_html) + end + + default_format: CONTENT_FORMAT + do + Result := plain_text --FIXME + end + + plain_text: PLAIN_TEXT_CONTENT_FORMAT + once + create Result + end + + full_html: FULL_HTML_CONTENT_FORMAT + once + create Result + end + + filtered_html: FILTERED_HTML_CONTENT_FORMAT + once + create Result + 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/cms/src/kernel/form/cms_form.e b/cms/src/kernel/form/cms_form.e new file mode 100644 index 0000000..2038a14 --- /dev/null +++ b/cms/src/kernel/form/cms_form.e @@ -0,0 +1,42 @@ +note + description: "Summary description for {CMS_FORM}." + date: "$Date: 2014-08-28 08:21:49 -0300 (ju. 28 de ago. de 2014) $" + revision: "$Revision: 95708 $" + +class + CMS_FORM + +inherit + WSF_FORM + rename + process as process_form + end + +create + make + +feature -- Basic operation + + prepare (a_response: CMS_RESPONSE) + do + a_response.call_form_alter_hooks (Current, Void) + end + + process (a_response: CMS_RESPONSE) + do + process_form (a_response.request, agent on_prepared (a_response, ?), agent on_processed (a_response, ?)) + end + + on_prepared (a_response: CMS_RESPONSE; fd: WSF_FORM_DATA) + do + a_response.call_form_alter_hooks (Current, fd) + end + + on_processed (a_response: CMS_RESPONSE; fd: WSF_FORM_DATA) + do + if not fd.is_valid or fd.has_error then + a_response.report_form_errors (fd) + end + end + +end diff --git a/cms/src/kernel/link/cms_menu_system.e b/cms/src/kernel/link/cms_menu_system.e new file mode 100644 index 0000000..5565c5d --- /dev/null +++ b/cms/src/kernel/link/cms_menu_system.e @@ -0,0 +1,100 @@ +note + description: "Describe the navigation menus." + date: "$Date: 2014-08-28 08:21:49 -0300 (ju. 28 de ago. de 2014) $" + revision: "$Revision: 95708 $" + +class + CMS_MENU_SYSTEM + +inherit + ITERABLE [CMS_MENU] + + REFACTORING_HELPER +create + make + +feature {NONE} -- Initialization + + make + -- Create a predefined manu system + do + to_implement ("Refactor, take the info from a Database or Configuration file.") + create items.make (5) + force (create {CMS_MENU}.make ("primary", 3)) -- primary menu + force (create {CMS_MENU}.make_with_title ("management", "Management", 3)) -- secondary in admin view. + force (create {CMS_MENU}.make_with_title ("secondary", "Navigation", 3)) -- secondary + force (create {CMS_MENU}.make_with_title ("user", "User", 3)) -- first_side_bar + end + +feature -- Access + + item (n: like {CMS_MENU}.name): CMS_MENU + local + m: detachable CMS_MENU + do + m := items.item (n) + if m = Void then + create m.make (n, 3) + force (m) + end + Result := m + end + + main_menu: CMS_MENU + obsolete + "Use `primary_menu' [Nov/2014]" + do + Result := primary_menu + end + + primary_menu: CMS_MENU + do + Result := item ("primary") + end + + secondary_menu: CMS_MENU + do + Result := item ("secondary") + end + + management_menu: CMS_MENU + do + Result := item ("management") + end + + navigation_menu: CMS_MENU + do + Result := item ("navigation") + end + + user_menu: CMS_MENU + do + Result := item ("user") + end + + primary_tabs: CMS_MENU + do + Result := item ("primary-tabs") + end + +feature -- Change + + force (m: CMS_MENU) + do + items.force (m, m.name) + end + +feature -- Access + + new_cursor: ITERATION_CURSOR [CMS_MENU] + -- Fresh cursor associated with current structure. + do + Result := items.new_cursor + end + +feature {NONE} -- Implementation + + items: HASH_TABLE [CMS_MENU, like {CMS_MENU}.name] +-- items: ARRAYED_LIST [CMS_MENU] + +end diff --git a/cms/src/modules/basic_auth/basic_auth_module.e b/cms/src/modules/basic_auth/basic_auth_module.e index 2c589d1..555d2cb 100644 --- a/cms/src/modules/basic_auth/basic_auth_module.e +++ b/cms/src/modules/basic_auth/basic_auth_module.e @@ -18,57 +18,53 @@ create feature {NONE} -- Initialization - make (a_config: CMS_SETUP) + make do name := "basic auth" version := "1.0" description := "Service to manage basic authentication" package := "core" - config := a_config end - config: CMS_SETUP - -- Node configuration. - feature -- Access: router - router: WSF_ROUTER + router (a_api: CMS_API): WSF_ROUTER -- Node router. do create Result.make (2) - configure_api_login (Result) - configure_api_logoff (Result) + configure_api_login (a_api, Result) + configure_api_logoff (a_api, Result) end feature -- Access: filter - filters: detachable LIST [WSF_FILTER] + filters (a_api: CMS_API): detachable LIST [WSF_FILTER] -- Possibly list of Filter's module. do create {ARRAYED_LIST [WSF_FILTER]} Result.make (2) Result.extend (create {CORS_FILTER}) - Result.extend (create {BASIC_AUTH_FILTER}.make (config)) + Result.extend (create {BASIC_AUTH_FILTER}.make (a_api)) end feature {NONE} -- Implementation: routes - configure_api_login (a_router: WSF_ROUTER) + configure_api_login (api: CMS_API; a_router: WSF_ROUTER) local l_bal_handler: BASIC_AUTH_LOGIN_HANDLER l_methods: WSF_REQUEST_METHODS do - create l_bal_handler.make (config) + create l_bal_handler.make (api) create l_methods l_methods.enable_get a_router.handle_with_request_methods ("/basic_auth_login", l_bal_handler, l_methods) end - configure_api_logoff (a_router: WSF_ROUTER) + configure_api_logoff (api: CMS_API; a_router: WSF_ROUTER) local l_bal_handler: BASIC_AUTH_LOGOFF_HANDLER l_methods: WSF_REQUEST_METHODS do - create l_bal_handler.make (config) + create l_bal_handler.make (api) create l_methods l_methods.enable_get a_router.handle_with_request_methods ("/basic_auth_logoff", l_bal_handler, l_methods) diff --git a/cms/src/modules/basic_auth/filter/basic_auth_filter.e b/cms/src/modules/basic_auth/filter/basic_auth_filter.e index d5abd0a..31ddb21 100644 --- a/cms/src/modules/basic_auth/filter/basic_auth_filter.e +++ b/cms/src/modules/basic_auth/filter/basic_auth_filter.e @@ -31,8 +31,8 @@ feature -- Basic operations -- A valid user if (attached l_auth.type as l_auth_type and then l_auth_type.is_case_insensitive_equal_general ("basic")) and then attached l_auth.login as l_auth_login and then attached l_auth.password as l_auth_password then - if api_service.is_valid_credential (l_auth_login, l_auth_password) then - if attached api_service.user_by_name (l_auth_login) as l_user then + if api.is_valid_credential (l_auth_login, l_auth_password) then + if attached api.user_by_name (l_auth_login) as l_user then req.set_execution_variable ("user", l_user) execute_next (req, res) else diff --git a/cms/src/modules/basic_auth/handler/basic_auth_login_handler.e b/cms/src/modules/basic_auth/handler/basic_auth_login_handler.e index a0e6df8..4035e0f 100644 --- a/cms/src/modules/basic_auth/handler/basic_auth_login_handler.e +++ b/cms/src/modules/basic_auth/handler/basic_auth_login_handler.e @@ -47,8 +47,6 @@ feature -- HTTP Methods do_get (req: WSF_REQUEST; res: WSF_RESPONSE) -- - local - l_page: CMS_RESPONSE do log.write_information(generator + ".do_get Processing basic auth login") if attached {STRING_32} current_user_name (req) as l_user then diff --git a/cms/src/modules/basic_auth/handler/basic_auth_logoff_handler.e b/cms/src/modules/basic_auth/handler/basic_auth_logoff_handler.e index b274ab4..300eafe 100644 --- a/cms/src/modules/basic_auth/handler/basic_auth_logoff_handler.e +++ b/cms/src/modules/basic_auth/handler/basic_auth_logoff_handler.e @@ -50,7 +50,7 @@ feature -- HTTP Methods if attached req.query_parameter ("prompt") as l_prompt then (create {CMS_GENERIC_RESPONSE}).new_response_unauthorized (req, res) else - create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, setup, "master2/basic_auth/logoff") + create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api) l_page.set_status_code ({HTTP_STATUS_CODE}.unauthorized) l_page.execute end diff --git a/cms/src/modules/cms_module.e b/cms/src/modules/cms_module.e index a58805e..ce0a9a2 100644 --- a/cms/src/modules/cms_module.e +++ b/cms/src/modules/cms_module.e @@ -20,16 +20,25 @@ feature -- Access feature -- Router - router: WSF_ROUTER + router (a_api: CMS_API): WSF_ROUTER -- Router configuration. require is_enabled: is_enabled deferred end +feature -- Hooks configuration + + register_hooks (a_response: CMS_RESPONSE) + -- Module hooks configuration. + require + is_enabled: is_enabled + do + end + feature -- Filter - filters: detachable LIST [WSF_FILTER] + filters (a_api: CMS_API): detachable LIST [WSF_FILTER] -- Optional list of filter for Current module. require is_enabled: is_enabled diff --git a/cms/src/modules/node/handler/node_content_handler.e b/cms/src/modules/node/handler/node_content_handler.e index a7113b7..11ebd9d 100644 --- a/cms/src/modules/node/handler/node_content_handler.e +++ b/cms/src/modules/node/handler/node_content_handler.e @@ -69,8 +69,8 @@ feature -- HTTP Methods if attached current_user_name (req) then -- Existing node if attached {WSF_STRING} req.path_parameter ("id") as l_id then - if l_id.is_integer and then attached {CMS_NODE} api_service.node (l_id.integer_value) as l_node then - create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, setup, "modules/node_content") + if l_id.is_integer and then attached {CMS_NODE} api.node (l_id.integer_value) as l_node then + create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api) l_page.add_variable (l_node.content, "node_content") l_page.add_variable (l_id.value, "id") l_page.execute @@ -78,7 +78,7 @@ feature -- HTTP Methods do_error (req, res, l_id) end else - (create {ERROR_500_CMS_RESPONSE}.make (req, res, setup, "master2/error")).execute + (create {ERROR_500_CMS_RESPONSE}.make (req, res, api)).execute end else (create {CMS_GENERIC_RESPONSE}).new_response_unauthorized (req, res) @@ -88,24 +88,22 @@ feature -- HTTP Methods do_post (req: WSF_REQUEST; res: WSF_RESPONSE) -- - local - l_page: CMS_RESPONSE do if attached current_user_name (req) then if attached {WSF_STRING} req.path_parameter ("id") as l_id then - if l_id.is_integer and then attached {CMS_NODE} api_service.node (l_id.integer_value) as l_node then + if l_id.is_integer and then attached {CMS_NODE} api.node (l_id.integer_value) as l_node then if attached {WSF_STRING} req.form_parameter ("method") as l_method then if l_method.is_case_insensitive_equal ("PUT") then do_put (req, res) else - (create {ERROR_500_CMS_RESPONSE}.make (req, res, setup, "master2/error")).execute + (create {ERROR_500_CMS_RESPONSE}.make (req, res, api)).execute end end else do_error (req, res, l_id) end else - (create {ERROR_500_CMS_RESPONSE}.make (req, res, setup, "master2/error")).execute + (create {ERROR_500_CMS_RESPONSE}.make (req, res, api)).execute end else (create {CMS_GENERIC_RESPONSE}).new_response_unauthorized (req, res) @@ -116,21 +114,20 @@ feature -- HTTP Methods -- local u_node: CMS_NODE - l_page: CMS_RESPONSE do to_implement ("Check if user has permissions") 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 {CMS_NODE} api_service.node (l_id.integer_value) as l_node then + if l_id.is_integer and then attached {CMS_NODE} api.node (l_id.integer_value) as l_node then u_node := extract_data_form (req) u_node.set_id (l_id.integer_value) - api_service.update_node_content (l_user.id, u_node.id, u_node.content) + api.update_node_content (l_user.id, u_node.id, u_node.content) (create {CMS_GENERIC_RESPONSE}).new_response_redirect (req, res, req.absolute_script_url ("")) else do_error (req, res, l_id) end else - (create {ERROR_500_CMS_RESPONSE}.make (req, res, setup, "master2/error")).execute + (create {ERROR_500_CMS_RESPONSE}.make (req, res, api)).execute end else (create {CMS_GENERIC_RESPONSE}).new_response_unauthorized (req, res) @@ -143,7 +140,7 @@ feature -- Error local l_page: CMS_RESPONSE do - create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, setup, "master2/error") + create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api) l_page.add_variable (req.absolute_script_url (req.path_info), "request") if a_id.is_integer then -- resource not found diff --git a/cms/src/modules/node/handler/node_handler.e b/cms/src/modules/node/handler/node_handler.e index e9d789f..2dcb47f 100644 --- a/cms/src/modules/node/handler/node_handler.e +++ b/cms/src/modules/node/handler/node_handler.e @@ -68,8 +68,8 @@ feature -- HTTP Methods do -- Existing node if attached {WSF_STRING} req.path_parameter ("id") as l_id then - if l_id.is_integer and then attached {CMS_NODE} api_service.node (l_id.integer_value) as l_node then - create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, setup,"modules/node") + if l_id.is_integer and then attached {CMS_NODE} api.node (l_id.integer_value) as l_node then + create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api) l_page.add_variable (l_node, "node") l_page.execute else @@ -85,19 +85,18 @@ feature -- HTTP Methods -- local u_node: CMS_NODE - l_page: CMS_RESPONSE do to_implement ("Check user permissions!!!") 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 {CMS_NODE} api_service.node (l_id.integer_value) as l_node then + if l_id.is_integer and then attached {CMS_NODE} api.node (l_id.integer_value) as l_node then if attached {WSF_STRING} req.form_parameter ("method") as l_method then if l_method.is_case_insensitive_equal ("DELETE") then do_delete (req, res) elseif l_method.is_case_insensitive_equal ("PUT") then do_put (req, res) else - (create {ERROR_500_CMS_RESPONSE}.make (req, res, setup, "master2/error")).execute + (create {ERROR_500_CMS_RESPONSE}.make (req, res, api)).execute end end else @@ -107,7 +106,7 @@ feature -- HTTP Methods -- New node u_node := extract_data_form (req) u_node.set_author (l_user) - api_service.new_node (u_node) + api.new_node (u_node) (create {CMS_GENERIC_RESPONSE}).new_response_redirect (req, res, req.absolute_script_url ("")) end else @@ -123,16 +122,16 @@ feature -- HTTP Methods 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 {CMS_NODE} api_service.node (l_id.integer_value) as l_node then + if l_id.is_integer and then attached {CMS_NODE} api.node (l_id.integer_value) as l_node then u_node := extract_data_form (req) u_node.set_id (l_id.integer_value) - api_service.update_node (l_user.id,u_node) + api.update_node (l_user.id,u_node) (create {CMS_GENERIC_RESPONSE}).new_response_redirect (req, res, req.absolute_script_url ("")) else do_error (req, res, l_id) end else - (create {ERROR_500_CMS_RESPONSE}.make (req, res, setup, "master2/error")).execute + (create {ERROR_500_CMS_RESPONSE}.make (req, res, api)).execute end else (create {CMS_GENERIC_RESPONSE}).new_response_unauthorized (req, res) @@ -145,14 +144,14 @@ feature -- HTTP Methods do if attached current_user_name (req) then if attached {WSF_STRING} req.path_parameter ("id") as l_id then - if l_id.is_integer and then attached {CMS_NODE} api_service.node (l_id.integer_value) as l_node then - api_service.delete_node (l_id.integer_value) + if l_id.is_integer and then attached {CMS_NODE} api.node (l_id.integer_value) as l_node then + api.delete_node (l_id.integer_value) (create {CMS_GENERIC_RESPONSE}).new_response_redirect (req, res, req.absolute_script_url ("")) else do_error (req, res, l_id) end else - (create {ERROR_500_CMS_RESPONSE}.make (req, res, setup, "master2/error")).execute + (create {ERROR_500_CMS_RESPONSE}.make (req, res, api)).execute end else (create {CMS_GENERIC_RESPONSE}).new_response_unauthorized (req, res) @@ -166,7 +165,7 @@ feature -- Error local l_page: CMS_RESPONSE do - create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, setup, "master2/error") + create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api) l_page.add_variable (req.absolute_script_url (req.path_info), "request") if a_id.is_integer then -- resource not found @@ -187,7 +186,7 @@ feature {NONE} -- Node l_page: CMS_RESPONSE do if attached current_user_name (req) then - create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, setup, "modules/node") + create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api) l_page.add_variable (setup.is_html, "html") l_page.add_variable (setup.is_web, "web") l_page.execute diff --git a/cms/src/modules/node/handler/node_summary_handler.e b/cms/src/modules/node/handler/node_summary_handler.e index d3ec258..01553b2 100644 --- a/cms/src/modules/node/handler/node_summary_handler.e +++ b/cms/src/modules/node/handler/node_summary_handler.e @@ -68,8 +68,8 @@ feature -- HTTP Methods if attached current_user_name (req) then -- Existing node if attached {WSF_STRING} req.path_parameter ("id") as l_id then - if l_id.is_integer and then attached {CMS_NODE} api_service.node (l_id.integer_value) as l_node then - create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, setup, "modules/node_summary") + if l_id.is_integer and then attached {CMS_NODE} api.node (l_id.integer_value) as l_node then + create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api) l_page.add_variable (l_id.value, "id") l_page.add_variable (l_node.summary, "node_summary") l_page.execute @@ -77,7 +77,7 @@ feature -- HTTP Methods do_error (req, res, l_id) end else - (create {ERROR_500_CMS_RESPONSE}.make (req, res, setup, "master2/error")).execute + (create {ERROR_500_CMS_RESPONSE}.make (req, res, api)).execute end else (create {CMS_GENERIC_RESPONSE}).new_response_unauthorized (req, res) @@ -87,24 +87,22 @@ feature -- HTTP Methods do_post (req: WSF_REQUEST; res: WSF_RESPONSE) -- - local - u_node: CMS_NODE do if attached current_user_name (req) then if attached {WSF_STRING} req.path_parameter ("id") as l_id then - if l_id.is_integer and then attached {CMS_NODE} api_service.node (l_id.integer_value) as l_node then + if l_id.is_integer and then attached {CMS_NODE} api.node (l_id.integer_value) as l_node then if attached {WSF_STRING} req.form_parameter ("method") as l_method then if l_method.is_case_insensitive_equal ("PUT") then do_put (req, res) else - (create {ERROR_500_CMS_RESPONSE}.make (req, res, setup, "master2/error")).execute + (create {ERROR_500_CMS_RESPONSE}.make (req, res, api)).execute end end else do_error (req, res, l_id) end else - (create {ERROR_500_CMS_RESPONSE}.make (req, res, setup, "master2/error")).execute + (create {ERROR_500_CMS_RESPONSE}.make (req, res, api)).execute end else (create {CMS_GENERIC_RESPONSE}).new_response_unauthorized (req, res) @@ -118,16 +116,16 @@ feature -- HTTP Methods 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 {CMS_NODE} api_service.node (l_id.integer_value) as l_node then + if l_id.is_integer and then attached {CMS_NODE} api.node (l_id.integer_value) as l_node then u_node := extract_data_form (req) u_node.set_id (l_id.integer_value) - api_service.update_node_summary (l_user.id,u_node.id, u_node.summary) + api.update_node_summary (l_user.id,u_node.id, u_node.summary) (create {CMS_GENERIC_RESPONSE}).new_response_redirect (req, res, req.absolute_script_url ("")) else do_error (req, res, l_id) end else - (create {ERROR_500_CMS_RESPONSE}.make (req, res, setup, "master2/error")).execute + (create {ERROR_500_CMS_RESPONSE}.make (req, res, api)).execute end else (create {CMS_GENERIC_RESPONSE}).new_response_unauthorized (req, res) @@ -142,7 +140,7 @@ feature -- Error local l_page: CMS_RESPONSE do - create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, setup, "master2/error") + create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api) l_page.add_variable (req.absolute_script_url (req.path_info), "request") if a_id.is_integer then -- resource not found diff --git a/cms/src/modules/node/handler/node_title_handler.e b/cms/src/modules/node/handler/node_title_handler.e index 570b155..0cfe30d 100644 --- a/cms/src/modules/node/handler/node_title_handler.e +++ b/cms/src/modules/node/handler/node_title_handler.e @@ -68,8 +68,8 @@ feature -- HTTP Methods if attached current_user_name (req) as l_user then -- Existing node if attached {WSF_STRING} req.path_parameter ("id") as l_id then - if l_id.is_integer and then attached {CMS_NODE} api_service.node (l_id.integer_value) as l_node then - create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, setup, "modules/node_title") + if l_id.is_integer and then attached {CMS_NODE} api.node (l_id.integer_value) as l_node then + create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api) l_page.add_variable (l_node.title, "node_title") l_page.add_variable (l_id.value, "id") l_page.execute @@ -77,7 +77,7 @@ feature -- HTTP Methods do_error (req, res, l_id) end else - (create {ERROR_500_CMS_RESPONSE}.make (req, res, setup, "master2/error")).execute + (create {ERROR_500_CMS_RESPONSE}.make (req, res, api)).execute end else (create {CMS_GENERIC_RESPONSE}).new_response_unauthorized (req, res) @@ -86,24 +86,22 @@ feature -- HTTP Methods do_post (req: WSF_REQUEST; res: WSF_RESPONSE) -- - local - u_node: CMS_NODE do if attached current_user_name (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 {CMS_NODE} api_service.node (l_id.integer_value) as l_node then + if l_id.is_integer and then attached {CMS_NODE} api.node (l_id.integer_value) as l_node then if attached {WSF_STRING} req.form_parameter ("method") as l_method then if l_method.is_case_insensitive_equal ("PUT") then do_put (req, res) else - (create {ERROR_500_CMS_RESPONSE}.make (req, res, setup, "master2/error")).execute + (create {ERROR_500_CMS_RESPONSE}.make (req, res, api)).execute end end else do_error (req, res, l_id) end else - (create {ERROR_500_CMS_RESPONSE}.make (req, res, setup, "master2/error")).execute + (create {ERROR_500_CMS_RESPONSE}.make (req, res, api)).execute end else (create {CMS_GENERIC_RESPONSE}).new_response_unauthorized (req, res) @@ -118,16 +116,16 @@ feature -- HTTP Methods to_implement ("Check if user has permissions") 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 {CMS_NODE} api_service.node (l_id.integer_value) as l_node then + if l_id.is_integer and then attached {CMS_NODE} api.node (l_id.integer_value) as l_node then u_node := extract_data_form (req) u_node.set_id (l_id.integer_value) - api_service.update_node_title (l_user.id,u_node.id, u_node.title) + api.update_node_title (l_user.id,u_node.id, u_node.title) (create {CMS_GENERIC_RESPONSE}).new_response_redirect (req, res, req.absolute_script_url ("")) else do_error (req, res, l_id) end else - (create {ERROR_500_CMS_RESPONSE}.make (req, res, setup, "master2/error")).execute + (create {ERROR_500_CMS_RESPONSE}.make (req, res, api)).execute end else (create {CMS_GENERIC_RESPONSE}).new_response_unauthorized (req, res) @@ -141,7 +139,7 @@ feature -- Error local l_page: CMS_RESPONSE do - create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, setup, "master2/error") + create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api) l_page.add_variable (req.absolute_script_url (req.path_info), "request") if a_id.is_integer then -- resource not found diff --git a/cms/src/modules/node/handler/nodes_handler.e b/cms/src/modules/node/handler/nodes_handler.e index f1097db..651e8e7 100644 --- a/cms/src/modules/node/handler/nodes_handler.e +++ b/cms/src/modules/node/handler/nodes_handler.e @@ -52,8 +52,8 @@ feature -- HTTP Methods -- 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, setup, "modules/nodes") - l_page.add_variable (api_service.nodes, "nodes") + create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api) + l_page.add_variable (api.nodes, "nodes") l_page.execute end end diff --git a/cms/src/modules/node/node_module.e b/cms/src/modules/node/node_module.e index 1ecaea3..f5c7349 100644 --- a/cms/src/modules/node/node_module.e +++ b/cms/src/modules/node/node_module.e @@ -9,78 +9,88 @@ class inherit CMS_MODULE + redefine + register_hooks + end + + CMS_HOOK_MENU_ALTER + + CMS_HOOK_BLOCK + create make feature {NONE} -- Initialization - make (a_config: CMS_SETUP) + make (a_setup: CMS_SETUP) -- Create Current module, disabled by default. do name := "node" version := "1.0" description := "Service to manage content based on 'node'" package := "core" - config := a_config + config := a_setup end + config: CMS_SETUP -- Node configuration. feature -- Access: router - router: WSF_ROUTER + router (a_api: CMS_API): WSF_ROUTER -- Node router. do create Result.make (5) - configure_api_node (Result) - configure_api_nodes (Result) - configure_api_node_title (Result) - configure_api_node_summary (Result) - configure_api_node_content (Result) + configure_api_node (a_api, Result) + configure_api_nodes (a_api, Result) + configure_api_node_title (a_api, Result) + configure_api_node_summary (a_api, Result) + configure_api_node_content (a_api, Result) end feature {NONE} -- Implementation: routes - configure_api_node (a_router: WSF_ROUTER) + configure_api_node (api: CMS_API; a_router: WSF_ROUTER) local l_node_handler: NODE_HANDLER l_methods: WSF_REQUEST_METHODS do - create l_node_handler.make (config) + create l_node_handler.make (api) create l_methods l_methods.enable_get l_methods.enable_post l_methods.enable_put a_router.handle_with_request_methods ("/node", l_node_handler, l_methods) - create l_node_handler.make (config) + create l_node_handler.make (api) create l_methods l_methods.enable_get l_methods.enable_post l_methods.enable_put l_methods.enable_delete a_router.handle_with_request_methods ("/node/{id}", l_node_handler, l_methods) + a_router.handle_with_request_methods ("/nodes/", create {WSF_URI_AGENT_HANDLER}.make (agent do_get_nodes (?,?, api)), a_router.methods_get) end - configure_api_nodes (a_router: WSF_ROUTER) + configure_api_nodes (api: CMS_API; a_router: WSF_ROUTER) local l_nodes_handler: NODES_HANDLER l_methods: WSF_REQUEST_METHODS do - create l_nodes_handler.make (config) + create l_nodes_handler.make (api) create l_methods l_methods.enable_get a_router.handle_with_request_methods ("/nodes", l_nodes_handler, l_methods) end - configure_api_node_summary (a_router: WSF_ROUTER) + configure_api_node_summary (api: CMS_API; a_router: WSF_ROUTER) local l_report_handler: NODE_SUMMARY_HANDLER l_methods: WSF_REQUEST_METHODS do - create l_report_handler.make (config) + create l_report_handler.make (api) create l_methods l_methods.enable_get l_methods.enable_post @@ -88,13 +98,12 @@ feature {NONE} -- Implementation: routes a_router.handle_with_request_methods ("/node/{id}/summary", l_report_handler, l_methods) end - - configure_api_node_title (a_router: WSF_ROUTER) + configure_api_node_title (api: CMS_API; a_router: WSF_ROUTER) local l_report_handler: NODE_TITLE_HANDLER l_methods: WSF_REQUEST_METHODS do - create l_report_handler.make (config) + create l_report_handler.make (api) create l_methods l_methods.enable_get l_methods.enable_post @@ -102,12 +111,12 @@ feature {NONE} -- Implementation: routes a_router.handle_with_request_methods ("/node/{id}/title", l_report_handler, l_methods) end - configure_api_node_content (a_router: WSF_ROUTER) + configure_api_node_content (api: CMS_API; a_router: WSF_ROUTER) local l_report_handler: NODE_CONTENT_HANDLER l_methods: WSF_REQUEST_METHODS do - create l_report_handler.make (config) + create l_report_handler.make (api) create l_methods l_methods.enable_get l_methods.enable_post @@ -115,4 +124,46 @@ feature {NONE} -- Implementation: routes a_router.handle_with_request_methods ("/node/{id}/content", l_report_handler, l_methods) end +feature -- Hooks + + register_hooks (a_response: CMS_RESPONSE) + do + a_response.add_menu_alter_hook (Current) + a_response.add_block_hook (Current) + end + + block_list: ITERABLE [like {CMS_BLOCK}.name] + do + Result := <<"node-info">> + end + + get_block_view (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE) + local +-- b: CMS_CONTENT_BLOCK + do +-- create b.make (a_block_id, "Block::node", "This is a block test", Void) +-- a_response.add_block (b, "sidebar_second") + end + + menu_alter (a_menu_system: CMS_MENU_SYSTEM; a_response: CMS_RESPONSE) + local + lnk: CMS_LOCAL_LINK +-- perms: detachable ARRAYED_LIST [READABLE_STRING_8] + do + create lnk.make ("List of nodes", a_response.url ("/nodes", Void)) + a_menu_system.primary_menu.extend (lnk) + end + +feature -- Handler + + do_get_nodes (req: WSF_REQUEST; res: WSF_RESPONSE; a_api: CMS_API) + local + r: CMS_RESPONSE + do + create {NOT_IMPLEMENTED_ERROR_CMS_RESPONSE} r.make (req, res, a_api) + r.set_main_content ("Sorry: listing the CMS nodes is not yet implemented.") + r.add_block (create {CMS_CONTENT_BLOCK}.make ("nodes_warning", Void, "/nodes/ is not yet implemented", Void), "highlighted") + r.execute + end + end diff --git a/cms/src/service/cms_api_service.e b/cms/src/service/cms_api.e similarity index 55% rename from cms/src/service/cms_api_service.e rename to cms/src/service/cms_api.e index c7b69ff..877bbf7 100644 --- a/cms/src/service/cms_api_service.e +++ b/cms/src/service/cms_api.e @@ -1,36 +1,87 @@ note - description: "Summary description for {CMS_API_SERVICE}." + description: "Summary description for {CMS_API}." date: "$Date$" revision: "$Revision$" class - CMS_API_SERVICE + CMS_API inherit SHARED_ERROR - REFACTORING_HELPER + REFACTORING_HELPER create make feature -- Initialize - make (a_storage: CMS_STORAGE) + make (a_setup: CMS_SETUP) -- Create the API service with an storege `a_storage'. do - storage := a_storage + setup := a_setup + create error_handler.make + initialize set_successful ensure - storage_set: storage = a_storage +-- storage_set: storage = a_storage + end + + setup: CMS_SETUP + -- CMS setup. + + initialize + local + l_database: DATABASE_CONNECTION + retried: BOOLEAN + l_message: STRING + do + if not retried then + to_implement ("Refactor database setup") + if attached (create {JSON_CONFIGURATION}).new_database_configuration (setup.layout.application_config_path) as l_database_config then + create {DATABASE_CONNECTION_MYSQL} l_database.login_with_connection_string (l_database_config.connection_string) + create {CMS_STORAGE_MYSQL} storage.make (l_database) + else + create {DATABASE_CONNECTION_NULL} l_database.make_common + create {CMS_STORAGE_NULL} storage + end + else + to_implement ("Workaround code, persistence layer does not implement yet this kind of error handling.") + -- error hanling. + create {DATABASE_CONNECTION_NULL} l_database.make_common + create {CMS_STORAGE_NULL} storage + create l_message.make (1024) + if attached ((create {EXCEPTION_MANAGER}).last_exception) as l_exception then + if attached l_exception.description as l_description then + l_message.append (l_description.as_string_32) + l_message.append ("%N%N") + elseif attached l_exception.trace as l_trace then + l_message.append (l_trace) + l_message.append ("%N%N") + else + l_message.append (l_exception.out) + l_message.append ("%N%N") + end + else + l_message.append ("The application crash without available information") + l_message.append ("%N%N") + end + error_handler.add_custom_error (0, " Database Connection ", l_message) + end + rescue + retried := True + retry end feature -- Access + error_handler: ERROR_HANDLER + -- Error handler. + +feature -- Status Report + is_valid_credential (l_auth_login, l_auth_password: READABLE_STRING_32): BOOLEAN - local - l_security: SECURITY_PROVIDER do Result := storage.is_valid_credential (l_auth_login, l_auth_password) end diff --git a/cms/src/service/cms_api_options.e b/cms/src/service/cms_api_options.e new file mode 100644 index 0000000..1a5dc6e --- /dev/null +++ b/cms/src/service/cms_api_options.e @@ -0,0 +1,17 @@ +note + description: "Summary description for {CMS_API_OPTIONS}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + CMS_API_OPTIONS + +inherit + WSF_API_OPTIONS + +create + make, + make_from_manifest + +end diff --git a/cms/src/service/cms_request_util.e b/cms/src/service/cms_request_util.e index e9e26c8..e6a1be6 100644 --- a/cms/src/service/cms_request_util.e +++ b/cms/src/service/cms_request_util.e @@ -9,6 +9,8 @@ deferred class inherit + CMS_ENCODERS + REFACTORING_HELPER feature -- User @@ -21,8 +23,6 @@ feature -- User if attached {CMS_USER} current_user (req) as l_user then Result := l_user.name end - - end current_user (req: WSF_REQUEST): detachable CMS_USER diff --git a/cms/src/service/cms_service.e b/cms/src/service/cms_service.e index 37a4759..973bc6e 100644 --- a/cms/src/service/cms_service.e +++ b/cms/src/service/cms_service.e @@ -41,11 +41,11 @@ create feature {NONE} -- Initialization - make (a_setup: CMS_SETUP) + make (a_api: CMS_API) -- Build a CMS service with `a_setup' configuration. do - setup := a_setup - configuration := a_setup.configuration + api := a_api + configuration := a_api.setup.configuration initialize end @@ -103,36 +103,41 @@ feature -- Settings: router -- local l_module: CMS_MODULE + l_api: like api + l_router: like router do log.write_debug (generator + ".setup_router") -- Configure root of api handler. - configure_api_root + + l_router := router + configure_api_root (l_router) -- Include routes from modules. + l_api := api across modules as ic loop l_module := ic.item - router.import (l_module.router) + l_router.import (l_module.router (l_api)) end -- Configure files handler. - configure_api_file_handler + configure_api_file_handler (l_router) end - configure_api_root + configure_api_root (a_router: WSF_ROUTER) local l_root_handler: CMS_ROOT_HANDLER l_methods: WSF_REQUEST_METHODS do log.write_debug (generator + ".configure_api_root") - create l_root_handler.make (setup) + create l_root_handler.make (api) create l_methods l_methods.enable_get - router.handle_with_request_methods ("/", l_root_handler, l_methods) - router.handle_with_request_methods ("", l_root_handler, l_methods) + a_router.handle_with_request_methods ("/", l_root_handler, l_methods) + a_router.handle_with_request_methods ("", l_root_handler, l_methods) end - configure_api_file_handler + configure_api_file_handler (a_router: WSF_ROUTER) local fhdl: WSF_FILE_SYSTEM_HANDLER do @@ -143,7 +148,7 @@ feature -- Settings: router do execute_default (ia_req, ia_res) end) - router.handle_with_request_methods ("/", fhdl, router.methods_GET) + a_router.handle_with_request_methods ("/", fhdl, router.methods_GET) end feature -- Execute Filter @@ -162,22 +167,30 @@ feature -- Filters local f, l_filter: detachable WSF_FILTER l_module: CMS_MODULE + l_api: like api do log.write_debug (generator + ".create_filter") 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 as l_m_filters + attached l_module.filters (l_api) as l_m_filters then across l_m_filters as f_ic loop f := f_ic.item @@ -207,11 +220,16 @@ feature -- Filters f.set_next (Current) end - feature -- Access + api: CMS_API + -- API service. + setup: CMS_SETUP -- CMS setup. + do + Result := api.setup + end configuration: CMS_CONFIGURATION -- CMS configuration. diff --git a/cms/src/service/cms_url_utilities.e b/cms/src/service/cms_url_utilities.e new file mode 100644 index 0000000..8fff472 --- /dev/null +++ b/cms/src/service/cms_url_utilities.e @@ -0,0 +1,129 @@ +note + description: "Summary description for {CMS_URL_UTILITIES}." + author: "" + date: "$Date$" + revision: "$Revision$" + +deferred class + CMS_URL_UTILITIES + +inherit + CMS_REQUEST_UTIL + +feature -- Core + + site_url: READABLE_STRING_8 + deferred + end + + base_url: detachable READABLE_STRING_8 + -- Base url if any. + deferred + end + + based_path (p: STRING): STRING + -- Path `p' in the context of the `base_url' + do + if attached base_url as l_base_url then + create Result.make_from_string (l_base_url) + if p.is_empty then + else + if p[1] = '/' then + Result.append (p.substring (2, p.count)) + else + Result.append (p) + end + end + else + Result := p + end + end + +feature -- Url + + absolute_url (a_path: STRING; opts: detachable CMS_API_OPTIONS): STRING + local + l_opts: detachable CMS_API_OPTIONS + do + l_opts := opts + if l_opts = Void then + create l_opts.make (1) + end + l_opts.force (True, "absolute") + Result := url (a_path, l_opts) + end + + url (a_path: READABLE_STRING_8; opts: detachable CMS_API_OPTIONS): STRING + -- URL for path `a_path' and optional parameters from `opts'. + --| Options `opts' could be + --| - absolute: True|False => return absolute url + --| - query: string => append "?query" + --| - fragment: string => append "#fragment" + local + q,f: detachable STRING_8 + l_abs: BOOLEAN + do + l_abs := False + + if opts /= Void then + l_abs := opts.boolean_item ("absolute", l_abs) + if attached opts.item ("query") as l_query then + if attached {READABLE_STRING_8} l_query as s_value then + q := s_value + elseif attached {ITERABLE [TUPLE [key, value: READABLE_STRING_GENERAL]]} l_query as lst then + create q.make_empty + across + lst as c + loop + if q.is_empty then + else + q.append_character ('&') + end + q.append (url_encoded (c.item.key)) + q.append_character ('=') + q.append (url_encoded (c.item.value)) + end + end + end + if attached opts.string_item ("fragment") as s_frag then + f := s_frag + end + end + if l_abs then + if a_path.substring_index ("://", 1) = 0 then + create Result.make_from_string (site_url) + if a_path.is_empty then + elseif Result.ends_with ("/") then + if a_path[1] = '/' then + Result.append_string (a_path.substring (2, a_path.count)) + else + Result.append_string (a_path) + end + else + if a_path[1] = '/' then + Result.append_string (a_path) + else + Result.append_character ('/') + Result.append_string (a_path) + end + end + else + Result := a_path + end + else + Result := based_path (a_path) + end + if q /= Void then + Result.append ("?" + q) + end + if f /= Void then + Result.append ("#" + f) + end + end + + checked_url (a_url: READABLE_STRING_8): READABLE_STRING_8 + do + Result := a_url + end + +end diff --git a/cms/src/service/filter/cms_error_filter.e b/cms/src/service/filter/cms_error_filter.e new file mode 100644 index 0000000..2c8c780 --- /dev/null +++ b/cms/src/service/filter/cms_error_filter.e @@ -0,0 +1,33 @@ +note + description: "Summary description for {CMS_ERROR_FILTER}." + date: "$Date$" + revision: "$Revision$" + +class + CMS_ERROR_FILTER + +inherit + + WSF_URI_TEMPLATE_HANDLER + CMS_HANDLER + WSF_FILTER + +create + make + +feature -- Basic operations + + execute (req: WSF_REQUEST; res: WSF_RESPONSE) + -- Execute the filter + do + if not api.error_handler.has_error then + log.write_information (generator + ".execute") + execute_next (req, res) + else + log.write_critical (generator + ".execute" + api.error_handler.as_string_representation ) + (create {ERROR_500_CMS_RESPONSE}.make (req, res, api)).execute + api.error_handler.reset + end + end + +end diff --git a/cms/src/service/handler/cms_handler.e b/cms/src/service/handler/cms_handler.e index c6d2902..9de1552 100644 --- a/cms/src/service/handler/cms_handler.e +++ b/cms/src/service/handler/cms_handler.e @@ -19,20 +19,20 @@ inherit feature {NONE} -- Initialization - make (a_setup: CMS_SETUP) + make (a_api: CMS_API) do - setup := a_setup + api := a_api end feature -- Setup setup: CMS_SETUP + do + Result := api.setup + end feature -- API Service - api_service: CMS_API_SERVICE - do - Result := setup.api_service - end + api: CMS_API end diff --git a/cms/src/service/handler/cms_root_handler.e b/cms/src/service/handler/cms_root_handler.e index fdb2783..cf1284d 100644 --- a/cms/src/service/handler/cms_root_handler.e +++ b/cms/src/service/handler/cms_root_handler.e @@ -48,7 +48,7 @@ feature -- HTTP Methods do_get (req: WSF_REQUEST; res: WSF_RESPONSE) -- do - (create {HOME_CMS_RESPONSE}.make (req, res, setup,"layout2")).execute + (create {HOME_CMS_RESPONSE}.make (req, res, api)).execute end end diff --git a/cms/src/service/response/cms_generic_response.e b/cms/src/service/response/cms_generic_response.e index 380a391..371bc05 100644 --- a/cms/src/service/response/cms_generic_response.e +++ b/cms/src/service/response/cms_generic_response.e @@ -50,7 +50,6 @@ feature -- Responses -- Handle not authorized. local h: HTTP_HEADER - output: STRING do create h.make h.put_content_type_text_html diff --git a/cms/src/service/response/cms_response.e b/cms/src/service/response/cms_response.e index 671c031..14894ab 100644 --- a/cms/src/service/response/cms_response.e +++ b/cms/src/service/response/cms_response.e @@ -1,5 +1,5 @@ note - description: "Generic CMS Response, place to add HOOKS features as collaborators." + description: "Generic CMS Response.It builds the content to get process to render the output" date: "$Date$" revision: "$Revision$" @@ -7,27 +7,45 @@ deferred class CMS_RESPONSE inherit - - CMS_REQUEST_UTIL + CMS_URL_UTILITIES REFACTORING_HELPER feature {NONE} -- Initialization - make (req: WSF_REQUEST; res: WSF_RESPONSE; a_setup: like setup; a_template: like template) + make (req: WSF_REQUEST; res: WSF_RESPONSE; a_api: like api) do status_code := {HTTP_STATUS_CODE}.ok - setup := a_setup + api := a_api request := req response := res - template := a_template create header.make + create values.make (3) initialize end initialize do get_theme + create menu_system.make + initialize_block_region_settings + register_hooks + end + + register_hooks + local + l_module: CMS_MODULE + l_available_modules: CMS_MODULE_COLLECTION + do + l_available_modules := setup.modules + across + l_available_modules as ic + loop + l_module := ic.item + if l_module.is_enabled then + l_module.register_hooks (Current) + end + end end feature -- Access @@ -36,8 +54,14 @@ feature -- Access response: WSF_RESPONSE + api: CMS_API + -- Current CMS API. + setup: CMS_SETUP - -- Current setup + -- Current setup + do + Result := api.setup + end status_code: INTEGER @@ -50,8 +74,107 @@ feature -- Access main_content: detachable STRING_8 - template: READABLE_STRING_32 - -- Current template. + additional_page_head_lines: detachable LIST [READABLE_STRING_8] + -- HTML>head>...extra lines + +feature -- URL utilities + + is_front: BOOLEAN + -- Is current response related to "front" page? + local + l_path_info: READABLE_STRING_8 + do + l_path_info := request.path_info + if attached setup.front_page_path as l_front_page_path then + Result := l_front_page_path.same_string (l_path_info) + else + if attached base_url as l_base_url then + Result := l_path_info.same_string (l_base_url) + else + Result := l_path_info.is_empty or else l_path_info.same_string ("/") + end + end + end + + site_url: READABLE_STRING_8 + do + Result := absolute_host (request, "") + end + + 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 + + site_name: STRING_32 + do + Result := setup.site_name + end + + front_page_url: READABLE_STRING_8 + do + Result := request.absolute_script_url ("/") + end + + values: CMS_VALUE_TABLE + -- Associated values indexed by string name. + + + +feature -- Permission + -- FIXME: to be implemented has_permissions and has_permission. + +feature -- Status + -- FIXME: to be implemented + -- is_from, is_module, has_js. + + +feature -- Head customization + + add_additional_head_line (s: READABLE_STRING_8; a_allow_duplication: BOOLEAN) + local + lst: like additional_page_head_lines + do + lst := additional_page_head_lines + if lst = Void then + create {ARRAYED_LIST [like additional_page_head_lines.item]} lst.make (1) + additional_page_head_lines := lst + end + if a_allow_duplication or else across lst as c all not c.item.same_string (s) end then + lst.extend (s) + end + end + + add_style (a_href: STRING; a_media: detachable STRING) + local + s: STRING_8 + do + s := "") + add_additional_head_line (s, False) + end + + add_javascript_url (a_src: STRING) + local + s: STRING_8 + do + s := "" + add_additional_head_line (s, False) + end + + add_javascript_content (a_script: STRING) + local + s: STRING_8 + do + s := "" + add_additional_head_line (s, True) + end feature -- Element change @@ -71,10 +194,499 @@ feature -- Element change main_content := s end + set_value (v: detachable ANY; k: READABLE_STRING_GENERAL) + -- Set value `v' associated with name `k'. + do + values.force (v, k) + end + + unset_value (k: READABLE_STRING_GENERAL) + -- Unset value associated with name `k'. + do + values.remove (k) + end + + +feature -- Logging + + log (a_category: READABLE_STRING_8; a_message: READABLE_STRING_8; a_level: INTEGER; a_link: detachable CMS_LINK) + local +-- l_log: CMS_LOG + do + debug + to_implement ("Add implemenatation") + end +-- create l_log.make (a_category, a_message, a_level, Void) +-- if a_link /= Void then +-- l_log.set_link (a_link) +-- end +-- l_log.set_info (request.http_user_agent) +-- service.storage.save_log (l_log) + end + +feature -- Formats + + formats: CMS_FORMATS + once + create Result + end + +feature -- Menu + + menu_system: CMS_MENU_SYSTEM + + main_menu: CMS_MENU + obsolete + "Use `primary_menu' [Nov/2014]" + do + Result := primary_menu + end + + primary_menu: CMS_MENU + do + Result := menu_system.primary_menu + end + + management_menu: CMS_MENU + do + Result := menu_system.management_menu + end + + navigation_menu: CMS_MENU + do + Result := menu_system.navigation_menu + end + + user_menu: CMS_MENU + do + Result := menu_system.user_menu + end + + primary_tabs: CMS_MENU + do + Result := menu_system.primary_tabs + end + +feature -- Blocks initialization + + initialize_block_region_settings + local + l_table: like block_region_settings + do + fixme ("CHECK:Can we use the same structure as in theme.info?") + create regions.make_caseless (5) + + fixme ("let the user choose ...") + create l_table.make_caseless (10) + l_table["top"] := "top" + l_table["header"] := "header" + l_table["highlighted"] := "highlighted" + l_table["help"] := "help" + l_table["content"] := "content" + l_table["footer"] := "footer" + l_table["management"] := "first_sidebar" + l_table["navigation"] := "first_sidebar" + l_table["user"] := "first_sidebar" + l_table["bottom"] := "page_bottom" + block_region_settings := l_table + end + +feature -- Blocks regions + + regions: STRING_TABLE [CMS_BLOCK_REGION] + -- Layout regions, that contains blocks. + + block_region_settings: STRING_TABLE [STRING] + + block_region (b: CMS_BLOCK; a_default_region: detachable READABLE_STRING_8): CMS_BLOCK_REGION + -- Region associated with block `b', or else `a_default_region' if provided. + local + l_region_name: detachable READABLE_STRING_8 + do + l_region_name := block_region_settings.item (b.name) + if l_region_name = Void then + if a_default_region /= Void then + l_region_name := a_default_region + else + -- Default .. put it in same named region + -- Maybe a bad idea + + l_region_name := b.name.as_lower + end + end + if attached regions.item (l_region_name) as res then + Result := res + else + create Result.make (l_region_name) + regions.force (Result, l_region_name) + end + end + + +feature -- Blocks + + add_block (b: CMS_BLOCK; a_default_region: detachable READABLE_STRING_8) + -- Add block `b' to associated region or `a_default_region' if provided. + local + l_region: detachable like block_region + do + l_region := block_region (b, a_default_region) + l_region.extend (b) + end + + + get_blocks + do + fixme ("find a way to have this in configuration or database, and allow different order") + add_block (top_header_block, "top") + add_block (header_block, "header") + if attached message_block as m then + add_block (m, "content") + end + -- FIXME: avoid hardcoded html! should be only in theme. + add_block (create {CMS_CONTENT_BLOCK}.make_raw ("top_content_anchor", Void, "%N", formats.full_html), "content") + if attached page_title as l_page_title then + -- FIXME: avoid hardcoded html! should be only in theme. + add_block (create {CMS_CONTENT_BLOCK}.make_raw ("page_title", Void, "

"+ l_page_title +"

%N", formats.full_html), "content") + end + if attached primary_tabs_block as m then + add_block (m, "content") + end + add_block (content_block, "content") + + if attached management_menu_block as l_block then + add_block (l_block, "first_sidebar") + end + if attached navigation_menu_block as l_block then + add_block (l_block, "first_sidebar") + end + if attached user_menu_block as l_block then + add_block (l_block, "first_sidebar") + end + + if attached footer_block as l_block then + add_block (l_block, "footer") + end + + hook_block_view + end + + primary_menu_block: detachable CMS_MENU_BLOCK + do + if attached primary_menu as m and then not m.is_empty then + create Result.make (m) + end + end + + management_menu_block: detachable CMS_MENU_BLOCK + do + if attached management_menu as m and then not m.is_empty then + create Result.make (m) + end + end + + navigation_menu_block: detachable CMS_MENU_BLOCK + do + if attached navigation_menu as m and then not m.is_empty then + create Result.make (m) + end + end + + user_menu_block: detachable CMS_MENU_BLOCK + do + if attached user_menu as m and then not m.is_empty then + create Result.make (m) + end + end + + primary_tabs_block: detachable CMS_MENU_BLOCK + do + if attached primary_tabs as m and then not m.is_empty then + create Result.make (m) + end + end + + top_header_block: CMS_CONTENT_BLOCK + local + s: STRING + do + create s.make_empty + create Result.make ("page_top", Void, s, formats.full_html) + Result.set_is_raw (True) + end + + header_block: CMS_CONTENT_BLOCK + local + s: STRING + l_hb: STRING + do + create s.make_from_string (theme.menu_html (primary_menu, True)) + create l_hb.make_empty + create Result.make ("header", Void, l_hb, formats.full_html) + Result.set_is_raw (True) + end + + horizontal_primary_menu_html: STRING + do + create Result.make_empty + Result.append ("
") + Result.append (theme.menu_html (primary_menu, True)) + Result.append ("
") + end + + message_html: detachable STRING + do + if attached message as m and then not m.is_empty then + Result := "
" + m + "
" + end + end + + message_block: detachable CMS_CONTENT_BLOCK + do + if attached message as m and then not m.is_empty then + create Result.make ("message", Void, "
" + m + "
", formats.full_html) + Result.set_is_raw (True) + end + end + + content_block: CMS_CONTENT_BLOCK + local + s: STRING + do + if attached main_content as l_content then + s := l_content + else + s := "" + debug + s := "No Content" + end + end + create Result.make ("content", Void, s, formats.full_html) + Result.set_is_raw (True) + end + + made_with_html: STRING + do + create Result.make_empty + Result.append ("Made with EWF") + end + + footer_block: CMS_CONTENT_BLOCK + do + create Result.make ("made_with", Void, made_with_html, Void) + end + +feature -- Hook: value alter + + add_value_alter_hook (h: like value_alter_hooks.item) + local + lst: like value_alter_hooks + do + lst := value_alter_hooks + if lst = Void then + create lst.make (1) + value_alter_hooks := lst + end + if not lst.has (h) then + lst.force (h) + end + end + + value_alter_hooks: detachable ARRAYED_LIST [CMS_HOOK_VALUE_ALTER] + + call_value_alter_hooks (m: CMS_VALUE_TABLE) + do + if attached value_alter_hooks as lst then + across + lst as c + loop + c.item.value_alter (m, Current) + end + end + end + +feature -- Hook: menu_alter + + add_menu_alter_hook (h: like menu_alter_hooks.item) + local + lst: like menu_alter_hooks + do + lst := menu_alter_hooks + if lst = Void then + create lst.make (1) + menu_alter_hooks := lst + end + if not lst.has (h) then + lst.force (h) + end + end + + menu_alter_hooks: detachable ARRAYED_LIST [CMS_HOOK_MENU_ALTER] + + call_menu_alter_hooks (m: CMS_MENU_SYSTEM ) + do + if attached menu_alter_hooks as lst then + across + lst as c + loop + c.item.menu_alter (m, Current) + end + end + end + +feature -- Hook: form_alter + + add_form_alter_hook (h: like form_alter_hooks.item) + local + lst: like form_alter_hooks + do + lst := form_alter_hooks + if lst = Void then + create lst.make (1) + form_alter_hooks := lst + end + if not lst.has (h) then + lst.force (h) + end + end + + form_alter_hooks: detachable ARRAYED_LIST [CMS_HOOK_FORM_ALTER] + + call_form_alter_hooks (f: CMS_FORM; a_form_data: detachable WSF_FORM_DATA; ) + do + if attached form_alter_hooks as lst then + across + lst as c + loop + c.item.form_alter (f, a_form_data, Current) + end + end + end + +feature -- Hook: block + + add_block_hook (h: like block_hooks.item) + local + lst: like block_hooks + do + lst := block_hooks + if lst = Void then + create lst.make (1) + block_hooks := lst + end + if not lst.has (h) then + lst.force (h) + end + end + + block_hooks: detachable ARRAYED_LIST [CMS_HOOK_BLOCK] + + hook_block_view + do + if attached block_hooks as lst then + across + lst as c + loop + across + c.item.block_list as blst + loop + c.item.get_block_view (blst.item, Current) + end + end + end + end + + +feature -- Menu: change + + add_to_main_menu (lnk: CMS_LINK) + obsolete + "use add_to_primary_menu [Nov/2014]" + do + add_to_primary_menu (lnk) + end + + add_to_primary_menu (lnk: CMS_LINK) + do + add_to_menu (lnk, primary_menu) + end + + add_to_menu (lnk: CMS_LINK; m: CMS_MENU) + do +-- if attached {CMS_LOCAL_LINK} lnk as l_local then +-- l_local.get_is_active (request) +-- end + m.extend (lnk) + end + +feature -- Message + + add_message (a_msg: READABLE_STRING_8; a_category: detachable READABLE_STRING_8) + local + m: like message + do + m := message + if m = Void then + create m.make (a_msg.count + 9) + message := m + end + if a_category /= Void then + m.append ("
  • ") + else + m.append ("
  • ") + end + m.append (a_msg + "
  • ") + end + + add_notice_message (a_msg: READABLE_STRING_8) + do + add_message (a_msg, "notice") + end + + add_warning_message (a_msg: READABLE_STRING_8) + do + add_message (a_msg, "warning") + end + + add_error_message (a_msg: READABLE_STRING_8) + do + add_message (a_msg, "error") + end + + add_success_message (a_msg: READABLE_STRING_8) + do + add_message (a_msg, "success") + end + + report_form_errors (fd: WSF_FORM_DATA) + require + has_error: not fd.is_valid + do + if attached fd.errors as errs then + across + errs as err + loop + if attached err.item as e then + if attached e.field as l_field then + if attached e.message as e_msg then + add_error_message (e_msg) --"Field [" + l_field.name + "] is invalid. " + e_msg) + else + add_error_message ("Field [" + l_field.name + "] is invalid.") + end + elseif attached e.message as e_msg then + add_error_message (e_msg) + end + end + end + end + end + + message: detachable STRING_8 + feature -- Theme theme: CMS_THEME - -- Current theme + -- Current theme get_theme local @@ -86,7 +698,7 @@ 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, template) + create {SMARTY_CMS_THEME} theme.make (setup, l_info) else create {DEFAULT_CMS_THEME} theme.make (setup, l_info) end @@ -109,25 +721,180 @@ feature -- Generation prepare (page: CMS_HTML_PAGE) do + -- Menu + add_to_primary_menu (create {CMS_LOCAL_LINK}.make ("Home", "/")) + call_menu_alter_hooks (menu_system) + prepare_menu_system (menu_system) + + -- Blocks + get_blocks + across + regions as reg_ic + loop + across + reg_ic.item.blocks as ic + loop + if attached {CMS_MENU_BLOCK} ic.item as l_menu_block then + recursive_get_active (l_menu_block.menu, request) + end + end + end + + -- Values common_prepare (page) custom_prepare (page) - end - common_prepare (page: CMS_HTML_PAGE) - do - fixme ("Fix generacion common") - page.register_variable (request.absolute_script_url (""), "host") - page.register_variable (setup.is_web, "web") - page.register_variable (setup.is_html, "html") - if attached current_user_name (request) as l_user then - page.register_variable (l_user, "user") + -- Cms values + call_value_alter_hooks (values) + + -- Predefined values + page.register_variable (page, "page") -- DO NOT REMOVE + + -- Values Associated with current Execution object. + across + values as ic + loop + page.register_variable (ic.item, ic.key) + end + + -- Block rendering + across + regions as reg_ic + loop + across + reg_ic.item.blocks as ic + loop + page.add_to_region (theme.block_html (ic.item), reg_ic.item.name) + end + end + + -- Additional lines in + if attached additional_page_head_lines as l_head_lines then + across + l_head_lines as hl + loop + page.head_lines.force (hl.item) + end end end + common_prepare (page: CMS_HTML_PAGE) + -- Common preparation for page `page'. + do + fixme ("Fix generation common") + + -- Information + page.set_title (title) + debug ("cms") + if title = Void then + page.set_title ("CMS::" + request.path_info) --| FIXME: probably, should be removed and handled by theme. + end + end + + -- Variables + page.register_variable (request.absolute_script_url (""), "site_url") + page.register_variable (request.absolute_script_url (""), "host") -- Same as `site_url'. + if attached current_user_name (request) as l_user then + page.register_variable (l_user, "user") + end + page.register_variable (title, "site_title") + page.set_is_front (is_front) + + -- Variables/Setup + page.register_variable (setup.is_web, "web") + page.register_variable (setup.is_html, "html") + + -- Variables/Misc + +-- FIXME: logo .. could be a settings of theme, managed by admin front-end/database. +-- if attached logo_location as l_logo then +-- page.register_variable (l_logo, "logo") +-- end + + -- Menu... + page.register_variable (horizontal_primary_menu_html, "primary_nav") + end + custom_prepare (page: CMS_HTML_PAGE) + -- Common preparation for page `page' that can be redefined by descendants. do end + prepare_menu_system (a_menu_system: CMS_MENU_SYSTEM) + do + across + a_menu_system as c + loop + prepare_links (c.item) + end + end + + prepare_links (a_menu: CMS_LINK_COMPOSITE) + local + to_remove: ARRAYED_LIST [CMS_LINK] + do + create to_remove.make (0) + across + a_menu as c + loop + if attached {CMS_LOCAL_LINK} c.item as lm then +-- if attached lm.permission_arguments as perms and then not has_permissions (perms) then +-- to_remove.force (lm) +-- else + -- if lm.permission_arguments is Void , this is permitted + get_local_link_active_status (lm) + if attached {CMS_LINK_COMPOSITE} lm as comp then + prepare_links (comp) + end +-- end + elseif attached {CMS_LINK_COMPOSITE} c.item as comp then + prepare_links (comp) + end + end + across + to_remove as c + loop + a_menu.remove (c.item) + end + end + + recursive_get_active (a_comp: CMS_LINK_COMPOSITE; req: WSF_REQUEST) + -- Update the active status recursively on `a_comp'. + local + ln: CMS_LINK + do + if attached a_comp.items as l_items then + across + l_items as ic + loop + ln := ic.item + if attached {CMS_LOCAL_LINK} ln as l_local then + get_local_link_active_status (l_local) + end + if (ln.is_expanded or ln.is_collapsed) and then attached {CMS_LINK_COMPOSITE} ln as l_comp then + recursive_get_active (l_comp, req) + end + end + end + end + + get_local_link_active_status (a_lnk: CMS_LOCAL_LINK) + -- Get `a_lnk.is_active' value according to `request' data. + local + qs: STRING + l_is_active: BOOLEAN + do + create qs.make_from_string (request.percent_encoded_path_info) + 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 + qs.append_character ('?') + qs.append (l_query_string) + end + l_is_active := qs.same_string (a_lnk.location) + end + a_lnk.set_is_active (l_is_active) + end feature -- Custom Variables diff --git a/cms/src/service/response/error_500_cms_response.e b/cms/src/service/response/error_500_cms_response.e index 24c908e..7bfea99 100644 --- a/cms/src/service/response/error_500_cms_response.e +++ b/cms/src/service/response/error_500_cms_response.e @@ -21,8 +21,8 @@ feature -- Generation custom_prepare (page: CMS_HTML_PAGE) do page.register_variable (request.absolute_script_url (request.path_info), "request") - page.register_variable ("500", "code") - page.set_status_code (500) + page.set_status_code ({HTTP_STATUS_CODE}.internal_server_error) + page.register_variable (page.status_code.out, "code") end feature -- Execution diff --git a/cms/src/service/response/home_cms_response.e b/cms/src/service/response/home_cms_response.e index cf51ad9..78e9347 100644 --- a/cms/src/service/response/home_cms_response.e +++ b/cms/src/service/response/home_cms_response.e @@ -21,7 +21,7 @@ feature -- Generation custom_prepare (page: CMS_HTML_PAGE) do Precursor (page) - page.register_variable (setup.api_service.recent_nodes (0, 5), "nodes") + page.register_variable (api.recent_nodes (0, 5), "nodes") end feature -- Execution @@ -29,7 +29,7 @@ feature -- Execution process -- Computed response message. do - set_title ("Home") + set_title (Void) set_page_title (Void) end end diff --git a/cms/src/service/response/not_implemented_error_cms_response.e b/cms/src/service/response/not_implemented_error_cms_response.e new file mode 100644 index 0000000..2d37558 --- /dev/null +++ b/cms/src/service/response/not_implemented_error_cms_response.e @@ -0,0 +1,37 @@ +note + description: "Summary description for {NOT_IMPLEMENTED_ERROR_CMS_RESPONSE}." + date: "$Date$" + revision: "$Revision$" + +class + NOT_IMPLEMENTED_ERROR_CMS_RESPONSE + +inherit + + CMS_RESPONSE + redefine + custom_prepare + end + +create + make + +feature -- Generation + + custom_prepare (page: CMS_HTML_PAGE) + do + page.register_variable (request.absolute_script_url (request.path_info), "request") + page.register_variable ("501", "code") + page.set_status_code (501) + end + +feature -- Execution + + process + -- Computed response message. + do + set_title ("Not Implemented") + set_page_title (Void) + end +end + diff --git a/cms/src/theme/cms_html_page.e b/cms/src/theme/cms_html_page.e index 5c6a5c0..3b06281 100644 --- a/cms/src/theme/cms_html_page.e +++ b/cms/src/theme/cms_html_page.e @@ -1,7 +1,8 @@ note description: "Summary description for {CMS_HTML_PAGE}." - date: "$Date$" - revision: "$Revision$" + author: "" + date: "$Date: 2014-11-04 09:57:24 -0300 (ma. 04 de nov. de 2014) $" + revision: "$Revision: 96034 $" class CMS_HTML_PAGE @@ -23,6 +24,7 @@ feature {NONE} -- Initialization do create regions.make (5) language := "en" + status_code := {HTTP_STATUS_CODE}.ok create header.make create {ARRAYED_LIST [STRING]} head_lines.make (5) @@ -36,7 +38,9 @@ feature -- Access -- Optional page type. -- such as "front", "about", ... that could be customized by themes. - title: detachable STRING + is_front: BOOLEAN + + title: detachable READABLE_STRING_32 language: STRING @@ -57,6 +61,7 @@ feature -- Access feature -- Status + status_code: INTEGER feature -- Header @@ -65,7 +70,7 @@ feature -- Header feature -- Region - regions: HASH_TABLE [STRING_8, STRING_8] + regions: STRING_TABLE [STRING_8] -- header -- content -- footer @@ -83,23 +88,14 @@ feature -- Region end end - header_region: STRING_8 - do - Result := region ("header") - end - - content_region: STRING_8 - do - Result := region ("content") - end - - footer_region: STRING_8 - do - Result := region ("content") - end - feature -- Element change + set_is_front (b: BOOLEAN) + -- Set `is_front' to `b'. + do + is_front := b + end + register_variable (a_value: detachable ANY; k: READABLE_STRING_GENERAL) do variables.force (a_value, k) @@ -118,41 +114,11 @@ feature -- Element change end end - add_to_header_region (s: STRING) - do - add_to_region (s, "header") - end - - add_to_content_region (s: STRING) - do - add_to_region (s, "content") - end - - add_to_footer_region (s: STRING) - do - add_to_region (s, "footer") - end - set_region (s: STRING; k: STRING) do regions.force (s, k) end - set_header_region (s: STRING) - do - set_region (s, "header") - end - - set_content_region (s: STRING) - do - set_region (s, "content") - end - - set_footer_region (s: STRING) - do - set_region (s, "footer") - end - feature -- Element change set_status_code (c: like status_code) @@ -170,6 +136,50 @@ feature -- Element change title := s end + add_meta_name_content (a_name: STRING; a_content: STRING) + local + s: STRING_8 + do + s := "" + head_lines.extend (s) + end + + add_meta_http_equiv (a_http_equiv: STRING; a_content: STRING) + local + s: STRING_8 + do + s := "" + head_lines.extend (s) + end + + add_style (a_href: STRING; a_media: detachable STRING) + local + s: STRING_8 + do + s := "") + head_lines.extend (s) + end + + add_javascript_url (a_src: STRING) + local + s: STRING_8 + do + s := "" + head_lines.extend (s) + end + + add_javascript_content (a_script: STRING) + local + s: STRING_8 + do + s := "" + head_lines.extend (s) + end + note copyright: "2011-2014, Jocelyn Fiat, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" diff --git a/cms/src/theme/cms_theme.e b/cms/src/theme/cms_theme.e index 4557a61..6066077 100644 --- a/cms/src/theme/cms_theme.e +++ b/cms/src/theme/cms_theme.e @@ -1,12 +1,17 @@ note description: "Summary description for {WSF_CMS_THEME}." - author: "" date: "$Date$" revision: "$Revision$" deferred class CMS_THEME +inherit + CMS_ENCODERS + + REFACTORING_HELPER + + feature {NONE} -- Access setup: CMS_SETUP @@ -14,19 +19,63 @@ feature {NONE} -- Access feature -- Access name: STRING + -- theme name. deferred end regions: ARRAY [STRING] + -- theme's regions. deferred end page_template: CMS_TEMPLATE + -- theme template page. deferred end feature -- Conversion + menu_html (a_menu: CMS_MENU; is_horizontal: BOOLEAN): STRING_8 + do + fixme ("Refactor HTML code to use the new Bootstrap theme template") + create Result.make_from_string ("
    ") + if is_horizontal then + Result.append ("
      %N") + else + Result.append ("
        %N") + end + across + a_menu as c + loop + append_cms_link_to (c.item, Result) + end + Result.append ("
      %N") + Result.append ("
    ") + end + + block_html (a_block: CMS_BLOCK): STRING_8 + local + s: STRING + do + fixme ("Refactor HTML code to use the new Bootstrap theme template") + if attached {CMS_CONTENT_BLOCK} a_block as l_content_block and then l_content_block.is_raw then + create s.make_empty + if attached l_content_block.title as l_title then + s.append ("
    " + html_encoded (l_title) + "
    ") + end + s.append (l_content_block.to_html (Current)) + else + create s.make_from_string ("
    ") + if attached a_block.title as l_title then + s.append ("
    " + html_encoded (l_title) + "
    ") + end + s.append ("
    ") + s.append (a_block.to_html (Current)) + s.append ("
    ") + s.append ("
    ") + end + Result := s + end page_html (page: CMS_HTML_PAGE): STRING_8 -- Render `page' as html. deferred @@ -34,6 +83,41 @@ feature -- Conversion feature {NONE} -- Implementation + append_cms_link_to (lnk: CMS_LINK; s: STRING_8) + local + cl: STRING + do + fixme ("Remove HTML from Eiffel") + create cl.make_empty + if lnk.is_active then + cl.append ("active ") + end + if lnk.is_expandable then + cl.append ("expandable ") + end + if lnk.is_expanded then + cl.append ("expanded ") + end + if cl.is_empty then + s.append ("
  • ") + else + s.append ("
  • ") + end + s.append ("" + html_encoded (lnk.title) + "") + if + (lnk.is_expanded or lnk.is_collapsed) and then + attached lnk.children as l_children + then + s.append ("
      %N") + across + l_children as c + loop + append_cms_link_to (c.item, s) + end + s.append ("
    ") + end + s.append ("
  • ") + end note copyright: "2011-2014, Jocelyn Fiat, Eiffel Software and others" diff --git a/cms/src/theme/cms_theme_information.e b/cms/src/theme/cms_theme_information.e index ee0800a..719b3c1 100644 --- a/cms/src/theme/cms_theme_information.e +++ b/cms/src/theme/cms_theme_information.e @@ -18,7 +18,7 @@ feature {NONE} -- Initialization create items.make_caseless (1) create regions.make (5) across - (<<"header", "content", "footer", "first_sidebar", "second_sidebar">>) as ic + (<<"top","header", "highlighted","help", "content", "footer", "first_sidebar", "second_sidebar", "bottom">>) as ic loop regions.force (ic.item, ic.item) end diff --git a/cms/src/theme/default_theme/default_cms_theme.e b/cms/src/theme/default_theme/default_cms_theme.e index dcf4950..5cc4189 100644 --- a/cms/src/theme/default_theme/default_cms_theme.e +++ b/cms/src/theme/default_theme/default_cms_theme.e @@ -60,7 +60,6 @@ feature -- Conversion prepare (page: CMS_HTML_PAGE) do --- page.add_style (url ("/theme/style.css", Void), Void) end page_html (page: CMS_HTML_PAGE): STRING_8 @@ -75,6 +74,11 @@ feature -- Conversion Result := html_template.to_html (page) end + navigation_template: detachable READABLE_STRING_GENERAL + -- navigation template name, if any. + do + end + feature {NONE} -- Internal internal_page_template: detachable like page_template diff --git a/cms/src/theme/smarty_theme/smarty_cms_html_page_inspector.e b/cms/src/theme/smarty_theme/smarty_cms_html_page_inspector.e new file mode 100644 index 0000000..cbe3c4a --- /dev/null +++ b/cms/src/theme/smarty_theme/smarty_cms_html_page_inspector.e @@ -0,0 +1,60 @@ +note + description: "Summary description for {SMARTY_CMS_HTML_PAGE_INSPECTOR}." + author: "" + date: "$Date: 2014-11-07 04:58:41 -0300 (vi. 07 de nov. de 2014) $" + revision: "$Revision: 96042 $" + +class + SMARTY_CMS_HTML_PAGE_INSPECTOR + +inherit + TEMPLATE_INSPECTOR + redefine + internal_data + end + + CMS_ENCODERS + +create + register + +feature {TEMPLATE_ROUTINES} + + internal_data (field_name: STRING; obj: detachable ANY): detachable CELL [detachable ANY] + -- Return object in a cell + -- If not handled by this inspector, return Void + local + l_fn: STRING + do + if attached {CMS_HTML_PAGE} obj as l_page then + l_fn := field_name.as_lower + if attached l_page.variables.item (l_fn) as v then + Result := cell_of (v) + elseif l_fn.is_case_insensitive_equal ("title") then + if attached l_page.title as l_title then + Result := cell_of (html_encoded (l_title)) + else + Result := cell_of (Void) + end + elseif l_fn.is_case_insensitive_equal ("is_front") then + Result := cell_of (l_page.is_front) + elseif l_fn.starts_with_general ("region_") then + l_fn.remove_head (7) -- remove "region_" + Result := cell_of (l_page.region (l_fn)) + elseif l_fn.is_case_insensitive_equal ("regions") then + Result := cell_of (l_page.regions) + end + end + 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/cms/src/theme/smarty_theme/smarty_cms_page_template.e b/cms/src/theme/smarty_theme/smarty_cms_page_template.e index b02fe15..d5b45ab 100644 --- a/cms/src/theme/smarty_theme/smarty_cms_page_template.e +++ b/cms/src/theme/smarty_theme/smarty_cms_page_template.e @@ -9,6 +9,8 @@ class inherit CMS_PAGE_TEMPLATE + CMS_ENCODERS + SHARED_TEMPLATE_CONTEXT create @@ -41,12 +43,13 @@ feature -- Access variables.force (ic.item, ic.key) end + -- FIXME: review variables ! if attached page.title as l_title then - variables.force (l_title, "page_title") - variables.force (l_title, "head_title") + variables.force (html_encoded (l_title), "head_title") + variables.force (html_encoded (l_title), "page_title") else + variables.force ("CMS", "head_title") variables.force ("", "page_title") - variables.force ("", "head_title") end variables.force (page.language, "language") @@ -55,7 +58,7 @@ feature -- Access across theme.regions as r loop - variables.force (page.region (r.item), r.item) + variables.force (page.region (r.item), "region_" + r.item) end end diff --git a/cms/src/theme/smarty_theme/smarty_cms_regions_inspector.e b/cms/src/theme/smarty_theme/smarty_cms_regions_inspector.e new file mode 100644 index 0000000..6325103 --- /dev/null +++ b/cms/src/theme/smarty_theme/smarty_cms_regions_inspector.e @@ -0,0 +1,47 @@ +note + description: "Summary description for {SMARTY_CMS_REGIONS_INSPECTOR}." + author: "" + date: "$Date: 2014-11-06 17:59:12 -0300 (ju. 06 de nov. de 2014) $" + revision: "$Revision: 96040 $" + +class + SMARTY_CMS_REGIONS_INSPECTOR + +inherit + TEMPLATE_INSPECTOR + redefine + internal_data + end + +create + register + +feature {TEMPLATE_ROUTINES} + + internal_data (field_name: STRING; obj: detachable ANY): detachable CELL [detachable ANY] + -- Return object in a cell + -- If not handled by this inspector, return Void + local + l_fn: STRING + do + if attached {like {CMS_RESPONSE}.regions} obj as l_regions then + l_fn := field_name.as_lower + if l_fn.is_case_insensitive_equal ("count") then + Result := cell_of (l_regions.count) + elseif l_regions.has (l_fn) then + Result := cell_of (l_regions.item (l_fn)) + end + end + 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/cms/src/theme/smarty_theme/smarty_cms_theme.e b/cms/src/theme/smarty_theme/smarty_cms_theme.e index 2b2e6a4..c69aeb0 100644 --- a/cms/src/theme/smarty_theme/smarty_cms_theme.e +++ b/cms/src/theme/smarty_theme/smarty_cms_theme.e @@ -15,11 +15,10 @@ create feature {NONE} -- Initialization - make (a_setup: like setup; a_info: like information; a_template: like template) + make (a_setup: like setup; a_info: like information;) do setup := a_setup information := a_info - template := a_template if attached a_info.item ("template_dir") as s then templates_directory := a_setup.theme_location.extended (s) else @@ -28,15 +27,12 @@ feature {NONE} -- Initialization ensure setup_set: setup = a_setup information_set: information = a_info - template_set: template = a_template end feature -- Access name: STRING = "smarty-CMS" - template: STRING; - templates_directory: PATH information: CMS_THEME_INFORMATION @@ -59,7 +55,7 @@ feature -- Access i := i + 1 end else - l_regions := <<"header", "content", "footer", "first_sidebar", "second_sidebar">> + l_regions := <<"top","header", "content", "footer", "first_sidebar", "second_sidebar","bottom">> end internaL_regions := l_regions end @@ -72,7 +68,7 @@ feature -- Access do tpl := internal_page_template if tpl = Void then - create tpl.make (template, Current) + create tpl.make ("page", Current) internal_page_template := tpl end Result := tpl @@ -82,13 +78,42 @@ feature -- Conversion prepare (page: CMS_HTML_PAGE) do + page.register_variable (page, "page") + page.register_variable (page.regions, "regions") + across + page.regions as ic + loop + page.register_variable (ic.item, "region_" + ic.key) + end end page_html (page: CMS_HTML_PAGE): STRING_8 + local + l_page_inspector: detachable SMARTY_CMS_HTML_PAGE_INSPECTOR + l_regions_inspector: detachable SMARTY_CMS_REGIONS_INSPECTOR + l_table_inspector: detachable STRING_TABLE_OF_STRING_INSPECTOR do prepare (page) + create l_page_inspector.register (page.generating_type) + + if attached {CMS_RESPONSE} page.variables.item ("cms") as l_cms then + if attached l_cms.regions as l_regions then + create l_regions_inspector.register (l_regions.generating_type) + end + end + + create l_table_inspector.register (({detachable STRING_TABLE [STRING]}).name) page_template.prepare (page) Result := page_template.to_html (page) + + -- Clean template inspector. + if l_regions_inspector /= Void then + l_regions_inspector.unregister + end + if l_page_inspector /= Void then + l_page_inspector.unregister + end + l_table_inspector.unregister end feature {NONE} -- Internal diff --git a/cms/src/theme/smarty_theme/string_table_of_string_inspector.e b/cms/src/theme/smarty_theme/string_table_of_string_inspector.e new file mode 100644 index 0000000..4a61134 --- /dev/null +++ b/cms/src/theme/smarty_theme/string_table_of_string_inspector.e @@ -0,0 +1,47 @@ +note + description: "Summary description for {STRING_TABLE_OF_STRING_INSPECTOR}." + author: "" + date: "$Date: 2014-11-06 17:59:12 -0300 (ju. 06 de nov. de 2014) $" + revision: "$Revision: 96040 $" + +class + STRING_TABLE_OF_STRING_INSPECTOR + +inherit + TEMPLATE_INSPECTOR + redefine + internal_data + end + +create + register + +feature {TEMPLATE_ROUTINES} + + internal_data (field_name: STRING; obj: detachable ANY): detachable CELL [detachable ANY] + -- Return object in a cell + -- If not handled by this inspector, return Void + local + l_fn: STRING + do + if attached {STRING_TABLE [STRING]} obj as l_regions then + l_fn := field_name.as_lower + if l_fn.is_case_insensitive_equal ("count") then + Result := cell_of (l_regions.count) + elseif attached l_regions.item (l_fn) as v then + Result := cell_of (v) + end + end + 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/examples/api/roc_api.ecf b/examples/api/roc_api.ecf index a68d4e1..02794df 100644 --- a/examples/api/roc_api.ecf +++ b/examples/api/roc_api.ecf @@ -22,6 +22,7 @@ + diff --git a/examples/roc_api/modules/demo/cms_demo_module-safe.ecf b/examples/roc_api/modules/demo/cms_demo_module-safe.ecf index dd678f2..a954561 100644 --- a/examples/roc_api/modules/demo/cms_demo_module-safe.ecf +++ b/examples/roc_api/modules/demo/cms_demo_module-safe.ecf @@ -12,6 +12,7 @@ + diff --git a/examples/roc_api/modules/demo/cms_demo_module.e b/examples/roc_api/modules/demo/cms_demo_module.e index aeabe7b..879a064 100644 --- a/examples/roc_api/modules/demo/cms_demo_module.e +++ b/examples/roc_api/modules/demo/cms_demo_module.e @@ -9,45 +9,91 @@ class inherit CMS_MODULE + redefine + register_hooks + end + + CMS_HOOK_MENU_ALTER + + CMS_HOOK_BLOCK create make feature {NONE} -- Initialization - make (a_config: CMS_SETUP) + make do name := "Demo module" version := "1.0" description := "Service to demonstrate and test cms system" package := "demo" - config := a_config end - config: CMS_SETUP - -- Node configuration. - feature -- Access: router - router: WSF_ROUTER + router (a_api: CMS_API): WSF_ROUTER -- Node router. do create Result.make (2) - map_uri_template_agent (Result, "/demo/", agent handle_demo) - map_uri_template_agent (Result, "/book/{id}", agent handle_demo_entry) + map_uri_template_agent (Result, "/demo/", agent handle_demo (?,?,a_api)) + map_uri_template_agent (Result, "/demo/{id}", agent handle_demo_entry (?,?,a_api)) + end + +feature -- Hooks + + register_hooks (a_response: CMS_RESPONSE) + do + a_response.add_menu_alter_hook (Current) + a_response.add_block_hook (Current) + end + + block_list: ITERABLE [like {CMS_BLOCK}.name] + do + Result := <<"demo-info">> + end + + get_block_view (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE) + local + b: CMS_CONTENT_BLOCK + mb: CMS_MENU_BLOCK + m: CMS_MENU + lnk: CMS_LOCAL_LINK + do + 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)) + m.extend (lnk) + create lnk.make ("/demo/123", a_response.url ("/demo/123", Void)) + m.extend (lnk) + create mb.make (m) + a_response.add_block (mb, "sidebar_second") + end + end + end + + menu_alter (a_menu_system: CMS_MENU_SYSTEM; a_response: CMS_RESPONSE) + local + lnk: CMS_LOCAL_LINK +-- perms: detachable ARRAYED_LIST [READABLE_STRING_8] + do + create lnk.make ("Demo", "/demo/") + a_menu_system.primary_menu.extend (lnk) end feature -- Handler handle_demo, - handle_demo_entry (req: WSF_REQUEST; res: WSF_RESPONSE) + handle_demo_entry (req: WSF_REQUEST; res: WSF_RESPONSE; a_api: CMS_API) local - m: WSF_NOT_FOUND_RESPONSE + r: NOT_IMPLEMENTED_ERROR_CMS_RESPONSE do - create m.make (req) - m.set_body ("Not yet implemented!") - res.send (m) + 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.execute end feature -- Mapping helper: uri template diff --git a/examples/roc_api/site/config/application_configuration.json b/examples/roc_api/site/config/application_configuration.json index d493ed8..793f8ef 100644 --- a/examples/roc_api/site/config/application_configuration.json +++ b/examples/roc_api/site/config/application_configuration.json @@ -24,7 +24,7 @@ "backup_count":"4" }, "server": { - "mode":"api" + "mode":"html" } } diff --git a/examples/roc_api/site/config/cms.ini b/examples/roc_api/site/config/cms.ini index 27ebf1f..05a3774 100644 --- a/examples/roc_api/site/config/cms.ini +++ b/examples/roc_api/site/config/cms.ini @@ -3,4 +3,4 @@ site.name=EWF Web CMS site.email=your@email.com var-dir=var files-dir=files -theme=api +theme=bootstrap diff --git a/examples/roc_api/site/www/template/html/master2/content.tpl b/examples/roc_api/site/www/template/html/master2/content.tpl deleted file mode 100644 index b18c5dd..0000000 --- a/examples/roc_api/site/www/template/html/master2/content.tpl +++ /dev/null @@ -1,11 +0,0 @@ - -
    -

    Top most recent nodes


    - - - {foreach from="$nodes" item="item"} - - {/foreach} -
    diff --git a/examples/roc_api/site/www/template/html/master2/error.tpl b/examples/roc_api/site/www/template/html/master2/error.tpl deleted file mode 100644 index 0ca7ad0..0000000 --- a/examples/roc_api/site/www/template/html/master2/error.tpl +++ /dev/null @@ -1,18 +0,0 @@ -

    Error: {$code/}

    - -{assign name="status400" value="400"/} -{assign name="status404" value="404"/} -{assign name="status500" value="500"/} - -{if condition="$code ~ $status500"} -

    Internal server error, for the request {$request/}

    -{/if} - - -{if condition="$code ~ $status404"} -

    Resourse not found, for the request {$request/}

    -{/if} - -{if condition="$code ~ $status400"} -

    Bad request, the request {$request/} is not valid

    -{/if} \ No newline at end of file diff --git a/examples/roc_api/site/www/template/html/master2/footer.tpl b/examples/roc_api/site/www/template/html/master2/footer.tpl deleted file mode 100644 index 11fe183..0000000 --- a/examples/roc_api/site/www/template/html/master2/footer.tpl +++ /dev/null @@ -1,7 +0,0 @@ - -
    -

    API Documentation     - Questions? Comments? Let us know!

    -

    © Copyright 2014 Eiffel Software -- Privacy Policy -

    -
    \ No newline at end of file diff --git a/examples/roc_api/site/www/template/html/master2/head.tpl b/examples/roc_api/site/www/template/html/master2/head.tpl deleted file mode 100644 index 4ba4616..0000000 --- a/examples/roc_api/site/www/template/html/master2/head.tpl +++ /dev/null @@ -1,10 +0,0 @@ - - -Eiffel RESTonCMS -{if condition="$web"} - {include file="master2/optional_styling_css.tpl"/} -{/if} -{if condition="$html"} - {include file="master2/optional_styling_css.tpl"/} -{/if} - diff --git a/examples/roc_api/site/www/template/html/master2/header.tpl b/examples/roc_api/site/www/template/html/master2/header.tpl deleted file mode 100644 index ce8ec71..0000000 --- a/examples/roc_api/site/www/template/html/master2/header.tpl +++ /dev/null @@ -1,2 +0,0 @@ -

    RESTonCMS

    -

    Tagline

    \ No newline at end of file diff --git a/examples/roc_api/site/www/template/html/master2/logoff.tpl b/examples/roc_api/site/www/template/html/master2/logoff.tpl deleted file mode 100644 index 8139dc7..0000000 --- a/examples/roc_api/site/www/template/html/master2/logoff.tpl +++ /dev/null @@ -1,5 +0,0 @@ -

    You have successfully signed out

    - -You may want to return - -Press this neat little button:Take Me Home diff --git a/examples/roc_api/site/www/template/html/master2/main_navigation.tpl b/examples/roc_api/site/www/template/html/master2/main_navigation.tpl deleted file mode 100644 index 88365d7..0000000 --- a/examples/roc_api/site/www/template/html/master2/main_navigation.tpl +++ /dev/null @@ -1,5 +0,0 @@ - \ No newline at end of file diff --git a/examples/roc_api/site/www/template/html/master2/optional_enhancement_js.tpl b/examples/roc_api/site/www/template/html/master2/optional_enhancement_js.tpl deleted file mode 100644 index 1353b83..0000000 --- a/examples/roc_api/site/www/template/html/master2/optional_enhancement_js.tpl +++ /dev/null @@ -1,5 +0,0 @@ - - -{if condition="$web"} - -{/if} \ No newline at end of file diff --git a/examples/roc_api/site/www/template/html/master2/optional_styling_css.tpl b/examples/roc_api/site/www/template/html/master2/optional_styling_css.tpl deleted file mode 100644 index f56d770..0000000 --- a/examples/roc_api/site/www/template/html/master2/optional_styling_css.tpl +++ /dev/null @@ -1,9 +0,0 @@ -{if condition="$html"} - - - -{/if} -{if condition="$web"} - - -{/if} diff --git a/examples/roc_api/site/www/template/html/master2/site_navigation.tpl b/examples/roc_api/site/www/template/html/master2/site_navigation.tpl deleted file mode 100644 index a75760c..0000000 --- a/examples/roc_api/site/www/template/html/master2/site_navigation.tpl +++ /dev/null @@ -1,27 +0,0 @@ - - - - \ No newline at end of file diff --git a/examples/roc_api/site/www/template/html/modules/navigation.tpl b/examples/roc_api/site/www/template/html/modules/navigation.tpl deleted file mode 100644 index ee2d15e..0000000 --- a/examples/roc_api/site/www/template/html/modules/navigation.tpl +++ /dev/null @@ -1,8 +0,0 @@ -{if isset="$user"} - Logoff -{/if} -{unless isset="$user"} - Login - Register -{/unless} -List of Nodes diff --git a/examples/roc_api/site/www/template/html/modules/node.tpl b/examples/roc_api/site/www/template/html/modules/node.tpl deleted file mode 100644 index 0f6173f..0000000 --- a/examples/roc_api/site/www/template/html/modules/node.tpl +++ /dev/null @@ -1,174 +0,0 @@ -{if condition="html"} - - - - {include file="master2/head.tpl"/} - - -{/if} - -{unless condition="$web"} - - {include file="master2/site_navigation.tpl"/} -{/unless} - - -{if condition="html"} - -
    -
    -
    -
    -{/if} - - -
    - {if condition="$web"} - - {/if} - {if condition="$html"} - - {/if} -
    -
    - {if isset="$node"} -
    -
    -
    -
    -

    {$node.title/}

    -
    -
    -
    {$node.content/}
    -
    -
    -
    - {/if} -
    - -
    - {if isset="$user"} -
    -
    -
    - {if isset="$node"} - -
    - {/if} -
    -
    -
    - {if isset="$user"} -
    -
    - - {if isset="$node"} -
    - -
    - Delete Node - -
    - -
    -
    -
    - {/if} -
    - {/if} -
    -
    -
    - -{if condition="html"} -
    -
    -
    -{/if} - - -{if condition="html"} - - - - {include file="master2/optional_enhancement_js.tpl"/} - - - -{/if} \ No newline at end of file diff --git a/examples/roc_api/site/www/template/html/modules/node_content.tpl b/examples/roc_api/site/www/template/html/modules/node_content.tpl deleted file mode 100644 index 4825500..0000000 --- a/examples/roc_api/site/www/template/html/modules/node_content.tpl +++ /dev/null @@ -1,70 +0,0 @@ -{if condition="html"} - - - - {include file="master2/head.tpl"/} - - -{/if} - -{unless condition="$web"} - - {include file="master2/site_navigation.tpl"/} -{/unless} - -{if condition="html"} - -
    -
    -
    -
    -{/if} - - -
    -
    -
    - -
    - Edit Node Content - -
    -
    - -
    -
    - -
    -
    - -
    - -
    -
    -
    -
    -
    -{if condition="html"} - -
    -
    -
    -{/if} - - -{if condition="html"} - - - - {include file="master2/optional_enhancement_js.tpl"/} - - - -{/if} \ No newline at end of file diff --git a/examples/roc_api/site/www/template/html/modules/node_summary.tpl b/examples/roc_api/site/www/template/html/modules/node_summary.tpl deleted file mode 100644 index 24f69e6..0000000 --- a/examples/roc_api/site/www/template/html/modules/node_summary.tpl +++ /dev/null @@ -1,71 +0,0 @@ -{if condition="html"} - - - - {include file="master2/head.tpl"/} - - -{/if} - - - {unless condition="$web"} - - {include file="master2/site_navigation.tpl"/} - {/unless} - -{if condition="html"} - -
    -
    -
    -
    -{/if} - -
    -
    -
    - -
    - Edit Node Summary - -
    -
    - -
    -
    - -
    -
    - -
    - -
    -
    -
    -
    -
    - -{if condition="html"} - -
    -
    -
    -{/if} - - -{if condition="html"} - - - - {include file="master2/optional_enhancement_js.tpl"/} - - - -{/if} \ No newline at end of file diff --git a/examples/roc_api/site/www/template/html/modules/node_title.tpl b/examples/roc_api/site/www/template/html/modules/node_title.tpl deleted file mode 100644 index 2e02d02..0000000 --- a/examples/roc_api/site/www/template/html/modules/node_title.tpl +++ /dev/null @@ -1,70 +0,0 @@ -{if condition="html"} - - - - {include file="master2/head.tpl"/} - - -{/if} - - {unless condition="$web"} - - {include file="master2/site_navigation.tpl"/} - {/unless} - - -{if condition="html"} - -
    -
    -
    -
    -{/if} - -
    -
    -
    - -
    - Edit Node Title - -
    -
    - -
    -
    - -
    -
    - -
    - -
    -
    -
    -
    -
    -{if condition="html"} - -
    -
    -
    -{/if} - - -{if condition="html"} - - - - {include file="master2/optional_enhancement_js.tpl"/} - - - -{/if} \ No newline at end of file diff --git a/examples/roc_api/site/www/template/html/modules/nodes.tpl b/examples/roc_api/site/www/template/html/modules/nodes.tpl deleted file mode 100644 index 23b24c7..0000000 --- a/examples/roc_api/site/www/template/html/modules/nodes.tpl +++ /dev/null @@ -1,52 +0,0 @@ -{if condition="html"} - - - - {include file="master2/head.tpl"/} - - -{/if} - -{unless condition="$web"} - - {include file="master2/site_navigation.tpl"/} -{/unless} - -{if condition="html"} - -
    -
    -
    -
    -{/if} -
    -

    List nodes


    - - - {foreach from="$nodes" item="item"} - - {/foreach} -
    - -{if condition="html"} -
    -
    -
    -{/if} - - -{if condition="html"} - - - - {include file="master2/optional_enhancement_js.tpl"/} - - - -{/if} \ No newline at end of file diff --git a/examples/roc_api/site/www/template/html/modules/register.tpl b/examples/roc_api/site/www/template/html/modules/register.tpl deleted file mode 100644 index 3a14667..0000000 --- a/examples/roc_api/site/www/template/html/modules/register.tpl +++ /dev/null @@ -1,100 +0,0 @@ -{if condition="html"} - - - - {include file="master2/head.tpl"/} - - -{/if} - - -{unless condition="$web"} - - {include file="master2/site_navigation.tpl"/} -{/unless} - -{if condition="html"} - -
    -
    -
    -
    -{/if} - - -
    -
    -
    -
    - Register -
    -

    Register new user

    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    - s
    - -
    - -
    -
    -
    -
    -
    - -{if condition="html"} -
    -
    -
    -{/if} - - -{if condition="html"} - - - - {include file="master2/optional_enhancement_js.tpl"/} - - - -{/if} \ No newline at end of file diff --git a/examples/roc_api/site/www/template/html/layout2.tpl b/examples/roc_api/site/www/themes/api/layout.tpl similarity index 87% rename from examples/roc_api/site/www/template/html/layout2.tpl rename to examples/roc_api/site/www/themes/api/layout.tpl index 34a5659..6025408 100644 --- a/examples/roc_api/site/www/template/html/layout2.tpl +++ b/examples/roc_api/site/www/themes/api/layout.tpl @@ -8,10 +8,6 @@ {include file="master2/site_navigation.tpl"/} - -

    diff --git a/examples/roc_api/site/www/themes/bootstrap.7z b/examples/roc_api/site/www/themes/bootstrap.7z new file mode 100644 index 0000000..45c941d Binary files /dev/null and b/examples/roc_api/site/www/themes/bootstrap.7z differ diff --git a/examples/roc_api/site/www/themes/bootstrap/block/header_block.tpl b/examples/roc_api/site/www/themes/bootstrap/block/header_block.tpl new file mode 100644 index 0000000..4a3b24c --- /dev/null +++ b/examples/roc_api/site/www/themes/bootstrap/block/header_block.tpl @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/examples/roc_api/site/www/themes/bootstrap/page.tpl b/examples/roc_api/site/www/themes/bootstrap/page.tpl new file mode 100644 index 0000000..53f29fd --- /dev/null +++ b/examples/roc_api/site/www/themes/bootstrap/page.tpl @@ -0,0 +1,84 @@ + + + + + ROC- Layout with defualt Regions + + + + + + + + + + + + + + + + +{$head_title/} + + + + {if isset="$region_top"} + {$region_top/} + {/if} + +
    + + + + + +
    + + {unless empty="$page.region_sidebar_first"} +
    + {$page.region_sidebar_first/} +
    + {/unless} + + + +
    + + {$page.region_highlighted/} + + + {$page.region_help/} + + + {unless empty="$page_title"}

    {$page_title/}

    {/unless} + {$page.region_content/} +
    + + + {unless empty="$page.region_sidebar_second"} +
    + {$page.region_sidebar_second/} +
    + {/unless} + +
    +
    + + + {$page.region_footer/} + + + {$page.region_bottom/} + + + + diff --git a/examples/roc_api/site/www/themes/bootstrap/roc_template -2.html b/examples/roc_api/site/www/themes/bootstrap/roc_template -2.html new file mode 100644 index 0000000..17b8074 --- /dev/null +++ b/examples/roc_api/site/www/themes/bootstrap/roc_template -2.html @@ -0,0 +1,108 @@ + + + + + ROC- Layout with defualt Regions + + + + + + + + +ROC CMS - A responsive layout + + + + +
    +

    ROC Layout with Defaul Regions

    + + + +
    + + + + + + + +
    +

    Highlighted Section

    +

    Help Section

    + +

    Main Content Section

    +

    Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum.

    + +

    Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.

    +
    + + + +
    +
    + + + + + + + + + diff --git a/examples/roc_api/site/www/themes/bootstrap/roc_template.html b/examples/roc_api/site/www/themes/bootstrap/roc_template.html new file mode 100644 index 0000000..1472f38 --- /dev/null +++ b/examples/roc_api/site/www/themes/bootstrap/roc_template.html @@ -0,0 +1,135 @@ + + + + + ROC- Layout with defualt Regions + + + + + + + + + + + + + + + + +ROC CMS - A responsive layout + + + + + +
    + + + +
    + + + + + + + +
    +

    Highlighted Section

    +

    Help Section

    + +

    Main Content Section

    +

    Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum.

    + +

    Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.

    +
    + + + + + +
    +
    + + + + + + + + + diff --git a/examples/roc_api/site/www/themes/bootstrap/theme.info b/examples/roc_api/site/www/themes/bootstrap/theme.info new file mode 100644 index 0000000..b084985 --- /dev/null +++ b/examples/roc_api/site/www/themes/bootstrap/theme.info @@ -0,0 +1,14 @@ +name=bootstrap +engine=smarty +author=jvelilla +version=0.1 +regions[page_top] = Top +regions[header] = Header +regions[content] = Content +regions[highlighted] = Highlighted +regions[help] = Help +regions[footer] = Footer +regions[first_sidebar] = first sidebar +regions[second_sidebar] = second sidebar +regions[page_bottom] = Bottom +navigation=default_nav \ No newline at end of file diff --git a/examples/roc_api/site/www/themes/bootstrap/tpl/help_section.tpl b/examples/roc_api/site/www/themes/bootstrap/tpl/help_section.tpl new file mode 100644 index 0000000..b20cb47 --- /dev/null +++ b/examples/roc_api/site/www/themes/bootstrap/tpl/help_section.tpl @@ -0,0 +1 @@ +

    Help Section

    \ No newline at end of file diff --git a/examples/roc_api/site/www/themes/bootstrap/tpl/highlighted_section.tpl b/examples/roc_api/site/www/themes/bootstrap/tpl/highlighted_section.tpl new file mode 100644 index 0000000..fc75c0c --- /dev/null +++ b/examples/roc_api/site/www/themes/bootstrap/tpl/highlighted_section.tpl @@ -0,0 +1 @@ +

    Highlighted Section

    diff --git a/examples/roc_api/site/www/themes/bootstrap/tpl/left_sidebar.tpl b/examples/roc_api/site/www/themes/bootstrap/tpl/left_sidebar.tpl new file mode 100644 index 0000000..ee2ee4c --- /dev/null +++ b/examples/roc_api/site/www/themes/bootstrap/tpl/left_sidebar.tpl @@ -0,0 +1,8 @@ + diff --git a/examples/roc_api/site/www/themes/bootstrap/tpl/main_content.tpl b/examples/roc_api/site/www/themes/bootstrap/tpl/main_content.tpl new file mode 100644 index 0000000..0df8def --- /dev/null +++ b/examples/roc_api/site/www/themes/bootstrap/tpl/main_content.tpl @@ -0,0 +1,4 @@ +

    Main Content Section

    +

    Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum.

    + +

    Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.

    \ No newline at end of file diff --git a/examples/roc_api/site/www/themes/bootstrap/tpl/page_bottom.tpl b/examples/roc_api/site/www/themes/bootstrap/tpl/page_bottom.tpl new file mode 100644 index 0000000..e69de29 diff --git a/examples/roc_api/site/www/themes/bootstrap/tpl/page_footer.tpl b/examples/roc_api/site/www/themes/bootstrap/tpl/page_footer.tpl new file mode 100644 index 0000000..9c7ee8e --- /dev/null +++ b/examples/roc_api/site/www/themes/bootstrap/tpl/page_footer.tpl @@ -0,0 +1,9 @@ + \ No newline at end of file diff --git a/examples/roc_api/site/www/themes/bootstrap/tpl/page_header.tpl b/examples/roc_api/site/www/themes/bootstrap/tpl/page_header.tpl new file mode 100644 index 0000000..db83655 --- /dev/null +++ b/examples/roc_api/site/www/themes/bootstrap/tpl/page_header.tpl @@ -0,0 +1,34 @@ + + diff --git a/examples/roc_api/site/www/themes/bootstrap/tpl/page_header2.tpl b/examples/roc_api/site/www/themes/bootstrap/tpl/page_header2.tpl new file mode 100644 index 0000000..5f1e3e6 --- /dev/null +++ b/examples/roc_api/site/www/themes/bootstrap/tpl/page_header2.tpl @@ -0,0 +1,28 @@ + {if isset="$default_nav"} + +{/if} \ No newline at end of file diff --git a/examples/roc_api/site/www/themes/bootstrap/tpl/page_top.tpl b/examples/roc_api/site/www/themes/bootstrap/tpl/page_top.tpl new file mode 100644 index 0000000..e69de29 diff --git a/examples/roc_api/site/www/themes/bootstrap/tpl/primary_nav.tpl b/examples/roc_api/site/www/themes/bootstrap/tpl/primary_nav.tpl new file mode 100644 index 0000000..221563a --- /dev/null +++ b/examples/roc_api/site/www/themes/bootstrap/tpl/primary_nav.tpl @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/examples/roc_api/site/www/themes/bootstrap/tpl/right_sidebar.tpl b/examples/roc_api/site/www/themes/bootstrap/tpl/right_sidebar.tpl new file mode 100644 index 0000000..b0f6904 --- /dev/null +++ b/examples/roc_api/site/www/themes/bootstrap/tpl/right_sidebar.tpl @@ -0,0 +1,8 @@ + \ No newline at end of file diff --git a/examples/roc_api/site/www/themes/bootstrap/tpl/secondary_nav.tpl b/examples/roc_api/site/www/themes/bootstrap/tpl/secondary_nav.tpl new file mode 100644 index 0000000..a40739c --- /dev/null +++ b/examples/roc_api/site/www/themes/bootstrap/tpl/secondary_nav.tpl @@ -0,0 +1,7 @@ + + \ No newline at end of file diff --git a/examples/roc_api/src/ewf_roc_server.e b/examples/roc_api/src/ewf_roc_server.e index 4919a54..6edeb1b 100644 --- a/examples/roc_api/src/ewf_roc_server.e +++ b/examples/roc_api/src/ewf_roc_server.e @@ -117,13 +117,12 @@ feature -- CMS Initialization initialize_cms (a_setup: CMS_SETUP) local cms: CMS_SERVICE - l_modules: CMS_MODULE_COLLECTION + api: CMS_API do log.write_debug (generator + ".initialize_cms") - setup_modules (a_setup) - - create cms.make (a_setup) + create api.make (a_setup) + create cms.make (api) cms_service := cms end @@ -134,14 +133,13 @@ feature -- CMS setup local m: CMS_MODULE do - create {NODE_MODULE} m.make (a_setup) + create {BASIC_AUTH_MODULE} m.make m.enable a_setup.modules.extend (m) - create {CMS_DEMO_MODULE} m.make (a_setup) + create {CMS_DEMO_MODULE} m.make m.enable a_setup.modules.extend (m) - end setup_storage (a_setup: CMS_SETUP) diff --git a/model/model-safe.ecf b/model/model-safe.ecf new file mode 100644 index 0000000..cc50b08 --- /dev/null +++ b/model/model-safe.ecf @@ -0,0 +1,19 @@ + + + + + + + + + + + /EIFGENs$ + /.svn$ + /CVS$ + + + + diff --git a/model/src/cms_content_type.e b/model/src/cms_content_type.e new file mode 100644 index 0000000..fc6cec2 --- /dev/null +++ b/model/src/cms_content_type.e @@ -0,0 +1,10 @@ +note + description: "Summary description for {CMS_CONTENT_TYPE}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + CMS_CONTENT_TYPE + +end diff --git a/model/src/cms_link.e b/model/src/cms_link.e new file mode 100644 index 0000000..70aca33 --- /dev/null +++ b/model/src/cms_link.e @@ -0,0 +1,80 @@ +note + description: "Summary description for {CMS_MENU}." + author: "" + date: "$Date$" + revision: "$Revision$" + +deferred class + CMS_LINK + +inherit + REFACTORING_HELPER + + DEBUG_OUTPUT + + ITERABLE [CMS_LINK] + +feature -- Access + + title: READABLE_STRING_32 + -- link's title. + + location: READABLE_STRING_8 + -- link's location. + +feature -- status report + + is_active: BOOLEAN + deferred + end + + is_expanded: BOOLEAN + -- Is expanded and visually expanded? + deferred + end + + is_collapsed: BOOLEAN + -- Is expanded, but visually collapsed? + deferred + ensure + Result implies is_expandable + end + + is_expandable: BOOLEAN + -- Is expandable? + deferred + end + + has_children: BOOLEAN + deferred + end + +feature -- Query + + parent: detachable CMS_LINK + + children: detachable LIST [CMS_LINK] + deferred + end + +feature -- Access + + new_cursor: ITERATION_CURSOR [CMS_LINK] + -- Fresh cursor associated with current structure + do + if attached children as lst then + Result := lst.new_cursor + else + Result := (create {ARRAYED_LIST [CMS_LINK]}.make (0)).new_cursor + end + end + +feature -- Status report + + debug_output: STRING + -- String that should be displayed in debugger to represent `Current'. + do + Result := title.as_string_8 + " -> " + location + end + +end diff --git a/model/src/cms_link_composite.e b/model/src/cms_link_composite.e new file mode 100644 index 0000000..3a9c7da --- /dev/null +++ b/model/src/cms_link_composite.e @@ -0,0 +1,27 @@ +note + description: "Summary description for {CMS_LINK_COMPOSITE}." + author: "" + date: "$Date$" + revision: "$Revision$" + +deferred class + CMS_LINK_COMPOSITE + +inherit + ITERABLE [CMS_LINK] + +feature -- Access + + items: detachable LIST [CMS_LINK] + deferred + end + + extend (lnk: CMS_LINK) + deferred + end + + remove (lnk: CMS_LINK) + deferred + end + +end diff --git a/model/src/cms_local_link.e b/model/src/cms_local_link.e new file mode 100644 index 0000000..a8757d6 --- /dev/null +++ b/model/src/cms_local_link.e @@ -0,0 +1,136 @@ +note + description: "Summary description for {CMS_LOCAL_MENU}." + date: "$Date$" + revision: "$Revision$" + +class + CMS_LOCAL_LINK + +inherit + CMS_LINK + + CMS_LINK_COMPOSITE + rename + items as children, + extend as add_link, + remove as remove_link + end + +create + make + +feature {NONE} -- Initialization + + make (a_title: detachable like title; a_location: like location) + do + if a_title /= Void then + title := a_title + else + title := a_location + end + location := a_location + end + +feature -- Status report + + is_active: BOOLEAN + + is_expanded: BOOLEAN + do + Result := is_expandable and then internal_is_expanded + end + + is_collapsed: BOOLEAN + -- Is expanded, but visually collapsed? + do + Result := is_expandable and then internal_is_collapsed + end + + is_expandable: BOOLEAN + do + Result := internal_is_expandable or internal_is_expanded or has_children + end + + has_children: BOOLEAN + do + Result := attached children as l_children and then not l_children.is_empty + end + + permission_arguments: detachable ITERABLE [READABLE_STRING_8] + + children: detachable LIST [CMS_LINK] + + internal_is_expandable: BOOLEAN + + internal_is_expanded: BOOLEAN + + internal_is_collapsed: BOOLEAN + +feature -- Element change + + add_link (lnk: CMS_LINK) + local + lst: like children + do + lst := children + if lst = Void then + create {ARRAYED_LIST [CMS_LINK]} lst.make (1) + children := lst + end + lst.force (lnk) + end + + remove_link (lnk: CMS_LINK) + local + lst: like children + do + lst := children + if lst /= Void then + lst.prune_all (lnk) + if lst.is_empty then + children := Void + end + end + end + + set_children (lst: like children) + do + children := lst + end + +feature -- Status change + + set_is_active (b: BOOLEAN) + -- Set `is_active' to `b'. + do + is_active := b + end + + set_expanded (b: like is_expanded) + do + if b then + set_expandable (True) + set_collapsed (False) + end + internal_is_expanded := b + end + + set_collapsed (b: like is_collapsed) + do + if b then + set_expanded (False) + end + internal_is_collapsed := b + end + + set_expandable (b: like is_expandable) + do + internal_is_expandable := b + end + + set_permission_arguments (args: like permission_arguments) + do + permission_arguments := args + end + +end diff --git a/model/src/cms_menu.e b/model/src/cms_menu.e new file mode 100644 index 0000000..6cb332f --- /dev/null +++ b/model/src/cms_menu.e @@ -0,0 +1,72 @@ +note + description: "Summary description for {CMS_MENU}." + date: "$Date$" + revision: "$Revision$" + +class + CMS_MENU + +inherit + CMS_LINK_COMPOSITE + +create + make, + make_with_title + +feature {NONE} -- Initialization + + make (a_name: like name; n: INTEGER) + do + name := a_name + create items.make (n) + end + + make_with_title (a_name: like name; a_title: READABLE_STRING_32; n: INTEGER) + do + make (a_name, n) + set_title (a_title) + end + +feature -- Access + + name: READABLE_STRING_8 + + title: detachable READABLE_STRING_32 + + items: ARRAYED_LIST [CMS_LINK] + + extend (lnk: CMS_LINK) + do + items.extend (lnk) + end + + remove (lnk: CMS_LINK) + do + items.prune_all (lnk) + end + +feature -- status report + + is_empty: BOOLEAN + do + Result := items.is_empty + end + +feature -- Element change + + set_title (t: like title) + do + title := t + end + +feature -- Access + + new_cursor: ITERATION_CURSOR [CMS_LINK] + -- Fresh cursor associated with current structure + do + Result := items.new_cursor + end + +invariant + +end diff --git a/persistence/implementation/common/model/cms_node.e b/model/src/cms_node.e similarity index 100% rename from persistence/implementation/common/model/cms_node.e rename to model/src/cms_node.e diff --git a/persistence/implementation/common/model/cms_user.e b/model/src/cms_user.e similarity index 100% rename from persistence/implementation/common/model/cms_user.e rename to model/src/cms_user.e diff --git a/persistence/implementation/common/model/cms_user_profile.e b/model/src/cms_user_profile.e similarity index 100% rename from persistence/implementation/common/model/cms_user_profile.e rename to model/src/cms_user_profile.e diff --git a/persistence/implementation/common/model/cms_user_role.e b/model/src/cms_user_role.e similarity index 100% rename from persistence/implementation/common/model/cms_user_role.e rename to model/src/cms_user_role.e diff --git a/persistence/implementation/common/cms_storage_null.e b/persistence/implementation/common/cms_storage_null.e index c82e9b6..89eb3df 100644 --- a/persistence/implementation/common/cms_storage_null.e +++ b/persistence/implementation/common/cms_storage_null.e @@ -9,8 +9,22 @@ class inherit CMS_STORAGE + redefine + default_create + select + default_create + end REFACTORING_HELPER + rename + default_create as default_create_rh + end +feature -- Initialization + + default_create + do + create error_handler.make + end feature -- Access: user diff --git a/persistence/implementation/common/database/database_connection.e b/persistence/implementation/common/database/database_connection.e index 7591273..5f0e9f7 100644 --- a/persistence/implementation/common/database/database_connection.e +++ b/persistence/implementation/common/database/database_connection.e @@ -10,8 +10,6 @@ inherit DATABASE_CONFIG - SHARED_ERROR - feature {NONE} -- Initialization make_common @@ -72,6 +70,65 @@ feature -- Database Setup keep_connection: BOOLEAN -- Keep connection alive? +feature -- Transactions + + begin_transaction + -- Start a transaction which will be terminated by a call to `rollback' or `commit'. + local + rescued: BOOLEAN + do + if not rescued then + if db_control.is_ok then + db_control.begin + else + database_error_handler.add_database_error (db_control.error_message_32, db_control.error_code) + end + end + rescue + rescued := True + exception_as_error ((create {EXCEPTION_MANAGER}).last_exception) + db_control.reset + retry + end + + commit + -- Commit updates in the database. + local + rescued: BOOLEAN + do + if not rescued then + if db_control.is_ok then + db_control.commit + else + database_error_handler.add_database_error (db_control.error_message_32, db_control.error_code) + end + end + rescue + rescued := True + exception_as_error ((create {EXCEPTION_MANAGER}).last_exception) + db_control.reset + retry + end + + rollback + -- Rollback updates in the database. + local + rescued: BOOLEAN + do + if not rescued then + if db_control.is_ok then + db_control.rollback + else + database_error_handler.add_database_error (db_control.error_message_32, db_control.error_code) + end + end + rescue + rescued := True + exception_as_error ((create {EXCEPTION_MANAGER}).last_exception) + db_control.reset + retry + end + feature -- Change Element not_keep_connection @@ -107,4 +164,28 @@ feature -- Conection Result := db_control.is_connected end +feature -- Error Handling + + database_error_handler: DATABASE_ERROR_HANDLER + -- Error handler. + +feature -- Status Report + + has_error: BOOLEAN + -- Has error? + do + Result := database_error_handler.has_error + end + +feature -- Helper + + exception_as_error (a_e: like {EXCEPTION_MANAGER}.last_exception) + -- Record exception as an error. + do + if attached a_e as l_e and then attached l_e.trace as l_trace then + database_error_handler.add_error_details (l_e.code, once "Exception", l_trace.as_string_32) + end + end + + end diff --git a/persistence/implementation/common/database/database_connection_null.e b/persistence/implementation/common/database/database_connection_null.e index d9257b3..ec54d13 100644 --- a/persistence/implementation/common/database/database_connection_null.e +++ b/persistence/implementation/common/database/database_connection_null.e @@ -22,6 +22,7 @@ feature -- Initialization make_common -- Create a database handler for ODBC with common settings. do + create database_error_handler.make create db_application.login (username, password) db_application.set_hostname (hostname) db_application.set_data_source (database_name) diff --git a/persistence/implementation/common/database/database_handler.e b/persistence/implementation/common/database/database_handler.e index 3551e4a..3517ff3 100644 --- a/persistence/implementation/common/database/database_handler.e +++ b/persistence/implementation/common/database/database_handler.e @@ -8,7 +8,7 @@ deferred class inherit - SHARED_ERROR + SHARED_LOGGER feature -- Access @@ -42,15 +42,15 @@ feature -- Modifiers feature -- Functionality Store Procedures - execute_reader - -- Execute store. + execute_store_reader + -- Execute a `store' to read data. require store_not_void: store /= void deferred end - execute_writer - -- Execute store. + execute_store_writer + -- Execute a `store' to write data. require store_not_void: store /= void deferred @@ -59,14 +59,14 @@ feature -- Functionality Store Procedures feature -- SQL Queries execute_query - -- Execute query. + -- Execute sql query, the read data from the database. require query_not_void: query /= void deferred end execute_change - -- Execute sqlquery that update/add data. + -- Execute sql query that update/add data. require query_not_void: query /= void deferred @@ -147,15 +147,75 @@ feature -- Access feature -- Status Report - has_error: BOOLEAN - -- Is there an error? - count: INTEGER -- Number of rows, last execution. deferred end -feature {NODE_DATA_PROVIDER}-- Implementation + connection: DATABASE_CONNECTION + -- Database connection. + + db_control: DB_CONTROL + -- Database control. + do + Result := connection.db_control + end + + db_result: detachable DB_RESULT + -- Database query result. + + db_selection: detachable DB_SELECTION + -- Database selection. + + db_change: detachable DB_CHANGE + -- Database modification. + +feature -- Error handling + + check_database_change_error + -- Check database error from `db_change'. + do + if attached db_change as l_change and then not l_change.is_ok then + database_error_handler.add_database_error (l_change.error_message_32, l_change.error_code) + log.write_error (generator + ".check_database_change_error: " + l_change.error_message_32) + l_change.reset + end + end + + check_database_selection_error + -- Check database error from `db_selection'. + do + if attached db_selection as l_selection and then not l_selection.is_ok then + database_error_handler.add_database_error (l_selection.error_message_32, l_selection.error_code) + log.write_error (generator + ".check_database_selection_error: " + l_selection.error_message_32) + l_selection.reset + end + end + +feature -- Error Handling + + database_error_handler: DATABASE_ERROR_HANDLER + -- Error handler. + +feature -- Status Report + + has_error: BOOLEAN + -- Has error? + do + Result := database_error_handler.has_error + end + +feature -- Helper + + exception_as_error (a_e: like {EXCEPTION_MANAGER}.last_exception) + -- Record exception as an error. + do + if attached a_e as l_e and then attached l_e.trace as l_trace then + database_error_handler.add_error_details (l_e.code, once "Exception", l_trace.as_string_32) + end + end + +feature -- Connection Handling connect -- Connect to the database. diff --git a/persistence/implementation/common/database/database_handler_impl.e b/persistence/implementation/common/database/database_handler_impl.e index 96078ee..1de28a1 100644 --- a/persistence/implementation/common/database/database_handler_impl.e +++ b/persistence/implementation/common/database/database_handler_impl.e @@ -21,79 +21,62 @@ feature {NONE} -- Initialization do connection := a_connection create last_query.make_now - set_successful + create database_error_handler.make ensure connection_not_void: connection /= Void last_query_not_void: last_query /= Void + database_error_handler_set: attached database_error_handler end feature -- Functionality - execute_reader + execute_store_reader -- Execute stored procedure that returns data. local l_db_selection: DB_SELECTION l_retried: BOOLEAN do if not l_retried then - if not keep_connection then - connect - end - + database_error_handler.reset if attached store as l_store then create l_db_selection.make db_selection := l_db_selection items := l_store.execute_reader (l_db_selection) + check_database_selection_error end - - if not keep_connection then - disconnect - end - set_successful log.write_debug ( generator+".execute_reader Successful") end rescue - set_last_error_from_exception ("Store procedure execution") - log.write_critical (generator+ ".execute_reader " + last_error_message) - if is_connected then - disconnect - end l_retried := True + exception_as_error ((create {EXCEPTION_MANAGER}).last_exception) + if attached db_selection as l_selection then + l_selection.reset + end retry end - execute_writer + execute_store_writer -- Execute stored procedure that update/add data. local l_db_change: DB_CHANGE l_retried : BOOLEAN do if not l_retried then - if not keep_connection and not is_connected then - connect - end - + database_error_handler.reset if attached store as l_store then create l_db_change.make - db_update := l_db_change + db_change := l_db_change l_store.execute_writer (l_db_change) - if not l_store.has_error then - db_control.commit - end + check_database_change_error end - if not keep_connection then - disconnect - end - set_successful log.write_debug ( generator+".execute_writer Successful") end rescue - set_last_error_from_exception ("Store procedure execution") - log.write_critical (generator+ ".execute_writer " + last_error_message) - if is_connected then - disconnect - end l_retried := True + exception_as_error ((create {EXCEPTION_MANAGER}).last_exception) + if attached db_change as l_change then + l_change.reset + end retry end @@ -106,60 +89,45 @@ feature -- SQL Queries l_retried: BOOLEAN do if not l_retried then - if not keep_connection then - connect - end - + database_error_handler.reset if attached query as l_query then create l_db_selection.make db_selection := l_db_selection items := l_query.execute_reader (l_db_selection) + check_database_selection_error end - if not keep_connection then - disconnect - end - set_successful end rescue - set_last_error_from_exception ("execute_query") - log.write_critical (generator+ ".execute_query " + last_error_message) - if is_connected then - disconnect - end l_retried := True + exception_as_error ((create {EXCEPTION_MANAGER}).last_exception) + if attached db_selection as l_selection then + l_selection.reset + end retry end execute_change - -- Execute sqlquery that update/add data. + -- Execute sql_query that update/add data. local l_db_change: DB_CHANGE l_retried : BOOLEAN do if not l_retried then - if not keep_connection and not is_connected then - connect - end - + database_error_handler.reset if attached query as l_query then create l_db_change.make - db_update := l_db_change + db_change := l_db_change l_query.execute_change (l_db_change) - db_control.commit + check_database_change_error end - if not keep_connection then - disconnect - end - set_successful end rescue - set_last_error_from_exception ("Store procedure execution") - log.write_critical (generator+ ".execute_writer " + last_error_message) - if is_connected then - disconnect - end l_retried := True + exception_as_error ((create {EXCEPTION_MANAGER}).last_exception) + if attached db_change as l_change then + l_change.reset + end retry end @@ -207,24 +175,6 @@ feature -- Iteration feature {NONE} -- Implementation - connection: DATABASE_CONNECTION - -- Database connection. - - db_control: DB_CONTROL - -- Database control. - do - Result := connection.db_control - end - - db_result: detachable DB_RESULT - -- Database query result. - - db_selection: detachable DB_SELECTION - -- Database selection. - - db_update: detachable DB_CHANGE - -- Database modification. - last_query: DATE_TIME -- Last time when a query was executed. @@ -263,7 +213,7 @@ feature {NONE} -- Implementation affected_row_count: INTEGER -- The number of rows changed, deleted, or inserted by the last statement. do - if attached db_update as l_update then + if attached db_change as l_update then Result := l_update.affected_row_count end end diff --git a/persistence/implementation/common/database/database_iteration_cursor.e b/persistence/implementation/common/database/database_iteration_cursor.e index f38d844..1688b76 100644 --- a/persistence/implementation/common/database/database_iteration_cursor.e +++ b/persistence/implementation/common/database/database_iteration_cursor.e @@ -1,5 +1,5 @@ note - description: "External iteration cursor for {ESA_DATABASE_HANDLER}" + description: "External iteration cursor for {DATABASE_HANDLER}" date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $" revision: "$Revision: 95678 $" diff --git a/persistence/implementation/common/database/database_null.e b/persistence/implementation/common/database/database_null.e index 9d5dc15..a26437a 100644 --- a/persistence/implementation/common/database/database_null.e +++ b/persistence/implementation/common/database/database_null.e @@ -167,6 +167,7 @@ feature -- LOGIN and DATABASE_APPL only for password_ok password_ok (upasswd: STRING): BOOLEAN -- Can the user password be Void? do + Result := True end password_ensure (name, passwd, uname, upasswd: STRING): BOOLEAN diff --git a/persistence/implementation/common/database/database_query.e b/persistence/implementation/common/database/database_query.e index 1a5f8cd..25088b3 100644 --- a/persistence/implementation/common/database/database_query.e +++ b/persistence/implementation/common/database/database_query.e @@ -8,14 +8,14 @@ class inherit - SHARED_ERROR - REFACTORING_HELPER + SHARED_LOGGER + create data_reader -feature -- Intialization +feature {NONE} -- Intialization data_reader (a_query: STRING; a_parameters: STRING_TABLE [detachable ANY]) -- SQL data reader for the query `a_query' with arguments `a_parameters' @@ -29,6 +29,8 @@ feature -- Intialization parameters_set: parameters = a_parameters end +feature -- Execution + execute_reader (a_base_selection: DB_SELECTION): detachable LIST [DB_RESULT] -- Execute the Current sql query. do @@ -42,7 +44,6 @@ feature -- Intialization a_base_selection.load_result Result := a_base_selection.container else - set_last_error (a_base_selection.error_message_32, generator + ".execute_reader" ) log.write_error (generator + "." + a_base_selection.error_message_32) end unset_map_name (a_base_selection) @@ -50,17 +51,12 @@ feature -- Intialization end execute_change (a_base_change: DB_CHANGE) - -- Execute the Current sql query . + -- Execute the Current sql query to change/update data in the database. do to_implement ("Check test dynamic sequel. to redesign.") set_map_name (a_base_change) a_base_change.set_query (query) a_base_change.execute_query - if a_base_change.is_ok then - else - set_last_error (a_base_change.error_message_32, generator + ".execute_reader" ) - log.write_error (generator + "." + a_base_change.error_message_32) - end unset_map_name (a_base_change) end @@ -72,17 +68,6 @@ feature -- Access parameters: STRING_TABLE [detachable ANY] -- query parameters. -feature -- Status Report - - has_error: BOOLEAN - -- is there an error? - - error_message: detachable STRING_32 - -- Error message if any. - - error_code: INTEGER - -- Error code. - feature {NONE} -- Implementation set_map_name (a_base_selection: DB_EXPRESSION) @@ -140,4 +125,4 @@ feature {NONE} -- Implementation end -end -- ESA_DATABASE_QUERY +end -- DATABASE_QUERY diff --git a/persistence/implementation/common/database/database_storage_manager.e b/persistence/implementation/common/database/database_storage_manager.e deleted file mode 100644 index e59ef5a..0000000 --- a/persistence/implementation/common/database/database_storage_manager.e +++ /dev/null @@ -1,371 +0,0 @@ -note - description: "[ - Manager to initialize data api for database access, - create database connection and so on - ]" - date: "$Date: 2013-08-08 16:39:49 -0300 (ju. 08 de ago. de 2013) $" - revision: "$Revision: 195 $" - -class - DATABASE_STORAGE_MANAGER - -inherit - GLOBAL_SETTINGS - - REFACTORING_HELPER - - SHARED_ERROR_HANDLER - -create - make - -feature -- Initialization - - make (a_data_app: like data_app; a_database_name: like database_name; a_name: like name; a_password: like password; - a_host_name: like host_name; a_role_id: like role_id; a_role_password: like role_password - a_data_source: like data_source; a_group: like group) - -- Initialize with login info. - -- - -- `a_database_name' is used for MySQL - -- `a_name', the login user name - -- `a_password', the login user password, unencrypted. - local - l_storage: STRING_8 - do - create l_storage.make (64) - storage_url := l_storage - l_storage.append (a_data_app.db_spec.database_handle_name.as_lower) - l_storage.append ("://") - - data_app := a_data_app - database_name := a_database_name - name := a_name - password := a_password - host_name := a_host_name - role_id := a_role_id - role_password := a_role_password - data_source := a_data_source - group := a_group - - set_use_extended_types (True) - set_map_zero_null_value (False) - - l_storage.append (a_name.as_string_8) - l_storage.append (":********@") - if a_host_name /= Void then - a_data_app.set_hostname (a_host_name) - l_storage.append (a_host_name) - end - - if a_database_name /= Void then - a_data_app.set_application (a_database_name.as_string_8) - l_storage.append ("/" + a_database_name.as_string_8) - end - - if a_data_source /= Void then - a_data_app.set_data_source (a_data_source) - end - if a_role_id /= Void and then a_role_password /= Void then - a_data_app.set_role (a_role_id, a_role_password) - end - if a_group /= Void then - a_data_app.set_group (a_group) - end - - a_data_app.login (a_name.as_string_8, a_password.as_string_8) - a_data_app.set_base - - create session_control.make - - end - - report_database_schema_incompatibility (a_output: BOOLEAN) - -- Report the application code is not compatible with database schema version - -- if `a_output' is True, write error in io.error as well - require --- incompatible_database_schema_version: not is_database_schema_version_compatible - local - db_v: READABLE_STRING_8 - do --- if attached database_schema_version as v then --- db_v := v.version --- else --- db_v := "?.?.?.?" --- end --- database_error_handler.add_error_details (0, "MISC Error", "Schema version incompatible (application=" --- + database_storage_version.version + " database=" + db_v + ")." --- ) - if a_output then - io.error.put_string (database_error_handler.as_string_representation) - io.error.put_new_line - end - end - -feature -- System Update - - update_system - do --- if is_database_schema_version_compatible then --- misc_manager.initialize_reference_types --- history_manager.initialize_data --- user_role_permission_manager.initialize_built_in_user_role_permission --- user_role_permission_manager.initialize_extra_user_role_permission --- task_manager.initialize_data --- else --- -- If schema incompatible, report it and exit --- report_database_schema_incompatibility (True) --- (create {EXCEPTIONS}).die (-1) --- end - --- [2012-Mars-21] Idea about update system implementation --- if update_version < 01.00.0012 then --- if update_version < 01.00.0005 then --- update_version_01_00_0005 --- end --- update_version_01_00_0012 --- end - end - - reset_storage_manager - do --- initialize_managers (Current) - end - -feature -- Storage - - storage_url: READABLE_STRING_8 - -- Associated storage URL - - storage_connection_kept_alive: BOOLEAN - -- Keep storage connection alive? - -- i.e: never disconnect between 2 transactions. - - keep_storage_connection_alive (b: BOOLEAN) - do - storage_connection_kept_alive := b - end - - connect_storage - -- Connect the database - do - if not session_control.is_connected then - session_control.connect - end - end - - disconnect_from_storage - -- Disconnect from the storage - require - is_connected_to_storage: is_connected_to_storage - do - if not storage_connection_kept_alive then - session_control.disconnect - end - end - - force_disconnect_from_storage - -- Force disconnection from the storage - -- i.e ignore any `storage_connection_kept_alive' - do - if session_control.is_connected then - session_control.disconnect - end - end - - is_connected_to_storage: BOOLEAN - -- Is connected to the database - do - Result := session_control.is_connected - end - -feature -- Transaction Status - - in_transaction_session: BOOLEAN - -- Is session started? - - transaction_session_depth: INTEGER - -- Depth in the transaction session - -feature -- Transaction Operation - - start_transaction_session - -- Start session - -- if already started, increase the `transaction_session_depth' - require - in_transaction_session implies transaction_session_depth > 0 - not in_transaction_session implies transaction_session_depth = 0 - local - l_session_control: like session_control - l_retried: INTEGER - do - if l_retried = 0 then - if not in_transaction_session then - database_error_handler.reset - - check transaction_session_depth = 0 end - - debug ("database_session") - print ("..Start session%N") - end - connect_storage -- connect the DB - if is_connected_to_storage then - in_transaction_session := True - session_control.begin -- start transaction - else - l_session_control := session_control - if not l_session_control.is_ok then - database_error_handler.add_database_error (l_session_control.error_message_32, l_session_control.error_code) - else - database_error_handler.add_database_error (Session_not_started_error_message, 0) - end - l_session_control.reset - end - end - transaction_session_depth := transaction_session_depth + 1 - else - if l_retried = 1 then - transaction_session_depth := transaction_session_depth + 1 - if attached (create {EXCEPTION_MANAGER}).last_exception as e then - if attached {ASSERTION_VIOLATION} e then - --| Ignore for now with MYSQL ... - else - exception_as_error (e) - end - end - - in_transaction_session := False - session_control.reset - else - in_transaction_session := False - end - end - ensure - transaction_session_depth = (old transaction_session_depth) + 1 - rescue - l_retried := l_retried + 1 - retry - end - - end_transaction_session - -- End session - local - l_retried: BOOLEAN - do - if not l_retried then - transaction_session_depth := transaction_session_depth - 1 - if transaction_session_depth = 0 then - debug ("database_session") - print ("..End session%N") - end - if is_connected_to_storage then - if not database_error_handler.has_error then - session_control.commit -- Commit transaction - else - session_control.rollback -- Rollback transaction - end - disconnect_from_storage - end - in_transaction_session := False - end - else - exception_as_error ((create {EXCEPTION_MANAGER}).last_exception) - in_transaction_session := False - transaction_session_depth := transaction_session_depth - 1 - session_control.reset - end - rescue - l_retried := True - retry - end - - execute_query (a_query: STRING_32) - -- Execute `a_q' - require - is_session_started: in_transaction_session - local - rescued: BOOLEAN - l_change: like new_database_change - do - if not rescued then - session_control.reset - l_change := new_database_change - l_change.set_query (a_query) - l_change.execute_query - else - database_error_handler.add_error_details (0, "Unexpected Error", "Unexpected Error when executing query") - end - rescue - rescued := True - retry - end - -feature -- Element Change - - set_last_inserted_id_function (a_f: like last_inserted_id_function) - -- Set `last_inserted_id_function' with `a_f' - do - last_inserted_id_function := a_f - ensure - last_inserted_id_function_set: last_inserted_id_function = a_f - end - -feature -- Access - - database_name: detachable READABLE_STRING_GENERAL - -- Database to access - - name: READABLE_STRING_GENERAL - -- Login user name - - password: READABLE_STRING_8 - -- Password - - host_name: detachable READABLE_STRING_8 - -- Host name, and port if needed - - role_id: detachable READABLE_STRING_8 - -- Role id - - role_password: detachable READABLE_STRING_8 - -- Role password - - data_source: detachable READABLE_STRING_8 - -- Data source - - group: detachable READABLE_STRING_8 - -- Group - - data_app: DATABASE_APPL [DATABASE] - -- Database application - - last_inserted_id_function: detachable FUNCTION [ANY, TUPLE, NATURAL_64] - -- Function to get last inserted id. - -feature -- Factory - - new_database_change: DB_CHANGE - -- Database change - do - create Result.make - end - - new_database_selection: DB_SELECTION - -- Database selection - do - create Result.make - end - - new_procedure (a_name: like {DB_PROC}.name): DB_PROC - -- Database procedure - do - create Result.make (a_name) - end - -feature {NONE} -- Implementation - - session_not_started_error_message: STRING_32 = "Session could not be started for unknown reason" - - session_control: DB_CONTROL - -- Session - -end diff --git a/persistence/implementation/common/database/error/database_error.e b/persistence/implementation/common/database/error/database_error.e new file mode 100644 index 0000000..2dcd646 --- /dev/null +++ b/persistence/implementation/common/database/error/database_error.e @@ -0,0 +1,23 @@ +note + description: "Error from database" + date: "$Date: 2013-08-08 16:39:49 -0300 (ju. 08 de ago. de 2013) $" + revision: "$Revision: 195 $" + +class + DATABASE_ERROR + +inherit + ERROR_CUSTOM + +create + make_from_message + +feature {NONE} -- Init + + make_from_message (a_m: like message; a_code: like code) + -- Create from `a_m' + do + make (a_code, once "Database Error", a_m) + end + +end diff --git a/persistence/implementation/common/database/database_error_handler.e b/persistence/implementation/common/database/error/database_error_handler.e similarity index 60% rename from persistence/implementation/common/database/database_error_handler.e rename to persistence/implementation/common/database/error/database_error_handler.e index a2718fe..5af3545 100644 --- a/persistence/implementation/common/database/database_error_handler.e +++ b/persistence/implementation/common/database/error/database_error_handler.e @@ -15,21 +15,21 @@ create feature -- Error operation add_database_error (a_message: READABLE_STRING_32; a_code: INTEGER) - -- Add a database error + -- Add a database error. local --- l_error: DATABASE_ERROR + l_error: DATABASE_ERROR do --- create l_error.make_from_message (a_message, a_code) --- add_error (l_error) + create l_error.make_from_message (a_message, a_code) + add_error (l_error) end add_database_no_change_error (a_message: READABLE_STRING_32; a_code: INTEGER) - -- Add a database error + -- Add a database error. local --- l_error: DATABASE_NO_CHANGE_ERROR + l_error: DATABASE_NO_CHANGE_ERROR do --- create l_error.make_from_message (a_message, a_code) --- add_error (l_error) + create l_error.make_from_message (a_message, a_code) + add_error (l_error) end end diff --git a/persistence/implementation/common/database/error/database_no_change_error.e b/persistence/implementation/common/database/error/database_no_change_error.e new file mode 100644 index 0000000..6855279 --- /dev/null +++ b/persistence/implementation/common/database/error/database_no_change_error.e @@ -0,0 +1,27 @@ +note + description: "Summary description for {DATABASE_NO_CHANGE_ERROR}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + DATABASE_NO_CHANGE_ERROR + +inherit + DATABASE_ERROR + redefine + make_from_message + end + +create + make_from_message + +feature {NONE} -- Init + + make_from_message (a_m: like message; a_code: like code) + -- Create from `a_m' + do + make (a_code, once "Database No Change Error", a_m) + end + +end diff --git a/persistence/implementation/common/database/shared_error_handler.e b/persistence/implementation/common/database/shared_error_handler.e deleted file mode 100644 index 9c26bfd..0000000 --- a/persistence/implementation/common/database/shared_error_handler.e +++ /dev/null @@ -1,27 +0,0 @@ -note - description: "Shared error handler for database" - date: "$Date: 2013-08-08 16:39:49 -0300 (ju. 08 de ago. de 2013) $" - revision: "$Revision: 195 $" - -class - SHARED_ERROR_HANDLER - -feature -- Access - - database_error_handler: DATABASE_ERROR_HANDLER - -- Error handler - once - create Result.make - end - -feature -- Helper - - exception_as_error (a_e: like {EXCEPTION_MANAGER}.last_exception) - -- Record exception as an error. - do - if attached a_e as l_e and then attached l_e.exception_trace as l_trace then - database_error_handler.add_error_details (l_e.code, once "Exception", l_trace.as_string_32) - end - end - -end diff --git a/persistence/implementation/mysql/persistence_mysql-safe.ecf b/persistence/implementation/mysql/persistence_mysql-safe.ecf index 6811629..9d99a01 100644 --- a/persistence/implementation/mysql/persistence_mysql-safe.ecf +++ b/persistence/implementation/mysql/persistence_mysql-safe.ecf @@ -13,6 +13,7 @@ + diff --git a/persistence/implementation/mysql/src/cms_storage_mysql.e b/persistence/implementation/mysql/src/cms_storage_mysql.e index 74a72ce..62422aa 100644 --- a/persistence/implementation/mysql/src/cms_storage_mysql.e +++ b/persistence/implementation/mysql/src/cms_storage_mysql.e @@ -21,11 +21,11 @@ feature {NONE} -- Initialization require is_connected: a_connection.is_connected do + connection := a_connection log.write_information (generator+".make_with_database is database connected? "+ a_connection.is_connected.out ) create node_provider.make (a_connection) create user_provider.make (a_connection) - post_node_provider_execution - post_user_provider_execution + create error_handler.make end @@ -35,7 +35,6 @@ feature -- Access: user -- Has any user? do Result := user_provider.has_user - post_user_provider_execution end all_users: LIST [CMS_USER] @@ -47,19 +46,19 @@ feature -- Access: user user_by_id (a_id: like {CMS_USER}.id): detachable CMS_USER do Result := user_provider.user (a_id) - post_user_provider_execution + end user_by_name (a_name: like {CMS_USER}.name): detachable CMS_USER do Result := user_provider.user_by_name (a_name) - post_user_provider_execution + end user_by_email (a_email: like {CMS_USER}.email): detachable CMS_USER do Result := user_provider.user_by_email (a_email) - post_user_provider_execution + end is_valid_credential (l_auth_login, l_auth_password: READABLE_STRING_32): BOOLEAN @@ -81,7 +80,7 @@ feature -- Access: user log.write_information (generator + ".login_valid User:" + l_auth_login + "does not exist" ) end end - post_user_provider_execution + end feature -- User Nodes @@ -125,13 +124,15 @@ feature -- Change: user save_user (a_user: CMS_USER) -- Add a new user `a_user'. do + if attached a_user.password as l_password and then attached a_user.email as l_email then + connection.begin_transaction user_provider.new_user (a_user.name, l_password, l_email) + connection.commit else - set_last_error ("User or Password not attached", generator + ".save_user") end end @@ -144,7 +145,7 @@ feature -- Access: node across node_provider.nodes as c loop Result.force (c.item) end - post_node_provider_execution + end recent_nodes (a_lower: INTEGER; a_count: INTEGER): LIST [CMS_NODE] @@ -154,21 +155,21 @@ feature -- Access: node across node_provider.recent_nodes (a_lower,a_count) as c loop Result.force (c.item) end - post_node_provider_execution + end node (a_id: INTEGER_64): detachable CMS_NODE -- do Result := node_provider.node (a_id) - post_node_provider_execution + end node_author (a_id: like {CMS_NODE}.id): detachable CMS_USER -- do Result := node_provider.node_author (a_id) - post_node_provider_execution + end node_collaborators (a_id: like {CMS_NODE}.id): LIST [CMS_USER] @@ -184,21 +185,21 @@ feature -- Node -- do node_provider.new_node (a_node) - post_node_provider_execution + end delete_node (a_id: INTEGER_64) do node_provider.delete_from_user_nodes(a_id) node_provider.delete_node (a_id) - post_node_provider_execution + end update_node (a_id: like {CMS_USER}.id; a_node: CMS_NODE) -- do node_provider.update_node (a_id, a_node) - post_node_provider_execution + end update_node_title (a_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_title: READABLE_STRING_32) @@ -206,7 +207,7 @@ feature -- Node do node_provider.update_node_title (a_node_id, a_title) internal_node_update (a_id, a_node_id) - post_node_provider_execution + end update_node_summary (a_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_summary: READABLE_STRING_32) @@ -214,7 +215,7 @@ feature -- Node do node_provider.update_node_summary (a_node_id, a_summary) internal_node_update (a_id, a_node_id) - post_node_provider_execution + end update_node_content (a_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_content: READABLE_STRING_32) @@ -222,7 +223,7 @@ feature -- Node do node_provider.update_node_content (a_node_id, a_content) internal_node_update (a_id, a_node_id) - post_node_provider_execution + end feature {NONE} -- NODE Implemenation @@ -254,27 +255,6 @@ feature -- User feature {NONE} -- Post process - post_node_provider_execution - do - if node_provider.successful then - set_successful - else - if attached node_provider.last_error then - set_last_error_from_handler (node_provider.last_error) - end - end - end - - post_user_provider_execution - do - if user_provider.successful then - set_successful - else - if attached user_provider.last_error then - set_last_error_from_handler (user_provider.last_error) - end - end - end node_provider: NODE_DATA_PROVIDER -- Node Data provider. @@ -282,4 +262,6 @@ feature {NONE} -- Post process user_provider: USER_DATA_PROVIDER -- User Data provider. + connection: DATABASE_CONNECTION + -- Current database connection. end diff --git a/persistence/implementation/mysql/src/database/database_connection_mysql.e b/persistence/implementation/mysql/src/database/database_connection_mysql.e index bc5f890..05776f6 100644 --- a/persistence/implementation/mysql/src/database/database_connection_mysql.e +++ b/persistence/implementation/mysql/src/database/database_connection_mysql.e @@ -23,6 +23,7 @@ feature -- Initialization local l_retried: BOOLEAN do + create database_error_handler.make create db_application.login (username, password) if not l_retried then @@ -34,17 +35,12 @@ feature -- Initialization if keep_connection then connect end - set_successful else create db_control.make end rescue - create db_control.make - set_last_error_from_exception ("Connection execution") - log.write_critical (generator + ".make_common:" + last_error_message) - if is_connected then - disconnect - end + create database_error_handler.make + exception_as_error ((create {EXCEPTION_MANAGER}).last_exception) l_retried := True retry end @@ -55,6 +51,7 @@ feature -- Initialization local l_retried: BOOLEAN do + create database_error_handler.make create db_application.login (username, password) if not l_retried then @@ -66,17 +63,12 @@ feature -- Initialization if keep_connection then connect end - set_successful else create db_control.make end rescue - create db_control.make - set_last_error_from_exception ("Connection execution") - log.write_critical (generator + ".make_common:" + last_error_message) - if is_connected then - disconnect - end + create database_error_handler.make + exception_as_error ((create {EXCEPTION_MANAGER}).last_exception) l_retried := True retry end @@ -88,6 +80,7 @@ feature -- Initialization -- `database_name' to `a_database_name' -- `connection' to `a_connection' do + create database_error_handler.make create db_application.login (a_username, a_password) db_application.set_hostname (a_hostname) db_application.set_data_source (a_database_name) @@ -109,6 +102,8 @@ feature -- Initialization l_user: STRING l_password: STRING do + create database_error_handler.make + l_string := a_string.split (';') l_server := l_string.at (2).split ('=').at (2) l_port := l_string.at (3).split ('=').at (2) @@ -123,12 +118,12 @@ feature -- Initialization db_application.set_base create db_control.make keep_connection := is_keep_connection - end login_with_schema (a_schema: STRING; a_username: STRING; a_password: STRING) -- Login with `a_connection_string'and immediately connect to database. do + create database_error_handler.make create db_application db_application.set_application (a_schema) db_application.login_and_connect (a_username, a_password) diff --git a/persistence/implementation/mysql/src/provider/node_data_provider.e b/persistence/implementation/mysql/src/provider/node_data_provider.e index 3bcfc84..5951cc5 100644 --- a/persistence/implementation/mysql/src/provider/node_data_provider.e +++ b/persistence/implementation/mysql/src/provider/node_data_provider.e @@ -10,10 +10,10 @@ inherit PARAMETER_NAME_HELPER - SHARED_ERROR - REFACTORING_HELPER + SHARED_LOGGER + create make @@ -23,6 +23,7 @@ feature -- Initialization -- Create a data provider. do create {DATABASE_HANDLER_IMPL} db_handler.make (a_connection) + create error_handler.make post_execution end @@ -34,9 +35,13 @@ feature -- Status Report is_successful: BOOLEAN -- Is the last execution sucessful? do - Result := db_handler.successful + Result := not error_handler.has_error end +feature -- Error Handler + + error_handler: ERROR_HANDLER + feature -- Access nodes: DATABASE_ITERATION_CURSOR [CMS_NODE] @@ -44,6 +49,7 @@ feature -- Access local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".nodes") create l_parameters.make (0) db_handler.set_query (create {DATABASE_QUERY}.data_reader (Select_nodes, l_parameters)) @@ -58,6 +64,7 @@ feature -- Access l_parameters: STRING_TABLE [ANY] l_query: STRING do + error_handler.reset log.write_information (generator + ".recent_nodes") create l_parameters.make (2) l_parameters.put (a_rows, "rows") @@ -74,6 +81,7 @@ feature -- Access local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".node") create l_parameters.make (1) l_parameters.put (a_id,"id") @@ -90,6 +98,7 @@ feature -- Access local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".count") create l_parameters.make (0) db_handler.set_query (create {DATABASE_QUERY}.data_reader (select_count, l_parameters)) @@ -106,6 +115,7 @@ feature -- Access local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".last_inserted_node_id") create l_parameters.make (0) db_handler.set_query (create {DATABASE_QUERY}.data_reader (Sql_last_insert_node_id, l_parameters)) @@ -123,6 +133,7 @@ feature -- Basic operations local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".new_node") create l_parameters.make (7) l_parameters.put (a_node.title, "title") @@ -141,10 +152,7 @@ feature -- Basic operations db_handler.execute_change a_node.set_id (last_inserted_node_id) - post_execution - - end update_node_title (a_id: INTEGER_64; a_title: READABLE_STRING_32) @@ -152,6 +160,7 @@ feature -- Basic operations local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".update_node_title") create l_parameters.make (3) l_parameters.put (a_title, "title") @@ -167,6 +176,7 @@ feature -- Basic operations local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".update_node_summary") create l_parameters.make (3) l_parameters.put (a_summary, "summary") @@ -182,6 +192,7 @@ feature -- Basic operations local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".update_node_content") create l_parameters.make (3) l_parameters.put (a_content, "content") @@ -197,6 +208,7 @@ feature -- Basic operations local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".update_node") create l_parameters.make (7) l_parameters.put (a_node.title, "title") @@ -216,6 +228,7 @@ feature -- Basic operations local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".delete_node") create l_parameters.make (1) l_parameters.put (a_id, "id") @@ -228,6 +241,7 @@ feature -- Basic operations local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".delete_from_user_nodes") create l_parameters.make (1) l_parameters.put (a_id, "id") @@ -243,6 +257,7 @@ feature -- Basic Operations: User_Nodes local l_parameters: STRING_TABLE [detachable ANY] do + error_handler.reset log.write_information (generator + ".add_author") create l_parameters.make (2) l_parameters.put (a_user_id,"user_id") @@ -257,6 +272,7 @@ feature -- Basic Operations: User_Nodes local l_parameters: STRING_TABLE [detachable ANY] do + error_handler.reset log.write_information (generator + ".add_collaborator") create l_parameters.make (2) l_parameters.put (a_user_id,"users_id") @@ -271,6 +287,7 @@ feature -- Basic Operations: User_Nodes local l_parameters: STRING_TABLE [detachable ANY] do + error_handler.reset log.write_information (generator + ".add_collaborator") create l_parameters.make (2) l_parameters.put (a_user_id,"users_id") @@ -286,6 +303,7 @@ feature -- Basic Operations: User_Nodes local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".author_nodes") create l_parameters.make (1) l_parameters.put (a_id, "user_id") @@ -300,6 +318,7 @@ feature -- Basic Operations: User_Nodes local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".collaborator_nodes") create l_parameters.make (1) l_parameters.put (a_id, "user_id") @@ -315,6 +334,7 @@ feature -- Basic Operations: User_Nodes local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".node_author") create l_parameters.make (1) l_parameters.put (a_id, "node_id") @@ -331,6 +351,7 @@ feature -- Basic Operations: User_Nodes local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".node_collaborators") create l_parameters.make (1) l_parameters.put (a_id, "node_id") @@ -345,6 +366,7 @@ feature -- Basic Operations: User_Nodes local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".node_collaborators") create l_parameters.make (2) l_parameters.put (a_user_id, "user_id") @@ -354,7 +376,6 @@ feature -- Basic Operations: User_Nodes if db_handler.count = 1 then Result := db_handler.read_integer_32 (1) = 1 end - post_execution end @@ -481,12 +502,9 @@ feature {NONE} -- Implementation post_execution -- Post database execution. do - if db_handler.successful then - set_successful - else - if attached db_handler.last_error then - set_last_error_from_handler (db_handler.last_error) - end + error_handler.add_synchronization (db_handler.database_error_handler) + if error_handler.has_error then + log.write_critical (generator + ".post_execution " + error_handler.as_string_representation) end end diff --git a/persistence/implementation/mysql/src/provider/role_data_provider.e b/persistence/implementation/mysql/src/provider/role_data_provider.e index 61590a0..8e82a64 100644 --- a/persistence/implementation/mysql/src/provider/role_data_provider.e +++ b/persistence/implementation/mysql/src/provider/role_data_provider.e @@ -35,7 +35,7 @@ feature -- Status Report is_successful: BOOLEAN -- Is the last execution sucessful? do - Result := db_handler.successful +-- Result := db_handler.successful end has_roles: BOOLEAN @@ -210,13 +210,7 @@ feature {NONE} -- Implementation post_execution -- Post database execution. do - if db_handler.successful then - set_successful - else - if attached db_handler.last_error then - set_last_error_from_handler (db_handler.last_error) - end - end + end end diff --git a/persistence/implementation/mysql/src/provider/user_data_provider.e b/persistence/implementation/mysql/src/provider/user_data_provider.e index a1ac47b..8660b8e 100644 --- a/persistence/implementation/mysql/src/provider/user_data_provider.e +++ b/persistence/implementation/mysql/src/provider/user_data_provider.e @@ -10,10 +10,10 @@ inherit PARAMETER_NAME_HELPER - SHARED_ERROR - REFACTORING_HELPER + SHARED_LOGGER + create make @@ -23,18 +23,24 @@ feature -- Initialization -- Create a data provider. do create {DATABASE_HANDLER_IMPL} db_handler.make (a_connection) + create error_handler.make post_execution end db_handler: DATABASE_HANDLER -- Db handler. +feature -- Error Handler + + error_handler: ERROR_HANDLER + + feature -- Status Report is_successful: BOOLEAN -- Is the last execution sucessful? do - Result := db_handler.successful + Result := not error_handler.has_error end has_user: BOOLEAN @@ -52,6 +58,7 @@ feature -- Basic Operations l_password_salt, l_password_hash: STRING l_security: SECURITY_PROVIDER do + error_handler.reset create l_security l_password_salt := l_security.salt l_password_hash := l_security.password_hash (a_password, l_password_salt) @@ -72,6 +79,7 @@ feature -- Basic Operations local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".user") create l_parameters.make (1) l_parameters.put (a_id,"id") @@ -88,6 +96,7 @@ feature -- Basic Operations local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".user_by_name") create l_parameters.make (1) l_parameters.put (a_name,"name") @@ -105,6 +114,7 @@ feature -- Basic Operations local l_parameters: STRING_TABLE [detachable ANY] do + error_handler.reset log.write_information (generator + ".user_by_email") create l_parameters.make (1) l_parameters.put (a_email,"email") @@ -121,6 +131,7 @@ feature -- Basic Operations local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".user_salt") create l_parameters.make (1) l_parameters.put (a_username,"name") @@ -139,6 +150,7 @@ feature -- Basic Operations local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".count") create l_parameters.make (0) db_handler.set_query (create {DATABASE_QUERY}.data_reader (select_count, l_parameters)) @@ -156,6 +168,7 @@ feature -- Basic operations: User Roles local l_parameters: STRING_TABLE [detachable ANY] do + error_handler.reset log.write_information (generator + ".add_role") create l_parameters.make (2) l_parameters.put (a_user_id,"users_id") @@ -170,6 +183,7 @@ feature -- Basic operations: User Roles local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".user_roles") create l_parameters.make (1) l_parameters.put (a_id, "user_id") @@ -187,6 +201,7 @@ feature -- Basic operations: User Profiles local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".save_profile_item") create l_parameters.make (3) l_parameters.put (a_key, "key") @@ -202,6 +217,7 @@ feature -- Basic operations: User Profiles local l_cursor: TABLE_ITERATION_CURSOR [READABLE_STRING_8, READABLE_STRING_8] do + error_handler.reset log.write_information (generator + ".save_profile") from l_cursor := a_user_profile.new_cursor @@ -220,6 +236,7 @@ feature -- Basic operations: User Profiles local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".user_profile") create l_parameters.make (1) l_parameters.put (a_user_id, "users_id") @@ -311,12 +328,9 @@ feature {NONE} -- Implementation post_execution -- Post database execution. do - if db_handler.successful then - set_successful - else - if attached db_handler.last_error then - set_last_error_from_handler (db_handler.last_error) - end + error_handler.add_synchronization (db_handler.database_error_handler) + if error_handler.has_error then + log.write_critical (generator + ".post_execution " + error_handler.as_string_representation) end end diff --git a/persistence/implementation/mysql/tests/handler/database_handler_test.e b/persistence/implementation/mysql/tests/handler/database_handler_test.e new file mode 100644 index 0000000..6ae64b4 --- /dev/null +++ b/persistence/implementation/mysql/tests/handler/database_handler_test.e @@ -0,0 +1,81 @@ +note + description: "[ + Eiffel tests that can be executed by testing tool. + ]" + author: "EiffelStudio test wizard" + date: "$Date$" + revision: "$Revision$" + testing: "type/manual" + +class + DATABASE_HANDLER_TEST + +inherit + EQA_TEST_SET + redefine + on_prepare, + on_clean + select + default_create + end + ABSTRACT_DB_TEST + rename + default_create as default_db_test + end + + +feature {NONE} -- Events + + on_prepare + -- + do + (create {CLEAN_DB}).clean_db(connection) + end + + on_clean + -- + do + end + + +feature -- Test routines + + test_wrong_database_query + -- New test routine + local + l_parameters: STRING_TABLE[detachable ANY] + do + create l_parameters.make (0) + handler.set_query (create {DATABASE_QUERY}.data_reader ("Sellect from users", l_parameters)) + handler.execute_query + assert ("Has error:", handler.has_error) + end + + + + test_sequences_of_wrong_and_correct_queries + -- New test routine + local + l_parameters: STRING_TABLE[detachable ANY] + do + create l_parameters.make (0) + handler.set_query (create {DATABASE_QUERY}.data_reader ("Sellect from users;", l_parameters)) + handler.execute_query + assert ("Has error:", handler.has_error) + + handler.set_query (create {DATABASE_QUERY}.data_reader ("Select * from users;", l_parameters)) + handler.execute_query + assert ("Not Has error:",not handler.has_error) + end + + +feature -- Handler + + handler: DATABASE_HANDLER + once + create {DATABASE_HANDLER_IMPL} Result.make (connection ) + end + +end + + diff --git a/persistence/implementation/mysql/tests/nodes/node_test_set.e b/persistence/implementation/mysql/tests/nodes/node_test_set.e index 7993a72..9b3b442 100644 --- a/persistence/implementation/mysql/tests/nodes/node_test_set.e +++ b/persistence/implementation/mysql/tests/nodes/node_test_set.e @@ -41,7 +41,9 @@ feature {NONE} -- Events feature -- Test routines test_new_node - do + note + testing: "execution/isolated" + do assert ("Empty Nodes", node_provider.nodes.after) node_provider.new_node (default_node) assert ("Not empty Nodes after new_node", not node_provider.nodes.after) @@ -53,6 +55,8 @@ feature -- Test routines test_update_node + note + testing: "execution/isolated" local l_node: CMS_NODE do @@ -85,6 +89,8 @@ feature -- Test routines end test_update_title + note + testing: "execution/isolated" local l_node: CMS_NODE do @@ -104,6 +110,8 @@ feature -- Test routines end test_update_summary + note + testing: "execution/isolated" local l_node: CMS_NODE do @@ -123,11 +131,14 @@ feature -- Test routines end test_update_content + note + testing: "execution/isolated" local l_node: CMS_NODE do assert ("Empty Nodes", node_provider.nodes.after) l_node := custom_node ("

    test node udpate

    ", "Update node", "Test case update") + connection.begin_transaction node_provider.new_node (l_node) assert ("Not empty Nodes after new_node", not node_provider.nodes.after) -- Exist node with id 1 @@ -139,6 +150,7 @@ feature -- Test routines node_provider.update_node_content (l_un.id,"New Content") assert ("Exist node with id 1", attached {CMS_NODE} node_provider.node (1) as ll_node and then not (ll_node.content ~ l_un.content) and then ll_node.content ~ "New Content" and then ll_node.summary ~ l_un.summary and then ll_node.title ~ l_un.title) end + connection.commit end diff --git a/persistence/implementation/mysql/tests/tests.ecf b/persistence/implementation/mysql/tests/tests.ecf index 363c33c..abe2c75 100644 --- a/persistence/implementation/mysql/tests/tests.ecf +++ b/persistence/implementation/mysql/tests/tests.ecf @@ -7,6 +7,7 @@ + diff --git a/persistence/implementation/mysql/tests/transactions/transaction_test_set.e b/persistence/implementation/mysql/tests/transactions/transaction_test_set.e new file mode 100644 index 0000000..4abdd8c --- /dev/null +++ b/persistence/implementation/mysql/tests/transactions/transaction_test_set.e @@ -0,0 +1,97 @@ +note + description: "[ + Eiffel tests that can be executed by testing tool. + ]" + author: "EiffelStudio test wizard" + date: "$Date$" + revision: "$Revision$" + testing: "type/manual" + +class + TRANSACTION_TEST_SET + +inherit + + EQA_TEST_SET + redefine + on_prepare, + on_clean + select + default_create + end + ABSTRACT_DB_TEST + rename + default_create as default_db_test + end + + +feature {NONE} -- Events + + on_prepare + -- + do + (create {CLEAN_DB}).clean_db(connection) + end + + on_clean + -- + do + end + +feature -- Test routines + + test_user_rollback + note + testing: "execution/isolated" + do + connection.begin_transaction + user_provider.new_user ("test", "test","test@admin.com") + assert ("Has user:", user_provider.has_user) + connection.rollback + assert ("Not has user:", not user_provider.has_user) + end + + test_user_node_rollback + note + testing: "execution/isolated" + do + connection.begin_transaction + user_provider.new_user ("test", "test","test@admin.com") + assert ("Has user:", user_provider.has_user) + node_provider.new_node (default_node) + node_provider.add_author (1, 1) + assert ("Has one node:", node_provider.count = 1) + connection.rollback + assert ("Not has user:", not user_provider.has_user) + assert ("Not has nodes:", node_provider.count = 0) + end + +feature {NONE} -- Implementation + + node_provider: NODE_DATA_PROVIDER + -- node provider. + once + create Result.make (connection) + end + + user_provider: USER_DATA_PROVIDER + -- user provider. + once + create Result.make (connection) + end + + +feature {NONE} -- Implementation Fixture Factories + + default_node: CMS_NODE + do + Result := custom_node ("Default content", "default summary", "Default") + end + + custom_node (a_content, a_summary, a_title: READABLE_STRING_32): CMS_NODE + do + create Result.make (a_content, a_summary, a_title) + end +end + + diff --git a/persistence/implementation/mysql/tests/util/clean_db.e b/persistence/implementation/mysql/tests/util/clean_db.e index 965465f..dce7176 100644 --- a/persistence/implementation/mysql/tests/util/clean_db.e +++ b/persistence/implementation/mysql/tests/util/clean_db.e @@ -24,6 +24,7 @@ feature do create l_parameters.make (0) + a_connection.begin_transaction -- Clean Profiles db_handler(a_connection).set_query (create {DATABASE_QUERY}.data_reader (Sql_delete_user_profiles, l_parameters)) @@ -72,6 +73,7 @@ feature db_handler(a_connection).set_query (create {DATABASE_QUERY}.data_reader (Rest_profiles_autoincrement, l_parameters)) db_handler(a_connection).execute_change + a_connection.commit end diff --git a/persistence/interface/cms_storage.e b/persistence/interface/cms_storage.e index eb5a44a..234613d 100644 --- a/persistence/interface/cms_storage.e +++ b/persistence/interface/cms_storage.e @@ -11,7 +11,7 @@ deferred class inherit - SHARED_ERROR + SHARED_LOGGER feature {NONE} -- Initialization @@ -19,6 +19,11 @@ feature {NONE} -- Initialization do end +feature -- Error Handling + + error_handler: ERROR_HANDLER + -- Error handler. + feature -- Access: user has_user: BOOLEAN