note description: "[ Module that provide contact us web form functionality. ]" author: "$Author$" date: "$Date$" revision: "$Revision$" class CONTACT_MODULE inherit CMS_MODULE redefine register_hooks end SHARED_HTML_ENCODER CMS_HOOK_BLOCK CMS_HOOK_BLOCK_HELPER CMS_HOOK_AUTO_REGISTER CMS_HOOK_MENU_SYSTEM_ALTER SHARED_EXECUTION_ENVIRONMENT export {NONE} all end REFACTORING_HELPER SHARED_LOGGER create make feature {NONE} -- Initialization make -- Create current module do name := "contact" version := "1.0" description := "Contact form module" package := "messaging" end feature -- Router router (a_api: CMS_API): WSF_ROUTER -- Router configuration. do create Result.make (0) Result.handle_with_request_methods ("/contact", create {WSF_URI_AGENT_HANDLER}.make (agent handle_contact (a_api, ?, ?)), Result.methods_head_get) Result.handle_with_request_methods ("/contact", create {WSF_URI_AGENT_HANDLER}.make (agent handle_post_contact (a_api, ?, ?)), Result.methods_put_post) end feature -- Recaptcha recaptcha_secret_key (api: CMS_API): detachable READABLE_STRING_8 -- Get recaptcha security key. local utf: UTF_CONVERTER do if attached api.module_configuration (name, Void) as cfg then if attached cfg.text_item ("recaptcha.secret_key") as l_recaptcha_key and then not l_recaptcha_key.is_empty then Result := utf.utf_32_string_to_utf_8_string_8 (l_recaptcha_key) end end end recaptcha_site_key (api: CMS_API): detachable READABLE_STRING_8 -- Get recaptcha security key. local utf: UTF_CONVERTER do if attached api.module_configuration (name, Void) as cfg then if attached cfg.text_item ("recaptcha.site_key") as l_recaptcha_key and then not l_recaptcha_key.is_empty then Result := utf.utf_32_string_to_utf_8_string_8 (l_recaptcha_key) end end end feature -- Hooks configuration register_hooks (a_response: CMS_RESPONSE) -- Module hooks configuration. do auto_subscribe_to_hooks (a_response) a_response.subscribe_to_block_hook (Current) end feature -- Hooks menu_system_alter (a_menu_system: CMS_MENU_SYSTEM; a_response: CMS_RESPONSE) -- Hook execution on collection of menu contained by `a_menu_system' -- for related response `a_response'. do debug ("refactor_fixme") fixme ("add /contact to menu") end end block_list: ITERABLE [like {CMS_BLOCK}.name] do Result := <<"contact", "post_contact">> end get_block_view (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE) local l_path_info: READABLE_STRING_8 do l_path_info := a_response.request.percent_encoded_path_info -- "contact", "post_contact" if a_block_id.is_case_insensitive_equal_general ("contact") and then l_path_info.starts_with ("/contact") and then a_response.request.is_get_request_method then if attached template_block (Current, a_block_id, a_response) as l_tpl_block then if attached recaptcha_site_key (a_response.api) as l_recaptcha_site_key then l_tpl_block.set_value (l_recaptcha_site_key, "recaptcha_site_key") end a_response.add_block (l_tpl_block, "content") log.write_debug (generator + ".get_block_view with template_block:" + l_tpl_block.out) else debug ("cms") a_response.add_warning_message ("Error with block [" + a_block_id + "]") end end elseif a_block_id.is_case_insensitive_equal_general ("post_contact") and then l_path_info.starts_with ("/contact") then if attached template_block (Current, a_block_id, a_response) as l_tpl_block then -- l_tpl_block.set_value (a_response.values.item ("has_error"), "has_error") -- a_response.add_block (l_tpl_block, "content") -- log.write_debug (generator + ".get_block_view with template_block:" + l_tpl_block.out) else debug ("cms") a_response.add_warning_message ("Error with block [" + a_block_id + "]") end end end end handle_contact (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE) local r: CMS_RESPONSE do -- FIXME: we should use WSF_FORM, and integrate the recaptcha using the form alter hook. log.write_debug (generator + ".handle_contact") create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) r.values.force ("contact", "contact") r.execute end handle_post_contact (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE) local r: CMS_RESPONSE es: CONTACT_EMAIL_SERVICE m: STRING um: STRING l_captcha_passed: BOOLEAN do log.write_information (generator + ".handle_post_contact") create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api) r.values.force (False, "has_error") log.write_debug (generator + ".handle_post_contact {Form Parameters:" + print_form_parameters (req) +"}") if attached {WSF_STRING} req.form_parameter ("name") as l_name and then attached {WSF_STRING} req.form_parameter ("email") as l_email and then attached {WSF_STRING} req.form_parameter ("message") as l_message then if attached recaptcha_secret_key (api) as l_recaptcha_key then if attached {WSF_STRING} req.form_parameter ("g-recaptcha-response") as l_recaptcha_response and then is_captcha_verified (l_recaptcha_key, l_recaptcha_response.value) then l_captcha_passed := True else --| Bad or missing captcha l_captcha_passed := False end else --| reCaptcha is not setup, so no verification l_captcha_passed := True end if l_captcha_passed then create m.make_from_string (email_template ("email", r)) log.write_information (generator + ".handle_post_contact: preparing the message:" + html_encoded (contact_message (r))) create es.make (create {CONTACT_EMAIL_SERVICE_PARAMETERS}.make (api)) log.write_debug (generator + ".handle_post_contact: send_contact_email") es.send_contact_email (l_email.value, m) create um.make_from_string (user_contact) um.replace_substring_all ("$name", html_encoded (l_name.value)) um.replace_substring_all ("$email", html_encoded (l_email.value)) um.replace_substring_all ("$message", html_encoded (l_message.value)) log.write_debug (generator + ".handle_post_contact: send_internal_email") es.send_internal_email (um) if attached es.last_error then log.write_error (generator + ".handle_post_contact: error message:["+ es.last_error_message +"]") r.set_status_code ({HTTP_CONSTANTS}.internal_server_error) r.values.force (True, "has_error") if attached template_block (Current, "post_contact", r) as l_tpl_block then l_tpl_block.set_value (r.values.item ("has_error"), "has_error") r.set_main_content (l_tpl_block.to_html(r.theme)) end else if attached template_block (Current, "post_contact", r) as l_tpl_block then r.set_main_content (l_tpl_block.to_html (r.theme)) end end r.execute else -- send a bad request status code and redisplay the form with the previous data loaded. r.set_value (False, "error") r.set_status_code ({HTTP_STATUS_CODE}.bad_request) if attached template_block (Current, "contact", r) as l_tpl_block then l_tpl_block.set_value (l_name.value, "name") l_tpl_block.set_value (l_email.value, "email") l_tpl_block.set_value (l_message.value, "message") if attached recaptcha_site_key (api) as l_recaptcha_site_key then l_tpl_block.set_value (l_recaptcha_site_key, "recaptcha_site_key") l_tpl_block.set_value (<<"Missing Captcha", "Internal Server Error">>, "error_response") end r.set_main_content (l_tpl_block.to_html (r.theme)) else debug ("cms") r.add_warning_message ("Error with block [contact]") end end r.execute end else -- Internal server error log.write_error (generator + ".handle_post_contact: Internal Server error") r.values.force (True, "has_error") r.set_status_code ({HTTP_CONSTANTS}.internal_server_error) if attached template_block (Current, "post_contact", r) as l_tpl_block then l_tpl_block.set_value (r.values.item ("has_error"), "has_error") r.set_main_content (l_tpl_block.to_html (r.theme)) end r.execute end end feature {NONE} -- Helpers print_form_parameters (req: WSF_REQUEST): STRING do create Result.make_empty across req.form_parameters as ic loop Result.append (ic.item.key) Result.append_character ('=') if attached {WSF_STRING} req.form_parameter (ic.item.key) as l_value then Result.append_string (l_value.value) elseif attached {WSF_MULTIPLE_STRING} req.form_parameter (ic.item.key) as l_value then Result.append_character ('[') Result.append_string (l_value.string_representation) Result.append_character (']') end Result.append_character ('%N') end end feature {NONE} -- HTML ENCODING. html_encoded (s: detachable READABLE_STRING_GENERAL): STRING_8 do if s /= Void then Result := html_encoder.general_encoded_string (s) else create Result.make_empty end end feature {NONE} -- Contact Message email_template (a_template: READABLE_STRING_8; a_response: CMS_RESPONSE): STRING -- Smarty email template. local p: detachable PATH l_block: CMS_SMARTY_TEMPLATE_BLOCK do log.write_debug (generator + ".email_template with template [" + a_template + " ]") create p.make_from_string ("templates") p := p.extended ("email_").appended (a_template).appended_with_extension ("tpl") p := a_response.module_resource_path (Current, p) if p /= Void then if attached p.entry as e then create l_block.make (a_template, Void, p.parent, e) log.write_debug (generator + ".email_template with template_block:" + l_block.out) else create l_block.make (a_template, Void, p.parent, p) log.write_debug (generator + ".email_template with template_block:" + l_block.out) end Result := l_block.to_html (a_response.theme) else Result := contact_message (a_response) log.write_debug (generator + ".email_template without template_block:" + Result) end end contact_message (a_response: CMS_RESPONSE): STRING do Result := "
Thank you for contacting " + html_encoded (a_response.api.setup.site_name) + ".
We will get back to you promptly on your contact request.