Compare commits
58 Commits
javier_roc
...
blog_ewf_v
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
53491274dc | ||
| 21800e71d3 | |||
| 0fc1cb68ad | |||
| 0b8bee3404 | |||
| 53a602d33c | |||
| 5578a9e622 | |||
| b8cfff487a | |||
| af8f410684 | |||
| cede341301 | |||
| 70d53b3ef1 | |||
|
|
f056b43ddc | ||
| c871eae10e | |||
|
|
957ca96bc5 | ||
|
|
ad9dd01f22 | ||
|
|
323ac598d0 | ||
|
|
e35893fdb9 | ||
| b77c5cd93c | |||
| 77f52388c1 | |||
|
|
e8ff313c28 | ||
|
|
0bd75e7c59 | ||
|
|
9b169f70a7 | ||
|
|
601b88ab36 | ||
|
|
2b0e1a2b84 | ||
|
|
db77c4024d | ||
|
|
261aeca300 | ||
|
|
027463a910 | ||
|
|
a4c50adefa | ||
|
|
1f61126d22 | ||
|
|
fb196735b6 | ||
|
|
306b39ab78 | ||
|
|
802ad0626e | ||
|
|
470b1b2e05 | ||
|
|
57c2a7bccd | ||
|
|
4dd980963a | ||
|
|
6a782e412d | ||
|
|
0e0cd131a5 | ||
|
|
53f3162b4a | ||
| 036013a0a2 | |||
|
|
202253e414 | ||
| 50da24d1af | |||
| 91457080fd | |||
| 51699f3bd3 | |||
|
|
f72fcce440 | ||
|
|
f48f09bfdf | ||
|
|
35b186cec8 | ||
|
|
c65265b025 | ||
|
|
77bb1fe123 | ||
|
|
e4e2d662b8 | ||
|
|
f0668e660e | ||
|
|
68fb21a4c1 | ||
|
|
3b90d522f9 | ||
|
|
1c59a65983 | ||
|
|
9fbadac7ac | ||
|
|
57bf5ad0dc | ||
|
|
988f32c6c4 | ||
|
|
44d14c4100 | ||
| 29ef17226b | |||
| 9514f1de9c |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -3,3 +3,5 @@ EIFGENs
|
||||
*.log*
|
||||
*.rc
|
||||
*.bak
|
||||
*.sqlite
|
||||
Thumbs.db
|
||||
|
||||
@@ -19,10 +19,12 @@
|
||||
<library name="encoder" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\text\encoder\encoder-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="i18n" location="$ISE_LIBRARY\library\i18n\i18n-safe.ecf"/>
|
||||
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json-safe.ecf" readonly="false"/>
|
||||
<library name="smarty" location="$ISE_LIBRARY\contrib\library\text\template\smarty\smarty-safe.ecf" readonly="false"/>
|
||||
<library name="text_filter" location="$ISE_LIBRARY\unstable\library\text\text_filter\text_filter-safe.ecf"/>
|
||||
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
|
||||
<library name="uri_template" location="$ISE_LIBRARY\contrib\library\text\parser\uri_template\uri_template-safe.ecf"/>
|
||||
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
|
||||
<library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension-safe.ecf" readonly="false"/>
|
||||
<library name="wsf_html" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf_html\wsf_html-safe.ecf" readonly="false"/>
|
||||
|
||||
2
cms.ecf
2
cms.ecf
@@ -17,12 +17,14 @@
|
||||
<library name="encoder" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\text\encoder\encoder.ecf" readonly="false"/>
|
||||
<library name="error" location="$ISE_LIBRARY\contrib\library\utility\general\error\error.ecf"/>
|
||||
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http.ecf"/>
|
||||
<library name="i18n" location="$ISE_LIBRARY\library\i18n\i18n.ecf"/>
|
||||
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json.ecf" readonly="false"/>
|
||||
<library name="cms_app_env" location=".\library\app_env\app_env.ecf"/>
|
||||
<library name="cms_model" location=".\library\model\cms_model.ecf" readonly="false"/>
|
||||
<library name="smarty" location="$ISE_LIBRARY\contrib\library\text\template\smarty\smarty.ecf" readonly="false"/>
|
||||
<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_template" location="$ISE_LIBRARY\contrib\library\text\parser\uri_template\uri_template.ecf"/>
|
||||
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf.ecf"/>
|
||||
<library name="wsf_html" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf_html\wsf_html.ecf" readonly="false"/>
|
||||
<library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension.ecf" readonly="false"/>
|
||||
|
||||
@@ -1,58 +1,78 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="demo" uuid="3643E657-BCBE-46AA-931B-71EAEA877A18" library_target="demo">
|
||||
<description>Example/demo for Eiffel ROC CMS library</description>
|
||||
<target name="common" abstract="true">
|
||||
<file_rule>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/CVS$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" full_class_checking="false" is_attached_by_default="true" void_safety="all" syntax="transitional">
|
||||
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||
</option>
|
||||
<setting name="concurrency" value="none"/>
|
||||
<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_basic_auth_module" location="..\..\modules\basic_auth\basic_auth-safe.ecf" readonly="false"/>
|
||||
<library name="cms_blog_module" location="modules\blog\cms_blog_module-safe.ecf" readonly="false"/>
|
||||
<library name="cms_demo_module" location="modules\demo\cms_demo_module-safe.ecf" readonly="false"/>
|
||||
<library name="cms_model" location="..\..\library\model\cms_model-safe.ecf" readonly="false"/>
|
||||
<library name="cms_node_module" location="..\..\modules\node\node-safe.ecf" readonly="false"/>
|
||||
<!--
|
||||
<library name="persistence_mysql" location="..\..\library\persistence\mysql\persistence_mysql-safe.ecf" readonly="false"/>
|
||||
-->
|
||||
<library name="persistence_sqlite" location="..\..\library\persistence\sqlite\persistence_sqlite-safe.ecf" readonly="false"/>
|
||||
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
|
||||
<library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension-safe.ecf" readonly="false"/>
|
||||
</target>
|
||||
<target name="demo_any" extends="common">
|
||||
<root class="EWF_ROC_SERVER" feature="make_and_launch"/>
|
||||
<library name="cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\cgi-safe.ecf"/>
|
||||
<library name="libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\libfcgi-safe.ecf"/>
|
||||
<library name="nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\nino-safe.ecf"/>
|
||||
<cluster name="launcher" location=".\launcher\any\" recursive="true"/>
|
||||
<cluster name="src" location=".\src\" recursive="true"/>
|
||||
</target>
|
||||
<target name="demo_nino" extends="common">
|
||||
<root class="EWF_ROC_SERVER" feature="make_and_launch"/>
|
||||
<setting name="concurrency" value="none"/>
|
||||
<library name="default_nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\nino-safe.ecf"/>
|
||||
<cluster name="launcher" location=".\launcher\default\" recursive="true"/>
|
||||
<cluster name="src" location=".\src\" recursive="true"/>
|
||||
</target>
|
||||
<target name="demo_cgi" extends="common">
|
||||
<root class="EWF_ROC_SERVER" feature="make_and_launch"/>
|
||||
<library name="default_cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\cgi-safe.ecf"/>
|
||||
<cluster name="launcher" location=".\launcher\default\" recursive="true"/>
|
||||
<cluster name="src" location=".\src\" recursive="true"/>
|
||||
</target>
|
||||
<target name="demo_libfcgi" extends="common">
|
||||
<root class="EWF_ROC_SERVER" feature="make_and_launch"/>
|
||||
<library name="default_libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\libfcgi-safe.ecf"/>
|
||||
<cluster name="launcher" location=".\launcher\default\" recursive="true"/>
|
||||
<cluster name="src" location=".\src\" recursive="true"/>
|
||||
</target>
|
||||
<target name="demo" extends="demo_nino">
|
||||
</target>
|
||||
<description>Example/demo for Eiffel ROC CMS library</description>
|
||||
<target name="common" abstract="true">
|
||||
<file_rule>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/CVS$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option debug="true" warning="true" full_class_checking="false" is_attached_by_default="true" void_safety="all" syntax="transitional">
|
||||
<debug name="dbglog" enabled="true"/>
|
||||
</option>
|
||||
<setting name="concurrency" value="thread"/>
|
||||
<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_basic_auth_module" location="..\..\modules\basic_auth\basic_auth-safe.ecf" readonly="false"/>
|
||||
<library name="cms_blog_module" location="modules\blog\cms_blog_module-safe.ecf" readonly="false"/>
|
||||
<library name="cms_demo_module" location="modules\demo\cms_demo_module-safe.ecf" readonly="false"/>
|
||||
<library name="cms_model" location="..\..\library\model\cms_model-safe.ecf" readonly="false"/>
|
||||
<library name="cms_node_module" location="..\..\modules\node\node-safe.ecf" readonly="false"/>
|
||||
<library name="persistence_sqlite" location="..\..\library\persistence\sqlite\persistence_sqlite-safe.ecf" readonly="false"/>
|
||||
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
|
||||
<library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension-safe.ecf" readonly="false"/>
|
||||
</target>
|
||||
<target name="demo_any" extends="common">
|
||||
<root class="EWF_ROC_SERVER" feature="make_and_launch"/>
|
||||
<setting name="concurrency" value="thread"/>
|
||||
<library name="cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\cgi-safe.ecf"/>
|
||||
<library name="libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\libfcgi-safe.ecf"/>
|
||||
<library name="nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\nino-safe.ecf"/>
|
||||
<library name="standalone" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\standalone-safe.ecf"/>
|
||||
<cluster name="launcher" location=".\launcher\any\" recursive="true"/>
|
||||
<cluster name="src" location=".\src\" recursive="true"/>
|
||||
</target>
|
||||
<target name="demo_standalone" extends="common">
|
||||
<root class="EWF_ROC_SERVER" feature="make_and_launch"/>
|
||||
<option debug="true">
|
||||
<debug name="dbglog" enabled="true"/>
|
||||
</option>
|
||||
<setting name="concurrency" value="thread"/>
|
||||
<library name="default_standalone" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\standalone-safe.ecf"/>
|
||||
<cluster name="launcher" location=".\launcher\default\" recursive="true"/>
|
||||
<cluster name="src" location=".\src\" recursive="true"/>
|
||||
</target>
|
||||
<target name="demo_standalone_none" extends="demo_standalone">
|
||||
<setting name="concurrency" value="none"/>
|
||||
</target>
|
||||
<target name="demo_standalone_mt" extends="demo_standalone">
|
||||
<setting name="concurrency" value="thread"/>
|
||||
</target>
|
||||
<target name="demo_standalone_scoop" extends="demo_standalone">
|
||||
<setting name="concurrency" value="scoop"/>
|
||||
</target>
|
||||
<target name="demo_nino" extends="common">
|
||||
<root class="EWF_ROC_SERVER" feature="make_and_launch"/>
|
||||
<setting name="concurrency" value="none"/>
|
||||
<library name="default_nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\nino-safe.ecf"/>
|
||||
<cluster name="launcher" location=".\launcher\default\" recursive="true"/>
|
||||
<cluster name="src" location=".\src\" recursive="true"/>
|
||||
</target>
|
||||
<target name="demo_cgi" extends="common">
|
||||
<root class="EWF_ROC_SERVER" feature="make_and_launch"/>
|
||||
<setting name="concurrency" value="none"/>
|
||||
<library name="default_cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\cgi-safe.ecf"/>
|
||||
<cluster name="launcher" location=".\launcher\default\" recursive="true"/>
|
||||
<cluster name="src" location=".\src\" recursive="true"/>
|
||||
</target>
|
||||
<target name="demo_libfcgi" extends="common">
|
||||
<root class="EWF_ROC_SERVER" feature="make_and_launch"/>
|
||||
<setting name="concurrency" value="none"/>
|
||||
<library name="default_libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\libfcgi-safe.ecf"/>
|
||||
<cluster name="launcher" location=".\launcher\default\" recursive="true"/>
|
||||
<cluster name="src" location=".\src\" recursive="true"/>
|
||||
</target>
|
||||
<target name="demo" extends="demo_standalone">
|
||||
</target>
|
||||
</system>
|
||||
|
||||
@@ -8,10 +8,10 @@ note
|
||||
revision: "$Revision: 36 $"
|
||||
|
||||
class
|
||||
APPLICATION_LAUNCHER
|
||||
APPLICATION_LAUNCHER [G -> WSF_EXECUTION create make end]
|
||||
|
||||
inherit
|
||||
APPLICATION_LAUNCHER_I
|
||||
APPLICATION_LAUNCHER_I [G]
|
||||
|
||||
feature -- Custom
|
||||
|
||||
|
||||
@@ -10,24 +10,28 @@ note
|
||||
revision: "$Revision: 36 $"
|
||||
|
||||
deferred class
|
||||
APPLICATION_LAUNCHER_I
|
||||
APPLICATION_LAUNCHER_I [G -> WSF_EXECUTION create make end]
|
||||
|
||||
inherit
|
||||
SHARED_EXECUTION_ENVIRONMENT
|
||||
|
||||
feature -- Execution
|
||||
|
||||
launch (a_service: WSF_SERVICE; opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
|
||||
launch (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
|
||||
local
|
||||
nature: like launcher_nature
|
||||
do
|
||||
nature := launcher_nature
|
||||
if nature = Void or else nature = nature_nino then
|
||||
launch_nino (a_service, opts)
|
||||
if nature = Void then
|
||||
launch_standalone (opts)
|
||||
elseif nature = nature_standalone then
|
||||
launch_standalone (opts)
|
||||
elseif nature = nature_nino then
|
||||
launch_nino (opts)
|
||||
elseif nature = nature_cgi then
|
||||
launch_cgi (a_service, opts)
|
||||
launch_cgi (opts)
|
||||
elseif nature = nature_libfcgi then
|
||||
launch_libfcgi (a_service, opts)
|
||||
launch_libfcgi (opts)
|
||||
else
|
||||
-- bye bye
|
||||
(create {EXCEPTIONS}).die (-1)
|
||||
@@ -43,7 +47,6 @@ feature {NONE} -- Access
|
||||
--| and we could use WSF_DEFAULT_SERVICE_LAUNCHER to configure this at compilation time.
|
||||
local
|
||||
p: PATH
|
||||
l_entry_name: READABLE_STRING_32
|
||||
ext: detachable READABLE_STRING_32
|
||||
do
|
||||
create p.make_from_string (execution_environment.arguments.command_name)
|
||||
@@ -51,6 +54,9 @@ feature {NONE} -- Access
|
||||
ext := l_entry.extension
|
||||
end
|
||||
if ext /= Void then
|
||||
if ext.same_string (nature_standalone) then
|
||||
Result := nature_standalone
|
||||
end
|
||||
if ext.same_string (nature_nino) then
|
||||
Result := nature_nino
|
||||
end
|
||||
@@ -61,39 +67,58 @@ feature {NONE} -- Access
|
||||
Result := nature_libfcgi
|
||||
end
|
||||
end
|
||||
Result := default_nature
|
||||
end
|
||||
|
||||
feature {NONE} -- standalone
|
||||
|
||||
nature_standalone: STRING = "standalone"
|
||||
|
||||
launch_standalone (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
|
||||
local
|
||||
launcher: WSF_STANDALONE_SERVICE_LAUNCHER [G]
|
||||
do
|
||||
create launcher.make_and_launch (opts)
|
||||
end
|
||||
|
||||
feature {NONE} -- nino
|
||||
|
||||
nature_nino: STRING = "nino"
|
||||
|
||||
launch_nino (a_service: WSF_SERVICE; opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
|
||||
launch_nino (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
|
||||
local
|
||||
launcher: WSF_NINO_SERVICE_LAUNCHER
|
||||
launcher: WSF_NINO_SERVICE_LAUNCHER [G]
|
||||
do
|
||||
create launcher.make_and_launch (a_service, opts)
|
||||
create launcher.make_and_launch (opts)
|
||||
end
|
||||
|
||||
feature {NONE} -- cgi
|
||||
|
||||
nature_cgi: STRING = "cgi"
|
||||
|
||||
launch_cgi (a_service: WSF_SERVICE; opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
|
||||
launch_cgi (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
|
||||
local
|
||||
launcher: WSF_CGI_SERVICE_LAUNCHER
|
||||
launcher: WSF_CGI_SERVICE_LAUNCHER [G]
|
||||
do
|
||||
create launcher.make_and_launch (a_service, opts)
|
||||
create launcher.make_and_launch (opts)
|
||||
end
|
||||
|
||||
feature {NONE} -- libfcgi
|
||||
|
||||
nature_libfcgi: STRING = "libfcgi"
|
||||
|
||||
launch_libfcgi (a_service: WSF_SERVICE; opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
|
||||
launch_libfcgi (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
|
||||
local
|
||||
launcher: WSF_LIBFCGI_SERVICE_LAUNCHER
|
||||
launcher: WSF_LIBFCGI_SERVICE_LAUNCHER [G]
|
||||
do
|
||||
create launcher.make_and_launch (a_service, opts)
|
||||
create launcher.make_and_launch (opts)
|
||||
end
|
||||
|
||||
feature -- Default
|
||||
|
||||
default_nature: STRING
|
||||
do
|
||||
Result := nature_standalone
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -8,10 +8,10 @@ note
|
||||
revision: "$Revision: 36 $"
|
||||
|
||||
class
|
||||
APPLICATION_LAUNCHER
|
||||
APPLICATION_LAUNCHER [G -> WSF_EXECUTION create make end]
|
||||
|
||||
inherit
|
||||
APPLICATION_LAUNCHER_I
|
||||
APPLICATION_LAUNCHER_I [G]
|
||||
|
||||
feature -- Custom
|
||||
|
||||
|
||||
@@ -10,15 +10,15 @@ note
|
||||
revision: "$Revision: 96596 $"
|
||||
|
||||
deferred class
|
||||
APPLICATION_LAUNCHER_I
|
||||
APPLICATION_LAUNCHER_I [G -> WSF_EXECUTION create make end]
|
||||
|
||||
feature -- Execution
|
||||
|
||||
launch (a_service: WSF_SERVICE; opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
|
||||
launch (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
|
||||
local
|
||||
launcher: WSF_DEFAULT_SERVICE_LAUNCHER
|
||||
launcher: WSF_DEFAULT_SERVICE_LAUNCHER [G]
|
||||
do
|
||||
create {WSF_DEFAULT_SERVICE_LAUNCHER} launcher.make_and_launch (a_service, opts)
|
||||
create launcher.make_and_launch (opts)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -31,7 +31,13 @@ feature -- Conversion
|
||||
do
|
||||
Precursor (a_node)
|
||||
if attached {CMS_BLOG} a_node as l_blog then
|
||||
-- l_blog
|
||||
if attached l_blog.tags as l_tags then
|
||||
across
|
||||
l_tags as ic
|
||||
loop
|
||||
add_tag (ic.item)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -42,7 +48,7 @@ feature -- Access
|
||||
Result := {CMS_BLOG_NODE_TYPE}.name
|
||||
end
|
||||
|
||||
feature -- Access: content
|
||||
feature -- Access: node
|
||||
|
||||
summary: detachable READABLE_STRING_8
|
||||
-- A short summary of the node.
|
||||
@@ -54,10 +60,12 @@ feature -- Access: content
|
||||
-- Format associated with `content' and `summary'.
|
||||
-- For example: text, mediawiki, html, etc
|
||||
|
||||
feature -- Access: blog
|
||||
|
||||
tags: detachable ARRAYED_LIST [READABLE_STRING_32]
|
||||
-- Optional tags
|
||||
|
||||
feature -- Element change
|
||||
feature -- Element change: node
|
||||
|
||||
set_content (a_content: like content; a_summary: like summary; a_format: like format)
|
||||
do
|
||||
@@ -66,6 +74,8 @@ feature -- Element change
|
||||
format := a_format
|
||||
end
|
||||
|
||||
feature -- Element change: blog
|
||||
|
||||
add_tag (a_tag: READABLE_STRING_32)
|
||||
-- Set `parent' to `a_page'
|
||||
require
|
||||
|
||||
118
examples/demo/modules/blog/cms_blog_api.e
Normal file
118
examples/demo/modules/blog/cms_blog_api.e
Normal file
@@ -0,0 +1,118 @@
|
||||
note
|
||||
description: "API to handle nodes of type blog. Extends the node API."
|
||||
author: "Dario Bösch <daboesch@student.ethz.ch"
|
||||
date: "$Date: 2015-05-21 14:46:00 +0100$"
|
||||
revision: "$Revision: 96616 $"
|
||||
|
||||
class
|
||||
CMS_BLOG_API
|
||||
|
||||
inherit
|
||||
CMS_MODULE_API
|
||||
rename
|
||||
make as make_with_cms_api
|
||||
redefine
|
||||
initialize
|
||||
end
|
||||
|
||||
REFACTORING_HELPER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_api: CMS_API; a_node_api: CMS_NODE_API)
|
||||
-- (from CMS_MODULE_API)
|
||||
-- (export status {NONE})
|
||||
do
|
||||
node_api := a_node_api
|
||||
make_with_cms_api (a_api)
|
||||
end
|
||||
|
||||
initialize
|
||||
-- <Precursor>
|
||||
do
|
||||
Precursor
|
||||
|
||||
-- Create the node storage for type blog
|
||||
if attached {CMS_STORAGE_SQL_I} storage as l_storage_sql then
|
||||
create {CMS_BLOG_STORAGE_SQL} blog_storage.make (l_storage_sql)
|
||||
else
|
||||
create {CMS_BLOG_STORAGE_NULL} blog_storage.make
|
||||
end
|
||||
-- initialize_node_types
|
||||
end
|
||||
|
||||
feature {CMS_API_ACCESS, CMS_MODULE, CMS_API} -- Restricted access
|
||||
|
||||
node_api: CMS_NODE_API
|
||||
|
||||
feature {CMS_MODULE} -- Access nodes storage.
|
||||
|
||||
blog_storage: CMS_BLOG_STORAGE_I
|
||||
|
||||
feature -- Configuration of blog handlers
|
||||
|
||||
entries_per_page : NATURAL_32 = 2
|
||||
-- The numbers of posts that are shown on one page. If there are more post a pagination is generated
|
||||
--| For test reasons this is 2, so we don't have to create a lot of blog entries.
|
||||
--| TODO: Set to bigger constant.
|
||||
|
||||
feature -- Access node
|
||||
|
||||
blogs_count: INTEGER_64
|
||||
-- Number of nodes of type blog.
|
||||
do
|
||||
Result := blog_storage.blogs_count
|
||||
end
|
||||
|
||||
blogs_count_from_user (a_user: CMS_USER): INTEGER_64
|
||||
-- Number of nodes of type blog from user with `a_user_id'.
|
||||
require
|
||||
has_id: a_user.has_id
|
||||
do
|
||||
Result := blog_storage.blogs_count_from_user (a_user)
|
||||
end
|
||||
|
||||
blogs_order_created_desc: LIST [CMS_BLOG]
|
||||
-- List of nodes ordered by creation date (descending)
|
||||
do
|
||||
Result := nodes_to_blogs (blog_storage.blogs)
|
||||
end
|
||||
|
||||
blogs_order_created_desc_limited (a_limit: NATURAL_32; a_offset: NATURAL_32): LIST [CMS_BLOG]
|
||||
-- List of nodes ordered by creation date and limited by limit and offset
|
||||
do
|
||||
-- load all posts and add the authors to each post
|
||||
Result := nodes_to_blogs (blog_storage.blogs_limited (a_limit, a_offset))
|
||||
end
|
||||
|
||||
blogs_from_user_order_created_desc_limited (a_user: CMS_USER; a_limit: NATURAL_32; a_offset: NATURAL_32) : LIST [CMS_BLOG]
|
||||
-- List of nodes ordered by creation date and limited by limit and offset
|
||||
require
|
||||
has_id: a_user.has_id
|
||||
do
|
||||
-- load all posts and add the authors to each post
|
||||
Result := nodes_to_blogs (blog_storage.blogs_from_user_limited (a_user, a_limit, a_offset))
|
||||
end
|
||||
|
||||
feature {NONE} -- Helpers
|
||||
|
||||
nodes_to_blogs (a_nodes: LIST [CMS_NODE]): ARRAYED_LIST [CMS_BLOG]
|
||||
-- Convert list of nodes into a list of blog when possible.
|
||||
do
|
||||
create {ARRAYED_LIST [CMS_BLOG]} Result.make (a_nodes.count)
|
||||
|
||||
if attached node_api as l_node_api then
|
||||
across
|
||||
a_nodes as ic
|
||||
loop
|
||||
if attached {CMS_BLOG} l_node_api.full_node (ic.item) as l_blog then
|
||||
Result.force (l_blog)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -20,6 +20,7 @@
|
||||
<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_html" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf_html\wsf_html-safe.ecf"/>
|
||||
<library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension-safe.ecf" readonly="false"/>
|
||||
<library name="wsf_encoder" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\text\encoder\encoder-safe.ecf"/>
|
||||
<cluster name="src" location=".\" recursive="true"/>
|
||||
</target>
|
||||
|
||||
@@ -1,18 +1,21 @@
|
||||
note
|
||||
description: "Summary description for {CMS_BLOG_MODULE}."
|
||||
date: "$Date: 2015-02-13 13:08:13 +0100 (ven., 13 févr. 2015) $"
|
||||
revision: "$Revision: 96616 $"
|
||||
description: "Displays all posts (pages with type blog). It's possible to list posts by user."
|
||||
author: "Dario Bösch <daboesch@student.ethz.ch>"
|
||||
date: "$Date: 2015-05-22 15:13:00 +0100 (lun., 18 mai 2015) $"
|
||||
revision: "$Revision 96616$"
|
||||
|
||||
class
|
||||
CMS_BLOG_MODULE
|
||||
|
||||
inherit
|
||||
CMS_MODULE
|
||||
rename
|
||||
module_api as blog_api
|
||||
redefine
|
||||
register_hooks,
|
||||
initialize,
|
||||
is_installed,
|
||||
install
|
||||
install,
|
||||
blog_api
|
||||
end
|
||||
|
||||
CMS_HOOK_MENU_SYSTEM_ALTER
|
||||
@@ -40,6 +43,10 @@ feature {CMS_API} -- Module Initialization
|
||||
Precursor (api)
|
||||
|
||||
if attached {CMS_NODE_API} api.module_api ({NODE_MODULE}) as l_node_api then
|
||||
create blog_api.make (api, l_node_api)
|
||||
|
||||
node_api := l_node_api
|
||||
-- Depends on {NODE_MODULE}
|
||||
create ct
|
||||
l_node_api.add_content_type (ct)
|
||||
l_node_api.add_content_type_webform_manager (create {CMS_BLOG_NODE_TYPE_WEBFORM_MANAGER}.make (ct))
|
||||
@@ -53,12 +60,6 @@ feature {CMS_API} -- Module Initialization
|
||||
|
||||
feature {CMS_API} -- Module management
|
||||
|
||||
is_installed (api: CMS_API): BOOLEAN
|
||||
-- Is Current module installed?
|
||||
do
|
||||
Result := attached api.storage.custom_value ("is_initialized", "module-" + name) as v and then v.is_case_insensitive_equal_general ("yes")
|
||||
end
|
||||
|
||||
install (api: CMS_API)
|
||||
local
|
||||
sql: STRING
|
||||
@@ -78,17 +79,57 @@ CREATE TABLE "blog_post_nodes"(
|
||||
api.logger.put_error ("Could not initialize database for blog module", generating_type)
|
||||
end
|
||||
end
|
||||
api.storage.set_custom_value ("is_initialized", "module-" + name, "yes")
|
||||
Precursor (api)
|
||||
end
|
||||
end
|
||||
|
||||
feature {CMS_API} -- Access: API
|
||||
|
||||
blog_api: detachable CMS_BLOG_API
|
||||
-- <Precursor>
|
||||
|
||||
node_api: detachable CMS_NODE_API
|
||||
|
||||
feature -- Access: router
|
||||
|
||||
router (a_api: CMS_API): WSF_ROUTER
|
||||
-- Node router.
|
||||
setup_router (a_router: WSF_ROUTER; a_api: CMS_API)
|
||||
-- <Precursor>
|
||||
do
|
||||
create Result.make (1)
|
||||
Result.handle_with_request_methods ("/blogs/", create {WSF_URI_AGENT_HANDLER}.make (agent handle_blogs (?,?, a_api)), Result.methods_get)
|
||||
if attached blog_api as l_blog_api then
|
||||
configure_web (a_api, l_blog_api, a_router)
|
||||
else
|
||||
-- Issue with api/dependencies,
|
||||
-- thus Current module should not be used!
|
||||
-- thus no url mapping
|
||||
end
|
||||
end
|
||||
|
||||
configure_web (a_api: CMS_API; a_blog_api: CMS_BLOG_API; a_router: WSF_ROUTER)
|
||||
-- Configure router mapping for web interface.
|
||||
local
|
||||
l_blog_handler: BLOG_HANDLER
|
||||
l_blog_user_handler: BLOG_USER_HANDLER
|
||||
l_uri_mapping: WSF_URI_MAPPING
|
||||
do
|
||||
-- TODO: for now, focused only on web interface, add REST api later. [2015-May-18]
|
||||
create l_blog_handler.make (a_api, a_blog_api)
|
||||
create l_blog_user_handler.make (a_api, a_blog_api)
|
||||
|
||||
-- Let the class BLOG_HANDLER handle the requests on "/blogs"
|
||||
create l_uri_mapping.make_trailing_slash_ignored ("/blogs", l_blog_handler)
|
||||
a_router.map_with_request_methods (l_uri_mapping, a_router.methods_get)
|
||||
|
||||
-- We can add a page number after /blogs/ to get older posts
|
||||
a_router.handle_with_request_methods ("/blogs/page/{page}", l_blog_handler, a_router.methods_get)
|
||||
|
||||
-- If a user id is given route with blog user handler
|
||||
--| FIXME: maybe /user/{user}/blogs/ would be better.
|
||||
a_router.handle_with_request_methods ("/blogs/user/{user}", l_blog_user_handler, a_router.methods_get)
|
||||
|
||||
-- If a user id is given we also want to allow different pages
|
||||
--| FIXME: what about /user/{user}/blogs/?page={page} ?
|
||||
a_router.handle_with_request_methods ("/blogs/user/{user}/page/{page}", l_blog_user_handler, a_router.methods_get)
|
||||
|
||||
end
|
||||
|
||||
feature -- Hooks
|
||||
@@ -102,19 +143,8 @@ feature -- Hooks
|
||||
local
|
||||
lnk: CMS_LOCAL_LINK
|
||||
do
|
||||
create lnk.make ("Blogs", "/blogs/")
|
||||
-- Add the link to the blog to the main menu
|
||||
create lnk.make ("Blogs", "blogs/")
|
||||
a_menu_system.primary_menu.extend (lnk)
|
||||
end
|
||||
|
||||
feature -- Handler
|
||||
|
||||
handle_blogs (req: WSF_REQUEST; res: WSF_RESPONSE; a_api: CMS_API)
|
||||
local
|
||||
r: NOT_IMPLEMENTED_ERROR_CMS_RESPONSE
|
||||
do
|
||||
create r.make (req, res, a_api)
|
||||
r.set_main_content ("Blog module is in development ...")
|
||||
r.execute
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -17,10 +17,11 @@ feature {NONE} -- Initialization
|
||||
default_create
|
||||
do
|
||||
Precursor
|
||||
create {ARRAYED_LIST [like available_formats.item]} available_formats.make (3)
|
||||
create {ARRAYED_LIST [like available_formats.item]} available_formats.make (4)
|
||||
available_formats.extend (create {PLAIN_TEXT_CONTENT_FORMAT})
|
||||
available_formats.extend (create {FILTERED_HTML_CONTENT_FORMAT})
|
||||
available_formats.extend (create {FULL_HTML_CONTENT_FORMAT})
|
||||
available_formats.extend (create {CMS_EDITOR_CONTENT_FORMAT})
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
279
examples/demo/modules/blog/handler/blog_handler.e
Normal file
279
examples/demo/modules/blog/handler/blog_handler.e
Normal file
@@ -0,0 +1,279 @@
|
||||
note
|
||||
description: "Request handler related to /blogs and /blogs/{page}. Displays all posts in the blog."
|
||||
author: "Dario Bösch <daboesch@student.ethz.ch>"
|
||||
date: "$Date: 2015-05-18 13:49:00 +0100 (lun., 18 mai 2015) $"
|
||||
revision: "$9661667$"
|
||||
|
||||
class
|
||||
BLOG_HANDLER
|
||||
|
||||
inherit
|
||||
CMS_BLOG_HANDLER
|
||||
|
||||
WSF_URI_HANDLER
|
||||
rename
|
||||
execute as uri_execute,
|
||||
new_mapping as new_uri_mapping
|
||||
end
|
||||
|
||||
WSF_URI_TEMPLATE_HANDLER
|
||||
rename
|
||||
execute as uri_template_execute,
|
||||
new_mapping as new_uri_template_mapping
|
||||
select
|
||||
new_uri_template_mapping
|
||||
end
|
||||
|
||||
WSF_RESOURCE_HANDLER_HELPER
|
||||
redefine
|
||||
do_get
|
||||
end
|
||||
|
||||
REFACTORING_HELPER
|
||||
|
||||
CMS_API_ACCESS
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- execute
|
||||
|
||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute request handler for any kind of mapping.
|
||||
do
|
||||
execute_methods (req, res)
|
||||
end
|
||||
|
||||
uri_execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute request handler for URI mapping.
|
||||
do
|
||||
execute (req, res)
|
||||
end
|
||||
|
||||
uri_template_execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute request handler for URI-template mapping.
|
||||
do
|
||||
execute (req, res)
|
||||
end
|
||||
|
||||
feature -- Global Variables
|
||||
|
||||
page_number: NATURAL_32
|
||||
-- Current page number.
|
||||
|
||||
feature -- HTTP Methods
|
||||
|
||||
do_get (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- <Precursor>
|
||||
local
|
||||
l_page: CMS_RESPONSE
|
||||
do
|
||||
-- Read page number from path parameter.
|
||||
page_number := page_number_path_parameter (req)
|
||||
|
||||
-- Responding with `main_content_html (l_page)'.
|
||||
create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)
|
||||
l_page.set_main_content (main_content_html (l_page))
|
||||
l_page.execute
|
||||
end
|
||||
|
||||
feature -- Query
|
||||
|
||||
posts: LIST [CMS_NODE]
|
||||
-- Blog posts to display on given page ordered by date (descending).
|
||||
do
|
||||
Result := blog_api.blogs_order_created_desc_limited (
|
||||
entries_per_page,
|
||||
entries_per_page * (page_number - 1)
|
||||
)
|
||||
end
|
||||
|
||||
multiple_pages_needed : BOOLEAN
|
||||
-- Return if more that one page is needed to display posts.
|
||||
do
|
||||
Result := entries_per_page < total_entries
|
||||
end
|
||||
|
||||
pages_count: NATURAL_32
|
||||
-- Number of pages needed to display all posts.
|
||||
require
|
||||
entries_per_page > 0
|
||||
local
|
||||
tmp: REAL_32
|
||||
do
|
||||
tmp := total_entries.to_real_32 / entries_per_page.to_real_32;
|
||||
Result := tmp.ceiling.to_natural_32
|
||||
end
|
||||
|
||||
page_number_path_parameter (req: WSF_REQUEST): NATURAL_32
|
||||
-- Page number from path /blogs/{page}.
|
||||
-- Unsigned integer since negative pages are not allowed.
|
||||
local
|
||||
s: STRING
|
||||
do
|
||||
Result := 1 -- default if not get variable is set
|
||||
if attached {WSF_STRING} req.path_parameter ("page") as p_page then
|
||||
s := p_page.value
|
||||
if s.is_natural_32 then
|
||||
if s.to_natural_32 > 1 then
|
||||
Result := s.to_natural_32
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
total_entries: NATURAL_32
|
||||
-- Total number of entries/posts.
|
||||
do
|
||||
Result := blog_api.blogs_count.to_natural_32
|
||||
end
|
||||
|
||||
feature -- HTML Output
|
||||
|
||||
frozen main_content_html (page: CMS_RESPONSE): STRING
|
||||
-- Content of the page as a html string.
|
||||
do
|
||||
create Result.make_empty
|
||||
append_main_content_html_to (page, Result)
|
||||
end
|
||||
|
||||
append_main_content_html_to (page: CMS_RESPONSE; a_output: STRING)
|
||||
-- Append to `a_output, the content of the page as a html string.
|
||||
local
|
||||
n: CMS_NODE
|
||||
lnk: CMS_LOCAL_LINK
|
||||
do
|
||||
-- Output the title. If more than one page, also output the current page number
|
||||
append_page_title_html_to (a_output)
|
||||
|
||||
-- Get the posts from the current page (given by page number and entries per page)
|
||||
-- Start list of posts
|
||||
a_output.append ("<ul class=%"cms_blog_nodes%">%N")
|
||||
across
|
||||
posts as ic
|
||||
loop
|
||||
n := ic.item
|
||||
lnk := blog_api.node_api.node_link (n)
|
||||
a_output.append ("<li class=%"cms_type_"+ n.content_type +"%">")
|
||||
|
||||
-- Output the creation date
|
||||
append_creation_date_html_to (n, a_output)
|
||||
|
||||
-- Output the author of the post
|
||||
append_author_html_to (n, a_output)
|
||||
|
||||
-- Output the title of the post as a link (to the detail page)
|
||||
append_title_html_to (n, page, a_output)
|
||||
|
||||
-- Output the summary of the post and a more link to the detail page
|
||||
append_summary_html_to (n, page, a_output)
|
||||
|
||||
a_output.append ("</li>%N")
|
||||
end
|
||||
|
||||
-- End of post list
|
||||
a_output.append ("</ul>%N")
|
||||
|
||||
-- Pagination (older and newer links)
|
||||
append_pagination_html_to (a_output)
|
||||
end
|
||||
|
||||
append_page_title_html_to (a_output: STRING)
|
||||
-- Append the title of the page as a html string to `a_output'.
|
||||
-- It shows the current page number.
|
||||
do
|
||||
a_output.append ("<h2>Blog")
|
||||
if multiple_pages_needed then
|
||||
a_output.append (" (Page " + page_number.out + " of " + pages_count.out + ")")
|
||||
end
|
||||
a_output.append ("</h2>")
|
||||
end
|
||||
|
||||
append_creation_date_html_to (n: CMS_NODE; a_output: STRING)
|
||||
-- Append the creation date as a html string to `a_output'.
|
||||
local
|
||||
hdate: HTTP_DATE
|
||||
do
|
||||
if attached n.creation_date as l_modified then
|
||||
create hdate.make_from_date_time (l_modified)
|
||||
hdate.append_to_yyyy_mmm_dd_string (a_output)
|
||||
a_output.append (" ")
|
||||
end
|
||||
end
|
||||
|
||||
append_author_html_to (n: CMS_NODE; a_output: STRING)
|
||||
-- Append to `a_output', the author of node `n' as html link to author's posts.
|
||||
do
|
||||
if attached n.author as l_author then
|
||||
a_output.append ("by ")
|
||||
a_output.append ("<a class=%"blog_user_link%" href=%"/blogs/user/" + l_author.id.out + "%">" + l_author.name + "</a>")
|
||||
end
|
||||
end
|
||||
|
||||
append_title_html_to (n: CMS_NODE; page: CMS_RESPONSE; a_output: STRING)
|
||||
-- Append to `a_output', the title of node `n' as html link to detail page.
|
||||
local
|
||||
lnk: CMS_LOCAL_LINK
|
||||
do
|
||||
lnk := blog_api.node_api.node_link (n)
|
||||
a_output.append ("<span class=%"blog_title%">")
|
||||
a_output.append (page.link (lnk.title, lnk.location, Void))
|
||||
a_output.append ("</span>")
|
||||
end
|
||||
|
||||
append_summary_html_to (n: CMS_NODE; page: CMS_RESPONSE; a_output: STRING)
|
||||
-- returns a html string with the summary of the node and a link to the detail page
|
||||
local
|
||||
lnk: CMS_LOCAL_LINK
|
||||
do
|
||||
if attached n.summary as l_summary then
|
||||
lnk := blog_api.node_api.node_link (n)
|
||||
a_output.append ("<p class=%"blog_list_summary%">")
|
||||
if attached api.format (n.format) as f then
|
||||
a_output.append (f.formatted_output (l_summary))
|
||||
else
|
||||
a_output.append (page.formats.default_format.formatted_output (l_summary))
|
||||
end
|
||||
a_output.append ("<br />")
|
||||
a_output.append (page.link ("See more...", lnk.location, Void))
|
||||
a_output.append ("</p>")
|
||||
end
|
||||
end
|
||||
|
||||
append_pagination_html_to (a_output: STRING)
|
||||
-- Append to `a_output' with the pagination links (if necessary).
|
||||
local
|
||||
tmp: NATURAL_32
|
||||
do
|
||||
if multiple_pages_needed then
|
||||
a_output.append ("<div class=%"pagination%">")
|
||||
|
||||
-- If exist older posts show link to next page
|
||||
if page_number < pages_count then
|
||||
tmp := page_number + 1
|
||||
a_output.append (" <a class=%"blog_older_posts%" href=%"" + base_path + "/page/" + tmp.out + "%"><< Older Posts</a> ")
|
||||
end
|
||||
|
||||
-- Delimiter
|
||||
if page_number < pages_count AND page_number > 1 then
|
||||
a_output.append (" | ")
|
||||
end
|
||||
|
||||
-- If exist newer posts show link to previous page
|
||||
if page_number > 1 then
|
||||
tmp := page_number -1
|
||||
a_output.append (" <a class=%"blog_newer_posts%" href=%"" + base_path + "/page/" + tmp.out + "%">Newer Posts >></a> ")
|
||||
end
|
||||
|
||||
a_output.append ("</div>")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
base_path : STRING
|
||||
-- the path to the page that lists all blogs
|
||||
do
|
||||
Result := "/blogs"
|
||||
end
|
||||
|
||||
end
|
||||
150
examples/demo/modules/blog/handler/blog_user_handler.e
Normal file
150
examples/demo/modules/blog/handler/blog_user_handler.e
Normal file
@@ -0,0 +1,150 @@
|
||||
note
|
||||
description: "[
|
||||
Request handler related to
|
||||
/blogs/user/{id}/
|
||||
or /blogs/user/{id}/page/{page}.
|
||||
|
||||
Displays all posts of the given user
|
||||
]"
|
||||
author: "Dario Bösch <daboesch@student.ethz.ch>"
|
||||
date: "$Date: 2015-05-22 15:13:00 +0100 (lun., 18 mai 2015) $"
|
||||
revision: "$Revision 96616$"
|
||||
|
||||
class
|
||||
BLOG_USER_HANDLER
|
||||
|
||||
inherit
|
||||
BLOG_HANDLER
|
||||
redefine
|
||||
do_get,
|
||||
posts,
|
||||
total_entries,
|
||||
append_page_title_html_to,
|
||||
base_path
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Global Variables
|
||||
|
||||
user : detachable CMS_USER
|
||||
|
||||
feature -- HTTP Methods
|
||||
|
||||
do_get (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- <Precursor>
|
||||
local
|
||||
l_error: NOT_FOUND_ERROR_CMS_RESPONSE
|
||||
do
|
||||
user := Void
|
||||
if attached user_from_request (req) as l_user then
|
||||
user := l_user
|
||||
-- Output the results, similar as in the blog hanlder (but with other queries)
|
||||
Precursor (req, res)
|
||||
else
|
||||
-- Throw a bad request error because the user is not valid
|
||||
create l_error.make (req, res, api)
|
||||
l_error.set_main_content ("<h1>Error</h1>User with id " + user_id_path_parameter (req).out + " doesn't exist!")
|
||||
l_error.execute
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Query
|
||||
|
||||
user_valid (req: WSF_REQUEST) : BOOLEAN
|
||||
-- Returns true if a valid user id is given and a user with this id exists,
|
||||
-- otherwise returns false.
|
||||
local
|
||||
user_id: INTEGER_32
|
||||
do
|
||||
user_id := user_id_path_parameter (req)
|
||||
|
||||
if user_id <= 0 then
|
||||
-- Given user id is not valid
|
||||
Result := False
|
||||
else
|
||||
--Check if user with user_id exists
|
||||
Result := api.user_api.user_by_id (user_id) /= Void
|
||||
end
|
||||
end
|
||||
|
||||
user_from_request (req: WSF_REQUEST): detachable CMS_USER
|
||||
-- Eventual user with given id in the path of request `req'.
|
||||
local
|
||||
uid: like user_id_path_parameter
|
||||
do
|
||||
uid := user_id_path_parameter (req)
|
||||
if uid > 0 then
|
||||
Result := api.user_api.user_by_id (uid)
|
||||
else
|
||||
-- Missing or invalid user id.
|
||||
end
|
||||
end
|
||||
|
||||
user_id_path_parameter (req: WSF_REQUEST): INTEGER_32
|
||||
-- User id from path /blogs/{user}.
|
||||
-- Unsigned integer since negative ids are not allowed.
|
||||
-- If no valid id can be read it returns -1
|
||||
local
|
||||
s: STRING
|
||||
do
|
||||
Result := -1
|
||||
if attached {WSF_STRING} req.path_parameter ("user") as l_user_id then
|
||||
if l_user_id.is_integer then
|
||||
Result := l_user_id.integer_value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
posts: LIST [CMS_BLOG]
|
||||
-- Blog posts to display on given page.
|
||||
-- Filters out the posts of the current user.
|
||||
do
|
||||
if attached user as l_user then
|
||||
Result := blog_api.blogs_from_user_order_created_desc_limited (l_user, entries_per_page, entries_per_page * (page_number - 1))
|
||||
else
|
||||
create {ARRAYED_LIST [CMS_BLOG]} Result.make (0)
|
||||
end
|
||||
end
|
||||
|
||||
total_entries : NATURAL_32
|
||||
-- Returns the number of total entries/posts of the current user
|
||||
do
|
||||
if attached user as l_user then
|
||||
Result := blog_api.blogs_count_from_user (l_user).to_natural_32
|
||||
else
|
||||
Result := Precursor
|
||||
end
|
||||
end
|
||||
|
||||
feature -- HTML Output
|
||||
|
||||
append_page_title_html_to (a_output: STRING)
|
||||
-- Returns the title of the page as a html string. It shows the current page number and the name of the current user
|
||||
do
|
||||
a_output.append ("<h2>Posts from ")
|
||||
if attached user as l_user then
|
||||
a_output.append (l_user.name)
|
||||
else
|
||||
a_output.append ("unknown user")
|
||||
end
|
||||
if multiple_pages_needed then
|
||||
a_output.append (" (Page " + page_number.out + " of " + pages_count.out + ")")
|
||||
-- Get the posts from the current page (limited by entries per page)
|
||||
end
|
||||
a_output.append ("</h2>")
|
||||
end
|
||||
|
||||
base_path : STRING
|
||||
-- Path to page listing all blogs.
|
||||
-- If user is logged in, include user id
|
||||
do
|
||||
if attached user as l_user then
|
||||
Result := "/blogs/user/" + l_user.id.out
|
||||
else
|
||||
Result := precursor
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
23
examples/demo/modules/blog/handler/cms_blog_handler.e
Normal file
23
examples/demo/modules/blog/handler/cms_blog_handler.e
Normal file
@@ -0,0 +1,23 @@
|
||||
note
|
||||
description: "Deferred request handler related to /blogs/... Has an own blog api."
|
||||
author: "Dario Bösch <daboesch@student.ethz.ch>"
|
||||
date: "$Date: 2015-05-18 13:49:00 +0100 (lun., 18 mai 2015) $"
|
||||
revision: "$9661667$"
|
||||
|
||||
deferred class
|
||||
CMS_BLOG_HANDLER
|
||||
|
||||
inherit
|
||||
CMS_MODULE_HANDLER [CMS_BLOG_API]
|
||||
rename
|
||||
module_api as blog_api
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
entries_per_page: NATURAL_32
|
||||
do
|
||||
Result := blog_api.entries_per_page
|
||||
end
|
||||
|
||||
end
|
||||
43
examples/demo/modules/blog/persistence/cms_blog_storage_i.e
Normal file
43
examples/demo/modules/blog/persistence/cms_blog_storage_i.e
Normal file
@@ -0,0 +1,43 @@
|
||||
note
|
||||
description: "Interface for accessing blog contents from the database."
|
||||
date: "$Date: 2015-01-27 19:15:02 +0100 (mar., 27 janv. 2015) $"
|
||||
revision: "$Revision: 96542 $"
|
||||
|
||||
deferred class
|
||||
CMS_BLOG_STORAGE_I
|
||||
|
||||
inherit
|
||||
CMS_NODE_STORAGE_I
|
||||
|
||||
feature -- Access
|
||||
|
||||
blogs_count: INTEGER_64
|
||||
-- Count of blog nodes
|
||||
deferred
|
||||
end
|
||||
|
||||
blogs_count_from_user (a_user: CMS_USER) : INTEGER_64
|
||||
-- Number of nodes of type blog from `a_user'.
|
||||
require
|
||||
has_id: a_user.has_id
|
||||
deferred
|
||||
end
|
||||
|
||||
blogs: LIST [CMS_NODE]
|
||||
-- List of nodes ordered by creation date (descending).
|
||||
deferred
|
||||
end
|
||||
|
||||
blogs_limited (limit: NATURAL_32; offset: NATURAL_32): LIST [CMS_NODE]
|
||||
-- List of posts ordered by creation date from offset to offset + limit.
|
||||
deferred
|
||||
end
|
||||
|
||||
blogs_from_user_limited (a_user: CMS_USER; limit: NATURAL_32; offset: NATURAL_32): LIST [CMS_NODE]
|
||||
-- List of posts from `a_user' ordered by creation date from offset to offset + limit.
|
||||
require
|
||||
has_id: a_user.has_id
|
||||
deferred
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,47 @@
|
||||
note
|
||||
description: "Summary description for {CMS_BLOG_STORAGE_NULL}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_BLOG_STORAGE_NULL
|
||||
|
||||
inherit
|
||||
CMS_NODE_STORAGE_NULL
|
||||
|
||||
CMS_BLOG_STORAGE_I
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Access
|
||||
|
||||
blogs_count: INTEGER_64
|
||||
-- Count of nodes.
|
||||
do
|
||||
end
|
||||
|
||||
blogs_count_from_user (a_user: CMS_USER) : INTEGER_64
|
||||
-- <Precursor>
|
||||
do
|
||||
end
|
||||
|
||||
blogs: LIST [CMS_NODE]
|
||||
-- <Precursor>
|
||||
do
|
||||
create {ARRAYED_LIST [CMS_NODE]} Result.make (0)
|
||||
end
|
||||
|
||||
blogs_limited (limit: NATURAL_32; offset: NATURAL_32) : LIST [CMS_NODE]
|
||||
-- <Precursor>
|
||||
do
|
||||
create {ARRAYED_LIST [CMS_NODE]} Result.make (0)
|
||||
end
|
||||
|
||||
blogs_from_user_limited (a_user: CMS_USER; limit: NATURAL_32; offset: NATURAL_32): LIST [CMS_NODE]
|
||||
-- <Precursor>
|
||||
do
|
||||
create {ARRAYED_LIST [CMS_NODE]} Result.make (0)
|
||||
end
|
||||
end
|
||||
140
examples/demo/modules/blog/persistence/cms_blog_storage_sql.e
Normal file
140
examples/demo/modules/blog/persistence/cms_blog_storage_sql.e
Normal file
@@ -0,0 +1,140 @@
|
||||
note
|
||||
description: "Access to the sql database for the blog module"
|
||||
author: "Dario Bösch <daboesch@student.ethz.ch>"
|
||||
date: "$Date: 2015-05-21 14:46:00 +0100$"
|
||||
revision: "$Revision: 96616 $"
|
||||
|
||||
class
|
||||
CMS_BLOG_STORAGE_SQL
|
||||
|
||||
inherit
|
||||
CMS_NODE_STORAGE_SQL
|
||||
|
||||
CMS_BLOG_STORAGE_I
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Access
|
||||
|
||||
blogs_count: INTEGER_64
|
||||
-- <Precursor>
|
||||
do
|
||||
error_handler.reset
|
||||
write_information_log (generator + ".blogs_count")
|
||||
sql_query (sql_select_blog_count, Void)
|
||||
if sql_rows_count = 1 then
|
||||
Result := sql_read_integer_64 (1)
|
||||
end
|
||||
end
|
||||
|
||||
blogs_count_from_user (a_user: CMS_USER) : INTEGER_64
|
||||
-- <Precursor>
|
||||
local
|
||||
l_parameters: STRING_TABLE [detachable ANY]
|
||||
do
|
||||
error_handler.reset
|
||||
write_information_log (generator + ".blogs_count_from_user")
|
||||
create l_parameters.make (2)
|
||||
l_parameters.put (a_user.id, "user")
|
||||
sql_query (sql_select_blog_count_from_user, l_parameters)
|
||||
if sql_rows_count = 1 then
|
||||
Result := sql_read_integer_64 (1)
|
||||
end
|
||||
end
|
||||
|
||||
blogs: LIST [CMS_NODE]
|
||||
-- <Precursor>
|
||||
do
|
||||
create {ARRAYED_LIST [CMS_NODE]} Result.make (0)
|
||||
|
||||
error_handler.reset
|
||||
write_information_log (generator + ".blogs")
|
||||
|
||||
from
|
||||
sql_query (sql_select_blogs_order_created_desc, Void)
|
||||
sql_start
|
||||
until
|
||||
sql_after
|
||||
loop
|
||||
if attached fetch_node as l_node then
|
||||
Result.force (l_node)
|
||||
end
|
||||
sql_forth
|
||||
end
|
||||
end
|
||||
|
||||
blogs_limited (a_limit: NATURAL_32; a_offset: NATURAL_32): LIST [CMS_NODE]
|
||||
-- <Precursor>
|
||||
local
|
||||
l_parameters: STRING_TABLE [detachable ANY]
|
||||
do
|
||||
create {ARRAYED_LIST [CMS_NODE]} Result.make (0)
|
||||
|
||||
error_handler.reset
|
||||
write_information_log (generator + ".blogs_limited")
|
||||
|
||||
from
|
||||
create l_parameters.make (2)
|
||||
l_parameters.put (a_limit, "limit")
|
||||
l_parameters.put (a_offset, "offset")
|
||||
sql_query (sql_blogs_limited, l_parameters)
|
||||
sql_start
|
||||
until
|
||||
sql_after
|
||||
loop
|
||||
if attached fetch_node as l_node then
|
||||
Result.force (l_node)
|
||||
end
|
||||
sql_forth
|
||||
end
|
||||
end
|
||||
|
||||
blogs_from_user_limited (a_user: CMS_USER; a_limit: NATURAL_32; a_offset: NATURAL_32): LIST [CMS_NODE]
|
||||
-- <Precursor>
|
||||
local
|
||||
l_parameters: STRING_TABLE [detachable ANY]
|
||||
do
|
||||
create {ARRAYED_LIST [CMS_NODE]} Result.make (0)
|
||||
|
||||
error_handler.reset
|
||||
write_information_log (generator + ".blogs_from_user_limited")
|
||||
|
||||
from
|
||||
create l_parameters.make (2)
|
||||
l_parameters.put (a_limit, "limit")
|
||||
l_parameters.put (a_offset, "offset")
|
||||
l_parameters.put (a_user.id, "user")
|
||||
sql_query (sql_blogs_from_user_limited, l_parameters)
|
||||
sql_start
|
||||
until
|
||||
sql_after
|
||||
loop
|
||||
if attached fetch_node as l_node then
|
||||
Result.force (l_node)
|
||||
end
|
||||
sql_forth
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Queries
|
||||
|
||||
sql_select_blog_count: STRING = "SELECT count(*) FROM Nodes WHERE status != -1 AND type = %"blog%";"
|
||||
-- Nodes count (Published and not Published)
|
||||
--| note: {CMS_NODE_API}.trashed = -1
|
||||
|
||||
sql_select_blog_count_from_user: STRING = "SELECT count(*) FROM Nodes WHERE status != -1 AND type = %"blog%" AND author = :user ;"
|
||||
-- Nodes count (Published and not Published)
|
||||
--| note: {CMS_NODE_API}.trashed = -1
|
||||
|
||||
sql_select_blogs_order_created_desc: STRING = "SELECT * FROM Nodes WHERE status != -1 AND type = %"blog%" ORDER BY created DESC;"
|
||||
-- SQL Query to retrieve all nodes that are from the type "blog" ordered by descending creation date.
|
||||
|
||||
sql_blogs_limited: STRING = "SELECT * FROM Nodes WHERE status != -1 AND type = %"blog%" ORDER BY created DESC LIMIT :limit OFFSET :offset ;"
|
||||
--- SQL Query to retrieve all node of type "blog" limited by limit and starting at offset
|
||||
|
||||
sql_blogs_from_user_limited: STRING = "SELECT * FROM Nodes WHERE status != -1 AND type = %"blog%" AND author = :user ORDER BY created DESC LIMIT :limit OFFSET :offset ;"
|
||||
--- SQL Query to retrieve all node of type "blog" from author with id limited by limit + offset
|
||||
|
||||
|
||||
end
|
||||
@@ -80,12 +80,11 @@ CREATE TABLE "tb_demo"(
|
||||
|
||||
feature -- Access: router
|
||||
|
||||
router (a_api: CMS_API): WSF_ROUTER
|
||||
-- Node router.
|
||||
setup_router (a_router: WSF_ROUTER; a_api: CMS_API)
|
||||
-- <Precursor>
|
||||
do
|
||||
create Result.make (2)
|
||||
map_uri_template_agent (Result, "/demo/", agent handle_demo (?,?,a_api))
|
||||
map_uri_template_agent (Result, "/demo/{id}", agent handle_demo_entry (?,?,a_api))
|
||||
map_uri_template_agent (a_router, "/demo/", agent handle_demo (?,?,a_api))
|
||||
map_uri_template_agent (a_router, "/demo/{id}", agent handle_demo_entry (?,?,a_api))
|
||||
end
|
||||
|
||||
feature -- Hooks
|
||||
@@ -111,9 +110,9 @@ feature -- Hooks
|
||||
if a_block_id.is_case_insensitive_equal_general ("demo-info") then
|
||||
if a_response.request.request_uri.starts_with ("/demo/") then
|
||||
create m.make_with_title (a_block_id, "Demo", 2)
|
||||
create lnk.make ("/demo/abc", a_response.url ("/demo/abc", Void))
|
||||
create lnk.make ("demo: abc", "demo/abc")
|
||||
m.extend (lnk)
|
||||
create lnk.make ("/demo/123", a_response.url ("/demo/123", Void))
|
||||
create lnk.make ("demo: 123", "demo/123")
|
||||
m.extend (lnk)
|
||||
create mb.make (m)
|
||||
a_response.add_block (mb, "sidebar_second")
|
||||
@@ -126,7 +125,7 @@ feature -- Hooks
|
||||
lnk: CMS_LOCAL_LINK
|
||||
-- perms: detachable ARRAYED_LIST [READABLE_STRING_8]
|
||||
do
|
||||
create lnk.make ("Demo", "/demo/")
|
||||
create lnk.make ("Demo", "demo/")
|
||||
a_menu_system.primary_menu.extend (lnk)
|
||||
end
|
||||
|
||||
@@ -138,8 +137,8 @@ feature -- Handler
|
||||
r: NOT_IMPLEMENTED_ERROR_CMS_RESPONSE
|
||||
do
|
||||
create r.make (req, res, a_api)
|
||||
r.set_main_content ("NODE module does not yet implement %"" + req.path_info + "%" ...")
|
||||
r.add_error_message ("NODE Module: not yet implemented")
|
||||
r.set_main_content ("DEMO module does not yet implement %"" + req.path_info + "%" ...")
|
||||
r.add_error_message ("DEMO Module: not yet implemented")
|
||||
r.execute
|
||||
end
|
||||
|
||||
|
||||
@@ -23,7 +23,8 @@
|
||||
"server": "localhost"
|
||||
},
|
||||
"logger": {
|
||||
"level":"debug",
|
||||
"level":"error",
|
||||
"type":"stderr",
|
||||
"backup_count":"4"
|
||||
},
|
||||
"server": {
|
||||
|
||||
@@ -1,35 +1,5 @@
|
||||
BEGIN;
|
||||
|
||||
CREATE TABLE "users"(
|
||||
"uid" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK("uid">=0),
|
||||
"name" VARCHAR(100) NOT NULL,
|
||||
"password" VARCHAR(100) NOT NULL,
|
||||
"salt" VARCHAR(100) NOT NULL,
|
||||
"email" VARCHAR(250) NOT NULL,
|
||||
"status" INTEGER,
|
||||
"created" DATETIME NOT NULL,
|
||||
"signed" DATETIME,
|
||||
CONSTRAINT "name"
|
||||
UNIQUE("name")
|
||||
);
|
||||
|
||||
CREATE TABLE "roles"(
|
||||
"rid" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK("rid">=0),
|
||||
"name" VARCHAR(100) NOT NULL,
|
||||
CONSTRAINT "name"
|
||||
UNIQUE("name")
|
||||
);
|
||||
|
||||
CREATE TABLE "users_roles"(
|
||||
"uid" INTEGER NOT NULL CHECK("uid">=0),
|
||||
"rid" INTEGER NOT NULL CHECK("rid">=0)
|
||||
);
|
||||
|
||||
CREATE TABLE "role_permissions"(
|
||||
"rid" INTEGER NOT NULL CHECK("rid">=0),
|
||||
"permission" VARCHAR(255) NOT NULL,
|
||||
"module" VARCHAR(255)
|
||||
);
|
||||
|
||||
CREATE TABLE "logs"(
|
||||
"id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK("id">=0),
|
||||
@@ -45,7 +15,14 @@ CREATE TABLE "logs"(
|
||||
CREATE TABLE "custom_values"(
|
||||
"type" VARCHAR(255) NOT NULL,
|
||||
"name" VARCHAR(255) NOT NULL,
|
||||
"value" VARCHAR(255) NOT NULL
|
||||
"value" TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE "path_aliases"(
|
||||
"pid" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK("pid">=0),
|
||||
"source" VARCHAR(255) NOT NULL,
|
||||
"alias" VARCHAR(255) NOT NULL,
|
||||
"lang" VARCHAR(12)
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
BEGIN;
|
||||
|
||||
CREATE TABLE "nodes"(
|
||||
"nid" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK("nid">=0),
|
||||
"revision" INTEGER,
|
||||
"type" TEXT NOT NULL,
|
||||
"title" VARCHAR(255) NOT NULL,
|
||||
"summary" TEXT,
|
||||
"content" MEDIUMTEXT NOT NULL,
|
||||
"format" VARCHAR(255),
|
||||
"author" INTEGER,
|
||||
"publish" DATETIME,
|
||||
"created" DATETIME NOT NULL,
|
||||
"changed" DATETIME NOT NULL
|
||||
CREATE TABLE "nodes" (
|
||||
"nid" INTEGER NOT NULL CHECK("nid" > 0) PRIMARY KEY AUTOINCREMENT UNIQUE,
|
||||
"revision" INTEGER,
|
||||
"type" TEXT NOT NULL,
|
||||
"title" VARCHAR(255) NOT NULL,
|
||||
"summary" TEXT,
|
||||
"content" TEXT,
|
||||
"format" VARCHAR(128),
|
||||
"author" INTEGER,
|
||||
"publish" DATETIME,
|
||||
"created" DATETIME NOT NULL,
|
||||
"changed" DATETIME NOT NULL,
|
||||
"status" INTEGER
|
||||
);
|
||||
|
||||
CREATE TABLE page_nodes(
|
||||
|
||||
34
examples/demo/site/scripts/user.sql
Normal file
34
examples/demo/site/scripts/user.sql
Normal file
@@ -0,0 +1,34 @@
|
||||
BEGIN;
|
||||
|
||||
CREATE TABLE "users"(
|
||||
"uid" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK("uid">=0),
|
||||
"name" VARCHAR(100) NOT NULL,
|
||||
"password" VARCHAR(100) NOT NULL,
|
||||
"salt" VARCHAR(100) NOT NULL,
|
||||
"email" VARCHAR(250) NOT NULL,
|
||||
"status" INTEGER,
|
||||
"created" DATETIME NOT NULL,
|
||||
"signed" DATETIME,
|
||||
CONSTRAINT "name"
|
||||
UNIQUE("name")
|
||||
);
|
||||
|
||||
CREATE TABLE "roles"(
|
||||
"rid" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK("rid">=0),
|
||||
"name" VARCHAR(100) NOT NULL,
|
||||
CONSTRAINT "name"
|
||||
UNIQUE("name")
|
||||
);
|
||||
|
||||
CREATE TABLE "users_roles"(
|
||||
"uid" INTEGER NOT NULL CHECK("uid">=0),
|
||||
"rid" INTEGER NOT NULL CHECK("rid">=0)
|
||||
);
|
||||
|
||||
CREATE TABLE "role_permissions"(
|
||||
"rid" INTEGER NOT NULL CHECK("rid">=0),
|
||||
"permission" VARCHAR(255) NOT NULL,
|
||||
"module" VARCHAR(255)
|
||||
);
|
||||
|
||||
COMMIT;
|
||||
25
examples/demo/site/themes/bootstrap/assets/css/blog.css
Normal file
25
examples/demo/site/themes/bootstrap/assets/css/blog.css
Normal file
@@ -0,0 +1,25 @@
|
||||
ul.cms_blog_nodes {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
ul.cms_blog_nodes li.cms_type_blog {
|
||||
list-style: none;
|
||||
display: block;
|
||||
margin-top: 20px;
|
||||
padding-bottom: 20px;
|
||||
border-bottom: 1px dotted black;
|
||||
}
|
||||
ul.cms_blog_nodes li.cms_type_blog .blog_title a {
|
||||
color: black;
|
||||
font-size: 18px;
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
margin: 6px 0;
|
||||
}
|
||||
ul.cms_blog_nodes li.cms_type_blog .blog_title a:hover {
|
||||
color: #999;
|
||||
}
|
||||
ul.cms_blog_nodes li.cms_type_blog .blog_list_summary a {
|
||||
margin-top: 20px;
|
||||
display: block;
|
||||
}
|
||||
@@ -3,13 +3,15 @@ ul.cms-nodes {
|
||||
padding: 3px 3px 3px 3px;
|
||||
border: solid 1px #ccc;
|
||||
}
|
||||
|
||||
li.cms_type_page {
|
||||
ul.cms-nodes li {
|
||||
border-top: dotted 1px #ccc;
|
||||
}
|
||||
li.cms_type_page a::before {
|
||||
content: "[page] ";
|
||||
}
|
||||
li.cms_type_page:first-child {
|
||||
ul.cms-nodes li:first-child {
|
||||
border-top: none;
|
||||
}
|
||||
ul.cms-nodes li.cms_type_page a::before {
|
||||
content: "[page] ";
|
||||
}
|
||||
ul.cms-nodes li.cms_type_blog a::before {
|
||||
content: "[blog] ";
|
||||
}
|
||||
|
||||
BIN
examples/demo/site/themes/bootstrap/assets/favicon.ico
Normal file
BIN
examples/demo/site/themes/bootstrap/assets/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 994 B |
30
examples/demo/site/themes/bootstrap/assets/scss/blog.scss
Normal file
30
examples/demo/site/themes/bootstrap/assets/scss/blog.scss
Normal file
@@ -0,0 +1,30 @@
|
||||
ul.cms_blog_nodes{
|
||||
|
||||
padding:0;
|
||||
margin:0;
|
||||
|
||||
li.cms_type_blog{
|
||||
list-style: none;
|
||||
display: block;
|
||||
margin-top:20px;
|
||||
padding-bottom:20px;
|
||||
border-bottom:1px dotted black;
|
||||
|
||||
.blog_title a{
|
||||
color:black;
|
||||
font-size:18px;
|
||||
text-decoration: none;
|
||||
display:block;
|
||||
margin:6px 0;
|
||||
|
||||
&:hover{
|
||||
color:#999;
|
||||
}
|
||||
}
|
||||
|
||||
.blog_list_summary a{
|
||||
margin-top:20px;
|
||||
display:block;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,24 @@
|
||||
ul.cms-nodes {
|
||||
|
||||
list-style-type: none;
|
||||
padding: 3px 3px 3px 3px;
|
||||
border: solid 1px #ccc;
|
||||
}
|
||||
li.cms_type_page {
|
||||
a::before {
|
||||
|
||||
li{
|
||||
border-top: dotted 1px #ccc;
|
||||
&:first-child {
|
||||
border-top: none;
|
||||
}
|
||||
}
|
||||
|
||||
li.cms_type_page a::before {
|
||||
content: "[page] ";
|
||||
}
|
||||
border-top: dotted 1px #ccc;
|
||||
&:first-child {
|
||||
border-top: none;
|
||||
|
||||
li.cms_type_blog a::before {
|
||||
content: "[blog] ";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -4,10 +4,14 @@
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<!-- EWF CMS -->
|
||||
<link rel="stylesheet" href="{$site_url/}/theme/css/style.css">
|
||||
<link rel="stylesheet" href="{$site_url/}/theme/css/node.css">
|
||||
<script src="{$site_url/}/theme/js/jquery-1.10.2.min.js"></script>
|
||||
<script src="{$site_url/}/theme/js/roc_auth.js"></script>
|
||||
<link rel="stylesheet" href="{$site_url/}theme/css/style.css">
|
||||
<link rel="stylesheet" href="{$site_url/}theme/css/node.css">
|
||||
|
||||
<!-- CMS Blog Module -->
|
||||
<link rel="stylesheet" href="{$site_url/}theme/css/blog.css">
|
||||
|
||||
<script src="{$site_url/}theme/js/jquery-1.10.2.min.js"></script>
|
||||
<script src="{$site_url/}theme/js/roc_auth.js"></script>
|
||||
|
||||
<!-- bootstrap framework -->
|
||||
<!-- Latest compiled and minified CSS -->
|
||||
|
||||
@@ -16,11 +16,6 @@ inherit
|
||||
initialize
|
||||
end
|
||||
|
||||
WSF_SERVICE
|
||||
redefine
|
||||
execute
|
||||
end
|
||||
|
||||
REFACTORING_HELPER
|
||||
|
||||
SHARED_EXECUTION_ENVIRONMENT
|
||||
@@ -40,37 +35,26 @@ feature {NONE} -- Initialization
|
||||
|
||||
initialize
|
||||
-- Initialize current service.
|
||||
local
|
||||
env: CMS_ENVIRONMENT
|
||||
do
|
||||
-- Launcher
|
||||
Precursor
|
||||
create {WSF_SERVICE_LAUNCHER_OPTIONS_FROM_INI} service_options.make_from_file ("demo.ini")
|
||||
|
||||
-- CMS
|
||||
initialize_cms
|
||||
end
|
||||
|
||||
feature -- Service
|
||||
|
||||
cms_service: CMS_SERVICE
|
||||
-- cms service.
|
||||
|
||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
do
|
||||
cms_service.execute (req, res)
|
||||
create env.make_default
|
||||
initialize_logger (env)
|
||||
end
|
||||
|
||||
feature {NONE} -- Launch operation
|
||||
|
||||
launcher: APPLICATION_LAUNCHER
|
||||
launcher: APPLICATION_LAUNCHER [EWF_ROC_SERVER_EXECUTION]
|
||||
|
||||
launch (a_service: WSF_SERVICE; opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
|
||||
launch (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
|
||||
local
|
||||
l_retry: BOOLEAN
|
||||
l_message: STRING
|
||||
do
|
||||
if not l_retry then
|
||||
write_debug_log (generator + ".launch")
|
||||
launcher.launch (a_service, opts)
|
||||
launcher.launch (opts)
|
||||
else
|
||||
-- error hanling.
|
||||
create l_message.make (1024)
|
||||
@@ -89,77 +73,12 @@ feature {NONE} -- Launch operation
|
||||
l_message.append ("The application crash without available information")
|
||||
l_message.append ("%N%N")
|
||||
end
|
||||
-- notify shutdown
|
||||
write_debug_log (generator + ".launch shutdown")
|
||||
-- send email shutdown
|
||||
end
|
||||
rescue
|
||||
l_retry := True
|
||||
retry
|
||||
end
|
||||
|
||||
feature -- CMS Initialization
|
||||
|
||||
initialize_cms
|
||||
local
|
||||
l_setup: CMS_DEFAULT_SETUP
|
||||
utf: UTF_CONVERTER
|
||||
cms_env: CMS_ENVIRONMENT
|
||||
do
|
||||
-- Application Environment initialization
|
||||
if attached execution_environment.arguments.separate_character_option_value ('d') as l_dir then
|
||||
create cms_env.make_with_directory_name (l_dir)
|
||||
else
|
||||
create cms_env.make_default
|
||||
end
|
||||
initialize_logger (cms_env)
|
||||
|
||||
-- CMS Setup
|
||||
write_debug_log (generator + ".initialize_cms / SETUP based directory=%"" + utf.escaped_utf_32_string_to_utf_8_string_8 (cms_env.path.name) + "%"")
|
||||
create l_setup.make (cms_env)
|
||||
|
||||
-- CMS
|
||||
write_debug_log (generator + ".initialize_cms / CMS")
|
||||
setup_storage (l_setup)
|
||||
setup_modules (l_setup)
|
||||
create cms_service.make (l_setup)
|
||||
end
|
||||
|
||||
feature -- CMS setup
|
||||
|
||||
setup_modules (a_setup: CMS_SETUP)
|
||||
-- Setup additional modules.
|
||||
local
|
||||
m: CMS_MODULE
|
||||
do
|
||||
create {NODE_MODULE} m.make (a_setup)
|
||||
m.enable
|
||||
a_setup.register_module (m)
|
||||
|
||||
create {BASIC_AUTH_MODULE} m.make
|
||||
if not a_setup.module_with_same_type_registered (m) then
|
||||
m.enable
|
||||
a_setup.register_module (m)
|
||||
end
|
||||
|
||||
create {CMS_DEBUG_MODULE} m.make
|
||||
m.enable
|
||||
a_setup.register_module (m)
|
||||
|
||||
create {CMS_DEMO_MODULE} m.make
|
||||
m.enable
|
||||
a_setup.register_module (m)
|
||||
|
||||
create {CMS_BLOG_MODULE} m.make
|
||||
m.enable
|
||||
a_setup.register_module (m)
|
||||
end
|
||||
|
||||
setup_storage (a_setup: CMS_SETUP)
|
||||
-- Setup storage by declaring storage builder.
|
||||
do
|
||||
-- a_setup.storage_drivers.force (create {CMS_STORAGE_MYSQL_BUILDER}.make, "mysql")
|
||||
a_setup.storage_drivers.force (create {CMS_STORAGE_SQLITE_BUILDER}.make, "sqlite")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
81
examples/demo/src/ewf_roc_server_execution.e
Normal file
81
examples/demo/src/ewf_roc_server_execution.e
Normal file
@@ -0,0 +1,81 @@
|
||||
note
|
||||
description: "Summary description for {EWF_ROC_SERVER_EXECUTION}."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
EWF_ROC_SERVER_EXECUTION
|
||||
|
||||
inherit
|
||||
CMS_EXECUTION
|
||||
redefine
|
||||
initialize
|
||||
end
|
||||
|
||||
REFACTORING_HELPER
|
||||
|
||||
SHARED_LOGGER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
initialize
|
||||
do
|
||||
Precursor
|
||||
end
|
||||
|
||||
initial_cms_setup: CMS_DEFAULT_SETUP
|
||||
-- CMS setup.
|
||||
local
|
||||
l_env: CMS_ENVIRONMENT
|
||||
do
|
||||
if attached execution_environment.arguments.separate_character_option_value ('d') as l_dir then
|
||||
create l_env.make_with_directory_name (l_dir)
|
||||
else
|
||||
create l_env.make_default
|
||||
end
|
||||
create Result.make (l_env)
|
||||
end
|
||||
|
||||
feature -- CMS setup
|
||||
|
||||
setup_storage (a_setup: CMS_SETUP)
|
||||
do
|
||||
debug ("refactor_fixme")
|
||||
to_implement ("To implement custom storage")
|
||||
end
|
||||
-- a_setup.storage_drivers.force (create {CMS_STORAGE_MYSQL_BUILDER}.make, "mysql")
|
||||
a_setup.storage_drivers.force (create {CMS_STORAGE_SQLITE_BUILDER}.make, "sqlite")
|
||||
end
|
||||
|
||||
setup_modules (a_setup: CMS_SETUP)
|
||||
-- Setup additional modules.
|
||||
local
|
||||
m: CMS_MODULE
|
||||
do
|
||||
create {NODE_MODULE} m.make (a_setup)
|
||||
m.enable
|
||||
a_setup.register_module (m)
|
||||
|
||||
create {BASIC_AUTH_MODULE} m.make
|
||||
if not a_setup.module_with_same_type_registered (m) then
|
||||
m.enable
|
||||
a_setup.register_module (m)
|
||||
end
|
||||
|
||||
create {CMS_DEBUG_MODULE} m.make
|
||||
m.enable
|
||||
a_setup.register_module (m)
|
||||
|
||||
create {CMS_DEMO_MODULE} m.make
|
||||
m.enable
|
||||
a_setup.register_module (m)
|
||||
|
||||
create {CMS_BLOG_MODULE} m.make
|
||||
m.enable
|
||||
a_setup.register_module (m)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -30,6 +30,7 @@ feature -- Initialization
|
||||
backup_count := 4
|
||||
level := Log_debug
|
||||
location := Void
|
||||
type := {STRING_32} "null"
|
||||
ensure then
|
||||
backup_count_set: backup_count = 4
|
||||
level_set: level = Log_debug
|
||||
@@ -48,6 +49,9 @@ feature -- Access
|
||||
level: INTEGER
|
||||
-- Logger level.
|
||||
|
||||
type: IMMUTABLE_STRING_32
|
||||
-- Type of logging.
|
||||
|
||||
feature -- Element Change
|
||||
|
||||
set_location (a_location: detachable PATH)
|
||||
@@ -65,6 +69,15 @@ feature -- Element Change
|
||||
set_location (create {PATH}.make_from_string (a_location))
|
||||
end
|
||||
|
||||
set_type_with_string (a_type: detachable READABLE_STRING_GENERAL)
|
||||
do
|
||||
if a_type /= Void and then not a_type.is_whitespace then
|
||||
create type.make_from_string_general (a_type)
|
||||
else
|
||||
create type.make_from_string_general ("null")
|
||||
end
|
||||
end
|
||||
|
||||
set_backup_count (a_backup: NATURAL)
|
||||
-- Set backup_count to `a_backup'.
|
||||
do
|
||||
|
||||
@@ -32,7 +32,7 @@ feature {NONE} -- Initialization
|
||||
create log.make
|
||||
end
|
||||
|
||||
make_with_environment (app: APPLICATION_ENVIRONMENT)
|
||||
make_with_environment (app: separate APPLICATION_ENVIRONMENT)
|
||||
-- Initialize a logger object with an application environment `app'.
|
||||
do
|
||||
make
|
||||
@@ -49,7 +49,7 @@ feature {NONE} -- Initialization
|
||||
|
||||
feature -- Change
|
||||
|
||||
apply_environment (app: APPLICATION_ENVIRONMENT)
|
||||
apply_environment (app: separate APPLICATION_ENVIRONMENT)
|
||||
do
|
||||
initialize_logger (app, log)
|
||||
end
|
||||
@@ -58,75 +58,107 @@ feature {NONE} -- Internal
|
||||
|
||||
log: LOGGING_FACILITY
|
||||
|
||||
feature -- Settings
|
||||
|
||||
level: INTEGER
|
||||
|
||||
feature -- Logging
|
||||
|
||||
put_debug (a_message: separate READABLE_STRING_8)
|
||||
-- Put message `a_message' to the log at debug level.
|
||||
do
|
||||
if level >= log_debug then
|
||||
log.write_debug (create {STRING}.make_from_separate (a_message))
|
||||
end
|
||||
end
|
||||
|
||||
put_information (a_message: separate READABLE_STRING_8)
|
||||
-- Put message `a_message' to the log at information level.
|
||||
do
|
||||
log.write_information (create {STRING}.make_from_separate (a_message))
|
||||
end
|
||||
|
||||
put_error (a_message: separate READABLE_STRING_8)
|
||||
-- Put message `a_message' to the log at error level.
|
||||
do
|
||||
log.write_error (create {STRING}.make_from_separate (a_message))
|
||||
if level >= log_information then
|
||||
log.write_information (create {STRING}.make_from_separate (a_message))
|
||||
end
|
||||
end
|
||||
|
||||
put_warning (a_message: separate READABLE_STRING_8)
|
||||
-- Put message `a_message' to the log at warning level.
|
||||
do
|
||||
log.write_warning (create {STRING}.make_from_separate (a_message))
|
||||
if level >= log_warning then
|
||||
log.write_warning (create {STRING}.make_from_separate (a_message))
|
||||
end
|
||||
end
|
||||
|
||||
put_error (a_message: separate READABLE_STRING_8)
|
||||
-- Put message `a_message' to the log at error level.
|
||||
do
|
||||
if level >= log_error then
|
||||
log.write_error (create {STRING}.make_from_separate (a_message))
|
||||
end
|
||||
end
|
||||
|
||||
put_critical (a_message: separate READABLE_STRING_8)
|
||||
-- Put message `a_message' to the log at critical level.
|
||||
do
|
||||
log.write_critical (create {STRING}.make_from_separate (a_message))
|
||||
if level >= log_critical then
|
||||
log.write_critical (create {STRING}.make_from_separate (a_message))
|
||||
end
|
||||
end
|
||||
|
||||
put_alert (a_message: separate READABLE_STRING_8)
|
||||
-- Put message `a_message' to the log at alert level.
|
||||
do
|
||||
log.write_alert (create {STRING}.make_from_separate (a_message))
|
||||
end
|
||||
|
||||
put_debug (a_message: separate READABLE_STRING_8)
|
||||
-- Put message `a_message' to the log at debug level.
|
||||
do
|
||||
log.write_debug (create {STRING}.make_from_separate (a_message))
|
||||
if level >= log_alert then
|
||||
log.write_alert (create {STRING}.make_from_separate (a_message))
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
initialize_logger (app: APPLICATION_ENVIRONMENT; a_log: like log)
|
||||
initialize_logger (app: separate APPLICATION_ENVIRONMENT; a_log: like log)
|
||||
local
|
||||
l_log_writer_file: LOG_ROLLING_WRITER_FILE
|
||||
l_log_writer: LOG_WRITER
|
||||
l_log_writer: detachable LOG_WRITER
|
||||
l_logs_path: detachable PATH
|
||||
l_logger_config: LOGGER_CONFIGURATION
|
||||
ut: FILE_UTILITIES
|
||||
p: PATH
|
||||
l_name: IMMUTABLE_STRING_32
|
||||
do
|
||||
l_logger_config := new_logger_level_configuration (app.application_config_path)
|
||||
l_logs_path := l_logger_config.location
|
||||
if l_logs_path = Void then
|
||||
l_logs_path := app.logs_path
|
||||
create l_name.make_from_separate (app.name)
|
||||
create p.make_from_separate (app.application_config_path)
|
||||
-- l_name := app.name
|
||||
-- p := app.application_config_path
|
||||
|
||||
l_logger_config := new_logger_level_configuration (p)
|
||||
if l_logger_config.type.is_case_insensitive_equal_general ("file") then
|
||||
l_logs_path := l_logger_config.location
|
||||
if l_logs_path = Void then
|
||||
create l_logs_path.make_from_separate (app.logs_path)
|
||||
end
|
||||
if ut.directory_path_exists (l_logs_path) then
|
||||
create l_log_writer_file.make_at_location (l_logs_path.extended (l_name).appended_with_extension ("log"))
|
||||
l_log_writer_file.set_max_file_size ({NATURAL_64} 1024 * 1204)
|
||||
l_log_writer_file.set_max_backup_count (l_logger_config.backup_count)
|
||||
l_log_writer := l_log_writer_file
|
||||
else
|
||||
-- Should we create the directory anyway ?
|
||||
end
|
||||
elseif l_logger_config.type.is_case_insensitive_equal_general ("stderr") then
|
||||
create {LOG_WRITER_STDERR} l_log_writer
|
||||
end
|
||||
if ut.directory_path_exists (l_logs_path) then
|
||||
create l_log_writer_file.make_at_location (l_logs_path.extended (app.name).appended_with_extension ("log"))
|
||||
l_log_writer_file.set_max_file_size ({NATURAL_64} 1024 * 1204)
|
||||
l_log_writer_file.set_max_backup_count (l_logger_config.backup_count)
|
||||
l_log_writer := l_log_writer_file
|
||||
else
|
||||
-- Should we create the directory anyway ?
|
||||
if l_log_writer = Void then
|
||||
create {LOG_WRITER_NULL} l_log_writer
|
||||
set_logger_level (l_log_writer, log_notice)
|
||||
else
|
||||
set_logger_level (l_log_writer, 0) -- None
|
||||
end
|
||||
set_logger_level (l_log_writer, l_logger_config.level)
|
||||
a_log.register_log_writer (l_log_writer)
|
||||
end
|
||||
|
||||
set_logger_level (a_log_writer: LOG_WRITER; a_priority: INTEGER)
|
||||
-- Setup the logger level based on `a_priority'
|
||||
do
|
||||
level := a_priority
|
||||
if a_priority = log_debug then
|
||||
a_log_writer.enable_debug_log_level
|
||||
elseif a_priority = Log_emergency then
|
||||
@@ -167,6 +199,9 @@ feature {NONE} -- Implementation
|
||||
attached l_parser.parsed_json_object as jv and then
|
||||
attached {JSON_OBJECT} jv.item ("logger") as l_logger
|
||||
then
|
||||
if attached {JSON_STRING} l_logger.item ("type") as l_type then
|
||||
Result.set_type_with_string (l_type.item)
|
||||
end
|
||||
if attached {JSON_STRING} l_logger.item ("location") as l_location then
|
||||
Result.set_location_with_string (l_location.item)
|
||||
end
|
||||
|
||||
@@ -35,72 +35,113 @@ feature -- Logging
|
||||
|
||||
write_debug_log (m: READABLE_STRING_8)
|
||||
do
|
||||
write_debug_log_to (m, logger)
|
||||
-- write_debug_log_to (m, logger)
|
||||
end
|
||||
|
||||
write_information_log (m: READABLE_STRING_8)
|
||||
do
|
||||
write_information_log_to (m, logger)
|
||||
-- write_information_log_to (m, logger)
|
||||
end
|
||||
|
||||
write_warning_log (m: READABLE_STRING_8)
|
||||
do
|
||||
write_warning_log_to (m, logger)
|
||||
-- write_warning_log_to (m, logger)
|
||||
end
|
||||
|
||||
write_error_log (m: READABLE_STRING_8)
|
||||
do
|
||||
write_error_log_to (m, logger)
|
||||
-- write_error_log_to (m, logger)
|
||||
end
|
||||
|
||||
write_critical_log (m: READABLE_STRING_8)
|
||||
do
|
||||
write_critical_log_to (m, logger)
|
||||
-- write_critical_log_to (m, logger)
|
||||
end
|
||||
|
||||
write_alert_log (m: READABLE_STRING_8)
|
||||
do
|
||||
write_alert_log_to (m, logger)
|
||||
-- write_alert_log_to (m, logger)
|
||||
end
|
||||
|
||||
feature {NONE} -- Logger: separate implementation
|
||||
|
||||
write_debug_log_to (m: READABLE_STRING_8; a_log: like logger)
|
||||
local
|
||||
retried: BOOLEAN
|
||||
do
|
||||
a_log.put_debug (m)
|
||||
if not retried then
|
||||
a_log.put_debug (m)
|
||||
end
|
||||
rescue
|
||||
retried := True
|
||||
retry
|
||||
end
|
||||
|
||||
write_information_log_to (m: READABLE_STRING_8; a_log: like logger)
|
||||
local
|
||||
retried: BOOLEAN
|
||||
do
|
||||
a_log.put_information (m)
|
||||
if not retried then
|
||||
a_log.put_information (m)
|
||||
end
|
||||
rescue
|
||||
retried := True
|
||||
retry
|
||||
end
|
||||
|
||||
write_warning_log_to (m: READABLE_STRING_8; a_log: like logger)
|
||||
local
|
||||
retried: BOOLEAN
|
||||
do
|
||||
a_log.put_warning (m)
|
||||
if not retried then
|
||||
a_log.put_warning (m)
|
||||
end
|
||||
rescue
|
||||
retried := True
|
||||
retry
|
||||
end
|
||||
|
||||
write_error_log_to (m: READABLE_STRING_8; a_log: like logger)
|
||||
local
|
||||
retried: BOOLEAN
|
||||
do
|
||||
a_log.put_error (m)
|
||||
if not retried then
|
||||
a_log.put_error (m)
|
||||
end
|
||||
rescue
|
||||
retried := True
|
||||
retry
|
||||
end
|
||||
|
||||
write_critical_log_to (m: READABLE_STRING_8; a_log: like logger)
|
||||
local
|
||||
retried: BOOLEAN
|
||||
do
|
||||
a_log.put_critical (m)
|
||||
if not retried then
|
||||
a_log.put_critical (m)
|
||||
end
|
||||
rescue
|
||||
retried := True
|
||||
retry
|
||||
end
|
||||
|
||||
write_alert_log_to (m: READABLE_STRING_8; a_log: like logger)
|
||||
local
|
||||
retried: BOOLEAN
|
||||
do
|
||||
a_log.put_alert (m)
|
||||
if not retried then
|
||||
a_log.put_alert (m)
|
||||
end
|
||||
rescue
|
||||
retried := True
|
||||
retry
|
||||
end
|
||||
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
initialize_logger (app: APPLICATION_ENVIRONMENT)
|
||||
local
|
||||
l_logger: LOGGER
|
||||
l_logger: separate LOGGER
|
||||
do
|
||||
create l_logger.make_with_environment (app)
|
||||
set_logger_to (l_logger, logger_cell)
|
||||
|
||||
@@ -25,15 +25,13 @@ create
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_title: detachable like title; a_location: like location)
|
||||
make (a_title: detachable READABLE_STRING_GENERAL; a_location: like location)
|
||||
-- Create current local link with optional title `a_title' and location `a_location'.
|
||||
require
|
||||
is_valid_local_location_argument: not a_location.starts_with_general ("/")
|
||||
do
|
||||
if a_title /= Void then
|
||||
title := a_title
|
||||
else
|
||||
title := a_location
|
||||
end
|
||||
location := a_location
|
||||
set_title (a_title)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
@@ -75,6 +73,16 @@ feature -- Status report
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_title (a_title: detachable READABLE_STRING_GENERAL)
|
||||
-- Set `title' to `a_title' or `location'.
|
||||
do
|
||||
if a_title /= Void then
|
||||
title := a_title.as_string_32
|
||||
else
|
||||
title := location.as_string_32
|
||||
end
|
||||
end
|
||||
|
||||
add_link (lnk: CMS_LINK)
|
||||
-- <Precursor>
|
||||
local
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
note
|
||||
description: "Summary description for {CMS_STORAGE_STORE_SQL}."
|
||||
author: ""
|
||||
description: "Storage based on Eiffel Store component."
|
||||
date: "$Date: 2015-02-13 13:08:13 +0100 (ven., 13 févr. 2015) $"
|
||||
revision: "$Revision: 96616 $"
|
||||
|
||||
@@ -8,9 +7,7 @@ deferred class
|
||||
CMS_STORAGE_STORE_SQL
|
||||
|
||||
inherit
|
||||
CMS_STORAGE
|
||||
|
||||
CMS_STORAGE_SQL_I
|
||||
CMS_STORAGE_SQL
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
@@ -25,7 +22,6 @@ feature {NONE} -- Initialization
|
||||
create {DATABASE_HANDLER_IMPL} db_handler.make (a_connection)
|
||||
|
||||
create error_handler.make
|
||||
-- error_handler.add_synchronization (db_handler.database_error_handler)
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
@@ -36,6 +32,15 @@ feature -- Status report
|
||||
Result := connection.is_connected
|
||||
end
|
||||
|
||||
feature -- Basic operation
|
||||
|
||||
close
|
||||
-- <Precursor>
|
||||
-- Disconnect from SQL database.
|
||||
do
|
||||
connection.disconnect
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
db_handler: DATABASE_HANDLER
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
note
|
||||
description: "[
|
||||
Common ancestor for builders responsible to instantiate storage based
|
||||
on Eiffel Store storage.
|
||||
]"
|
||||
author: "$Author: jfiat $"
|
||||
date: "$Date: 2015-02-13 13:08:13 +0100 (ven., 13 févr. 2015) $"
|
||||
revision: "$Revision: 96616 $"
|
||||
|
||||
deferred class
|
||||
CMS_STORAGE_STORE_SQL_BUILDER
|
||||
|
||||
inherit
|
||||
CMS_STORAGE_SQL_BUILDER
|
||||
|
||||
end
|
||||
@@ -1,6 +1,6 @@
|
||||
note
|
||||
description: "[
|
||||
Objects that ...
|
||||
Interface responsible to instantiate CMS_STORAGE_MYSQL object.
|
||||
]"
|
||||
author: "$Author: jfiat $"
|
||||
date: "$Date: 2015-01-27 19:15:02 +0100 (mar., 27 janv. 2015) $"
|
||||
@@ -10,7 +10,9 @@ class
|
||||
CMS_STORAGE_MYSQL_BUILDER
|
||||
|
||||
inherit
|
||||
CMS_STORAGE_SQL_BUILDER
|
||||
CMS_STORAGE_STORE_SQL_BUILDER
|
||||
|
||||
GLOBAL_SETTINGS
|
||||
|
||||
create
|
||||
make
|
||||
@@ -32,6 +34,12 @@ feature -- Factory
|
||||
create {DATABASE_CONNECTION_MYSQL} conn.login_with_connection_string (l_database_config.connection_string)
|
||||
if conn.is_connected then
|
||||
create Result.make (conn)
|
||||
set_map_zero_null_value (False) --| This way we map 0 to 0, instead of Null as default.
|
||||
if Result.is_available then
|
||||
if not Result.is_initialized then
|
||||
initialize (a_setup, Result)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
note
|
||||
description: "Summary description for {CMS_STORAGE_MYSQL}."
|
||||
description: "Summary description for {CMS_STORAGE_SQLITE}."
|
||||
date: "$Date: 2015-02-09 22:29:56 +0100 (lun., 09 févr. 2015) $"
|
||||
revision: "$Revision: 96596 $"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
note
|
||||
description: "[
|
||||
Objects that ...
|
||||
Interface responsible to instantiate CMS_STORAGE_SQLITE object.
|
||||
]"
|
||||
author: "$Author: jfiat $"
|
||||
date: "$Date: 2015-02-13 13:08:13 +0100 (ven., 13 févr. 2015) $"
|
||||
@@ -10,7 +10,9 @@ class
|
||||
CMS_STORAGE_SQLITE_BUILDER
|
||||
|
||||
inherit
|
||||
CMS_STORAGE_SQL_BUILDER
|
||||
CMS_STORAGE_STORE_SQL_BUILDER
|
||||
|
||||
GLOBAL_SETTINGS
|
||||
|
||||
create
|
||||
make
|
||||
@@ -27,50 +29,40 @@ feature -- Factory
|
||||
storage (a_setup: CMS_SETUP): detachable CMS_STORAGE_SQLITE
|
||||
local
|
||||
s: STRING
|
||||
conn: detachable DATABASE_CONNECTION
|
||||
do
|
||||
if attached (create {APPLICATION_JSON_CONFIGURATION_HELPER}).new_database_configuration (a_setup.environment.application_config_path) as l_database_config then
|
||||
if
|
||||
attached (create {APPLICATION_JSON_CONFIGURATION_HELPER}).new_database_configuration (a_setup.environment.application_config_path) as l_database_config
|
||||
then
|
||||
s := "Driver=SQLite3 ODBC Driver;Database="
|
||||
if attached l_database_config.database_name as db_name then
|
||||
s.append (db_name)
|
||||
end
|
||||
s.append (";LongNames=0;Timeout=1000;NoTXN=0;SyncPragma=NORMAL;StepAPI=0;")
|
||||
create Result.make (create {DATABASE_CONNECTION_ODBC}.login_with_connection_string (s))
|
||||
--create Result.make (create {DATABASE_CONNECTION_ODBC}.login_with_connection_string (l_database_config.connection_string))
|
||||
if Result.is_available then
|
||||
if not Result.is_initialized then
|
||||
initialize (a_setup, Result)
|
||||
if attached reuseable_connection.item as d then
|
||||
if s.same_string (d.name) then
|
||||
conn := d.connection
|
||||
end
|
||||
end
|
||||
if conn = Void or else not conn.is_connected then
|
||||
create {DATABASE_CONNECTION_ODBC} conn.login_with_connection_string (s)
|
||||
reuseable_connection.replace ([s, conn])
|
||||
end
|
||||
if conn.is_connected then
|
||||
create Result.make (conn)
|
||||
set_map_zero_null_value (False) --| This way we map 0 to 0, instead of Null as default.
|
||||
if Result.is_available then
|
||||
if not Result.is_initialized then
|
||||
initialize (a_setup, Result)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
initialize (a_setup: CMS_SETUP; a_storage: CMS_STORAGE_STORE_SQL)
|
||||
local
|
||||
u: CMS_USER
|
||||
r: CMS_USER_ROLE
|
||||
do
|
||||
-- Schema
|
||||
a_storage.sql_execute_file_script (a_setup.environment.path.extended ("scripts").extended ("core.sql"))
|
||||
|
||||
-- Data
|
||||
-- Users
|
||||
create u.make ("admin")
|
||||
u.set_password ("istrator#")
|
||||
u.set_email (a_setup.site_email)
|
||||
a_storage.new_user (u)
|
||||
|
||||
-- Roles
|
||||
create r.make ("anonymous")
|
||||
a_storage.save_user_role (r)
|
||||
create r.make ("authenticated")
|
||||
r.add_permission ("create page")
|
||||
r.add_permission ("edit page")
|
||||
a_storage.save_user_role (r)
|
||||
|
||||
-- Test custom value
|
||||
|
||||
a_storage.set_custom_value ("abc", "123", "test")
|
||||
a_storage.set_custom_value ("abc", "OK", "test")
|
||||
reuseable_connection: CELL [detachable TUPLE [name: STRING; connection: DATABASE_CONNECTION]]
|
||||
once
|
||||
create Result.put (Void)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -37,12 +37,11 @@ feature {NONE} -- Initialization
|
||||
|
||||
feature -- Access: router
|
||||
|
||||
router (a_api: CMS_API): WSF_ROUTER
|
||||
-- Node router.
|
||||
setup_router (a_router: WSF_ROUTER; a_api: CMS_API)
|
||||
-- <Precursor>
|
||||
do
|
||||
create Result.make (2)
|
||||
configure_api_login (a_api, Result)
|
||||
configure_api_logoff (a_api, Result)
|
||||
configure_api_login (a_api, a_router)
|
||||
configure_api_logoff (a_api, a_router)
|
||||
end
|
||||
|
||||
feature -- Access: filter
|
||||
@@ -110,9 +109,9 @@ feature -- Hooks
|
||||
lnk: CMS_LOCAL_LINK
|
||||
do
|
||||
if attached a_response.current_user (a_response.request) as u then
|
||||
create lnk.make (u.name + " (Logout)", "/basic_auth_logoff?destination=" + a_response.request.request_uri)
|
||||
create lnk.make (u.name + " (Logout)", "basic_auth_logoff?destination=" + a_response.request.request_uri)
|
||||
else
|
||||
create lnk.make ("Login", "/basic_auth_login?destination=" + a_response.request.request_uri)
|
||||
create lnk.make ("Login", "basic_auth_login?destination=" + a_response.request.request_uri)
|
||||
end
|
||||
-- if not a_menu_system.primary_menu.has (lnk) then
|
||||
lnk.set_weight (99)
|
||||
|
||||
@@ -25,8 +25,10 @@ feature -- Basic operations
|
||||
do
|
||||
api.logger.put_debug (generator + ".execute ", Void)
|
||||
create l_auth.make (req.http_authorization)
|
||||
if attached req.raw_header_data as l_raw_data then
|
||||
api.logger.put_debug (generator + ".execute " + l_raw_data, Void)
|
||||
debug
|
||||
if attached req.raw_header_data as l_raw_data then
|
||||
api.logger.put_debug (generator + ".execute " + (create {UTF_CONVERTER}).escaped_utf_32_string_to_utf_8_string_8 (l_raw_data), Void)
|
||||
end
|
||||
end
|
||||
-- A valid user
|
||||
if
|
||||
|
||||
@@ -16,20 +16,21 @@ inherit
|
||||
|
||||
REFACTORING_HELPER
|
||||
|
||||
create
|
||||
make
|
||||
create {NODE_MODULE}
|
||||
make_with_storage
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make_with_storage (a_api: CMS_API; a_node_storage: CMS_NODE_STORAGE_I)
|
||||
do
|
||||
node_storage := a_node_storage
|
||||
make (a_api)
|
||||
end
|
||||
|
||||
initialize
|
||||
-- <Precursor>
|
||||
do
|
||||
Precursor
|
||||
if attached {CMS_STORAGE_SQL_I} storage as l_storage_sql then
|
||||
create {CMS_NODE_STORAGE_SQL} node_storage.make (l_storage_sql)
|
||||
else
|
||||
create {CMS_NODE_STORAGE_NULL} node_storage.make
|
||||
end
|
||||
initialize_node_types
|
||||
end
|
||||
|
||||
@@ -170,30 +171,38 @@ feature -- URL
|
||||
-- or URI of path for selection of new content possibilities if ct is Void.
|
||||
do
|
||||
if ct /= Void then
|
||||
Result := "/node/add/" + ct.name
|
||||
Result := "node/add/" + ct.name
|
||||
else
|
||||
Result := "/node/"
|
||||
Result := "node/"
|
||||
end
|
||||
end
|
||||
|
||||
node_link (a_node: CMS_NODE): CMS_LOCAL_LINK
|
||||
-- CMS link for node `a_node'.
|
||||
require
|
||||
a_node.has_id
|
||||
do
|
||||
create Result.make (a_node.title, cms_api.path_alias (node_path (a_node)))
|
||||
end
|
||||
|
||||
node_path (a_node: CMS_NODE): STRING
|
||||
-- URI path for node `a_node'.
|
||||
-- using the /node/{nid} url.
|
||||
require
|
||||
a_node.has_id
|
||||
do
|
||||
Result := "/node/" + a_node.id.out
|
||||
Result := "node/" + a_node.id.out
|
||||
end
|
||||
|
||||
nodes_path: STRING
|
||||
-- URI path for list of nodes.
|
||||
do
|
||||
Result := "/nodes"
|
||||
Result := "nodes"
|
||||
end
|
||||
|
||||
feature -- Access: Node
|
||||
|
||||
nodes_count: INTEGER_64
|
||||
nodes_count: NATURAL_64
|
||||
do
|
||||
Result := node_storage.nodes_count
|
||||
end
|
||||
@@ -204,10 +213,17 @@ feature -- Access: Node
|
||||
Result := node_storage.nodes
|
||||
end
|
||||
|
||||
recent_nodes (a_offset, a_rows: INTEGER): LIST [CMS_NODE]
|
||||
trashed_nodes (a_user: CMS_USER): LIST [CMS_NODE]
|
||||
-- List of nodes with status in {CMS_NODE_API}.trashed.
|
||||
-- if the current user is admin, it will retrieve all the trashed nodes
|
||||
do
|
||||
Result := node_storage.trashed_nodes (a_user.id)
|
||||
end
|
||||
|
||||
recent_nodes (params: CMS_DATA_QUERY_PARAMETERS): ITERABLE [CMS_NODE]
|
||||
-- List of the `a_rows' most recent nodes starting from `a_offset'.
|
||||
do
|
||||
Result := node_storage.recent_nodes (a_offset, a_rows)
|
||||
Result := node_storage.recent_nodes (params.offset.to_integer_32, params.size.to_integer_32)
|
||||
end
|
||||
|
||||
node (a_id: INTEGER_64): detachable CMS_NODE
|
||||
@@ -234,6 +250,11 @@ feature -- Access: Node
|
||||
Result := a_node
|
||||
end
|
||||
|
||||
-- Update link with aliasing.
|
||||
if a_node /= Void and then a_node.has_id then
|
||||
a_node.set_link (node_link (a_node))
|
||||
end
|
||||
|
||||
-- Update partial user if needed.
|
||||
if
|
||||
Result /= Void and then
|
||||
@@ -249,6 +270,30 @@ feature -- Access: Node
|
||||
end
|
||||
end
|
||||
|
||||
is_author_of_node (u: CMS_USER; a_node: CMS_NODE): BOOLEAN
|
||||
-- Is the user `u' owner of the node `n'.
|
||||
do
|
||||
if attached node_storage.node_author (a_node.id) as l_author then
|
||||
Result := u.same_as (l_author)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Permission Scope: Node
|
||||
|
||||
has_permission_for_action_on_node (a_action: READABLE_STRING_8; a_node: CMS_NODE; a_user: detachable CMS_USER; ): BOOLEAN
|
||||
-- Has permission to execute action `a_action' on node `a_node', by eventual user `a_user'?
|
||||
local
|
||||
l_type_name: READABLE_STRING_8
|
||||
do
|
||||
l_type_name := a_node.content_type
|
||||
Result := cms_api.user_has_permission (a_user, a_action + " any " + l_type_name)
|
||||
if not Result and a_user /= Void then
|
||||
if is_author_of_node (a_user, a_node) then
|
||||
Result := cms_api.user_has_permission (a_user, a_action + " own " + l_type_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Change: Node
|
||||
|
||||
save_node (a_node: CMS_NODE)
|
||||
@@ -279,32 +324,31 @@ feature -- Change: Node
|
||||
node_storage.update_node (a_node)
|
||||
end
|
||||
|
||||
-- update_node_title (a_user_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_title: READABLE_STRING_32)
|
||||
-- -- Update node title, with user identified by `a_id', with node id `a_node_id' and a new title `a_title'.
|
||||
-- do
|
||||
-- debug ("refactor_fixme")
|
||||
-- fixme ("Check preconditions")
|
||||
-- end
|
||||
-- node_storage.update_node_title (a_user_id, a_node_id, a_title)
|
||||
-- end
|
||||
trash_node (a_node: CMS_NODE)
|
||||
-- Trash node `a_node'.
|
||||
--! remove the node from the storage.
|
||||
do
|
||||
node_storage.trash_node (a_node)
|
||||
end
|
||||
|
||||
-- update_node_summary (a_user_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_summary: READABLE_STRING_32)
|
||||
-- -- Update node summary, with user identified by `a_user_id', with node id `a_node_id' and a new summary `a_summary'.
|
||||
-- do
|
||||
-- debug ("refactor_fixme")
|
||||
-- fixme ("Check preconditions")
|
||||
-- end
|
||||
-- node_storage.update_node_summary (a_user_id, a_node_id, a_summary)
|
||||
-- end
|
||||
|
||||
-- update_node_content (a_user_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_content: READABLE_STRING_32)
|
||||
-- -- Update node content, with user identified by `a_user_id', with node id `a_node_id' and a new content `a_content'.
|
||||
-- do
|
||||
-- debug ("refactor_fixme")
|
||||
-- fixme ("Check preconditions")
|
||||
-- end
|
||||
-- node_storage.update_node_content (a_user_id, a_node_id, a_content)
|
||||
-- end
|
||||
restore_node (a_node: CMS_NODE)
|
||||
-- Restore node `a_node'.
|
||||
-- From {CMS_NODE_API}.trashed to {CMS_NODE_API}.not_published.
|
||||
do
|
||||
node_storage.restore_node (a_node)
|
||||
end
|
||||
|
||||
|
||||
feature -- Node status
|
||||
|
||||
Not_published: INTEGER = 0
|
||||
-- The node is not published.
|
||||
|
||||
Published: INTEGER = 1
|
||||
-- The node is published.
|
||||
|
||||
Trashed: INTEGER = -1
|
||||
-- The node is trashed (soft delete), ready to be deleted/destroyed from storage.
|
||||
|
||||
end
|
||||
|
||||
@@ -13,10 +13,6 @@ inherit
|
||||
|
||||
REFACTORING_HELPER
|
||||
|
||||
--create
|
||||
-- make,
|
||||
-- make_empty
|
||||
|
||||
feature{NONE} -- Initialization
|
||||
|
||||
make_empty
|
||||
@@ -35,10 +31,7 @@ feature{NONE} -- Initialization
|
||||
set_creation_date (l_time)
|
||||
set_modification_date (l_time)
|
||||
set_publication_date (l_time)
|
||||
|
||||
debug ("refactor_fixme")
|
||||
fixme ("Remove default harcoded format")
|
||||
end
|
||||
mark_not_published
|
||||
ensure
|
||||
title_set: title = a_title
|
||||
end
|
||||
@@ -60,6 +53,8 @@ feature -- Conversion
|
||||
a_node.summary,
|
||||
a_node.format
|
||||
)
|
||||
set_status (a_node.status)
|
||||
set_link (a_node.link)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
@@ -78,6 +73,12 @@ feature -- Access
|
||||
deferred
|
||||
end
|
||||
|
||||
status: INTEGER
|
||||
-- Associated status for the current node.
|
||||
-- default: {CMS_NODE_API}.Not_Published}
|
||||
-- {CMS_NODE_API}.Published
|
||||
-- {CMS_NODE_API}.Trashed
|
||||
|
||||
feature -- Access
|
||||
|
||||
title: READABLE_STRING_32
|
||||
@@ -142,6 +143,11 @@ feature -- status report
|
||||
Result := a_content_type.is_case_insensitive_equal (content_type)
|
||||
end
|
||||
|
||||
feature -- Access: menu
|
||||
|
||||
link: detachable CMS_LOCAL_LINK
|
||||
-- Associated menu link.
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_content (a_content: like content; a_summary: like summary; a_format: like format)
|
||||
@@ -158,6 +164,9 @@ feature -- Element change
|
||||
-- Assign `title' with `a_title'.
|
||||
do
|
||||
title := a_title
|
||||
if attached link as lnk then
|
||||
lnk.set_title (a_title)
|
||||
end
|
||||
ensure
|
||||
title_assigned: title = a_title
|
||||
end
|
||||
@@ -211,6 +220,48 @@ feature -- Element change
|
||||
auther_set: author = u
|
||||
end
|
||||
|
||||
set_link (a_link: like link)
|
||||
-- Set `link' to `a_link'.
|
||||
do
|
||||
link := a_link
|
||||
end
|
||||
|
||||
feature -- Status change
|
||||
|
||||
mark_not_published
|
||||
-- Set status to not_published.
|
||||
do
|
||||
set_status ({CMS_NODE_API}.not_published)
|
||||
ensure
|
||||
status_not_published: status = {CMS_NODE_API}.not_published
|
||||
end
|
||||
|
||||
mark_published
|
||||
-- Set status to published.
|
||||
do
|
||||
set_status ({CMS_NODE_API}.published)
|
||||
ensure
|
||||
status_published: status = {CMS_NODE_API}.published
|
||||
end
|
||||
|
||||
mark_trashed
|
||||
-- Set status to trashed.
|
||||
do
|
||||
set_status ({CMS_NODE_API}.trashed)
|
||||
ensure
|
||||
status_trash: status = {CMS_NODE_API}.trashed
|
||||
end
|
||||
|
||||
feature {CMS_NODE_STORAGE_I} -- Access: status change.
|
||||
|
||||
set_status (a_status: like status)
|
||||
-- Assign `status' with `a_status'.
|
||||
do
|
||||
status := a_status
|
||||
ensure
|
||||
status_set: status = a_status
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2015, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
|
||||
@@ -17,10 +17,11 @@ feature {NONE} -- Initialization
|
||||
default_create
|
||||
do
|
||||
Precursor
|
||||
create {ARRAYED_LIST [like available_formats.item]} available_formats.make (3)
|
||||
create {ARRAYED_LIST [like available_formats.item]} available_formats.make (4)
|
||||
available_formats.extend (create {PLAIN_TEXT_CONTENT_FORMAT})
|
||||
available_formats.extend (create {FILTERED_HTML_CONTENT_FORMAT})
|
||||
available_formats.extend (create {FULL_HTML_CONTENT_FORMAT})
|
||||
available_formats.extend (create {CMS_EDITOR_CONTENT_FORMAT})
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
@@ -9,16 +9,22 @@ deferred class
|
||||
inherit
|
||||
CMS_NODE_TYPE_WEBFORM_MANAGER_I [G]
|
||||
|
||||
SHARED_WSF_PERCENT_ENCODER
|
||||
|
||||
feature -- Forms ...
|
||||
|
||||
populate_form (response: NODE_RESPONSE; f: CMS_FORM; a_node: detachable CMS_NODE)
|
||||
local
|
||||
ti: WSF_FORM_TEXT_INPUT
|
||||
fset: WSF_FORM_FIELD_SET
|
||||
ta: WSF_FORM_TEXTAREA
|
||||
ta, sum: CMS_FORM_TEXTAREA
|
||||
tselect: WSF_FORM_SELECT
|
||||
opt: WSF_FORM_SELECT_OPTION
|
||||
cms_format: CMS_EDITOR_CONTENT_FORMAT
|
||||
l_uri: detachable READABLE_STRING_8
|
||||
do
|
||||
create cms_format
|
||||
|
||||
create ti.make ("title")
|
||||
ti.set_label ("Title")
|
||||
ti.set_size (70)
|
||||
@@ -30,25 +36,47 @@ feature -- Forms ...
|
||||
|
||||
f.extend_html_text ("<br/>")
|
||||
|
||||
create ta.make ("body")
|
||||
ta.set_rows (10)
|
||||
ta.set_cols (70)
|
||||
if a_node /= Void then
|
||||
ta.set_text_value (a_node.content)
|
||||
end
|
||||
-- ta.set_label ("Body")
|
||||
ta.set_description ("This is the main content")
|
||||
ta.set_is_required (False)
|
||||
|
||||
create fset.make
|
||||
fset.set_legend ("Body")
|
||||
fset.extend (ta)
|
||||
|
||||
fset.extend_html_text ("<br/>")
|
||||
|
||||
-- Select field has to be initialized before textareas are replaced, because they depend on the selection of the field
|
||||
create tselect.make ("format")
|
||||
tselect.set_label ("Body's format")
|
||||
tselect.set_is_required (True)
|
||||
|
||||
-- Main Content
|
||||
create ta.make ("body")
|
||||
ta.set_rows (10)
|
||||
ta.set_cols (70)
|
||||
ta.show_as_editor_if_selected (tselect, cms_format.name)
|
||||
if a_node /= Void then
|
||||
ta.set_text_value (a_node.content)
|
||||
end
|
||||
ta.set_label ("Content")
|
||||
ta.set_description ("This is the main content")
|
||||
ta.set_is_required (False)
|
||||
|
||||
-- Summary
|
||||
create sum.make ("summary")
|
||||
sum.set_rows (3)
|
||||
sum.set_cols (70)
|
||||
-- if cms_html is selected
|
||||
sum.show_as_editor_if_selected (tselect, cms_format.name)
|
||||
if a_node /= Void then
|
||||
sum.set_text_value (a_node.summary)
|
||||
end
|
||||
sum.set_label ("Summary")
|
||||
sum.set_description ("This is the summary")
|
||||
sum.set_is_required (False)
|
||||
|
||||
create fset.make
|
||||
fset.set_legend ("Body")
|
||||
|
||||
-- Add summary
|
||||
fset.extend (sum)
|
||||
fset.extend_html_text("<br />")
|
||||
|
||||
-- Add content (body)
|
||||
fset.extend (ta)
|
||||
fset.extend_html_text ("<br/>")
|
||||
|
||||
across
|
||||
content_type.available_formats as c
|
||||
loop
|
||||
@@ -65,11 +93,52 @@ feature -- Forms ...
|
||||
fset.extend (tselect)
|
||||
|
||||
f.extend (fset)
|
||||
|
||||
-- Path alias
|
||||
create ti.make ("path_alias")
|
||||
ti.set_label ("Path")
|
||||
ti.set_size (70)
|
||||
if a_node /= Void and then a_node.has_id then
|
||||
if attached a_node.link as lnk then
|
||||
l_uri := lnk.location
|
||||
else
|
||||
l_uri := percent_encoder.percent_decoded_string (response.api.path_alias (response.node_api.node_path (a_node)))
|
||||
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_validation_action (agent (fd: WSF_FORM_DATA; a_response: CMS_RESPONSE)
|
||||
do
|
||||
if
|
||||
attached fd.string_item ("path_alias") as f_path_alias
|
||||
then
|
||||
if a_response.api.is_valid_path_alias (f_path_alias) then
|
||||
-- Ok.
|
||||
elseif f_path_alias.is_empty then
|
||||
-- Ok
|
||||
elseif f_path_alias.starts_with_general ("/") then
|
||||
fd.report_invalid_field ("path_alias", "Path alias should not start with a slash '/' .")
|
||||
elseif f_path_alias.has_substring ("://") then
|
||||
fd.report_invalid_field ("path_alias", "Path alias should not be absolute url .")
|
||||
else
|
||||
-- TODO: implement full path alias validation
|
||||
end
|
||||
end
|
||||
end(?, response)
|
||||
)
|
||||
end
|
||||
if
|
||||
attached f.fields_by_name ("title") as l_title_fields and then
|
||||
attached l_title_fields.first as l_title_field
|
||||
then
|
||||
f.insert_after (ti, l_title_field)
|
||||
else
|
||||
f.extend (ti)
|
||||
end
|
||||
end
|
||||
|
||||
update_node (response: NODE_RESPONSE; fd: WSF_FORM_DATA; a_node: CMS_NODE)
|
||||
local
|
||||
b: detachable READABLE_STRING_8
|
||||
b,s: detachable READABLE_STRING_8
|
||||
f: detachable CONTENT_FORMAT
|
||||
do
|
||||
if attached fd.integer_item ("id") as l_id and then l_id > 0 then
|
||||
@@ -82,6 +151,12 @@ feature -- Forms ...
|
||||
if attached fd.string_item ("body") as l_body then
|
||||
b := l_body
|
||||
end
|
||||
|
||||
-- Read out the summary field from the form data
|
||||
if attached fd.string_item ("summary") as l_summary then
|
||||
s := l_summary
|
||||
end
|
||||
|
||||
if attached fd.string_item ("format") as s_format and then attached response.api.format (s_format) as f_format then
|
||||
f := f_format
|
||||
elseif a_node /= Void and then attached a_node.format as s_format and then attached response.api.format (s_format) as f_format then
|
||||
@@ -89,15 +164,19 @@ feature -- Forms ...
|
||||
else
|
||||
f := response.formats.default_format
|
||||
end
|
||||
|
||||
-- Update node with summary and body content
|
||||
if b /= Void then
|
||||
a_node.set_content (b, Void, f.name) -- FIXME: summary
|
||||
a_node.set_content (b, s, f.name)
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
new_node (response: NODE_RESPONSE; fd: WSF_FORM_DATA; a_node: detachable CMS_NODE): G
|
||||
-- <Precursor>
|
||||
local
|
||||
b: detachable READABLE_STRING_8
|
||||
b,s: detachable READABLE_STRING_8
|
||||
f: detachable CONTENT_FORMAT
|
||||
l_node: detachable like new_node
|
||||
do
|
||||
@@ -131,9 +210,16 @@ feature -- Forms ...
|
||||
end
|
||||
l_node.set_author (response.user)
|
||||
|
||||
--Summary
|
||||
if attached fd.string_item ("summary") as l_summary then
|
||||
s := l_summary
|
||||
end
|
||||
|
||||
--Content
|
||||
if attached fd.string_item ("body") as l_body then
|
||||
b := l_body
|
||||
end
|
||||
|
||||
if attached fd.string_item ("format") as s_format and then attached response.api.format (s_format) as f_format then
|
||||
f := f_format
|
||||
elseif a_node /= Void and then attached a_node.format as s_format and then attached response.api.format (s_format) as f_format then
|
||||
@@ -141,8 +227,10 @@ feature -- Forms ...
|
||||
else
|
||||
f := response.formats.default_format
|
||||
end
|
||||
|
||||
-- Update node with summary and content
|
||||
if b /= Void then
|
||||
l_node.set_content (b, Void, f.name)
|
||||
l_node.set_content (b, s, f.name)
|
||||
end
|
||||
Result := l_node
|
||||
end
|
||||
@@ -160,12 +248,31 @@ feature -- Output
|
||||
node_api := a_response.node_api
|
||||
|
||||
a_response.add_variable (a_node, "node")
|
||||
create lnk.make ("View", node_api.node_path (a_node))
|
||||
lnk := a_response.node_local_link (a_node, a_response.translation ("View", Void))
|
||||
lnk.set_weight (1)
|
||||
a_response.add_to_primary_tabs (lnk)
|
||||
create lnk.make ("Edit", node_api.node_path (a_node) + "/edit")
|
||||
lnk.set_weight (2)
|
||||
a_response.add_to_primary_tabs (lnk)
|
||||
|
||||
if a_node.status = {CMS_NODE_API}.trashed then
|
||||
create lnk.make ("Trash", node_api.node_path (a_node) + "/trash")
|
||||
lnk.set_weight (2)
|
||||
a_response.add_to_primary_tabs (lnk)
|
||||
else
|
||||
-- Node in {{CMS_NODE_API}.published} or {CMS_NODE_API}.not_published} status.
|
||||
create lnk.make ("Edit", node_api.node_path (a_node) + "/edit")
|
||||
lnk.set_weight (2)
|
||||
a_response.add_to_primary_tabs (lnk)
|
||||
|
||||
if
|
||||
a_node /= Void and then
|
||||
a_node.id > 0 and then
|
||||
attached node_api.node_type_for (a_node) as l_type and then
|
||||
node_api.has_permission_for_action_on_node ("delete", a_node, a_response.current_user (a_response.request))
|
||||
then
|
||||
create lnk.make ("Delete", node_api.node_path (a_node) + "/delete")
|
||||
lnk.set_weight (3)
|
||||
a_response.add_to_primary_tabs (lnk)
|
||||
end
|
||||
end
|
||||
|
||||
create s.make_empty
|
||||
s.append ("<div class=%"info%"> ")
|
||||
@@ -180,6 +287,23 @@ feature -- Output
|
||||
s.append (")")
|
||||
end
|
||||
s.append ("</div>")
|
||||
|
||||
|
||||
-- We don't show the summary on the detail page, since its just a short view of the full content. Otherwise we would write the same thing twice.
|
||||
-- The usage of the summary is to give a short overview in the list of nodes or for the meta tag "description"
|
||||
|
||||
-- if attached a_node.summary as l_summary then
|
||||
-- s.append ("<p class=%"summary%">")
|
||||
-- if attached node_api.cms_api.format (a_node.format) as f then
|
||||
-- s.append (f.formatted_output (l_summary))
|
||||
-- else
|
||||
-- s.append (a_response.formats.default_format.formatted_output (l_summary))
|
||||
-- end
|
||||
|
||||
-- s.append ("</p>")
|
||||
|
||||
-- end
|
||||
|
||||
if attached a_node.content as l_content then
|
||||
s.append ("<p class=%"content%">")
|
||||
if attached node_api.cms_api.format (a_node.format) as f then
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
note
|
||||
description: "Summary description for {CMS_PAGE_NODE_TYPE_WEBFORM_MANAGER}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ feature {NONE} -- Initialization
|
||||
initialize
|
||||
do
|
||||
Precursor
|
||||
create {WSF_CMS_THEME} wsf_theme.make (Current, theme)
|
||||
create {CMS_TO_WSF_THEME} wsf_theme.make (Current, theme)
|
||||
end
|
||||
|
||||
wsf_theme: WSF_THEME
|
||||
@@ -37,7 +37,7 @@ feature -- Execution
|
||||
-- Computed response message.
|
||||
local
|
||||
b: STRING_8
|
||||
f: like edit_form
|
||||
f: like new_edit_form
|
||||
fd: detachable WSF_FORM_DATA
|
||||
nid: INTEGER_64
|
||||
do
|
||||
@@ -48,43 +48,96 @@ feature -- Execution
|
||||
attached node_api.node (nid) as l_node
|
||||
then
|
||||
if attached node_api.node_type_for (l_node) as l_type then
|
||||
if has_permission ("edit " + l_type.name) then
|
||||
f := edit_form (l_node, url (request.path_info, Void), "edit-" + l_type.name, l_type)
|
||||
fixme ("refactor: process_edit, process_create porcess edit")
|
||||
if
|
||||
request.path_info.ends_with_general ("/edit") and then
|
||||
node_api.has_permission_for_action_on_node ("edit", l_node, current_user (request))
|
||||
then
|
||||
f := new_edit_form (l_node, url (request.path_info, Void), "edit-" + l_type.name, l_type)
|
||||
invoke_form_alter (f, fd)
|
||||
if request.is_post_request_method then
|
||||
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
|
||||
if l_node.has_id then
|
||||
add_to_menu (node_local_link (l_node, translation ("View", Void)), primary_tabs)
|
||||
add_to_menu (create {CMS_LOCAL_LINK}.make (translation ("Edit", Void), node_api.node_path (l_node) + "/edit"), primary_tabs)
|
||||
add_to_menu (create {CMS_LOCAL_LINK}.make ("Delete", node_api.node_path (l_node) + "/delete"), primary_tabs)
|
||||
end
|
||||
|
||||
if attached redirection as l_location then
|
||||
-- FIXME: Hack for now
|
||||
set_title (l_node.title)
|
||||
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)
|
||||
|
||||
b.append (html_encoded (l_type.title) + " saved")
|
||||
else
|
||||
set_title ("Edit " + html_encoded (l_type.title) + " #" + l_node.id.out)
|
||||
set_title (formatted_string (translation ("Edit $1 #$2", Void), [l_type.title, l_node.id]))
|
||||
f.append_to_html (wsf_theme, b)
|
||||
end
|
||||
elseif
|
||||
request.path_info.ends_with_general ("/delete") and then
|
||||
node_api.has_permission_for_action_on_node ("delete", l_node, current_user (request))
|
||||
then
|
||||
f := new_delete_form (l_node, url (request.path_info, Void), "delete-" + l_type.name, l_type)
|
||||
invoke_form_alter (f, fd)
|
||||
if request.is_post_request_method then
|
||||
f.process (Current)
|
||||
fd := f.last_data
|
||||
end
|
||||
if l_node.has_id then
|
||||
add_to_menu (node_local_link (l_node, translation ("View", Void)), primary_tabs)
|
||||
add_to_menu (create {CMS_LOCAL_LINK}.make (translation ("Edit", Void), node_api.node_path (l_node) + "/edit"), primary_tabs)
|
||||
add_to_menu (create {CMS_LOCAL_LINK}.make ("Delete", node_api.node_path (l_node) + "/delete"), primary_tabs)
|
||||
end
|
||||
|
||||
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 attached redirection as l_location then
|
||||
-- FIXME: Hack for now
|
||||
set_title (l_node.title)
|
||||
b.append (html_encoded (l_type.title) + " deleted")
|
||||
else
|
||||
set_title (formatted_string (translation ("Delete $1 #$2", Void), [l_type.title, l_node.id]))
|
||||
f.append_to_html (wsf_theme, b)
|
||||
end
|
||||
elseif
|
||||
request.path_info.ends_with_general ("/trash") and then
|
||||
node_api.has_permission_for_action_on_node ("trash", l_node, current_user (request))
|
||||
then
|
||||
f := new_trash_form (l_node, url (request.path_info, Void), "trash-" + l_type.name, l_type)
|
||||
invoke_form_alter (f, fd)
|
||||
if request.is_post_request_method then
|
||||
f.process (Current)
|
||||
fd := f.last_data
|
||||
end
|
||||
if l_node.has_id then
|
||||
add_to_menu (node_local_link (l_node, translation ("View", Void)), primary_tabs)
|
||||
add_to_menu (create {CMS_LOCAL_LINK}.make ("Trash", node_api.node_path (l_node) + "/Trash"), primary_tabs)
|
||||
end
|
||||
|
||||
if attached redirection as l_location then
|
||||
-- FIXME: Hack for now
|
||||
set_title (l_node.title)
|
||||
b.append (html_encoded (l_type.title) + " trashed")
|
||||
else
|
||||
set_title (formatted_string (translation ("Trash $1 #$2", Void), [l_type.title, l_node.id]))
|
||||
f.append_to_html (wsf_theme, b)
|
||||
end
|
||||
else
|
||||
b.append ("<h1>Access denied</h1>")
|
||||
b.append ("<h1>")
|
||||
b.append (translation ("Access denied", Void))
|
||||
b.append ("</h1>")
|
||||
end
|
||||
else
|
||||
set_title ("Unknown node")
|
||||
set_title (translation ("Unknown node", Void))
|
||||
end
|
||||
elseif
|
||||
attached {WSF_STRING} request.path_parameter ("type") as p_type and then
|
||||
attached node_api.node_type (p_type.value) as l_type
|
||||
then
|
||||
if has_permission ("create " + l_type.name) then
|
||||
if has_permissions (<<"create any", "create " + l_type.name>>) then
|
||||
if attached l_type.new_node (Void) as l_node then
|
||||
f := edit_form (l_node, url (request.path_info, Void), "edit-" + l_type.name, l_type)
|
||||
f := new_edit_form (l_node, url (request.path_info, Void), "edit-" + l_type.name, l_type)
|
||||
invoke_form_alter (f, fd)
|
||||
if request.is_post_request_method then
|
||||
f.validation_actions.extend (agent edit_form_validate (?, b))
|
||||
f.submit_actions.extend (agent edit_form_submit (?, l_node, l_type, b))
|
||||
@@ -94,27 +147,33 @@ feature -- Execution
|
||||
|
||||
set_title ("Edit " + html_encoded (l_type.title) + " #" + l_node.id.out)
|
||||
|
||||
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 l_node.has_id then
|
||||
add_to_menu (node_local_link (l_node, translation ("View", Void)), primary_tabs)
|
||||
add_to_menu (create {CMS_LOCAL_LINK}.make (translation ("Edit", Void), node_api.node_path (l_node) + "/edit"), primary_tabs)
|
||||
end
|
||||
|
||||
f.append_to_html (wsf_theme, b)
|
||||
else
|
||||
b.append ("<h1>Server error</h1>")
|
||||
b.append ("<h1>")
|
||||
b.append (translation ("Server error", Void))
|
||||
b.append ("</h1>")
|
||||
end
|
||||
else
|
||||
b.append ("<h1>Access denied</h1>")
|
||||
b.append ("<h1>")
|
||||
b.append (translation ("Access denied", Void))
|
||||
b.append ("</h1>")
|
||||
end
|
||||
else
|
||||
set_title ("Create new content ...")
|
||||
set_title (translation ("Create new content ...", Void))
|
||||
b.append ("<ul id=%"content-types%">")
|
||||
across
|
||||
node_api.node_types as ic
|
||||
loop
|
||||
if
|
||||
attached ic.item as l_node_type and then
|
||||
(has_permission ("create any") or has_permission ("create " + l_node_type.name))
|
||||
has_permissions (<<"create any", "create " + l_node_type.name>>)
|
||||
then
|
||||
b.append ("<li>" + link (l_node_type.name, "/node/add/" + l_node_type.name, Void))
|
||||
b.append ("<li>" + link (l_node_type.name, "node/add/" + l_node_type.name, Void))
|
||||
if attached l_node_type.description as d then
|
||||
b.append ("<div class=%"description%">" + d + "</div>")
|
||||
end
|
||||
@@ -160,6 +219,7 @@ feature -- Form
|
||||
l_preview: BOOLEAN
|
||||
l_node: detachable CMS_NODE
|
||||
s: STRING
|
||||
l_path_alias: detachable READABLE_STRING_8
|
||||
do
|
||||
l_preview := attached {WSF_STRING} fd.item ("op") as l_op and then l_op.same_string ("Preview")
|
||||
if not l_preview then
|
||||
@@ -191,16 +251,34 @@ feature -- Form
|
||||
end
|
||||
node_api.save_node (l_node)
|
||||
if attached current_user (request) as u then
|
||||
api.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))
|
||||
api.log ("node",
|
||||
"User %"" + user_html_link (u) + "%" " + s + " node " + node_html_link (l_node, a_type.name + " #" + l_node.id.out),
|
||||
0, node_local_link (l_node, Void)
|
||||
)
|
||||
else
|
||||
api.log ("node", "Anonymous " + s + " node " + a_type.name +" #" + l_node.id.out, 0, node_local_link (l_node))
|
||||
api.log ("node", "Anonymous " + s + " node " + a_type.name +" #" + l_node.id.out, 0, node_local_link (l_node, Void))
|
||||
end
|
||||
add_success_message ("Node #" + l_node.id.out + " saved.")
|
||||
set_redirection (node_url (l_node))
|
||||
|
||||
if
|
||||
attached fd.string_item ("path_alias") as f_path_alias and then
|
||||
not f_path_alias.is_empty
|
||||
then
|
||||
l_path_alias := percent_encoder.partial_encoded_string (f_path_alias, <<'/'>>)
|
||||
-- Path alias, are always from the root of the cms.
|
||||
api.set_path_alias (node_api.node_path (l_node), l_path_alias, False)
|
||||
l_node.set_link (create {CMS_LOCAL_LINK}.make (l_node.title, l_path_alias))
|
||||
else
|
||||
l_node.set_link (node_api.node_link (l_node))
|
||||
end
|
||||
if attached l_node.link as lnk then
|
||||
set_redirection (lnk.location)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
edit_form (a_node: detachable CMS_NODE; a_url: READABLE_STRING_8; a_name: STRING; a_type: CMS_NODE_TYPE [CMS_NODE]): CMS_FORM
|
||||
new_edit_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'.
|
||||
local
|
||||
f: CMS_FORM
|
||||
ts: WSF_FORM_SUBMIT_INPUT
|
||||
@@ -216,8 +294,7 @@ feature -- Form
|
||||
end
|
||||
f.extend (th)
|
||||
|
||||
fill_edit_form (a_type, f, a_node)
|
||||
|
||||
populate_form (a_node_type, f, a_node)
|
||||
f.extend_html_text ("<br/>")
|
||||
|
||||
create ts.make ("op")
|
||||
@@ -231,8 +308,87 @@ feature -- Form
|
||||
Result := f
|
||||
end
|
||||
|
||||
|
||||
new_delete_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'.
|
||||
local
|
||||
f: CMS_FORM
|
||||
ts: WSF_FORM_SUBMIT_INPUT
|
||||
do
|
||||
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>")
|
||||
|
||||
-- TODO check if we need to check for has_permissions!!
|
||||
if
|
||||
a_node /= Void and then
|
||||
a_node.id > 0
|
||||
then
|
||||
create ts.make ("op")
|
||||
ts.set_default_value ("Delete")
|
||||
fixme ("[
|
||||
ts.set_default_value (translation ("Delete"))
|
||||
]")
|
||||
f.extend (ts)
|
||||
fixme ("wsf_html: add support for HTML5 input attributes!!! ")
|
||||
f.extend_html_text("<input type='submit' value='Cancel' formmethod='GET', formaction='/node/"+a_node.id.out+"'>" )
|
||||
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'.
|
||||
local
|
||||
f: CMS_FORM
|
||||
ts: WSF_FORM_SUBMIT_INPUT
|
||||
do
|
||||
create f.make (a_url, a_name)
|
||||
|
||||
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
|
||||
create ts.make ("op")
|
||||
ts.set_default_value ("Trash")
|
||||
fixme ("[
|
||||
ts.set_default_value (translation ("Trash"))
|
||||
]")
|
||||
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")
|
||||
fixme ("[
|
||||
ts.set_default_value (translation ("Restore"))
|
||||
]")
|
||||
f.extend (ts)
|
||||
end
|
||||
Result := f
|
||||
end
|
||||
|
||||
|
||||
populate_form (a_content_type: CMS_NODE_TYPE [CMS_NODE]; a_form: WSF_FORM; a_node: detachable CMS_NODE)
|
||||
-- Fill the web form `a_form' with data from `a_node' if set,
|
||||
-- and apply this to content type `a_content_type'.
|
||||
do
|
||||
if attached node_api.node_type_webform_manager (a_content_type) as wf then
|
||||
wf.populate_form (Current, a_form, a_node)
|
||||
end
|
||||
end
|
||||
|
||||
new_node (a_content_type: CMS_NODE_TYPE [CMS_NODE]; a_form_data: WSF_FORM_DATA; a_node: detachable CMS_NODE): CMS_NODE
|
||||
--
|
||||
-- Node creation with form_data `a_form_data' for the given content type `a_content_type'
|
||||
-- using optional `a_node' to get extra node data.
|
||||
do
|
||||
if attached node_api.node_type_webform_manager (a_content_type) as wf then
|
||||
Result := wf.new_node (Current, a_form_data, a_node)
|
||||
@@ -249,11 +405,4 @@ feature -- Form
|
||||
end
|
||||
end
|
||||
|
||||
fill_edit_form (a_content_type: CMS_NODE_TYPE [CMS_NODE]; a_form: WSF_FORM; a_node: detachable CMS_NODE)
|
||||
do
|
||||
if attached node_api.node_type_webform_manager (a_content_type) as wf then
|
||||
wf.populate_form (Current, a_form, a_node)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -89,6 +89,14 @@ feature -- HTTP Methods
|
||||
check valid_url: req.path_info.starts_with_general ("/node/") end
|
||||
create edit_response.make (req, res, api, node_api)
|
||||
edit_response.execute
|
||||
elseif req.path_info.ends_with_general ("/delete") then
|
||||
check valid_url: req.path_info.starts_with_general ("/node/") end
|
||||
create edit_response.make (req, res, api, node_api)
|
||||
edit_response.execute
|
||||
elseif req.path_info.ends_with_general ("/trash") then
|
||||
check valid_url: req.path_info.starts_with_general ("/node/") end
|
||||
create edit_response.make (req, res, api, node_api)
|
||||
edit_response.execute
|
||||
else
|
||||
-- Display existing node
|
||||
l_nid := node_id_path_parameter (req)
|
||||
@@ -114,9 +122,29 @@ feature -- HTTP Methods
|
||||
local
|
||||
edit_response: NODE_FORM_RESPONSE
|
||||
do
|
||||
fixme ("Refactor code: extract methods: edit_node and add_node")
|
||||
if req.path_info.ends_with_general ("/edit") then
|
||||
create edit_response.make (req, res, api, node_api)
|
||||
edit_response.execute
|
||||
elseif req.path_info.ends_with_general ("/delete") then
|
||||
if
|
||||
attached {WSF_STRING} req.form_parameter ("op") as l_op and then
|
||||
l_op.value.same_string ("Delete")
|
||||
then
|
||||
do_delete (req, res)
|
||||
end
|
||||
elseif req.path_info.ends_with_general ("/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)
|
||||
elseif
|
||||
attached {WSF_STRING} req.form_parameter ("op") as l_op and then
|
||||
l_op.value.same_string ("Restore")
|
||||
then
|
||||
do_restore (req, res)
|
||||
end
|
||||
elseif req.path_info.starts_with_general ("/node/add/") then
|
||||
create edit_response.make (req, res, api, node_api)
|
||||
edit_response.execute
|
||||
@@ -142,11 +170,12 @@ feature -- HTTP Methods
|
||||
l_id.is_integer and then
|
||||
attached node_api.node (l_id.integer_value) as l_node
|
||||
then
|
||||
if api.user_has_permission (l_user, "delete " + l_node.content_type) then
|
||||
if node_api.has_permission_for_action_on_node ("delete", l_node, current_user (req)) then
|
||||
node_api.delete_node (l_node)
|
||||
res.send (create {CMS_REDIRECTION_RESPONSE_MESSAGE}.make (req.absolute_script_url ("")))
|
||||
else
|
||||
send_access_denied (req, res)
|
||||
-- send_not_authorized ?
|
||||
end
|
||||
else
|
||||
do_error (req, res, l_id)
|
||||
@@ -165,6 +194,62 @@ feature -- HTTP Methods
|
||||
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 from the database.
|
||||
do
|
||||
if attached current_user (req) as l_user then
|
||||
if attached {WSF_STRING} req.path_parameter ("id") as l_id then
|
||||
if
|
||||
l_id.is_integer and then
|
||||
attached node_api.node (l_id.integer_value) as l_node
|
||||
then
|
||||
if node_api.has_permission_for_action_on_node ("trash", l_node, current_user (req)) then
|
||||
node_api.trash_node (l_node)
|
||||
res.send (create {CMS_REDIRECTION_RESPONSE_MESSAGE}.make (req.absolute_script_url ("")))
|
||||
else
|
||||
send_access_denied (req, res)
|
||||
-- send_not_authorized ?
|
||||
end
|
||||
else
|
||||
do_error (req, res, l_id)
|
||||
end
|
||||
else
|
||||
(create {INTERNAL_SERVER_ERROR_CMS_RESPONSE}.make (req, res, api)).execute
|
||||
end
|
||||
else
|
||||
send_access_denied (req, res)
|
||||
end
|
||||
end
|
||||
|
||||
do_restore (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Restore a node: From {CMS_NODE_API}.trashed to {CMS_NODE_API}.not_published.
|
||||
do
|
||||
if attached current_user (req) as l_user then
|
||||
if attached {WSF_STRING} req.path_parameter ("id") as l_id then
|
||||
if
|
||||
l_id.is_integer and then
|
||||
attached node_api.node (l_id.integer_value) as l_node
|
||||
then
|
||||
if node_api.has_permission_for_action_on_node ("trash", l_node, current_user (req)) then
|
||||
node_api.restore_node (l_node)
|
||||
res.send (create {CMS_REDIRECTION_RESPONSE_MESSAGE}.make (req.absolute_script_url ("")))
|
||||
else
|
||||
send_access_denied (req, res)
|
||||
-- send_not_authorized ?
|
||||
end
|
||||
else
|
||||
do_error (req, res, l_id)
|
||||
end
|
||||
else
|
||||
(create {INTERNAL_SERVER_ERROR_CMS_RESPONSE}.make (req, res, api)).execute
|
||||
end
|
||||
else
|
||||
send_access_denied (req, res)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Error
|
||||
|
||||
do_error (req: WSF_REQUEST; res: WSF_RESPONSE; a_id: detachable WSF_STRING)
|
||||
|
||||
@@ -51,36 +51,63 @@ feature -- Helpers
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Helpers
|
||||
feature -- Helpers: cms link
|
||||
|
||||
user_local_link (u: CMS_USER): CMS_LINK
|
||||
user_local_link (u: CMS_USER; a_opt_title: detachable READABLE_STRING_GENERAL): CMS_LOCAL_LINK
|
||||
do
|
||||
create {CMS_LOCAL_LINK} Result.make (u.name, user_url (u))
|
||||
if a_opt_title /= Void then
|
||||
create Result.make (a_opt_title, user_url (u))
|
||||
else
|
||||
create Result.make (u.name, user_url (u))
|
||||
end
|
||||
end
|
||||
|
||||
node_local_link (n: CMS_NODE): CMS_LINK
|
||||
node_local_link (n: CMS_NODE; a_opt_title: detachable READABLE_STRING_GENERAL): CMS_LOCAL_LINK
|
||||
do
|
||||
create {CMS_LOCAL_LINK} Result.make (n.title, node_url (n))
|
||||
if attached n.link as lnk then
|
||||
Result := lnk
|
||||
else
|
||||
Result := node_api.node_link (n)
|
||||
end
|
||||
if a_opt_title /= Void and then not Result.title.same_string_general (a_opt_title) then
|
||||
create Result.make (a_opt_title, Result.location)
|
||||
end
|
||||
end
|
||||
|
||||
user_link (u: CMS_USER): like link
|
||||
feature -- Helpers: html link
|
||||
|
||||
user_html_link (u: CMS_USER): like link
|
||||
do
|
||||
Result := link (u.name, "/user/" + u.id.out, Void)
|
||||
Result := link (u.name, "user/" + u.id.out, Void)
|
||||
end
|
||||
|
||||
node_link (n: CMS_NODE): like link
|
||||
node_html_link (n: CMS_NODE; a_opt_title: detachable READABLE_STRING_GENERAL): like link
|
||||
local
|
||||
l_title: detachable READABLE_STRING_GENERAL
|
||||
do
|
||||
Result := link (n.title, "/node/" + n.id.out, Void)
|
||||
if a_opt_title /= Void then
|
||||
l_title := a_opt_title
|
||||
else
|
||||
l_title := n.title
|
||||
end
|
||||
Result := link (l_title, node_api.node_path (n), Void)
|
||||
|
||||
end
|
||||
|
||||
feature -- Helpers: URL
|
||||
|
||||
user_url (u: CMS_USER): like url
|
||||
require
|
||||
u_with_id: u.has_id
|
||||
do
|
||||
Result := url ("/user/" + u.id.out, Void)
|
||||
Result := url ("user/" + u.id.out, Void)
|
||||
end
|
||||
|
||||
node_url (n: CMS_NODE): like url
|
||||
require
|
||||
n_with_id: n.has_id
|
||||
do
|
||||
Result := url ("/node/" + n.id.out, Void)
|
||||
Result := url (node_api.node_link (n).location, Void)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -27,7 +27,7 @@ feature {NONE} -- Initialization
|
||||
initialize
|
||||
do
|
||||
Precursor
|
||||
create {WSF_CMS_THEME} wsf_theme.make (Current, theme)
|
||||
create {CMS_TO_WSF_THEME} wsf_theme.make (Current, theme)
|
||||
end
|
||||
|
||||
wsf_theme: WSF_THEME
|
||||
|
||||
@@ -37,36 +37,64 @@ feature -- HTTP Methods
|
||||
do_get (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- <Precursor>
|
||||
local
|
||||
l_page: CMS_RESPONSE
|
||||
l_response: CMS_RESPONSE
|
||||
s: STRING
|
||||
n: CMS_NODE
|
||||
lnk: CMS_LOCAL_LINK
|
||||
l_page_helper: CMS_PAGINATION_GENERATOR
|
||||
s_pager: STRING
|
||||
l_count: NATURAL_64
|
||||
do
|
||||
-- At the moment the template is hardcoded, but we can
|
||||
-- At the moment the template are hardcoded, but we can
|
||||
-- get them from the configuration file and load them into
|
||||
-- the setup class.
|
||||
|
||||
create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)
|
||||
l_page.add_variable (node_api.nodes, "nodes")
|
||||
l_count := node_api.nodes_count
|
||||
|
||||
create {GENERIC_VIEW_CMS_RESPONSE} l_response.make (req, res, api)
|
||||
|
||||
-- NOTE: for development purposes we have the following hardcode output.
|
||||
create s.make_from_string ("<p>Nodes:</p>")
|
||||
if attached node_api.nodes as lst then
|
||||
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")
|
||||
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
|
||||
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)
|
||||
if l_page_helper.page_size > 25 then
|
||||
s.append (s_pager)
|
||||
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
|
||||
s.append ("<ul class=%"cms-nodes%">%N")
|
||||
across
|
||||
lst as ic
|
||||
loop
|
||||
n := ic.item
|
||||
lnk := node_api.node_link (n)
|
||||
s.append ("<li class=%"cms_type_"+ n.content_type +"%">")
|
||||
s.append (l_page.link (n.title + " (#" + n.id.out + ")", node_api.node_path (n), Void))
|
||||
s.append (l_response.link (lnk.title, lnk.location, Void))
|
||||
debug
|
||||
if attached node_api.content_type (n.content_type) as ct then
|
||||
s.append ("<span class=%"description%">")
|
||||
s.append (html_encoded (ct.title))
|
||||
s.append ("</span>")
|
||||
end
|
||||
end
|
||||
s.append ("</li>%N")
|
||||
end
|
||||
s.append ("</ul>%N")
|
||||
end
|
||||
-- Again the pager at the bottom, if needed
|
||||
s.append (s_pager)
|
||||
|
||||
l_page.set_main_content (s)
|
||||
l_page.add_block (create {CMS_CONTENT_BLOCK}.make ("nodes_warning", Void, "/nodes/ is not yet fully implemented<br/>", Void), "highlighted")
|
||||
l_page.execute
|
||||
l_response.set_main_content (s)
|
||||
l_response.execute
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
80
modules/node/handler/trash_handler.e
Normal file
80
modules/node/handler/trash_handler.e
Normal file
@@ -0,0 +1,80 @@
|
||||
note
|
||||
description: "Request handler related to /trash "
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
TRASH_HANDLER
|
||||
|
||||
|
||||
inherit
|
||||
CMS_NODE_HANDLER
|
||||
|
||||
WSF_URI_HANDLER
|
||||
rename
|
||||
new_mapping as new_uri_mapping
|
||||
end
|
||||
|
||||
WSF_RESOURCE_HANDLER_HELPER
|
||||
redefine
|
||||
do_get
|
||||
end
|
||||
|
||||
REFACTORING_HELPER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- execute
|
||||
|
||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute request handler
|
||||
do
|
||||
execute_methods (req, res)
|
||||
end
|
||||
|
||||
feature -- HTTP Methods
|
||||
|
||||
do_get (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- <Precursor>
|
||||
local
|
||||
l_page: CMS_RESPONSE
|
||||
s: STRING
|
||||
n: CMS_NODE
|
||||
lnk: CMS_LOCAL_LINK
|
||||
do
|
||||
-- At the moment the template is hardcoded, but we can
|
||||
-- get them from the configuration file and load them into
|
||||
-- the setup class.
|
||||
|
||||
if attached current_user (req) as l_user then
|
||||
create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)
|
||||
|
||||
l_page.add_variable (node_api.trashed_nodes (l_user), "nodes")
|
||||
|
||||
-- NOTE: for development purposes we have the following hardcode output.
|
||||
create s.make_from_string ("<p>Nodes:</p>")
|
||||
if attached node_api.trashed_nodes (l_user) as lst then
|
||||
s.append ("<ul class=%"cms-nodes%">%N")
|
||||
across
|
||||
lst as ic
|
||||
loop
|
||||
n := ic.item
|
||||
lnk := node_api.node_link (n)
|
||||
s.append ("<li class=%"cms_type_"+ n.content_type +"%">")
|
||||
s.append (l_page.link (lnk.title, lnk.location, Void))
|
||||
s.append ("</li>%N")
|
||||
end
|
||||
s.append ("</ul>%N")
|
||||
end
|
||||
|
||||
l_page.set_main_content (s)
|
||||
-- l_page.add_block (create {CMS_CONTENT_BLOCK}.make ("nodes_warning", Void, "/nodes/ is not yet fully implemented<br/>", Void), "highlighted")
|
||||
l_page.execute
|
||||
else
|
||||
create {FORBIDDEN_ERROR_CMS_RESPONSE} l_page.make (req, res, api)
|
||||
l_page.execute
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -9,14 +9,12 @@ class
|
||||
inherit
|
||||
|
||||
CMS_MODULE
|
||||
rename
|
||||
module_api as node_api
|
||||
redefine
|
||||
register_hooks,
|
||||
initialize,
|
||||
is_installed,
|
||||
install,
|
||||
node_api
|
||||
module_api
|
||||
end
|
||||
|
||||
CMS_HOOK_MENU_SYSTEM_ALTER
|
||||
@@ -43,15 +41,26 @@ feature {NONE} -- Initialization
|
||||
|
||||
feature {CMS_API} -- Module Initialization
|
||||
|
||||
initialize (api: CMS_API)
|
||||
initialize (a_api: CMS_API)
|
||||
-- <Precursor>
|
||||
local
|
||||
p1,p2: CMS_PAGE
|
||||
ct: CMS_PAGE_NODE_TYPE
|
||||
l_node_api: like node_api
|
||||
l_node_storage: CMS_NODE_STORAGE_I
|
||||
do
|
||||
Precursor (api)
|
||||
create l_node_api.make (api)
|
||||
Precursor (a_api)
|
||||
|
||||
-- Storage initialization
|
||||
if attached {CMS_STORAGE_SQL_I} a_api.storage as l_storage_sql then
|
||||
create {CMS_NODE_STORAGE_SQL} l_node_storage.make (l_storage_sql)
|
||||
else
|
||||
-- FIXME: in case of NULL storage, should Current be disabled?
|
||||
create {CMS_NODE_STORAGE_NULL} l_node_storage.make
|
||||
end
|
||||
|
||||
-- Node API initialization
|
||||
create l_node_api.make_with_storage (a_api, l_node_storage)
|
||||
node_api := l_node_api
|
||||
|
||||
-- Add support for CMS_PAGE, which requires a storage extension to store the optional "parent" id.
|
||||
@@ -61,7 +70,7 @@ feature {CMS_API} -- Module Initialization
|
||||
|
||||
-- FIXME: the following code is mostly for test purpose/initialization, remove later
|
||||
if l_sql_node_storage.sql_table_items_count ("page_nodes") = 0 then
|
||||
if attached api.user_api.user_by_id (1) as u then
|
||||
if attached a_api.user_api.user_by_id (1) as u then
|
||||
create ct
|
||||
p1 := ct.new_node (Void)
|
||||
p1.set_title ("Welcome")
|
||||
@@ -81,46 +90,53 @@ feature {CMS_API} -- Module Initialization
|
||||
-- FIXME: maybe provide a default solution based on file system, when no SQL storage is available.
|
||||
-- IDEA: we could also have generic extension to node system, that handle generic addition field.
|
||||
end
|
||||
ensure then
|
||||
node_api_set: node_api /= Void
|
||||
end
|
||||
|
||||
feature {CMS_API} -- Module management
|
||||
|
||||
is_installed (api: CMS_API): BOOLEAN
|
||||
is_installed (a_api: CMS_API): BOOLEAN
|
||||
-- Is Current module installed?
|
||||
do
|
||||
if attached {CMS_STORAGE_SQL_I} api.storage as l_sql_storage then
|
||||
if attached {CMS_STORAGE_SQL_I} a_api.storage as l_sql_storage then
|
||||
Result := l_sql_storage.sql_table_exists ("nodes") and
|
||||
l_sql_storage.sql_table_exists ("page_nodes")
|
||||
end
|
||||
end
|
||||
|
||||
install (api: CMS_API)
|
||||
install (a_api: CMS_API)
|
||||
do
|
||||
-- Schema
|
||||
if attached {CMS_STORAGE_SQL_I} api.storage as l_sql_storage then
|
||||
l_sql_storage.sql_execute_file_script (api.setup.environment.path.extended ("scripts").extended (name).appended_with_extension ("sql"))
|
||||
if attached {CMS_STORAGE_SQL_I} a_api.storage as l_sql_storage then
|
||||
l_sql_storage.sql_execute_file_script (a_api.setup.environment.path.extended ("scripts").extended (name).appended_with_extension ("sql"))
|
||||
end
|
||||
end
|
||||
|
||||
feature {CMS_API} -- Access: API
|
||||
|
||||
module_api: detachable CMS_MODULE_API
|
||||
-- <Precursor>
|
||||
do
|
||||
if attached node_api as l_api then
|
||||
Result := l_api
|
||||
else
|
||||
-- Current is initialized, so node_api should be set.
|
||||
check has_node_api: False end
|
||||
end
|
||||
end
|
||||
|
||||
node_api: detachable CMS_NODE_API
|
||||
-- <Precursor>
|
||||
|
||||
feature -- Access: router
|
||||
|
||||
router (a_api: CMS_API): WSF_ROUTER
|
||||
-- Node router.
|
||||
local
|
||||
l_node_api: like node_api
|
||||
setup_router (a_router: WSF_ROUTER; a_api: CMS_API)
|
||||
-- <Precursor>
|
||||
do
|
||||
l_node_api := node_api
|
||||
if l_node_api = Void then
|
||||
create l_node_api.make (a_api)
|
||||
node_api := l_node_api
|
||||
if attached node_api as l_node_api then
|
||||
configure_web (a_api, l_node_api, a_router)
|
||||
end
|
||||
create Result.make (2)
|
||||
configure_web (a_api, l_node_api, Result)
|
||||
end
|
||||
|
||||
configure_web (a_api: CMS_API; a_node_api: CMS_NODE_API; a_router: WSF_ROUTER)
|
||||
@@ -128,6 +144,7 @@ feature -- Access: router
|
||||
l_node_handler: NODE_HANDLER
|
||||
l_nodes_handler: NODES_HANDLER
|
||||
l_uri_mapping: WSF_URI_MAPPING
|
||||
l_trash_handler: TRASH_HANDLER
|
||||
do
|
||||
-- TODO: for now, focused only on web interface, add REST api later. [2015-April-29]
|
||||
create l_node_handler.make (a_api, a_node_api)
|
||||
@@ -136,6 +153,8 @@ feature -- Access: router
|
||||
|
||||
a_router.handle_with_request_methods ("/node/add/{type}", l_node_handler, a_router.methods_get_post)
|
||||
a_router.handle_with_request_methods ("/node/{id}/edit", l_node_handler, a_router.methods_get_post)
|
||||
a_router.handle_with_request_methods ("/node/{id}/delete", l_node_handler, a_router.methods_get_post)
|
||||
a_router.handle_with_request_methods ("/node/{id}/trash", l_node_handler, a_router.methods_get_post)
|
||||
|
||||
a_router.handle_with_request_methods ("/node/{id}", l_node_handler, a_router.methods_get)
|
||||
-- For now: no REST API handling... a_router.methods_get_put_delete + a_router.methods_get_post)
|
||||
@@ -144,6 +163,13 @@ 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_with_request_methods (l_uri_mapping, a_router.methods_get)
|
||||
|
||||
--Trash
|
||||
|
||||
create l_trash_handler.make (a_api, a_node_api)
|
||||
create l_uri_mapping.make_trailing_slash_ignored ("/trash", l_trash_handler)
|
||||
a_router.map_with_request_methods (l_uri_mapping, a_router.methods_get)
|
||||
|
||||
end
|
||||
|
||||
feature -- Hooks
|
||||
@@ -174,10 +200,13 @@ feature -- Hooks
|
||||
lnk: CMS_LOCAL_LINK
|
||||
-- perms: detachable ARRAYED_LIST [READABLE_STRING_8]
|
||||
do
|
||||
create lnk.make ("List of nodes", a_response.url ("/nodes", Void))
|
||||
create lnk.make ("List of nodes", "nodes")
|
||||
a_menu_system.primary_menu.extend (lnk)
|
||||
|
||||
create lnk.make ("Create ..", a_response.url ("/node/", Void))
|
||||
create lnk.make ("Trash", "trash")
|
||||
a_menu_system.primary_menu.extend (lnk)
|
||||
|
||||
create lnk.make ("Create ..", "node")
|
||||
a_menu_system.primary_menu.extend (lnk)
|
||||
end
|
||||
|
||||
|
||||
@@ -43,6 +43,8 @@ feature {NONE} -- Implementation
|
||||
|
||||
extended_store (a_node: CMS_NODE)
|
||||
-- Store extended data from `a_node'.
|
||||
require
|
||||
not error_handler.has_error
|
||||
do
|
||||
if attached node_storage_extension (a_node) as ext then
|
||||
ext.store_node (a_node)
|
||||
@@ -51,16 +53,17 @@ feature {NONE} -- Implementation
|
||||
|
||||
extended_load (a_node: CMS_NODE)
|
||||
-- Load extended data into `a_node'.
|
||||
require
|
||||
not error_handler.has_error
|
||||
do
|
||||
if attached node_storage_extension (a_node) as ext then
|
||||
ext.load_node (a_node)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
feature -- Access
|
||||
|
||||
nodes_count: INTEGER_64
|
||||
nodes_count: NATURAL_64
|
||||
-- Count of nodes.
|
||||
deferred
|
||||
end
|
||||
@@ -70,6 +73,11 @@ feature -- Access
|
||||
deferred
|
||||
end
|
||||
|
||||
trashed_nodes (a_user_id: INTEGER_64): LIST [CMS_NODE]
|
||||
-- List of nodes by user `a_user_id'.
|
||||
deferred
|
||||
end
|
||||
|
||||
recent_nodes (a_lower: INTEGER; a_count: INTEGER): LIST [CMS_NODE]
|
||||
-- List of recent `a_count' nodes with an offset of `lower'.
|
||||
deferred
|
||||
@@ -107,6 +115,8 @@ feature -- Change: Node
|
||||
no_id: not a_node.has_id
|
||||
valid_user: attached a_node.author as l_author and then l_author.id > 0
|
||||
deferred
|
||||
ensure
|
||||
has_id: not error_handler.has_error implies a_node.has_id
|
||||
end
|
||||
|
||||
update_node (a_node: CMS_NODE)
|
||||
@@ -133,32 +143,35 @@ feature -- Change: Node
|
||||
deferred
|
||||
end
|
||||
|
||||
-- update_node_title (a_user_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_title: READABLE_STRING_32)
|
||||
-- -- Update node title to `a_title', node identified by id `a_node_id'.
|
||||
-- -- The user `a_user_id' is an existing or new collaborator.
|
||||
-- require
|
||||
-- valid_node_id: a_node_id > 0
|
||||
-- valid_user_id: a_user_id > 0
|
||||
-- deferred
|
||||
-- end
|
||||
trash_node (a_node: CMS_NODE)
|
||||
-- Trash `a_node'.
|
||||
do
|
||||
if a_node.has_id then
|
||||
trash_node_by_id (a_node.id)
|
||||
end
|
||||
end
|
||||
|
||||
-- update_node_summary (a_user_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_summary: READABLE_STRING_32)
|
||||
-- -- Update node summary to `a_summary', node identified by id `a_node_id'.
|
||||
-- -- The user `a_user_id' is an existing or new collaborator.
|
||||
-- require
|
||||
-- valid_id: a_node_id > 0
|
||||
-- valid_user_id: a_user_id > 0
|
||||
-- deferred
|
||||
-- end
|
||||
restore_node (a_node: CMS_NODE)
|
||||
-- Restore `a_node'.
|
||||
do
|
||||
if a_node.has_id then
|
||||
restore_node_by_id (a_node.id)
|
||||
end
|
||||
end
|
||||
|
||||
-- update_node_content (a_user_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_content: READABLE_STRING_32)
|
||||
-- -- Update node content to `a_content', node identified by id `a_node_id'.
|
||||
-- -- The user `a_user_id' is an existing or new collaborator.
|
||||
-- require
|
||||
-- valid_id: a_node_id > 0
|
||||
-- valid_user_id: a_user_id > 0
|
||||
-- deferred
|
||||
-- end
|
||||
trash_node_by_id (a_id: INTEGER_64)
|
||||
-- Trash node by id `a_id'.
|
||||
require
|
||||
valid_node_id: a_id > 0
|
||||
deferred
|
||||
end
|
||||
|
||||
restore_node_by_id (a_id: INTEGER_64)
|
||||
-- Restore node by id `a_id'.
|
||||
require
|
||||
valid_node_id: a_id > 0
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Helpers
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ feature -- Error Handling
|
||||
|
||||
feature -- Access: node
|
||||
|
||||
nodes_count: INTEGER_64
|
||||
nodes_count: NATURAL_64
|
||||
-- Count of nodes.
|
||||
do
|
||||
end
|
||||
@@ -41,6 +41,12 @@ feature -- Access: node
|
||||
create {ARRAYED_LIST [CMS_NODE]} Result.make (0)
|
||||
end
|
||||
|
||||
trashed_nodes (a_user_id: INTEGER_64): LIST [CMS_NODE]
|
||||
-- List of nodes by user `a_user_id'.
|
||||
do
|
||||
create {ARRAYED_LIST [CMS_NODE]} Result.make (0)
|
||||
end
|
||||
|
||||
recent_nodes (a_lower: INTEGER; a_count: INTEGER): LIST [CMS_NODE]
|
||||
-- List of the `a_count' most recent nodes, starting from `a_lower'.
|
||||
do
|
||||
@@ -80,6 +86,16 @@ feature -- Node
|
||||
do
|
||||
end
|
||||
|
||||
trash_node_by_id (a_id: INTEGER_64)
|
||||
-- <Precursor>
|
||||
do
|
||||
end
|
||||
|
||||
restore_node_by_id (a_id: INTEGER_64)
|
||||
-- <Precursor>
|
||||
do
|
||||
end
|
||||
|
||||
-- update_node_title (a_user_id: like {CMS_NODE}.id; a_node_id: like {CMS_NODE}.id; a_title: READABLE_STRING_32)
|
||||
-- -- <Precursor>
|
||||
-- do
|
||||
|
||||
@@ -22,17 +22,18 @@ create
|
||||
|
||||
feature -- Access
|
||||
|
||||
nodes_count: INTEGER_64
|
||||
nodes_count: NATURAL_64
|
||||
-- Number of items nodes.
|
||||
do
|
||||
error_handler.reset
|
||||
write_information_log (generator + ".nodes_count")
|
||||
sql_query (sql_select_nodes_count, Void)
|
||||
if sql_rows_count = 1 then
|
||||
Result := sql_read_integer_64 (1)
|
||||
Result := sql_read_natural_64 (1)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
nodes: LIST [CMS_NODE]
|
||||
-- List of nodes.
|
||||
do
|
||||
@@ -59,6 +60,36 @@ feature -- Access
|
||||
-- end
|
||||
end
|
||||
|
||||
trashed_nodes (a_user_id: INTEGER_64): LIST [CMS_NODE]
|
||||
-- List of nodes.
|
||||
local
|
||||
l_parameters: STRING_TABLE [detachable ANY]
|
||||
do
|
||||
create {ARRAYED_LIST [CMS_NODE]} Result.make (0)
|
||||
|
||||
error_handler.reset
|
||||
write_information_log (generator + ".trash_nodes")
|
||||
|
||||
from
|
||||
create l_parameters.make (1)
|
||||
if a_user_id > 1 then
|
||||
-- Not admin user
|
||||
l_parameters.put (a_user_id, "author")
|
||||
sql_query (sql_select_trash_nodes_by_author, l_parameters)
|
||||
else
|
||||
sql_query (sql_select_trash_nodes, Void)
|
||||
end
|
||||
sql_start
|
||||
until
|
||||
sql_after
|
||||
loop
|
||||
if attached fetch_node as l_node then
|
||||
Result.force (l_node)
|
||||
end
|
||||
sql_forth
|
||||
end
|
||||
end
|
||||
|
||||
recent_nodes (a_lower: INTEGER; a_count: INTEGER): LIST [CMS_NODE]
|
||||
-- List of recent `a_count' nodes with an offset of `lower'.
|
||||
local
|
||||
@@ -108,8 +139,8 @@ feature -- Access
|
||||
error_handler.reset
|
||||
write_information_log (generator + ".node_author")
|
||||
create l_parameters.make (1)
|
||||
l_parameters.put (a_id, "node_id")
|
||||
sql_query (select_node_author, l_parameters)
|
||||
l_parameters.put (a_id, "nid")
|
||||
sql_query (Select_user_author, l_parameters)
|
||||
if sql_rows_count >= 1 then
|
||||
Result := fetch_author
|
||||
end
|
||||
@@ -144,59 +175,52 @@ feature -- Change: Node
|
||||
-- Remove node by id `a_id'.
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
l_time: DATE_TIME
|
||||
do
|
||||
write_information_log (generator + ".delete_node")
|
||||
create l_time.make_now_utc
|
||||
write_information_log (generator + ".delete_node {" + a_id.out + "}")
|
||||
|
||||
error_handler.reset
|
||||
create l_parameters.make (1)
|
||||
l_parameters.put (l_time, "changed")
|
||||
l_parameters.put ({CMS_NODE_API}.trashed, "status")
|
||||
l_parameters.put (a_id, "nid")
|
||||
sql_change (sql_delete_node, l_parameters)
|
||||
end
|
||||
|
||||
-- update_node_title (a_user_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_title: READABLE_STRING_32)
|
||||
-- -- <Precursor>
|
||||
-- local
|
||||
-- l_parameters: STRING_TABLE [detachable ANY]
|
||||
-- do
|
||||
-- -- FIXME: unused a_user_id !
|
||||
-- error_handler.reset
|
||||
-- write_information_log (generator + ".update_node_title")
|
||||
-- create l_parameters.make (3)
|
||||
-- l_parameters.put (a_title, "title")
|
||||
-- l_parameters.put (create {DATE_TIME}.make_now_utc, "changed")
|
||||
-- l_parameters.put (a_node_id, "nid")
|
||||
-- sql_change (sql_update_node_title, l_parameters)
|
||||
-- end
|
||||
|
||||
-- update_node_summary (a_user_id: Like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_summary: READABLE_STRING_32)
|
||||
-- -- <Precursor>
|
||||
-- local
|
||||
-- l_parameters: STRING_TABLE [detachable ANY]
|
||||
-- do
|
||||
-- -- FIXME: unused a_user_id !
|
||||
-- error_handler.reset
|
||||
-- write_information_log (generator + ".update_node_summary")
|
||||
-- create l_parameters.make (3)
|
||||
-- l_parameters.put (a_summary, "summary")
|
||||
-- l_parameters.put (create {DATE_TIME}.make_now_utc, "changed")
|
||||
-- l_parameters.put (a_node_id, "nid")
|
||||
-- sql_change (sql_update_node_summary, l_parameters)
|
||||
-- end
|
||||
trash_node_by_id (a_id: INTEGER_64)
|
||||
-- <Precursor>
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
l_time: DATE_TIME
|
||||
do
|
||||
create l_time.make_now_utc
|
||||
write_information_log (generator + ".trash_node {" + a_id.out + "}")
|
||||
|
||||
error_handler.reset
|
||||
create l_parameters.make (1)
|
||||
l_parameters.put (a_id, "nid")
|
||||
sql_change (sql_trash_node, l_parameters)
|
||||
end
|
||||
|
||||
restore_node_by_id (a_id: INTEGER_64)
|
||||
-- <Precursor>
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
l_time: DATE_TIME
|
||||
do
|
||||
create l_time.make_now_utc
|
||||
write_information_log (generator + ".restore_node {" + a_id.out + "}")
|
||||
|
||||
error_handler.reset
|
||||
create l_parameters.make (1)
|
||||
l_parameters.put (l_time, "changed")
|
||||
l_parameters.put ({CMS_NODE_API}.not_published, "status")
|
||||
l_parameters.put (a_id, "nid")
|
||||
sql_change (sql_restore_node, l_parameters)
|
||||
end
|
||||
|
||||
-- update_node_content (a_user_id: Like {CMS_USER}.id;a_node_id: like {CMS_NODE}.id; a_content: READABLE_STRING_32)
|
||||
-- -- <Precursor>
|
||||
-- local
|
||||
-- l_parameters: STRING_TABLE [detachable ANY]
|
||||
-- do
|
||||
-- -- FIXME: unused a_user_id !
|
||||
-- error_handler.reset
|
||||
-- write_information_log (generator + ".update_node_content")
|
||||
-- create l_parameters.make (3)
|
||||
-- l_parameters.put (a_content, "content")
|
||||
-- l_parameters.put (create {DATE_TIME}.make_now_utc, "changed")
|
||||
-- l_parameters.put (a_node_id, "nid")
|
||||
-- sql_change (sql_update_node_content, l_parameters)
|
||||
-- end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
@@ -209,7 +233,7 @@ feature {NONE} -- Implementation
|
||||
error_handler.reset
|
||||
|
||||
write_information_log (generator + ".store_node")
|
||||
create l_parameters.make (8)
|
||||
create l_parameters.make (9)
|
||||
l_parameters.put (a_node.content_type, "type")
|
||||
l_parameters.put (a_node.title, "title")
|
||||
l_parameters.put (a_node.summary, "summary")
|
||||
@@ -217,6 +241,7 @@ feature {NONE} -- Implementation
|
||||
l_parameters.put (a_node.format, "format")
|
||||
l_parameters.put (a_node.publication_date, "publish")
|
||||
l_parameters.put (now, "changed")
|
||||
l_parameters.put (a_node.status, "status")
|
||||
if attached a_node.author as l_author then
|
||||
check valid_author: l_author.has_id end
|
||||
l_parameters.put (l_author.id, "author")
|
||||
@@ -243,8 +268,14 @@ feature {NONE} -- Implementation
|
||||
a_node.set_revision (1) -- New object.
|
||||
end
|
||||
end
|
||||
extended_store (a_node)
|
||||
sql_commit_transaction
|
||||
if not error_handler.has_error then
|
||||
extended_store (a_node)
|
||||
end
|
||||
if error_handler.has_error then
|
||||
sql_rollback_transaction
|
||||
else
|
||||
sql_commit_transaction
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Helpers
|
||||
@@ -260,24 +291,42 @@ feature -- Helpers
|
||||
|
||||
feature {NONE} -- Queries
|
||||
|
||||
sql_select_nodes_count: STRING = "SELECT count(*) from Nodes;"
|
||||
sql_select_nodes_count: STRING = "SELECT count(*) FROM Nodes WHERE status != -1 ;"
|
||||
-- Nodes count (Published and not Published)
|
||||
--| note: {CMS_NODE_API}.trashed = -1
|
||||
|
||||
sql_select_nodes: STRING = "SELECT * from Nodes;"
|
||||
sql_select_nodes: STRING = "SELECT * FROM Nodes WHERE status != -1 ;"
|
||||
-- SQL Query to retrieve all nodes.
|
||||
--| note: {CMS_NODE_API}.trashed = -1
|
||||
|
||||
sql_select_node_by_id: STRING = "SELECT nid, revision, type, title, summary, content, format, author, publish, created, changed FROM Nodes WHERE nid =:nid ORDER BY revision desc, publish desc LIMIT 1;"
|
||||
sql_select_trash_nodes: STRING = "SELECT * FROM Nodes WHERE status = -1 ;"
|
||||
-- SQL Query to retrieve all trahsed nodes.
|
||||
--| note: {CMS_NODE_API}.trashed = -1
|
||||
|
||||
sql_select_recent_nodes: STRING = "SELECT nid, revision, type, title, summary, content, format, author, publish, created, changed FROM Nodes ORDER BY nid desc, publish desc LIMIT :rows OFFSET :offset ;"
|
||||
sql_select_trash_nodes_by_author: STRING = "SELECT * FROM Nodes WHERE status = -1 and author = :author ;"
|
||||
-- SQL Query to retrieve all nodes by a given author.
|
||||
--| note: {CMS_NODE_API}.trashed = -1
|
||||
|
||||
sql_insert_node: STRING = "INSERT INTO nodes (revision, type, title, summary, content, format, publish, created, changed, author) VALUES (1, :type, :title, :summary, :content, :format, :publish, :created, :changed, :author);"
|
||||
sql_select_node_by_id: STRING = "SELECT nid, revision, type, title, summary, content, format, author, publish, created, changed, status FROM Nodes WHERE nid =:nid ORDER BY revision DESC, publish DESC LIMIT 1;"
|
||||
|
||||
sql_select_recent_nodes: STRING = "SELECT nid, revision, type, title, summary, content, format, author, publish, created, changed, status FROM Nodes ORDER BY nid DESC, publish DESC LIMIT :rows OFFSET :offset ;"
|
||||
|
||||
sql_insert_node: STRING = "INSERT INTO nodes (revision, type, title, summary, content, format, publish, created, changed, status, author) VALUES (1, :type, :title, :summary, :content, :format, :publish, :created, :changed, :status, :author);"
|
||||
-- SQL Insert to add a new node.
|
||||
|
||||
sql_update_node : STRING = "UPDATE nodes SET revision = revision, type=:type, title=:title, summary=:summary, content=:content, format=:format, publish=:publish, changed=:changed, author=:author WHERE nid=:nid;"
|
||||
sql_update_node : STRING = "UPDATE nodes SET revision = revision, type=:type, title=:title, summary=:summary, content=:content, format=:format, publish=:publish, changed=:changed, status=:status, author=:author WHERE nid=:nid;"
|
||||
-- FIXME: for now no revision inc.!
|
||||
-- sql_update_node : STRING = "UPDATE nodes SET revision = revision + 1, type=:type, title=:title, summary=:summary, content=:content, format=:format, publish=:publish, changed=:changed, revision = revision + 1, author=:author WHERE nid=:nid;"
|
||||
-- SQL node.
|
||||
|
||||
sql_delete_node: STRING = "DELETE FROM nodes WHERE nid=:nid;"
|
||||
sql_delete_node: STRING = "UPDATE nodes SET changed=:changed, status =:status WHERE nid=:nid"
|
||||
-- Soft deletion with free metadata.
|
||||
|
||||
sql_trash_node: STRING = "DELETE FROM nodes WHERE nid=:nid"
|
||||
-- Physical deletion with free metadata.
|
||||
|
||||
sql_restore_node: STRING = "UPDATE nodes SET changed=:changed, status =:status WHERE nid=:nid"
|
||||
-- Restore node to {CMS_NODE_API}.not_publised.
|
||||
|
||||
-- sql_update_node_author: STRING = "UPDATE nodes SET author=:author WHERE nid=:nid;"
|
||||
|
||||
@@ -294,7 +343,7 @@ feature {NONE} -- Queries
|
||||
|
||||
feature {NONE} -- Sql Queries: USER_ROLES collaborators, author
|
||||
|
||||
Select_user_author: STRING = "SELECT uid, name, password, salt, email, status, created, signed FROM Nodes INNER JOIN users ON nodes.author=users.uid AND users.uid = :uid;"
|
||||
Select_user_author: STRING = "SELECT uid, name, password, salt, email, users.status, users.created, signed FROM Nodes INNER JOIN users ON nodes.author=users.uid AND nodes.nid = :nid;"
|
||||
|
||||
Select_node_author: STRING = "SELECT nid, revision, type, title, summary, content, format, author, publish, created, changed FROM users INNER JOIN nodes ON nodes.author=users.uid AND nodes.nid =:nid;"
|
||||
|
||||
@@ -335,6 +384,9 @@ feature {NONE} -- Implementation
|
||||
if attached sql_read_date_time (11) as l_modif_date then
|
||||
Result.set_modification_date (l_modif_date)
|
||||
end
|
||||
if attached sql_read_integer_32 (12) as l_status then
|
||||
Result.set_status (l_status)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
31
package.iron
Normal file
31
package.iron
Normal file
@@ -0,0 +1,31 @@
|
||||
package ROC_cms
|
||||
|
||||
project
|
||||
cms = "cms-safe.ecf"
|
||||
cms = "cms.ecf"
|
||||
app_env = "library/app_env/app_env-safe.ecf"
|
||||
app_env = "library/app_env/app_env.ecf"
|
||||
config = "library/configuration/config-safe.ecf"
|
||||
config = "library/configuration/config.ecf"
|
||||
app_env = "library/layout/layout-safe.ecf"
|
||||
app_env = "library/layout/layout.ecf"
|
||||
cms_model = "library/model/cms_model-safe.ecf"
|
||||
cms_model = "library/model/cms_model.ecf"
|
||||
persistence_mysql = "library/persistence/mysql/persistence_mysql-safe.ecf"
|
||||
persistence_mysql = "library/persistence/mysql/persistence_mysql.ecf"
|
||||
persistence_sqlite = "library/persistence/sqlite/persistence_sqlite-safe.ecf"
|
||||
persistence_sqlite = "library/persistence/sqlite/persistence_sqlite.ecf"
|
||||
basic_auth = "modules/basic_auth/basic_auth-safe.ecf"
|
||||
basic_auth = "modules/basic_auth/basic_auth.ecf"
|
||||
node = "modules/node/node-safe.ecf"
|
||||
node = "modules/node/node.ecf"
|
||||
|
||||
note
|
||||
title: ROC CMS
|
||||
description: CMS written with Eiffel
|
||||
tags: cms, web, rest, api
|
||||
license: Eiffel Forum v2
|
||||
copyright: Jocelyn Fiat, Javier Velilla, Eiffel Software
|
||||
link[source]: "Github" https://github.com/EiffelWebFramework/ROC.git
|
||||
|
||||
end
|
||||
@@ -39,17 +39,21 @@ feature {NONE} -- Initialization
|
||||
end
|
||||
|
||||
configure
|
||||
local
|
||||
l_url: like site_url
|
||||
do
|
||||
--| Site id, used to identified a site, this could be set to a uuid, or else
|
||||
site_id := text_item_or_default ("site.id", "_EWF_CMS_NO_ID_")
|
||||
|
||||
-- Site url: optional, but ending with a slash
|
||||
site_url := string_8_item ("site_url")
|
||||
if attached site_url as l_url and then not l_url.is_empty then
|
||||
if l_url[l_url.count] /= '/' then
|
||||
site_url := l_url + "/"
|
||||
l_url := string_8_item ("site_url")
|
||||
if l_url /= Void and then not l_url.is_empty then
|
||||
if l_url [l_url.count] /= '/' then
|
||||
l_url := l_url + "/"
|
||||
end
|
||||
end
|
||||
site_url := l_url
|
||||
|
||||
-- Site name
|
||||
site_name := text_item_or_default ("site.name", "EWF::CMS")
|
||||
|
||||
@@ -84,7 +88,7 @@ feature {NONE} -- Initialization
|
||||
initialize_modules
|
||||
-- Intialize core modules.
|
||||
local
|
||||
m: CMS_MODULE
|
||||
-- m: CMS_MODULE
|
||||
do
|
||||
-- Core
|
||||
-- create {BASIC_AUTH_MODULE} m.make
|
||||
|
||||
@@ -62,7 +62,7 @@ feature -- Access: Site
|
||||
-- Mainly used for internal notification.
|
||||
|
||||
site_url: detachable READABLE_STRING_8
|
||||
-- Optional base url of the site.
|
||||
-- Optional url of current CMS site.
|
||||
|
||||
front_page_path: detachable READABLE_STRING_8
|
||||
-- Optional path defining the front page.
|
||||
|
||||
@@ -12,11 +12,12 @@ feature -- Factory
|
||||
template_block (a_module: CMS_MODULE; a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE): detachable CMS_SMARTY_TEMPLATE_BLOCK
|
||||
-- Smarty content block for `a_block_id' in the context of `a_module' and `a_response'.
|
||||
local
|
||||
res: PATH
|
||||
p: detachable PATH
|
||||
do
|
||||
create p.make_from_string ("templates")
|
||||
p := p.extended ("block_").appended (a_block_id).appended_with_extension ("tpl")
|
||||
p := a_response.module_resource_path (a_module, p)
|
||||
create res.make_from_string ("templates")
|
||||
res := res.extended ("block_").appended (a_block_id).appended_with_extension ("tpl")
|
||||
p := a_response.module_resource_path (a_module, res)
|
||||
if p /= Void then
|
||||
if attached p.entry as e then
|
||||
create Result.make (a_block_id, Void, p.parent, e)
|
||||
|
||||
31
src/kernel/content/format/cms_editor_content_format.e
Normal file
31
src/kernel/content/format/cms_editor_content_format.e
Normal file
@@ -0,0 +1,31 @@
|
||||
note
|
||||
description: "HTML Content format editable with WYSIWYG editor."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_EDITOR_CONTENT_FORMAT
|
||||
|
||||
inherit
|
||||
CONTENT_FORMAT
|
||||
redefine
|
||||
default_create
|
||||
end
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
default_create
|
||||
do
|
||||
Precursor
|
||||
create filters.make (0)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
name: STRING = "cms_editor"
|
||||
|
||||
title: STRING_8 = "CMS HTML content"
|
||||
|
||||
filters: ARRAYED_LIST [CONTENT_FILTER]
|
||||
|
||||
end
|
||||
@@ -27,10 +27,11 @@ feature -- Access
|
||||
once
|
||||
-- Can we provide an external file to read the
|
||||
-- supported formats?
|
||||
create {ARRAYED_LIST [CONTENT_FORMAT]} Result.make (3)
|
||||
create {ARRAYED_LIST [CONTENT_FORMAT]} Result.make (4)
|
||||
Result.force (plain_text)
|
||||
Result.force (full_html)
|
||||
Result.force (filtered_html)
|
||||
Result.force (cms_html)
|
||||
end
|
||||
|
||||
default_format: CONTENT_FORMAT
|
||||
@@ -43,6 +44,11 @@ feature -- Access
|
||||
create Result
|
||||
end
|
||||
|
||||
cms_html: CMS_EDITOR_CONTENT_FORMAT
|
||||
once
|
||||
create Result
|
||||
end
|
||||
|
||||
full_html: FULL_HTML_CONTENT_FORMAT
|
||||
once
|
||||
create Result
|
||||
@@ -53,7 +59,6 @@ feature -- Access
|
||||
create Result
|
||||
end
|
||||
|
||||
|
||||
note
|
||||
copyright: "2011-2014, Jocelyn Fiat, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
|
||||
106
src/kernel/form/cms_editor.e
Normal file
106
src/kernel/form/cms_editor.e
Normal file
@@ -0,0 +1,106 @@
|
||||
note
|
||||
description: "Class to import a WYSIWIG editor using javascript code"
|
||||
author: "Dario Bösch <daboesch@student.ethz.ch"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
CMS_EDITOR
|
||||
|
||||
feature -- Initialisation
|
||||
load_assets : STRING
|
||||
-- Loads all assest needed to show the editor
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Javascript
|
||||
|
||||
javascript_replace_textarea (a_textarea : WSF_FORM_TEXTAREA) : STRING
|
||||
-- Javascript code that replaces a textarea with the editor. The editor instance should be saved in editor_variable
|
||||
deferred
|
||||
end
|
||||
|
||||
javascript_restore_textarea (a_textarea : WSF_FORM_TEXTAREA) : STRING
|
||||
-- Javascript code that restores a textarea
|
||||
deferred
|
||||
end
|
||||
|
||||
javascript_textarea_to_editor(a_textarea : WSF_FORM_TEXTAREA) : STRING
|
||||
-- Javascript code to display the textarea as a WYSIWIG editor as soon as the document is loaded
|
||||
do
|
||||
Result := javascript_ready(javascript_replace_textarea (a_textarea))
|
||||
end
|
||||
|
||||
javascript_textarea_to_editor_if_selected (a_textarea : WSF_FORM_TEXTAREA; a_select_field : WSF_FORM_SELECT; a_value : STRING) : STRING
|
||||
-- Javascript code to display the textarea as a WYSIWIG editor if a_select_field has a_value
|
||||
local
|
||||
initial_replace_code, on_select_replace_code : STRING
|
||||
do
|
||||
-- Javascript that replaces the textarea if a_value is selected at load time
|
||||
initial_replace_code := javascript_ready(javascript_if_selected(a_select_field, a_value, javascript_replace_textarea(a_textarea)))
|
||||
|
||||
-- Javascript code that replaces the textarea as soon as value is selected at a_select_field
|
||||
on_select_replace_code := javascript_ready(
|
||||
javascript_init_editor_variable(a_textarea) +
|
||||
javascript_on_select(a_select_field, a_value,
|
||||
-- If a_value is selected, replace textarea
|
||||
javascript_replace_textarea(a_textarea),
|
||||
|
||||
-- Otherwise restore it
|
||||
javascript_restore_textarea(a_textarea)
|
||||
)
|
||||
)
|
||||
|
||||
Result := initial_replace_code + " " + on_select_replace_code
|
||||
end
|
||||
|
||||
javascript_init_editor_variable(a_textarea : WSF_FORM_TEXTAREA) : STRING
|
||||
-- Returns the javascript code that initializes a local variable to store the editor instance
|
||||
do
|
||||
Result := "var " + editor_variable(a_textarea) + "; "
|
||||
end
|
||||
|
||||
|
||||
|
||||
javascript_if_selected(a_select_field : WSF_FORM_SELECT; a_value : STRING; a_code : STRING) : STRING
|
||||
-- Javascript that executes a_code if a_value is selected at a_select_field
|
||||
do
|
||||
Result := "if($('#" + field_id(a_select_field) + "').val() == %"" + a_value + "%"){ " + a_code + " }"
|
||||
end
|
||||
|
||||
javascript_ready (a_code : STRING) : STRING
|
||||
-- Wraps the given javascript code with a ready statement, such that it's executed when the document has loaded
|
||||
do
|
||||
Result := "$(function() { " + a_code + " });"
|
||||
end
|
||||
|
||||
javascript_on_select (a_select_field : WSF_FORM_SELECT; a_value : STRING; a_then : STRING; a_else : STRING) : STRING
|
||||
-- Javascript code that executes a_then if at the given select_field the given string value is selected, otherwise it executes a_else
|
||||
do
|
||||
Result := "$('#" + field_id(a_select_field) + "').change(function(){" +
|
||||
javascript_if_selected(a_select_field, a_value, a_then) +
|
||||
"else{" +
|
||||
a_else +
|
||||
"}" +
|
||||
"});"
|
||||
end
|
||||
|
||||
feature -- Helper
|
||||
|
||||
field_id(a_select_field : WSF_FORM_SELECT) : STRING
|
||||
-- Returns the id of the given field
|
||||
do
|
||||
if attached a_select_field.css_id as a_id then
|
||||
Result := a_id
|
||||
else
|
||||
Result := a_select_field.name + "-select"
|
||||
end
|
||||
end
|
||||
|
||||
editor_variable (a_textarea : WSF_FORM_TEXTAREA) : STRING
|
||||
-- Returns the variable name that stores the editor instance of the given textarea
|
||||
do
|
||||
Result := "editor_" + a_textarea.name
|
||||
end
|
||||
|
||||
end
|
||||
37
src/kernel/form/cms_editor_ckeditor.e
Normal file
37
src/kernel/form/cms_editor_ckeditor.e
Normal file
@@ -0,0 +1,37 @@
|
||||
note
|
||||
description: "Summary description for {CMS_EDITOR_CKEDITOR}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_EDITOR_CKEDITOR
|
||||
|
||||
inherit
|
||||
CMS_EDITOR
|
||||
|
||||
feature -- Initialisation
|
||||
|
||||
load_assets : STRING
|
||||
-- <Precursor>
|
||||
do
|
||||
Result := "<script src=%"//cdn.ckeditor.com/4.4.7/standard/ckeditor.js%"></script>"
|
||||
end
|
||||
|
||||
feature -- Javascript
|
||||
|
||||
javascript_replace_textarea (a_textarea : WSF_FORM_TEXTAREA) : STRING
|
||||
-- <Precursor>
|
||||
do
|
||||
-- Replaces the textarea with an editor instance. Save the instance in a variable
|
||||
Result := editor_variable(a_textarea) + " = CKEDITOR.replace( '" + a_textarea.name + "' );"
|
||||
end
|
||||
|
||||
javascript_restore_textarea (a_textarea : WSF_FORM_TEXTAREA) : STRING
|
||||
-- <Precursor>
|
||||
do
|
||||
-- Replaces the textarea with an editor instance. Save the instance in a variable
|
||||
Result := "if (" + editor_variable(a_textarea) + " != undefined) " + editor_variable(a_textarea) + ".destroy();"
|
||||
end
|
||||
|
||||
end
|
||||
77
src/kernel/form/cms_form_textarea.e
Normal file
77
src/kernel/form/cms_form_textarea.e
Normal file
@@ -0,0 +1,77 @@
|
||||
note
|
||||
description: "Extends the WSF form textarea with features to add a WYSIWIG editor."
|
||||
author: "Dario Bösch <daboesch@student.ethz.ch"
|
||||
date: "$Date: 2015-05-23 16:02:55 +0100 (Sat, 23 May 2015) $"
|
||||
revision: "$Revision: 96616 $"
|
||||
|
||||
class
|
||||
CMS_FORM_TEXTAREA
|
||||
|
||||
inherit
|
||||
WSF_FORM_TEXTAREA
|
||||
redefine
|
||||
make,
|
||||
append_item_to_html
|
||||
end
|
||||
|
||||
CMS_EDITOR_CKEDITOR
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Initialisation
|
||||
|
||||
make (a_name: like name)
|
||||
-- <Precursor>
|
||||
do
|
||||
precursor(a_name)
|
||||
|
||||
-- By default we don't replace the textarea by an editor
|
||||
editor := False;
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
editor : BOOLEAN
|
||||
-- True if the textarea should be replaced by the editor. Default is false.
|
||||
|
||||
format_field : detachable WSF_FORM_SELECT
|
||||
-- Selection field for the format on that it depends, if the editor is shown or not.
|
||||
|
||||
condition_value : detachable STRING
|
||||
|
||||
feature -- Editor
|
||||
|
||||
show_as_editor
|
||||
-- The textarea will be replaced by a wysiwyg editor
|
||||
do
|
||||
editor := True
|
||||
end
|
||||
|
||||
show_as_editor_if_selected (a_select_field : WSF_FORM_SELECT; a_value : STRING)
|
||||
-- Replaces the textarea only if a_select_field has a_value (or the value gets selected)
|
||||
do
|
||||
editor := True
|
||||
format_field := a_select_field
|
||||
condition_value := a_value
|
||||
end
|
||||
|
||||
feature -- Conversion
|
||||
|
||||
append_item_to_html (a_theme: WSF_THEME; a_html: STRING_8)
|
||||
do
|
||||
-- Add javascript to replace textarea with editor
|
||||
precursor(a_theme, a_html)
|
||||
if editor then
|
||||
a_html.append (load_assets)
|
||||
a_html.append ("<script type=%"text/javascript%">");
|
||||
if attached format_field as l_field and then attached condition_value as l_value then
|
||||
a_html.append (javascript_textarea_to_editor_if_selected (Current, l_field, l_value))
|
||||
else
|
||||
a_html.append (javascript_textarea_to_editor (Current))
|
||||
end
|
||||
a_html.append ("</script>")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
15
src/kernel/form/cms_lower_upper_pager.e
Normal file
15
src/kernel/form/cms_lower_upper_pager.e
Normal file
@@ -0,0 +1,15 @@
|
||||
note
|
||||
description: "Pager widget for ROC CMS."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_LOWER_UPPER_PAGER
|
||||
|
||||
inherit
|
||||
WSF_WIDGET_PAGER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
end
|
||||
@@ -36,11 +36,10 @@ feature {NONE} -- Initialization
|
||||
|
||||
feature -- Router
|
||||
|
||||
router (a_api: CMS_API): WSF_ROUTER
|
||||
-- Router configuration.
|
||||
setup_router (a_router: WSF_ROUTER; a_api: CMS_API)
|
||||
-- <Precursor>
|
||||
do
|
||||
create Result.make (1)
|
||||
Result.handle ("/debug/", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_debug (a_api, ?, ?)))
|
||||
a_router.handle ("/debug/", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_debug (a_api, ?, ?)), Void)
|
||||
end
|
||||
|
||||
feature -- Hooks configuration
|
||||
|
||||
88
src/persistence/cms_data_query_parameters.e
Normal file
88
src/persistence/cms_data_query_parameters.e
Normal file
@@ -0,0 +1,88 @@
|
||||
note
|
||||
description: "[
|
||||
Parameters associated with data query.
|
||||
It could be query over http, or storage.
|
||||
]"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_DATA_QUERY_PARAMETERS
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_offset: NATURAL_64; a_size: NATURAL)
|
||||
do
|
||||
offset := a_offset
|
||||
size := a_size
|
||||
ensure
|
||||
size_set: size = a_size
|
||||
offset_set: offset = a_offset
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
size: NATURAL assign set_size
|
||||
-- Number of items per page.
|
||||
|
||||
offset: NATURAL_64 assign set_offset
|
||||
-- lower index of `items' pagination.
|
||||
|
||||
order_by: detachable READABLE_STRING_8
|
||||
-- field to order by.
|
||||
|
||||
order_ascending: BOOLEAN
|
||||
-- is ascending ordering?
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_size (a_size: NATURAL)
|
||||
-- Set `size' with `a_size'.
|
||||
do
|
||||
size := a_size
|
||||
ensure
|
||||
size_set: size = a_size
|
||||
end
|
||||
|
||||
set_offset (a_offset: NATURAL_64)
|
||||
-- Set offset with `a_offset'.
|
||||
do
|
||||
offset := a_offset
|
||||
ensure
|
||||
limit_set: offset = a_offset
|
||||
end
|
||||
|
||||
set_ascending_order_by_field (a_field: detachable READABLE_STRING_8)
|
||||
-- Pager with a order_by `a_field' asc.
|
||||
do
|
||||
if a_field /= Void then
|
||||
order_by := a_field
|
||||
order_ascending := True
|
||||
else
|
||||
order_by := Void
|
||||
end
|
||||
ensure
|
||||
order_by_unset: a_field = Void implies order_by = Void
|
||||
order_by_set: a_field /= Void implies attached order_by as l_order_by and then l_order_by.same_string (a_field)
|
||||
asc_true: order_ascending
|
||||
end
|
||||
|
||||
set_descending_order_by_field (a_field: detachable READABLE_STRING_8)
|
||||
-- Pager sorting descending with field `a_field' if set, otherwise remove sorting.
|
||||
do
|
||||
if a_field /= Void then
|
||||
order_by := a_field
|
||||
order_ascending := False
|
||||
else
|
||||
order_by := Void
|
||||
end
|
||||
ensure
|
||||
order_by_unset: a_field = Void implies order_by = Void
|
||||
order_by_set: a_field /= Void implies attached order_by as l_order_by and then l_order_by.same_string (a_field)
|
||||
asc_fasle: not order_ascending
|
||||
end
|
||||
|
||||
end
|
||||
@@ -39,6 +39,13 @@ feature -- Status report
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Basic operation
|
||||
|
||||
close
|
||||
-- Close/disconnect current storage.
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Error Handling
|
||||
|
||||
error_handler: ERROR_HANDLER
|
||||
|
||||
@@ -14,6 +14,11 @@ inherit
|
||||
default_create
|
||||
end
|
||||
|
||||
CMS_USER_STORAGE_NULL
|
||||
undefine
|
||||
default_create
|
||||
end
|
||||
|
||||
REFACTORING_HELPER
|
||||
rename
|
||||
default_create as default_create_rh
|
||||
@@ -40,74 +45,41 @@ feature -- Status report
|
||||
Result := True
|
||||
end
|
||||
|
||||
feature -- Access: user
|
||||
feature -- Basic operation
|
||||
|
||||
has_user: BOOLEAN
|
||||
-- Has any user?
|
||||
close
|
||||
-- <Precursor>
|
||||
do
|
||||
end
|
||||
|
||||
users: LIST [CMS_USER]
|
||||
do
|
||||
create {ARRAYED_LIST [CMS_USER]} Result.make (0)
|
||||
end
|
||||
feature -- URL aliases
|
||||
|
||||
user_by_id (a_id: like {CMS_USER}.id): detachable CMS_USER
|
||||
set_path_alias (a_source: READABLE_STRING_8; a_alias: READABLE_STRING_8)
|
||||
-- <Precursor>.
|
||||
do
|
||||
end
|
||||
|
||||
user_by_name (a_name: like {CMS_USER}.name): detachable CMS_USER
|
||||
replace_path_alias (a_source: READABLE_STRING_8; a_previous_alias: detachable READABLE_STRING_8; a_alias: READABLE_STRING_8)
|
||||
-- Replace eventual previous alias `a_previous_alias' with a new alias `a_alias'
|
||||
-- on source `a_source'.
|
||||
do
|
||||
end
|
||||
|
||||
user_by_email (a_email: like {CMS_USER}.email): detachable CMS_USER
|
||||
unset_path_alias (a_source: READABLE_STRING_8; a_alias: READABLE_STRING_8)
|
||||
-- Unalias `a_source' from `a_alias'.
|
||||
do
|
||||
end
|
||||
|
||||
is_valid_credential (l_auth_login, l_auth_password: READABLE_STRING_32): BOOLEAN
|
||||
path_alias (a_source: READABLE_STRING_8): detachable READABLE_STRING_8
|
||||
-- Return eventual path alias associated with `a_source'.
|
||||
do
|
||||
end
|
||||
|
||||
feature -- Change: user
|
||||
|
||||
new_user (a_user: CMS_USER)
|
||||
-- Add a new user `a_user'.
|
||||
do
|
||||
a_user.set_id (1)
|
||||
end
|
||||
|
||||
update_user (a_user: CMS_USER)
|
||||
-- Update user `a_user'.
|
||||
source_of_path_alias (a_alias: READABLE_STRING_8): detachable READABLE_STRING_8
|
||||
-- Source path for alias `a_alias'.
|
||||
do
|
||||
end
|
||||
|
||||
|
||||
feature -- Access: roles and permissions
|
||||
|
||||
user_role_by_id (a_id: like {CMS_USER_ROLE}.id): detachable CMS_USER_ROLE
|
||||
do
|
||||
end
|
||||
|
||||
user_roles_for (a_user: CMS_USER): LIST [CMS_USER_ROLE]
|
||||
-- User roles for user `a_user'.
|
||||
-- Note: anonymous and authenticated roles are not included.
|
||||
do
|
||||
create {ARRAYED_LIST [CMS_USER_ROLE]} Result.make (0)
|
||||
end
|
||||
|
||||
user_roles: LIST [CMS_USER_ROLE]
|
||||
do
|
||||
create {ARRAYED_LIST [CMS_USER_ROLE]} Result.make (0)
|
||||
end
|
||||
|
||||
feature -- Change: roles and permissions
|
||||
|
||||
save_user_role (a_user_role: CMS_USER_ROLE)
|
||||
do
|
||||
end
|
||||
|
||||
|
||||
|
||||
feature -- Logs
|
||||
|
||||
save_log (a_log: CMS_LOG)
|
||||
@@ -115,6 +87,8 @@ feature -- Logs
|
||||
do
|
||||
end
|
||||
|
||||
feature -- Custom
|
||||
|
||||
set_custom_value (a_name: READABLE_STRING_8; a_value: attached like custom_value; a_type: detachable READABLE_STRING_8)
|
||||
-- Save data `a_name:a_value' for type `a_type' (or default if none).
|
||||
do
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
note
|
||||
description: "[
|
||||
Objects that ...
|
||||
]"
|
||||
author: "$Author: jfiat $"
|
||||
date: "$Date: 2015-01-27 19:15:02 +0100 (mar., 27 janv. 2015) $"
|
||||
revision: "$Revision: 96542 $"
|
||||
|
||||
deferred class
|
||||
CMS_STORAGE_SQL_BUILDER
|
||||
|
||||
inherit
|
||||
CMS_STORAGE_BUILDER
|
||||
|
||||
end
|
||||
@@ -1,6 +1,6 @@
|
||||
note
|
||||
description: "[
|
||||
Objects that ...
|
||||
CMS Storage for core functionalities.
|
||||
]"
|
||||
author: "$Author$"
|
||||
date: "$Date$"
|
||||
@@ -19,6 +19,34 @@ feature -- Error Handling
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- URL aliases
|
||||
|
||||
set_path_alias (a_source: READABLE_STRING_8; a_alias: READABLE_STRING_8)
|
||||
-- Alias `a_source' with `a_alias'.
|
||||
deferred
|
||||
end
|
||||
|
||||
replace_path_alias (a_source: READABLE_STRING_8; a_previous_alias: detachable READABLE_STRING_8; a_alias: READABLE_STRING_8)
|
||||
-- Replace eventual previous alias `a_previous_alias' with a new alias `a_alias'
|
||||
-- on source `a_source'.
|
||||
deferred
|
||||
end
|
||||
|
||||
unset_path_alias (a_source: READABLE_STRING_8; a_alias: READABLE_STRING_8)
|
||||
-- Unalias `a_source' from `a_alias'.
|
||||
deferred
|
||||
end
|
||||
|
||||
path_alias (a_source: READABLE_STRING_8): detachable READABLE_STRING_8
|
||||
-- Return eventual path alias associated with `a_source'.
|
||||
deferred
|
||||
end
|
||||
|
||||
source_of_path_alias (a_alias: READABLE_STRING_8): detachable READABLE_STRING_8
|
||||
-- Source path for alias `a_alias'.
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Logs
|
||||
|
||||
save_log (a_log: CMS_LOG)
|
||||
|
||||
@@ -18,6 +18,123 @@ inherit
|
||||
|
||||
SHARED_LOGGER
|
||||
|
||||
feature -- URL aliases
|
||||
|
||||
set_path_alias (a_source: READABLE_STRING_8; a_alias: READABLE_STRING_8)
|
||||
-- <Precursor>
|
||||
local
|
||||
l_parameters: STRING_TABLE [detachable ANY]
|
||||
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
|
||||
else
|
||||
error_handler.add_custom_error (0, "alias exists", "Path alias %"" + a_alias + "%" already exists!")
|
||||
end
|
||||
else
|
||||
sql_change (sql_insert_path_alias, l_parameters)
|
||||
end
|
||||
end
|
||||
|
||||
replace_path_alias (a_source: READABLE_STRING_8; a_previous_alias: detachable READABLE_STRING_8; a_alias: READABLE_STRING_8)
|
||||
-- <Precursor>
|
||||
local
|
||||
l_parameters: STRING_TABLE [detachable ANY]
|
||||
l_previous_alias: detachable READABLE_STRING_8
|
||||
do
|
||||
error_handler.reset
|
||||
|
||||
if a_previous_alias = Void then
|
||||
l_previous_alias := path_alias (a_source)
|
||||
else
|
||||
l_previous_alias := a_previous_alias
|
||||
end
|
||||
if
|
||||
l_previous_alias /= Void and then
|
||||
not a_alias.same_string (l_previous_alias)
|
||||
then
|
||||
create l_parameters.make (3)
|
||||
l_parameters.put (a_source, "source")
|
||||
l_parameters.put (l_previous_alias, "old")
|
||||
l_parameters.put (a_alias, "alias")
|
||||
|
||||
sql_change (sql_update_path_alias, l_parameters)
|
||||
end
|
||||
end
|
||||
|
||||
unset_path_alias (a_source: READABLE_STRING_8; a_alias: READABLE_STRING_8)
|
||||
-- <Precursor>
|
||||
local
|
||||
l_parameters: STRING_TABLE [detachable ANY]
|
||||
do
|
||||
error_handler.reset
|
||||
|
||||
if attached source_of_path_alias (a_alias) as l_path then
|
||||
if a_source.same_string (l_path) then
|
||||
-- Found
|
||||
create l_parameters.make (1)
|
||||
l_parameters.put (a_alias, "alias")
|
||||
sql_change (sql_delete_path_alias, l_parameters)
|
||||
else
|
||||
error_handler.add_custom_error (0, "alias mismatch", "Path alias %"" + a_alias + "%" is not related to source %"" + a_source + "%"!")
|
||||
end
|
||||
else
|
||||
-- No such alias
|
||||
end
|
||||
end
|
||||
|
||||
path_alias (a_source: READABLE_STRING_8): detachable READABLE_STRING_8
|
||||
-- <Precursor>
|
||||
local
|
||||
l_parameters: STRING_TABLE [detachable ANY]
|
||||
do
|
||||
error_handler.reset
|
||||
create l_parameters.make (1)
|
||||
l_parameters.put (a_source, "source")
|
||||
sql_query (sql_select_path_source, l_parameters)
|
||||
if not has_error then
|
||||
if sql_rows_count = 1 then
|
||||
Result := sql_read_string (1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
source_of_path_alias (a_alias: READABLE_STRING_8): detachable READABLE_STRING_8
|
||||
-- <Precursor>
|
||||
local
|
||||
l_parameters: STRING_TABLE [detachable ANY]
|
||||
do
|
||||
error_handler.reset
|
||||
create l_parameters.make (1)
|
||||
l_parameters.put (a_alias, "alias")
|
||||
sql_query (sql_select_path_alias, l_parameters)
|
||||
if not has_error then
|
||||
if sql_rows_count = 1 then
|
||||
Result := sql_read_string (1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
sql_select_path_alias: STRING = "SELECT source FROM path_aliases WHERE alias=:alias ;"
|
||||
-- SQL select path aliases.
|
||||
|
||||
sql_select_path_source: STRING = "SELECT alias FROM path_aliases WHERE source=:source ORDER BY pid DESC LIMIT 1;"
|
||||
-- SQL select latest path aliasing :source.
|
||||
|
||||
sql_insert_path_alias: STRING = "INSERT INTO path_aliases (source, alias) VALUES (:source, :alias);"
|
||||
-- SQL insert path alias.
|
||||
|
||||
sql_update_path_alias: STRING = "UPDATE path_aliases SET alias=:alias WHERE source=:source AND alias=:old ;"
|
||||
-- SQL update path alias.
|
||||
|
||||
sql_delete_path_alias: STRING = "DELETE FROM path_aliases WHERE alias=:alias;"
|
||||
-- SQL delete path alias
|
||||
|
||||
feature -- Logs
|
||||
|
||||
save_log (a_log: CMS_LOG)
|
||||
|
||||
107
src/persistence/sql/cms_storage_fs_i.e
Normal file
107
src/persistence/sql/cms_storage_fs_i.e
Normal file
@@ -0,0 +1,107 @@
|
||||
note
|
||||
description: "Interface used to implement CMS Storage based on File system."
|
||||
date: "$Date: 2015-02-13 13:08:13 +0100 (ven., 13 févr. 2015) $"
|
||||
revision: "$Revision: 96616 $"
|
||||
|
||||
deferred class
|
||||
CMS_STORAGE_FS_I
|
||||
|
||||
inherit
|
||||
SHARED_LOGGER
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_location: PATH; a_api: CMS_API)
|
||||
do
|
||||
location := a_location
|
||||
api := a_api
|
||||
create error_handler.make
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
api: CMS_API
|
||||
-- Associated CMS api.
|
||||
|
||||
location: PATH
|
||||
-- File system location.
|
||||
|
||||
feature -- Error handler
|
||||
|
||||
error_handler: ERROR_HANDLER
|
||||
-- Error handler.
|
||||
|
||||
has_error: BOOLEAN
|
||||
-- Last operation reported error.
|
||||
do
|
||||
Result := error_handler.has_error
|
||||
end
|
||||
|
||||
reset_error
|
||||
-- Reset errors.
|
||||
do
|
||||
error_handler.reset
|
||||
end
|
||||
|
||||
feature -- Helpers
|
||||
|
||||
save_to_file (a_text: STRING; opt_name: detachable READABLE_STRING_GENERAL)
|
||||
local
|
||||
s: READABLE_STRING_GENERAL
|
||||
now: DATE_TIME
|
||||
fut: WSF_FILE_UTILITIES [RAW_FILE]
|
||||
do
|
||||
create fut
|
||||
if opt_name /= Void then
|
||||
s := opt_name
|
||||
else
|
||||
create now.make_now_utc
|
||||
s := date_to_yyyymmdd_hhmmss_string (now)
|
||||
end
|
||||
if attached fut.new_file (location.extended (s)) as f then
|
||||
f.put_string (a_text)
|
||||
f.close
|
||||
else
|
||||
error_handler.add_custom_error (0, "saving failure", Void)
|
||||
end
|
||||
end
|
||||
|
||||
date_to_yyyymmdd_hhmmss_string (d: DATE_TIME): STRING
|
||||
local
|
||||
i: INTEGER
|
||||
do
|
||||
create Result.make_empty
|
||||
Result.append_integer (d.year)
|
||||
Result.append_character ('-')
|
||||
i := d.month
|
||||
if i < 10 then
|
||||
Result.append_integer (0)
|
||||
end
|
||||
Result.append_integer (i)
|
||||
Result.append_character ('-')
|
||||
i := d.day
|
||||
if i < 10 then
|
||||
Result.append_integer (0)
|
||||
end
|
||||
Result.append_integer (i)
|
||||
Result.append_character ('_')
|
||||
i := d.hour
|
||||
if i < 10 then
|
||||
Result.append_integer (0)
|
||||
end
|
||||
Result.append_integer (i)
|
||||
Result.append_character ('-')
|
||||
i := d.minute
|
||||
if i < 10 then
|
||||
Result.append_integer (0)
|
||||
end
|
||||
Result.append_integer (i)
|
||||
Result.append_character ('-')
|
||||
i := d.second
|
||||
if i < 10 then
|
||||
Result.append_integer (0)
|
||||
end
|
||||
Result.append_integer (i)
|
||||
end
|
||||
|
||||
end
|
||||
15
src/persistence/sql/cms_storage_sql.e
Normal file
15
src/persistence/sql/cms_storage_sql.e
Normal file
@@ -0,0 +1,15 @@
|
||||
note
|
||||
description: "CMS Storage based on SQL statement."
|
||||
date: "$Date: 2015-02-13 13:08:13 +0100 (ven., 13 févr. 2015) $"
|
||||
revision: "$Revision: 96616 $"
|
||||
|
||||
deferred class
|
||||
CMS_STORAGE_SQL
|
||||
|
||||
inherit
|
||||
CMS_STORAGE
|
||||
|
||||
CMS_STORAGE_SQL_I
|
||||
|
||||
|
||||
end
|
||||
91
src/persistence/sql/cms_storage_sql_builder.e
Normal file
91
src/persistence/sql/cms_storage_sql_builder.e
Normal file
@@ -0,0 +1,91 @@
|
||||
note
|
||||
description: "[
|
||||
Common ancestor for builders responsible to instantiate storage based
|
||||
on SQL statement storage.
|
||||
]"
|
||||
author: "$Author: jfiat $"
|
||||
date: "$Date: 2015-01-27 19:15:02 +0100 (mar., 27 janv. 2015) $"
|
||||
revision: "$Revision: 96542 $"
|
||||
|
||||
deferred class
|
||||
CMS_STORAGE_SQL_BUILDER
|
||||
|
||||
inherit
|
||||
CMS_STORAGE_BUILDER
|
||||
|
||||
feature -- Initialization
|
||||
|
||||
initialize (a_setup: CMS_SETUP; a_storage: CMS_STORAGE_SQL)
|
||||
local
|
||||
u: CMS_USER
|
||||
l_anonymous_role, l_authenticated_role, r: CMS_USER_ROLE
|
||||
l_roles: LIST [CMS_USER_ROLE]
|
||||
do
|
||||
--| Schema
|
||||
a_storage.sql_execute_file_script (a_setup.environment.path.extended ("scripts").extended ("core.sql"))
|
||||
a_storage.sql_execute_file_script (a_setup.environment.path.extended ("scripts").extended ("user.sql"))
|
||||
|
||||
--| Roles
|
||||
create l_anonymous_role.make ("anonymous")
|
||||
a_storage.save_user_role (l_anonymous_role)
|
||||
|
||||
create l_authenticated_role.make ("authenticated")
|
||||
a_storage.save_user_role (l_authenticated_role)
|
||||
|
||||
--| Users
|
||||
create u.make ("admin")
|
||||
u.set_password ("istrator#")
|
||||
u.set_email (a_setup.site_email)
|
||||
a_storage.new_user (u)
|
||||
|
||||
--| Node
|
||||
-- FIXME: move that initialization to node module
|
||||
-- TODO: should we move the initialization to an
|
||||
--! external configuration file?
|
||||
--! at the moment we only have 1 admin to the whole site.
|
||||
--! is that ok?
|
||||
l_anonymous_role.add_permission ("view any page")
|
||||
a_storage.save_user_role (l_anonymous_role)
|
||||
|
||||
l_authenticated_role.add_permission ("create page")
|
||||
l_authenticated_role.add_permission ("view any page")
|
||||
l_authenticated_role.add_permission ("edit any page")
|
||||
l_authenticated_role.add_permission ("delete page")
|
||||
l_authenticated_role.add_permission ("trash page")
|
||||
l_authenticated_role.add_permission ("view own page")
|
||||
l_authenticated_role.add_permission ("edit own page")
|
||||
l_authenticated_role.add_permission ("delete own page")
|
||||
l_authenticated_role.add_permission ("trash own page")
|
||||
a_storage.save_user_role (l_authenticated_role)
|
||||
|
||||
|
||||
--|-------------------------------------------|--
|
||||
--| For testing purpose, to be removed later. |--
|
||||
--|-------------------------------------------|--
|
||||
|
||||
-- Roles, view role for testing.
|
||||
create r.make ("view")
|
||||
r.add_permission ("view any page")
|
||||
a_storage.save_user_role (r)
|
||||
|
||||
create {ARRAYED_LIST [CMS_USER_ROLE]} l_roles.make (1)
|
||||
l_roles.force (r)
|
||||
|
||||
create u.make ("auth")
|
||||
u.set_password ("enticated#")
|
||||
u.set_email (a_setup.site_email)
|
||||
a_storage.new_user (u)
|
||||
|
||||
create u.make ("test")
|
||||
u.set_password ("test#")
|
||||
u.set_email (a_setup.site_email)
|
||||
a_storage.new_user (u)
|
||||
|
||||
create u.make ("view")
|
||||
u.set_password ("only#")
|
||||
u.set_email (a_setup.site_email)
|
||||
u.set_roles (l_roles)
|
||||
a_storage.new_user (u)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -217,6 +217,21 @@ feature -- Access
|
||||
deferred
|
||||
end
|
||||
|
||||
sql_read_natural_64 (a_index: INTEGER): NATURAL_64
|
||||
-- Retrieved value at `a_index' position in `item'.
|
||||
local
|
||||
l_item: like sql_item
|
||||
do
|
||||
l_item := sql_item (a_index)
|
||||
if attached {NATURAL_64} l_item as i then
|
||||
Result := i
|
||||
elseif attached {NATURAL_64_REF} l_item as l_value then
|
||||
Result := l_value.item
|
||||
else
|
||||
Result := sql_read_integer_64 (a_index).to_natural_64
|
||||
end
|
||||
end
|
||||
|
||||
sql_read_integer_64 (a_index: INTEGER): INTEGER_64
|
||||
-- Retrieved value at `a_index' position in `item'.
|
||||
local
|
||||
79
src/persistence/user/cms_user_storage_null.e
Normal file
79
src/persistence/user/cms_user_storage_null.e
Normal file
@@ -0,0 +1,79 @@
|
||||
note
|
||||
description: "Summary description for {CMS_USER_STORAGE_NULL}."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
deferred class
|
||||
CMS_USER_STORAGE_NULL
|
||||
|
||||
inherit
|
||||
CMS_USER_STORAGE_I
|
||||
|
||||
feature -- Access: user
|
||||
|
||||
has_user: BOOLEAN
|
||||
-- Has any user?
|
||||
do
|
||||
end
|
||||
|
||||
users: LIST [CMS_USER]
|
||||
do
|
||||
create {ARRAYED_LIST [CMS_USER]} Result.make (0)
|
||||
end
|
||||
|
||||
user_by_id (a_id: like {CMS_USER}.id): detachable CMS_USER
|
||||
do
|
||||
end
|
||||
|
||||
user_by_name (a_name: like {CMS_USER}.name): detachable CMS_USER
|
||||
do
|
||||
end
|
||||
|
||||
user_by_email (a_email: like {CMS_USER}.email): detachable CMS_USER
|
||||
do
|
||||
end
|
||||
|
||||
is_valid_credential (l_auth_login, l_auth_password: READABLE_STRING_32): BOOLEAN
|
||||
do
|
||||
end
|
||||
|
||||
feature -- Change: user
|
||||
|
||||
new_user (a_user: CMS_USER)
|
||||
-- Add a new user `a_user'.
|
||||
do
|
||||
a_user.set_id (1)
|
||||
end
|
||||
|
||||
update_user (a_user: CMS_USER)
|
||||
-- Update user `a_user'.
|
||||
do
|
||||
end
|
||||
|
||||
|
||||
feature -- Access: roles and permissions
|
||||
|
||||
user_role_by_id (a_id: like {CMS_USER_ROLE}.id): detachable CMS_USER_ROLE
|
||||
do
|
||||
end
|
||||
|
||||
user_roles_for (a_user: CMS_USER): LIST [CMS_USER_ROLE]
|
||||
-- User roles for user `a_user'.
|
||||
-- Note: anonymous and authenticated roles are not included.
|
||||
do
|
||||
create {ARRAYED_LIST [CMS_USER_ROLE]} Result.make (0)
|
||||
end
|
||||
|
||||
user_roles: LIST [CMS_USER_ROLE]
|
||||
do
|
||||
create {ARRAYED_LIST [CMS_USER_ROLE]} Result.make (0)
|
||||
end
|
||||
|
||||
feature -- Change: roles and permissions
|
||||
|
||||
save_user_role (a_user_role: CMS_USER_ROLE)
|
||||
do
|
||||
end
|
||||
|
||||
end
|
||||
@@ -148,17 +148,15 @@ feature -- Permissions system
|
||||
|
||||
feature -- Query: module
|
||||
|
||||
module (a_type: TYPE [detachable CMS_MODULE]): detachable CMS_MODULE
|
||||
module (a_type: TYPE [CMS_MODULE]): detachable CMS_MODULE
|
||||
-- Enabled module typed `a_type', if any.
|
||||
--| usage: if attached module ({FOO_MODULE}) as mod then ...
|
||||
local
|
||||
t: STRING_8
|
||||
-- t: STRING_8
|
||||
l_type: TYPE [detachable CMS_MODULE]
|
||||
do
|
||||
t := a_type.name
|
||||
if t.starts_with ("!") then
|
||||
t.remove_head (1)
|
||||
end
|
||||
-- t := type_name_without_annotation (a_type)
|
||||
|
||||
across
|
||||
setup.modules as ic
|
||||
until
|
||||
@@ -171,8 +169,12 @@ feature -- Query: module
|
||||
l_type := Result.generating_type
|
||||
if a_type ~ l_type then
|
||||
-- Found
|
||||
elseif t.same_string (l_type.name) then
|
||||
elseif
|
||||
attached a_type.attempt (Result) and then attached l_type.generating_type.attempt (a_type)
|
||||
then
|
||||
-- Found
|
||||
-- elseif t.same_string (type_name_without_annotation (l_type)) then
|
||||
-- -- Found
|
||||
else
|
||||
Result := Void
|
||||
end
|
||||
@@ -186,7 +188,12 @@ feature -- Query: module
|
||||
-- Enabled module API associated with module typed `a_type'.
|
||||
do
|
||||
if attached module (a_type) as mod then
|
||||
Result := mod.module_api
|
||||
if mod.is_enabled then
|
||||
if not mod.is_initialized then
|
||||
mod.initialize (Current)
|
||||
end
|
||||
Result := mod.module_api
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -232,6 +239,73 @@ feature -- Query: API
|
||||
Result := l_api
|
||||
end
|
||||
|
||||
feature -- Path aliases
|
||||
|
||||
is_valid_path_alias (a_alias: READABLE_STRING_8): BOOLEAN
|
||||
do
|
||||
Result := a_alias.is_empty or else not a_alias.starts_with_general ("/")
|
||||
end
|
||||
|
||||
set_path_alias (a_source, a_alias: READABLE_STRING_8; a_keep_previous: BOOLEAN)
|
||||
-- Set `a_alias' as alias of `a_source',
|
||||
-- and eventually unset previous alias if any.
|
||||
require
|
||||
valid_alias: is_valid_path_alias (a_alias)
|
||||
local
|
||||
l_continue: BOOLEAN
|
||||
do
|
||||
if attached storage.path_alias (a_source) as l_existing_alias then
|
||||
if a_alias.same_string (l_existing_alias) then
|
||||
-- Already aliased as expected
|
||||
else
|
||||
-- New alias
|
||||
if a_keep_previous then
|
||||
l_continue := True
|
||||
else
|
||||
storage.replace_path_alias (a_source, l_existing_alias, a_alias)
|
||||
end
|
||||
end
|
||||
elseif a_alias.is_whitespace then
|
||||
-- Ignore
|
||||
elseif a_source.same_string (a_alias) then
|
||||
-- No need for alias
|
||||
else
|
||||
l_continue := True
|
||||
end
|
||||
if l_continue then
|
||||
storage.set_path_alias (a_source, a_alias)
|
||||
end
|
||||
end
|
||||
|
||||
unset_path_alias (a_source: READABLE_STRING_8; a_alias: READABLE_STRING_8)
|
||||
do
|
||||
storage.unset_path_alias (a_source, a_alias)
|
||||
end
|
||||
|
||||
path_alias (a_source: READABLE_STRING_8): READABLE_STRING_8
|
||||
-- Path alias associated with `a_source' or the source itself.
|
||||
do
|
||||
Result := a_source
|
||||
if attached storage.path_alias (Result) as l_path then
|
||||
Result := "/" + l_path
|
||||
end
|
||||
end
|
||||
|
||||
source_of_path_alias (a_alias: READABLE_STRING_8): READABLE_STRING_8
|
||||
-- Resolved path for alias `a_alias'.
|
||||
--| the CMS supports aliases for path, and then this function simply returns
|
||||
--| the effective target path/url for this `a_alias'.
|
||||
--| For instance: articles/2015/may/this-is-an-article can be an alias to node/123
|
||||
--| This function will return "node/123".
|
||||
--| If the alias is bad (i.e does not alias real path), then this function
|
||||
--| returns the alias itself.
|
||||
do
|
||||
Result := a_alias
|
||||
if attached storage.source_of_path_alias (Result) as l_path then
|
||||
Result := l_path
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Element Change: Error
|
||||
|
||||
reset_error
|
||||
@@ -248,6 +322,41 @@ feature {NONE}-- Implemenation
|
||||
internal_user_api: detachable like user_api
|
||||
-- Cached value for `user_api'.
|
||||
|
||||
type_name_without_annotation (a_type: TYPE [detachable ANY]): STRING
|
||||
-- Type name for `a_type, without any annotation.
|
||||
-- Used by `module' to search by type.
|
||||
local
|
||||
i,j,n: INTEGER
|
||||
c: CHARACTER
|
||||
do
|
||||
create Result.make_from_string (a_type.name)
|
||||
from
|
||||
i := 1
|
||||
n := Result.count
|
||||
until
|
||||
i > n
|
||||
loop
|
||||
c := Result[i]
|
||||
if c = '!' or c = '?' then
|
||||
Result.remove (i)
|
||||
n := n - 1
|
||||
elseif c.is_lower then
|
||||
j := Result.index_of (' ', i + 1)
|
||||
if j > 0 then
|
||||
Result.remove_substring (i, j)
|
||||
n := n - (j - i)
|
||||
end
|
||||
else
|
||||
i := i + 1
|
||||
end
|
||||
end
|
||||
if Result.starts_with ("!") or Result.starts_with ("?") then
|
||||
Result.remove_head (1)
|
||||
elseif Result.starts_with ("detachable ") then
|
||||
Result.remove_head (11)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Environment
|
||||
|
||||
module_configuration (a_module_name: READABLE_STRING_GENERAL; a_name: detachable READABLE_STRING_GENERAL): detachable CONFIG_READER
|
||||
|
||||
@@ -14,4 +14,10 @@ create
|
||||
make,
|
||||
make_from_manifest
|
||||
|
||||
convert
|
||||
make_from_manifest ({ ARRAY [TUPLE [key: STRING; value: detachable ANY]],
|
||||
ARRAY [TUPLE [STRING_8, ARRAY [TUPLE [STRING_8, STRING_32]]]],
|
||||
ARRAY [TUPLE [STRING_8, ARRAY [TUPLE [STRING_8, STRING_8]]]]
|
||||
})
|
||||
|
||||
end
|
||||
|
||||
@@ -6,54 +6,56 @@ note
|
||||
even for a specific handler.
|
||||
]"
|
||||
|
||||
class
|
||||
CMS_SERVICE
|
||||
deferred class
|
||||
CMS_EXECUTION
|
||||
|
||||
inherit
|
||||
WSF_ROUTED_SKELETON_SERVICE
|
||||
rename
|
||||
execute as execute_service
|
||||
WSF_FILTERED_ROUTED_SKELETON_EXECUTION
|
||||
undefine
|
||||
requires_proxy
|
||||
redefine
|
||||
execute_default
|
||||
end
|
||||
|
||||
WSF_FILTERED_SERVICE
|
||||
|
||||
WSF_FILTER
|
||||
rename
|
||||
execute as execute_filter
|
||||
create_router, router,
|
||||
execute_default,
|
||||
filter_execute,
|
||||
initialize
|
||||
end
|
||||
|
||||
WSF_NO_PROXY_POLICY
|
||||
|
||||
WSF_URI_HELPER_FOR_ROUTED_SERVICE
|
||||
WSF_URI_HELPER_FOR_ROUTED_EXECUTION
|
||||
|
||||
WSF_URI_TEMPLATE_HELPER_FOR_ROUTED_SERVICE
|
||||
WSF_URI_TEMPLATE_HELPER_FOR_ROUTED_EXECUTION
|
||||
|
||||
REFACTORING_HELPER
|
||||
|
||||
SHARED_LOGGER
|
||||
|
||||
create
|
||||
make
|
||||
--create
|
||||
-- make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_setup: CMS_SETUP)
|
||||
initialize
|
||||
-- Build a CMS service with `a_api'
|
||||
local
|
||||
l_setup: CMS_SETUP
|
||||
do
|
||||
create api.make (a_setup)
|
||||
initialize
|
||||
l_setup := initial_cms_setup
|
||||
setup_storage (l_setup)
|
||||
setup_modules (l_setup)
|
||||
create api.make (l_setup)
|
||||
modules := setup.enabled_modules
|
||||
|
||||
initialize_cms
|
||||
Precursor
|
||||
end
|
||||
|
||||
initialize
|
||||
-- Initialize various parts of the CMS service.
|
||||
initialize_cms
|
||||
do
|
||||
initialize_modules
|
||||
initialize_users
|
||||
initialize_mailer
|
||||
write_debug_log (generator + ".initialize_cms")
|
||||
|
||||
-- CMS Initialization
|
||||
|
||||
-- initialize_router
|
||||
-- initialize_filter: expanded here, for void-safety concern.
|
||||
create_filter
|
||||
@@ -69,23 +71,51 @@ feature {NONE} -- Initialization
|
||||
only_enabled_modules: across modules as ic all ic.item.is_enabled end
|
||||
end
|
||||
|
||||
initialize_users
|
||||
-- Initialize users.
|
||||
do
|
||||
feature -- Factory
|
||||
|
||||
initial_cms_setup: CMS_SETUP
|
||||
deferred
|
||||
end
|
||||
|
||||
initialize_mailer
|
||||
-- Initialize mailer engine.
|
||||
feature -- Access
|
||||
|
||||
api: CMS_API
|
||||
-- API service.
|
||||
|
||||
setup: CMS_SETUP
|
||||
-- CMS Setup.
|
||||
do
|
||||
to_implement ("To Implement mailer")
|
||||
Result := api.setup
|
||||
end
|
||||
|
||||
modules: CMS_MODULE_COLLECTION
|
||||
-- Configurator of possible modules.
|
||||
|
||||
feature -- CMS setup
|
||||
|
||||
setup_modules (a_setup: CMS_SETUP)
|
||||
-- Setup additional modules.
|
||||
deferred
|
||||
end
|
||||
|
||||
setup_storage (a_setup: CMS_SETUP)
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Settings: router
|
||||
|
||||
router: CMS_ROUTER
|
||||
-- <Precursor>
|
||||
|
||||
create_router
|
||||
-- Create `router'.
|
||||
do
|
||||
create router.make (api, 30)
|
||||
end
|
||||
|
||||
setup_router
|
||||
-- <Precursor>
|
||||
local
|
||||
l_module: CMS_MODULE
|
||||
l_api: like api
|
||||
l_router: like router
|
||||
do
|
||||
@@ -100,8 +130,7 @@ feature -- Settings: router
|
||||
across
|
||||
modules as ic
|
||||
loop
|
||||
l_module := ic.item
|
||||
l_router.import (l_module.router (l_api))
|
||||
ic.item.setup_router (l_router, l_api)
|
||||
end
|
||||
-- Configure files handler.
|
||||
configure_api_file_handler (l_router)
|
||||
@@ -116,9 +145,9 @@ feature -- Settings: router
|
||||
create l_root_handler.make (api)
|
||||
create l_methods
|
||||
l_methods.enable_get
|
||||
a_router.handle_with_request_methods ("/", l_root_handler, l_methods)
|
||||
a_router.handle_with_request_methods ("", l_root_handler, l_methods)
|
||||
map_uri_agent_with_request_methods ("/favicon.ico", agent handle_favicon, a_router.methods_head_get)
|
||||
a_router.handle ("/", l_root_handler, l_methods)
|
||||
a_router.handle ("", l_root_handler, l_methods)
|
||||
map_uri_agent ("/favicon.ico", agent handle_favicon, a_router.methods_head_get)
|
||||
end
|
||||
|
||||
configure_api_file_handler (a_router: WSF_ROUTER)
|
||||
@@ -129,11 +158,11 @@ feature -- Settings: router
|
||||
|
||||
create fhdl.make_hidden_with_path (setup.theme_assets_location)
|
||||
fhdl.disable_index
|
||||
fhdl.set_not_found_handler (agent (ia_uri: READABLE_STRING_8; ia_req: WSF_REQUEST; ia_res: WSF_RESPONSE)
|
||||
fhdl.set_not_found_handler (agent (ia_uri: READABLE_STRING_8; ia_req: WSF_REQUEST; ia_res: WSF_RESPONSE)
|
||||
do
|
||||
execute_default (ia_req, ia_res)
|
||||
end)
|
||||
a_router.handle_with_request_methods ("/theme/", fhdl, router.methods_GET)
|
||||
a_router.handle ("/theme/", fhdl, router.methods_GET)
|
||||
|
||||
|
||||
create fhdl.make_hidden_with_path (setup.environment.www_path)
|
||||
@@ -142,17 +171,17 @@ feature -- Settings: router
|
||||
do
|
||||
execute_default (ia_req, ia_res)
|
||||
end)
|
||||
a_router.handle_with_request_methods ("/", fhdl, router.methods_GET)
|
||||
a_router.handle ("/", fhdl, router.methods_GET)
|
||||
end
|
||||
|
||||
feature -- Execute Filter
|
||||
|
||||
execute_filter (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
filter_execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute the filter.
|
||||
do
|
||||
res.put_header_line ("Date: " + (create {HTTP_DATE}.make_now_utc).string)
|
||||
res.put_header_line ("X-EWF-Server: CMS_v1.0")
|
||||
execute_service (req, res)
|
||||
Precursor (req, res)
|
||||
end
|
||||
|
||||
feature -- Filters
|
||||
@@ -172,10 +201,10 @@ feature -- Filters
|
||||
f.set_next (l_filter)
|
||||
l_filter := f
|
||||
|
||||
-- Error Filter
|
||||
create {CMS_ERROR_FILTER} f.make (api)
|
||||
f.set_next (l_filter)
|
||||
l_filter := f
|
||||
-- -- Error Filter
|
||||
-- create {CMS_ERROR_FILTER} f.make (api)
|
||||
-- f.set_next (l_filter)
|
||||
-- l_filter := f
|
||||
|
||||
-- Include filters from modules
|
||||
l_api := api
|
||||
@@ -215,20 +244,6 @@ feature -- Filters
|
||||
f.set_next (Current)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
api: CMS_API
|
||||
-- API service.
|
||||
|
||||
setup: CMS_SETUP
|
||||
-- CMS setup.
|
||||
do
|
||||
Result := api.setup
|
||||
end
|
||||
|
||||
modules: CMS_MODULE_COLLECTION
|
||||
-- Configurator of possible modules.
|
||||
|
||||
feature -- Execution
|
||||
|
||||
handle_favicon (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
@@ -32,44 +32,57 @@ feature {CMS_API} -- Module Initialization
|
||||
-- Initialize Current module with `api'.
|
||||
require
|
||||
is_enabled: is_enabled
|
||||
is_not_initialized: not is_initialized
|
||||
do
|
||||
-- Redefine to process specific module initialization.
|
||||
is_initialized := True
|
||||
ensure
|
||||
is_initialized: is_initialized
|
||||
end
|
||||
|
||||
feature -- Status
|
||||
|
||||
is_initialized: BOOLEAN
|
||||
-- Is Current module initialized?
|
||||
|
||||
feature {CMS_API} -- Access: API
|
||||
|
||||
module_api: detachable CMS_MODULE_API
|
||||
-- Eventual module api.
|
||||
require
|
||||
is_initialized: is_initialized
|
||||
do
|
||||
-- No API by default.
|
||||
end
|
||||
|
||||
feature {CMS_API} -- Module management
|
||||
|
||||
is_installed (api: CMS_API): BOOLEAN
|
||||
-- Is Current module installed?
|
||||
do
|
||||
Result := is_enabled
|
||||
-- FIXME: implement proper installation status.
|
||||
Result := attached api.storage.custom_value ("is_initialized", "module-" + name) as v and then v.is_case_insensitive_equal_general ("yes")
|
||||
end
|
||||
|
||||
install (api: CMS_API)
|
||||
require
|
||||
is_not_installed: not is_installed (api)
|
||||
do
|
||||
-- Not Yet Supported
|
||||
api.storage.set_custom_value ("is_initialized", "module-" + name, "yes")
|
||||
end
|
||||
|
||||
uninstall (api: CMS_API)
|
||||
require
|
||||
is_installed: is_installed (api)
|
||||
do
|
||||
-- Not Yet Supported
|
||||
api.storage.set_custom_value ("is_initialized", "module-" + name, "no")
|
||||
end
|
||||
|
||||
feature -- Router
|
||||
|
||||
router (a_api: CMS_API): WSF_ROUTER
|
||||
-- Router configuration.
|
||||
setup_router (a_router: WSF_ROUTER; a_api: CMS_API)
|
||||
-- Setup url dispatching for Current module.
|
||||
require
|
||||
is_enabled: is_enabled
|
||||
is_initialized: is_initialized
|
||||
deferred
|
||||
end
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
note
|
||||
description: "Summary description for {CMS_MODULE_API}."
|
||||
author: ""
|
||||
date: "$Date: 2015-02-13 14:54:27 +0100 (ven., 13 févr. 2015) $"
|
||||
revision: "$Revision: 96620 $"
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
note
|
||||
description: "Summary description for {CMS_MODULE_COLLECTION}."
|
||||
author: ""
|
||||
description: "Collection of CMS modules."
|
||||
date: "$Date: 2015-02-09 22:29:56 +0100 (lun., 09 févr. 2015) $"
|
||||
revision: "$Revision: 96596 $"
|
||||
|
||||
|
||||
@@ -19,15 +19,19 @@ feature -- Basic operations
|
||||
|
||||
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
-- Execute the filter
|
||||
local
|
||||
utf: UTF_CONVERTER
|
||||
do
|
||||
fixme ("Check if it's ok to add new fetures CMS_API.has_error:BOOLEAN and CMS_API.error_description.")
|
||||
debug ("refactor_fixme")
|
||||
fixme ("Check if it's ok to add new features CMS_API.has_error:BOOLEAN and CMS_API.error_description.")
|
||||
end
|
||||
if not api.has_error then
|
||||
api.logger.put_information (generator + ".execute with req: " + req.debug_output, Void)
|
||||
if attached req.raw_header_data as l_header_data then
|
||||
api.logger.put_debug (generator + ".execute with req header: " + l_header_data, Void)
|
||||
api.logger.put_debug (generator + ".execute with req header: " + utf.escaped_utf_32_string_to_utf_8_string_8 (l_header_data), Void)
|
||||
end
|
||||
if attached req.raw_input_data as l_input_data then
|
||||
api.logger.put_debug (generator + ".execute with req input: " + l_input_data, Void)
|
||||
api.logger.put_debug (generator + ".execute with req input: " + utf.escaped_utf_32_string_to_utf_8_string_8 (l_input_data), Void)
|
||||
end
|
||||
execute_next (req, res)
|
||||
else
|
||||
|
||||
@@ -36,6 +36,18 @@ feature -- Response helpers
|
||||
-- res.send (create {CMS_REDIRECTION_RESPONSE_MESSAGE}.make (a_location))
|
||||
end
|
||||
|
||||
send_bad_request_message (res: WSF_RESPONSE)
|
||||
-- Send via `res' a bad request response.
|
||||
do
|
||||
res.send (create {CMS_CUSTOM_RESPONSE_MESSAGE}.make ({HTTP_STATUS_CODE}.bad_request))
|
||||
end
|
||||
|
||||
send_not_found_message (res: WSF_RESPONSE)
|
||||
-- Send via `res' a bad request response.
|
||||
do
|
||||
res.send (create {CMS_CUSTOM_RESPONSE_MESSAGE}.make ({HTTP_STATUS_CODE}.not_found))
|
||||
end
|
||||
|
||||
send_access_denied_message (res: WSF_RESPONSE)
|
||||
-- Send via `res' an access denied response.
|
||||
do
|
||||
|
||||
@@ -70,14 +70,4 @@ feature -- Media Type
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Absolute Host
|
||||
|
||||
absolute_host (req: WSF_REQUEST; a_path:STRING): STRING
|
||||
do
|
||||
Result := req.absolute_script_url (a_path)
|
||||
if Result.last_index_of ('/', Result.count) = Result.count then
|
||||
Result.remove_tail (1)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -13,6 +13,7 @@ inherit
|
||||
feature -- Core
|
||||
|
||||
site_url: READABLE_STRING_8
|
||||
-- Absolute site URL of Current CMS site.
|
||||
deferred
|
||||
end
|
||||
|
||||
|
||||
52
src/service/path/cms_router.e
Normal file
52
src/service/path/cms_router.e
Normal file
@@ -0,0 +1,52 @@
|
||||
note
|
||||
description: "Specific version of WSF_ROUTER for CMS component."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_ROUTER
|
||||
|
||||
inherit
|
||||
WSF_ROUTER
|
||||
rename
|
||||
make as make_router
|
||||
redefine
|
||||
path_to_dispatch
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_api: CMS_API; a_capacity: INTEGER)
|
||||
do
|
||||
api := a_api
|
||||
make_router (a_capacity)
|
||||
end
|
||||
|
||||
api: CMS_API
|
||||
|
||||
feature {WSF_ROUTER_MAPPING} -- Dispatch helper
|
||||
|
||||
path_to_dispatch (req: WSF_REQUEST): READABLE_STRING_8
|
||||
-- Path used by the router, to apply url dispatching of request `req'.
|
||||
local
|
||||
l_path: STRING_8
|
||||
do
|
||||
create l_path.make_from_string (Precursor (req))
|
||||
if not l_path.is_empty and l_path [1] = '/' then
|
||||
l_path.remove_head (1)
|
||||
end
|
||||
Result := api.source_of_path_alias (l_path)
|
||||
if Result.is_empty then
|
||||
Result := "/"
|
||||
elseif Result [1] /= '/' then
|
||||
create l_path.make (Result.count + 1)
|
||||
l_path.append_character ('/')
|
||||
l_path.append (Result)
|
||||
Result := l_path
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -3,8 +3,8 @@ note
|
||||
Generic CMS Response.
|
||||
It builds the content to get process to render the output.
|
||||
]"
|
||||
date: "$Date: 2015-02-16 20:14:19 +0100 (lun., 16 févr. 2015) $"
|
||||
revision: "$Revision: 96643 $"
|
||||
date: "$Date: 2015-05-20 11:48:26 +0200 (mer., 20 mai 2015) $"
|
||||
revision: "$Revision: 97327 $"
|
||||
|
||||
deferred class
|
||||
CMS_RESPONSE
|
||||
@@ -29,6 +29,7 @@ feature {NONE} -- Initialization
|
||||
|
||||
initialize
|
||||
do
|
||||
initialize_site_url
|
||||
get_theme
|
||||
create menu_system.make
|
||||
initialize_block_region_settings
|
||||
@@ -36,6 +37,35 @@ feature {NONE} -- Initialization
|
||||
register_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
|
||||
|
||||
register_hooks
|
||||
local
|
||||
l_module: CMS_MODULE
|
||||
@@ -76,6 +106,35 @@ feature -- Access
|
||||
redirection: detachable READABLE_STRING_8
|
||||
-- Location for eventual redirection.
|
||||
|
||||
location: STRING_8
|
||||
-- Associated cms local location.
|
||||
do
|
||||
create Result.make_from_string (request.percent_encoded_path_info)
|
||||
if not Result.is_empty and then Result[1] = '/' then
|
||||
Result.remove_head (1)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Internationalization (i18n)
|
||||
|
||||
translation (a_text: READABLE_STRING_GENERAL; opts: detachable CMS_API_OPTIONS): STRING_32
|
||||
-- Translated text `a_text' according to expected context (lang, ...)
|
||||
-- and adapt according to options eventually set by `opts'.
|
||||
do
|
||||
to_implement ("Implement i18n support [2015-may]")
|
||||
Result := a_text.as_string_32
|
||||
end
|
||||
|
||||
formatted_string (a_text: READABLE_STRING_GENERAL; args: TUPLE): STRING_32
|
||||
-- Format `a_text' using arguments `args'.
|
||||
--| ex: formatted_string ("hello $1, see page $title.", ["bob", "contact"] -> "hello bob, see page contact"
|
||||
local
|
||||
l_formatter: CMS_STRING_FORMATTER
|
||||
do
|
||||
create l_formatter
|
||||
Result := l_formatter.formatted_string (a_text, args)
|
||||
end
|
||||
|
||||
feature -- API
|
||||
|
||||
api: CMS_API
|
||||
@@ -101,9 +160,11 @@ feature -- Module
|
||||
rp: PATH
|
||||
ut: FILE_UTILITIES
|
||||
do
|
||||
-- Check first in selected theme folder.
|
||||
rp := module_assets_theme_location (a_module)
|
||||
Result := rp.extended_path (a_resource)
|
||||
if not ut.file_path_exists (Result) then
|
||||
-- And if not found, look into site/modules/$a_module.name/.... folders.
|
||||
rp := module_assets_location (a_module)
|
||||
Result := rp.extended_path (a_resource)
|
||||
if not ut.file_path_exists (Result) then
|
||||
@@ -143,16 +204,13 @@ feature -- URL utilities
|
||||
end
|
||||
end
|
||||
|
||||
site_url: READABLE_STRING_8
|
||||
do
|
||||
Result := absolute_host (request, "")
|
||||
end
|
||||
site_url: IMMUTABLE_STRING_8
|
||||
-- Absolute site url.
|
||||
|
||||
base_url: detachable READABLE_STRING_8
|
||||
base_url: detachable IMMUTABLE_STRING_8
|
||||
-- Base url if any.
|
||||
--| Usually it is Void, but it could be
|
||||
--| /project/demo/
|
||||
--| FIXME: for now, no way to change that. Always at the root "/"
|
||||
|
||||
feature -- Access: CMS
|
||||
|
||||
@@ -163,7 +221,7 @@ feature -- Access: CMS
|
||||
|
||||
front_page_url: READABLE_STRING_8
|
||||
do
|
||||
Result := request.absolute_script_url ("/")
|
||||
Result := absolute_url ("/", Void)
|
||||
end
|
||||
|
||||
values: CMS_VALUE_TABLE
|
||||
@@ -185,12 +243,30 @@ feature -- Permission
|
||||
Result := user_has_permission (current_user (request), a_permission)
|
||||
end
|
||||
|
||||
has_permissions (a_permission_list: ITERABLE [READABLE_STRING_GENERAL]): BOOLEAN
|
||||
-- Does current user has any of the permissions `a_permission_list' ?
|
||||
do
|
||||
Result := user_has_permissions (current_user (request), a_permission_list)
|
||||
end
|
||||
|
||||
user_has_permission (a_user: detachable CMS_USER; a_permission: READABLE_STRING_GENERAL): BOOLEAN
|
||||
-- Does `a_user' has permission `a_permission' ?
|
||||
do
|
||||
Result := 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 -- Head customization
|
||||
|
||||
add_additional_head_line (s: READABLE_STRING_8; a_allow_duplication: BOOLEAN)
|
||||
@@ -768,9 +844,9 @@ feature -- Theme
|
||||
create l_info.make_default
|
||||
end
|
||||
if l_info.engine.is_case_insensitive_equal_general ("smarty") then
|
||||
create {SMARTY_CMS_THEME} theme.make (setup, l_info)
|
||||
create {SMARTY_CMS_THEME} theme.make (setup, l_info, site_url)
|
||||
else
|
||||
create {MISSING_CMS_THEME} theme.make (setup)
|
||||
create {MISSING_CMS_THEME} theme.make (setup, l_info, site_url)
|
||||
status_code := {HTTP_STATUS_CODE}.service_unavailable
|
||||
to_implement ("Check how to add the Retry-after, http://tools.ietf.org/html/rfc7231#section-6.6.4 and http://tools.ietf.org/html/rfc7231#section-7.1.3")
|
||||
end
|
||||
@@ -796,7 +872,7 @@ feature -- Generation
|
||||
lnk: CMS_LINK
|
||||
do
|
||||
-- Menu
|
||||
create {CMS_LOCAL_LINK} lnk.make ("Home", "/")
|
||||
create {CMS_LOCAL_LINK} lnk.make ("Home", "")
|
||||
lnk.set_weight (-10)
|
||||
add_to_primary_menu (lnk)
|
||||
invoke_menu_system_alter (menu_system)
|
||||
@@ -882,8 +958,8 @@ feature -- Generation
|
||||
end
|
||||
|
||||
-- Variables
|
||||
page.register_variable (request.absolute_script_url (""), "site_url")
|
||||
page.register_variable (request.absolute_script_url (""), "host") -- Same as `site_url'.
|
||||
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 current_user_name (request) as l_user then
|
||||
page.register_variable (l_user, "user")
|
||||
@@ -991,6 +1067,9 @@ feature -- Generation
|
||||
l_is_active: BOOLEAN
|
||||
do
|
||||
create qs.make_from_string (request.percent_encoded_path_info)
|
||||
if qs.starts_with ("/") then
|
||||
qs.remove_head (1)
|
||||
end
|
||||
l_is_active := qs.same_string (a_lnk.location)
|
||||
if not l_is_active then
|
||||
if attached request.query_string as l_query_string and then not l_query_string.is_empty then
|
||||
@@ -1064,8 +1143,8 @@ feature {NONE} -- Execution
|
||||
-- h.put_location (l_location)
|
||||
response.redirect_now (l_location)
|
||||
else
|
||||
-- h.put_location (request.absolute_script_url (l_location))
|
||||
response.redirect_now (request.absolute_script_url (l_location))
|
||||
-- h.put_location (request.absolute_url (l_location, Void))
|
||||
response.redirect_now (absolute_url (l_location, Void))
|
||||
end
|
||||
else
|
||||
h.put_header_object (header)
|
||||
|
||||
@@ -20,7 +20,7 @@ feature -- Generation
|
||||
|
||||
custom_prepare (page: CMS_HTML_PAGE)
|
||||
do
|
||||
page.register_variable (request.absolute_script_url (request.path_info), "request")
|
||||
page.register_variable (absolute_url (request.path_info, Void), "request")
|
||||
page.set_status_code ({HTTP_STATUS_CODE}.bad_request)
|
||||
page.register_variable (page.status_code.out, "code")
|
||||
end
|
||||
|
||||
@@ -20,7 +20,7 @@ feature -- Generation
|
||||
|
||||
custom_prepare (page: CMS_HTML_PAGE)
|
||||
do
|
||||
page.register_variable (request.absolute_script_url (request.path_info), "request")
|
||||
page.register_variable (absolute_url (request.path_info, Void), "request")
|
||||
page.set_status_code ({HTTP_STATUS_CODE}.forbidden)
|
||||
page.register_variable (page.status_code.out, "code")
|
||||
end
|
||||
|
||||
@@ -20,7 +20,7 @@ feature -- Generation
|
||||
|
||||
custom_prepare (page: CMS_HTML_PAGE)
|
||||
do
|
||||
page.register_variable (request.absolute_script_url (request.path_info), "request")
|
||||
page.register_variable (absolute_url (request.path_info, Void), "request")
|
||||
page.set_status_code ({HTTP_STATUS_CODE}.internal_server_error)
|
||||
page.register_variable (page.status_code.out, "code")
|
||||
end
|
||||
|
||||
@@ -20,7 +20,7 @@ feature -- Generation
|
||||
|
||||
custom_prepare (page: CMS_HTML_PAGE)
|
||||
do
|
||||
page.register_variable (request.absolute_script_url (request.path_info), "request")
|
||||
page.register_variable (absolute_url (request.path_info, Void), "request")
|
||||
page.set_status_code ({HTTP_STATUS_CODE}.not_found)
|
||||
page.register_variable (page.status_code.out, "code")
|
||||
end
|
||||
|
||||
@@ -20,7 +20,7 @@ feature -- Generation
|
||||
|
||||
custom_prepare (page: CMS_HTML_PAGE)
|
||||
do
|
||||
page.register_variable (request.absolute_script_url (request.path_info), "request")
|
||||
page.register_variable (absolute_url (request.path_info, Void), "request")
|
||||
page.set_status_code ({HTTP_STATUS_CODE}.not_implemented)
|
||||
page.register_variable (page.status_code.out, "code")
|
||||
end
|
||||
|
||||
64
src/service/response/message/cms_custom_response_message.e
Normal file
64
src/service/response/message/cms_custom_response_message.e
Normal file
@@ -0,0 +1,64 @@
|
||||
note
|
||||
description: "Custom cms response message."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_CUSTOM_RESPONSE_MESSAGE
|
||||
|
||||
inherit
|
||||
CMS_RESPONSE_MESSAGE
|
||||
redefine
|
||||
send_payload_to
|
||||
end
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_code: INTEGER)
|
||||
-- Set `status_code' to `a_code'.
|
||||
require
|
||||
a_code_valid: a_code > 0
|
||||
do
|
||||
initialize
|
||||
status_code := a_code
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
payload: detachable READABLE_STRING_8
|
||||
-- Optional payload.
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_status_code (a_code: INTEGER)
|
||||
-- Set `status_code' to `a_code'.
|
||||
require
|
||||
a_code_valid: a_code > 0
|
||||
do
|
||||
status_code := a_code
|
||||
end
|
||||
|
||||
set_payload (s: detachable READABLE_STRING_8)
|
||||
-- Set `payload' to `s'.
|
||||
do
|
||||
if s /= Void then
|
||||
payload := s
|
||||
header.put_content_length (s.count)
|
||||
else
|
||||
end
|
||||
end
|
||||
|
||||
feature {WSF_RESPONSE} -- Output
|
||||
|
||||
send_payload_to (res: WSF_RESPONSE)
|
||||
-- Send payload data to response `res'.
|
||||
do
|
||||
if attached payload as s then
|
||||
res.put_string (s)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
284
src/support/cms_pagination_generator.e
Normal file
284
src/support/cms_pagination_generator.e
Normal file
@@ -0,0 +1,284 @@
|
||||
note
|
||||
description: "Pagination class to generate html pagination links and header summary."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_PAGINATION_GENERATOR
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_resource: READABLE_STRING_8; a_count: NATURAL_64; a_page_size: NATURAL)
|
||||
-- Create an object with a pages of size `a_page_size'.
|
||||
-- If `a_page_size' is zero, use default pagination size.
|
||||
require
|
||||
a_page_size > 0
|
||||
do
|
||||
create resource.make (a_resource)
|
||||
set_page_size (a_page_size)
|
||||
set_upper (a_count)
|
||||
set_current_page_index (1)
|
||||
|
||||
maximum_ith_page_links := 7
|
||||
page_parameter_id := "page"
|
||||
size_parameter_id := "size"
|
||||
set_first_text_id ("<<")
|
||||
set_prev_text_id ("<")
|
||||
set_next_text_id (">")
|
||||
set_last_text_id (">>")
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
resource: URI_TEMPLATE
|
||||
-- Resource associated with current pager.
|
||||
|
||||
page_size: NATURAL
|
||||
-- Number of items per page.
|
||||
|
||||
upper: NATURAL_64
|
||||
-- number of items.
|
||||
-- if zero, no upper limit.
|
||||
|
||||
current_page_index: INTEGER
|
||||
-- Current page index.
|
||||
|
||||
current_page_offset: NATURAL_64
|
||||
-- Lower index - 1 for current page.
|
||||
do
|
||||
if current_page_index > 1 then
|
||||
Result := (current_page_index - 1).to_natural_32 * page_size
|
||||
else
|
||||
Result := 0
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
has_upper_limit: BOOLEAN
|
||||
-- Upper limit known?
|
||||
do
|
||||
Result := upper > 0
|
||||
end
|
||||
|
||||
pages_count: INTEGER
|
||||
-- Number of pages.
|
||||
-- If upper is
|
||||
require
|
||||
has_upper_limit: has_upper_limit
|
||||
do
|
||||
Result := (upper // page_size.as_natural_64).to_integer_32
|
||||
if upper \\ page_size.to_natural_64 > 0 then
|
||||
Result := Result + 1
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Parameters
|
||||
|
||||
page_parameter_id: STRING
|
||||
-- Parameter id for page value.
|
||||
|
||||
size_parameter_id: STRING
|
||||
-- Parameter id for size value.
|
||||
|
||||
maximum_ith_page_links: INTEGER
|
||||
-- Maximum number of numeric ith page link.
|
||||
-- ex: max = 6 gives "1 2 3 4 5 6 ... > >>".
|
||||
|
||||
label_first: IMMUTABLE_STRING_32
|
||||
label_previous: IMMUTABLE_STRING_32
|
||||
label_next: IMMUTABLE_STRING_32
|
||||
label_last: IMMUTABLE_STRING_32
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_page_size (a_size: NATURAL)
|
||||
-- Set `page_size' to `a_size'.
|
||||
do
|
||||
page_size := a_size
|
||||
end
|
||||
|
||||
set_upper (a_upper: NATURAL_64)
|
||||
-- Set pages count, or upper limit `upper' to `a_size'.
|
||||
do
|
||||
upper := a_upper
|
||||
end
|
||||
|
||||
set_current_page_index (a_page_index: like current_page_index)
|
||||
-- Set Current page index to `a_page_index'.
|
||||
do
|
||||
current_page_index := a_page_index
|
||||
end
|
||||
|
||||
set_page_parameter_id (a_id: READABLE_STRING_8)
|
||||
-- Set "page" query parameter to `a_id'.
|
||||
do
|
||||
page_parameter_id := a_id
|
||||
end
|
||||
|
||||
set_size_parameter_id (a_id: READABLE_STRING_8)
|
||||
-- Set "size" query parameter to `a_id'.
|
||||
do
|
||||
size_parameter_id := a_id
|
||||
end
|
||||
|
||||
get_setting_from_request (req: WSF_REQUEST)
|
||||
-- Get various pager related settings from request `req' query paramenters.
|
||||
-- Using `page_parameter_id' and `size_parameter_id' value for parameter names.
|
||||
do
|
||||
-- Size
|
||||
if
|
||||
attached {WSF_STRING} req.query_parameter (size_parameter_id) as l_size and then
|
||||
attached l_size.value as l_value and then
|
||||
l_value.is_natural
|
||||
then
|
||||
set_page_size (l_value.to_natural_32)
|
||||
else
|
||||
-- Keep default size
|
||||
end
|
||||
|
||||
-- Page
|
||||
if
|
||||
attached {WSF_STRING} req.query_parameter (page_parameter_id) as l_page and then
|
||||
l_page.is_integer
|
||||
then
|
||||
set_current_page_index (l_page.integer_value)
|
||||
else
|
||||
set_current_page_index (1)
|
||||
end
|
||||
end
|
||||
|
||||
set_first_text_id (s: READABLE_STRING_GENERAL)
|
||||
-- Set label for "First" link to `s'.
|
||||
-- default: "<<"
|
||||
do
|
||||
create label_first.make_from_string_general (s)
|
||||
end
|
||||
|
||||
set_prev_text_id (s: READABLE_STRING_GENERAL)
|
||||
-- Set label for "Prev" link to `s'.
|
||||
-- default: "<"
|
||||
do
|
||||
create label_previous.make_from_string_general (s)
|
||||
end
|
||||
|
||||
set_next_text_id (s: READABLE_STRING_GENERAL)
|
||||
-- Set label for "Next" link to `s'.
|
||||
-- default: ">"
|
||||
do
|
||||
create label_next.make_from_string_general (s)
|
||||
end
|
||||
|
||||
set_last_text_id (s: READABLE_STRING_GENERAL)
|
||||
-- Set label for "Last" link to `s'.
|
||||
-- default: ">>"
|
||||
do
|
||||
create label_last.make_from_string_general (s)
|
||||
end
|
||||
|
||||
set_maximum_ith_page_links (nb: INTEGER)
|
||||
-- Set `maximum_ith_page_links' to `nb'.
|
||||
do
|
||||
maximum_ith_page_links := nb
|
||||
end
|
||||
|
||||
feature -- Conversion
|
||||
|
||||
pagination_links: ARRAYED_LIST [CMS_LOCAL_LINK]
|
||||
-- CMS local links related to Current paginations.
|
||||
local
|
||||
lnk: CMS_LOCAL_LINK
|
||||
tb: HASH_TABLE [detachable ANY, STRING_8]
|
||||
curr, max: INTEGER
|
||||
i,j: INTEGER
|
||||
do
|
||||
create Result.make (maximum_ith_page_links)
|
||||
|
||||
curr := current_page_index
|
||||
if has_upper_limit then
|
||||
max := pages_count
|
||||
else
|
||||
max := curr + page_size.to_integer_32
|
||||
end
|
||||
|
||||
create tb.make (2)
|
||||
tb.force (page_size, size_parameter_id)
|
||||
tb.force (1, page_parameter_id)
|
||||
if curr > 1 then
|
||||
create lnk.make (label_first, resource.expanded_string (tb))
|
||||
Result.force (lnk)
|
||||
end
|
||||
|
||||
if curr > 1 then
|
||||
tb.force (curr - 1, "page")
|
||||
create lnk.make (label_previous, resource.expanded_string (tb))
|
||||
Result.force (lnk)
|
||||
end
|
||||
from
|
||||
if curr >= maximum_ith_page_links // 2 then
|
||||
i := curr - (maximum_ith_page_links // 2)
|
||||
else
|
||||
i := 1
|
||||
end
|
||||
j := 0
|
||||
until
|
||||
j >= maximum_ith_page_links or (has_upper_limit and then i > max)
|
||||
loop
|
||||
tb.force (i, "page")
|
||||
create lnk.make (i.out, resource.expanded_string (tb))
|
||||
lnk.set_is_active (i = curr)
|
||||
Result.force (lnk)
|
||||
j := j + 1
|
||||
i := i + 1
|
||||
end
|
||||
if not has_upper_limit or else i < max then
|
||||
tb.force (i, "page")
|
||||
create lnk.make ("...", resource.expanded_string (tb))
|
||||
Result.force (lnk)
|
||||
end
|
||||
|
||||
if curr < max then
|
||||
tb.force (curr + 1, "page")
|
||||
create lnk.make (label_next, resource.expanded_string (tb))
|
||||
Result.force (lnk)
|
||||
end
|
||||
|
||||
if upper > 0 and curr /= max then
|
||||
tb.force (max, "page")
|
||||
create lnk.make (label_last, resource.expanded_string (tb))
|
||||
Result.force (lnk)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Convertion
|
||||
|
||||
append_to_html (a_response: CMS_RESPONSE; a_output: STRING)
|
||||
-- Append html pager to `a_output' in the context of `a_response'.
|
||||
-- note: First, [Prev], [Next], Last.
|
||||
local
|
||||
lnk: CMS_LOCAL_LINK
|
||||
do
|
||||
a_output.append ("<ul class=%"pagination%">%N")
|
||||
across
|
||||
pagination_links as ic
|
||||
loop
|
||||
lnk := ic.item
|
||||
if lnk.is_active then
|
||||
a_output.append ("<li class=%"active%">")
|
||||
elseif lnk.title.same_string (label_previous) then
|
||||
a_output.append ("<li class=%"previous%">")
|
||||
elseif lnk.title.same_string (label_next) then
|
||||
a_output.append ("<li class=%"next%">")
|
||||
else
|
||||
a_output.append ("<li>")
|
||||
end
|
||||
a_output.append (a_response.link (lnk.title, lnk.location, Void))
|
||||
a_output.append ("</li>")
|
||||
end
|
||||
a_output.append ("</ul>")
|
||||
end
|
||||
|
||||
end
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user