Compare commits

..

32 Commits

Author SHA1 Message Date
Jocelyn Fiat
53491274dc Merged CMS based on concurrent EWF (i.e ewf_v1) with blog branch. 2015-06-15 11:27:44 +02:00
21800e71d3 Removed obsolete calls.
Updated code to make it clear what is the resource, and what is the associated module resource path.
2015-06-11 23:03:34 +02:00
0fc1cb68ad Apply recent changes from EWF v1 2015-06-10 18:39:41 +02:00
0b8bee3404 favor EiffelThread for now, while waiting for SCOOP to be fully ready. 2015-06-10 11:06:58 +02:00
53a602d33c Removed CMS_SERVICE
Updated install.bat script
2015-06-10 09:43:04 +02:00
5578a9e622 Adapted ROC CMS to concurrent EWF.
Revisited the shared logger to reduced number of useless calls.
2015-06-09 19:42:37 +02:00
b8cfff487a Removed dependency from pagination to cms_data_query_parameters
TODO: review and fix any NATURAL_64 truncation.
2015-06-02 15:56:27 +02:00
af8f410684 Updated the CMS pagination component.
Harmonized count type to NATURAL_64 for recent_nodes (more to do later).
Fix get is active code.
2015-06-02 15:39:08 +02:00
cede341301 Merged remote-tracking branch 'jvelilla/roc_pg' into pagination
Renamed pagination related classes, and moved them to cms library under "support" cluster.
2015-05-31 22:43:19 +02:00
70d53b3ef1 Provide a default CMS_MODULE.is_installed: BOOLEAN implementation based on storage of custom value.
Now use CMS_MODULE.is_initialized: BOOLEAN as precondition of many routines.
Instantiation of node storage is now done in NODE_MODULE and not any more in CMS_NODE_API.
CMS_NODE_API can be instantiated only by NODE_MODULE.
2015-05-29 19:20:31 +02:00
jvelilla
f056b43ddc Updated CMS PAGINATION with the last Jocelyn's suggestion.
Added a node pagination helper, to build the html links and header related to
pagination.
2015-05-29 09:25:28 -03:00
jvelilla
957ca96bc5 Updated code based on comments. 2015-05-27 11:26:49 -03:00
jvelilla
ad9dd01f22 Update based on comments 2015-05-26 20:25:45 -03:00
jvelilla
323ac598d0 Updated code based on comments 2015-05-26 20:24:05 -03:00
b77c5cd93c Added abstraction of cms storage on file system. (mostly helpers features). 2015-05-22 23:04:09 +02:00
77f52388c1 Improved site_url and base_url interface and initialization.
Added CMS_CUSTOM_RESPONSE_MESSAGE interface to send easily simple response message.
Updated CMS_RESPONSE to use CMS_CUSTOM_RESPONSE_MESSAGE
2015-05-22 22:37:18 +02:00
jvelilla
306b39ab78 Updated code based on Jocelyn's suggestions. 2015-05-21 16:46:06 -03:00
jvelilla
53f3162b4a Inital page builder implementation to add paging support to cms_nodes. 2015-05-19 18:40:57 -03:00
036013a0a2 Use CMS local location (i.e relative) and not url for cms local links. 2015-05-19 22:02:56 +02:00
50da24d1af Added support for base_url (i.e the CMS can be hosted on the root, or sub folder).
Local paths are relative to cms site url (i.e no starting slash).
Favor CMS_RESPONSE.absolute_url and url .. instead of using directly WSF_REQUEST.absolute_script_url and script_url.
Handled unicode truncation issue for logger.
Code cleaning.
2015-05-19 13:50:39 +02:00
91457080fd Added support for base_url (i.e the CMS can be hosted on the root, or sub folder).
Local paths are relative to cms site url (i.e no starting slash).
Favor CMS_RESPONSE.absolute_url and url .. instead of using directly WSF_REQUEST.absolute_script_url and script_url.
Handled unicode truncation issue for logger.
Code cleaning.
2015-05-19 13:44:08 +02:00
51699f3bd3 updated db schema 2015-05-19 12:25:16 +02:00
jvelilla
77bb1fe123 Merge branch 'jvelilla-roc_trash' 2015-05-17 12:14:01 -03:00
jvelilla
e4e2d662b8 Renaming revert string to restore. 2015-05-15 13:10:12 -03:00
jvelilla
f0668e660e refactor rename NODE_HANLDER.do_restore instead of do_revert. 2015-05-15 11:34:21 -03:00
jvelilla
68fb21a4c1 Fixed typo 2015-05-15 11:01:59 -03:00
jvelilla
3b90d522f9 Refactor rename: using trashed_nodes instead of trash_nodes. 2015-05-15 10:44:04 -03:00
jvelilla
1c59a65983 Updated code based on Jocelyn suggestions. 2015-05-15 09:40:18 -03:00
jvelilla
9fbadac7ac Added trash feature: Remove or revert a node.
Added Handler to show the current trash nodes for a given user.
An admin can see all the trash nodes.
Updated storage to handle trash and revert nodes.
2015-05-14 11:07:15 -03:00
jvelilla
57bf5ad0dc Added delete option as a tab only if the current user has permissions to delete the
current resource
2015-05-13 15:17:19 -03:00
jvelilla
988f32c6c4 Merge branch 'master' of https://github.com/EiffelWebFramework/ROC into roc_trash
Conflicts:
	modules/node/handler/node_form_response.e
2015-05-13 12:38:25 -03:00
jvelilla
44d14c4100 delete with tabs 2015-05-13 12:27:02 -03:00
75 changed files with 2069 additions and 512 deletions

View File

@@ -24,6 +24,7 @@
<library name="smarty" location="$ISE_LIBRARY\contrib\library\text\template\smarty\smarty-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="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="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" 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_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"/> <library name="wsf_html" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf_html\wsf_html-safe.ecf" readonly="false"/>

View File

@@ -24,6 +24,7 @@
<library name="smarty" location="$ISE_LIBRARY\contrib\library\text\template\smarty\smarty.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="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="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" 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_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"/> <library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension.ecf" readonly="false"/>

View File

@@ -7,10 +7,10 @@
<exclude>/CVS$</exclude> <exclude>/CVS$</exclude>
<exclude>/.svn$</exclude> <exclude>/.svn$</exclude>
</file_rule> </file_rule>
<option warning="true" full_class_checking="false" is_attached_by_default="true" void_safety="all" syntax="transitional"> <option debug="true" 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"/> <debug name="dbglog" enabled="true"/>
</option> </option>
<setting name="concurrency" value="none"/> <setting name="concurrency" value="thread"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/> <library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="cms" location="..\..\cms-safe.ecf" readonly="false"/> <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_app_env" location="..\..\library\app_env\app_env-safe.ecf" readonly="false"/>
@@ -19,21 +19,39 @@
<library name="cms_demo_module" location="modules\demo\cms_demo_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_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="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="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" 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_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension-safe.ecf" readonly="false"/>
</target> </target>
<target name="demo_any" extends="common"> <target name="demo_any" extends="common">
<root class="EWF_ROC_SERVER" feature="make_and_launch"/> <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="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="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="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="launcher" location=".\launcher\any\" recursive="true"/>
<cluster name="src" location=".\src\" recursive="true"/> <cluster name="src" location=".\src\" recursive="true"/>
</target> </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"> <target name="demo_nino" extends="common">
<root class="EWF_ROC_SERVER" feature="make_and_launch"/> <root class="EWF_ROC_SERVER" feature="make_and_launch"/>
<setting name="concurrency" value="none"/> <setting name="concurrency" value="none"/>
@@ -43,16 +61,18 @@
</target> </target>
<target name="demo_cgi" extends="common"> <target name="demo_cgi" extends="common">
<root class="EWF_ROC_SERVER" feature="make_and_launch"/> <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"/> <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="launcher" location=".\launcher\default\" recursive="true"/>
<cluster name="src" location=".\src\" recursive="true"/> <cluster name="src" location=".\src\" recursive="true"/>
</target> </target>
<target name="demo_libfcgi" extends="common"> <target name="demo_libfcgi" extends="common">
<root class="EWF_ROC_SERVER" feature="make_and_launch"/> <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"/> <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="launcher" location=".\launcher\default\" recursive="true"/>
<cluster name="src" location=".\src\" recursive="true"/> <cluster name="src" location=".\src\" recursive="true"/>
</target> </target>
<target name="demo" extends="demo_nino"> <target name="demo" extends="demo_standalone">
</target> </target>
</system> </system>

View File

@@ -8,10 +8,10 @@ note
revision: "$Revision: 36 $" revision: "$Revision: 36 $"
class class
APPLICATION_LAUNCHER APPLICATION_LAUNCHER [G -> WSF_EXECUTION create make end]
inherit inherit
APPLICATION_LAUNCHER_I APPLICATION_LAUNCHER_I [G]
feature -- Custom feature -- Custom

View File

@@ -10,24 +10,28 @@ note
revision: "$Revision: 36 $" revision: "$Revision: 36 $"
deferred class deferred class
APPLICATION_LAUNCHER_I APPLICATION_LAUNCHER_I [G -> WSF_EXECUTION create make end]
inherit inherit
SHARED_EXECUTION_ENVIRONMENT SHARED_EXECUTION_ENVIRONMENT
feature -- Execution feature -- Execution
launch (a_service: WSF_SERVICE; opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) launch (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
local local
nature: like launcher_nature nature: like launcher_nature
do do
nature := launcher_nature nature := launcher_nature
if nature = Void or else nature = nature_nino then if nature = Void then
launch_nino (a_service, opts) launch_standalone (opts)
elseif nature = nature_standalone then
launch_standalone (opts)
elseif nature = nature_nino then
launch_nino (opts)
elseif nature = nature_cgi then elseif nature = nature_cgi then
launch_cgi (a_service, opts) launch_cgi (opts)
elseif nature = nature_libfcgi then elseif nature = nature_libfcgi then
launch_libfcgi (a_service, opts) launch_libfcgi (opts)
else else
-- bye bye -- bye bye
(create {EXCEPTIONS}).die (-1) (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. --| and we could use WSF_DEFAULT_SERVICE_LAUNCHER to configure this at compilation time.
local local
p: PATH p: PATH
l_entry_name: READABLE_STRING_32
ext: detachable READABLE_STRING_32 ext: detachable READABLE_STRING_32
do do
create p.make_from_string (execution_environment.arguments.command_name) create p.make_from_string (execution_environment.arguments.command_name)
@@ -51,6 +54,9 @@ feature {NONE} -- Access
ext := l_entry.extension ext := l_entry.extension
end end
if ext /= Void then if ext /= Void then
if ext.same_string (nature_standalone) then
Result := nature_standalone
end
if ext.same_string (nature_nino) then if ext.same_string (nature_nino) then
Result := nature_nino Result := nature_nino
end end
@@ -61,39 +67,58 @@ feature {NONE} -- Access
Result := nature_libfcgi Result := nature_libfcgi
end end
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 end
feature {NONE} -- nino feature {NONE} -- nino
nature_nino: STRING = "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 local
launcher: WSF_NINO_SERVICE_LAUNCHER launcher: WSF_NINO_SERVICE_LAUNCHER [G]
do do
create launcher.make_and_launch (a_service, opts) create launcher.make_and_launch (opts)
end end
feature {NONE} -- cgi feature {NONE} -- cgi
nature_cgi: STRING = "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 local
launcher: WSF_CGI_SERVICE_LAUNCHER launcher: WSF_CGI_SERVICE_LAUNCHER [G]
do do
create launcher.make_and_launch (a_service, opts) create launcher.make_and_launch (opts)
end end
feature {NONE} -- libfcgi feature {NONE} -- libfcgi
nature_libfcgi: STRING = "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 local
launcher: WSF_LIBFCGI_SERVICE_LAUNCHER launcher: WSF_LIBFCGI_SERVICE_LAUNCHER [G]
do 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 end

View File

@@ -8,10 +8,10 @@ note
revision: "$Revision: 36 $" revision: "$Revision: 36 $"
class class
APPLICATION_LAUNCHER APPLICATION_LAUNCHER [G -> WSF_EXECUTION create make end]
inherit inherit
APPLICATION_LAUNCHER_I APPLICATION_LAUNCHER_I [G]
feature -- Custom feature -- Custom

View File

@@ -10,15 +10,15 @@ note
revision: "$Revision: 96596 $" revision: "$Revision: 96596 $"
deferred class deferred class
APPLICATION_LAUNCHER_I APPLICATION_LAUNCHER_I [G -> WSF_EXECUTION create make end]
feature -- Execution feature -- Execution
launch (a_service: WSF_SERVICE; opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) launch (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
local local
launcher: WSF_DEFAULT_SERVICE_LAUNCHER launcher: WSF_DEFAULT_SERVICE_LAUNCHER [G]
do do
create {WSF_DEFAULT_SERVICE_LAUNCHER} launcher.make_and_launch (a_service, opts) create launcher.make_and_launch (opts)
end end
end end

View File

@@ -14,7 +14,6 @@ inherit
redefine redefine
register_hooks, register_hooks,
initialize, initialize,
is_installed,
install, install,
blog_api blog_api
end end
@@ -61,12 +60,6 @@ feature {CMS_API} -- Module Initialization
feature {CMS_API} -- Module management 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) install (api: CMS_API)
local local
sql: STRING sql: STRING
@@ -86,7 +79,7 @@ CREATE TABLE "blog_post_nodes"(
api.logger.put_error ("Could not initialize database for blog module", generating_type) api.logger.put_error ("Could not initialize database for blog module", generating_type)
end end
end end
api.storage.set_custom_value ("is_initialized", "module-" + name, "yes") Precursor (api)
end end
end end
@@ -151,7 +144,7 @@ feature -- Hooks
lnk: CMS_LOCAL_LINK lnk: CMS_LOCAL_LINK
do do
-- Add the link to the blog to the main menu -- Add the link to the blog to the main menu
create lnk.make ("Blogs", "/blogs/") create lnk.make ("Blogs", "blogs/")
a_menu_system.primary_menu.extend (lnk) a_menu_system.primary_menu.extend (lnk)
end end
end end

View File

@@ -110,9 +110,9 @@ feature -- Hooks
if a_block_id.is_case_insensitive_equal_general ("demo-info") then if a_block_id.is_case_insensitive_equal_general ("demo-info") then
if a_response.request.request_uri.starts_with ("/demo/") then if a_response.request.request_uri.starts_with ("/demo/") then
create m.make_with_title (a_block_id, "Demo", 2) 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) m.extend (lnk)
create lnk.make ("/demo/123", a_response.url ("/demo/123", Void)) create lnk.make ("demo: 123", "demo/123")
m.extend (lnk) m.extend (lnk)
create mb.make (m) create mb.make (m)
a_response.add_block (mb, "sidebar_second") a_response.add_block (mb, "sidebar_second")
@@ -125,7 +125,7 @@ feature -- Hooks
lnk: CMS_LOCAL_LINK lnk: CMS_LOCAL_LINK
-- perms: detachable ARRAYED_LIST [READABLE_STRING_8] -- perms: detachable ARRAYED_LIST [READABLE_STRING_8]
do do
create lnk.make ("Demo", "/demo/") create lnk.make ("Demo", "demo/")
a_menu_system.primary_menu.extend (lnk) a_menu_system.primary_menu.extend (lnk)
end end
@@ -137,8 +137,8 @@ feature -- Handler
r: NOT_IMPLEMENTED_ERROR_CMS_RESPONSE r: NOT_IMPLEMENTED_ERROR_CMS_RESPONSE
do do
create r.make (req, res, a_api) create r.make (req, res, a_api)
r.set_main_content ("NODE module does not yet implement %"" + req.path_info + "%" ...") r.set_main_content ("DEMO module does not yet implement %"" + req.path_info + "%" ...")
r.add_error_message ("NODE Module: not yet implemented") r.add_error_message ("DEMO Module: not yet implemented")
r.execute r.execute
end end

View File

@@ -23,7 +23,8 @@
"server": "localhost" "server": "localhost"
}, },
"logger": { "logger": {
"level":"debug", "level":"error",
"type":"stderr",
"backup_count":"4" "backup_count":"4"
}, },
"server": { "server": {

View File

@@ -15,7 +15,7 @@ CREATE TABLE "logs"(
CREATE TABLE "custom_values"( CREATE TABLE "custom_values"(
"type" VARCHAR(255) NOT NULL, "type" VARCHAR(255) NOT NULL,
"name" VARCHAR(255) NOT NULL, "name" VARCHAR(255) NOT NULL,
"value" VARCHAR(255) NOT NULL "value" TEXT
); );
CREATE TABLE "path_aliases"( CREATE TABLE "path_aliases"(

View File

@@ -1,13 +1,13 @@
BEGIN; BEGIN;
CREATE TABLE "nodes" ( CREATE TABLE "nodes" (
"nid" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK("nid">=0), "nid" INTEGER NOT NULL CHECK("nid" > 0) PRIMARY KEY AUTOINCREMENT UNIQUE,
"revision" INTEGER, "revision" INTEGER,
"type" TEXT NOT NULL, "type" TEXT NOT NULL,
"title" VARCHAR(255) NOT NULL, "title" VARCHAR(255) NOT NULL,
"summary" TEXT, "summary" TEXT,
"content" MEDIUMTEXT NOT NULL, "content" TEXT,
"format" VARCHAR(255), "format" VARCHAR(128),
"author" INTEGER, "author" INTEGER,
"publish" DATETIME, "publish" DATETIME,
"created" DATETIME NOT NULL, "created" DATETIME NOT NULL,

Binary file not shown.

After

Width:  |  Height:  |  Size: 994 B

View File

@@ -4,14 +4,14 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<!-- EWF CMS --> <!-- EWF CMS -->
<link rel="stylesheet" href="{$site_url/}/theme/css/style.css"> <link rel="stylesheet" href="{$site_url/}theme/css/style.css">
<link rel="stylesheet" href="{$site_url/}/theme/css/node.css"> <link rel="stylesheet" href="{$site_url/}theme/css/node.css">
<!-- CMS Blog Module --> <!-- CMS Blog Module -->
<link rel="stylesheet" href="{$site_url/}/theme/css/blog.css"> <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/jquery-1.10.2.min.js"></script>
<script src="{$site_url/}/theme/js/roc_auth.js"></script> <script src="{$site_url/}theme/js/roc_auth.js"></script>
<!-- bootstrap framework --> <!-- bootstrap framework -->
<!-- Latest compiled and minified CSS --> <!-- Latest compiled and minified CSS -->

View File

@@ -16,11 +16,6 @@ inherit
initialize initialize
end end
WSF_SERVICE
redefine
execute
end
REFACTORING_HELPER REFACTORING_HELPER
SHARED_EXECUTION_ENVIRONMENT SHARED_EXECUTION_ENVIRONMENT
@@ -40,37 +35,26 @@ feature {NONE} -- Initialization
initialize initialize
-- Initialize current service. -- Initialize current service.
local
env: CMS_ENVIRONMENT
do do
-- Launcher
Precursor Precursor
create {WSF_SERVICE_LAUNCHER_OPTIONS_FROM_INI} service_options.make_from_file ("demo.ini") create {WSF_SERVICE_LAUNCHER_OPTIONS_FROM_INI} service_options.make_from_file ("demo.ini")
create env.make_default
-- CMS initialize_logger (env)
initialize_cms
end
feature -- Service
cms_service: CMS_SERVICE
-- cms service.
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
do
cms_service.execute (req, res)
end end
feature {NONE} -- Launch operation 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 local
l_retry: BOOLEAN l_retry: BOOLEAN
l_message: STRING l_message: STRING
do do
if not l_retry then if not l_retry then
write_debug_log (generator + ".launch") launcher.launch (opts)
launcher.launch (a_service, opts)
else else
-- error hanling. -- error hanling.
create l_message.make (1024) 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 ("The application crash without available information")
l_message.append ("%N%N") l_message.append ("%N%N")
end end
-- notify shutdown -- send email shutdown
write_debug_log (generator + ".launch shutdown")
end end
rescue rescue
l_retry := True l_retry := True
retry retry
end 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 end

View 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

View File

@@ -30,6 +30,7 @@ feature -- Initialization
backup_count := 4 backup_count := 4
level := Log_debug level := Log_debug
location := Void location := Void
type := {STRING_32} "null"
ensure then ensure then
backup_count_set: backup_count = 4 backup_count_set: backup_count = 4
level_set: level = Log_debug level_set: level = Log_debug
@@ -48,6 +49,9 @@ feature -- Access
level: INTEGER level: INTEGER
-- Logger level. -- Logger level.
type: IMMUTABLE_STRING_32
-- Type of logging.
feature -- Element Change feature -- Element Change
set_location (a_location: detachable PATH) set_location (a_location: detachable PATH)
@@ -65,6 +69,15 @@ feature -- Element Change
set_location (create {PATH}.make_from_string (a_location)) set_location (create {PATH}.make_from_string (a_location))
end 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 (a_backup: NATURAL)
-- Set backup_count to `a_backup'. -- Set backup_count to `a_backup'.
do do

View File

@@ -32,7 +32,7 @@ feature {NONE} -- Initialization
create log.make create log.make
end end
make_with_environment (app: APPLICATION_ENVIRONMENT) make_with_environment (app: separate APPLICATION_ENVIRONMENT)
-- Initialize a logger object with an application environment `app'. -- Initialize a logger object with an application environment `app'.
do do
make make
@@ -49,7 +49,7 @@ feature {NONE} -- Initialization
feature -- Change feature -- Change
apply_environment (app: APPLICATION_ENVIRONMENT) apply_environment (app: separate APPLICATION_ENVIRONMENT)
do do
initialize_logger (app, log) initialize_logger (app, log)
end end
@@ -58,75 +58,107 @@ feature {NONE} -- Internal
log: LOGGING_FACILITY log: LOGGING_FACILITY
feature -- Settings
level: INTEGER
feature -- Logging 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_information (a_message: separate READABLE_STRING_8)
-- Put message `a_message' to the log at information level. -- Put message `a_message' to the log at information level.
do do
if level >= log_information then
log.write_information (create {STRING}.make_from_separate (a_message)) log.write_information (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
log.write_error (create {STRING}.make_from_separate (a_message))
end end
put_warning (a_message: separate READABLE_STRING_8) put_warning (a_message: separate READABLE_STRING_8)
-- Put message `a_message' to the log at warning level. -- Put message `a_message' to the log at warning level.
do do
if level >= log_warning then
log.write_warning (create {STRING}.make_from_separate (a_message)) log.write_warning (create {STRING}.make_from_separate (a_message))
end 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_critical (a_message: separate READABLE_STRING_8)
-- Put message `a_message' to the log at critical level. -- Put message `a_message' to the log at critical level.
do do
if level >= log_critical then
log.write_critical (create {STRING}.make_from_separate (a_message)) log.write_critical (create {STRING}.make_from_separate (a_message))
end end
end
put_alert (a_message: separate READABLE_STRING_8) put_alert (a_message: separate READABLE_STRING_8)
-- Put message `a_message' to the log at alert level. -- Put message `a_message' to the log at alert level.
do do
if level >= log_alert then
log.write_alert (create {STRING}.make_from_separate (a_message)) log.write_alert (create {STRING}.make_from_separate (a_message))
end 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))
end end
feature {NONE} -- Implementation feature {NONE} -- Implementation
initialize_logger (app: APPLICATION_ENVIRONMENT; a_log: like log) initialize_logger (app: separate APPLICATION_ENVIRONMENT; a_log: like log)
local local
l_log_writer_file: LOG_ROLLING_WRITER_FILE 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_logs_path: detachable PATH
l_logger_config: LOGGER_CONFIGURATION l_logger_config: LOGGER_CONFIGURATION
ut: FILE_UTILITIES ut: FILE_UTILITIES
p: PATH
l_name: IMMUTABLE_STRING_32
do do
l_logger_config := new_logger_level_configuration (app.application_config_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 l_logs_path := l_logger_config.location
if l_logs_path = Void then if l_logs_path = Void then
l_logs_path := app.logs_path create l_logs_path.make_from_separate (app.logs_path)
end end
if ut.directory_path_exists (l_logs_path) then 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")) 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_file_size ({NATURAL_64} 1024 * 1204)
l_log_writer_file.set_max_backup_count (l_logger_config.backup_count) l_log_writer_file.set_max_backup_count (l_logger_config.backup_count)
l_log_writer := l_log_writer_file l_log_writer := l_log_writer_file
else else
-- Should we create the directory anyway ? -- Should we create the directory anyway ?
create {LOG_WRITER_NULL} l_log_writer
end end
set_logger_level (l_log_writer, l_logger_config.level) elseif l_logger_config.type.is_case_insensitive_equal_general ("stderr") then
create {LOG_WRITER_STDERR} l_log_writer
end
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
a_log.register_log_writer (l_log_writer) a_log.register_log_writer (l_log_writer)
end end
set_logger_level (a_log_writer: LOG_WRITER; a_priority: INTEGER) set_logger_level (a_log_writer: LOG_WRITER; a_priority: INTEGER)
-- Setup the logger level based on `a_priority' -- Setup the logger level based on `a_priority'
do do
level := a_priority
if a_priority = log_debug then if a_priority = log_debug then
a_log_writer.enable_debug_log_level a_log_writer.enable_debug_log_level
elseif a_priority = Log_emergency then elseif a_priority = Log_emergency then
@@ -167,6 +199,9 @@ feature {NONE} -- Implementation
attached l_parser.parsed_json_object as jv and then attached l_parser.parsed_json_object as jv and then
attached {JSON_OBJECT} jv.item ("logger") as l_logger attached {JSON_OBJECT} jv.item ("logger") as l_logger
then 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 if attached {JSON_STRING} l_logger.item ("location") as l_location then
Result.set_location_with_string (l_location.item) Result.set_location_with_string (l_location.item)
end end

View File

@@ -35,72 +35,113 @@ feature -- Logging
write_debug_log (m: READABLE_STRING_8) write_debug_log (m: READABLE_STRING_8)
do do
write_debug_log_to (m, logger) -- write_debug_log_to (m, logger)
end end
write_information_log (m: READABLE_STRING_8) write_information_log (m: READABLE_STRING_8)
do do
write_information_log_to (m, logger) -- write_information_log_to (m, logger)
end end
write_warning_log (m: READABLE_STRING_8) write_warning_log (m: READABLE_STRING_8)
do do
write_warning_log_to (m, logger) -- write_warning_log_to (m, logger)
end end
write_error_log (m: READABLE_STRING_8) write_error_log (m: READABLE_STRING_8)
do do
write_error_log_to (m, logger) -- write_error_log_to (m, logger)
end end
write_critical_log (m: READABLE_STRING_8) write_critical_log (m: READABLE_STRING_8)
do do
write_critical_log_to (m, logger) -- write_critical_log_to (m, logger)
end end
write_alert_log (m: READABLE_STRING_8) write_alert_log (m: READABLE_STRING_8)
do do
write_alert_log_to (m, logger) -- write_alert_log_to (m, logger)
end end
feature {NONE} -- Logger: separate implementation feature {NONE} -- Logger: separate implementation
write_debug_log_to (m: READABLE_STRING_8; a_log: like logger) write_debug_log_to (m: READABLE_STRING_8; a_log: like logger)
local
retried: BOOLEAN
do do
if not retried then
a_log.put_debug (m) a_log.put_debug (m)
end end
rescue
retried := True
retry
end
write_information_log_to (m: READABLE_STRING_8; a_log: like logger) write_information_log_to (m: READABLE_STRING_8; a_log: like logger)
local
retried: BOOLEAN
do do
if not retried then
a_log.put_information (m) a_log.put_information (m)
end end
rescue
retried := True
retry
end
write_warning_log_to (m: READABLE_STRING_8; a_log: like logger) write_warning_log_to (m: READABLE_STRING_8; a_log: like logger)
local
retried: BOOLEAN
do do
if not retried then
a_log.put_warning (m) a_log.put_warning (m)
end end
rescue
retried := True
retry
end
write_error_log_to (m: READABLE_STRING_8; a_log: like logger) write_error_log_to (m: READABLE_STRING_8; a_log: like logger)
local
retried: BOOLEAN
do do
if not retried then
a_log.put_error (m) a_log.put_error (m)
end end
rescue
retried := True
retry
end
write_critical_log_to (m: READABLE_STRING_8; a_log: like logger) write_critical_log_to (m: READABLE_STRING_8; a_log: like logger)
local
retried: BOOLEAN
do do
if not retried then
a_log.put_critical (m) a_log.put_critical (m)
end end
rescue
retried := True
retry
end
write_alert_log_to (m: READABLE_STRING_8; a_log: like logger) write_alert_log_to (m: READABLE_STRING_8; a_log: like logger)
local
retried: BOOLEAN
do do
if not retried then
a_log.put_alert (m) a_log.put_alert (m)
end end
rescue
retried := True
retry
end
feature {NONE} -- Implementation feature {NONE} -- Implementation
initialize_logger (app: APPLICATION_ENVIRONMENT) initialize_logger (app: APPLICATION_ENVIRONMENT)
local local
l_logger: LOGGER l_logger: separate LOGGER
do do
create l_logger.make_with_environment (app) create l_logger.make_with_environment (app)
set_logger_to (l_logger, logger_cell) set_logger_to (l_logger, logger_cell)

View File

@@ -25,8 +25,10 @@ create
feature {NONE} -- Initialization 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'. -- 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 do
location := a_location location := a_location
set_title (a_title) set_title (a_title)
@@ -71,13 +73,13 @@ feature -- Status report
feature -- Element change feature -- Element change
set_title (a_title: detachable like title) set_title (a_title: detachable READABLE_STRING_GENERAL)
-- Set `title' to `a_title' or `location'. -- Set `title' to `a_title' or `location'.
do do
if a_title /= Void then if a_title /= Void then
title := a_title title := a_title.as_string_32
else else
title := location title := location.as_string_32
end end
end end

View File

@@ -32,6 +32,15 @@ feature -- Status report
Result := connection.is_connected Result := connection.is_connected
end end
feature -- Basic operation
close
-- <Precursor>
-- Disconnect from SQL database.
do
connection.disconnect
end
feature {NONE} -- Implementation feature {NONE} -- Implementation
db_handler: DATABASE_HANDLER db_handler: DATABASE_HANDLER

View File

@@ -29,15 +29,25 @@ feature -- Factory
storage (a_setup: CMS_SETUP): detachable CMS_STORAGE_SQLITE storage (a_setup: CMS_SETUP): detachable CMS_STORAGE_SQLITE
local local
s: STRING s: STRING
conn: DATABASE_CONNECTION conn: detachable DATABASE_CONNECTION
do 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=" s := "Driver=SQLite3 ODBC Driver;Database="
if attached l_database_config.database_name as db_name then if attached l_database_config.database_name as db_name then
s.append (db_name) s.append (db_name)
end end
s.append (";LongNames=0;Timeout=1000;NoTXN=0;SyncPragma=NORMAL;StepAPI=0;") s.append (";LongNames=0;Timeout=1000;NoTXN=0;SyncPragma=NORMAL;StepAPI=0;")
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) create {DATABASE_CONNECTION_ODBC} conn.login_with_connection_string (s)
reuseable_connection.replace ([s, conn])
end
if conn.is_connected then if conn.is_connected then
create Result.make (conn) create Result.make (conn)
set_map_zero_null_value (False) --| This way we map 0 to 0, instead of Null as default. set_map_zero_null_value (False) --| This way we map 0 to 0, instead of Null as default.
@@ -50,4 +60,9 @@ feature -- Factory
end end
end end
reuseable_connection: CELL [detachable TUPLE [name: STRING; connection: DATABASE_CONNECTION]]
once
create Result.put (Void)
end
end end

View File

@@ -109,9 +109,9 @@ feature -- Hooks
lnk: CMS_LOCAL_LINK lnk: CMS_LOCAL_LINK
do do
if attached a_response.current_user (a_response.request) as u then 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 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 end
-- if not a_menu_system.primary_menu.has (lnk) then -- if not a_menu_system.primary_menu.has (lnk) then
lnk.set_weight (99) lnk.set_weight (99)

View File

@@ -25,8 +25,10 @@ feature -- Basic operations
do do
api.logger.put_debug (generator + ".execute ", Void) api.logger.put_debug (generator + ".execute ", Void)
create l_auth.make (req.http_authorization) create l_auth.make (req.http_authorization)
debug
if attached req.raw_header_data as l_raw_data then if attached req.raw_header_data as l_raw_data then
api.logger.put_debug (generator + ".execute " + l_raw_data, Void) api.logger.put_debug (generator + ".execute " + (create {UTF_CONVERTER}).escaped_utf_32_string_to_utf_8_string_8 (l_raw_data), Void)
end
end end
-- A valid user -- A valid user
if if

View File

@@ -16,20 +16,21 @@ inherit
REFACTORING_HELPER REFACTORING_HELPER
create create {NODE_MODULE}
make 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 initialize
-- <Precursor> -- <Precursor>
do do
Precursor 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 initialize_node_types
end end
@@ -170,9 +171,9 @@ feature -- URL
-- or URI of path for selection of new content possibilities if ct is Void. -- or URI of path for selection of new content possibilities if ct is Void.
do do
if ct /= Void then if ct /= Void then
Result := "/node/add/" + ct.name Result := "node/add/" + ct.name
else else
Result := "/node/" Result := "node/"
end end
end end
@@ -190,18 +191,18 @@ feature -- URL
require require
a_node.has_id a_node.has_id
do do
Result := "/node/" + a_node.id.out Result := "node/" + a_node.id.out
end end
nodes_path: STRING nodes_path: STRING
-- URI path for list of nodes. -- URI path for list of nodes.
do do
Result := "/nodes" Result := "nodes"
end end
feature -- Access: Node feature -- Access: Node
nodes_count: INTEGER_64 nodes_count: NATURAL_64
do do
Result := node_storage.nodes_count Result := node_storage.nodes_count
end end
@@ -212,10 +213,17 @@ feature -- Access: Node
Result := node_storage.nodes Result := node_storage.nodes
end 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'. -- List of the `a_rows' most recent nodes starting from `a_offset'.
do 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 end
node (a_id: INTEGER_64): detachable CMS_NODE node (a_id: INTEGER_64): detachable CMS_NODE
@@ -316,6 +324,21 @@ feature -- Change: Node
node_storage.update_node (a_node) node_storage.update_node (a_node)
end 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
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 feature -- Node status

View File

@@ -9,6 +9,8 @@ deferred class
inherit inherit
CMS_NODE_TYPE_WEBFORM_MANAGER_I [G] CMS_NODE_TYPE_WEBFORM_MANAGER_I [G]
SHARED_WSF_PERCENT_ENCODER
feature -- Forms ... feature -- Forms ...
populate_form (response: NODE_RESPONSE; f: CMS_FORM; a_node: detachable CMS_NODE) populate_form (response: NODE_RESPONSE; f: CMS_FORM; a_node: detachable CMS_NODE)
@@ -19,6 +21,7 @@ feature -- Forms ...
tselect: WSF_FORM_SELECT tselect: WSF_FORM_SELECT
opt: WSF_FORM_SELECT_OPTION opt: WSF_FORM_SELECT_OPTION
cms_format: CMS_EDITOR_CONTENT_FORMAT cms_format: CMS_EDITOR_CONTENT_FORMAT
l_uri: detachable READABLE_STRING_8
do do
create cms_format create cms_format
@@ -97,10 +100,31 @@ feature -- Forms ...
ti.set_size (70) ti.set_size (70)
if a_node /= Void and then a_node.has_id then if a_node /= Void and then a_node.has_id then
if attached a_node.link as lnk then if attached a_node.link as lnk then
ti.set_text_value (lnk.location) l_uri := lnk.location
else else
ti.set_text_value (response.api.path_alias (response.node_api.node_path (a_node))) l_uri := percent_encoder.percent_decoded_string (response.api.path_alias (response.node_api.node_path (a_node)))
end 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 end
if if
attached f.fields_by_name ("title") as l_title_fields and then attached f.fields_by_name ("title") as l_title_fields and then
@@ -224,14 +248,32 @@ feature -- Output
node_api := a_response.node_api node_api := a_response.node_api
a_response.add_variable (a_node, "node") a_response.add_variable (a_node, "node")
create lnk.make (a_response.translation ("View", Void), a_response.node_local_link (a_node).location) lnk := a_response.node_local_link (a_node, a_response.translation ("View", Void))
lnk.set_weight (1) lnk.set_weight (1)
a_response.add_to_primary_tabs (lnk) 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") create lnk.make ("Edit", node_api.node_path (a_node) + "/edit")
lnk.set_weight (2) lnk.set_weight (2)
a_response.add_to_primary_tabs (lnk) 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 create s.make_empty
s.append ("<div class=%"info%"> ") s.append ("<div class=%"info%"> ")
if attached a_node.author as l_author then if attached a_node.author as l_author then

View File

@@ -26,7 +26,7 @@ feature {NONE} -- Initialization
initialize initialize
do do
Precursor Precursor
create {WSF_CMS_THEME} wsf_theme.make (Current, theme) create {CMS_TO_WSF_THEME} wsf_theme.make (Current, theme)
end end
wsf_theme: WSF_THEME wsf_theme: WSF_THEME
@@ -48,7 +48,11 @@ feature -- Execution
attached node_api.node (nid) as l_node attached node_api.node (nid) as l_node
then then
if attached node_api.node_type_for (l_node) as l_type then if attached node_api.node_type_for (l_node) as l_type then
if node_api.has_permission_for_action_on_node ("edit", l_node, current_user (request)) then 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) f := new_edit_form (l_node, url (request.path_info, Void), "edit-" + l_type.name, l_type)
invoke_form_alter (f, fd) invoke_form_alter (f, fd)
if request.is_post_request_method then if request.is_post_request_method then
@@ -58,8 +62,9 @@ feature -- Execution
fd := f.last_data fd := f.last_data
end end
if l_node.has_id then if l_node.has_id then
add_to_menu (create {CMS_LOCAL_LINK}.make (translation ("View", Void), node_url (l_node)), primary_tabs) 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/" + l_node.id.out + "/edit"), 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 end
if attached redirection as l_location then if attached redirection as l_location then
@@ -70,6 +75,53 @@ feature -- Execution
set_title (formatted_string (translation ("Edit $1 #$2", Void), [l_type.title, l_node.id])) set_title (formatted_string (translation ("Edit $1 #$2", Void), [l_type.title, l_node.id]))
f.append_to_html (wsf_theme, b) f.append_to_html (wsf_theme, b)
end 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
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 else
b.append ("<h1>") b.append ("<h1>")
b.append (translation ("Access denied", Void)) b.append (translation ("Access denied", Void))
@@ -96,8 +148,8 @@ feature -- Execution
set_title ("Edit " + html_encoded (l_type.title) + " #" + l_node.id.out) set_title ("Edit " + html_encoded (l_type.title) + " #" + l_node.id.out)
if l_node.has_id then if l_node.has_id then
add_to_menu (create {CMS_LOCAL_LINK}.make (translation ("View", Void), node_url (l_node)), primary_tabs) 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/" + l_node.id.out + "/edit"), primary_tabs) add_to_menu (create {CMS_LOCAL_LINK}.make (translation ("Edit", Void), node_api.node_path (l_node) + "/edit"), primary_tabs)
end end
f.append_to_html (wsf_theme, b) f.append_to_html (wsf_theme, b)
@@ -121,7 +173,7 @@ feature -- Execution
attached ic.item as l_node_type and then attached ic.item as l_node_type and then
has_permissions (<<"create any", "create " + l_node_type.name>>) has_permissions (<<"create any", "create " + l_node_type.name>>)
then 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 if attached l_node_type.description as d then
b.append ("<div class=%"description%">" + d + "</div>") b.append ("<div class=%"description%">" + d + "</div>")
end end
@@ -167,6 +219,7 @@ feature -- Form
l_preview: BOOLEAN l_preview: BOOLEAN
l_node: detachable CMS_NODE l_node: detachable CMS_NODE
s: STRING s: STRING
l_path_alias: detachable READABLE_STRING_8
do do
l_preview := attached {WSF_STRING} fd.item ("op") as l_op and then l_op.same_string ("Preview") l_preview := attached {WSF_STRING} fd.item ("op") as l_op and then l_op.same_string ("Preview")
if not l_preview then if not l_preview then
@@ -198,20 +251,29 @@ feature -- Form
end end
node_api.save_node (l_node) node_api.save_node (l_node)
if attached current_user (request) as u then if attached current_user (request) as u then
api.log ("node", "User %"" + user_html_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 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 end
add_success_message ("Node #" + l_node.id.out + " saved.") add_success_message ("Node #" + l_node.id.out + " saved.")
if attached fd.string_item ("path_alias") as l_path_alias then 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) 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)) l_node.set_link (create {CMS_LOCAL_LINK}.make (l_node.title, l_path_alias))
else else
l_node.set_link (node_api.node_link (l_node)) l_node.set_link (node_api.node_link (l_node))
end end
if attached l_node.link as lnk then
set_redirection (node_url (l_node)) set_redirection (lnk.location)
end
end end
end end
@@ -243,10 +305,25 @@ feature -- Form
ts.set_default_value ("Preview") ts.set_default_value ("Preview")
f.extend (ts) f.extend (ts)
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 if
a_node /= Void and then a_node /= Void and then
a_node.id > 0 and then a_node.id > 0
has_permission ("delete " + a_name)
then then
create ts.make ("op") create ts.make ("op")
ts.set_default_value ("Delete") ts.set_default_value ("Delete")
@@ -254,11 +331,52 @@ feature -- Form
ts.set_default_value (translation ("Delete")) ts.set_default_value (translation ("Delete"))
]") ]")
f.extend (ts) 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 end
Result := f Result := f
end 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) 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, -- Fill the web form `a_form' with data from `a_node' if set,
-- and apply this to content type `a_content_type'. -- and apply this to content type `a_content_type'.

View File

@@ -89,6 +89,14 @@ feature -- HTTP Methods
check valid_url: req.path_info.starts_with_general ("/node/") end check valid_url: req.path_info.starts_with_general ("/node/") end
create edit_response.make (req, res, api, node_api) create edit_response.make (req, res, api, node_api)
edit_response.execute 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 else
-- Display existing node -- Display existing node
l_nid := node_id_path_parameter (req) l_nid := node_id_path_parameter (req)
@@ -116,14 +124,26 @@ feature -- HTTP Methods
do do
fixme ("Refactor code: extract methods: edit_node and add_node") fixme ("Refactor code: extract methods: edit_node and add_node")
if req.path_info.ends_with_general ("/edit") then 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 if
attached {WSF_STRING} req.form_parameter ("op") as l_op and then attached {WSF_STRING} req.form_parameter ("op") as l_op and then
l_op.value.same_string ("Delete") l_op.value.same_string ("Delete")
then then
do_delete (req, res) do_delete (req, res)
else end
create edit_response.make (req, res, api, node_api) elseif req.path_info.ends_with_general ("/trash") then
edit_response.execute 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 end
elseif req.path_info.starts_with_general ("/node/add/") then elseif req.path_info.starts_with_general ("/node/add/") then
create edit_response.make (req, res, api, node_api) create edit_response.make (req, res, api, node_api)
@@ -174,6 +194,62 @@ feature -- HTTP Methods
send_not_implemented ("REST API not yet implemented", req, res) send_not_implemented ("REST API not yet implemented", req, res)
end 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 feature -- Error
do_error (req: WSF_REQUEST; res: WSF_RESPONSE; a_id: detachable WSF_STRING) do_error (req: WSF_REQUEST; res: WSF_RESPONSE; a_id: detachable WSF_STRING)

View File

@@ -53,30 +53,45 @@ feature -- Helpers
feature -- Helpers: cms link feature -- Helpers: cms link
user_local_link (u: CMS_USER): CMS_LOCAL_LINK user_local_link (u: CMS_USER; a_opt_title: detachable READABLE_STRING_GENERAL): CMS_LOCAL_LINK
do do
if a_opt_title /= Void then
create Result.make (a_opt_title, user_url (u))
else
create Result.make (u.name, user_url (u)) create Result.make (u.name, user_url (u))
end end
end
node_local_link (n: CMS_NODE): CMS_LOCAL_LINK node_local_link (n: CMS_NODE; a_opt_title: detachable READABLE_STRING_GENERAL): CMS_LOCAL_LINK
do do
if attached n.link as lnk then if attached n.link as lnk then
Result := lnk Result := lnk
else else
Result := node_api.node_link (n) Result := node_api.node_link (n)
end 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 end
feature -- Helpers: html link feature -- Helpers: html link
user_html_link (u: CMS_USER): like link user_html_link (u: CMS_USER): like link
do do
Result := link (u.name, "/user/" + u.id.out, Void) Result := link (u.name, "user/" + u.id.out, Void)
end end
node_html_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 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 end
feature -- Helpers: URL feature -- Helpers: URL
@@ -85,7 +100,7 @@ feature -- Helpers: URL
require require
u_with_id: u.has_id u_with_id: u.has_id
do do
Result := url ("/user/" + u.id.out, Void) Result := url ("user/" + u.id.out, Void)
end end
node_url (n: CMS_NODE): like url node_url (n: CMS_NODE): like url

View File

@@ -27,7 +27,7 @@ feature {NONE} -- Initialization
initialize initialize
do do
Precursor Precursor
create {WSF_CMS_THEME} wsf_theme.make (Current, theme) create {CMS_TO_WSF_THEME} wsf_theme.make (Current, theme)
end end
wsf_theme: WSF_THEME wsf_theme: WSF_THEME

View File

@@ -37,22 +37,40 @@ feature -- HTTP Methods
do_get (req: WSF_REQUEST; res: WSF_RESPONSE) do_get (req: WSF_REQUEST; res: WSF_RESPONSE)
-- <Precursor> -- <Precursor>
local local
l_page: CMS_RESPONSE l_response: CMS_RESPONSE
s: STRING s: STRING
n: CMS_NODE n: CMS_NODE
lnk: CMS_LOCAL_LINK lnk: CMS_LOCAL_LINK
l_page_helper: CMS_PAGINATION_GENERATOR
s_pager: STRING
l_count: NATURAL_64
do 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 -- get them from the configuration file and load them into
-- the setup class. -- the setup class.
create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api) l_count := node_api.nodes_count
l_page.add_variable (node_api.nodes, "nodes")
create {GENERIC_VIEW_CMS_RESPONSE} l_response.make (req, res, api)
-- NOTE: for development purposes we have the following hardcode output. create s.make_empty
create s.make_from_string ("<p>Nodes:</p>") if l_count > 1 then
if attached node_api.nodes as lst 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") s.append ("<ul class=%"cms-nodes%">%N")
across across
lst as ic lst as ic
@@ -60,16 +78,23 @@ feature -- HTTP Methods
n := ic.item n := ic.item
lnk := node_api.node_link (n) lnk := node_api.node_link (n)
s.append ("<li class=%"cms_type_"+ n.content_type +"%">") s.append ("<li class=%"cms_type_"+ n.content_type +"%">")
s.append (l_page.link (lnk.title, lnk.location, Void)) s.append (l_response.link (lnk.title, lnk.location, Void))
-- s.append (l_page.link (n.title + " (#" + n.id.out + ")", node_api.node_path (n), 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") s.append ("</li>%N")
end end
s.append ("</ul>%N") s.append ("</ul>%N")
end end
-- Again the pager at the bottom, if needed
s.append (s_pager)
l_page.set_main_content (s) l_response.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_response.execute
l_page.execute
end end
end end

View 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

View File

@@ -9,14 +9,12 @@ class
inherit inherit
CMS_MODULE CMS_MODULE
rename
module_api as node_api
redefine redefine
register_hooks, register_hooks,
initialize, initialize,
is_installed, is_installed,
install, install,
node_api module_api
end end
CMS_HOOK_MENU_SYSTEM_ALTER CMS_HOOK_MENU_SYSTEM_ALTER
@@ -43,15 +41,26 @@ feature {NONE} -- Initialization
feature {CMS_API} -- Module Initialization feature {CMS_API} -- Module Initialization
initialize (api: CMS_API) initialize (a_api: CMS_API)
-- <Precursor> -- <Precursor>
local local
p1,p2: CMS_PAGE p1,p2: CMS_PAGE
ct: CMS_PAGE_NODE_TYPE ct: CMS_PAGE_NODE_TYPE
l_node_api: like node_api l_node_api: like node_api
l_node_storage: CMS_NODE_STORAGE_I
do do
Precursor (api) Precursor (a_api)
create l_node_api.make (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 node_api := l_node_api
-- Add support for CMS_PAGE, which requires a storage extension to store the optional "parent" id. -- 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 -- 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 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 create ct
p1 := ct.new_node (Void) p1 := ct.new_node (Void)
p1.set_title ("Welcome") p1.set_title ("Welcome")
@@ -81,29 +90,42 @@ feature {CMS_API} -- Module Initialization
-- FIXME: maybe provide a default solution based on file system, when no SQL storage is available. -- 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. -- IDEA: we could also have generic extension to node system, that handle generic addition field.
end end
ensure then
node_api_set: node_api /= Void
end end
feature {CMS_API} -- Module management feature {CMS_API} -- Module management
is_installed (api: CMS_API): BOOLEAN is_installed (a_api: CMS_API): BOOLEAN
-- Is Current module installed? -- Is Current module installed?
do 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 Result := l_sql_storage.sql_table_exists ("nodes") and
l_sql_storage.sql_table_exists ("page_nodes") l_sql_storage.sql_table_exists ("page_nodes")
end end
end end
install (api: CMS_API) install (a_api: CMS_API)
do do
-- Schema -- Schema
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
l_sql_storage.sql_execute_file_script (api.setup.environment.path.extended ("scripts").extended (name).appended_with_extension ("sql")) l_sql_storage.sql_execute_file_script (a_api.setup.environment.path.extended ("scripts").extended (name).appended_with_extension ("sql"))
end end
end end
feature {CMS_API} -- Access: API 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 node_api: detachable CMS_NODE_API
-- <Precursor> -- <Precursor>
@@ -111,22 +133,18 @@ feature -- Access: router
setup_router (a_router: WSF_ROUTER; a_api: CMS_API) setup_router (a_router: WSF_ROUTER; a_api: CMS_API)
-- <Precursor> -- <Precursor>
local
l_node_api: like node_api
do do
l_node_api := node_api if attached node_api as l_node_api then
if l_node_api = Void then
create l_node_api.make (a_api)
node_api := l_node_api
end
configure_web (a_api, l_node_api, a_router) configure_web (a_api, l_node_api, a_router)
end end
end
configure_web (a_api: CMS_API; a_node_api: CMS_NODE_API; a_router: WSF_ROUTER) configure_web (a_api: CMS_API; a_node_api: CMS_NODE_API; a_router: WSF_ROUTER)
local local
l_node_handler: NODE_HANDLER l_node_handler: NODE_HANDLER
l_nodes_handler: NODES_HANDLER l_nodes_handler: NODES_HANDLER
l_uri_mapping: WSF_URI_MAPPING l_uri_mapping: WSF_URI_MAPPING
l_trash_handler: TRASH_HANDLER
do do
-- TODO: for now, focused only on web interface, add REST api later. [2015-April-29] -- 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) create l_node_handler.make (a_api, a_node_api)
@@ -135,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/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}/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) 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) -- For now: no REST API handling... a_router.methods_get_put_delete + a_router.methods_get_post)
@@ -143,6 +163,13 @@ feature -- Access: router
create l_nodes_handler.make (a_api, a_node_api) create l_nodes_handler.make (a_api, a_node_api)
create l_uri_mapping.make_trailing_slash_ignored ("/nodes", l_nodes_handler) 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) 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 end
feature -- Hooks feature -- Hooks
@@ -173,10 +200,13 @@ feature -- Hooks
lnk: CMS_LOCAL_LINK lnk: CMS_LOCAL_LINK
-- perms: detachable ARRAYED_LIST [READABLE_STRING_8] -- perms: detachable ARRAYED_LIST [READABLE_STRING_8]
do 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) 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) a_menu_system.primary_menu.extend (lnk)
end end

View File

@@ -43,6 +43,8 @@ feature {NONE} -- Implementation
extended_store (a_node: CMS_NODE) extended_store (a_node: CMS_NODE)
-- Store extended data from `a_node'. -- Store extended data from `a_node'.
require
not error_handler.has_error
do do
if attached node_storage_extension (a_node) as ext then if attached node_storage_extension (a_node) as ext then
ext.store_node (a_node) ext.store_node (a_node)
@@ -51,16 +53,17 @@ feature {NONE} -- Implementation
extended_load (a_node: CMS_NODE) extended_load (a_node: CMS_NODE)
-- Load extended data into `a_node'. -- Load extended data into `a_node'.
require
not error_handler.has_error
do do
if attached node_storage_extension (a_node) as ext then if attached node_storage_extension (a_node) as ext then
ext.load_node (a_node) ext.load_node (a_node)
end end
end end
feature -- Access feature -- Access
nodes_count: INTEGER_64 nodes_count: NATURAL_64
-- Count of nodes. -- Count of nodes.
deferred deferred
end end
@@ -70,6 +73,11 @@ feature -- Access
deferred deferred
end 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] recent_nodes (a_lower: INTEGER; a_count: INTEGER): LIST [CMS_NODE]
-- List of recent `a_count' nodes with an offset of `lower'. -- List of recent `a_count' nodes with an offset of `lower'.
deferred deferred
@@ -108,7 +116,7 @@ feature -- Change: Node
valid_user: attached a_node.author as l_author and then l_author.id > 0 valid_user: attached a_node.author as l_author and then l_author.id > 0
deferred deferred
ensure ensure
has_id: a_node.has_id has_id: not error_handler.has_error implies a_node.has_id
end end
update_node (a_node: CMS_NODE) update_node (a_node: CMS_NODE)
@@ -135,32 +143,35 @@ feature -- Change: Node
deferred deferred
end end
-- update_node_title (a_user_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_title: READABLE_STRING_32) trash_node (a_node: CMS_NODE)
-- -- Update node title to `a_title', node identified by id `a_node_id'. -- Trash `a_node'.
-- -- The user `a_user_id' is an existing or new collaborator. do
-- require if a_node.has_id then
-- valid_node_id: a_node_id > 0 trash_node_by_id (a_node.id)
-- valid_user_id: a_user_id > 0 end
-- deferred end
-- end
-- update_node_summary (a_user_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_summary: READABLE_STRING_32) restore_node (a_node: CMS_NODE)
-- -- Update node summary to `a_summary', node identified by id `a_node_id'. -- Restore `a_node'.
-- -- The user `a_user_id' is an existing or new collaborator. do
-- require if a_node.has_id then
-- valid_id: a_node_id > 0 restore_node_by_id (a_node.id)
-- valid_user_id: a_user_id > 0 end
-- deferred end
-- end
-- update_node_content (a_user_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_content: READABLE_STRING_32) trash_node_by_id (a_id: INTEGER_64)
-- -- Update node content to `a_content', node identified by id `a_node_id'. -- Trash node by id `a_id'.
-- -- The user `a_user_id' is an existing or new collaborator. require
-- require valid_node_id: a_id > 0
-- valid_id: a_node_id > 0 deferred
-- valid_user_id: a_user_id > 0 end
-- 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 feature -- Helpers

View File

@@ -30,7 +30,7 @@ feature -- Error Handling
feature -- Access: node feature -- Access: node
nodes_count: INTEGER_64 nodes_count: NATURAL_64
-- Count of nodes. -- Count of nodes.
do do
end end
@@ -41,6 +41,12 @@ feature -- Access: node
create {ARRAYED_LIST [CMS_NODE]} Result.make (0) create {ARRAYED_LIST [CMS_NODE]} Result.make (0)
end 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] recent_nodes (a_lower: INTEGER; a_count: INTEGER): LIST [CMS_NODE]
-- List of the `a_count' most recent nodes, starting from `a_lower'. -- List of the `a_count' most recent nodes, starting from `a_lower'.
do do
@@ -80,6 +86,16 @@ feature -- Node
do do
end 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) -- update_node_title (a_user_id: like {CMS_NODE}.id; a_node_id: like {CMS_NODE}.id; a_title: READABLE_STRING_32)
-- -- <Precursor> -- -- <Precursor>
-- do -- do

View File

@@ -22,14 +22,14 @@ create
feature -- Access feature -- Access
nodes_count: INTEGER_64 nodes_count: NATURAL_64
-- Number of items nodes. -- Number of items nodes.
do do
error_handler.reset error_handler.reset
write_information_log (generator + ".nodes_count") write_information_log (generator + ".nodes_count")
sql_query (sql_select_nodes_count, Void) sql_query (sql_select_nodes_count, Void)
if sql_rows_count = 1 then if sql_rows_count = 1 then
Result := sql_read_integer_64 (1) Result := sql_read_natural_64 (1)
end end
end end
@@ -60,6 +60,36 @@ feature -- Access
-- end -- end
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] recent_nodes (a_lower: INTEGER; a_count: INTEGER): LIST [CMS_NODE]
-- List of recent `a_count' nodes with an offset of `lower'. -- List of recent `a_count' nodes with an offset of `lower'.
local local
@@ -148,7 +178,7 @@ feature -- Change: Node
l_time: DATE_TIME l_time: DATE_TIME
do do
create l_time.make_now_utc create l_time.make_now_utc
write_information_log (generator + ".delete_node") write_information_log (generator + ".delete_node {" + a_id.out + "}")
error_handler.reset error_handler.reset
create l_parameters.make (1) create l_parameters.make (1)
@@ -158,6 +188,40 @@ feature -- Change: Node
sql_change (sql_delete_node, l_parameters) sql_change (sql_delete_node, l_parameters)
end 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
feature {NONE} -- Implementation feature {NONE} -- Implementation
store_node (a_node: CMS_NODE) store_node (a_node: CMS_NODE)
@@ -204,9 +268,15 @@ feature {NONE} -- Implementation
a_node.set_revision (1) -- New object. a_node.set_revision (1) -- New object.
end end
end end
if not error_handler.has_error then
extended_store (a_node) extended_store (a_node)
end
if error_handler.has_error then
sql_rollback_transaction
else
sql_commit_transaction sql_commit_transaction
end end
end
feature -- Helpers feature -- Helpers
@@ -229,6 +299,14 @@ feature {NONE} -- Queries
-- SQL Query to retrieve all nodes. -- SQL Query to retrieve all nodes.
--| note: {CMS_NODE_API}.trashed = -1 --| note: {CMS_NODE_API}.trashed = -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_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_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_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_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 ;"
@@ -244,6 +322,12 @@ feature {NONE} -- Queries
sql_delete_node: STRING = "UPDATE nodes SET changed=:changed, status =:status WHERE nid=:nid" sql_delete_node: STRING = "UPDATE nodes SET changed=:changed, status =:status WHERE nid=:nid"
-- Soft deletion with free metadata. -- 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;" -- sql_update_node_author: STRING = "UPDATE nodes SET author=:author WHERE nid=:nid;"
-- sql_update_node_title: STRING ="UPDATE nodes SET title=:title, changed=:changed, revision = revision + 1 WHERE nid=:nid;" -- sql_update_node_title: STRING ="UPDATE nodes SET title=:title, changed=:changed, revision = revision + 1 WHERE nid=:nid;"

31
package.iron Normal file
View 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

View File

@@ -39,17 +39,21 @@ feature {NONE} -- Initialization
end end
configure configure
local
l_url: like site_url
do do
--| Site id, used to identified a site, this could be set to a uuid, or else --| 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_id := text_item_or_default ("site.id", "_EWF_CMS_NO_ID_")
-- Site url: optional, but ending with a slash -- Site url: optional, but ending with a slash
site_url := string_8_item ("site_url") l_url := string_8_item ("site_url")
if attached site_url as l_url and then not l_url.is_empty then if l_url /= Void and then not l_url.is_empty then
if l_url [l_url.count] /= '/' then if l_url [l_url.count] /= '/' then
site_url := l_url + "/" l_url := l_url + "/"
end end
end end
site_url := l_url
-- Site name -- Site name
site_name := text_item_or_default ("site.name", "EWF::CMS") site_name := text_item_or_default ("site.name", "EWF::CMS")

View File

@@ -62,7 +62,7 @@ feature -- Access: Site
-- Mainly used for internal notification. -- Mainly used for internal notification.
site_url: detachable READABLE_STRING_8 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 front_page_path: detachable READABLE_STRING_8
-- Optional path defining the front page. -- Optional path defining the front page.

View File

@@ -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 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'. -- Smarty content block for `a_block_id' in the context of `a_module' and `a_response'.
local local
res: PATH
p: detachable PATH p: detachable PATH
do do
create p.make_from_string ("templates") create res.make_from_string ("templates")
p := p.extended ("block_").appended (a_block_id).appended_with_extension ("tpl") res := res.extended ("block_").appended (a_block_id).appended_with_extension ("tpl")
p := a_response.module_resource_path (a_module, p) p := a_response.module_resource_path (a_module, res)
if p /= Void then if p /= Void then
if attached p.entry as e then if attached p.entry as e then
create Result.make (a_block_id, Void, p.parent, e) create Result.make (a_block_id, Void, p.parent, e)

View 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

View File

@@ -39,7 +39,7 @@ feature -- Router
setup_router (a_router: WSF_ROUTER; a_api: CMS_API) setup_router (a_router: WSF_ROUTER; a_api: CMS_API)
-- <Precursor> -- <Precursor>
do do
a_router.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 end
feature -- Hooks configuration feature -- Hooks configuration

View 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

View File

@@ -39,6 +39,13 @@ feature -- Status report
deferred deferred
end end
feature -- Basic operation
close
-- Close/disconnect current storage.
deferred
end
feature -- Error Handling feature -- Error Handling
error_handler: ERROR_HANDLER error_handler: ERROR_HANDLER

View File

@@ -45,6 +45,13 @@ feature -- Status report
Result := True Result := True
end end
feature -- Basic operation
close
-- <Precursor>
do
end
feature -- URL aliases feature -- URL aliases
set_path_alias (a_source: READABLE_STRING_8; a_alias: READABLE_STRING_8) set_path_alias (a_source: READABLE_STRING_8; a_alias: READABLE_STRING_8)

View File

@@ -1,6 +1,6 @@
note note
description: "[ description: "[
Objects that ... CMS Storage for core functionalities.
]" ]"
author: "$Author$" author: "$Author$"
date: "$Date$" date: "$Date$"

View 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

View File

@@ -40,6 +40,10 @@ feature -- Initialization
--| Node --| Node
-- FIXME: move that initialization to node module -- 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") l_anonymous_role.add_permission ("view any page")
a_storage.save_user_role (l_anonymous_role) a_storage.save_user_role (l_anonymous_role)
@@ -47,9 +51,11 @@ feature -- Initialization
l_authenticated_role.add_permission ("view any page") l_authenticated_role.add_permission ("view any page")
l_authenticated_role.add_permission ("edit any page") l_authenticated_role.add_permission ("edit any page")
l_authenticated_role.add_permission ("delete 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 ("view own page")
l_authenticated_role.add_permission ("edit own page") l_authenticated_role.add_permission ("edit own page")
l_authenticated_role.add_permission ("delete 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) a_storage.save_user_role (l_authenticated_role)

View File

@@ -217,6 +217,21 @@ feature -- Access
deferred deferred
end 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 sql_read_integer_64 (a_index: INTEGER): INTEGER_64
-- Retrieved value at `a_index' position in `item'. -- Retrieved value at `a_index' position in `item'.
local local

View File

@@ -148,17 +148,15 @@ feature -- Permissions system
feature -- Query: module 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. -- Enabled module typed `a_type', if any.
--| usage: if attached module ({FOO_MODULE}) as mod then ... --| usage: if attached module ({FOO_MODULE}) as mod then ...
local local
t: STRING_8 -- t: STRING_8
l_type: TYPE [detachable CMS_MODULE] l_type: TYPE [detachable CMS_MODULE]
do do
t := a_type.name -- t := type_name_without_annotation (a_type)
if t.starts_with ("!") then
t.remove_head (1)
end
across across
setup.modules as ic setup.modules as ic
until until
@@ -171,8 +169,12 @@ feature -- Query: module
l_type := Result.generating_type l_type := Result.generating_type
if a_type ~ l_type then if a_type ~ l_type then
-- Found -- 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 -- Found
-- elseif t.same_string (type_name_without_annotation (l_type)) then
-- -- Found
else else
Result := Void Result := Void
end end
@@ -185,8 +187,11 @@ feature -- Query: module
module_api (a_type: TYPE [CMS_MODULE]): detachable CMS_MODULE_API module_api (a_type: TYPE [CMS_MODULE]): detachable CMS_MODULE_API
-- Enabled module API associated with module typed `a_type'. -- Enabled module API associated with module typed `a_type'.
do do
if attached {CMS_MODULE} module (a_type) as mod then if attached module (a_type) as mod then
if mod.is_enabled then if mod.is_enabled then
if not mod.is_initialized then
mod.initialize (Current)
end
Result := mod.module_api Result := mod.module_api
end end
end end
@@ -236,9 +241,16 @@ feature -- Query: API
feature -- Path aliases 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_path_alias (a_source, a_alias: READABLE_STRING_8; a_keep_previous: BOOLEAN)
-- Set `a_alias' as alias of `a_source', -- Set `a_alias' as alias of `a_source',
-- and eventually unset previous alias if any. -- and eventually unset previous alias if any.
require
valid_alias: is_valid_path_alias (a_alias)
local local
l_continue: BOOLEAN l_continue: BOOLEAN
do do
@@ -283,8 +295,8 @@ feature -- Path aliases
-- Resolved path for alias `a_alias'. -- Resolved path for alias `a_alias'.
--| the CMS supports aliases for path, and then this function simply returns --| the CMS supports aliases for path, and then this function simply returns
--| the effective target path/url for this `a_alias'. --| 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 --| For instance: articles/2015/may/this-is-an-article can be an alias to node/123
--| This function will return "/node/123". --| This function will return "node/123".
--| If the alias is bad (i.e does not alias real path), then this function --| If the alias is bad (i.e does not alias real path), then this function
--| returns the alias itself. --| returns the alias itself.
do do
@@ -310,6 +322,41 @@ feature {NONE}-- Implemenation
internal_user_api: detachable like user_api internal_user_api: detachable like user_api
-- Cached value for `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 feature -- Environment
module_configuration (a_module_name: READABLE_STRING_GENERAL; a_name: detachable READABLE_STRING_GENERAL): detachable CONFIG_READER module_configuration (a_module_name: READABLE_STRING_GENERAL; a_name: detachable READABLE_STRING_GENERAL): detachable CONFIG_READER

View File

@@ -14,4 +14,10 @@ create
make, make,
make_from_manifest 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 end

View File

@@ -6,56 +6,56 @@ note
even for a specific handler. even for a specific handler.
]" ]"
class deferred class
CMS_SERVICE CMS_EXECUTION
inherit inherit
WSF_ROUTED_SKELETON_SERVICE WSF_FILTERED_ROUTED_SKELETON_EXECUTION
rename
execute as execute_service
undefine undefine
requires_proxy requires_proxy
redefine redefine
create_router, router,
execute_default, execute_default,
create_router, filter_execute,
router initialize
end
WSF_FILTERED_SERVICE
WSF_FILTER
rename
execute as execute_filter
end end
WSF_NO_PROXY_POLICY 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 REFACTORING_HELPER
SHARED_LOGGER SHARED_LOGGER
create --create
make -- make
feature {NONE} -- Initialization feature {NONE} -- Initialization
make (a_setup: CMS_SETUP)
-- Build a CMS service with `a_api'
do
create api.make (a_setup)
initialize initialize
-- Build a CMS service with `a_api'
local
l_setup: CMS_SETUP
do
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 end
initialize initialize_cms
-- Initialize various parts of the CMS service.
do do
initialize_modules write_debug_log (generator + ".initialize_cms")
initialize_users
initialize_mailer -- CMS Initialization
-- initialize_router -- initialize_router
-- initialize_filter: expanded here, for void-safety concern. -- initialize_filter: expanded here, for void-safety concern.
create_filter create_filter
@@ -71,20 +71,41 @@ feature {NONE} -- Initialization
only_enabled_modules: across modules as ic all ic.item.is_enabled end only_enabled_modules: across modules as ic all ic.item.is_enabled end
end end
initialize_users feature -- Factory
-- Initialize users.
do initial_cms_setup: CMS_SETUP
deferred
end end
initialize_mailer feature -- Access
-- Initialize mailer engine.
api: CMS_API
-- API service.
setup: CMS_SETUP
-- CMS Setup.
do 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 end
feature -- Settings: router feature -- Settings: router
router: CMS_ROUTER router: CMS_ROUTER
-- <Precursor>
create_router create_router
-- Create `router'. -- Create `router'.
@@ -124,9 +145,9 @@ feature -- Settings: router
create l_root_handler.make (api) create l_root_handler.make (api)
create l_methods create l_methods
l_methods.enable_get l_methods.enable_get
a_router.handle_with_request_methods ("/", l_root_handler, l_methods) a_router.handle ("/", l_root_handler, l_methods)
a_router.handle_with_request_methods ("", l_root_handler, l_methods) a_router.handle ("", l_root_handler, l_methods)
map_uri_agent_with_request_methods ("/favicon.ico", agent handle_favicon, a_router.methods_head_get) map_uri_agent ("/favicon.ico", agent handle_favicon, a_router.methods_head_get)
end end
configure_api_file_handler (a_router: WSF_ROUTER) configure_api_file_handler (a_router: WSF_ROUTER)
@@ -141,7 +162,7 @@ feature -- Settings: router
do do
execute_default (ia_req, ia_res) execute_default (ia_req, ia_res)
end) 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) create fhdl.make_hidden_with_path (setup.environment.www_path)
@@ -150,17 +171,17 @@ feature -- Settings: router
do do
execute_default (ia_req, ia_res) execute_default (ia_req, ia_res)
end) end)
a_router.handle_with_request_methods ("/", fhdl, router.methods_GET) a_router.handle ("/", fhdl, router.methods_GET)
end end
feature -- Execute Filter feature -- Execute Filter
execute_filter (req: WSF_REQUEST; res: WSF_RESPONSE) filter_execute (req: WSF_REQUEST; res: WSF_RESPONSE)
-- Execute the filter. -- Execute the filter.
do do
res.put_header_line ("Date: " + (create {HTTP_DATE}.make_now_utc).string) res.put_header_line ("Date: " + (create {HTTP_DATE}.make_now_utc).string)
res.put_header_line ("X-EWF-Server: CMS_v1.0") res.put_header_line ("X-EWF-Server: CMS_v1.0")
execute_service (req, res) Precursor (req, res)
end end
feature -- Filters feature -- Filters
@@ -180,10 +201,10 @@ feature -- Filters
f.set_next (l_filter) f.set_next (l_filter)
l_filter := f l_filter := f
-- Error Filter -- -- Error Filter
create {CMS_ERROR_FILTER} f.make (api) -- create {CMS_ERROR_FILTER} f.make (api)
f.set_next (l_filter) -- f.set_next (l_filter)
l_filter := f -- l_filter := f
-- Include filters from modules -- Include filters from modules
l_api := api l_api := api
@@ -223,20 +244,6 @@ feature -- Filters
f.set_next (Current) f.set_next (Current)
end 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 feature -- Execution
handle_favicon (req: WSF_REQUEST; res: WSF_RESPONSE) handle_favicon (req: WSF_REQUEST; res: WSF_RESPONSE)

View File

@@ -49,28 +49,32 @@ feature {CMS_API} -- Access: API
module_api: detachable CMS_MODULE_API module_api: detachable CMS_MODULE_API
-- Eventual module api. -- Eventual module api.
require
is_initialized: is_initialized
do
-- No API by default.
end
feature {CMS_API} -- Module management feature {CMS_API} -- Module management
is_installed (api: CMS_API): BOOLEAN is_installed (api: CMS_API): BOOLEAN
-- Is Current module installed? -- Is Current module installed?
do do
Result := is_enabled Result := attached api.storage.custom_value ("is_initialized", "module-" + name) as v and then v.is_case_insensitive_equal_general ("yes")
-- FIXME: implement proper installation status.
end end
install (api: CMS_API) install (api: CMS_API)
require require
is_not_installed: not is_installed (api) is_not_installed: not is_installed (api)
do do
-- Not Yet Supported api.storage.set_custom_value ("is_initialized", "module-" + name, "yes")
end end
uninstall (api: CMS_API) uninstall (api: CMS_API)
require require
is_installed: is_installed (api) is_installed: is_installed (api)
do do
-- Not Yet Supported api.storage.set_custom_value ("is_initialized", "module-" + name, "no")
end end
feature -- Router feature -- Router

View File

@@ -1,6 +1,5 @@
note note
description: "Summary description for {CMS_MODULE_API}." description: "Summary description for {CMS_MODULE_API}."
author: ""
date: "$Date: 2015-02-13 14:54:27 +0100 (ven., 13 févr. 2015) $" date: "$Date: 2015-02-13 14:54:27 +0100 (ven., 13 févr. 2015) $"
revision: "$Revision: 96620 $" revision: "$Revision: 96620 $"

View File

@@ -1,6 +1,5 @@
note note
description: "Summary description for {CMS_MODULE_COLLECTION}." description: "Collection of CMS modules."
author: ""
date: "$Date: 2015-02-09 22:29:56 +0100 (lun., 09 févr. 2015) $" date: "$Date: 2015-02-09 22:29:56 +0100 (lun., 09 févr. 2015) $"
revision: "$Revision: 96596 $" revision: "$Revision: 96596 $"

View File

@@ -19,15 +19,19 @@ feature -- Basic operations
execute (req: WSF_REQUEST; res: WSF_RESPONSE) execute (req: WSF_REQUEST; res: WSF_RESPONSE)
-- Execute the filter -- Execute the filter
local
utf: UTF_CONVERTER
do 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 if not api.has_error then
api.logger.put_information (generator + ".execute with req: " + req.debug_output, Void) api.logger.put_information (generator + ".execute with req: " + req.debug_output, Void)
if attached req.raw_header_data as l_header_data then 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 end
if attached req.raw_input_data as l_input_data then 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 end
execute_next (req, res) execute_next (req, res)
else else

View File

@@ -36,6 +36,18 @@ feature -- Response helpers
-- res.send (create {CMS_REDIRECTION_RESPONSE_MESSAGE}.make (a_location)) -- res.send (create {CMS_REDIRECTION_RESPONSE_MESSAGE}.make (a_location))
end 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_access_denied_message (res: WSF_RESPONSE)
-- Send via `res' an access denied response. -- Send via `res' an access denied response.
do do

View File

@@ -70,14 +70,4 @@ feature -- Media Type
end end
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 end

View File

@@ -13,6 +13,7 @@ inherit
feature -- Core feature -- Core
site_url: READABLE_STRING_8 site_url: READABLE_STRING_8
-- Absolute site URL of Current CMS site.
deferred deferred
end end

View File

@@ -31,8 +31,22 @@ feature {WSF_ROUTER_MAPPING} -- Dispatch helper
path_to_dispatch (req: WSF_REQUEST): READABLE_STRING_8 path_to_dispatch (req: WSF_REQUEST): READABLE_STRING_8
-- Path used by the router, to apply url dispatching of request `req'. -- Path used by the router, to apply url dispatching of request `req'.
local
l_path: STRING_8
do do
Result := api.source_of_path_alias (Precursor (req)) 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
end end

View File

@@ -3,8 +3,8 @@ note
Generic CMS Response. Generic CMS Response.
It builds the content to get process to render the output. 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) $" date: "$Date: 2015-05-20 11:48:26 +0200 (mer., 20 mai 2015) $"
revision: "$Revision: 96643 $" revision: "$Revision: 97327 $"
deferred class deferred class
CMS_RESPONSE CMS_RESPONSE
@@ -29,6 +29,7 @@ feature {NONE} -- Initialization
initialize initialize
do do
initialize_site_url
get_theme get_theme
create menu_system.make create menu_system.make
initialize_block_region_settings initialize_block_region_settings
@@ -36,6 +37,35 @@ feature {NONE} -- Initialization
register_hooks register_hooks
end 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 register_hooks
local local
l_module: CMS_MODULE l_module: CMS_MODULE
@@ -76,6 +106,15 @@ feature -- Access
redirection: detachable READABLE_STRING_8 redirection: detachable READABLE_STRING_8
-- Location for eventual redirection. -- 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) feature -- Internationalization (i18n)
translation (a_text: READABLE_STRING_GENERAL; opts: detachable CMS_API_OPTIONS): STRING_32 translation (a_text: READABLE_STRING_GENERAL; opts: detachable CMS_API_OPTIONS): STRING_32
@@ -121,9 +160,11 @@ feature -- Module
rp: PATH rp: PATH
ut: FILE_UTILITIES ut: FILE_UTILITIES
do do
-- Check first in selected theme folder.
rp := module_assets_theme_location (a_module) rp := module_assets_theme_location (a_module)
Result := rp.extended_path (a_resource) Result := rp.extended_path (a_resource)
if not ut.file_path_exists (Result) then 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) rp := module_assets_location (a_module)
Result := rp.extended_path (a_resource) Result := rp.extended_path (a_resource)
if not ut.file_path_exists (Result) then if not ut.file_path_exists (Result) then
@@ -163,16 +204,13 @@ feature -- URL utilities
end end
end end
site_url: READABLE_STRING_8 site_url: IMMUTABLE_STRING_8
do -- Absolute site url.
Result := absolute_host (request, "")
end
base_url: detachable READABLE_STRING_8 base_url: detachable IMMUTABLE_STRING_8
-- Base url if any. -- Base url if any.
--| Usually it is Void, but it could be --| Usually it is Void, but it could be
--| /project/demo/ --| /project/demo/
--| FIXME: for now, no way to change that. Always at the root "/"
feature -- Access: CMS feature -- Access: CMS
@@ -183,7 +221,7 @@ feature -- Access: CMS
front_page_url: READABLE_STRING_8 front_page_url: READABLE_STRING_8
do do
Result := request.absolute_script_url ("/") Result := absolute_url ("/", Void)
end end
values: CMS_VALUE_TABLE values: CMS_VALUE_TABLE
@@ -806,9 +844,9 @@ feature -- Theme
create l_info.make_default create l_info.make_default
end end
if l_info.engine.is_case_insensitive_equal_general ("smarty") then 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 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 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") 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 end
@@ -834,7 +872,7 @@ feature -- Generation
lnk: CMS_LINK lnk: CMS_LINK
do do
-- Menu -- Menu
create {CMS_LOCAL_LINK} lnk.make ("Home", "/") create {CMS_LOCAL_LINK} lnk.make ("Home", "")
lnk.set_weight (-10) lnk.set_weight (-10)
add_to_primary_menu (lnk) add_to_primary_menu (lnk)
invoke_menu_system_alter (menu_system) invoke_menu_system_alter (menu_system)
@@ -920,8 +958,8 @@ feature -- Generation
end end
-- Variables -- Variables
page.register_variable (request.absolute_script_url (""), "site_url") page.register_variable (absolute_url ("", Void), "site_url")
page.register_variable (request.absolute_script_url (""), "host") -- Same as `site_url'. page.register_variable (absolute_url ("", Void), "host") -- Same as `site_url'.
page.register_variable (request.is_https, "is_https") page.register_variable (request.is_https, "is_https")
if attached current_user_name (request) as l_user then if attached current_user_name (request) as l_user then
page.register_variable (l_user, "user") page.register_variable (l_user, "user")
@@ -1029,6 +1067,9 @@ feature -- Generation
l_is_active: BOOLEAN l_is_active: BOOLEAN
do do
create qs.make_from_string (request.percent_encoded_path_info) 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) l_is_active := qs.same_string (a_lnk.location)
if not l_is_active then if not l_is_active then
if attached request.query_string as l_query_string and then not l_query_string.is_empty then if attached request.query_string as l_query_string and then not l_query_string.is_empty then
@@ -1102,8 +1143,8 @@ feature {NONE} -- Execution
-- h.put_location (l_location) -- h.put_location (l_location)
response.redirect_now (l_location) response.redirect_now (l_location)
else else
-- h.put_location (request.absolute_script_url (l_location)) -- h.put_location (request.absolute_url (l_location, Void))
response.redirect_now (request.absolute_script_url (l_location)) response.redirect_now (absolute_url (l_location, Void))
end end
else else
h.put_header_object (header) h.put_header_object (header)

View File

@@ -20,7 +20,7 @@ feature -- Generation
custom_prepare (page: CMS_HTML_PAGE) custom_prepare (page: CMS_HTML_PAGE)
do 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.set_status_code ({HTTP_STATUS_CODE}.bad_request)
page.register_variable (page.status_code.out, "code") page.register_variable (page.status_code.out, "code")
end end

View File

@@ -20,7 +20,7 @@ feature -- Generation
custom_prepare (page: CMS_HTML_PAGE) custom_prepare (page: CMS_HTML_PAGE)
do 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.set_status_code ({HTTP_STATUS_CODE}.forbidden)
page.register_variable (page.status_code.out, "code") page.register_variable (page.status_code.out, "code")
end end

View File

@@ -20,7 +20,7 @@ feature -- Generation
custom_prepare (page: CMS_HTML_PAGE) custom_prepare (page: CMS_HTML_PAGE)
do 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.set_status_code ({HTTP_STATUS_CODE}.internal_server_error)
page.register_variable (page.status_code.out, "code") page.register_variable (page.status_code.out, "code")
end end

View File

@@ -20,7 +20,7 @@ feature -- Generation
custom_prepare (page: CMS_HTML_PAGE) custom_prepare (page: CMS_HTML_PAGE)
do 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.set_status_code ({HTTP_STATUS_CODE}.not_found)
page.register_variable (page.status_code.out, "code") page.register_variable (page.status_code.out, "code")
end end

View File

@@ -20,7 +20,7 @@ feature -- Generation
custom_prepare (page: CMS_HTML_PAGE) custom_prepare (page: CMS_HTML_PAGE)
do 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.set_status_code ({HTTP_STATUS_CODE}.not_implemented)
page.register_variable (page.status_code.out, "code") page.register_variable (page.status_code.out, "code")
end end

View 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

View 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

View File

@@ -1,7 +1,7 @@
note note
description: "Abstract class describing a generic theme" description: "Abstract class describing a generic theme"
date: "$Date: 2015-02-16 12:52:35 +0100 (lun., 16 févr. 2015) $" date: "$Date: 2015-05-20 11:48:26 +0200 (mer., 20 mai 2015) $"
revision: "$Revision: 96630 $" revision: "$Revision: 97327 $"
deferred class deferred class
CMS_THEME CMS_THEME
@@ -9,6 +9,8 @@ deferred class
inherit inherit
CMS_ENCODERS CMS_ENCODERS
CMS_URL_UTILITIES
REFACTORING_HELPER REFACTORING_HELPER
@@ -16,6 +18,12 @@ feature {NONE} -- Access
setup: CMS_SETUP setup: CMS_SETUP
site_url: IMMUTABLE_STRING_8
-- Absolute URL for Current CMS site.
base_url: detachable IMMUTABLE_STRING_8
-- Optional base url of current CMS site.
feature -- Access feature -- Access
name: STRING name: STRING
@@ -41,6 +49,31 @@ feature -- Status report
Result := across regions as ic some a_region_name.is_case_insensitive_equal (ic.item) end Result := across regions as ic some a_region_name.is_case_insensitive_equal (ic.item) end
end end
feature -- Element change
set_site_url (a_url: READABLE_STRING_8)
-- Set `site_url' to `a_url'.
require
a_url.ends_with_general ("/")
local
i,j: INTEGER
do
base_url := Void
if a_url [a_url.count] = '/' then
create site_url.make_from_string (a_url)
else
create site_url.make_from_string (a_url + "/")
end
i := a_url.substring_index ("://", 1)
if i > 0 then
j := a_url.index_of ('/', i + 3)
if j > 0 then
create base_url.make_from_string (a_url.substring (j, a_url.count))
end
end
end
feature -- Conversion feature -- Conversion
menu_html (a_menu: CMS_MENU; is_horizontal: BOOLEAN; a_options: detachable CMS_HTML_OPTIONS): STRING_8 menu_html (a_menu: CMS_MENU; is_horizontal: BOOLEAN; a_options: detachable CMS_HTML_OPTIONS): STRING_8
@@ -133,7 +166,11 @@ feature {NONE} -- Implementation
else else
s.append ("<li class=%""+ cl + "%">") s.append ("<li class=%""+ cl + "%">")
end end
s.append ("<a href=%"" + (lnk.location) + "%">" + html_encoded (lnk.title) + "</a>") s.append ("<a href=%"")
s.append (url (lnk.location, Void))
s.append ("%">")
s.append (html_encoded (lnk.title))
s.append ("</a>")
if if
(lnk.is_expanded or lnk.is_collapsed) and then (lnk.is_expanded or lnk.is_collapsed) and then
attached lnk.children as l_children attached lnk.children as l_children

View File

@@ -18,15 +18,19 @@ create
feature {NONE} -- Initialization feature {NONE} -- Initialization
make (a_setup: like setup) make (a_setup: like setup; a_info: like information; abs_site_url: READABLE_STRING_8)
do do
setup := a_setup setup := a_setup
information := a_info
set_site_url (abs_site_url)
ensure ensure
setup_set: setup = a_setup setup_set: setup = a_setup
end end
feature -- Access feature -- Access
information: CMS_THEME_INFORMATION
name: STRING = "missing theme" name: STRING = "missing theme"
regions: ARRAY [STRING] regions: ARRAY [STRING]

View File

@@ -14,7 +14,7 @@ create
feature {NONE} -- Initialization feature {NONE} -- Initialization
make (a_setup: like setup; a_info: like information;) make (a_setup: like setup; a_info: like information; abs_site_url: READABLE_STRING_8)
do do
setup := a_setup setup := a_setup
information := a_info information := a_info
@@ -23,6 +23,7 @@ feature {NONE} -- Initialization
else else
templates_directory := a_setup.theme_location templates_directory := a_setup.theme_location
end end
set_site_url (abs_site_url)
ensure ensure
setup_set: setup = a_setup setup_set: setup = a_setup
information_set: information = a_info information_set: information = a_info

View File

@@ -1,10 +1,10 @@
note note
description: "Summary description for {WSF_CMS_THEME}." description: "Theme from the EWF framework, but dedicated for the CMS."
date: "$Date$" date: "$Date$"
revision: "$Revision$" revision: "$Revision$"
class class
WSF_CMS_THEME CMS_TO_WSF_THEME
inherit inherit
WSF_THEME WSF_THEME
@@ -25,13 +25,14 @@ feature -- Access
request: WSF_REQUEST request: WSF_REQUEST
response: detachable CMS_RESPONSE response: CMS_RESPONSE
cms_theme: CMS_THEME cms_theme: CMS_THEME
feature -- Element change feature -- Element change
set_response (a_response: CMS_RESPONSE) set_response (a_response: CMS_RESPONSE)
-- Set `response' to `a_response'.
do do
response := a_response response := a_response
end end
@@ -39,20 +40,15 @@ feature -- Element change
feature -- Core feature -- Core
site_url: READABLE_STRING_8 site_url: READABLE_STRING_8
-- CMS site url.
do do
if attached response as r then Result := response.site_url
Result := r.site_url
else
Result := request.absolute_script_url ("")
end
end end
base_url: detachable READABLE_STRING_8 base_url: detachable READABLE_STRING_8
-- Base url if any. -- Base url if any.
do do
if attached response as r then Result := response.base_url
Result := r.base_url
end
end end
end end

View File

@@ -0,0 +1,17 @@
note
description: "Summary description for {WSF_CMS_THEME}."
date: "$Date$"
revision: "$Revision$"
class
WSF_CMS_THEME
obsolete "Use CMS_TO_WSF_THEME [2015-May]"
inherit
CMS_TO_WSF_THEME
create
make
end

71
tools/install.bat Normal file
View File

@@ -0,0 +1,71 @@
@echo off
setlocal
set TMP_EXCLUDE=%~dp0.install_ROC-copydir-exclude
set COPYCMD= xcopy /EXCLUDE:%TMP_EXCLUDE% /I /E /Y
set TMP_DIR=%~dp0..
set SAFE_RMDIR=rd /q/s
echo EIFGENs > %TMP_EXCLUDE%
echo .git >> %TMP_EXCLUDE%
echo .svn >> %TMP_EXCLUDE%
set TMP_TARGET_DIR=%1
if -%TMP_TARGET_DIR%- == -- goto ask_target_dir
goto start
:ask_target_dir
echo Please provide a installation directory (target library)
if -%ISE_LIBRARY%- == -- set ISE_LIBRARY=%EIFFEL_LIBRARY%
if -%ISE_LIBRARY%- == -- set ISE_LIBRARY=%ISE_EIFFEL%
if -%EIFFEL_LIBRARY%- == -- set EIFFEL_LIBRARY=%ISE_LIBRARY%
echo 1: using $EIFFEL_LIBRARY=%EIFFEL_LIBRARY%
echo 2: using $ISE_LIBRARY=%ISE_LIBRARY%
echo 3: using current directory=%CD%\ewf
CHOICE /C 123q /M " > selection:"
if .%ERRORLEVEL%. == .1. goto use_eiffel_library
if .%ERRORLEVEL%. == .2. goto use_ise_library
if .%ERRORLEVEL%. == .3. goto use_current_dir
echo No target directory were specified, you can pass it using the command line
echo Usage: install_ewf {target_directory}
echo Bye ...
goto end
:use_eiffel_library
if -%EIFFEL_LIBRARY%- == -- goto use_ise_library
set TMP_TARGET_DIR=%EIFFEL_LIBRARY%
goto start
:use_ise_library
if -%ISE_LIBRARY%- == -- goto use_current_dir
set TMP_TARGET_DIR=%ISE_LIBRARY%
goto start
:use_current_dir
set TMP_TARGET_DIR=%CD%\ewf
goto start
:start
set TMP_CONTRIB_DIR=%TMP_TARGET_DIR%\contrib
set TMP_UNSTABLE_DIR=%TMP_TARGET_DIR%\unstable
echo Install ROC as CMS ewf
%SAFE_RMDIR% %TMP_UNSTABLE_DIR%\library\cms\library
%SAFE_RMDIR% %TMP_UNSTABLE_DIR%\library\cms\src
%SAFE_RMDIR% %TMP_UNSTABLE_DIR%\library\cms\doc
%SAFE_RMDIR% %TMP_UNSTABLE_DIR%\library\cms\modules
%SAFE_RMDIR% %TMP_UNSTABLE_DIR%\library\cms\examples
%COPYCMD% %TMP_DIR%\library %TMP_UNSTABLE_DIR%\library\web\cms\library
%COPYCMD% %TMP_DIR%\src %TMP_UNSTABLE_DIR%\library\web\cms\src
%COPYCMD% %TMP_DIR%\doc %TMP_UNSTABLE_DIR%\library\web\cms\doc
%COPYCMD% %TMP_DIR%\modules %TMP_UNSTABLE_DIR%\library\web\cms\modules
%COPYCMD% %TMP_DIR%\examples %TMP_UNSTABLE_DIR%\library\web\cms\examples
copy %TMP_DIR%\cms.ecf %TMP_UNSTABLE_DIR%\library\web\cms\cms.ecf
copy %TMP_DIR%\cms-safe.ecf %TMP_UNSTABLE_DIR%\library\web\cms\cms-safe.ecf
copy %TMP_DIR%\README.md %TMP_UNSTABLE_DIR%\library\web\cms\README.md
copy %TMP_DIR%\package.iron %TMP_UNSTABLE_DIR%\library\web\cms\package.iron
:end
del %TMP_EXCLUDE%