Compare commits

...

30 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
c871eae10e Renamed node_api and node_storage by blog_api and blog_storage in related CMS_BLOG_* classes. Mainly to avoid confusion with NODE_ classes.
Merged CMS_BLOG_CONFIG with CMS_BLOG_API.
In CMS_BLOG_API, prefer argument of type CMS_USER, rather than using directly user id.
Added a CMS_EDITOR_CONTENT_FORMAT for now, to be the format editable by the WYSIWYG editor.
Added CMS_MODULE.is_initialized: BOOLEAN to equip router, and module_api with expected preconditions.

Fixed typo, especially in log output.
Corrected a few routine names such as add_authors that should not be a function according to its name.
Converted various function returning html content, to procedure appending html content to an output string to minimize temporary string object creation.
Cosmetic: added spaces to make code easier to read, and indentation.
2015-05-27 19:00:32 +02:00
Dario Bösch
e35893fdb9 Integrated the CKEditor
#7 and #8: The class CMS_EDITOR generates javascript code that replaces a textarea with a wysiwyg editor. Only a few methods have to be implemented by the subclasses, for example by CMD_EDITOR_CKEDITOR. The class CMS_FORM_TEXTAREA extends WSF_FORM_TEXTAREA with features to include the javascript from CMS_EDITOR. The most complex usage is shown in CMS_NODE_TYPE_WEBFORM_MANAGER, where the textarea is only replaced if "full_html" is selected as the desired body format. This works dynamically on the browser side as soon as the user selects another format.
2015-05-23 21:11:39 +02:00
Dario Bösch
e8ff313c28 added some commments 2015-05-22 17:58:46 +02:00
Dario Bösch
0bd75e7c59 Added list of posts of a specific user
Similar to the blog handler the blog user handler routes /blogs/users/{id}. Pagination is implemented as well
2015-05-22 17:31:30 +02:00
Dario Bösch
9b169f70a7 page_number global in blog_handler 2015-05-22 15:43:29 +02:00
Dario Bösch
601b88ab36 blog handler optimized, blog user handler created 2015-05-22 15:34:32 +02:00
Dario Bösch
2b0e1a2b84 Improved structure of blog handler 2015-05-22 14:39:43 +02:00
Dario Bösch
db77c4024d created blog.scss, added link to blogs/{user}
Later we will list all posts of a user under the route blogs/{user}
2015-05-22 14:04:00 +02:00
Dario Bösch
261aeca300 Bugfix: Author was hidden
I had to add the authors to each post after getting the list. Made a helper feature add_authors.
2015-05-22 12:34:30 +02:00
Dario Bösch
027463a910 #3: added pagination links at bottom of the blog page 2015-05-22 12:02:33 +02:00
Dario Bösch
a4c50adefa #3: Calculate and show number of total pages 2015-05-22 11:48:20 +02:00
Dario Bösch
1f61126d22 Configuration File added
Created CMS_BLOG_CONFIG at moved the feature entries_per_page to this new class. The blog hander inherits from the config class
2015-05-22 11:30:54 +02:00
Dario Bösch
fb196735b6 #3: Routet page and limited entries
The blog module routes /blog/{page} and the blog handler limits the entries per page (given as a feature) and sets the offsets according to the given page number
2015-05-22 11:17:34 +02:00
Dario Bösch
802ad0626e Bugfix: wrong API in initialisation of blog module 2015-05-21 16:10:07 +02:00
Dario Bösch
470b1b2e05 Restructured Blog Module
All blog handlers and storage classes are detached from the nodes module. All files of the blog module are in the modules/blog folder
2015-05-21 16:04:58 +02:00
Dario Bösch
57c2a7bccd Removed the summary from the detail page 2015-05-21 14:12:01 +02:00
Dario Bösch
4dd980963a Moved filter of nodes of type blog to the node storage layer.
This is more efficient because the result set from the query will be smaller and it will be easier to implement the pagination
2015-05-21 14:06:08 +02:00
Dario Bösch
6a782e412d #2 Structure of list of posts (blog)Ordered the posts by creation date. For this, I added a field to the nodes storage and api. Show the creation date and author. Styled the post and added a more link to the detail page 2015-05-21 12:03:09 +02:00
Dario Bösch
0e0cd131a5 #1: Added the summary field to all nodes. It gets saved if we edit the node. On a node page the summary is shown first, then the main content. In the blog list the title and the summry is shown 2015-05-21 10:18:03 +02:00
Dario Bösch
202253e414 Added summary field in edit and add mode of a node 2015-05-19 17:28:37 +02:00
Dario Bösch
f72fcce440 Link fix 2015-05-18 15:40:47 +02:00
Dario Bösch
f48f09bfdf Bugfix (blog disappeared as create option) 2015-05-18 14:49:21 +02:00
Dario Bösch
35b186cec8 gitignore 2015-05-18 14:39:49 +02:00
Dario Bösch
c65265b025 added blog handler that lists all blog entries 2015-05-18 14:36:24 +02:00
52 changed files with 1854 additions and 353 deletions

4
.gitignore vendored
View File

@@ -2,4 +2,6 @@ EIFGENs
*.swp *.swp
*.log* *.log*
*.rc *.rc
*.bak *.bak
*.sqlite
Thumbs.db

View File

@@ -1,58 +1,78 @@
<?xml version="1.0" encoding="ISO-8859-1"?> <?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="demo" uuid="3643E657-BCBE-46AA-931B-71EAEA877A18" library_target="demo"> <system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="demo" uuid="3643E657-BCBE-46AA-931B-71EAEA877A18" library_target="demo">
<description>Example/demo for Eiffel ROC CMS library</description> <description>Example/demo for Eiffel ROC CMS library</description>
<target name="common" abstract="true"> <target name="common" abstract="true">
<file_rule> <file_rule>
<exclude>/EIFGENs$</exclude> <exclude>/EIFGENs$</exclude>
<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"/>
<library name="cms_basic_auth_module" location="..\..\modules\basic_auth\basic_auth-safe.ecf" readonly="false"/> <library name="cms_basic_auth_module" location="..\..\modules\basic_auth\basic_auth-safe.ecf" readonly="false"/>
<library name="cms_blog_module" location="modules\blog\cms_blog_module-safe.ecf" readonly="false"/> <library name="cms_blog_module" location="modules\blog\cms_blog_module-safe.ecf" readonly="false"/>
<library name="cms_demo_module" location="modules\demo\cms_demo_module-safe.ecf" readonly="false"/> <library name="cms_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_sqlite" location="..\..\library\persistence\sqlite\persistence_sqlite-safe.ecf" readonly="false"/>
<library name="persistence_mysql" location="..\..\library\persistence\mysql\persistence_mysql-safe.ecf" readonly="false"/> <library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
--> <library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension-safe.ecf" readonly="false"/>
<library name="persistence_sqlite" location="..\..\library\persistence\sqlite\persistence_sqlite-safe.ecf" readonly="false"/> </target>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/> <target name="demo_any" extends="common">
<library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension-safe.ecf" readonly="false"/> <root class="EWF_ROC_SERVER" feature="make_and_launch"/>
</target> <setting name="concurrency" value="thread"/>
<target name="demo_any" extends="common"> <library name="cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\cgi-safe.ecf"/>
<root class="EWF_ROC_SERVER" feature="make_and_launch"/> <library name="libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\libfcgi-safe.ecf"/>
<library name="cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\cgi-safe.ecf"/> <library name="nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\nino-safe.ecf"/>
<library name="libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\libfcgi-safe.ecf"/> <library name="standalone" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\standalone-safe.ecf"/>
<library name="nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\nino-safe.ecf"/> <cluster name="launcher" location=".\launcher\any\" recursive="true"/>
<cluster name="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">
<target name="demo_nino" extends="common"> <root class="EWF_ROC_SERVER" feature="make_and_launch"/>
<root class="EWF_ROC_SERVER" feature="make_and_launch"/> <option debug="true">
<setting name="concurrency" value="none"/> <debug name="dbglog" enabled="true"/>
<library name="default_nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\nino-safe.ecf"/> </option>
<cluster name="launcher" location=".\launcher\default\" recursive="true"/> <setting name="concurrency" value="thread"/>
<cluster name="src" location=".\src\" recursive="true"/> <library name="default_standalone" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\standalone-safe.ecf"/>
</target> <cluster name="launcher" location=".\launcher\default\" recursive="true"/>
<target name="demo_cgi" extends="common"> <cluster name="src" location=".\src\" recursive="true"/>
<root class="EWF_ROC_SERVER" feature="make_and_launch"/> </target>
<library name="default_cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\cgi-safe.ecf"/> <target name="demo_standalone_none" extends="demo_standalone">
<cluster name="launcher" location=".\launcher\default\" recursive="true"/> <setting name="concurrency" value="none"/>
<cluster name="src" location=".\src\" recursive="true"/> </target>
</target> <target name="demo_standalone_mt" extends="demo_standalone">
<target name="demo_libfcgi" extends="common"> <setting name="concurrency" value="thread"/>
<root class="EWF_ROC_SERVER" feature="make_and_launch"/> </target>
<library name="default_libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\libfcgi-safe.ecf"/> <target name="demo_standalone_scoop" extends="demo_standalone">
<cluster name="launcher" location=".\launcher\default\" recursive="true"/> <setting name="concurrency" value="scoop"/>
<cluster name="src" location=".\src\" recursive="true"/> </target>
</target> <target name="demo_nino" extends="common">
<target name="demo" extends="demo_nino"> <root class="EWF_ROC_SERVER" feature="make_and_launch"/>
</target> <setting name="concurrency" value="none"/>
<library name="default_nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\nino-safe.ecf"/>
<cluster name="launcher" location=".\launcher\default\" recursive="true"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
<target name="demo_cgi" extends="common">
<root class="EWF_ROC_SERVER" feature="make_and_launch"/>
<setting name="concurrency" value="none"/>
<library name="default_cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\cgi-safe.ecf"/>
<cluster name="launcher" location=".\launcher\default\" recursive="true"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
<target name="demo_libfcgi" extends="common">
<root class="EWF_ROC_SERVER" feature="make_and_launch"/>
<setting name="concurrency" value="none"/>
<library name="default_libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\libfcgi-safe.ecf"/>
<cluster name="launcher" location=".\launcher\default\" recursive="true"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
<target name="demo" extends="demo_standalone">
</target>
</system> </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,14 +47,16 @@ 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)
if attached p.entry as l_entry then if attached p.entry as l_entry then
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

@@ -31,7 +31,13 @@ feature -- Conversion
do do
Precursor (a_node) Precursor (a_node)
if attached {CMS_BLOG} a_node as l_blog then if attached {CMS_BLOG} a_node as l_blog then
-- l_blog if attached l_blog.tags as l_tags then
across
l_tags as ic
loop
add_tag (ic.item)
end
end
end end
end end
@@ -42,7 +48,7 @@ feature -- Access
Result := {CMS_BLOG_NODE_TYPE}.name Result := {CMS_BLOG_NODE_TYPE}.name
end end
feature -- Access: content feature -- Access: node
summary: detachable READABLE_STRING_8 summary: detachable READABLE_STRING_8
-- A short summary of the node. -- A short summary of the node.
@@ -54,10 +60,12 @@ feature -- Access: content
-- Format associated with `content' and `summary'. -- Format associated with `content' and `summary'.
-- For example: text, mediawiki, html, etc -- For example: text, mediawiki, html, etc
feature -- Access: blog
tags: detachable ARRAYED_LIST [READABLE_STRING_32] tags: detachable ARRAYED_LIST [READABLE_STRING_32]
-- Optional tags -- Optional tags
feature -- Element change feature -- Element change: node
set_content (a_content: like content; a_summary: like summary; a_format: like format) set_content (a_content: like content; a_summary: like summary; a_format: like format)
do do
@@ -66,6 +74,8 @@ feature -- Element change
format := a_format format := a_format
end end
feature -- Element change: blog
add_tag (a_tag: READABLE_STRING_32) add_tag (a_tag: READABLE_STRING_32)
-- Set `parent' to `a_page' -- Set `parent' to `a_page'
require require

View File

@@ -0,0 +1,118 @@
note
description: "API to handle nodes of type blog. Extends the node API."
author: "Dario B<>sch <daboesch@student.ethz.ch"
date: "$Date: 2015-05-21 14:46:00 +0100$"
revision: "$Revision: 96616 $"
class
CMS_BLOG_API
inherit
CMS_MODULE_API
rename
make as make_with_cms_api
redefine
initialize
end
REFACTORING_HELPER
create
make
feature {NONE} -- Initialization
make (a_api: CMS_API; a_node_api: CMS_NODE_API)
-- (from CMS_MODULE_API)
-- (export status {NONE})
do
node_api := a_node_api
make_with_cms_api (a_api)
end
initialize
-- <Precursor>
do
Precursor
-- Create the node storage for type blog
if attached {CMS_STORAGE_SQL_I} storage as l_storage_sql then
create {CMS_BLOG_STORAGE_SQL} blog_storage.make (l_storage_sql)
else
create {CMS_BLOG_STORAGE_NULL} blog_storage.make
end
-- initialize_node_types
end
feature {CMS_API_ACCESS, CMS_MODULE, CMS_API} -- Restricted access
node_api: CMS_NODE_API
feature {CMS_MODULE} -- Access nodes storage.
blog_storage: CMS_BLOG_STORAGE_I
feature -- Configuration of blog handlers
entries_per_page : NATURAL_32 = 2
-- The numbers of posts that are shown on one page. If there are more post a pagination is generated
--| For test reasons this is 2, so we don't have to create a lot of blog entries.
--| TODO: Set to bigger constant.
feature -- Access node
blogs_count: INTEGER_64
-- Number of nodes of type blog.
do
Result := blog_storage.blogs_count
end
blogs_count_from_user (a_user: CMS_USER): INTEGER_64
-- Number of nodes of type blog from user with `a_user_id'.
require
has_id: a_user.has_id
do
Result := blog_storage.blogs_count_from_user (a_user)
end
blogs_order_created_desc: LIST [CMS_BLOG]
-- List of nodes ordered by creation date (descending)
do
Result := nodes_to_blogs (blog_storage.blogs)
end
blogs_order_created_desc_limited (a_limit: NATURAL_32; a_offset: NATURAL_32): LIST [CMS_BLOG]
-- List of nodes ordered by creation date and limited by limit and offset
do
-- load all posts and add the authors to each post
Result := nodes_to_blogs (blog_storage.blogs_limited (a_limit, a_offset))
end
blogs_from_user_order_created_desc_limited (a_user: CMS_USER; a_limit: NATURAL_32; a_offset: NATURAL_32) : LIST [CMS_BLOG]
-- List of nodes ordered by creation date and limited by limit and offset
require
has_id: a_user.has_id
do
-- load all posts and add the authors to each post
Result := nodes_to_blogs (blog_storage.blogs_from_user_limited (a_user, a_limit, a_offset))
end
feature {NONE} -- Helpers
nodes_to_blogs (a_nodes: LIST [CMS_NODE]): ARRAYED_LIST [CMS_BLOG]
-- Convert list of nodes into a list of blog when possible.
do
create {ARRAYED_LIST [CMS_BLOG]} Result.make (a_nodes.count)
if attached node_api as l_node_api then
across
a_nodes as ic
loop
if attached {CMS_BLOG} l_node_api.full_node (ic.item) as l_blog then
Result.force (l_blog)
end
end
end
end
end

View File

@@ -20,6 +20,7 @@
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/> <library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/> <library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
<library name="wsf_html" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf_html\wsf_html-safe.ecf"/> <library name="wsf_html" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf_html\wsf_html-safe.ecf"/>
<library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension-safe.ecf" readonly="false"/>
<library name="wsf_encoder" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\text\encoder\encoder-safe.ecf"/> <library name="wsf_encoder" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\text\encoder\encoder-safe.ecf"/>
<cluster name="src" location=".\" recursive="true"/> <cluster name="src" location=".\" recursive="true"/>
</target> </target>

View File

@@ -1,17 +1,21 @@
note note
description: "Summary description for {CMS_BLOG_MODULE}." description: "Displays all posts (pages with type blog). It's possible to list posts by user."
date: "$Date: 2015-02-13 13:08:13 +0100 (ven., 13 févr. 2015) $" author: "Dario B<>sch <daboesch@student.ethz.ch>"
revision: "$Revision: 96616 $" date: "$Date: 2015-05-22 15:13:00 +0100 (lun., 18 mai 2015) $"
revision: "$Revision 96616$"
class class
CMS_BLOG_MODULE CMS_BLOG_MODULE
inherit inherit
CMS_MODULE CMS_MODULE
rename
module_api as blog_api
redefine redefine
register_hooks, register_hooks,
initialize, initialize,
install install,
blog_api
end end
CMS_HOOK_MENU_SYSTEM_ALTER CMS_HOOK_MENU_SYSTEM_ALTER
@@ -39,6 +43,10 @@ feature {CMS_API} -- Module Initialization
Precursor (api) Precursor (api)
if attached {CMS_NODE_API} api.module_api ({NODE_MODULE}) as l_node_api then if attached {CMS_NODE_API} api.module_api ({NODE_MODULE}) as l_node_api then
create blog_api.make (api, l_node_api)
node_api := l_node_api
-- Depends on {NODE_MODULE}
create ct create ct
l_node_api.add_content_type (ct) l_node_api.add_content_type (ct)
l_node_api.add_content_type_webform_manager (create {CMS_BLOG_NODE_TYPE_WEBFORM_MANAGER}.make (ct)) l_node_api.add_content_type_webform_manager (create {CMS_BLOG_NODE_TYPE_WEBFORM_MANAGER}.make (ct))
@@ -75,12 +83,53 @@ CREATE TABLE "blog_post_nodes"(
end end
end end
feature {CMS_API} -- Access: API
blog_api: detachable CMS_BLOG_API
-- <Precursor>
node_api: detachable CMS_NODE_API
feature -- Access: router 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>
do do
a_router.handle_with_request_methods ("/blogs/", create {WSF_URI_AGENT_HANDLER}.make (agent handle_blogs (?,?, a_api)), a_router.methods_get) if attached blog_api as l_blog_api then
configure_web (a_api, l_blog_api, a_router)
else
-- Issue with api/dependencies,
-- thus Current module should not be used!
-- thus no url mapping
end
end
configure_web (a_api: CMS_API; a_blog_api: CMS_BLOG_API; a_router: WSF_ROUTER)
-- Configure router mapping for web interface.
local
l_blog_handler: BLOG_HANDLER
l_blog_user_handler: BLOG_USER_HANDLER
l_uri_mapping: WSF_URI_MAPPING
do
-- TODO: for now, focused only on web interface, add REST api later. [2015-May-18]
create l_blog_handler.make (a_api, a_blog_api)
create l_blog_user_handler.make (a_api, a_blog_api)
-- Let the class BLOG_HANDLER handle the requests on "/blogs"
create l_uri_mapping.make_trailing_slash_ignored ("/blogs", l_blog_handler)
a_router.map_with_request_methods (l_uri_mapping, a_router.methods_get)
-- We can add a page number after /blogs/ to get older posts
a_router.handle_with_request_methods ("/blogs/page/{page}", l_blog_handler, a_router.methods_get)
-- If a user id is given route with blog user handler
--| FIXME: maybe /user/{user}/blogs/ would be better.
a_router.handle_with_request_methods ("/blogs/user/{user}", l_blog_user_handler, a_router.methods_get)
-- If a user id is given we also want to allow different pages
--| FIXME: what about /user/{user}/blogs/?page={page} ?
a_router.handle_with_request_methods ("/blogs/user/{user}/page/{page}", l_blog_user_handler, a_router.methods_get)
end end
feature -- Hooks feature -- Hooks
@@ -94,19 +143,8 @@ feature -- Hooks
local local
lnk: CMS_LOCAL_LINK lnk: CMS_LOCAL_LINK
do do
-- 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
feature -- Handler
handle_blogs (req: WSF_REQUEST; res: WSF_RESPONSE; a_api: CMS_API)
local
r: NOT_IMPLEMENTED_ERROR_CMS_RESPONSE
do
create r.make (req, res, a_api)
r.set_main_content ("Blog module is in development ...")
r.execute
end
end end

View File

@@ -17,10 +17,11 @@ feature {NONE} -- Initialization
default_create default_create
do do
Precursor Precursor
create {ARRAYED_LIST [like available_formats.item]} available_formats.make (3) create {ARRAYED_LIST [like available_formats.item]} available_formats.make (4)
available_formats.extend (create {PLAIN_TEXT_CONTENT_FORMAT}) available_formats.extend (create {PLAIN_TEXT_CONTENT_FORMAT})
available_formats.extend (create {FILTERED_HTML_CONTENT_FORMAT}) available_formats.extend (create {FILTERED_HTML_CONTENT_FORMAT})
available_formats.extend (create {FULL_HTML_CONTENT_FORMAT}) available_formats.extend (create {FULL_HTML_CONTENT_FORMAT})
available_formats.extend (create {CMS_EDITOR_CONTENT_FORMAT})
end end
feature -- Access feature -- Access

View File

@@ -0,0 +1,279 @@
note
description: "Request handler related to /blogs and /blogs/{page}. Displays all posts in the blog."
author: "Dario B<>sch <daboesch@student.ethz.ch>"
date: "$Date: 2015-05-18 13:49:00 +0100 (lun., 18 mai 2015) $"
revision: "$9661667$"
class
BLOG_HANDLER
inherit
CMS_BLOG_HANDLER
WSF_URI_HANDLER
rename
execute as uri_execute,
new_mapping as new_uri_mapping
end
WSF_URI_TEMPLATE_HANDLER
rename
execute as uri_template_execute,
new_mapping as new_uri_template_mapping
select
new_uri_template_mapping
end
WSF_RESOURCE_HANDLER_HELPER
redefine
do_get
end
REFACTORING_HELPER
CMS_API_ACCESS
create
make
feature -- execute
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
-- Execute request handler for any kind of mapping.
do
execute_methods (req, res)
end
uri_execute (req: WSF_REQUEST; res: WSF_RESPONSE)
-- Execute request handler for URI mapping.
do
execute (req, res)
end
uri_template_execute (req: WSF_REQUEST; res: WSF_RESPONSE)
-- Execute request handler for URI-template mapping.
do
execute (req, res)
end
feature -- Global Variables
page_number: NATURAL_32
-- Current page number.
feature -- HTTP Methods
do_get (req: WSF_REQUEST; res: WSF_RESPONSE)
-- <Precursor>
local
l_page: CMS_RESPONSE
do
-- Read page number from path parameter.
page_number := page_number_path_parameter (req)
-- Responding with `main_content_html (l_page)'.
create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)
l_page.set_main_content (main_content_html (l_page))
l_page.execute
end
feature -- Query
posts: LIST [CMS_NODE]
-- Blog posts to display on given page ordered by date (descending).
do
Result := blog_api.blogs_order_created_desc_limited (
entries_per_page,
entries_per_page * (page_number - 1)
)
end
multiple_pages_needed : BOOLEAN
-- Return if more that one page is needed to display posts.
do
Result := entries_per_page < total_entries
end
pages_count: NATURAL_32
-- Number of pages needed to display all posts.
require
entries_per_page > 0
local
tmp: REAL_32
do
tmp := total_entries.to_real_32 / entries_per_page.to_real_32;
Result := tmp.ceiling.to_natural_32
end
page_number_path_parameter (req: WSF_REQUEST): NATURAL_32
-- Page number from path /blogs/{page}.
-- Unsigned integer since negative pages are not allowed.
local
s: STRING
do
Result := 1 -- default if not get variable is set
if attached {WSF_STRING} req.path_parameter ("page") as p_page then
s := p_page.value
if s.is_natural_32 then
if s.to_natural_32 > 1 then
Result := s.to_natural_32
end
end
end
end
total_entries: NATURAL_32
-- Total number of entries/posts.
do
Result := blog_api.blogs_count.to_natural_32
end
feature -- HTML Output
frozen main_content_html (page: CMS_RESPONSE): STRING
-- Content of the page as a html string.
do
create Result.make_empty
append_main_content_html_to (page, Result)
end
append_main_content_html_to (page: CMS_RESPONSE; a_output: STRING)
-- Append to `a_output, the content of the page as a html string.
local
n: CMS_NODE
lnk: CMS_LOCAL_LINK
do
-- Output the title. If more than one page, also output the current page number
append_page_title_html_to (a_output)
-- Get the posts from the current page (given by page number and entries per page)
-- Start list of posts
a_output.append ("<ul class=%"cms_blog_nodes%">%N")
across
posts as ic
loop
n := ic.item
lnk := blog_api.node_api.node_link (n)
a_output.append ("<li class=%"cms_type_"+ n.content_type +"%">")
-- Output the creation date
append_creation_date_html_to (n, a_output)
-- Output the author of the post
append_author_html_to (n, a_output)
-- Output the title of the post as a link (to the detail page)
append_title_html_to (n, page, a_output)
-- Output the summary of the post and a more link to the detail page
append_summary_html_to (n, page, a_output)
a_output.append ("</li>%N")
end
-- End of post list
a_output.append ("</ul>%N")
-- Pagination (older and newer links)
append_pagination_html_to (a_output)
end
append_page_title_html_to (a_output: STRING)
-- Append the title of the page as a html string to `a_output'.
-- It shows the current page number.
do
a_output.append ("<h2>Blog")
if multiple_pages_needed then
a_output.append (" (Page " + page_number.out + " of " + pages_count.out + ")")
end
a_output.append ("</h2>")
end
append_creation_date_html_to (n: CMS_NODE; a_output: STRING)
-- Append the creation date as a html string to `a_output'.
local
hdate: HTTP_DATE
do
if attached n.creation_date as l_modified then
create hdate.make_from_date_time (l_modified)
hdate.append_to_yyyy_mmm_dd_string (a_output)
a_output.append (" ")
end
end
append_author_html_to (n: CMS_NODE; a_output: STRING)
-- Append to `a_output', the author of node `n' as html link to author's posts.
do
if attached n.author as l_author then
a_output.append ("by ")
a_output.append ("<a class=%"blog_user_link%" href=%"/blogs/user/" + l_author.id.out + "%">" + l_author.name + "</a>")
end
end
append_title_html_to (n: CMS_NODE; page: CMS_RESPONSE; a_output: STRING)
-- Append to `a_output', the title of node `n' as html link to detail page.
local
lnk: CMS_LOCAL_LINK
do
lnk := blog_api.node_api.node_link (n)
a_output.append ("<span class=%"blog_title%">")
a_output.append (page.link (lnk.title, lnk.location, Void))
a_output.append ("</span>")
end
append_summary_html_to (n: CMS_NODE; page: CMS_RESPONSE; a_output: STRING)
-- returns a html string with the summary of the node and a link to the detail page
local
lnk: CMS_LOCAL_LINK
do
if attached n.summary as l_summary then
lnk := blog_api.node_api.node_link (n)
a_output.append ("<p class=%"blog_list_summary%">")
if attached api.format (n.format) as f then
a_output.append (f.formatted_output (l_summary))
else
a_output.append (page.formats.default_format.formatted_output (l_summary))
end
a_output.append ("<br />")
a_output.append (page.link ("See more...", lnk.location, Void))
a_output.append ("</p>")
end
end
append_pagination_html_to (a_output: STRING)
-- Append to `a_output' with the pagination links (if necessary).
local
tmp: NATURAL_32
do
if multiple_pages_needed then
a_output.append ("<div class=%"pagination%">")
-- If exist older posts show link to next page
if page_number < pages_count then
tmp := page_number + 1
a_output.append (" <a class=%"blog_older_posts%" href=%"" + base_path + "/page/" + tmp.out + "%"><< Older Posts</a> ")
end
-- Delimiter
if page_number < pages_count AND page_number > 1 then
a_output.append (" | ")
end
-- If exist newer posts show link to previous page
if page_number > 1 then
tmp := page_number -1
a_output.append (" <a class=%"blog_newer_posts%" href=%"" + base_path + "/page/" + tmp.out + "%">Newer Posts >></a> ")
end
a_output.append ("</div>")
end
end
base_path : STRING
-- the path to the page that lists all blogs
do
Result := "/blogs"
end
end

View File

@@ -0,0 +1,150 @@
note
description: "[
Request handler related to
/blogs/user/{id}/
or /blogs/user/{id}/page/{page}.
Displays all posts of the given user
]"
author: "Dario B<>sch <daboesch@student.ethz.ch>"
date: "$Date: 2015-05-22 15:13:00 +0100 (lun., 18 mai 2015) $"
revision: "$Revision 96616$"
class
BLOG_USER_HANDLER
inherit
BLOG_HANDLER
redefine
do_get,
posts,
total_entries,
append_page_title_html_to,
base_path
end
create
make
feature -- Global Variables
user : detachable CMS_USER
feature -- HTTP Methods
do_get (req: WSF_REQUEST; res: WSF_RESPONSE)
-- <Precursor>
local
l_error: NOT_FOUND_ERROR_CMS_RESPONSE
do
user := Void
if attached user_from_request (req) as l_user then
user := l_user
-- Output the results, similar as in the blog hanlder (but with other queries)
Precursor (req, res)
else
-- Throw a bad request error because the user is not valid
create l_error.make (req, res, api)
l_error.set_main_content ("<h1>Error</h1>User with id " + user_id_path_parameter (req).out + " doesn't exist!")
l_error.execute
end
end
feature -- Query
user_valid (req: WSF_REQUEST) : BOOLEAN
-- Returns true if a valid user id is given and a user with this id exists,
-- otherwise returns false.
local
user_id: INTEGER_32
do
user_id := user_id_path_parameter (req)
if user_id <= 0 then
-- Given user id is not valid
Result := False
else
--Check if user with user_id exists
Result := api.user_api.user_by_id (user_id) /= Void
end
end
user_from_request (req: WSF_REQUEST): detachable CMS_USER
-- Eventual user with given id in the path of request `req'.
local
uid: like user_id_path_parameter
do
uid := user_id_path_parameter (req)
if uid > 0 then
Result := api.user_api.user_by_id (uid)
else
-- Missing or invalid user id.
end
end
user_id_path_parameter (req: WSF_REQUEST): INTEGER_32
-- User id from path /blogs/{user}.
-- Unsigned integer since negative ids are not allowed.
-- If no valid id can be read it returns -1
local
s: STRING
do
Result := -1
if attached {WSF_STRING} req.path_parameter ("user") as l_user_id then
if l_user_id.is_integer then
Result := l_user_id.integer_value
end
end
end
posts: LIST [CMS_BLOG]
-- Blog posts to display on given page.
-- Filters out the posts of the current user.
do
if attached user as l_user then
Result := blog_api.blogs_from_user_order_created_desc_limited (l_user, entries_per_page, entries_per_page * (page_number - 1))
else
create {ARRAYED_LIST [CMS_BLOG]} Result.make (0)
end
end
total_entries : NATURAL_32
-- Returns the number of total entries/posts of the current user
do
if attached user as l_user then
Result := blog_api.blogs_count_from_user (l_user).to_natural_32
else
Result := Precursor
end
end
feature -- HTML Output
append_page_title_html_to (a_output: STRING)
-- Returns the title of the page as a html string. It shows the current page number and the name of the current user
do
a_output.append ("<h2>Posts from ")
if attached user as l_user then
a_output.append (l_user.name)
else
a_output.append ("unknown user")
end
if multiple_pages_needed then
a_output.append (" (Page " + page_number.out + " of " + pages_count.out + ")")
-- Get the posts from the current page (limited by entries per page)
end
a_output.append ("</h2>")
end
base_path : STRING
-- Path to page listing all blogs.
-- If user is logged in, include user id
do
if attached user as l_user then
Result := "/blogs/user/" + l_user.id.out
else
Result := precursor
end
end
end

View File

@@ -0,0 +1,23 @@
note
description: "Deferred request handler related to /blogs/... Has an own blog api."
author: "Dario B<>sch <daboesch@student.ethz.ch>"
date: "$Date: 2015-05-18 13:49:00 +0100 (lun., 18 mai 2015) $"
revision: "$9661667$"
deferred class
CMS_BLOG_HANDLER
inherit
CMS_MODULE_HANDLER [CMS_BLOG_API]
rename
module_api as blog_api
end
feature -- Access
entries_per_page: NATURAL_32
do
Result := blog_api.entries_per_page
end
end

View File

@@ -0,0 +1,43 @@
note
description: "Interface for accessing blog contents from the database."
date: "$Date: 2015-01-27 19:15:02 +0100 (mar., 27 janv. 2015) $"
revision: "$Revision: 96542 $"
deferred class
CMS_BLOG_STORAGE_I
inherit
CMS_NODE_STORAGE_I
feature -- Access
blogs_count: INTEGER_64
-- Count of blog nodes
deferred
end
blogs_count_from_user (a_user: CMS_USER) : INTEGER_64
-- Number of nodes of type blog from `a_user'.
require
has_id: a_user.has_id
deferred
end
blogs: LIST [CMS_NODE]
-- List of nodes ordered by creation date (descending).
deferred
end
blogs_limited (limit: NATURAL_32; offset: NATURAL_32): LIST [CMS_NODE]
-- List of posts ordered by creation date from offset to offset + limit.
deferred
end
blogs_from_user_limited (a_user: CMS_USER; limit: NATURAL_32; offset: NATURAL_32): LIST [CMS_NODE]
-- List of posts from `a_user' ordered by creation date from offset to offset + limit.
require
has_id: a_user.has_id
deferred
end
end

View File

@@ -0,0 +1,47 @@
note
description: "Summary description for {CMS_BLOG_STORAGE_NULL}."
author: ""
date: "$Date$"
revision: "$Revision$"
class
CMS_BLOG_STORAGE_NULL
inherit
CMS_NODE_STORAGE_NULL
CMS_BLOG_STORAGE_I
create
make
feature -- Access
blogs_count: INTEGER_64
-- Count of nodes.
do
end
blogs_count_from_user (a_user: CMS_USER) : INTEGER_64
-- <Precursor>
do
end
blogs: LIST [CMS_NODE]
-- <Precursor>
do
create {ARRAYED_LIST [CMS_NODE]} Result.make (0)
end
blogs_limited (limit: NATURAL_32; offset: NATURAL_32) : LIST [CMS_NODE]
-- <Precursor>
do
create {ARRAYED_LIST [CMS_NODE]} Result.make (0)
end
blogs_from_user_limited (a_user: CMS_USER; limit: NATURAL_32; offset: NATURAL_32): LIST [CMS_NODE]
-- <Precursor>
do
create {ARRAYED_LIST [CMS_NODE]} Result.make (0)
end
end

View File

@@ -0,0 +1,140 @@
note
description: "Access to the sql database for the blog module"
author: "Dario B<>sch <daboesch@student.ethz.ch>"
date: "$Date: 2015-05-21 14:46:00 +0100$"
revision: "$Revision: 96616 $"
class
CMS_BLOG_STORAGE_SQL
inherit
CMS_NODE_STORAGE_SQL
CMS_BLOG_STORAGE_I
create
make
feature -- Access
blogs_count: INTEGER_64
-- <Precursor>
do
error_handler.reset
write_information_log (generator + ".blogs_count")
sql_query (sql_select_blog_count, Void)
if sql_rows_count = 1 then
Result := sql_read_integer_64 (1)
end
end
blogs_count_from_user (a_user: CMS_USER) : INTEGER_64
-- <Precursor>
local
l_parameters: STRING_TABLE [detachable ANY]
do
error_handler.reset
write_information_log (generator + ".blogs_count_from_user")
create l_parameters.make (2)
l_parameters.put (a_user.id, "user")
sql_query (sql_select_blog_count_from_user, l_parameters)
if sql_rows_count = 1 then
Result := sql_read_integer_64 (1)
end
end
blogs: LIST [CMS_NODE]
-- <Precursor>
do
create {ARRAYED_LIST [CMS_NODE]} Result.make (0)
error_handler.reset
write_information_log (generator + ".blogs")
from
sql_query (sql_select_blogs_order_created_desc, Void)
sql_start
until
sql_after
loop
if attached fetch_node as l_node then
Result.force (l_node)
end
sql_forth
end
end
blogs_limited (a_limit: NATURAL_32; a_offset: NATURAL_32): LIST [CMS_NODE]
-- <Precursor>
local
l_parameters: STRING_TABLE [detachable ANY]
do
create {ARRAYED_LIST [CMS_NODE]} Result.make (0)
error_handler.reset
write_information_log (generator + ".blogs_limited")
from
create l_parameters.make (2)
l_parameters.put (a_limit, "limit")
l_parameters.put (a_offset, "offset")
sql_query (sql_blogs_limited, l_parameters)
sql_start
until
sql_after
loop
if attached fetch_node as l_node then
Result.force (l_node)
end
sql_forth
end
end
blogs_from_user_limited (a_user: CMS_USER; a_limit: NATURAL_32; a_offset: NATURAL_32): LIST [CMS_NODE]
-- <Precursor>
local
l_parameters: STRING_TABLE [detachable ANY]
do
create {ARRAYED_LIST [CMS_NODE]} Result.make (0)
error_handler.reset
write_information_log (generator + ".blogs_from_user_limited")
from
create l_parameters.make (2)
l_parameters.put (a_limit, "limit")
l_parameters.put (a_offset, "offset")
l_parameters.put (a_user.id, "user")
sql_query (sql_blogs_from_user_limited, l_parameters)
sql_start
until
sql_after
loop
if attached fetch_node as l_node then
Result.force (l_node)
end
sql_forth
end
end
feature {NONE} -- Queries
sql_select_blog_count: STRING = "SELECT count(*) FROM Nodes WHERE status != -1 AND type = %"blog%";"
-- Nodes count (Published and not Published)
--| note: {CMS_NODE_API}.trashed = -1
sql_select_blog_count_from_user: STRING = "SELECT count(*) FROM Nodes WHERE status != -1 AND type = %"blog%" AND author = :user ;"
-- Nodes count (Published and not Published)
--| note: {CMS_NODE_API}.trashed = -1
sql_select_blogs_order_created_desc: STRING = "SELECT * FROM Nodes WHERE status != -1 AND type = %"blog%" ORDER BY created DESC;"
-- SQL Query to retrieve all nodes that are from the type "blog" ordered by descending creation date.
sql_blogs_limited: STRING = "SELECT * FROM Nodes WHERE status != -1 AND type = %"blog%" ORDER BY created DESC LIMIT :limit OFFSET :offset ;"
--- SQL Query to retrieve all node of type "blog" limited by limit and starting at offset
sql_blogs_from_user_limited: STRING = "SELECT * FROM Nodes WHERE status != -1 AND type = %"blog%" AND author = :user ORDER BY created DESC LIMIT :limit OFFSET :offset ;"
--- SQL Query to retrieve all node of type "blog" from author with id limited by limit + offset
end

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

@@ -0,0 +1,25 @@
ul.cms_blog_nodes {
padding: 0;
margin: 0;
}
ul.cms_blog_nodes li.cms_type_blog {
list-style: none;
display: block;
margin-top: 20px;
padding-bottom: 20px;
border-bottom: 1px dotted black;
}
ul.cms_blog_nodes li.cms_type_blog .blog_title a {
color: black;
font-size: 18px;
text-decoration: none;
display: block;
margin: 6px 0;
}
ul.cms_blog_nodes li.cms_type_blog .blog_title a:hover {
color: #999;
}
ul.cms_blog_nodes li.cms_type_blog .blog_list_summary a {
margin-top: 20px;
display: block;
}

View File

@@ -3,13 +3,15 @@ ul.cms-nodes {
padding: 3px 3px 3px 3px; padding: 3px 3px 3px 3px;
border: solid 1px #ccc; border: solid 1px #ccc;
} }
ul.cms-nodes li {
li.cms_type_page {
border-top: dotted 1px #ccc; border-top: dotted 1px #ccc;
} }
li.cms_type_page a::before { ul.cms-nodes li:first-child {
content: "[page] ";
}
li.cms_type_page:first-child {
border-top: none; border-top: none;
} }
ul.cms-nodes li.cms_type_page a::before {
content: "[page] ";
}
ul.cms-nodes li.cms_type_blog a::before {
content: "[blog] ";
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 994 B

View File

@@ -0,0 +1,30 @@
ul.cms_blog_nodes{
padding:0;
margin:0;
li.cms_type_blog{
list-style: none;
display: block;
margin-top:20px;
padding-bottom:20px;
border-bottom:1px dotted black;
.blog_title a{
color:black;
font-size:18px;
text-decoration: none;
display:block;
margin:6px 0;
&:hover{
color:#999;
}
}
.blog_list_summary a{
margin-top:20px;
display:block;
}
}
}

View File

@@ -1,14 +1,24 @@
ul.cms-nodes { ul.cms-nodes {
list-style-type: none; list-style-type: none;
padding: 3px 3px 3px 3px; padding: 3px 3px 3px 3px;
border: solid 1px #ccc; border: solid 1px #ccc;
}
li.cms_type_page { li{
a::before { border-top: dotted 1px #ccc;
&:first-child {
border-top: none;
}
}
li.cms_type_page a::before {
content: "[page] "; content: "[page] ";
} }
border-top: dotted 1px #ccc;
&:first-child { li.cms_type_blog a::before {
border-top: none; content: "[blog] ";
} }
} }

View File

@@ -4,10 +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">
<script src="{$site_url/}/theme/js/jquery-1.10.2.min.js"></script>
<script src="{$site_url/}/theme/js/roc_auth.js"></script> <!-- CMS Blog Module -->
<link rel="stylesheet" href="{$site_url/}theme/css/blog.css">
<script src="{$site_url/}theme/js/jquery-1.10.2.min.js"></script>
<script src="{$site_url/}theme/js/roc_auth.js"></script>
<!-- bootstrap framework --> <!-- 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
log.write_information (create {STRING}.make_from_separate (a_message)) if level >= log_information then
end log.write_information (create {STRING}.make_from_separate (a_message))
end
put_error (a_message: separate READABLE_STRING_8)
-- Put message `a_message' to the log at error level.
do
log.write_error (create {STRING}.make_from_separate (a_message))
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
log.write_warning (create {STRING}.make_from_separate (a_message)) if level >= log_warning then
log.write_warning (create {STRING}.make_from_separate (a_message))
end
end
put_error (a_message: separate READABLE_STRING_8)
-- Put message `a_message' to the log at error level.
do
if level >= log_error then
log.write_error (create {STRING}.make_from_separate (a_message))
end
end 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
log.write_critical (create {STRING}.make_from_separate (a_message)) if level >= log_critical then
log.write_critical (create {STRING}.make_from_separate (a_message))
end
end 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
log.write_alert (create {STRING}.make_from_separate (a_message)) if level >= log_alert then
end log.write_alert (create {STRING}.make_from_separate (a_message))
end
put_debug (a_message: separate READABLE_STRING_8)
-- Put message `a_message' to the log at debug level.
do
log.write_debug (create {STRING}.make_from_separate (a_message))
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)
l_logs_path := l_logger_config.location create p.make_from_separate (app.application_config_path)
if l_logs_path = Void then -- l_name := app.name
l_logs_path := app.logs_path -- p := app.application_config_path
l_logger_config := new_logger_level_configuration (p)
if l_logger_config.type.is_case_insensitive_equal_general ("file") then
l_logs_path := l_logger_config.location
if l_logs_path = Void then
create l_logs_path.make_from_separate (app.logs_path)
end
if ut.directory_path_exists (l_logs_path) then
create l_log_writer_file.make_at_location (l_logs_path.extended (l_name).appended_with_extension ("log"))
l_log_writer_file.set_max_file_size ({NATURAL_64} 1024 * 1204)
l_log_writer_file.set_max_backup_count (l_logger_config.backup_count)
l_log_writer := l_log_writer_file
else
-- Should we create the directory anyway ?
end
elseif l_logger_config.type.is_case_insensitive_equal_general ("stderr") then
create {LOG_WRITER_STDERR} l_log_writer
end end
if ut.directory_path_exists (l_logs_path) then if l_log_writer = Void then
create l_log_writer_file.make_at_location (l_logs_path.extended (app.name).appended_with_extension ("log"))
l_log_writer_file.set_max_file_size ({NATURAL_64} 1024 * 1204)
l_log_writer_file.set_max_backup_count (l_logger_config.backup_count)
l_log_writer := l_log_writer_file
else
-- Should we create the directory anyway ?
create {LOG_WRITER_NULL} l_log_writer 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 end
set_logger_level (l_log_writer, l_logger_config.level)
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
a_log.put_debug (m) if not retried then
a_log.put_debug (m)
end
rescue
retried := True
retry
end 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
a_log.put_information (m) if not retried then
a_log.put_information (m)
end
rescue
retried := True
retry
end 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
a_log.put_warning (m) if not retried then
a_log.put_warning (m)
end
rescue
retried := True
retry
end 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
a_log.put_error (m) if not retried then
a_log.put_error (m)
end
rescue
retried := True
retry
end 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
a_log.put_critical (m) if not retried then
a_log.put_critical (m)
end
rescue
retried := True
retry
end 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
a_log.put_alert (m) if not retried then
a_log.put_alert (m)
end
rescue
retried := True
retry
end 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

@@ -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;")
create {DATABASE_CONNECTION_ODBC} conn.login_with_connection_string (s) if attached reuseable_connection.item as d then
if s.same_string (d.name) then
conn := d.connection
end
end
if conn = Void or else not conn.is_connected then
create {DATABASE_CONNECTION_ODBC} conn.login_with_connection_string (s)
reuseable_connection.replace ([s, conn])
end
if conn.is_connected then 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

@@ -22,12 +22,13 @@ feature -- Basic operations
-- Execute the filter. -- Execute the filter.
local local
l_auth: HTTP_AUTHORIZATION l_auth: HTTP_AUTHORIZATION
utf: UTF_CONVERTER
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)
if attached req.raw_header_data as l_raw_data then debug
api.logger.put_debug (generator + ".execute " + utf.escaped_utf_32_string_to_utf_8_string_8 (l_raw_data), Void) if attached req.raw_header_data as l_raw_data then
api.logger.put_debug (generator + ".execute " + (create {UTF_CONVERTER}).escaped_utf_32_string_to_utf_8_string_8 (l_raw_data), Void)
end
end end
-- A valid user -- A valid user
if if

View File

@@ -17,10 +17,11 @@ feature {NONE} -- Initialization
default_create default_create
do do
Precursor Precursor
create {ARRAYED_LIST [like available_formats.item]} available_formats.make (3) create {ARRAYED_LIST [like available_formats.item]} available_formats.make (4)
available_formats.extend (create {PLAIN_TEXT_CONTENT_FORMAT}) available_formats.extend (create {PLAIN_TEXT_CONTENT_FORMAT})
available_formats.extend (create {FILTERED_HTML_CONTENT_FORMAT}) available_formats.extend (create {FILTERED_HTML_CONTENT_FORMAT})
available_formats.extend (create {FULL_HTML_CONTENT_FORMAT}) available_formats.extend (create {FULL_HTML_CONTENT_FORMAT})
available_formats.extend (create {CMS_EDITOR_CONTENT_FORMAT})
end end
feature -- Access feature -- Access

View File

@@ -17,11 +17,14 @@ feature -- Forms ...
local local
ti: WSF_FORM_TEXT_INPUT ti: WSF_FORM_TEXT_INPUT
fset: WSF_FORM_FIELD_SET fset: WSF_FORM_FIELD_SET
ta: WSF_FORM_TEXTAREA ta, sum: CMS_FORM_TEXTAREA
tselect: WSF_FORM_SELECT tselect: WSF_FORM_SELECT
opt: WSF_FORM_SELECT_OPTION opt: WSF_FORM_SELECT_OPTION
cms_format: CMS_EDITOR_CONTENT_FORMAT
l_uri: detachable READABLE_STRING_8 l_uri: detachable READABLE_STRING_8
do do
create cms_format
create ti.make ("title") create ti.make ("title")
ti.set_label ("Title") ti.set_label ("Title")
ti.set_size (70) ti.set_size (70)
@@ -33,25 +36,47 @@ feature -- Forms ...
f.extend_html_text ("<br/>") f.extend_html_text ("<br/>")
create ta.make ("body") -- Select field has to be initialized before textareas are replaced, because they depend on the selection of the field
ta.set_rows (10)
ta.set_cols (70)
if a_node /= Void then
ta.set_text_value (a_node.content)
end
-- ta.set_label ("Body")
ta.set_description ("This is the main content")
ta.set_is_required (False)
create fset.make
fset.set_legend ("Body")
fset.extend (ta)
fset.extend_html_text ("<br/>")
create tselect.make ("format") create tselect.make ("format")
tselect.set_label ("Body's format") tselect.set_label ("Body's format")
tselect.set_is_required (True) tselect.set_is_required (True)
-- Main Content
create ta.make ("body")
ta.set_rows (10)
ta.set_cols (70)
ta.show_as_editor_if_selected (tselect, cms_format.name)
if a_node /= Void then
ta.set_text_value (a_node.content)
end
ta.set_label ("Content")
ta.set_description ("This is the main content")
ta.set_is_required (False)
-- Summary
create sum.make ("summary")
sum.set_rows (3)
sum.set_cols (70)
-- if cms_html is selected
sum.show_as_editor_if_selected (tselect, cms_format.name)
if a_node /= Void then
sum.set_text_value (a_node.summary)
end
sum.set_label ("Summary")
sum.set_description ("This is the summary")
sum.set_is_required (False)
create fset.make
fset.set_legend ("Body")
-- Add summary
fset.extend (sum)
fset.extend_html_text("<br />")
-- Add content (body)
fset.extend (ta)
fset.extend_html_text ("<br/>")
across across
content_type.available_formats as c content_type.available_formats as c
loop loop
@@ -69,7 +94,7 @@ feature -- Forms ...
f.extend (fset) f.extend (fset)
-- Path alias -- Path alias
create ti.make ("path_alias") create ti.make ("path_alias")
ti.set_label ("Path") ti.set_label ("Path")
ti.set_size (70) ti.set_size (70)
@@ -113,7 +138,7 @@ feature -- Forms ...
update_node (response: NODE_RESPONSE; fd: WSF_FORM_DATA; a_node: CMS_NODE) update_node (response: NODE_RESPONSE; fd: WSF_FORM_DATA; a_node: CMS_NODE)
local local
b: detachable READABLE_STRING_8 b,s: detachable READABLE_STRING_8
f: detachable CONTENT_FORMAT f: detachable CONTENT_FORMAT
do do
if attached fd.integer_item ("id") as l_id and then l_id > 0 then if attached fd.integer_item ("id") as l_id and then l_id > 0 then
@@ -126,6 +151,12 @@ feature -- Forms ...
if attached fd.string_item ("body") as l_body then if attached fd.string_item ("body") as l_body then
b := l_body b := l_body
end end
-- Read out the summary field from the form data
if attached fd.string_item ("summary") as l_summary then
s := l_summary
end
if attached fd.string_item ("format") as s_format and then attached response.api.format (s_format) as f_format then if attached fd.string_item ("format") as s_format and then attached response.api.format (s_format) as f_format then
f := f_format f := f_format
elseif a_node /= Void and then attached a_node.format as s_format and then attached response.api.format (s_format) as f_format then elseif a_node /= Void and then attached a_node.format as s_format and then attached response.api.format (s_format) as f_format then
@@ -133,15 +164,19 @@ feature -- Forms ...
else else
f := response.formats.default_format f := response.formats.default_format
end end
-- Update node with summary and body content
if b /= Void then if b /= Void then
a_node.set_content (b, Void, f.name) -- FIXME: summary a_node.set_content (b, s, f.name)
end end
end end
new_node (response: NODE_RESPONSE; fd: WSF_FORM_DATA; a_node: detachable CMS_NODE): G new_node (response: NODE_RESPONSE; fd: WSF_FORM_DATA; a_node: detachable CMS_NODE): G
-- <Precursor> -- <Precursor>
local local
b: detachable READABLE_STRING_8 b,s: detachable READABLE_STRING_8
f: detachable CONTENT_FORMAT f: detachable CONTENT_FORMAT
l_node: detachable like new_node l_node: detachable like new_node
do do
@@ -175,9 +210,16 @@ feature -- Forms ...
end end
l_node.set_author (response.user) l_node.set_author (response.user)
--Summary
if attached fd.string_item ("summary") as l_summary then
s := l_summary
end
--Content
if attached fd.string_item ("body") as l_body then if attached fd.string_item ("body") as l_body then
b := l_body b := l_body
end end
if attached fd.string_item ("format") as s_format and then attached response.api.format (s_format) as f_format then if attached fd.string_item ("format") as s_format and then attached response.api.format (s_format) as f_format then
f := f_format f := f_format
elseif a_node /= Void and then attached a_node.format as s_format and then attached response.api.format (s_format) as f_format then elseif a_node /= Void and then attached a_node.format as s_format and then attached response.api.format (s_format) as f_format then
@@ -185,8 +227,10 @@ feature -- Forms ...
else else
f := response.formats.default_format f := response.formats.default_format
end end
-- Update node with summary and content
if b /= Void then if b /= Void then
l_node.set_content (b, Void, f.name) l_node.set_content (b, s, f.name)
end end
Result := l_node Result := l_node
end end
@@ -243,6 +287,23 @@ feature -- Output
s.append (")") s.append (")")
end end
s.append ("</div>") s.append ("</div>")
-- We don't show the summary on the detail page, since its just a short view of the full content. Otherwise we would write the same thing twice.
-- The usage of the summary is to give a short overview in the list of nodes or for the meta tag "description"
-- if attached a_node.summary as l_summary then
-- s.append ("<p class=%"summary%">")
-- if attached node_api.cms_api.format (a_node.format) as f then
-- s.append (f.formatted_output (l_summary))
-- else
-- s.append (a_response.formats.default_format.formatted_output (l_summary))
-- end
-- s.append ("</p>")
-- end
if attached a_node.content as l_content then if attached a_node.content as l_content then
s.append ("<p class=%"content%">") s.append ("<p class=%"content%">")
if attached node_api.cms_api.format (a_node.format) as f then if attached node_api.cms_api.format (a_node.format) as f then

View File

@@ -63,7 +63,7 @@ feature -- HTTP Methods
create s_pager.make_empty 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 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) l_page_helper.get_setting_from_request (req)
if l_page_helper.pages_count > 1 then 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) l_page_helper.append_to_html (l_response, s_pager)
if l_page_helper.page_size > 25 then if l_page_helper.page_size > 25 then
s.append (s_pager) s.append (s_pager)

View File

@@ -47,9 +47,8 @@ feature -- HTTP Methods
-- 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)
if attached current_user (req) as l_user then 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") l_page.add_variable (node_api.trashed_nodes (l_user), "nodes")
@@ -72,6 +71,9 @@ feature -- HTTP Methods
l_page.set_main_content (s) 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.add_block (create {CMS_CONTENT_BLOCK}.make ("nodes_warning", Void, "/nodes/ is not yet fully implemented<br/>", Void), "highlighted")
l_page.execute l_page.execute
else
create {FORBIDDEN_ERROR_CMS_RESPONSE} l_page.make (req, res, api)
l_page.execute
end end
end end

View File

@@ -33,6 +33,7 @@ feature -- Access
end end
end end
nodes: LIST [CMS_NODE] nodes: LIST [CMS_NODE]
-- List of nodes. -- List of nodes.
do do

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,31 @@
note
description: "HTML Content format editable with WYSIWYG editor."
date: "$Date$"
revision: "$Revision$"
class
CMS_EDITOR_CONTENT_FORMAT
inherit
CONTENT_FORMAT
redefine
default_create
end
feature {NONE} -- Initialization
default_create
do
Precursor
create filters.make (0)
end
feature -- Access
name: STRING = "cms_editor"
title: STRING_8 = "CMS HTML content"
filters: ARRAYED_LIST [CONTENT_FILTER]
end

View File

@@ -27,10 +27,11 @@ feature -- Access
once once
-- Can we provide an external file to read the -- Can we provide an external file to read the
-- supported formats? -- supported formats?
create {ARRAYED_LIST [CONTENT_FORMAT]} Result.make (3) create {ARRAYED_LIST [CONTENT_FORMAT]} Result.make (4)
Result.force (plain_text) Result.force (plain_text)
Result.force (full_html) Result.force (full_html)
Result.force (filtered_html) Result.force (filtered_html)
Result.force (cms_html)
end end
default_format: CONTENT_FORMAT default_format: CONTENT_FORMAT
@@ -43,6 +44,11 @@ feature -- Access
create Result create Result
end end
cms_html: CMS_EDITOR_CONTENT_FORMAT
once
create Result
end
full_html: FULL_HTML_CONTENT_FORMAT full_html: FULL_HTML_CONTENT_FORMAT
once once
create Result create Result
@@ -53,7 +59,6 @@ feature -- Access
create Result create Result
end end
note note
copyright: "2011-2014, Jocelyn Fiat, Eiffel Software and others" copyright: "2011-2014, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"

View File

@@ -0,0 +1,106 @@
note
description: "Class to import a WYSIWIG editor using javascript code"
author: "Dario B<>sch <daboesch@student.ethz.ch"
date: "$Date$"
revision: "$Revision$"
deferred class
CMS_EDITOR
feature -- Initialisation
load_assets : STRING
-- Loads all assest needed to show the editor
deferred
end
feature -- Javascript
javascript_replace_textarea (a_textarea : WSF_FORM_TEXTAREA) : STRING
-- Javascript code that replaces a textarea with the editor. The editor instance should be saved in editor_variable
deferred
end
javascript_restore_textarea (a_textarea : WSF_FORM_TEXTAREA) : STRING
-- Javascript code that restores a textarea
deferred
end
javascript_textarea_to_editor(a_textarea : WSF_FORM_TEXTAREA) : STRING
-- Javascript code to display the textarea as a WYSIWIG editor as soon as the document is loaded
do
Result := javascript_ready(javascript_replace_textarea (a_textarea))
end
javascript_textarea_to_editor_if_selected (a_textarea : WSF_FORM_TEXTAREA; a_select_field : WSF_FORM_SELECT; a_value : STRING) : STRING
-- Javascript code to display the textarea as a WYSIWIG editor if a_select_field has a_value
local
initial_replace_code, on_select_replace_code : STRING
do
-- Javascript that replaces the textarea if a_value is selected at load time
initial_replace_code := javascript_ready(javascript_if_selected(a_select_field, a_value, javascript_replace_textarea(a_textarea)))
-- Javascript code that replaces the textarea as soon as value is selected at a_select_field
on_select_replace_code := javascript_ready(
javascript_init_editor_variable(a_textarea) +
javascript_on_select(a_select_field, a_value,
-- If a_value is selected, replace textarea
javascript_replace_textarea(a_textarea),
-- Otherwise restore it
javascript_restore_textarea(a_textarea)
)
)
Result := initial_replace_code + " " + on_select_replace_code
end
javascript_init_editor_variable(a_textarea : WSF_FORM_TEXTAREA) : STRING
-- Returns the javascript code that initializes a local variable to store the editor instance
do
Result := "var " + editor_variable(a_textarea) + "; "
end
javascript_if_selected(a_select_field : WSF_FORM_SELECT; a_value : STRING; a_code : STRING) : STRING
-- Javascript that executes a_code if a_value is selected at a_select_field
do
Result := "if($('#" + field_id(a_select_field) + "').val() == %"" + a_value + "%"){ " + a_code + " }"
end
javascript_ready (a_code : STRING) : STRING
-- Wraps the given javascript code with a ready statement, such that it's executed when the document has loaded
do
Result := "$(function() { " + a_code + " });"
end
javascript_on_select (a_select_field : WSF_FORM_SELECT; a_value : STRING; a_then : STRING; a_else : STRING) : STRING
-- Javascript code that executes a_then if at the given select_field the given string value is selected, otherwise it executes a_else
do
Result := "$('#" + field_id(a_select_field) + "').change(function(){" +
javascript_if_selected(a_select_field, a_value, a_then) +
"else{" +
a_else +
"}" +
"});"
end
feature -- Helper
field_id(a_select_field : WSF_FORM_SELECT) : STRING
-- Returns the id of the given field
do
if attached a_select_field.css_id as a_id then
Result := a_id
else
Result := a_select_field.name + "-select"
end
end
editor_variable (a_textarea : WSF_FORM_TEXTAREA) : STRING
-- Returns the variable name that stores the editor instance of the given textarea
do
Result := "editor_" + a_textarea.name
end
end

View File

@@ -0,0 +1,37 @@
note
description: "Summary description for {CMS_EDITOR_CKEDITOR}."
author: ""
date: "$Date$"
revision: "$Revision$"
class
CMS_EDITOR_CKEDITOR
inherit
CMS_EDITOR
feature -- Initialisation
load_assets : STRING
-- <Precursor>
do
Result := "<script src=%"//cdn.ckeditor.com/4.4.7/standard/ckeditor.js%"></script>"
end
feature -- Javascript
javascript_replace_textarea (a_textarea : WSF_FORM_TEXTAREA) : STRING
-- <Precursor>
do
-- Replaces the textarea with an editor instance. Save the instance in a variable
Result := editor_variable(a_textarea) + " = CKEDITOR.replace( '" + a_textarea.name + "' );"
end
javascript_restore_textarea (a_textarea : WSF_FORM_TEXTAREA) : STRING
-- <Precursor>
do
-- Replaces the textarea with an editor instance. Save the instance in a variable
Result := "if (" + editor_variable(a_textarea) + " != undefined) " + editor_variable(a_textarea) + ".destroy();"
end
end

View File

@@ -0,0 +1,77 @@
note
description: "Extends the WSF form textarea with features to add a WYSIWIG editor."
author: "Dario B<>sch <daboesch@student.ethz.ch"
date: "$Date: 2015-05-23 16:02:55 +0100 (Sat, 23 May 2015) $"
revision: "$Revision: 96616 $"
class
CMS_FORM_TEXTAREA
inherit
WSF_FORM_TEXTAREA
redefine
make,
append_item_to_html
end
CMS_EDITOR_CKEDITOR
create
make
feature -- Initialisation
make (a_name: like name)
-- <Precursor>
do
precursor(a_name)
-- By default we don't replace the textarea by an editor
editor := False;
end
feature -- Access
editor : BOOLEAN
-- True if the textarea should be replaced by the editor. Default is false.
format_field : detachable WSF_FORM_SELECT
-- Selection field for the format on that it depends, if the editor is shown or not.
condition_value : detachable STRING
feature -- Editor
show_as_editor
-- The textarea will be replaced by a wysiwyg editor
do
editor := True
end
show_as_editor_if_selected (a_select_field : WSF_FORM_SELECT; a_value : STRING)
-- Replaces the textarea only if a_select_field has a_value (or the value gets selected)
do
editor := True
format_field := a_select_field
condition_value := a_value
end
feature -- Conversion
append_item_to_html (a_theme: WSF_THEME; a_html: STRING_8)
do
-- Add javascript to replace textarea with editor
precursor(a_theme, a_html)
if editor then
a_html.append (load_assets)
a_html.append ("<script type=%"text/javascript%">");
if attached format_field as l_field and then attached condition_value as l_value then
a_html.append (javascript_textarea_to_editor_if_selected (Current, l_field, l_value))
else
a_html.append (javascript_textarea_to_editor (Current))
end
a_html.append ("</script>")
end
end
end

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

@@ -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

@@ -287,7 +287,7 @@ feature -- Path aliases
do do
Result := a_source Result := a_source
if attached storage.path_alias (Result) as l_path then if attached storage.path_alias (Result) as l_path then
Result := l_path Result := "/" + l_path
end end
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) initialize
-- Build a CMS service with `a_api' -- Build a CMS service with `a_api'
local
l_setup: CMS_SETUP
do do
create api.make (a_setup) l_setup := initial_cms_setup
initialize 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)
@@ -137,11 +158,11 @@ feature -- Settings: router
create fhdl.make_hidden_with_path (setup.theme_assets_location) create fhdl.make_hidden_with_path (setup.theme_assets_location)
fhdl.disable_index fhdl.disable_index
fhdl.set_not_found_handler (agent (ia_uri: READABLE_STRING_8; ia_req: WSF_REQUEST; ia_res: WSF_RESPONSE) fhdl.set_not_found_handler (agent (ia_uri: READABLE_STRING_8; ia_req: WSF_REQUEST; ia_res: WSF_RESPONSE)
do 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

@@ -43,7 +43,7 @@ feature {CMS_API} -- Module Initialization
feature -- Status feature -- Status
is_initialized: BOOLEAN is_initialized: BOOLEAN
-- Is Current module initialized? -- Is Current module initialized?
feature {CMS_API} -- Access: API feature {CMS_API} -- Access: API

View File

@@ -22,7 +22,9 @@ feature -- Basic operations
local local
utf: UTF_CONVERTER 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

View File

@@ -160,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

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%