Added support for OpenID identity
Added user roles management Improvement CMS_HOOK_FORM_ALTER design. Factorized code into CMS_WIDGET_COMPOSITE Use general notion of CMS_WIDGET (and CMS_FORM allows CMS_WIDGET, and not just CMS_FORM_ITEM) Fixed various CMS_WIDGET traversal, and fixed related issue for CMS forms Fixed CMS_FORM_CHECKBOX_INPUT when no value was set. Added CMS_FORM_DATA.cached_value .. to pass computed values during validation to submit actions (mainly for optimization) Added support for @include=filename in CMS_CONFIGURATION Added CMS_WIDGET_TABLE as filled version of CMS_WIDGET_AGENT_TABLE (renamed from previous CMS_WIDGET_TABLE) Many improvements to the CMS_FORM design Some improvements to CMS_MODULE ...
This commit is contained in:
@@ -6,7 +6,7 @@ class
|
||||
NODE_ADD_CMS_EXECUTION
|
||||
|
||||
inherit
|
||||
CMS_EXECUTION
|
||||
NODE_CMS_EXECUTION
|
||||
|
||||
create
|
||||
make
|
||||
@@ -19,71 +19,20 @@ feature -- Execution
|
||||
b: STRING_8
|
||||
f: like edit_form
|
||||
fd: detachable CMS_FORM_DATA
|
||||
l_preview: BOOLEAN
|
||||
l_format: detachable CMS_FORMAT
|
||||
do
|
||||
create b.make_empty
|
||||
if attached non_empty_string_path_parameter ("type") as s_type then
|
||||
if attached service.content_type (s_type) as l_type then
|
||||
f := edit_form (Void, url (request.path_info, Void), "add-" + l_type.name, l_type)
|
||||
if request.is_post_request_method then
|
||||
create fd.make (request, f)
|
||||
l_preview := attached {WSF_STRING} fd.item ("op") as l_op and then l_op.same_string ("Preview")
|
||||
end
|
||||
|
||||
set_title ("Create " + l_type.title)
|
||||
if has_permission ("create " + l_type.name) then
|
||||
|
||||
if fd /= Void and l_preview then
|
||||
b.append ("<strong>Preview</strong><div class=%"preview%">")
|
||||
if attached fd.string_item ("format") as s_format and then attached formats.format (s_format) as f_format then
|
||||
l_format := f_format
|
||||
end
|
||||
if attached fd.string_item ("title") as l_title then
|
||||
b.append ("<strong>Title:</strong><div class=%"title%">" + html_encoded (l_title) + "</div>")
|
||||
end
|
||||
if attached fd.string_item ("body") as l_body then
|
||||
b.append ("<strong>Body:</strong><div class=%"body%">")
|
||||
if l_format /= Void then
|
||||
b.append (l_format.to_html (l_body))
|
||||
else
|
||||
b.append (html_encoded (l_body))
|
||||
end
|
||||
b.append ("</div>")
|
||||
end
|
||||
b.append ("</div>")
|
||||
end
|
||||
|
||||
if fd /= Void and then fd.is_valid and not l_preview then
|
||||
across
|
||||
fd as c
|
||||
loop
|
||||
b.append ("<li>" + html_encoded (c.key) + "=")
|
||||
if attached c.item as v then
|
||||
b.append (html_encoded (v.string_representation))
|
||||
end
|
||||
b.append ("</li>")
|
||||
end
|
||||
if attached l_type.new_node (Current, fd, Void) as l_node then
|
||||
service.storage.save_node (l_node)
|
||||
if attached user as u then
|
||||
service.log ("node", "User %"" + user_link (u) + "%" created node " + link (l_type.name +" #" + l_node.id.out, "/node/" + l_node.id.out , Void), 0, node_local_link (l_node))
|
||||
else
|
||||
service.log ("node", "Anonymous created node "+ l_type.name +" #" + l_node.id.out, 0, node_local_link (l_node))
|
||||
end
|
||||
add_success_message ("Node #" + l_node.id.out + " saved.")
|
||||
set_redirection (node_url (l_node))
|
||||
end
|
||||
-- Creation ...
|
||||
else
|
||||
if fd /= Void then
|
||||
if not fd.is_valid then
|
||||
report_form_errors (fd)
|
||||
end
|
||||
fd.apply_to_associated_form
|
||||
end
|
||||
f.append_to_html (theme, b)
|
||||
if request.is_post_request_method then
|
||||
f.validation_actions.extend (agent edit_form_validate (?, b))
|
||||
f.submit_actions.extend (agent edit_form_submit (?, Void, l_type, b))
|
||||
f.process (Current)
|
||||
fd := f.last_data
|
||||
end
|
||||
f.append_to_html (theme, b)
|
||||
else
|
||||
set_title ("Access denied")
|
||||
end
|
||||
@@ -109,35 +58,4 @@ feature -- Execution
|
||||
set_main_content (b)
|
||||
end
|
||||
|
||||
edit_form (a_node: detachable CMS_NODE; a_url: READABLE_STRING_8; a_name: STRING; a_type: CMS_CONTENT_TYPE): CMS_FORM
|
||||
local
|
||||
f: CMS_FORM
|
||||
ts: CMS_FORM_SUBMIT_INPUT
|
||||
th: CMS_FORM_HIDDEN_INPUT
|
||||
do
|
||||
create f.make (a_url, a_name)
|
||||
|
||||
create th.make ("node-id")
|
||||
if a_node /= Void then
|
||||
th.set_text_value (a_node.id.out)
|
||||
else
|
||||
th.set_text_value ("0")
|
||||
end
|
||||
f.extend (th)
|
||||
|
||||
a_type.fill_edit_form (f, a_node)
|
||||
|
||||
f.extend_text ("<br/>")
|
||||
|
||||
create ts.make ("op")
|
||||
ts.set_default_value ("Save")
|
||||
f.extend (ts)
|
||||
|
||||
create ts.make ("op")
|
||||
ts.set_default_value ("Preview")
|
||||
f.extend (ts)
|
||||
|
||||
Result := f
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
141
draft/application/cms/src/modules/node/node_cms_execution.e
Normal file
141
draft/application/cms/src/modules/node/node_cms_execution.e
Normal file
@@ -0,0 +1,141 @@
|
||||
note
|
||||
description: "Summary description for {NODE_CMS_EXECUTION}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
NODE_CMS_EXECUTION
|
||||
|
||||
inherit
|
||||
CMS_EXECUTION
|
||||
|
||||
feature -- Form
|
||||
|
||||
edit_form_validate (fd: CMS_FORM_DATA; b: STRING)
|
||||
local
|
||||
l_preview: BOOLEAN
|
||||
l_format: detachable CMS_FORMAT
|
||||
do
|
||||
l_preview := attached {WSF_STRING} fd.item ("op") as l_op and then l_op.same_string ("Preview")
|
||||
if l_preview then
|
||||
b.append ("<strong>Preview</strong><div class=%"preview%">")
|
||||
if attached fd.string_item ("format") as s_format and then attached formats.format (s_format) as f_format then
|
||||
l_format := f_format
|
||||
end
|
||||
if attached fd.string_item ("title") as l_title then
|
||||
b.append ("<strong>Title:</strong><div class=%"title%">" + html_encoded (l_title) + "</div>")
|
||||
end
|
||||
if attached fd.string_item ("body") as l_body then
|
||||
b.append ("<strong>Body:</strong><div class=%"body%">")
|
||||
if l_format /= Void then
|
||||
b.append (l_format.to_html (l_body))
|
||||
else
|
||||
b.append (html_encoded (l_body))
|
||||
end
|
||||
b.append ("</div>")
|
||||
end
|
||||
b.append ("</div>")
|
||||
end
|
||||
end
|
||||
|
||||
edit_form_submit (fd: CMS_FORM_DATA; a_node: detachable CMS_NODE; a_type: CMS_CONTENT_TYPE; b: STRING)
|
||||
local
|
||||
l_preview: BOOLEAN
|
||||
l_node: detachable CMS_NODE
|
||||
s: STRING
|
||||
do
|
||||
l_preview := attached {WSF_STRING} fd.item ("op") as l_op and then l_op.same_string ("Preview")
|
||||
if not l_preview then
|
||||
debug ("cms")
|
||||
across
|
||||
fd as c
|
||||
loop
|
||||
b.append ("<li>" + html_encoded (c.key) + "=")
|
||||
if attached c.item as v then
|
||||
b.append (html_encoded (v.string_representation))
|
||||
end
|
||||
b.append ("</li>")
|
||||
end
|
||||
end
|
||||
if a_node /= Void then
|
||||
l_node := a_node
|
||||
a_type.change_node (Current, fd, a_node)
|
||||
s := "modified"
|
||||
else
|
||||
l_node := a_type.new_node (Current, fd, Void)
|
||||
s := "created"
|
||||
end
|
||||
service.storage.save_node (l_node)
|
||||
if attached user as u then
|
||||
service.log ("node", "User %"" + user_link (u) + "%" " + s + " node " + link (a_type.name +" #" + l_node.id.out, "/node/" + l_node.id.out , Void), 0, node_local_link (l_node))
|
||||
else
|
||||
service.log ("node", "Anonymous " + s + " node " + a_type.name +" #" + l_node.id.out, 0, node_local_link (l_node))
|
||||
end
|
||||
add_success_message ("Node #" + l_node.id.out + " saved.")
|
||||
set_redirection (node_url (l_node))
|
||||
end
|
||||
end
|
||||
|
||||
-- edit_form_submit (fd: CMS_FORM_DATA; a_type: CMS_CONTENT_TYPE; b: STRING)
|
||||
-- local
|
||||
-- l_preview: BOOLEAN
|
||||
-- do
|
||||
-- l_preview := attached {WSF_STRING} fd.item ("op") as l_op and then l_op.same_string ("Preview")
|
||||
-- if not l_preview then
|
||||
-- debug ("cms")
|
||||
-- across
|
||||
-- fd as c
|
||||
-- loop
|
||||
-- b.append ("<li>" + html_encoded (c.key) + "=")
|
||||
-- if attached c.item as v then
|
||||
-- b.append (html_encoded (v.string_representation))
|
||||
-- end
|
||||
-- b.append ("</li>")
|
||||
-- end
|
||||
-- end
|
||||
-- if attached a_type.new_node (Current, fd, Void) as l_node then
|
||||
-- service.storage.save_node (l_node)
|
||||
-- if attached user as u then
|
||||
-- service.log ("node", "User %"" + user_link (u) + "%" created node " + link (a_type.name +" #" + l_node.id.out, "/node/" + l_node.id.out , Void), 0, node_local_link (l_node))
|
||||
-- else
|
||||
-- service.log ("node", "Anonymous created node "+ a_type.name +" #" + l_node.id.out, 0, node_local_link (l_node))
|
||||
-- end
|
||||
-- add_success_message ("Node #" + l_node.id.out + " saved.")
|
||||
-- set_redirection (node_url (l_node))
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
|
||||
edit_form (a_node: detachable CMS_NODE; a_url: READABLE_STRING_8; a_name: STRING; a_type: CMS_CONTENT_TYPE): CMS_FORM
|
||||
local
|
||||
f: CMS_FORM
|
||||
ts: CMS_FORM_SUBMIT_INPUT
|
||||
th: CMS_FORM_HIDDEN_INPUT
|
||||
do
|
||||
create f.make (a_url, a_name)
|
||||
|
||||
create th.make ("node-id")
|
||||
if a_node /= Void then
|
||||
th.set_text_value (a_node.id.out)
|
||||
else
|
||||
th.set_text_value ("0")
|
||||
end
|
||||
f.extend (th)
|
||||
|
||||
a_type.fill_edit_form (f, a_node)
|
||||
|
||||
f.extend_text ("<br/>")
|
||||
|
||||
create ts.make ("op")
|
||||
ts.set_default_value ("Save")
|
||||
f.extend (ts)
|
||||
|
||||
create ts.make ("op")
|
||||
ts.set_default_value ("Preview")
|
||||
f.extend (ts)
|
||||
|
||||
Result := f
|
||||
end
|
||||
|
||||
end
|
||||
@@ -6,7 +6,7 @@ class
|
||||
NODE_EDIT_CMS_EXECUTION
|
||||
|
||||
inherit
|
||||
CMS_EXECUTION
|
||||
NODE_CMS_EXECUTION
|
||||
|
||||
create
|
||||
make
|
||||
@@ -19,8 +19,6 @@ feature -- Execution
|
||||
b: STRING_8
|
||||
f: like edit_form
|
||||
fd: detachable CMS_FORM_DATA
|
||||
l_preview: BOOLEAN
|
||||
l_format: detachable CMS_FORMAT
|
||||
do
|
||||
create b.make_empty
|
||||
if
|
||||
@@ -32,8 +30,10 @@ feature -- Execution
|
||||
if has_permission ("edit " + l_type.name) then
|
||||
f := edit_form (l_node, url (request.path_info, Void), "edit-" + l_type.name, l_type)
|
||||
if request.is_post_request_method then
|
||||
create fd.make (request, f)
|
||||
l_preview := attached {WSF_STRING} fd.item ("op") as l_op and then l_op.same_string ("Preview")
|
||||
f.validation_actions.extend (agent edit_form_validate (?, b))
|
||||
f.submit_actions.extend (agent edit_form_submit (?, l_node, l_type, b))
|
||||
f.process (Current)
|
||||
fd := f.last_data
|
||||
end
|
||||
|
||||
set_title ("Edit #" + l_node.id.out)
|
||||
@@ -41,54 +41,7 @@ feature -- Execution
|
||||
add_to_menu (create {CMS_LOCAL_LINK}.make ("View", node_url (l_node)), primary_tabs)
|
||||
add_to_menu (create {CMS_LOCAL_LINK}.make ("Edit", "/node/" + l_node.id.out + "/edit"), primary_tabs)
|
||||
|
||||
if fd /= Void and l_preview then
|
||||
b.append ("<strong>Preview</strong><div class=%"preview%">")
|
||||
if attached fd.string_item ("format") as s_format and then attached formats.format (s_format) as f_format then
|
||||
l_format := f_format
|
||||
end
|
||||
if attached fd.string_item ("title") as l_title then
|
||||
b.append ("<strong>Title:</strong><div class=%"title%">" + html_encoded (l_title) + "</div>")
|
||||
end
|
||||
if attached fd.string_item ("body") as l_body then
|
||||
b.append ("<strong>Body:</strong><div class=%"body%">")
|
||||
if l_format /= Void then
|
||||
b.append (l_format.to_html (l_body))
|
||||
else
|
||||
b.append (html_encoded (l_body))
|
||||
end
|
||||
b.append ("</div>")
|
||||
end
|
||||
b.append ("</div>")
|
||||
end
|
||||
|
||||
if fd /= Void and then fd.is_valid and not l_preview then
|
||||
across
|
||||
fd as c
|
||||
loop
|
||||
b.append ("<li>" + html_encoded (c.key) + "=")
|
||||
if attached c.item as v then
|
||||
b.append (html_encoded (v.string_representation))
|
||||
end
|
||||
b.append ("</li>")
|
||||
end
|
||||
l_type.change_node (Current, fd, l_node)
|
||||
service.storage.save_node (l_node)
|
||||
if attached user as u then
|
||||
service.log ("node", "User %"" + user_link (u) + "%" modified node " + link (l_type.name +" #" + l_node.id.out, "/node/" + l_node.id.out , Void), 0, node_local_link (l_node))
|
||||
else
|
||||
service.log ("node", "Anonymous modified node "+ l_type.name +" #" + l_node.id.out, 0, node_local_link (l_node))
|
||||
end
|
||||
add_success_message ("Node #" + l_node.id.out + " saved.")
|
||||
set_redirection (node_url (l_node))
|
||||
else
|
||||
if fd /= Void then
|
||||
if not fd.is_valid then
|
||||
report_form_errors (fd)
|
||||
end
|
||||
fd.apply_to_associated_form
|
||||
end
|
||||
f.append_to_html (theme, b)
|
||||
end
|
||||
f.append_to_html (theme, b)
|
||||
else
|
||||
b.append ("<h1>Access denied</h1>")
|
||||
end
|
||||
@@ -114,35 +67,100 @@ feature -- Execution
|
||||
set_main_content (b)
|
||||
end
|
||||
|
||||
edit_form (a_node: detachable CMS_NODE; a_url: READABLE_STRING_8; a_name: STRING; a_type: CMS_CONTENT_TYPE): CMS_FORM
|
||||
local
|
||||
f: CMS_FORM
|
||||
ts: CMS_FORM_SUBMIT_INPUT
|
||||
th: CMS_FORM_HIDDEN_INPUT
|
||||
do
|
||||
create f.make (a_url, a_name)
|
||||
-- edit_form_validate (fd: CMS_FORM_DATA; b: STRING)
|
||||
-- local
|
||||
-- l_preview: BOOLEAN
|
||||
-- l_format: detachable CMS_FORMAT
|
||||
-- do
|
||||
-- l_preview := attached {WSF_STRING} fd.item ("op") as l_op and then l_op.same_string ("Preview")
|
||||
-- if l_preview then
|
||||
-- b.append ("<strong>Preview</strong><div class=%"preview%">")
|
||||
-- if attached fd.string_item ("format") as s_format and then attached formats.format (s_format) as f_format then
|
||||
-- l_format := f_format
|
||||
-- end
|
||||
-- if attached fd.string_item ("title") as l_title then
|
||||
-- b.append ("<strong>Title:</strong><div class=%"title%">" + html_encoded (l_title) + "</div>")
|
||||
-- end
|
||||
-- if attached fd.string_item ("body") as l_body then
|
||||
-- b.append ("<strong>Body:</strong><div class=%"body%">")
|
||||
-- if l_format /= Void then
|
||||
-- b.append (l_format.to_html (l_body))
|
||||
-- else
|
||||
-- b.append (html_encoded (l_body))
|
||||
-- end
|
||||
-- b.append ("</div>")
|
||||
-- end
|
||||
-- b.append ("</div>")
|
||||
-- end
|
||||
-- end
|
||||
|
||||
create th.make ("node-id")
|
||||
if a_node /= Void then
|
||||
th.set_text_value (a_node.id.out)
|
||||
else
|
||||
th.set_text_value ("0")
|
||||
end
|
||||
f.extend (th)
|
||||
-- edit_form_submit (fd: CMS_FORM_DATA; a_node: detachable CMS_NODE; a_type: CMS_CONTENT_TYPE; b: STRING)
|
||||
-- local
|
||||
-- l_preview: BOOLEAN
|
||||
-- l_node: detachable CMS_NODE
|
||||
-- s: STRING
|
||||
-- do
|
||||
-- l_preview := attached {WSF_STRING} fd.item ("op") as l_op and then l_op.same_string ("Preview")
|
||||
-- if not l_preview then
|
||||
-- debug ("cms")
|
||||
-- across
|
||||
-- fd as c
|
||||
-- loop
|
||||
-- b.append ("<li>" + html_encoded (c.key) + "=")
|
||||
-- if attached c.item as v then
|
||||
-- b.append (html_encoded (v.string_representation))
|
||||
-- end
|
||||
-- b.append ("</li>")
|
||||
-- end
|
||||
-- end
|
||||
-- if a_node /= Void then
|
||||
-- l_node := a_node
|
||||
-- a_type.change_node (Current, fd, a_node)
|
||||
-- s := "modified"
|
||||
-- else
|
||||
-- l_node := a_type.new_node (Current, fd, Void)
|
||||
-- s := "created"
|
||||
-- end
|
||||
-- service.storage.save_node (l_node)
|
||||
-- if attached user as u then
|
||||
-- service.log ("node", "User %"" + user_link (u) + "%" " + s + " node " + link (a_type.name +" #" + l_node.id.out, "/node/" + l_node.id.out , Void), 0, node_local_link (l_node))
|
||||
-- else
|
||||
-- service.log ("node", "Anonymous " + s + " node " + a_type.name +" #" + l_node.id.out, 0, node_local_link (l_node))
|
||||
-- end
|
||||
-- add_success_message ("Node #" + l_node.id.out + " saved.")
|
||||
-- set_redirection (node_url (l_node))
|
||||
-- end
|
||||
-- end
|
||||
|
||||
a_type.fill_edit_form (f, a_node)
|
||||
-- edit_form (a_node: detachable CMS_NODE; a_url: READABLE_STRING_8; a_name: STRING; a_type: CMS_CONTENT_TYPE): CMS_FORM
|
||||
-- local
|
||||
-- f: CMS_FORM
|
||||
-- ts: CMS_FORM_SUBMIT_INPUT
|
||||
-- th: CMS_FORM_HIDDEN_INPUT
|
||||
-- do
|
||||
-- create f.make (a_url, a_name)
|
||||
|
||||
f.extend_text ("<br/>")
|
||||
-- create th.make ("node-id")
|
||||
-- if a_node /= Void then
|
||||
-- th.set_text_value (a_node.id.out)
|
||||
-- else
|
||||
-- th.set_text_value ("0")
|
||||
-- end
|
||||
-- f.extend (th)
|
||||
|
||||
create ts.make ("op")
|
||||
ts.set_default_value ("Save")
|
||||
f.extend (ts)
|
||||
-- a_type.fill_edit_form (f, a_node)
|
||||
|
||||
create ts.make ("op")
|
||||
ts.set_default_value ("Preview")
|
||||
f.extend (ts)
|
||||
-- f.extend_text ("<br/>")
|
||||
|
||||
Result := f
|
||||
end
|
||||
-- create ts.make ("op")
|
||||
-- ts.set_default_value ("Save")
|
||||
-- f.extend (ts)
|
||||
|
||||
-- create ts.make ("op")
|
||||
-- ts.set_default_value ("Preview")
|
||||
-- f.extend (ts)
|
||||
|
||||
-- Result := f
|
||||
-- end
|
||||
|
||||
end
|
||||
|
||||
@@ -9,6 +9,9 @@ class
|
||||
|
||||
inherit
|
||||
CMS_MODULE
|
||||
redefine
|
||||
permissions
|
||||
end
|
||||
|
||||
CMS_HOOK_MENU_ALTER
|
||||
|
||||
@@ -29,6 +32,20 @@ feature {NONE} -- Initialization
|
||||
enable
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
permissions (a_service: CMS_SERVICE): LIST [CMS_PERMISSION]
|
||||
do
|
||||
Result := Precursor (a_service)
|
||||
across
|
||||
a_service.content_types as c
|
||||
loop
|
||||
Result.extend ("create " + c.item.name)
|
||||
Result.extend ("edit " + c.item.name)
|
||||
Result.extend ("delete " + c.item.name)
|
||||
end
|
||||
end
|
||||
|
||||
feature {CMS_SERVICE} -- Registration
|
||||
|
||||
service: detachable CMS_SERVICE
|
||||
@@ -51,6 +68,7 @@ feature {CMS_SERVICE} -- Registration
|
||||
|
||||
a_service.add_menu_alter_hook (Current)
|
||||
a_service.add_block_hook (Current)
|
||||
|
||||
end
|
||||
|
||||
feature -- Hooks
|
||||
@@ -76,18 +94,19 @@ feature -- Hooks
|
||||
menu_alter (a_menu_system: CMS_MENU_SYSTEM; a_execution: CMS_EXECUTION)
|
||||
local
|
||||
lnk: CMS_LOCAL_LINK
|
||||
perms: detachable ARRAYED_LIST [READABLE_STRING_8]
|
||||
do
|
||||
if a_execution.authenticated then
|
||||
create lnk.make ("Add content", "/node/add/")
|
||||
lnk.set_permission_arguments (<<"authenticated">>)
|
||||
a_menu_system.navigation_menu.extend (lnk)
|
||||
if attached a_execution.service.content_types as lst then
|
||||
create perms.make (lst.count)
|
||||
across
|
||||
lst as c
|
||||
loop
|
||||
perms.force ("create " + c.item.name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
links: HASH_TABLE [CMS_MODULE_LINK, STRING]
|
||||
-- Link indexed by path
|
||||
do
|
||||
create Result.make (0)
|
||||
create lnk.make ("Add content", "/node/add/")
|
||||
lnk.set_permission_arguments (perms)
|
||||
a_menu_system.navigation_menu.extend (lnk)
|
||||
end
|
||||
|
||||
handle_node_view (cms: CMS_SERVICE; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
|
||||
@@ -6,7 +6,7 @@ class
|
||||
NODE_VIEW_CMS_EXECUTION
|
||||
|
||||
inherit
|
||||
CMS_EXECUTION
|
||||
NODE_CMS_EXECUTION
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
Reference in New Issue
Block a user