")
if attached a_node.author as l_author then
@@ -430,6 +458,4 @@ feature -- Output
end
a_output.append ("")
end
-
end
-
diff --git a/modules/node/handler/node_form_response.e b/modules/node/handler/node_form_response.e
index e1c750c..804fef6 100644
--- a/modules/node/handler/node_form_response.e
+++ b/modules/node/handler/node_form_response.e
@@ -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 ("
")
- f.extend_html_text ("
")
+ f.extend_html_text ("
")
-- 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 ("
")
- f.extend_html_text ("
")
- 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 ("
")
- f.extend_html_text ("
")
- if
- a_node /= Void and then
- a_node.id > 0
- then
+ if a_node.is_trashed then
+ f.extend_html_text ("
")
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 ("
")
+ 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
diff --git a/modules/node/handler/node_handler.e b/modules/node/handler/node_handler.e
index 52d52eb..1518e80 100644
--- a/modules/node/handler/node_handler.e
+++ b/modules/node/handler/node_handler.e
@@ -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 ?
diff --git a/modules/node/handler/nodes_handler.e b/modules/node/handler/nodes_handler.e
index 7d87d1f..f9a5131 100644
--- a/modules/node/handler/nodes_handler.e
+++ b/modules/node/handler/nodes_handler.e
@@ -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 ("
+
diff --git a/modules/node/persistence/cms_node_storage_i.e b/modules/node/persistence/cms_node_storage_i.e
index fabf03e..53fa89a 100644
--- a/modules/node/persistence/cms_node_storage_i.e
+++ b/modules/node/persistence/cms_node_storage_i.e
@@ -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]
diff --git a/modules/node/persistence/cms_node_storage_null.e b/modules/node/persistence/cms_node_storage_null.e
index 6196d8f..978dc06 100644
--- a/modules/node/persistence/cms_node_storage_null.e
+++ b/modules/node/persistence/cms_node_storage_null.e
@@ -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
diff --git a/modules/node/persistence/cms_node_storage_sql.e b/modules/node/persistence/cms_node_storage_sql.e
index 51cab65..b61079d 100644
--- a/modules/node/persistence/cms_node_storage_sql.e
+++ b/modules/node/persistence/cms_node_storage_sql.e
@@ -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);"
diff --git a/modules/taxonomy/cms_taxonomy_api.e b/modules/taxonomy/cms_taxonomy_api.e
index 1cd781a..bec5114 100644
--- a/modules/taxonomy/cms_taxonomy_api.e
+++ b/modules/taxonomy/cms_taxonomy_api.e
@@ -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 ('"')
diff --git a/src/kernel/content/cms_smarty_template_text.e b/src/kernel/content/cms_smarty_template_text.e
new file mode 100644
index 0000000..f6dd782
--- /dev/null
+++ b/src/kernel/content/cms_smarty_template_text.e
@@ -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
+ --
+ 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
diff --git a/src/persistence/core/cms_core_storage_sql_i.e b/src/persistence/core/cms_core_storage_sql_i.e
index 1329cd3..6e5a877 100644
--- a/src/persistence/core/cms_core_storage_sql_i.e
+++ b/src/persistence/core/cms_core_storage_sql_i.e
@@ -24,19 +24,34 @@ feature -- URL aliases
--
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
diff --git a/src/service/cms_api.e b/src/service/cms_api.e
index fb4fefa..3b135d1 100644
--- a/src/service/cms_api.e
+++ b/src/service/cms_api.e
@@ -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
diff --git a/src/service/cms_api_import_imp.e b/src/service/cms_api_import_imp.e
index f3fec86..b27a8ef 100644
--- a/src/service/cms_api_import_imp.e
+++ b/src/service/cms_api_import_imp.e
@@ -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 + " .")
diff --git a/src/service/cms_email.e b/src/service/cms_email.e
index a61d9d8..fb33b49 100644
--- a/src/service/cms_email.e
+++ b/src/service/cms_email.e
@@ -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
diff --git a/src/service/response/cms_response.e b/src/service/response/cms_response.e
index 130aa24..f2fc91b 100644
--- a/src/service/response/cms_response.e
+++ b/src/service/response/cms_response.e
@@ -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
diff --git a/src/service/user/cms_user_api.e b/src/service/user/cms_user_api.e
index f402a8f..082b4a5 100644
--- a/src/service/user/cms_user_api.e
+++ b/src/service/user/cms_user_api.e
@@ -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