Merge branch 'master' into es_17_01
# Conflicts: # examples/demo/demo.ecf # modules/node/node-safe.ecf
This commit is contained in:
@@ -30,6 +30,7 @@
|
||||
<library name="cms_feed_aggregator_module" location="..\..\modules\feed_aggregator\feed_aggregator.ecf" readonly="false"/>
|
||||
<library name="cms_files_module" location="..\..\modules\files\files.ecf" readonly="false"/>
|
||||
<library name="cms_google_search_module" location="..\..\modules\google_search\google_search.ecf" readonly="false" use_application_options="true"/>
|
||||
<library name="cms_messaging_module" location="..\..\modules\messaging\messaging.ecf"/>
|
||||
<library name="cms_model" location="..\..\library\model\cms_model.ecf" readonly="false"/>
|
||||
<library name="cms_node_module" location="..\..\modules\node\node.ecf" readonly="false"/>
|
||||
<library name="cms_oauth_20_module" location="..\..\modules\oauth20\oauth20.ecf" readonly="false"/>
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
"files": { "location": "../../modules/files" },
|
||||
"custom_block": { "location": "../../modules/custom_block" },
|
||||
"wikitext": { "location": "../../modules/wikitext" },
|
||||
"messaging": { "location": "../../modules/messaging" },
|
||||
"comments": { "location": "../../modules/comments" }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ ul.cms-users li:first-child {
|
||||
border-top: none;
|
||||
}
|
||||
ul.cms-users li.cms_user a::before {
|
||||
content: "[users] ";
|
||||
content: "[user] ";
|
||||
}
|
||||
|
||||
ul.cms-roles {
|
||||
@@ -25,7 +25,7 @@ ul.cms-roles li:first-child {
|
||||
border-top: none;
|
||||
}
|
||||
ul.cms-roles li.cms_role a::before {
|
||||
content: "[roles] ";
|
||||
content: "[role] ";
|
||||
}
|
||||
|
||||
ul.cms-permissions {
|
||||
|
||||
@@ -12,7 +12,7 @@ ul.cms-users {
|
||||
}
|
||||
|
||||
li.cms_user a::before {
|
||||
content: "[users] ";
|
||||
content: "[user] ";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ ul.cms-roles {
|
||||
}
|
||||
|
||||
li.cms_role a::before {
|
||||
content: "[roles] ";
|
||||
content: "[role] ";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
.messaging-box fieldset {
|
||||
overflow: scroll;
|
||||
height: 250px;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
.messaging-box {
|
||||
fieldset {
|
||||
overflow:scroll;
|
||||
height:250px;
|
||||
}
|
||||
}
|
||||
@@ -84,6 +84,7 @@ feature -- CMS modules
|
||||
a_setup.register_module (create {FEED_AGGREGATOR_MODULE}.make)
|
||||
|
||||
-- Miscellanious
|
||||
a_setup.register_module (create {CMS_MESSAGING_MODULE}.make)
|
||||
a_setup.register_module (create {GOOGLE_CUSTOM_SEARCH_MODULE}.make)
|
||||
a_setup.register_module (create {CMS_CUSTOM_BLOCK_MODULE}.make)
|
||||
a_setup.register_module (create {CMS_DEBUG_MODULE}.make)
|
||||
|
||||
@@ -124,6 +124,7 @@ feature -- Security
|
||||
Result.force ("admin users")
|
||||
Result.force ("admin roles")
|
||||
Result.force ("admin modules")
|
||||
Result.force ("admin cache")
|
||||
Result.force ("admin core caches")
|
||||
Result.force ("clear blocks cache")
|
||||
Result.force ("admin export")
|
||||
@@ -159,13 +160,16 @@ feature -- Hooks
|
||||
|
||||
-- Per module cache permission!
|
||||
create lnk.make ("Cache", "admin/cache")
|
||||
lnk.set_permission_arguments (<<"admin cache">>)
|
||||
admin_lnk.extend (lnk)
|
||||
|
||||
-- Per module export permission!
|
||||
create lnk.make ("Export", "admin/export")
|
||||
lnk.set_permission_arguments (<<"admin export">>)
|
||||
admin_lnk.extend (lnk)
|
||||
-- Per module import permission!
|
||||
create lnk.make ("Import", "admin/import")
|
||||
lnk.set_permission_arguments (<<"admin import">>)
|
||||
admin_lnk.extend (lnk)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -41,11 +41,15 @@ feature -- Execution
|
||||
s: STRING
|
||||
f: CMS_FORM
|
||||
do
|
||||
create {GENERIC_VIEW_CMS_RESPONSE} l_response.make (req, res, api)
|
||||
f := clear_cache_web_form (l_response)
|
||||
create s.make_empty
|
||||
f.append_to_html (l_response.wsf_theme, s)
|
||||
l_response.set_main_content (s)
|
||||
if api.has_permission ("admin cache") then
|
||||
create {GENERIC_VIEW_CMS_RESPONSE} l_response.make (req, res, api)
|
||||
f := clear_cache_web_form (l_response)
|
||||
create s.make_empty
|
||||
f.append_to_html (l_response.wsf_theme, s)
|
||||
l_response.set_main_content (s)
|
||||
else
|
||||
create {FORBIDDEN_ERROR_CMS_RESPONSE} l_response.make (req, res, api)
|
||||
end
|
||||
l_response.execute
|
||||
end
|
||||
|
||||
@@ -55,23 +59,27 @@ feature -- Execution
|
||||
s: STRING
|
||||
f: CMS_FORM
|
||||
do
|
||||
create {GENERIC_VIEW_CMS_RESPONSE} l_response.make (req, res, api)
|
||||
f := clear_cache_web_form (l_response)
|
||||
f.process (l_response)
|
||||
if
|
||||
attached f.last_data as fd and then
|
||||
fd.is_valid
|
||||
then
|
||||
if attached fd.string_item ("op") as l_op and then l_op.same_string (text_clear_all_caches) then
|
||||
api.hooks.invoke_clear_cache (Void, l_response)
|
||||
l_response.add_notice_message ("Caches cleared (if allowed)!")
|
||||
else
|
||||
fd.report_error ("Invalid form data!")
|
||||
if api.has_permission ("admin cache") then
|
||||
create {GENERIC_VIEW_CMS_RESPONSE} l_response.make (req, res, api)
|
||||
f := clear_cache_web_form (l_response)
|
||||
f.process (l_response)
|
||||
if
|
||||
attached f.last_data as fd and then
|
||||
fd.is_valid
|
||||
then
|
||||
if attached fd.string_item ("op") as l_op and then l_op.same_string (text_clear_all_caches) then
|
||||
api.hooks.invoke_clear_cache (Void, l_response)
|
||||
l_response.add_notice_message ("Caches cleared (if allowed)!")
|
||||
else
|
||||
fd.report_error ("Invalid form data!")
|
||||
end
|
||||
end
|
||||
create s.make_empty
|
||||
f.append_to_html (l_response.wsf_theme, s)
|
||||
l_response.set_main_content (s)
|
||||
else
|
||||
create {FORBIDDEN_ERROR_CMS_RESPONSE} l_response.make (req, res, api)
|
||||
end
|
||||
create s.make_empty
|
||||
f.append_to_html (l_response.wsf_theme, s)
|
||||
l_response.set_main_content (s)
|
||||
l_response.execute
|
||||
end
|
||||
|
||||
|
||||
@@ -41,11 +41,15 @@ feature -- Execution
|
||||
s: STRING
|
||||
f: CMS_FORM
|
||||
do
|
||||
create {GENERIC_VIEW_CMS_RESPONSE} l_response.make (req, res, api)
|
||||
f := exportation_web_form (l_response)
|
||||
create s.make_empty
|
||||
f.append_to_html (l_response.wsf_theme, s)
|
||||
l_response.set_main_content (s)
|
||||
if api.has_permission ("admin export") then
|
||||
create {GENERIC_VIEW_CMS_RESPONSE} l_response.make (req, res, api)
|
||||
f := exportation_web_form (l_response)
|
||||
create s.make_empty
|
||||
f.append_to_html (l_response.wsf_theme, s)
|
||||
l_response.set_main_content (s)
|
||||
else
|
||||
create {FORBIDDEN_ERROR_CMS_RESPONSE} l_response.make (req, res, api)
|
||||
end
|
||||
l_response.execute
|
||||
end
|
||||
|
||||
@@ -56,37 +60,41 @@ feature -- Execution
|
||||
f: CMS_FORM
|
||||
l_exportation: CMS_EXPORT_CONTEXT
|
||||
do
|
||||
create {GENERIC_VIEW_CMS_RESPONSE} l_response.make (req, res, api)
|
||||
f := exportation_web_form (l_response)
|
||||
f.process (l_response)
|
||||
if
|
||||
attached f.last_data as fd and then
|
||||
fd.is_valid
|
||||
then
|
||||
if attached fd.string_item ("op") as l_op and then l_op.same_string (text_export_all_data) then
|
||||
if attached fd.string_item ("folder") as l_folder then
|
||||
create l_exportation.make (api.site_location.extended ("export").extended (l_folder))
|
||||
if api.has_permission ("admin export") then
|
||||
create {GENERIC_VIEW_CMS_RESPONSE} l_response.make (req, res, api)
|
||||
f := exportation_web_form (l_response)
|
||||
f.process (l_response)
|
||||
if
|
||||
attached f.last_data as fd and then
|
||||
fd.is_valid
|
||||
then
|
||||
if attached fd.string_item ("op") as l_op and then l_op.same_string (text_export_all_data) then
|
||||
if attached fd.string_item ("folder") as l_folder then
|
||||
create l_exportation.make (api.site_location.extended ("export").extended (l_folder))
|
||||
else
|
||||
create l_exportation.make (api.site_location.extended ("export").extended ((create {DATE_TIME}.make_now_utc).formatted_out ("yyyy-[0]mm-[0]dd---hh24-[0]mi-[0]ss")))
|
||||
end
|
||||
api.hooks.invoke_export_to (Void, l_exportation, l_response)
|
||||
l_response.add_notice_message ("All data exported (if allowed)!")
|
||||
create s.make_empty
|
||||
across
|
||||
l_exportation.logs as ic
|
||||
loop
|
||||
s.append (ic.item)
|
||||
s.append ("<br/>")
|
||||
s.append_character ('%N')
|
||||
end
|
||||
l_response.add_notice_message (s)
|
||||
else
|
||||
create l_exportation.make (api.site_location.extended ("export").extended ((create {DATE_TIME}.make_now_utc).formatted_out ("yyyy-[0]mm-[0]dd---hh24-[0]mi-[0]ss")))
|
||||
fd.report_error ("Invalid form data!")
|
||||
end
|
||||
api.hooks.invoke_export_to (Void, l_exportation, l_response)
|
||||
l_response.add_notice_message ("All data exported (if allowed)!")
|
||||
create s.make_empty
|
||||
across
|
||||
l_exportation.logs as ic
|
||||
loop
|
||||
s.append (ic.item)
|
||||
s.append ("<br/>")
|
||||
s.append_character ('%N')
|
||||
end
|
||||
l_response.add_notice_message (s)
|
||||
else
|
||||
fd.report_error ("Invalid form data!")
|
||||
end
|
||||
create s.make_empty
|
||||
f.append_to_html (l_response.wsf_theme, s)
|
||||
l_response.set_main_content (s)
|
||||
else
|
||||
create {FORBIDDEN_ERROR_CMS_RESPONSE} l_response.make (req, res, api)
|
||||
end
|
||||
create s.make_empty
|
||||
f.append_to_html (l_response.wsf_theme, s)
|
||||
l_response.set_main_content (s)
|
||||
l_response.execute
|
||||
end
|
||||
|
||||
|
||||
@@ -41,11 +41,15 @@ feature -- Execution
|
||||
s: STRING
|
||||
f: CMS_FORM
|
||||
do
|
||||
create {GENERIC_VIEW_CMS_RESPONSE} l_response.make (req, res, api)
|
||||
f := importation_web_form (l_response)
|
||||
create s.make_empty
|
||||
f.append_to_html (l_response.wsf_theme, s)
|
||||
l_response.set_main_content (s)
|
||||
if api.has_permission ("admin import") then
|
||||
create {GENERIC_VIEW_CMS_RESPONSE} l_response.make (req, res, api)
|
||||
f := importation_web_form (l_response)
|
||||
create s.make_empty
|
||||
f.append_to_html (l_response.wsf_theme, s)
|
||||
l_response.set_main_content (s)
|
||||
else
|
||||
create {FORBIDDEN_ERROR_CMS_RESPONSE} l_response.make (req, res, api)
|
||||
end
|
||||
l_response.execute
|
||||
end
|
||||
|
||||
@@ -57,43 +61,48 @@ feature -- Execution
|
||||
l_importation: CMS_IMPORT_CONTEXT
|
||||
p: PATH
|
||||
do
|
||||
create {GENERIC_VIEW_CMS_RESPONSE} l_response.make (req, res, api)
|
||||
f := importation_web_form (l_response)
|
||||
f.process (l_response)
|
||||
if
|
||||
attached f.last_data as fd and then
|
||||
fd.is_valid
|
||||
then
|
||||
if attached fd.string_item ("op") as l_op and then l_op.same_string (text_import_all_data) then
|
||||
if attached fd.string_item ("folder") as l_folder then
|
||||
create p.make_from_string (l_folder)
|
||||
create l_importation.make (api.site_location.extended (import_folder_name).extended (l_folder))
|
||||
if l_importation.location_exists then
|
||||
l_response.add_notice_message ("Import all data (if permitted)!")
|
||||
api.hooks.invoke_import_from (Void, l_importation, l_response)
|
||||
create s.make_empty
|
||||
across
|
||||
l_importation.logs as ic
|
||||
loop
|
||||
s.append (ic.item)
|
||||
s.append ("<br/>")
|
||||
s.append_character ('%N')
|
||||
if api.has_permission ("admin import") then
|
||||
create {GENERIC_VIEW_CMS_RESPONSE} l_response.make (req, res, api)
|
||||
f := importation_web_form (l_response)
|
||||
f.process (l_response)
|
||||
if
|
||||
attached f.last_data as fd and then
|
||||
fd.is_valid
|
||||
then
|
||||
if attached fd.string_item ("op") as l_op and then l_op.same_string (text_import_all_data) then
|
||||
if attached fd.string_item ("folder") as l_folder then
|
||||
create p.make_from_string (l_folder)
|
||||
create l_importation.make (api.site_location.extended (import_folder_name).extended (l_folder))
|
||||
if l_importation.location_exists then
|
||||
l_response.add_notice_message ("Import all data (if permitted)!")
|
||||
api.hooks.invoke_import_from (Void, l_importation, l_response)
|
||||
create s.make_empty
|
||||
across
|
||||
l_importation.logs as ic
|
||||
loop
|
||||
s.append (ic.item)
|
||||
s.append ("<br/>")
|
||||
s.append_character ('%N')
|
||||
end
|
||||
l_response.add_notice_message (s)
|
||||
else
|
||||
l_response.add_error_message ("Specified import folder is not found!")
|
||||
fd.report_invalid_field ("folder", "Folder not found!")
|
||||
end
|
||||
l_response.add_notice_message (s)
|
||||
else
|
||||
l_response.add_error_message ("Specified import folder is not found!")
|
||||
fd.report_invalid_field ("folder", "Folder not found!")
|
||||
fd.report_error ("Invalid form data!")
|
||||
end
|
||||
else
|
||||
fd.report_error ("Invalid form data!")
|
||||
end
|
||||
else
|
||||
fd.report_error ("Invalid form data!")
|
||||
end
|
||||
create s.make_empty
|
||||
f.append_to_html (l_response.wsf_theme, s)
|
||||
l_response.set_main_content (s)
|
||||
else
|
||||
create {FORBIDDEN_ERROR_CMS_RESPONSE} l_response.make (req, res, api)
|
||||
end
|
||||
create s.make_empty
|
||||
f.append_to_html (l_response.wsf_theme, s)
|
||||
l_response.set_main_content (s)
|
||||
|
||||
l_response.execute
|
||||
end
|
||||
|
||||
|
||||
@@ -66,6 +66,7 @@ feature -- HTTP Methods
|
||||
s_pager: STRING
|
||||
l_count: INTEGER
|
||||
user_api: CMS_USER_API
|
||||
l_display_name: READABLE_STRING_32
|
||||
do
|
||||
-- At the moment the template are hardcoded, but we can
|
||||
-- get them from the configuration file and load them into
|
||||
@@ -81,9 +82,9 @@ feature -- HTTP Methods
|
||||
|
||||
create s.make_empty
|
||||
if l_count > 1 then
|
||||
l_response.set_title ("Listing " + l_count.out + " Users")
|
||||
l_response.set_title ("Listing " + l_count.out + " users")
|
||||
else
|
||||
l_response.set_title ("Listing " + l_count.out + " User")
|
||||
l_response.set_title ("A single user")
|
||||
end
|
||||
|
||||
create s_pager.make_empty
|
||||
@@ -106,7 +107,13 @@ feature -- HTTP Methods
|
||||
s.append ("<a href=%"")
|
||||
s.append (req.absolute_script_url ("/admin/user/"+u.id.out))
|
||||
s.append ("%">")
|
||||
s.append (html_encoded (u.name))
|
||||
l_display_name := user_api.user_display_name (u)
|
||||
s.append (html_encoded (l_display_name))
|
||||
if not l_display_name.same_string (u.name) then
|
||||
s.append (" [")
|
||||
s.append (html_encoded (u.name))
|
||||
s.append ("]")
|
||||
end
|
||||
s.append ("</a>")
|
||||
if attached user_api.user_roles (u) as l_roles and then not l_roles.is_empty then
|
||||
s.append (" <span class=%"cms_roles%">(")
|
||||
|
||||
@@ -10,7 +10,7 @@ ul.cms-users li:first-child {
|
||||
border-top: none;
|
||||
}
|
||||
ul.cms-users li.cms_user a::before {
|
||||
content: "[users] ";
|
||||
content: "[user] ";
|
||||
}
|
||||
|
||||
ul.cms-roles {
|
||||
@@ -25,7 +25,7 @@ ul.cms-roles li:first-child {
|
||||
border-top: none;
|
||||
}
|
||||
ul.cms-roles li.cms_role a::before {
|
||||
content: "[roles] ";
|
||||
content: "[role] ";
|
||||
}
|
||||
|
||||
ul.cms-permissions {
|
||||
|
||||
@@ -12,7 +12,7 @@ ul.cms-users {
|
||||
}
|
||||
|
||||
li.cms_user a::before {
|
||||
content: "[users] ";
|
||||
content: "[user] ";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ ul.cms-roles {
|
||||
}
|
||||
|
||||
li.cms_role a::before {
|
||||
content: "[roles] ";
|
||||
content: "[role] ";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
20
modules/messaging/messaging-safe.ecf
Normal file
20
modules/messaging/messaging-safe.ecf
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="messaging" uuid="939C9362-FD46-4B4F-BB36-A593089430AB" library_target="messaging">
|
||||
<target name="messaging">
|
||||
<root all_classes="true"/>
|
||||
<option>
|
||||
</option>
|
||||
<setting name="concurrency" value="scoop"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="cms" location="..\..\cms-safe.ecf" readonly="false"/>
|
||||
<library name="cms_app_env" location="..\..\library\app_env\app_env-safe.ecf" readonly="false"/>
|
||||
<library name="cms_model" location="..\..\library\model\cms_model-safe.ecf" readonly="false"/>
|
||||
<library name="error" location="$ISE_LIBRARY\contrib\library\utility\general\error\error-safe.ecf"/>
|
||||
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-safe.ecf"/>
|
||||
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
|
||||
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
|
||||
<library name="wsf_encoder" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\text\encoder\encoder-safe.ecf"/>
|
||||
<library name="wsf_html" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf_html\wsf_html-safe.ecf"/>
|
||||
<cluster name="src" location="src\" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
4
modules/messaging/site/files/css/messaging.css
Normal file
4
modules/messaging/site/files/css/messaging.css
Normal file
@@ -0,0 +1,4 @@
|
||||
.messaging-box fieldset {
|
||||
overflow: scroll;
|
||||
height: 250px;
|
||||
}
|
||||
6
modules/messaging/site/files/scss/messaging.scss
Normal file
6
modules/messaging/site/files/scss/messaging.scss
Normal file
@@ -0,0 +1,6 @@
|
||||
.messaging-box {
|
||||
fieldset {
|
||||
overflow:scroll;
|
||||
height:250px;
|
||||
}
|
||||
}
|
||||
17
modules/messaging/src/cms_messaging_api.e
Normal file
17
modules/messaging/src/cms_messaging_api.e
Normal file
@@ -0,0 +1,17 @@
|
||||
note
|
||||
description: "API for the contact module."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_MESSAGING_API
|
||||
|
||||
inherit
|
||||
CMS_MODULE_API
|
||||
|
||||
REFACTORING_HELPER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
end
|
||||
381
modules/messaging/src/cms_messaging_module.e
Normal file
381
modules/messaging/src/cms_messaging_module.e
Normal file
@@ -0,0 +1,381 @@
|
||||
note
|
||||
description: "[
|
||||
Module that provides messenger functionality.
|
||||
]"
|
||||
author: "$Author$"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_MESSAGING_MODULE
|
||||
|
||||
inherit
|
||||
CMS_MODULE
|
||||
rename
|
||||
module_api as messaging_api
|
||||
redefine
|
||||
setup_hooks,
|
||||
-- install,
|
||||
initialize,
|
||||
permissions,
|
||||
messaging_api
|
||||
end
|
||||
|
||||
CMS_HOOK_AUTO_REGISTER
|
||||
|
||||
CMS_HOOK_MENU_SYSTEM_ALTER
|
||||
|
||||
REFACTORING_HELPER
|
||||
|
||||
SHARED_LOGGER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
-- Create current module
|
||||
do
|
||||
version := "1.0"
|
||||
description := "Messaging module"
|
||||
package := "messaging"
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
name: STRING = "messaging"
|
||||
-- <Precursor>
|
||||
|
||||
feature {CMS_API} -- Module Initialization
|
||||
|
||||
initialize (api: CMS_API)
|
||||
-- <Precursor>
|
||||
local
|
||||
l_messaging_api: like messaging_api
|
||||
do
|
||||
Precursor (api)
|
||||
create l_messaging_api.make (api)
|
||||
messaging_api := l_messaging_api
|
||||
end
|
||||
|
||||
feature {CMS_API} -- Access: API
|
||||
|
||||
messaging_api: detachable CMS_MESSAGING_API
|
||||
|
||||
feature -- Router
|
||||
|
||||
setup_router (a_router: WSF_ROUTER; a_api: CMS_API)
|
||||
-- Router configuration.
|
||||
local
|
||||
m: WSF_URI_MAPPING
|
||||
do
|
||||
create m.make_trailing_slash_ignored ("/messaging", create {WSF_URI_AGENT_HANDLER}.make (agent handle_get_messaging (a_api, ?, ?)))
|
||||
a_router.map (m, a_router.methods_head_get)
|
||||
a_router.handle ("/messaging", create {WSF_URI_AGENT_HANDLER}.make (agent handle_post_messaging (a_api, ?, ?)), a_router.methods_put_post)
|
||||
end
|
||||
|
||||
feature -- Security
|
||||
|
||||
permissions: LIST [READABLE_STRING_8]
|
||||
-- List of permission ids, used by this module, and declared.
|
||||
do
|
||||
Result := Precursor
|
||||
Result.force ("admin messaging")
|
||||
Result.force ("message any user")
|
||||
Result.force ("use messaging")
|
||||
end
|
||||
|
||||
feature -- Hooks configuration
|
||||
|
||||
setup_hooks (a_hooks: CMS_HOOK_CORE_MANAGER)
|
||||
-- Module hooks configuration.
|
||||
do
|
||||
auto_subscribe_to_hooks (a_hooks)
|
||||
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 messaging to menu")
|
||||
end
|
||||
end
|
||||
|
||||
new_html_messaging_form (a_response: CMS_RESPONSE; api: CMS_API): STRING
|
||||
local
|
||||
f: CMS_FORM
|
||||
do
|
||||
a_response.add_style (a_response.url ("/module/" + name + "/files/css/messaging.css", Void), Void)
|
||||
-- TODO: use template to overwrite/customize
|
||||
-- if attached smarty_template_block (Current, "messaging", api) as l_tpl_block then
|
||||
-- across
|
||||
-- a_response.values as tb
|
||||
-- loop
|
||||
-- l_tpl_block.set_value (tb.item, tb.key)
|
||||
-- end
|
||||
-- Result := l_tpl_block.to_html (a_response.theme)
|
||||
-- else
|
||||
f := new_messaging_form (a_response, api)
|
||||
api.hooks.invoke_form_alter (f, f.last_data, a_response)
|
||||
|
||||
Result := "<div class=%"messaging-box%"><h1>Send message to ...</h1>" + f.to_html (a_response.wsf_theme) + "<br/></div>"
|
||||
-- end
|
||||
end
|
||||
|
||||
new_messaging_form (a_response: CMS_RESPONSE; api: CMS_API): CMS_FORM
|
||||
local
|
||||
f: CMS_FORM
|
||||
f_name: WSF_FORM_TEXT_INPUT
|
||||
f_msg: WSF_FORM_TEXTAREA
|
||||
f_submit: WSF_FORM_SUBMIT_INPUT
|
||||
f_user: WSF_FORM_CHECKBOX_INPUT
|
||||
f_set: WSF_FORM_FIELD_SET
|
||||
l_params: CMS_DATA_QUERY_PARAMETERS
|
||||
nb: INTEGER
|
||||
i: INTEGER
|
||||
do
|
||||
create f.make (a_response.url ("messaging", Void), "messaging-form")
|
||||
if attached api.user as l_current_user then
|
||||
nb := api.user_api.users_count
|
||||
from
|
||||
create f_set.make
|
||||
f_set.set_legend ("Select users")
|
||||
f.extend (f_set)
|
||||
i := 0
|
||||
until
|
||||
i > nb
|
||||
loop
|
||||
create l_params.make (i.to_natural_64, 25)
|
||||
if attached api.user_api.recent_users (l_params) as l_users then
|
||||
across
|
||||
l_users as ic
|
||||
loop
|
||||
if l_current_user.id = ic.item.id then
|
||||
else
|
||||
create f_user.make_with_value ("users[]", ic.item.id.out)
|
||||
f_user.set_title (api.user_api.user_display_name (ic.item))
|
||||
f_set.extend (f_user)
|
||||
end
|
||||
end
|
||||
end
|
||||
i := i + 25
|
||||
end
|
||||
|
||||
create f_name.make ("title")
|
||||
f_name.set_size (80)
|
||||
f_name.set_label ("Title")
|
||||
f_name.set_is_required (True)
|
||||
f.extend (f_name)
|
||||
|
||||
create f_msg.make ("message")
|
||||
f_msg.set_cols (80)
|
||||
f_msg.set_rows (75)
|
||||
f_msg.set_label ("Message")
|
||||
f_msg.set_rows (5)
|
||||
f_msg.set_is_required (True)
|
||||
f.extend (f_msg)
|
||||
|
||||
create f_submit.make_with_text ("submit-op", "Send")
|
||||
f.extend (f_submit)
|
||||
end
|
||||
Result := f
|
||||
end
|
||||
|
||||
handle_get_messaging (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
local
|
||||
r: CMS_RESPONSE
|
||||
do
|
||||
if api.has_permission ("use messaging") or api.has_permission ("message any user") then
|
||||
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
|
||||
r.values.force ("messaging", "messaging")
|
||||
r.set_main_content (new_html_messaging_form (r, api))
|
||||
else
|
||||
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api)
|
||||
end
|
||||
r.execute
|
||||
end
|
||||
|
||||
handle_post_messaging (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
local
|
||||
r: CMS_RESPONSE
|
||||
e: CMS_EMAIL
|
||||
l_emails: ARRAYED_LIST [CMS_EMAIL]
|
||||
vars: STRING_TABLE [READABLE_STRING_8]
|
||||
l_messaging_email_address: READABLE_STRING_8
|
||||
s: STRING
|
||||
l_uid: READABLE_STRING_32
|
||||
f: like new_messaging_form
|
||||
l_user: detachable CMS_USER
|
||||
l_email_title: READABLE_STRING_8
|
||||
l_email_messg: READABLE_STRING_8
|
||||
do
|
||||
if api.has_permission ("message any user") then
|
||||
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
|
||||
r.add_style (r.url ("/module/" + name + "/files/css/messaging.css", Void), Void)
|
||||
|
||||
create s.make_empty
|
||||
|
||||
f := new_messaging_form (r, api)
|
||||
f.process (r)
|
||||
if attached f.last_data as fd then
|
||||
if
|
||||
not fd.has_error and then
|
||||
attached fd.string_item ("title") as l_title and then
|
||||
attached fd.string_item ("message") as l_message and then
|
||||
attached fd.table_item ("users") as l_users
|
||||
then
|
||||
create l_emails.make (l_users.count)
|
||||
|
||||
s.append ("Send message %"")
|
||||
s.append (r.html_encoded (l_title))
|
||||
s.append ("%"")
|
||||
s.append (" to users: <ul>")
|
||||
across
|
||||
l_users as ic
|
||||
loop
|
||||
if attached {WSF_STRING} ic.item as p_uid then
|
||||
l_uid := p_uid.value
|
||||
if l_uid.is_integer_64 then
|
||||
l_user := api.user_api.user_by_id (l_uid.to_integer_64)
|
||||
else
|
||||
l_user := api.user_api.user_by_name (l_uid)
|
||||
end
|
||||
s.append ("<li>")
|
||||
if l_user /= Void and then attached l_user.email as l_user_email then
|
||||
s.append (r.html_encoded (api.user_api.user_display_name (l_user)))
|
||||
s.append (" <")
|
||||
s.append (r.html_encoded (l_user_email))
|
||||
s.append (">")
|
||||
|
||||
l_email_title := resolved_template_text (api, l_title, l_user)
|
||||
l_email_messg := resolved_template_text (api, l_message, l_user)
|
||||
|
||||
|
||||
e := api.new_email (l_user_email, l_email_title, l_email_messg)
|
||||
|
||||
s.append (" <pre>")
|
||||
s.append (e.message)
|
||||
s.append ("</pre>")
|
||||
l_emails.force (e)
|
||||
api.process_email (e)
|
||||
if e.is_sent then
|
||||
s.append (" successfully sent.")
|
||||
else
|
||||
s.append (" failure, not sent!")
|
||||
end
|
||||
else
|
||||
s.append (r.html_encoded (p_uid.value))
|
||||
s.append (" skipped!")
|
||||
end
|
||||
s.append ("</li>%N")
|
||||
end
|
||||
end
|
||||
else
|
||||
f.append_to_html (r.wsf_theme, s)
|
||||
end
|
||||
end
|
||||
r.set_main_content (s)
|
||||
else
|
||||
create {FORBIDDEN_ERROR_CMS_RESPONSE} r.make (req, res, api)
|
||||
end
|
||||
r.execute
|
||||
end
|
||||
|
||||
feature {NONE} -- Helpers
|
||||
|
||||
form_parameters_as_string (req: WSF_REQUEST): STRING
|
||||
do
|
||||
create Result.make_empty
|
||||
across req.form_parameters as ic loop
|
||||
Result.append (ic.item.key)
|
||||
Result.append_character ('=')
|
||||
Result.append_string (ic.item.string_representation)
|
||||
Result.append_character ('%N')
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Contact Message
|
||||
|
||||
resolved_template_text (api: CMS_API; a_text: READABLE_STRING_GENERAL; a_target_user: detachable CMS_USER): STRING_8
|
||||
local
|
||||
smt: CMS_SMARTY_TEMPLATE_TEXT
|
||||
utf: UTF_CONVERTER
|
||||
do
|
||||
create smt.make (utf.utf_32_string_to_utf_8_string_8 (a_text))
|
||||
across
|
||||
api.builtin_variables as vars_ic
|
||||
loop
|
||||
smt.set_value (vars_ic.item, vars_ic.key)
|
||||
end
|
||||
if a_target_user /= Void then
|
||||
smt.set_value (a_target_user.name, "target_user_name")
|
||||
smt.set_value (api.user_api.user_display_name (a_target_user), "target_user_profile_name")
|
||||
smt.set_value (a_target_user.id.out, "target_user_id")
|
||||
if attached a_target_user.email as l_email then
|
||||
smt.set_value (l_email, "target_user_email")
|
||||
end
|
||||
end
|
||||
Result := smt.string
|
||||
end
|
||||
|
||||
-- email_html_message (a_message_id: READABLE_STRING_8; a_response: CMS_RESPONSE; a_html_encoded_values: STRING_TABLE [READABLE_STRING_8]): STRING
|
||||
-- -- html message related to `a_message_id'.
|
||||
-- local
|
||||
-- res: PATH
|
||||
-- p: detachable PATH
|
||||
-- tpl: CMS_SMARTY_TEMPLATE_BLOCK
|
||||
-- exp: CMS_STRING_EXPANDER [STRING_8]
|
||||
-- do
|
||||
-- write_debug_log (generator + ".email_html_message for [" + a_message_id + " ]")
|
||||
|
||||
-- create res.make_from_string ("templates")
|
||||
-- res := res.extended ("email_").appended (a_message_id).appended_with_extension ("tpl")
|
||||
-- p := a_response.api.module_theme_resource_location (Current, res)
|
||||
-- if p /= Void then
|
||||
-- if attached p.entry as e then
|
||||
-- create tpl.make (a_message_id, Void, p.parent, e)
|
||||
-- write_debug_log (generator + ".email_html_message from smarty template:" + tpl.out)
|
||||
-- else
|
||||
-- create tpl.make (a_message_id, Void, p.parent, p)
|
||||
-- write_debug_log (generator + ".email_html_message from smarty template:" + tpl.out)
|
||||
-- end
|
||||
-- across
|
||||
-- a_html_encoded_values as ic
|
||||
-- loop
|
||||
-- tpl.set_value (ic.item, ic.key)
|
||||
-- end
|
||||
-- Result := tpl.to_html (a_response.theme)
|
||||
-- else
|
||||
-- if a_message_id.is_case_insensitive_equal_general ("message") then
|
||||
-- create Result.make_from_string (messaging_message_template)
|
||||
-- elseif a_message_id.is_case_insensitive_equal_general ("notification") then
|
||||
-- create Result.make_from_string (messaging_notification_message_template)
|
||||
-- else
|
||||
-- create Result.make_from_string (a_message_id)
|
||||
-- across
|
||||
-- a_html_encoded_values as ic
|
||||
-- loop
|
||||
-- Result.append ("<li>")
|
||||
-- Result.append (html_encoded (ic.key))
|
||||
-- Result.append (": ")
|
||||
-- Result.append (ic.item) -- Already html encoded.
|
||||
-- Result.append ("</li>%N")
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- create exp.make
|
||||
-- across
|
||||
-- a_html_encoded_values as ic
|
||||
-- loop
|
||||
-- exp.put (ic.item, ic.key)
|
||||
-- end
|
||||
-- exp.expand_string (Result)
|
||||
-- write_debug_log (generator + ".email_html_message using built-in message:" + Result)
|
||||
-- end
|
||||
-- end
|
||||
|
||||
end
|
||||
@@ -153,6 +153,11 @@ feature -- Access: Node
|
||||
Result := node_storage.nodes_count
|
||||
end
|
||||
|
||||
nodes_of_type_count (a_content_type: CMS_CONTENT_TYPE): NATURAL_64
|
||||
do
|
||||
Result := node_storage.nodes_of_type_count (a_content_type)
|
||||
end
|
||||
|
||||
nodes: LIST [CMS_NODE]
|
||||
-- List of nodes.
|
||||
do
|
||||
@@ -179,6 +184,12 @@ feature -- Access: Node
|
||||
Result := node_storage.recent_nodes (params.offset.to_integer_32, params.size.to_integer_32)
|
||||
end
|
||||
|
||||
recent_nodes_of_type (a_content_type: CMS_CONTENT_TYPE; params: CMS_DATA_QUERY_PARAMETERS): ITERABLE [CMS_NODE]
|
||||
-- Most recent `a_content_type` nodes according to `params.offset' and `params.size'.
|
||||
do
|
||||
Result := node_storage.recent_nodes_of_type (a_content_type, params.offset.to_integer_32, params.size.to_integer_32)
|
||||
end
|
||||
|
||||
recent_node_changes_before (params: CMS_DATA_QUERY_PARAMETERS; a_date: DATE_TIME): ITERABLE [CMS_NODE]
|
||||
-- List of recent changes, before `a_date', according to `params' settings.
|
||||
do
|
||||
@@ -356,6 +367,85 @@ feature -- Change: Node
|
||||
error_handler.append (node_storage.error_handler)
|
||||
end
|
||||
|
||||
feature -- path_alias suggestion
|
||||
|
||||
path_alias_uri_suggestion (a_node: detachable CMS_NODE; a_content_type: CMS_CONTENT_TYPE): STRING
|
||||
local
|
||||
dt: DATE_TIME
|
||||
uri: URI
|
||||
do
|
||||
create uri.make_from_string ("/")
|
||||
uri.add_unencoded_path_segment (a_content_type.name)
|
||||
if a_node /= Void then
|
||||
dt := a_node.creation_date
|
||||
else
|
||||
create dt.make_now_utc
|
||||
end
|
||||
if attached cms_api.user as u and then not cms_api.user_api.is_admin_user (u) then
|
||||
uri.add_unencoded_path_segment (cms_api.user_api.user_display_name (u))
|
||||
end
|
||||
uri.add_unencoded_path_segment (dt.year.out)
|
||||
if dt.month <= 9 then
|
||||
uri.add_unencoded_path_segment ("0" + dt.month.out)
|
||||
else
|
||||
uri.add_unencoded_path_segment (dt.month.out)
|
||||
end
|
||||
if a_node /= Void and then attached a_node.title as l_title then
|
||||
uri.add_unencoded_path_segment (safe_path_alias_uri_segment_text (l_title))
|
||||
else
|
||||
uri.add_unencoded_path_segment ("")
|
||||
end
|
||||
|
||||
Result := uri.string
|
||||
end
|
||||
|
||||
safe_path_alias_uri_segment_text (s: READABLE_STRING_GENERAL): STRING_32
|
||||
local
|
||||
i,n: INTEGER
|
||||
c, prev: CHARACTER_32
|
||||
l_words: ITERABLE [READABLE_STRING_GENERAL]
|
||||
w: STRING_32
|
||||
do
|
||||
l_words := << "a", "an", "as", "at", "before", "but", "by", "for", "from", "is", "in", "into", "like", "of", "off", "on", "onto", "per", "since", "than", "the", "this", "that", "to", "up", "via", "with" >>
|
||||
from
|
||||
i := 1
|
||||
n := s.count
|
||||
create Result.make (n)
|
||||
create w.make_empty
|
||||
until
|
||||
i > n
|
||||
loop
|
||||
c := s[i].as_lower
|
||||
if c.is_alpha_numeric then
|
||||
w.append_character (c)
|
||||
prev := c
|
||||
else
|
||||
if w.is_empty then
|
||||
-- Ignore
|
||||
else
|
||||
if across l_words as ic some w.same_string_general (ic.item) end then
|
||||
-- Ignore
|
||||
w.wipe_out
|
||||
else
|
||||
if not Result.is_empty then
|
||||
Result.append_character ('-')
|
||||
end
|
||||
Result.append (w)
|
||||
w.wipe_out
|
||||
end
|
||||
end
|
||||
end
|
||||
i := i + 1
|
||||
end
|
||||
if not w.is_empty then
|
||||
if not Result.is_empty then
|
||||
Result.append_character ('-')
|
||||
end
|
||||
Result.append (w)
|
||||
w.wipe_out
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Node status
|
||||
|
||||
Not_published: INTEGER = 0
|
||||
|
||||
@@ -150,13 +150,13 @@ feature -- Access
|
||||
Result.force ("restore own " + l_type_name)
|
||||
|
||||
Result.force ("view unpublished " + l_type_name)
|
||||
|
||||
Result.force ("view revisions own " + l_type_name)
|
||||
|
||||
Result.force ("export " + l_type_name)
|
||||
end
|
||||
end
|
||||
Result.force ("view trash")
|
||||
Result.force ("view own trash")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -195,6 +195,7 @@ feature -- Access: router
|
||||
create l_nodes_handler.make (a_api, a_node_api)
|
||||
create l_uri_mapping.make_trailing_slash_ignored ("/nodes", l_nodes_handler)
|
||||
a_router.map (l_uri_mapping, a_router.methods_get)
|
||||
a_router.handle ("/nodes/{type}", l_nodes_handler, a_router.methods_get)
|
||||
|
||||
-- Trash
|
||||
create l_trash_handler.make (a_api, a_node_api)
|
||||
|
||||
@@ -92,7 +92,15 @@ feature -- Status reports
|
||||
do
|
||||
Result := status = {CMS_NODE_API}.published
|
||||
ensure
|
||||
Result implies not is_trashed
|
||||
Result implies not is_trashed and not is_not_published
|
||||
end
|
||||
|
||||
is_not_published: BOOLEAN
|
||||
-- Is Current not published?
|
||||
do
|
||||
Result := status = {CMS_NODE_API}.not_published
|
||||
ensure
|
||||
Result implies not is_published
|
||||
end
|
||||
|
||||
is_trashed: BOOLEAN
|
||||
|
||||
@@ -107,10 +107,14 @@ feature -- Forms ...
|
||||
populate_form_with_path_alias (response: NODE_RESPONSE; f: CMS_FORM; a_node: detachable CMS_NODE)
|
||||
local
|
||||
ti: WSF_FORM_TEXT_INPUT
|
||||
thi: WSF_FORM_HIDDEN_INPUT
|
||||
l_uri: detachable READABLE_STRING_8
|
||||
l_iri: detachable READABLE_STRING_32
|
||||
l_auto_path_alias: READABLE_STRING_8
|
||||
do
|
||||
-- Path alias
|
||||
l_auto_path_alias := node_api.path_alias_uri_suggestion (a_node, content_type)
|
||||
|
||||
create ti.make ("path_alias")
|
||||
ti.set_label ("Path")
|
||||
ti.set_pattern ("^([A-Za-z0-9-_+ ]).+")
|
||||
@@ -119,13 +123,19 @@ feature -- Forms ...
|
||||
if a_node /= Void and then a_node.has_id then
|
||||
if attached a_node.link as lnk then
|
||||
l_uri := lnk.location
|
||||
if l_uri.same_string (node_api.node_path (a_node)) then
|
||||
l_uri := ""
|
||||
end
|
||||
else
|
||||
l_iri := percent_encoder.percent_decoded_string (response.api.location_alias (response.node_api.node_path (a_node)))
|
||||
l_uri := l_iri.to_string_8
|
||||
end
|
||||
ti.set_text_value (l_uri)
|
||||
ti.set_description ("Optionally specify an alternative URL path by which this content can be accessed. For example, type 'about' when writing an about page. Use a relative path or the URL alias won't work.")
|
||||
ti.set_description ("Optionally specify an alternative URL path by which this content can be accessed.<br/>%NFor example, type 'about' when writing an about page. Use a relative path or the URL alias won't work.")
|
||||
else
|
||||
l_uri := ""
|
||||
end
|
||||
ti.set_text_value (l_uri)
|
||||
ti.set_placeholder (l_auto_path_alias)
|
||||
ti.set_validation_action (agent (fd: WSF_FORM_DATA; ia_response: NODE_RESPONSE; ia_node: detachable CMS_NODE)
|
||||
do
|
||||
if
|
||||
@@ -163,6 +173,11 @@ feature -- Forms ...
|
||||
else
|
||||
f.extend (ti)
|
||||
end
|
||||
-- Auto path alias / suggestion
|
||||
create thi.make ("auto_path_alias")
|
||||
thi.set_text_value (l_auto_path_alias)
|
||||
thi.set_is_readonly (True)
|
||||
f.insert_after (thi, ti)
|
||||
end
|
||||
|
||||
update_node (response: NODE_RESPONSE; fd: WSF_FORM_DATA; a_node: CMS_NODE)
|
||||
@@ -291,9 +306,12 @@ feature -- Output
|
||||
a_response.add_to_primary_tabs (lnk)
|
||||
|
||||
if a_node.status = {CMS_NODE_API}.trashed then
|
||||
create lnk.make ("Delete", l_node_api.node_path (a_node) + "/delete")
|
||||
create lnk.make ("Restore", l_node_api.node_path (a_node) + "/trash")
|
||||
lnk.set_weight (2)
|
||||
a_response.add_to_primary_tabs (lnk)
|
||||
create lnk.make ("Delete", l_node_api.node_path (a_node) + "/delete")
|
||||
lnk.set_weight (3)
|
||||
a_response.add_to_primary_tabs (lnk)
|
||||
elseif a_node.has_id then
|
||||
-- Node in {{CMS_NODE_API}.published} or {CMS_NODE_API}.not_published} status.
|
||||
create lnk.make ("Edit", l_node_api.node_path (a_node) + "/edit")
|
||||
@@ -320,7 +338,17 @@ feature -- Output
|
||||
if is_teaser then
|
||||
a_output.append (" cms-teaser")
|
||||
end
|
||||
a_output.append ("cms-node node-" + a_node.content_type + "%">")
|
||||
a_output.append ("cms-node node-" + a_node.content_type)
|
||||
if a_node.is_published then
|
||||
a_output.append (" cms-status-published")
|
||||
elseif a_node.is_trashed then
|
||||
a_output.append (" cms-status-trashed")
|
||||
elseif a_node.is_not_published then
|
||||
a_output.append (" cms-status-unpublished")
|
||||
else
|
||||
a_output.append (" cms-status-" + a_node.status.out)
|
||||
end
|
||||
a_output.append ("%">")
|
||||
|
||||
a_output.append ("<div class=%"info%"> ")
|
||||
if attached a_node.author as l_author then
|
||||
@@ -430,6 +458,4 @@ feature -- Output
|
||||
end
|
||||
a_output.append ("</li>")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -159,7 +159,6 @@ feature {NONE} -- Create a new node
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
delete_node (a_node: CMS_NODE; a_type: CMS_NODE_TYPE [CMS_NODE]; b: STRING_8)
|
||||
local
|
||||
f: like new_edit_form
|
||||
@@ -187,7 +186,7 @@ feature {NONE} -- Create a new node
|
||||
f.append_to_html (wsf_theme, b)
|
||||
end
|
||||
else
|
||||
--
|
||||
b.append ("ERROR: node is not in the trash!")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -254,7 +253,7 @@ feature -- Form
|
||||
l_node: detachable CMS_NODE
|
||||
s: STRING
|
||||
l_node_path: READABLE_STRING_8
|
||||
l_path_alias, l_existing_path_alias: detachable READABLE_STRING_8
|
||||
l_path_alias, l_existing_path_alias, l_auto_path_alias: detachable READABLE_STRING_8
|
||||
do
|
||||
fixme ("Refactor code per operacion: Preview, Save")
|
||||
l_preview := attached {WSF_STRING} fd.item ("op") as l_op and then l_op.same_string ("Preview")
|
||||
@@ -302,10 +301,13 @@ feature -- Form
|
||||
add_success_message ("Node #" + l_node.id.out + " saved.")
|
||||
end
|
||||
|
||||
-- Path aliase
|
||||
l_node_path := node_api.node_path (l_node)
|
||||
l_existing_path_alias := api.location_alias (l_node_path)
|
||||
|
||||
l_auto_path_alias := node_api.path_alias_uri_suggestion (l_node, a_type)
|
||||
if attached fd.string_item ("path_alias") as f_path_alias then
|
||||
l_node_path := node_api.node_path (l_node)
|
||||
l_path_alias := percent_encoder.partial_encoded_string (f_path_alias, <<'/'>>)
|
||||
l_existing_path_alias := api.location_alias (l_node_path)
|
||||
if
|
||||
l_existing_path_alias /= Void and then
|
||||
l_path_alias.same_string (l_existing_path_alias)
|
||||
@@ -315,7 +317,10 @@ feature -- Form
|
||||
elseif l_existing_path_alias /= Void and then l_path_alias.is_whitespace then
|
||||
-- Reset to builtin alias.
|
||||
if api.has_permission ("edit path_alias") then
|
||||
api.set_path_alias (l_node_path, l_node_path, True)
|
||||
api.set_path_alias (l_node_path, l_auto_path_alias, True)
|
||||
elseif l_existing_path_alias.same_string (l_node_path) then
|
||||
-- not aliased! Use default.
|
||||
api.set_path_alias (l_node_path, l_auto_path_alias, True)
|
||||
else
|
||||
add_error_message ("Permission denied to reset path alias on node #" + l_node.id.out + "!")
|
||||
end
|
||||
@@ -330,6 +335,12 @@ feature -- Form
|
||||
l_node.set_link (node_api.node_link (l_node))
|
||||
end
|
||||
end
|
||||
elseif l_existing_path_alias /= Void then
|
||||
l_node.set_link (create {CMS_LOCAL_LINK}.make (l_node.title, l_existing_path_alias))
|
||||
elseif l_auto_path_alias /= Void then
|
||||
-- Use auto path alias
|
||||
api.set_path_alias (l_node_path, l_auto_path_alias, True)
|
||||
l_node.set_link (create {CMS_LOCAL_LINK}.make (l_node.title, l_auto_path_alias))
|
||||
else
|
||||
l_node.set_link (node_api.node_link (l_node))
|
||||
end
|
||||
@@ -381,7 +392,7 @@ feature -- Form
|
||||
create f.make (a_url, a_name)
|
||||
|
||||
f.extend_html_text ("<br/>")
|
||||
f.extend_html_text ("<legend>Are you sure you want to delete?</legend>")
|
||||
f.extend_html_text ("<legend>Are you sure you want to delete? (impossible to undo)</legend>")
|
||||
|
||||
-- TODO check if we need to check for has_permissions!!
|
||||
if
|
||||
@@ -400,46 +411,42 @@ feature -- Form
|
||||
ts.set_formmethod ("GET")
|
||||
f.extend (ts)
|
||||
end
|
||||
f.extend_html_text ("<br/>")
|
||||
f.extend_html_text ("<legend>Do you want to restore the current node?</legend>")
|
||||
if
|
||||
a_node /= Void and then
|
||||
a_node.id > 0
|
||||
then
|
||||
create ts.make ("op")
|
||||
ts.set_default_value ("Restore")
|
||||
ts.set_formaction ("/node/"+a_node.id.out+"/delete")
|
||||
ts.set_formmethod ("POST")
|
||||
fixme ("[
|
||||
ts.set_default_value (translation ("Restore"))
|
||||
]")
|
||||
f.extend (ts)
|
||||
end
|
||||
Result := f
|
||||
end
|
||||
|
||||
|
||||
new_trash_form (a_node: detachable CMS_NODE; a_url: READABLE_STRING_8; a_name: STRING; a_node_type: CMS_NODE_TYPE [CMS_NODE]): CMS_FORM
|
||||
-- Create a web form named `a_name' for node `a_node' (if set), using form action url `a_url', and for type of node `a_node_type'.
|
||||
new_trash_form (a_node: CMS_NODE; a_url: READABLE_STRING_8; a_name: STRING; a_node_type: CMS_NODE_TYPE [CMS_NODE]): CMS_FORM
|
||||
-- Create a web form named `a_name' for node `a_node', using form action url `a_url', and for type of node `a_node_type'.
|
||||
local
|
||||
f: CMS_FORM
|
||||
ts: WSF_FORM_SUBMIT_INPUT
|
||||
do
|
||||
create f.make (a_url, a_name)
|
||||
f.set_method_post
|
||||
|
||||
f.extend_html_text ("<br/>")
|
||||
f.extend_html_text ("<legend>Are you sure you want to trash the current node?</legend>")
|
||||
if
|
||||
a_node /= Void and then
|
||||
a_node.id > 0
|
||||
then
|
||||
if a_node.is_trashed then
|
||||
f.extend_html_text ("<legend>Are you sure you want to restore the current node?</legend>")
|
||||
create ts.make ("op")
|
||||
ts.set_default_value ("Trash")
|
||||
ts.set_default_value ("Restore")
|
||||
ts.set_formaction ("/node/" + a_node.id.out + "/trash")
|
||||
ts.set_formmethod ("POST")
|
||||
fixme ("[
|
||||
ts.set_default_value (translation ("Trash"))
|
||||
]")
|
||||
f.extend (ts)
|
||||
else
|
||||
f.extend_html_text ("<legend>Are you sure you want to trash the current node?</legend>")
|
||||
create ts.make ("op")
|
||||
ts.set_default_value ("Trash")
|
||||
ts.set_formaction ("/node/" + a_node.id.out + "/trash")
|
||||
ts.set_formmethod ("POST")
|
||||
|
||||
fixme ("[
|
||||
ts.set_default_value (translation ("Trash"))
|
||||
]")
|
||||
|
||||
end
|
||||
|
||||
f.extend (ts)
|
||||
Result := f
|
||||
end
|
||||
|
||||
|
||||
@@ -174,18 +174,20 @@ feature -- HTTP Methods
|
||||
l_op.value.same_string ("Delete")
|
||||
then
|
||||
do_delete (req, res)
|
||||
elseif
|
||||
attached {WSF_STRING} req.form_parameter ("op") as l_op and then
|
||||
l_op.value.same_string ("Restore")
|
||||
then
|
||||
do_restore (req, res)
|
||||
else
|
||||
send_bad_request (req, res)
|
||||
end
|
||||
elseif req.percent_encoded_path_info.ends_with ("/trash") then
|
||||
if
|
||||
attached {WSF_STRING} req.form_parameter ("op") as l_op and then
|
||||
l_op.value.same_string ("Trash")
|
||||
then
|
||||
do_trash (req, res)
|
||||
if attached {WSF_STRING} req.form_parameter ("op") as l_op then
|
||||
if l_op.is_case_insensitive_equal ("Trash") then
|
||||
do_trash (req, res)
|
||||
elseif l_op.is_case_insensitive_equal ("Restore") then
|
||||
do_restore (req, res)
|
||||
else
|
||||
send_bad_request (req, res)
|
||||
end
|
||||
else
|
||||
send_bad_request (req, res)
|
||||
end
|
||||
elseif req.percent_encoded_path_info.starts_with ("/node/add/") then
|
||||
create edit_response.make (req, res, api, node_api)
|
||||
@@ -206,6 +208,14 @@ feature -- HTTP Methods
|
||||
send_not_implemented ("REST API not yet implemented", req, res)
|
||||
end
|
||||
|
||||
process_node_creation (req: WSF_REQUEST; res: WSF_RESPONSE; a_user: CMS_USER)
|
||||
do
|
||||
to_implement ("REST API")
|
||||
send_not_implemented ("REST API not yet implemented", req, res)
|
||||
end
|
||||
|
||||
feature {NONE} -- Trash:Restore
|
||||
|
||||
do_trash (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Trash a node, soft delete.
|
||||
do
|
||||
@@ -233,14 +243,6 @@ feature -- HTTP Methods
|
||||
end
|
||||
end
|
||||
|
||||
process_node_creation (req: WSF_REQUEST; res: WSF_RESPONSE; a_user: CMS_USER)
|
||||
do
|
||||
to_implement ("REST API")
|
||||
send_not_implemented ("REST API not yet implemented", req, res)
|
||||
end
|
||||
|
||||
feature {NONE} -- Trash:Restore
|
||||
|
||||
do_delete (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Delete a node from the database.
|
||||
local
|
||||
@@ -283,7 +285,7 @@ feature {NONE} -- Trash:Restore
|
||||
then
|
||||
if node_api.has_permission_for_action_on_node ("restore", l_node, l_user) then
|
||||
node_api.restore_node (l_node)
|
||||
res.send (create {CMS_REDIRECTION_RESPONSE_MESSAGE}.make (req.absolute_script_url ("")))
|
||||
res.send (create {CMS_REDIRECTION_RESPONSE_MESSAGE}.make (req.absolute_script_url ("/" + node_api.node_path (l_node))))
|
||||
else
|
||||
send_access_denied (req, res)
|
||||
-- send_not_authorized ?
|
||||
|
||||
@@ -11,7 +11,16 @@ inherit
|
||||
|
||||
WSF_URI_HANDLER
|
||||
rename
|
||||
new_mapping as new_uri_mapping
|
||||
new_mapping as new_uri_mapping,
|
||||
execute as execute_uri
|
||||
end
|
||||
|
||||
WSF_URI_TEMPLATE_HANDLER
|
||||
rename
|
||||
new_mapping as new_uri_template_mapping,
|
||||
execute as execute_uri_template
|
||||
select
|
||||
new_uri_template_mapping
|
||||
end
|
||||
|
||||
WSF_RESOURCE_HANDLER_HELPER
|
||||
@@ -26,6 +35,16 @@ create
|
||||
|
||||
feature -- execute
|
||||
|
||||
execute_uri (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
execute (req, res)
|
||||
end
|
||||
|
||||
execute_uri_template (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
execute (req, res)
|
||||
end
|
||||
|
||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute request handler
|
||||
do
|
||||
@@ -39,30 +58,57 @@ feature -- HTTP Methods
|
||||
local
|
||||
l_response: CMS_RESPONSE
|
||||
s: STRING
|
||||
l_content_type: detachable CMS_CONTENT_TYPE
|
||||
n: CMS_NODE
|
||||
lnk: CMS_LOCAL_LINK
|
||||
l_page_helper: CMS_PAGINATION_GENERATOR
|
||||
s_pager: STRING
|
||||
l_count: NATURAL_64
|
||||
inc: BOOLEAN
|
||||
l_include_trashed: BOOLEAN
|
||||
lst: detachable ITERABLE [CMS_NODE]
|
||||
do
|
||||
-- At the moment the template are hardcoded, but we can
|
||||
-- get them from the configuration file and load them into
|
||||
-- the setup class.
|
||||
|
||||
l_count := node_api.nodes_count
|
||||
if attached {WSF_STRING} req.path_parameter ("type") as p_node_type and then attached api.content_type (p_node_type.value) as ct then
|
||||
l_content_type := api.content_type (p_node_type.value)
|
||||
end
|
||||
|
||||
create {GENERIC_VIEW_CMS_RESPONSE} l_response.make (req, res, api)
|
||||
|
||||
create s.make_empty
|
||||
if l_count > 1 then
|
||||
l_response.set_title ("Listing " + l_count.out + " nodes")
|
||||
else
|
||||
l_response.set_title ("Listing " + l_count.out + " node")
|
||||
across
|
||||
api.content_types as ic
|
||||
loop
|
||||
if attached {CMS_NODE_TYPE [CMS_NODE]} ic.item as l_note_type then
|
||||
create lnk.make (l_note_type.name, "nodes/" + l_note_type.name)
|
||||
if l_note_type = l_content_type then
|
||||
lnk.set_is_active (True)
|
||||
end
|
||||
l_response.add_to_primary_tabs (lnk)
|
||||
end
|
||||
end
|
||||
|
||||
create s_pager.make_empty
|
||||
create l_page_helper.make ("nodes/?page={page}&size={size}", node_api.nodes_count, 25) -- FIXME: Make this default page size a global CMS settings
|
||||
if l_content_type /= Void then
|
||||
l_count := node_api.nodes_of_type_count (l_content_type)
|
||||
if l_count > 1 then
|
||||
l_response.set_title ("Listing " + l_count.out + " " + l_content_type.name + " nodes")
|
||||
else
|
||||
l_response.set_title ("Listing " + l_count.out + " " + l_content_type.name + " node")
|
||||
end
|
||||
create l_page_helper.make ("nodes/" + l_content_type.name + "/?page={page}&size={size}", l_count, 25) -- FIXME: Make this default page size a global CMS settings
|
||||
else
|
||||
l_count := node_api.nodes_count
|
||||
if l_count > 1 then
|
||||
l_response.set_title ("Listing " + l_count.out + " nodes")
|
||||
else
|
||||
l_response.set_title ("Listing " + l_count.out + " node")
|
||||
end
|
||||
create l_page_helper.make ("nodes/?page={page}&size={size}", l_count, 25) -- FIXME: Make this default page size a global CMS settings
|
||||
end
|
||||
|
||||
l_page_helper.get_setting_from_request (req)
|
||||
if l_page_helper.has_upper_limit and then l_page_helper.pages_count > 1 then
|
||||
l_page_helper.append_to_html (l_response, s_pager)
|
||||
@@ -71,7 +117,12 @@ feature -- HTTP Methods
|
||||
end
|
||||
end
|
||||
|
||||
if attached node_api.recent_nodes (create {CMS_DATA_QUERY_PARAMETERS}.make (l_page_helper.current_page_offset, l_page_helper.page_size)) as lst then
|
||||
if l_content_type /= Void then
|
||||
lst := node_api.recent_nodes_of_type (l_content_type, create {CMS_DATA_QUERY_PARAMETERS}.make (l_page_helper.current_page_offset, l_page_helper.page_size))
|
||||
else
|
||||
lst := node_api.recent_nodes (create {CMS_DATA_QUERY_PARAMETERS}.make (l_page_helper.current_page_offset, l_page_helper.page_size))
|
||||
end
|
||||
if lst /= Void then
|
||||
if attached {WSF_STRING} req.query_parameter ("include_trash") as v and then v.is_case_insensitive_equal ("yes") then
|
||||
l_include_trashed := l_response.has_permissions (<<"view trash", "view any trash">>)
|
||||
end
|
||||
@@ -80,7 +131,14 @@ feature -- HTTP Methods
|
||||
lst as ic
|
||||
loop
|
||||
n := ic.item
|
||||
if not n.is_trashed or else l_include_trashed then
|
||||
inc := True
|
||||
if not n.is_published then
|
||||
inc := view_unpublished_node_permitted (n)
|
||||
end
|
||||
if inc and n.is_trashed then
|
||||
inc := l_include_trashed
|
||||
end
|
||||
if inc then
|
||||
lnk := node_api.node_link (n)
|
||||
s.append ("<li class=%"cms_type_"+ n.content_type)
|
||||
if not n.is_published then
|
||||
@@ -131,4 +189,15 @@ feature -- HTTP Methods
|
||||
l_response.execute
|
||||
end
|
||||
|
||||
feature -- Helper
|
||||
|
||||
view_unpublished_node_permitted (n: CMS_NODE): BOOLEAN
|
||||
do
|
||||
if api.has_permission ("view unpublished " + n.content_type) then
|
||||
Result := True
|
||||
elseif attached api.user as u then
|
||||
Result := u.same_as (n.author)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json.ecf"/>
|
||||
<library name="text_filter" location="$ISE_LIBRARY\unstable\library\text\text_filter\text_filter.ecf"/>
|
||||
<library name="time" location="$ISE_LIBRARY\library\time\time.ecf"/>
|
||||
<library name="uri" location="$ISE_LIBRARY\library\text\uri\uri.ecf"/>
|
||||
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf.ecf"/>
|
||||
<library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension.ecf" readonly="false"/>
|
||||
<library name="wsf_html" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf_html\wsf_html.ecf" readonly="false"/>
|
||||
|
||||
@@ -100,6 +100,13 @@ feature -- Access
|
||||
deferred
|
||||
end
|
||||
|
||||
recent_nodes_of_type (a_node_type: CMS_CONTENT_TYPE; a_lower: INTEGER; a_count: INTEGER): LIST [CMS_NODE]
|
||||
-- Recent `a_count` nodes of type `a_node_type` with an offset of `lower`.
|
||||
deferred
|
||||
ensure
|
||||
across Result as ic all ic.item.is_typed_as (a_node_type.name) end
|
||||
end
|
||||
|
||||
recent_node_changes_before (a_lower: INTEGER; a_count: INTEGER; a_date: DATE_TIME): LIST [CMS_NODE]
|
||||
-- List of recent changes, before `a_date', according to `params' settings.
|
||||
deferred
|
||||
@@ -120,6 +127,12 @@ feature -- Access
|
||||
deferred
|
||||
end
|
||||
|
||||
nodes_of_type_count (a_node_type: CMS_CONTENT_TYPE): NATURAL_64
|
||||
-- Count of nodes of type `a_node_type`.
|
||||
do
|
||||
Result := nodes_of_type (a_node_type).count.to_natural_64
|
||||
end
|
||||
|
||||
nodes_of_type (a_node_type: CMS_CONTENT_TYPE): LIST [CMS_NODE]
|
||||
-- List of nodes of type `a_node_type'.
|
||||
--| Redefine to optimize!
|
||||
@@ -137,7 +150,7 @@ feature -- Access
|
||||
end
|
||||
end
|
||||
ensure
|
||||
expected_type: across Result as ic all ic.item.content_type.same_string (a_node_type.name) end
|
||||
expected_type: across Result as ic all ic.item.is_typed_as (a_node_type.name) end
|
||||
end
|
||||
|
||||
nodes_of_type_with_title (a_node_type: CMS_CONTENT_TYPE; a_title: READABLE_STRING_GENERAL): LIST [CMS_NODE]
|
||||
|
||||
@@ -59,6 +59,12 @@ feature -- Access: node
|
||||
create {ARRAYED_LIST [CMS_NODE]} Result.make (0)
|
||||
end
|
||||
|
||||
recent_nodes_of_type (a_node_type: CMS_CONTENT_TYPE; a_lower: INTEGER; a_count: INTEGER): LIST [CMS_NODE]
|
||||
-- Recent `a_count` nodes of type `a_node_type` with an offset of `lower`.
|
||||
do
|
||||
create {ARRAYED_LIST [CMS_NODE]} Result.make (0)
|
||||
end
|
||||
|
||||
recent_node_changes_before (a_lower: INTEGER; a_count: INTEGER; a_date: DATE_TIME): LIST [CMS_NODE]
|
||||
-- List of recent changes, before `a_date', according to `params' settings.
|
||||
do
|
||||
|
||||
@@ -13,6 +13,7 @@ inherit
|
||||
|
||||
CMS_NODE_STORAGE_I
|
||||
redefine
|
||||
nodes_of_type_count,
|
||||
nodes_of_type,
|
||||
nodes_of_type_with_title
|
||||
end
|
||||
@@ -38,6 +39,22 @@ feature -- Access
|
||||
sql_finalize
|
||||
end
|
||||
|
||||
nodes_of_type_count (a_node_type: CMS_CONTENT_TYPE): NATURAL_64
|
||||
-- Count of nodes of type `a_node_type`.
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
do
|
||||
error_handler.reset
|
||||
|
||||
create l_parameters.make (1)
|
||||
l_parameters.force (a_node_type.name, "node_type")
|
||||
sql_query (sql_select_nodes_of_type_count, l_parameters)
|
||||
if not has_error and not sql_after then
|
||||
Result := sql_read_natural_64 (1)
|
||||
end
|
||||
sql_finalize
|
||||
end
|
||||
|
||||
nodes: LIST [CMS_NODE]
|
||||
-- List of nodes.
|
||||
do
|
||||
@@ -145,6 +162,31 @@ feature -- Access
|
||||
sql_finalize
|
||||
end
|
||||
|
||||
recent_nodes_of_type (a_node_type: CMS_CONTENT_TYPE; a_lower: INTEGER; a_count: INTEGER): LIST [CMS_NODE]
|
||||
-- Recent `a_count` nodes of type `a_node_type` with an offset of `lower`.
|
||||
local
|
||||
l_parameters: STRING_TABLE [detachable ANY]
|
||||
do
|
||||
create {ARRAYED_LIST [CMS_NODE]} Result.make (0)
|
||||
error_handler.reset
|
||||
from
|
||||
create l_parameters.make (3)
|
||||
l_parameters.put (a_node_type.name, "node_type")
|
||||
l_parameters.put (a_count, "size")
|
||||
l_parameters.put (a_lower, "offset")
|
||||
sql_query (sql_select_recent_nodes_of_type, l_parameters)
|
||||
sql_start
|
||||
until
|
||||
sql_after
|
||||
loop
|
||||
if attached fetch_node as l_node then
|
||||
Result.force (l_node)
|
||||
end
|
||||
sql_forth
|
||||
end
|
||||
sql_finalize
|
||||
end
|
||||
|
||||
recent_node_changes_before (a_lower: INTEGER; a_count: INTEGER; a_date: DATE_TIME): LIST [CMS_NODE]
|
||||
-- List of recent changes, before `a_date', according to `params' settings.
|
||||
local
|
||||
@@ -270,7 +312,7 @@ feature -- Access
|
||||
sql_after
|
||||
loop
|
||||
if attached fetch_node as l_node then
|
||||
check expected_node_type: l_node.content_type.same_string (a_node_type.name) end
|
||||
check expected_node_type: l_node.is_typed_as (a_node_type.name) end
|
||||
Result.force (l_node)
|
||||
end
|
||||
sql_forth
|
||||
@@ -474,6 +516,10 @@ feature {NONE} -- Queries
|
||||
-- Nodes count (Published and not Published)
|
||||
--| note: {CMS_NODE_API}.trashed = -1
|
||||
|
||||
sql_select_nodes_of_type_count: STRING = "SELECT count(*) FROM nodes WHERE type=:node_type AND status != -1 ;"
|
||||
-- Nodes of type `:node_type` count (Published and not Published)
|
||||
--| note: {CMS_NODE_API}.trashed = -1
|
||||
|
||||
sql_select_nodes: STRING = "SELECT nid, revision, type, title, summary, content, format, author, publish, created, changed, status FROM nodes WHERE status != -1 ;"
|
||||
-- SQL Query to retrieve all nodes.
|
||||
--| note: {CMS_NODE_API}.trashed = -1
|
||||
@@ -503,6 +549,8 @@ feature {NONE} -- Queries
|
||||
|
||||
sql_select_recent_nodes: STRING = "SELECT nid, revision, type, title, summary, content, format, author, publish, created, changed, status FROM nodes ORDER BY changed DESC, publish DESC LIMIT :size OFFSET :offset ;"
|
||||
|
||||
sql_select_recent_nodes_of_type: STRING = "SELECT nid, revision, type, title, summary, content, format, author, publish, created, changed, status FROM nodes WHERE type=:node_type ORDER BY changed DESC, publish DESC LIMIT :size OFFSET :offset ;"
|
||||
|
||||
sql_select_recent_node_changes_before: STRING = "SELECT nid, revision, type, title, summary, content, format, author, publish, created, changed, status FROM nodes WHERE changed <= :date ORDER BY changed DESC, nid DESC LIMIT :size OFFSET :offset ;"
|
||||
|
||||
sql_insert_node: STRING = "INSERT INTO nodes (revision, type, title, summary, content, format, publish, created, changed, status, author) VALUES (:revision, :type, :title, :summary, :content, :format, :publish, :created, :changed, :status, :author);"
|
||||
|
||||
@@ -318,7 +318,7 @@ feature -- Web forms
|
||||
s.append_character (',')
|
||||
s.append_character (' ')
|
||||
end
|
||||
if ic.item.text.has (' ') then
|
||||
if ic.item.text.has (',') then
|
||||
s.append_character ('"')
|
||||
s.append (t.text)
|
||||
s.append_character ('"')
|
||||
|
||||
98
src/kernel/content/cms_smarty_template_text.e
Normal file
98
src/kernel/content/cms_smarty_template_text.e
Normal file
@@ -0,0 +1,98 @@
|
||||
note
|
||||
description: "[
|
||||
CMS text with smarty template text content.
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_SMARTY_TEMPLATE_TEXT
|
||||
|
||||
inherit
|
||||
ANY
|
||||
|
||||
SHARED_TEMPLATE_CONTEXT
|
||||
undefine
|
||||
is_equal
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_source: like source)
|
||||
-- Create template text from `a_source`.
|
||||
do
|
||||
source := a_source
|
||||
create values.make (0)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
source: READABLE_STRING_8
|
||||
-- Template source.
|
||||
|
||||
values: STRING_TABLE [detachable ANY]
|
||||
-- Additional value used during template output processing.
|
||||
|
||||
value (k: READABLE_STRING_GENERAL): detachable ANY assign set_value
|
||||
do
|
||||
Result := values.item (k)
|
||||
end
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_value (v: detachable ANY; k: READABLE_STRING_GENERAL)
|
||||
-- Associate value `v' with key `k'.
|
||||
do
|
||||
values.force (v, k)
|
||||
end
|
||||
|
||||
unset_value (k: READABLE_STRING_GENERAL)
|
||||
-- Remove value indexed by key `k'.
|
||||
do
|
||||
values.remove (k)
|
||||
end
|
||||
|
||||
feature -- Conversion
|
||||
|
||||
string: STRING_8
|
||||
-- <Precursor>
|
||||
local
|
||||
tpl: detachable TEMPLATE_TEXT
|
||||
l_table_inspector: detachable STRING_TABLE_OF_STRING_INSPECTOR
|
||||
do
|
||||
template_context.disable_verbose
|
||||
debug ("cms")
|
||||
template_context.enable_verbose
|
||||
end
|
||||
|
||||
create tpl.make_from_text (source)
|
||||
|
||||
across
|
||||
values as ic
|
||||
loop
|
||||
tpl.add_value (ic.item, ic.key)
|
||||
end
|
||||
|
||||
create l_table_inspector.register (({detachable STRING_TABLE [STRING_8]}).name)
|
||||
create l_table_inspector.register (({detachable STRING_TABLE [STRING_32]}).name)
|
||||
create l_table_inspector.register (({detachable STRING_TABLE [READABLE_STRING_8]}).name)
|
||||
create l_table_inspector.register (({detachable STRING_TABLE [READABLE_STRING_32]}).name)
|
||||
tpl.get_structure
|
||||
tpl.get_output
|
||||
l_table_inspector.unregister
|
||||
-- l_table32_inspector.unregister
|
||||
|
||||
if attached tpl.output as l_output then
|
||||
Result := l_output
|
||||
else
|
||||
Result := source
|
||||
end
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
end
|
||||
@@ -24,19 +24,34 @@ feature -- URL aliases
|
||||
-- <Precursor>
|
||||
local
|
||||
l_parameters: STRING_TABLE [detachable ANY]
|
||||
l_source: like source_of_path_alias
|
||||
l_continue: BOOLEAN
|
||||
do
|
||||
error_handler.reset
|
||||
|
||||
create l_parameters.make (2)
|
||||
l_parameters.put (a_source, "source")
|
||||
l_parameters.put (a_alias, "alias")
|
||||
if attached source_of_path_alias (a_alias) as l_path then
|
||||
if a_source.same_string (l_path) then
|
||||
-- already up to date
|
||||
l_source := source_of_path_alias (a_alias)
|
||||
l_continue := True
|
||||
if
|
||||
l_source /= Void -- Alias exists!
|
||||
then
|
||||
if a_source.same_string (l_source) then
|
||||
if attached path_alias (l_source) as l_alias and then l_alias.same_string (a_alias) then
|
||||
-- already up to date
|
||||
l_continue := False
|
||||
else
|
||||
-- multiple alias and a_alias is not the default alias
|
||||
-- then unset, and set again !
|
||||
unset_path_alias (a_source, a_alias)
|
||||
end
|
||||
else
|
||||
l_continue := False
|
||||
error_handler.add_custom_error (0, "alias exists", "Path alias %"" + a_alias + "%" already exists!")
|
||||
end
|
||||
else
|
||||
end
|
||||
if l_continue then
|
||||
sql_insert (sql_insert_path_alias, l_parameters)
|
||||
sql_finalize
|
||||
end
|
||||
|
||||
@@ -44,6 +44,9 @@ feature {NONE} -- Initialize
|
||||
l_enabled_modules: CMS_MODULE_COLLECTION
|
||||
l_uninstalled_mods: detachable ARRAYED_LIST [CMS_MODULE]
|
||||
do
|
||||
-- Initialize site_url
|
||||
initialize_site_url
|
||||
|
||||
-- Initialize formats.
|
||||
initialize_formats
|
||||
-- Initialize contents.
|
||||
@@ -101,6 +104,35 @@ feature {NONE} -- Initialize
|
||||
setup_hooks
|
||||
end
|
||||
|
||||
initialize_site_url
|
||||
-- Initialize site and base url.
|
||||
local
|
||||
l_url: detachable STRING_8
|
||||
i,j: INTEGER
|
||||
do
|
||||
--| WARNING: do not use `absolute_url' and `url', since it relies on site_url and base_url.
|
||||
if attached setup.site_url as l_site_url and then not l_site_url.is_empty then
|
||||
create l_url.make_from_string (l_site_url)
|
||||
else
|
||||
l_url := request.absolute_script_url ("/")
|
||||
end
|
||||
check is_not_empty: not l_url.is_empty end
|
||||
if l_url [l_url.count] /= '/' then
|
||||
l_url.append_character ('/')
|
||||
end
|
||||
site_url := l_url
|
||||
i := l_url.substring_index ("://", 1)
|
||||
if i > 0 then
|
||||
j := l_url.index_of ('/', i + 3)
|
||||
if j > 0 then
|
||||
base_url := l_url.substring (j, l_url.count)
|
||||
end
|
||||
end
|
||||
ensure
|
||||
site_url_set: site_url /= Void
|
||||
site_url_ends_with_slash: site_url.ends_with_general ("/")
|
||||
end
|
||||
|
||||
initialize_content_types
|
||||
-- Initialize content types.
|
||||
do
|
||||
@@ -199,6 +231,16 @@ feature -- Access
|
||||
storage: CMS_STORAGE
|
||||
-- Default persistence storage.
|
||||
|
||||
feature -- Access: url
|
||||
|
||||
site_url: IMMUTABLE_STRING_8
|
||||
-- Site url
|
||||
|
||||
base_url: detachable IMMUTABLE_STRING_8
|
||||
-- Base url if any.
|
||||
--| Usually it is Void, but it could be
|
||||
--| /project/demo/
|
||||
|
||||
feature -- Settings
|
||||
|
||||
is_debug: BOOLEAN
|
||||
@@ -400,6 +442,8 @@ feature -- Emails
|
||||
setup.mailer.safe_process_email (e)
|
||||
if setup.mailer.has_error then
|
||||
error_handler.add_custom_error (0, "Mailer error", "Error occurred while processing email.")
|
||||
else
|
||||
e.set_is_sent (True)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -442,7 +486,13 @@ feature -- Permissions system
|
||||
-- Anonymous or user `user' has permission for `a_permission'?
|
||||
--| `a_permission' could be for instance "create page".
|
||||
do
|
||||
Result := user_api.user_has_permission (user, a_permission)
|
||||
Result := user_has_permission (user, a_permission)
|
||||
end
|
||||
|
||||
has_permissions (a_permission_list: ITERABLE [READABLE_STRING_GENERAL]): BOOLEAN
|
||||
-- Anonymous or user `user' has any of the permissions `a_permission_list`?
|
||||
do
|
||||
Result := user_has_permissions (user, a_permission_list)
|
||||
end
|
||||
|
||||
user_has_permission (a_user: detachable CMS_USER; a_permission: detachable READABLE_STRING_GENERAL): BOOLEAN
|
||||
@@ -452,6 +502,18 @@ feature -- Permissions system
|
||||
Result := user_api.user_has_permission (a_user, a_permission)
|
||||
end
|
||||
|
||||
user_has_permissions (a_user: detachable CMS_USER; a_permission_list: ITERABLE [READABLE_STRING_GENERAL]): BOOLEAN
|
||||
-- Does `a_user' has any of the permissions `a_permission_list' ?
|
||||
do
|
||||
across
|
||||
a_permission_list as ic
|
||||
until
|
||||
Result
|
||||
loop
|
||||
Result := user_has_permission (a_user, ic.item)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Query: module
|
||||
|
||||
is_module_installed (a_module: CMS_MODULE): BOOLEAN
|
||||
@@ -905,6 +967,24 @@ feature -- Access: active user
|
||||
user_api.update_user (a_user)
|
||||
end
|
||||
|
||||
feature -- Site builtin variables
|
||||
|
||||
builtin_variables: STRING_TABLE [detachable ANY]
|
||||
-- Builtin variables , value indexed by name.
|
||||
do
|
||||
create Result.make (7)
|
||||
|
||||
Result["site_url"] := site_url
|
||||
Result["site_email"] := setup.site_email
|
||||
Result["site_name"] := setup.site_name
|
||||
if attached user as l_user then
|
||||
Result["active_user"] := l_user
|
||||
Result["user"] := l_user.name
|
||||
Result["user_id"] := l_user.id
|
||||
Result["user_profile_name"] := user_api.user_display_name (l_user)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Request utilities
|
||||
|
||||
execution_variable (a_name: READABLE_STRING_GENERAL): detachable ANY
|
||||
|
||||
@@ -160,7 +160,7 @@ feature -- Import
|
||||
|
||||
import_json_user (j_user: JSON_OBJECT; a_import_ctx: CMS_IMPORT_CONTEXT)
|
||||
local
|
||||
l_user_by_name, l_user_by_email: detachable CMS_USER
|
||||
l_user_by_name, l_user_by_email, l_user: detachable CMS_USER
|
||||
do
|
||||
if attached json_to_user (j_user) as u then
|
||||
l_user_by_name := user_api.user_by_name (u.name)
|
||||
@@ -170,6 +170,28 @@ feature -- Import
|
||||
if l_user_by_name /= Void or l_user_by_email /= Void then
|
||||
a_import_ctx.log ("Skip user %"" + u.name + "%": already exists!")
|
||||
-- Already exists!
|
||||
if l_user_by_email /= Void then
|
||||
l_user := l_user_by_email
|
||||
if
|
||||
l_user_by_name /= Void and then
|
||||
l_user_by_name.same_as (l_user)
|
||||
then
|
||||
-- Two different accounts exists!
|
||||
a_import_ctx.log ("Two different accounts already exists for username %"" + u.name + "%" !")
|
||||
end
|
||||
else
|
||||
l_user := l_user_by_name
|
||||
end
|
||||
-- Check if new information are now available.
|
||||
if
|
||||
l_user /= Void and then
|
||||
l_user.profile_name = Void and then
|
||||
attached u.profile_name as l_new_prof_name and then
|
||||
not l_new_prof_name.is_whitespace
|
||||
then
|
||||
l_user.set_profile_name (l_new_prof_name)
|
||||
user_api.update_user (l_user)
|
||||
end
|
||||
else
|
||||
user_api.new_user (u)
|
||||
a_import_ctx.log ("New user %"" + u.name + "%" -> " + u.id.out + " .")
|
||||
|
||||
@@ -12,7 +12,19 @@ inherit
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Status report
|
||||
|
||||
is_sent: BOOLEAN
|
||||
-- Current Email is sent.
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_is_sent (b: BOOLEAN)
|
||||
do
|
||||
is_sent := b
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
end
|
||||
|
||||
@@ -24,46 +24,18 @@ feature {NONE} -- Initialization
|
||||
response := res
|
||||
create header.make
|
||||
create values.make (3)
|
||||
site_url := a_api.site_url
|
||||
base_url := a_api.base_url
|
||||
initialize
|
||||
end
|
||||
|
||||
initialize
|
||||
do
|
||||
initialize_site_url
|
||||
get_theme
|
||||
create menu_system.make
|
||||
initialize_block_region_settings
|
||||
end
|
||||
|
||||
initialize_site_url
|
||||
-- Initialize site and base url.
|
||||
local
|
||||
l_url: detachable STRING_8
|
||||
i,j: INTEGER
|
||||
do
|
||||
--| WARNING: do not use `absolute_url' and `url', since it relies on site_url and base_url.
|
||||
if attached setup.site_url as l_site_url and then not l_site_url.is_empty then
|
||||
create l_url.make_from_string (l_site_url)
|
||||
else
|
||||
l_url := request.absolute_script_url ("/")
|
||||
end
|
||||
check is_not_empty: not l_url.is_empty end
|
||||
if l_url [l_url.count] /= '/' then
|
||||
l_url.append_character ('/')
|
||||
end
|
||||
site_url := l_url
|
||||
i := l_url.substring_index ("://", 1)
|
||||
if i > 0 then
|
||||
j := l_url.index_of ('/', i + 3)
|
||||
if j > 0 then
|
||||
base_url := l_url.substring (j, l_url.count)
|
||||
end
|
||||
end
|
||||
ensure
|
||||
site_url_set: site_url /= Void
|
||||
site_url_ends_with_slash: site_url.ends_with_general ("/")
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
request: WSF_REQUEST
|
||||
@@ -236,13 +208,7 @@ feature -- Permission
|
||||
user_has_permissions (a_user: detachable CMS_USER; a_permission_list: ITERABLE [READABLE_STRING_GENERAL]): BOOLEAN
|
||||
-- Does `a_user' has any of the permissions `a_permission_list' ?
|
||||
do
|
||||
across
|
||||
a_permission_list as ic
|
||||
until
|
||||
Result
|
||||
loop
|
||||
Result := user_has_permission (a_user, ic.item)
|
||||
end
|
||||
Result := api.user_has_permissions (a_user, a_permission_list)
|
||||
end
|
||||
|
||||
feature -- Head customization
|
||||
@@ -1088,6 +1054,17 @@ feature -- Cache managment
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Response builtin variables
|
||||
|
||||
builtin_variables: STRING_TABLE [detachable ANY]
|
||||
-- builtin variables value indexed by name.
|
||||
do
|
||||
Result := api.builtin_variables
|
||||
Result ["site_url"] := site_url
|
||||
Result ["host"] := site_url -- FIXME: check and remove if unused.
|
||||
Result ["is_https"] := request.is_https
|
||||
end
|
||||
|
||||
feature -- Generation
|
||||
|
||||
prepare (page: CMS_HTML_PAGE)
|
||||
@@ -1233,14 +1210,17 @@ feature -- Generation
|
||||
end
|
||||
end
|
||||
|
||||
-- Fill with CMS builtin variables.
|
||||
across
|
||||
builtin_variables as ic
|
||||
loop
|
||||
page.register_variable (ic.item, ic.key)
|
||||
end
|
||||
|
||||
-- Variables
|
||||
page.register_variable (absolute_url ("", Void), "site_url")
|
||||
page.register_variable (absolute_url ("", Void), "host") -- Same as `site_url'.
|
||||
page.register_variable (request.is_https, "is_https")
|
||||
if attached user as l_user then
|
||||
page.register_variable (l_user.name, "user")
|
||||
page.register_variable (user_profile_name (l_user), "user_profile_name")
|
||||
end
|
||||
if attached title as l_title then
|
||||
page.register_variable (l_title, "site_title")
|
||||
else
|
||||
@@ -1358,15 +1338,9 @@ feature -- Helpers: cms link
|
||||
|
||||
feature -- Helpers: html links
|
||||
|
||||
user_profile_name (u: CMS_USER): READABLE_STRING_32
|
||||
user_profile_name, user_display_name (u: CMS_USER): READABLE_STRING_32
|
||||
do
|
||||
if attached u.profile_name as pn and then not pn.is_whitespace then
|
||||
Result := pn
|
||||
elseif not u.name.is_whitespace then
|
||||
Result := u.name
|
||||
else
|
||||
Result := {STRING_32} "user #" + u.id.out
|
||||
end
|
||||
Result := api.user_api.user_display_name (u)
|
||||
end
|
||||
|
||||
user_html_link (u: CMS_USER): STRING
|
||||
|
||||
@@ -68,6 +68,20 @@ feature -- Validation
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Query
|
||||
|
||||
user_display_name (u: CMS_USER): READABLE_STRING_32
|
||||
-- Display name for user `u`.
|
||||
do
|
||||
if attached u.profile_name as pn and then not pn.is_whitespace then
|
||||
Result := pn
|
||||
elseif not u.name.is_whitespace then
|
||||
Result := u.name
|
||||
else
|
||||
Result := {STRING_32} "user #" + u.id.out
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Access: user
|
||||
|
||||
user_by_id (a_id: like {CMS_USER}.id): detachable CMS_USER
|
||||
|
||||
Reference in New Issue
Block a user