diff --git a/cms/cms-safe.ecf b/cms/cms-safe.ecf
index 235bd74..e8f43fa 100644
--- a/cms/cms-safe.ecf
+++ b/cms/cms-safe.ecf
@@ -10,11 +10,18 @@
+
+
+
+
+
+
+ /EIFGENs$
diff --git a/cms/src/configuration/cms_default_setup.e b/cms/src/configuration/cms_default_setup.e
index e1bf624..76dcab2 100644
--- a/cms/src/configuration/cms_default_setup.e
+++ b/cms/src/configuration/cms_default_setup.e
@@ -26,9 +26,7 @@ feature {NONE} -- Initialization
do
configure
create modules.make (3)
- build_api_service
build_mailer
-
initialize_modules
end
@@ -61,11 +59,6 @@ feature {NONE} -- Initialization
-- m.enable
-- modules.extend (m)
-
- create {BASIC_AUTH_MODULE} m.make (Current)
- m.enable
- modules.extend (m)
-
create {NODE_MODULE} m.make (Current)
m.enable
modules.extend (m)
@@ -90,20 +83,6 @@ feature -- Access
end
- build_api_service
- local
- l_database: DATABASE_CONNECTION
- do
- to_implement ("Refactor database setup")
- if attached (create {JSON_CONFIGURATION}).new_database_configuration (layout.application_config_path) as l_database_config then
- create {DATABASE_CONNECTION_MYSQL} l_database.login_with_connection_string (l_database_config.connection_string)
- create api_service.make (create {CMS_STORAGE_MYSQL}.make (l_database))
- else
- create {DATABASE_CONNECTION_NULL} l_database.make_common
- create api_service.make (create {CMS_STORAGE_NULL})
- end
- end
-
build_auth_engine
do
to_implement ("Not implemented authentication")
diff --git a/cms/src/configuration/cms_setup.e b/cms/src/configuration/cms_setup.e
index f0af327..58b0e31 100644
--- a/cms/src/configuration/cms_setup.e
+++ b/cms/src/configuration/cms_setup.e
@@ -14,9 +14,6 @@ feature -- Access
layout: CMS_LAYOUT
-- CMS layout.
- api_service: CMS_API_SERVICE
- -- cms api service.
-
is_html: BOOLEAN
-- api with progressive enhancements css and js, server side rendering.
deferred
@@ -48,6 +45,10 @@ feature -- Access: Site
files_location: PATH
+ front_page_path: detachable READABLE_STRING_8
+ -- Optional path defining the front page.
+ -- By default "" or "/".
+
feature -- Access: Theme
themes_location: PATH
diff --git a/cms/src/hooks/cms_hook.e b/cms/src/hooks/cms_hook.e
new file mode 100644
index 0000000..83f9ac3
--- /dev/null
+++ b/cms/src/hooks/cms_hook.e
@@ -0,0 +1,9 @@
+note
+ description: "Marker interface"
+ date: "$Date$"
+ revision: "$Revision$"
+
+deferred class
+ CMS_HOOK
+
+end
diff --git a/cms/src/hooks/cms_hook_auto_register.e b/cms/src/hooks/cms_hook_auto_register.e
new file mode 100644
index 0000000..d960b6d
--- /dev/null
+++ b/cms/src/hooks/cms_hook_auto_register.e
@@ -0,0 +1,33 @@
+note
+ description: "[
+ Summary description for {CMS_HOOK_AUTO_REGISTER}.
+ When inheriting from this class, the declared hooks are automatically
+ registered, otherwise, each descendant has to add it to the cms service
+ itself.
+ ]"
+ date: "$Date: 2014-08-28 08:21:49 -0300 (ju. 28 de ago. de 2014) $"
+ revision: "$Revision: 95708 $"
+
+deferred class
+ CMS_HOOK_AUTO_REGISTER
+
+inherit
+ CMS_HOOK
+
+feature -- Hook
+
+ hook_auto_register (a_response: CMS_RESPONSE)
+ do
+ if attached {CMS_HOOK_MENU_ALTER} Current as h_menu_alter then
+ a_response.add_menu_alter_hook (h_menu_alter)
+ end
+ if attached {CMS_HOOK_BLOCK} Current as h_block then
+ a_response.add_block_hook (h_block)
+ end
+ if attached {CMS_HOOK_FORM_ALTER} Current as h_block then
+ a_response.add_form_alter_hook (h_block)
+ end
+
+ end
+
+end
diff --git a/cms/src/hooks/cms_hook_block.e b/cms/src/hooks/cms_hook_block.e
new file mode 100644
index 0000000..89d001c
--- /dev/null
+++ b/cms/src/hooks/cms_hook_block.e
@@ -0,0 +1,25 @@
+note
+ description: "Summary description for {CMS_HOOK_BLOCK}."
+ author: ""
+ date: "$Date: 2014-08-28 08:21:49 -0300 (ju. 28 de ago. de 2014) $"
+ revision: "$Revision: 95708 $"
+
+deferred class
+ CMS_HOOK_BLOCK
+
+inherit
+ CMS_HOOK
+
+feature -- Hook
+
+ block_list: ITERABLE [like {CMS_BLOCK}.name]
+ -- List of block names, managed by current object.
+ deferred
+ end
+
+ get_block_view (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE)
+ -- Get block object identified by `a_block_id' and associate with `a_response'.
+ deferred
+ end
+
+end
diff --git a/cms/src/hooks/cms_hook_form_alter.e b/cms/src/hooks/cms_hook_form_alter.e
new file mode 100644
index 0000000..472979c
--- /dev/null
+++ b/cms/src/hooks/cms_hook_form_alter.e
@@ -0,0 +1,17 @@
+note
+ description: "Describe how to alter a form before it's rendered"
+ date: "$Date: 2014-08-28 08:21:49 -0300 (ju. 28 de ago. de 2014) $"
+
+deferred class
+ CMS_HOOK_FORM_ALTER
+
+inherit
+ CMS_HOOK
+
+feature -- Hook
+
+ form_alter (a_form: CMS_FORM; a_form_data: detachable WSF_FORM_DATA; a_response: CMS_RESPONSE)
+ deferred
+ end
+
+end
diff --git a/cms/src/hooks/cms_hook_menu_alter.e b/cms/src/hooks/cms_hook_menu_alter.e
new file mode 100644
index 0000000..d409662
--- /dev/null
+++ b/cms/src/hooks/cms_hook_menu_alter.e
@@ -0,0 +1,17 @@
+note
+ description: "Describe how to alter a menu before it's rendered."
+ date: "$Date: 2014-08-28 08:21:49 -0300 (ju. 28 de ago. de 2014) $"
+
+deferred class
+ CMS_HOOK_MENU_ALTER
+
+inherit
+ CMS_HOOK
+
+feature -- Hook
+
+ menu_alter (a_menu_system: CMS_MENU_SYSTEM; a_response: CMS_RESPONSE)
+ deferred
+ end
+
+end
diff --git a/cms/src/hooks/cms_hook_value_alter.e b/cms/src/hooks/cms_hook_value_alter.e
new file mode 100644
index 0000000..0ec43b9
--- /dev/null
+++ b/cms/src/hooks/cms_hook_value_alter.e
@@ -0,0 +1,28 @@
+note
+ description: "Describe how to alter generic values before they are rendered."
+ date: "$Date: 2014-10-23 08:30:11 -0300 (ju. 23 de oct. de 2014) $"
+ revision: "$Revision: 95980 $"
+
+deferred class
+ CMS_HOOK_VALUE_ALTER
+
+inherit
+
+ CMS_HOOK
+
+feature -- Hook
+
+ value_alter (a_value: CMS_VALUE_TABLE; a_response: CMS_RESPONSE)
+ deferred
+ end
+note
+ copyright: "2011-2014, Jocelyn Fiat, Eiffel Software and others"
+ license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
+ source: "[
+ Eiffel Software
+ 5949 Hollister Ave., Goleta, CA 93117 USA
+ Telephone 805-685-1006, Fax 805-685-6869
+ Website http://www.eiffel.com
+ Customer support http://support.eiffel.com
+ ]"
+end
diff --git a/cms/src/kernel/cms_common_api.e b/cms/src/kernel/cms_common_api.e
new file mode 100644
index 0000000..9301ddf
--- /dev/null
+++ b/cms/src/kernel/cms_common_api.e
@@ -0,0 +1,97 @@
+note
+ description: "Summary description for {WSF_CMS_COMMON_API}."
+ author: ""
+ date: "$Date: 2014-08-28 08:21:49 -0300 (ju. 28 de ago. de 2014) $"
+ revision: "$Revision: 95708 $"
+
+deferred class
+ CMS_COMMON_API
+
+inherit
+ WSF_API_UTILITIES
+
+feature {NONE} -- Access
+
+ site_url: READABLE_STRING_8
+ do
+ Result := ""
+ end
+
+ base_url: detachable READABLE_STRING_8
+ -- Base url if any.
+ do
+ end
+
+feature -- Access
+
+ user_link (u: CMS_USER): like link
+ do
+ Result := link (u.name, "/user/" + u.id.out, Void)
+ end
+
+ node_link (n: CMS_NODE): like link
+ do
+ Result := link (n.title, "/node/" + n.id.out, Void)
+ end
+
+ user_url (u: CMS_USER): like url
+ do
+ Result := url ("/user/" + u.id.out, Void)
+ end
+
+ node_url (n: CMS_NODE): like url
+ do
+ Result := url ("/node/" + n.id.out, Void)
+ end
+
+feature -- Helper
+
+ is_empty (s: detachable READABLE_STRING_GENERAL): BOOLEAN
+ -- Is `s' is Void or empty ?
+ do
+ Result := s = Void or else s.is_empty
+ end
+
+ unix_timestamp (dt: DATE_TIME): INTEGER_64
+ do
+ Result := (create {HTTP_DATE_TIME_UTILITIES}).unix_time_stamp (dt)
+ end
+
+ unix_timestamp_to_date_time (t: INTEGER_64): DATE_TIME
+ do
+ Result := (create {HTTP_DATE_TIME_UTILITIES}).unix_time_stamp_to_date_time (t)
+ end
+
+ string_unix_timestamp_to_date_time (s: READABLE_STRING_8): DATE_TIME
+ do
+ if s.is_integer_64 then
+ Result := (create {HTTP_DATE_TIME_UTILITIES}).unix_time_stamp_to_date_time (s.to_integer_64)
+ else
+ Result := (create {HTTP_DATE_TIME_UTILITIES}).unix_time_stamp_to_date_time (0)
+ end
+ end
+
+feature {NONE} -- Implementation
+
+ options_boolean (opts: HASH_TABLE [detachable ANY, STRING]; k: STRING; dft: BOOLEAN): BOOLEAN
+ do
+ if attached {BOOLEAN} opts.item (k) as h then
+ Result := h
+ else
+ Result := dft
+ end
+ end
+
+ options_string (opts: HASH_TABLE [detachable ANY, STRING]; k: STRING): detachable STRING
+ do
+ if attached {STRING} opts.item (k) as s then
+ Result := s
+ end
+ end
+
+-- html_encoder: HTML_ENCODER
+-- once ("thread")
+-- create Result
+-- end
+
+end
diff --git a/cms/src/kernel/content/cms_block.e b/cms/src/kernel/content/cms_block.e
new file mode 100644
index 0000000..0b67db7
--- /dev/null
+++ b/cms/src/kernel/content/cms_block.e
@@ -0,0 +1,28 @@
+note
+ description: "Summary description for {CMS_BLOCK}."
+ date: "$Date: 2014-08-28 08:21:49 -0300 (ju. 28 de ago. de 2014) $"
+
+deferred class
+ CMS_BLOCK
+
+feature -- Access
+
+ name: READABLE_STRING_8
+ deferred
+ end
+
+ title: detachable READABLE_STRING_32
+ deferred
+ end
+
+feature -- status report
+
+ is_enabled: BOOLEAN
+
+feature -- Conversion
+
+ to_html (a_theme: CMS_THEME): STRING_8
+ deferred
+ end
+
+end
diff --git a/cms/src/kernel/content/cms_block_region.e b/cms/src/kernel/content/cms_block_region.e
new file mode 100644
index 0000000..baef14f
--- /dev/null
+++ b/cms/src/kernel/content/cms_block_region.e
@@ -0,0 +1,42 @@
+note
+ description: "Summary description for {CMS_BLOCK_REGION}."
+ date: "$Date: 2014-10-30 12:55:33 -0300 (ju. 30 de oct. de 2014) $"
+
+class
+ CMS_BLOCK_REGION
+
+create
+ make
+
+feature {NONE} -- Initialization
+
+ make (a_name: like name)
+ do
+ name := a_name
+ create blocks.make (1)
+ end
+
+feature -- Access
+
+ name: READABLE_STRING_8
+
+ blocks: ARRAYED_LIST [CMS_BLOCK]
+
+feature -- Element change
+
+ extend (b: CMS_BLOCK)
+ do
+ blocks.force (b)
+ end
+
+;note
+ copyright: "2011-2014, Jocelyn Fiat, Eiffel Software and others"
+ license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
+ source: "[
+ Eiffel Software
+ 5949 Hollister Ave., Goleta, CA 93117 USA
+ Telephone 805-685-1006, Fax 805-685-6869
+ Website http://www.eiffel.com
+ Customer support http://support.eiffel.com
+ ]"
+end
diff --git a/cms/src/kernel/content/cms_content_block.e b/cms/src/kernel/content/cms_content_block.e
new file mode 100644
index 0000000..466c2f3
--- /dev/null
+++ b/cms/src/kernel/content/cms_content_block.e
@@ -0,0 +1,79 @@
+note
+ description: "Summary description for {CMS_CONTENT_BLOCK}."
+ author: ""
+ date: "$Date: 2014-10-30 12:55:33 -0300 (ju. 30 de oct. de 2014) $"
+ revision: "$Revision: 96018 $"
+
+class
+ CMS_CONTENT_BLOCK
+
+inherit
+ CMS_BLOCK
+
+create
+ make,
+ make_raw
+
+feature {NONE} -- Initialization
+
+ make (a_name: like name; a_title: like title; a_content: like content; a_format: like format)
+ do
+ is_enabled := True
+ name := a_name
+ title := a_title
+ content := a_content
+ format := a_format
+ end
+
+ make_raw (a_name: like name; a_title: like title; a_content: like content; a_format: like format)
+ do
+ make (a_name, a_title, a_content, a_format)
+ set_is_raw (True)
+ end
+
+feature -- Access
+
+ name: READABLE_STRING_8
+
+ title: detachable READABLE_STRING_32
+
+ content: READABLE_STRING_8
+
+ format: detachable CONTENT_FORMAT
+
+feature -- Status report
+
+ is_raw: BOOLEAN
+ -- Is raw?
+ -- If True, do not get wrapped it with block specific div
+
+feature -- Element change
+
+ set_is_raw (b: BOOLEAN)
+ do
+ is_raw := b
+ end
+
+feature -- Conversion
+
+ to_html (a_theme: CMS_THEME): STRING_8
+ do
+ -- Why in this particular case theme is not used to generate the content?
+
+ if attached format as f then
+ Result := f.formatted_output (content)
+ else
+ Result := content
+ end
+ end
+note
+ copyright: "2011-2014, Jocelyn Fiat, Eiffel Software and others"
+ license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
+ source: "[
+ Eiffel Software
+ 5949 Hollister Ave., Goleta, CA 93117 USA
+ Telephone 805-685-1006, Fax 805-685-6869
+ Website http://www.eiffel.com
+ Customer support http://support.eiffel.com
+ ]"
+end
diff --git a/cms/src/kernel/content/cms_encoders.e b/cms/src/kernel/content/cms_encoders.e
new file mode 100644
index 0000000..36b60fc
--- /dev/null
+++ b/cms/src/kernel/content/cms_encoders.e
@@ -0,0 +1,35 @@
+note
+ description: "Summary description for {CMS_ENCODERS}."
+ author: ""
+ date: "$Date$"
+ revision: "$Revision$"
+
+class
+ CMS_ENCODERS
+
+feature -- Encoders
+
+ url_encoded (s: detachable READABLE_STRING_GENERAL): STRING_8
+ local
+ enc: URL_ENCODER
+ do
+ create enc
+ if s /= Void then
+ Result := enc.general_encoded_string (s)
+ else
+ create Result.make_empty
+ end
+ end
+
+ html_encoded (s: detachable READABLE_STRING_GENERAL): STRING_8
+ local
+ enc: HTML_ENCODER
+ do
+ create enc
+ if s /= Void then
+ Result := enc.general_encoded_string (s)
+ else
+ create Result.make_empty
+ end
+ end
+end
diff --git a/cms/src/kernel/content/cms_menu_block.e b/cms/src/kernel/content/cms_menu_block.e
new file mode 100644
index 0000000..a7a0797
--- /dev/null
+++ b/cms/src/kernel/content/cms_menu_block.e
@@ -0,0 +1,41 @@
+note
+ description: "Summary description for {CMS_MENU_BLOCK}."
+ date: "$Date: 2014-08-28 08:21:49 -0300 (ju. 28 de ago. de 2014) $"
+
+class
+ CMS_MENU_BLOCK
+
+inherit
+ CMS_BLOCK
+
+create
+ make
+
+feature {NONE} -- Initialization
+
+ make (a_menu: like menu)
+ do
+ is_enabled := True
+ menu := a_menu
+ name := a_menu.name
+ title := a_menu.title
+ end
+
+feature -- Access
+
+ menu: CMS_MENU
+
+ name: READABLE_STRING_8
+
+ title: detachable READABLE_STRING_32
+
+ is_horizontal: BOOLEAN
+
+feature -- Conversion
+
+ to_html (a_theme: CMS_THEME): STRING_8
+ do
+ Result := a_theme.menu_html (menu, is_horizontal)
+ end
+
+end
diff --git a/cms/src/kernel/content/cms_value_table.e b/cms/src/kernel/content/cms_value_table.e
new file mode 100644
index 0000000..2e5ccc9
--- /dev/null
+++ b/cms/src/kernel/content/cms_value_table.e
@@ -0,0 +1,89 @@
+note
+ description: "Summary description for {CMS_VALUE_TABLE}."
+ date: "$Date: 2014-10-23 08:30:11 -0300 (ju. 23 de oct. de 2014) $"
+ revision: "$Revision: 95980 $"
+
+class
+ CMS_VALUE_TABLE
+
+inherit
+ TABLE_ITERABLE [detachable ANY, READABLE_STRING_GENERAL]
+
+create
+ make
+
+feature {NONE} -- Initialization
+
+ make (nb: INTEGER)
+ do
+ create table.make (nb)
+ end
+
+feature -- Access
+
+ count: INTEGER
+ -- Number of items.
+ do
+ Result := table.count
+ end
+
+ item (key: READABLE_STRING_GENERAL): detachable ANY
+ -- Item associated with `key', if present
+ -- otherwise default value of type `G'.
+ note
+ option: stable
+ do
+ Result := table.item (key)
+ end
+
+ has (key: READABLE_STRING_GENERAL): BOOLEAN
+ -- Has item associated with key `key'?
+ do
+ Result := table.has (key)
+ end
+
+ new_cursor: TABLE_ITERATION_CURSOR [detachable ANY, READABLE_STRING_GENERAL]
+ --
+ do
+ Result := table.new_cursor
+ end
+
+feature -- Element change
+
+ put (new: detachable ANY; key: READABLE_STRING_GENERAL)
+ -- Insert `new' with `key' if there is no other item
+ -- associated with the same key.
+ do
+ table.put (new, key)
+ end
+
+ force (new: detachable ANY; key: READABLE_STRING_GENERAL)
+ -- Update table so that `new' will be the item associated
+ -- with `key'.
+ do
+ table.force (new, key)
+ end
+
+ remove (key: READABLE_STRING_GENERAL)
+ do
+ table.remove (key)
+ end
+
+feature {NONE} -- Duplication
+
+ table: STRING_TABLE [detachable ANY]
+
+invariant
+ table_set: table /= Void
+
+note
+ copyright: "2011-2014, Jocelyn Fiat, Eiffel Software and others"
+ license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
+ source: "[
+ Eiffel Software
+ 5949 Hollister Ave., Goleta, CA 93117 USA
+ Telephone 805-685-1006, Fax 805-685-6869
+ Website http://www.eiffel.com
+ Customer support http://support.eiffel.com
+ ]"
+end
diff --git a/cms/src/kernel/content/format/cms_formats.e b/cms/src/kernel/content/format/cms_formats.e
new file mode 100644
index 0000000..11823ae
--- /dev/null
+++ b/cms/src/kernel/content/format/cms_formats.e
@@ -0,0 +1,64 @@
+note
+ description: "Summary description for {CMS_FORMATS}."
+ author: ""
+ date: "$Date: 2014-10-16 04:45:23 -0300 (ju. 16 de oct. de 2014) $"
+ revision: "$Revision: 95932 $"
+
+class
+ CMS_FORMATS
+
+feature -- Access
+
+ format (a_name: like {CONTENT_FORMAT}.name): detachable CONTENT_FORMAT
+ do
+ across
+ all_formats as c
+ until
+ Result /= Void
+ loop
+ if c.item.name.same_string (a_name) then
+ Result := c.item
+ end
+ end
+ end
+
+ all_formats: LIST [CONTENT_FORMAT]
+ once
+ create {ARRAYED_LIST [CONTENT_FORMAT]} Result.make (3)
+ Result.force (plain_text)
+ Result.force (full_html)
+ Result.force (filtered_html)
+ end
+
+ default_format: CONTENT_FORMAT
+ do
+ Result := plain_text --FIXME
+ end
+
+ plain_text: PLAIN_TEXT_CONTENT_FORMAT
+ once
+ create Result
+ end
+
+ full_html: FULL_HTML_CONTENT_FORMAT
+ once
+ create Result
+ end
+
+ filtered_html: FILTERED_HTML_CONTENT_FORMAT
+ once
+ create Result
+ end
+
+
+note
+ copyright: "2011-2014, Jocelyn Fiat, Eiffel Software and others"
+ license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
+ source: "[
+ Eiffel Software
+ 5949 Hollister Ave., Goleta, CA 93117 USA
+ Telephone 805-685-1006, Fax 805-685-6869
+ Website http://www.eiffel.com
+ Customer support http://support.eiffel.com
+ ]"
+end
diff --git a/cms/src/kernel/form/cms_form.e b/cms/src/kernel/form/cms_form.e
new file mode 100644
index 0000000..2038a14
--- /dev/null
+++ b/cms/src/kernel/form/cms_form.e
@@ -0,0 +1,42 @@
+note
+ description: "Summary description for {CMS_FORM}."
+ date: "$Date: 2014-08-28 08:21:49 -0300 (ju. 28 de ago. de 2014) $"
+ revision: "$Revision: 95708 $"
+
+class
+ CMS_FORM
+
+inherit
+ WSF_FORM
+ rename
+ process as process_form
+ end
+
+create
+ make
+
+feature -- Basic operation
+
+ prepare (a_response: CMS_RESPONSE)
+ do
+ a_response.call_form_alter_hooks (Current, Void)
+ end
+
+ process (a_response: CMS_RESPONSE)
+ do
+ process_form (a_response.request, agent on_prepared (a_response, ?), agent on_processed (a_response, ?))
+ end
+
+ on_prepared (a_response: CMS_RESPONSE; fd: WSF_FORM_DATA)
+ do
+ a_response.call_form_alter_hooks (Current, fd)
+ end
+
+ on_processed (a_response: CMS_RESPONSE; fd: WSF_FORM_DATA)
+ do
+ if not fd.is_valid or fd.has_error then
+ a_response.report_form_errors (fd)
+ end
+ end
+
+end
diff --git a/cms/src/kernel/link/cms_menu_system.e b/cms/src/kernel/link/cms_menu_system.e
new file mode 100644
index 0000000..5565c5d
--- /dev/null
+++ b/cms/src/kernel/link/cms_menu_system.e
@@ -0,0 +1,100 @@
+note
+ description: "Describe the navigation menus."
+ date: "$Date: 2014-08-28 08:21:49 -0300 (ju. 28 de ago. de 2014) $"
+ revision: "$Revision: 95708 $"
+
+class
+ CMS_MENU_SYSTEM
+
+inherit
+ ITERABLE [CMS_MENU]
+
+ REFACTORING_HELPER
+create
+ make
+
+feature {NONE} -- Initialization
+
+ make
+ -- Create a predefined manu system
+ do
+ to_implement ("Refactor, take the info from a Database or Configuration file.")
+ create items.make (5)
+ force (create {CMS_MENU}.make ("primary", 3)) -- primary menu
+ force (create {CMS_MENU}.make_with_title ("management", "Management", 3)) -- secondary in admin view.
+ force (create {CMS_MENU}.make_with_title ("secondary", "Navigation", 3)) -- secondary
+ force (create {CMS_MENU}.make_with_title ("user", "User", 3)) -- first_side_bar
+ end
+
+feature -- Access
+
+ item (n: like {CMS_MENU}.name): CMS_MENU
+ local
+ m: detachable CMS_MENU
+ do
+ m := items.item (n)
+ if m = Void then
+ create m.make (n, 3)
+ force (m)
+ end
+ Result := m
+ end
+
+ main_menu: CMS_MENU
+ obsolete
+ "Use `primary_menu' [Nov/2014]"
+ do
+ Result := primary_menu
+ end
+
+ primary_menu: CMS_MENU
+ do
+ Result := item ("primary")
+ end
+
+ secondary_menu: CMS_MENU
+ do
+ Result := item ("secondary")
+ end
+
+ management_menu: CMS_MENU
+ do
+ Result := item ("management")
+ end
+
+ navigation_menu: CMS_MENU
+ do
+ Result := item ("navigation")
+ end
+
+ user_menu: CMS_MENU
+ do
+ Result := item ("user")
+ end
+
+ primary_tabs: CMS_MENU
+ do
+ Result := item ("primary-tabs")
+ end
+
+feature -- Change
+
+ force (m: CMS_MENU)
+ do
+ items.force (m, m.name)
+ end
+
+feature -- Access
+
+ new_cursor: ITERATION_CURSOR [CMS_MENU]
+ -- Fresh cursor associated with current structure.
+ do
+ Result := items.new_cursor
+ end
+
+feature {NONE} -- Implementation
+
+ items: HASH_TABLE [CMS_MENU, like {CMS_MENU}.name]
+-- items: ARRAYED_LIST [CMS_MENU]
+
+end
diff --git a/cms/src/modules/basic_auth/basic_auth_module.e b/cms/src/modules/basic_auth/basic_auth_module.e
index 2c589d1..555d2cb 100644
--- a/cms/src/modules/basic_auth/basic_auth_module.e
+++ b/cms/src/modules/basic_auth/basic_auth_module.e
@@ -18,57 +18,53 @@ create
feature {NONE} -- Initialization
- make (a_config: CMS_SETUP)
+ make
do
name := "basic auth"
version := "1.0"
description := "Service to manage basic authentication"
package := "core"
- config := a_config
end
- config: CMS_SETUP
- -- Node configuration.
-
feature -- Access: router
- router: WSF_ROUTER
+ router (a_api: CMS_API): WSF_ROUTER
-- Node router.
do
create Result.make (2)
- configure_api_login (Result)
- configure_api_logoff (Result)
+ configure_api_login (a_api, Result)
+ configure_api_logoff (a_api, Result)
end
feature -- Access: filter
- filters: detachable LIST [WSF_FILTER]
+ filters (a_api: CMS_API): detachable LIST [WSF_FILTER]
-- Possibly list of Filter's module.
do
create {ARRAYED_LIST [WSF_FILTER]} Result.make (2)
Result.extend (create {CORS_FILTER})
- Result.extend (create {BASIC_AUTH_FILTER}.make (config))
+ Result.extend (create {BASIC_AUTH_FILTER}.make (a_api))
end
feature {NONE} -- Implementation: routes
- configure_api_login (a_router: WSF_ROUTER)
+ configure_api_login (api: CMS_API; a_router: WSF_ROUTER)
local
l_bal_handler: BASIC_AUTH_LOGIN_HANDLER
l_methods: WSF_REQUEST_METHODS
do
- create l_bal_handler.make (config)
+ create l_bal_handler.make (api)
create l_methods
l_methods.enable_get
a_router.handle_with_request_methods ("/basic_auth_login", l_bal_handler, l_methods)
end
- configure_api_logoff (a_router: WSF_ROUTER)
+ configure_api_logoff (api: CMS_API; a_router: WSF_ROUTER)
local
l_bal_handler: BASIC_AUTH_LOGOFF_HANDLER
l_methods: WSF_REQUEST_METHODS
do
- create l_bal_handler.make (config)
+ create l_bal_handler.make (api)
create l_methods
l_methods.enable_get
a_router.handle_with_request_methods ("/basic_auth_logoff", l_bal_handler, l_methods)
diff --git a/cms/src/modules/basic_auth/filter/basic_auth_filter.e b/cms/src/modules/basic_auth/filter/basic_auth_filter.e
index d5abd0a..31ddb21 100644
--- a/cms/src/modules/basic_auth/filter/basic_auth_filter.e
+++ b/cms/src/modules/basic_auth/filter/basic_auth_filter.e
@@ -31,8 +31,8 @@ feature -- Basic operations
-- A valid user
if (attached l_auth.type as l_auth_type and then l_auth_type.is_case_insensitive_equal_general ("basic")) and then
attached l_auth.login as l_auth_login and then attached l_auth.password as l_auth_password then
- if api_service.is_valid_credential (l_auth_login, l_auth_password) then
- if attached api_service.user_by_name (l_auth_login) as l_user then
+ if api.is_valid_credential (l_auth_login, l_auth_password) then
+ if attached api.user_by_name (l_auth_login) as l_user then
req.set_execution_variable ("user", l_user)
execute_next (req, res)
else
diff --git a/cms/src/modules/basic_auth/handler/basic_auth_login_handler.e b/cms/src/modules/basic_auth/handler/basic_auth_login_handler.e
index a0e6df8..4035e0f 100644
--- a/cms/src/modules/basic_auth/handler/basic_auth_login_handler.e
+++ b/cms/src/modules/basic_auth/handler/basic_auth_login_handler.e
@@ -47,8 +47,6 @@ feature -- HTTP Methods
do_get (req: WSF_REQUEST; res: WSF_RESPONSE)
--
- local
- l_page: CMS_RESPONSE
do
log.write_information(generator + ".do_get Processing basic auth login")
if attached {STRING_32} current_user_name (req) as l_user then
diff --git a/cms/src/modules/basic_auth/handler/basic_auth_logoff_handler.e b/cms/src/modules/basic_auth/handler/basic_auth_logoff_handler.e
index b274ab4..300eafe 100644
--- a/cms/src/modules/basic_auth/handler/basic_auth_logoff_handler.e
+++ b/cms/src/modules/basic_auth/handler/basic_auth_logoff_handler.e
@@ -50,7 +50,7 @@ feature -- HTTP Methods
if attached req.query_parameter ("prompt") as l_prompt then
(create {CMS_GENERIC_RESPONSE}).new_response_unauthorized (req, res)
else
- create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, setup, "master2/basic_auth/logoff")
+ create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)
l_page.set_status_code ({HTTP_STATUS_CODE}.unauthorized)
l_page.execute
end
diff --git a/cms/src/modules/cms_module.e b/cms/src/modules/cms_module.e
index a58805e..ce0a9a2 100644
--- a/cms/src/modules/cms_module.e
+++ b/cms/src/modules/cms_module.e
@@ -20,16 +20,25 @@ feature -- Access
feature -- Router
- router: WSF_ROUTER
+ router (a_api: CMS_API): WSF_ROUTER
-- Router configuration.
require
is_enabled: is_enabled
deferred
end
+feature -- Hooks configuration
+
+ register_hooks (a_response: CMS_RESPONSE)
+ -- Module hooks configuration.
+ require
+ is_enabled: is_enabled
+ do
+ end
+
feature -- Filter
- filters: detachable LIST [WSF_FILTER]
+ filters (a_api: CMS_API): detachable LIST [WSF_FILTER]
-- Optional list of filter for Current module.
require
is_enabled: is_enabled
diff --git a/cms/src/modules/node/handler/node_content_handler.e b/cms/src/modules/node/handler/node_content_handler.e
index a7113b7..11ebd9d 100644
--- a/cms/src/modules/node/handler/node_content_handler.e
+++ b/cms/src/modules/node/handler/node_content_handler.e
@@ -69,8 +69,8 @@ feature -- HTTP Methods
if attached current_user_name (req) then
-- Existing node
if attached {WSF_STRING} req.path_parameter ("id") as l_id then
- if l_id.is_integer and then attached {CMS_NODE} api_service.node (l_id.integer_value) as l_node then
- create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, setup, "modules/node_content")
+ if l_id.is_integer and then attached {CMS_NODE} api.node (l_id.integer_value) as l_node then
+ create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)
l_page.add_variable (l_node.content, "node_content")
l_page.add_variable (l_id.value, "id")
l_page.execute
@@ -78,7 +78,7 @@ feature -- HTTP Methods
do_error (req, res, l_id)
end
else
- (create {ERROR_500_CMS_RESPONSE}.make (req, res, setup, "master2/error")).execute
+ (create {ERROR_500_CMS_RESPONSE}.make (req, res, api)).execute
end
else
(create {CMS_GENERIC_RESPONSE}).new_response_unauthorized (req, res)
@@ -88,24 +88,22 @@ feature -- HTTP Methods
do_post (req: WSF_REQUEST; res: WSF_RESPONSE)
--
- local
- l_page: CMS_RESPONSE
do
if attached current_user_name (req) then
if attached {WSF_STRING} req.path_parameter ("id") as l_id then
- if l_id.is_integer and then attached {CMS_NODE} api_service.node (l_id.integer_value) as l_node then
+ if l_id.is_integer and then attached {CMS_NODE} api.node (l_id.integer_value) as l_node then
if attached {WSF_STRING} req.form_parameter ("method") as l_method then
if l_method.is_case_insensitive_equal ("PUT") then
do_put (req, res)
else
- (create {ERROR_500_CMS_RESPONSE}.make (req, res, setup, "master2/error")).execute
+ (create {ERROR_500_CMS_RESPONSE}.make (req, res, api)).execute
end
end
else
do_error (req, res, l_id)
end
else
- (create {ERROR_500_CMS_RESPONSE}.make (req, res, setup, "master2/error")).execute
+ (create {ERROR_500_CMS_RESPONSE}.make (req, res, api)).execute
end
else
(create {CMS_GENERIC_RESPONSE}).new_response_unauthorized (req, res)
@@ -116,21 +114,20 @@ feature -- HTTP Methods
--
local
u_node: CMS_NODE
- l_page: CMS_RESPONSE
do
to_implement ("Check if user has permissions")
if attached current_user (req) as l_user then
if attached {WSF_STRING} req.path_parameter ("id") as l_id then
- if l_id.is_integer and then attached {CMS_NODE} api_service.node (l_id.integer_value) as l_node then
+ if l_id.is_integer and then attached {CMS_NODE} api.node (l_id.integer_value) as l_node then
u_node := extract_data_form (req)
u_node.set_id (l_id.integer_value)
- api_service.update_node_content (l_user.id, u_node.id, u_node.content)
+ api.update_node_content (l_user.id, u_node.id, u_node.content)
(create {CMS_GENERIC_RESPONSE}).new_response_redirect (req, res, req.absolute_script_url (""))
else
do_error (req, res, l_id)
end
else
- (create {ERROR_500_CMS_RESPONSE}.make (req, res, setup, "master2/error")).execute
+ (create {ERROR_500_CMS_RESPONSE}.make (req, res, api)).execute
end
else
(create {CMS_GENERIC_RESPONSE}).new_response_unauthorized (req, res)
@@ -143,7 +140,7 @@ feature -- Error
local
l_page: CMS_RESPONSE
do
- create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, setup, "master2/error")
+ create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)
l_page.add_variable (req.absolute_script_url (req.path_info), "request")
if a_id.is_integer then
-- resource not found
diff --git a/cms/src/modules/node/handler/node_handler.e b/cms/src/modules/node/handler/node_handler.e
index e9d789f..2dcb47f 100644
--- a/cms/src/modules/node/handler/node_handler.e
+++ b/cms/src/modules/node/handler/node_handler.e
@@ -68,8 +68,8 @@ feature -- HTTP Methods
do
-- Existing node
if attached {WSF_STRING} req.path_parameter ("id") as l_id then
- if l_id.is_integer and then attached {CMS_NODE} api_service.node (l_id.integer_value) as l_node then
- create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, setup,"modules/node")
+ if l_id.is_integer and then attached {CMS_NODE} api.node (l_id.integer_value) as l_node then
+ create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)
l_page.add_variable (l_node, "node")
l_page.execute
else
@@ -85,19 +85,18 @@ feature -- HTTP Methods
--
local
u_node: CMS_NODE
- l_page: CMS_RESPONSE
do
to_implement ("Check user permissions!!!")
if attached current_user (req) as l_user then
if attached {WSF_STRING} req.path_parameter ("id") as l_id then
- if l_id.is_integer and then attached {CMS_NODE} api_service.node (l_id.integer_value) as l_node then
+ if l_id.is_integer and then attached {CMS_NODE} api.node (l_id.integer_value) as l_node then
if attached {WSF_STRING} req.form_parameter ("method") as l_method then
if l_method.is_case_insensitive_equal ("DELETE") then
do_delete (req, res)
elseif l_method.is_case_insensitive_equal ("PUT") then
do_put (req, res)
else
- (create {ERROR_500_CMS_RESPONSE}.make (req, res, setup, "master2/error")).execute
+ (create {ERROR_500_CMS_RESPONSE}.make (req, res, api)).execute
end
end
else
@@ -107,7 +106,7 @@ feature -- HTTP Methods
-- New node
u_node := extract_data_form (req)
u_node.set_author (l_user)
- api_service.new_node (u_node)
+ api.new_node (u_node)
(create {CMS_GENERIC_RESPONSE}).new_response_redirect (req, res, req.absolute_script_url (""))
end
else
@@ -123,16 +122,16 @@ feature -- HTTP Methods
if attached current_user (req) as l_user then
if attached {WSF_STRING} req.path_parameter ("id") as l_id then
- if l_id.is_integer and then attached {CMS_NODE} api_service.node (l_id.integer_value) as l_node then
+ if l_id.is_integer and then attached {CMS_NODE} api.node (l_id.integer_value) as l_node then
u_node := extract_data_form (req)
u_node.set_id (l_id.integer_value)
- api_service.update_node (l_user.id,u_node)
+ api.update_node (l_user.id,u_node)
(create {CMS_GENERIC_RESPONSE}).new_response_redirect (req, res, req.absolute_script_url (""))
else
do_error (req, res, l_id)
end
else
- (create {ERROR_500_CMS_RESPONSE}.make (req, res, setup, "master2/error")).execute
+ (create {ERROR_500_CMS_RESPONSE}.make (req, res, api)).execute
end
else
(create {CMS_GENERIC_RESPONSE}).new_response_unauthorized (req, res)
@@ -145,14 +144,14 @@ feature -- HTTP Methods
do
if attached current_user_name (req) then
if attached {WSF_STRING} req.path_parameter ("id") as l_id then
- if l_id.is_integer and then attached {CMS_NODE} api_service.node (l_id.integer_value) as l_node then
- api_service.delete_node (l_id.integer_value)
+ if l_id.is_integer and then attached {CMS_NODE} api.node (l_id.integer_value) as l_node then
+ api.delete_node (l_id.integer_value)
(create {CMS_GENERIC_RESPONSE}).new_response_redirect (req, res, req.absolute_script_url (""))
else
do_error (req, res, l_id)
end
else
- (create {ERROR_500_CMS_RESPONSE}.make (req, res, setup, "master2/error")).execute
+ (create {ERROR_500_CMS_RESPONSE}.make (req, res, api)).execute
end
else
(create {CMS_GENERIC_RESPONSE}).new_response_unauthorized (req, res)
@@ -166,7 +165,7 @@ feature -- Error
local
l_page: CMS_RESPONSE
do
- create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, setup, "master2/error")
+ create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)
l_page.add_variable (req.absolute_script_url (req.path_info), "request")
if a_id.is_integer then
-- resource not found
@@ -187,7 +186,7 @@ feature {NONE} -- Node
l_page: CMS_RESPONSE
do
if attached current_user_name (req) then
- create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, setup, "modules/node")
+ create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)
l_page.add_variable (setup.is_html, "html")
l_page.add_variable (setup.is_web, "web")
l_page.execute
diff --git a/cms/src/modules/node/handler/node_summary_handler.e b/cms/src/modules/node/handler/node_summary_handler.e
index d3ec258..01553b2 100644
--- a/cms/src/modules/node/handler/node_summary_handler.e
+++ b/cms/src/modules/node/handler/node_summary_handler.e
@@ -68,8 +68,8 @@ feature -- HTTP Methods
if attached current_user_name (req) then
-- Existing node
if attached {WSF_STRING} req.path_parameter ("id") as l_id then
- if l_id.is_integer and then attached {CMS_NODE} api_service.node (l_id.integer_value) as l_node then
- create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, setup, "modules/node_summary")
+ if l_id.is_integer and then attached {CMS_NODE} api.node (l_id.integer_value) as l_node then
+ create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)
l_page.add_variable (l_id.value, "id")
l_page.add_variable (l_node.summary, "node_summary")
l_page.execute
@@ -77,7 +77,7 @@ feature -- HTTP Methods
do_error (req, res, l_id)
end
else
- (create {ERROR_500_CMS_RESPONSE}.make (req, res, setup, "master2/error")).execute
+ (create {ERROR_500_CMS_RESPONSE}.make (req, res, api)).execute
end
else
(create {CMS_GENERIC_RESPONSE}).new_response_unauthorized (req, res)
@@ -87,24 +87,22 @@ feature -- HTTP Methods
do_post (req: WSF_REQUEST; res: WSF_RESPONSE)
--
- local
- u_node: CMS_NODE
do
if attached current_user_name (req) then
if attached {WSF_STRING} req.path_parameter ("id") as l_id then
- if l_id.is_integer and then attached {CMS_NODE} api_service.node (l_id.integer_value) as l_node then
+ if l_id.is_integer and then attached {CMS_NODE} api.node (l_id.integer_value) as l_node then
if attached {WSF_STRING} req.form_parameter ("method") as l_method then
if l_method.is_case_insensitive_equal ("PUT") then
do_put (req, res)
else
- (create {ERROR_500_CMS_RESPONSE}.make (req, res, setup, "master2/error")).execute
+ (create {ERROR_500_CMS_RESPONSE}.make (req, res, api)).execute
end
end
else
do_error (req, res, l_id)
end
else
- (create {ERROR_500_CMS_RESPONSE}.make (req, res, setup, "master2/error")).execute
+ (create {ERROR_500_CMS_RESPONSE}.make (req, res, api)).execute
end
else
(create {CMS_GENERIC_RESPONSE}).new_response_unauthorized (req, res)
@@ -118,16 +116,16 @@ feature -- HTTP Methods
do
if attached current_user (req) as l_user then
if attached {WSF_STRING} req.path_parameter ("id") as l_id then
- if l_id.is_integer and then attached {CMS_NODE} api_service.node (l_id.integer_value) as l_node then
+ if l_id.is_integer and then attached {CMS_NODE} api.node (l_id.integer_value) as l_node then
u_node := extract_data_form (req)
u_node.set_id (l_id.integer_value)
- api_service.update_node_summary (l_user.id,u_node.id, u_node.summary)
+ api.update_node_summary (l_user.id,u_node.id, u_node.summary)
(create {CMS_GENERIC_RESPONSE}).new_response_redirect (req, res, req.absolute_script_url (""))
else
do_error (req, res, l_id)
end
else
- (create {ERROR_500_CMS_RESPONSE}.make (req, res, setup, "master2/error")).execute
+ (create {ERROR_500_CMS_RESPONSE}.make (req, res, api)).execute
end
else
(create {CMS_GENERIC_RESPONSE}).new_response_unauthorized (req, res)
@@ -142,7 +140,7 @@ feature -- Error
local
l_page: CMS_RESPONSE
do
- create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, setup, "master2/error")
+ create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)
l_page.add_variable (req.absolute_script_url (req.path_info), "request")
if a_id.is_integer then
-- resource not found
diff --git a/cms/src/modules/node/handler/node_title_handler.e b/cms/src/modules/node/handler/node_title_handler.e
index 570b155..0cfe30d 100644
--- a/cms/src/modules/node/handler/node_title_handler.e
+++ b/cms/src/modules/node/handler/node_title_handler.e
@@ -68,8 +68,8 @@ feature -- HTTP Methods
if attached current_user_name (req) as l_user then
-- Existing node
if attached {WSF_STRING} req.path_parameter ("id") as l_id then
- if l_id.is_integer and then attached {CMS_NODE} api_service.node (l_id.integer_value) as l_node then
- create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, setup, "modules/node_title")
+ if l_id.is_integer and then attached {CMS_NODE} api.node (l_id.integer_value) as l_node then
+ create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)
l_page.add_variable (l_node.title, "node_title")
l_page.add_variable (l_id.value, "id")
l_page.execute
@@ -77,7 +77,7 @@ feature -- HTTP Methods
do_error (req, res, l_id)
end
else
- (create {ERROR_500_CMS_RESPONSE}.make (req, res, setup, "master2/error")).execute
+ (create {ERROR_500_CMS_RESPONSE}.make (req, res, api)).execute
end
else
(create {CMS_GENERIC_RESPONSE}).new_response_unauthorized (req, res)
@@ -86,24 +86,22 @@ feature -- HTTP Methods
do_post (req: WSF_REQUEST; res: WSF_RESPONSE)
--
- local
- u_node: CMS_NODE
do
if attached current_user_name (req) as l_user then
if attached {WSF_STRING} req.path_parameter ("id") as l_id then
- if l_id.is_integer and then attached {CMS_NODE} api_service.node (l_id.integer_value) as l_node then
+ if l_id.is_integer and then attached {CMS_NODE} api.node (l_id.integer_value) as l_node then
if attached {WSF_STRING} req.form_parameter ("method") as l_method then
if l_method.is_case_insensitive_equal ("PUT") then
do_put (req, res)
else
- (create {ERROR_500_CMS_RESPONSE}.make (req, res, setup, "master2/error")).execute
+ (create {ERROR_500_CMS_RESPONSE}.make (req, res, api)).execute
end
end
else
do_error (req, res, l_id)
end
else
- (create {ERROR_500_CMS_RESPONSE}.make (req, res, setup, "master2/error")).execute
+ (create {ERROR_500_CMS_RESPONSE}.make (req, res, api)).execute
end
else
(create {CMS_GENERIC_RESPONSE}).new_response_unauthorized (req, res)
@@ -118,16 +116,16 @@ feature -- HTTP Methods
to_implement ("Check if user has permissions")
if attached current_user (req) as l_user then
if attached {WSF_STRING} req.path_parameter ("id") as l_id then
- if l_id.is_integer and then attached {CMS_NODE} api_service.node (l_id.integer_value) as l_node then
+ if l_id.is_integer and then attached {CMS_NODE} api.node (l_id.integer_value) as l_node then
u_node := extract_data_form (req)
u_node.set_id (l_id.integer_value)
- api_service.update_node_title (l_user.id,u_node.id, u_node.title)
+ api.update_node_title (l_user.id,u_node.id, u_node.title)
(create {CMS_GENERIC_RESPONSE}).new_response_redirect (req, res, req.absolute_script_url (""))
else
do_error (req, res, l_id)
end
else
- (create {ERROR_500_CMS_RESPONSE}.make (req, res, setup, "master2/error")).execute
+ (create {ERROR_500_CMS_RESPONSE}.make (req, res, api)).execute
end
else
(create {CMS_GENERIC_RESPONSE}).new_response_unauthorized (req, res)
@@ -141,7 +139,7 @@ feature -- Error
local
l_page: CMS_RESPONSE
do
- create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, setup, "master2/error")
+ create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)
l_page.add_variable (req.absolute_script_url (req.path_info), "request")
if a_id.is_integer then
-- resource not found
diff --git a/cms/src/modules/node/handler/nodes_handler.e b/cms/src/modules/node/handler/nodes_handler.e
index f1097db..651e8e7 100644
--- a/cms/src/modules/node/handler/nodes_handler.e
+++ b/cms/src/modules/node/handler/nodes_handler.e
@@ -52,8 +52,8 @@ feature -- HTTP Methods
-- At the moment the template is hardcoded, but we can
-- get them from the configuration file and load them into
-- the setup class.
- create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, setup, "modules/nodes")
- l_page.add_variable (api_service.nodes, "nodes")
+ create {GENERIC_VIEW_CMS_RESPONSE} l_page.make (req, res, api)
+ l_page.add_variable (api.nodes, "nodes")
l_page.execute
end
end
diff --git a/cms/src/modules/node/node_module.e b/cms/src/modules/node/node_module.e
index 1ecaea3..f5c7349 100644
--- a/cms/src/modules/node/node_module.e
+++ b/cms/src/modules/node/node_module.e
@@ -9,78 +9,88 @@ class
inherit
CMS_MODULE
+ redefine
+ register_hooks
+ end
+
+ CMS_HOOK_MENU_ALTER
+
+ CMS_HOOK_BLOCK
+
create
make
feature {NONE} -- Initialization
- make (a_config: CMS_SETUP)
+ make (a_setup: CMS_SETUP)
-- Create Current module, disabled by default.
do
name := "node"
version := "1.0"
description := "Service to manage content based on 'node'"
package := "core"
- config := a_config
+ config := a_setup
end
+
config: CMS_SETUP
-- Node configuration.
feature -- Access: router
- router: WSF_ROUTER
+ router (a_api: CMS_API): WSF_ROUTER
-- Node router.
do
create Result.make (5)
- configure_api_node (Result)
- configure_api_nodes (Result)
- configure_api_node_title (Result)
- configure_api_node_summary (Result)
- configure_api_node_content (Result)
+ configure_api_node (a_api, Result)
+ configure_api_nodes (a_api, Result)
+ configure_api_node_title (a_api, Result)
+ configure_api_node_summary (a_api, Result)
+ configure_api_node_content (a_api, Result)
end
feature {NONE} -- Implementation: routes
- configure_api_node (a_router: WSF_ROUTER)
+ configure_api_node (api: CMS_API; a_router: WSF_ROUTER)
local
l_node_handler: NODE_HANDLER
l_methods: WSF_REQUEST_METHODS
do
- create l_node_handler.make (config)
+ create l_node_handler.make (api)
create l_methods
l_methods.enable_get
l_methods.enable_post
l_methods.enable_put
a_router.handle_with_request_methods ("/node", l_node_handler, l_methods)
- create l_node_handler.make (config)
+ create l_node_handler.make (api)
create l_methods
l_methods.enable_get
l_methods.enable_post
l_methods.enable_put
l_methods.enable_delete
a_router.handle_with_request_methods ("/node/{id}", l_node_handler, l_methods)
+ a_router.handle_with_request_methods ("/nodes/", create {WSF_URI_AGENT_HANDLER}.make (agent do_get_nodes (?,?, api)), a_router.methods_get)
end
- configure_api_nodes (a_router: WSF_ROUTER)
+ configure_api_nodes (api: CMS_API; a_router: WSF_ROUTER)
local
l_nodes_handler: NODES_HANDLER
l_methods: WSF_REQUEST_METHODS
do
- create l_nodes_handler.make (config)
+ create l_nodes_handler.make (api)
create l_methods
l_methods.enable_get
a_router.handle_with_request_methods ("/nodes", l_nodes_handler, l_methods)
end
- configure_api_node_summary (a_router: WSF_ROUTER)
+ configure_api_node_summary (api: CMS_API; a_router: WSF_ROUTER)
local
l_report_handler: NODE_SUMMARY_HANDLER
l_methods: WSF_REQUEST_METHODS
do
- create l_report_handler.make (config)
+ create l_report_handler.make (api)
create l_methods
l_methods.enable_get
l_methods.enable_post
@@ -88,13 +98,12 @@ feature {NONE} -- Implementation: routes
a_router.handle_with_request_methods ("/node/{id}/summary", l_report_handler, l_methods)
end
-
- configure_api_node_title (a_router: WSF_ROUTER)
+ configure_api_node_title (api: CMS_API; a_router: WSF_ROUTER)
local
l_report_handler: NODE_TITLE_HANDLER
l_methods: WSF_REQUEST_METHODS
do
- create l_report_handler.make (config)
+ create l_report_handler.make (api)
create l_methods
l_methods.enable_get
l_methods.enable_post
@@ -102,12 +111,12 @@ feature {NONE} -- Implementation: routes
a_router.handle_with_request_methods ("/node/{id}/title", l_report_handler, l_methods)
end
- configure_api_node_content (a_router: WSF_ROUTER)
+ configure_api_node_content (api: CMS_API; a_router: WSF_ROUTER)
local
l_report_handler: NODE_CONTENT_HANDLER
l_methods: WSF_REQUEST_METHODS
do
- create l_report_handler.make (config)
+ create l_report_handler.make (api)
create l_methods
l_methods.enable_get
l_methods.enable_post
@@ -115,4 +124,46 @@ feature {NONE} -- Implementation: routes
a_router.handle_with_request_methods ("/node/{id}/content", l_report_handler, l_methods)
end
+feature -- Hooks
+
+ register_hooks (a_response: CMS_RESPONSE)
+ do
+ a_response.add_menu_alter_hook (Current)
+ a_response.add_block_hook (Current)
+ end
+
+ block_list: ITERABLE [like {CMS_BLOCK}.name]
+ do
+ Result := <<"node-info">>
+ end
+
+ get_block_view (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE)
+ local
+-- b: CMS_CONTENT_BLOCK
+ do
+-- create b.make (a_block_id, "Block::node", "This is a block test", Void)
+-- a_response.add_block (b, "sidebar_second")
+ end
+
+ menu_alter (a_menu_system: CMS_MENU_SYSTEM; a_response: CMS_RESPONSE)
+ local
+ lnk: CMS_LOCAL_LINK
+-- perms: detachable ARRAYED_LIST [READABLE_STRING_8]
+ do
+ create lnk.make ("List of nodes", a_response.url ("/nodes", Void))
+ a_menu_system.primary_menu.extend (lnk)
+ end
+
+feature -- Handler
+
+ do_get_nodes (req: WSF_REQUEST; res: WSF_RESPONSE; a_api: CMS_API)
+ local
+ r: CMS_RESPONSE
+ do
+ create {NOT_IMPLEMENTED_ERROR_CMS_RESPONSE} r.make (req, res, a_api)
+ r.set_main_content ("Sorry: listing the CMS nodes is not yet implemented.")
+ r.add_block (create {CMS_CONTENT_BLOCK}.make ("nodes_warning", Void, "/nodes/ is not yet implemented", Void), "highlighted")
+ r.execute
+ end
+
end
diff --git a/cms/src/service/cms_api_service.e b/cms/src/service/cms_api.e
similarity index 55%
rename from cms/src/service/cms_api_service.e
rename to cms/src/service/cms_api.e
index c7b69ff..877bbf7 100644
--- a/cms/src/service/cms_api_service.e
+++ b/cms/src/service/cms_api.e
@@ -1,36 +1,87 @@
note
- description: "Summary description for {CMS_API_SERVICE}."
+ description: "Summary description for {CMS_API}."
date: "$Date$"
revision: "$Revision$"
class
- CMS_API_SERVICE
+ CMS_API
inherit
SHARED_ERROR
- REFACTORING_HELPER
+ REFACTORING_HELPER
create
make
feature -- Initialize
- make (a_storage: CMS_STORAGE)
+ make (a_setup: CMS_SETUP)
-- Create the API service with an storege `a_storage'.
do
- storage := a_storage
+ setup := a_setup
+ create error_handler.make
+ initialize
set_successful
ensure
- storage_set: storage = a_storage
+-- storage_set: storage = a_storage
+ end
+
+ setup: CMS_SETUP
+ -- CMS setup.
+
+ initialize
+ local
+ l_database: DATABASE_CONNECTION
+ retried: BOOLEAN
+ l_message: STRING
+ do
+ if not retried then
+ to_implement ("Refactor database setup")
+ if attached (create {JSON_CONFIGURATION}).new_database_configuration (setup.layout.application_config_path) as l_database_config then
+ create {DATABASE_CONNECTION_MYSQL} l_database.login_with_connection_string (l_database_config.connection_string)
+ create {CMS_STORAGE_MYSQL} storage.make (l_database)
+ else
+ create {DATABASE_CONNECTION_NULL} l_database.make_common
+ create {CMS_STORAGE_NULL} storage
+ end
+ else
+ to_implement ("Workaround code, persistence layer does not implement yet this kind of error handling.")
+ -- error hanling.
+ create {DATABASE_CONNECTION_NULL} l_database.make_common
+ create {CMS_STORAGE_NULL} storage
+ create l_message.make (1024)
+ if attached ((create {EXCEPTION_MANAGER}).last_exception) as l_exception then
+ if attached l_exception.description as l_description then
+ l_message.append (l_description.as_string_32)
+ l_message.append ("%N%N")
+ elseif attached l_exception.trace as l_trace then
+ l_message.append (l_trace)
+ l_message.append ("%N%N")
+ else
+ l_message.append (l_exception.out)
+ l_message.append ("%N%N")
+ end
+ else
+ l_message.append ("The application crash without available information")
+ l_message.append ("%N%N")
+ end
+ error_handler.add_custom_error (0, " Database Connection ", l_message)
+ end
+ rescue
+ retried := True
+ retry
end
feature -- Access
+ error_handler: ERROR_HANDLER
+ -- Error handler.
+
+feature -- Status Report
+
is_valid_credential (l_auth_login, l_auth_password: READABLE_STRING_32): BOOLEAN
- local
- l_security: SECURITY_PROVIDER
do
Result := storage.is_valid_credential (l_auth_login, l_auth_password)
end
diff --git a/cms/src/service/cms_api_options.e b/cms/src/service/cms_api_options.e
new file mode 100644
index 0000000..1a5dc6e
--- /dev/null
+++ b/cms/src/service/cms_api_options.e
@@ -0,0 +1,17 @@
+note
+ description: "Summary description for {CMS_API_OPTIONS}."
+ author: ""
+ date: "$Date$"
+ revision: "$Revision$"
+
+class
+ CMS_API_OPTIONS
+
+inherit
+ WSF_API_OPTIONS
+
+create
+ make,
+ make_from_manifest
+
+end
diff --git a/cms/src/service/cms_request_util.e b/cms/src/service/cms_request_util.e
index e9e26c8..e6a1be6 100644
--- a/cms/src/service/cms_request_util.e
+++ b/cms/src/service/cms_request_util.e
@@ -9,6 +9,8 @@ deferred class
inherit
+ CMS_ENCODERS
+
REFACTORING_HELPER
feature -- User
@@ -21,8 +23,6 @@ feature -- User
if attached {CMS_USER} current_user (req) as l_user then
Result := l_user.name
end
-
-
end
current_user (req: WSF_REQUEST): detachable CMS_USER
diff --git a/cms/src/service/cms_service.e b/cms/src/service/cms_service.e
index 37a4759..973bc6e 100644
--- a/cms/src/service/cms_service.e
+++ b/cms/src/service/cms_service.e
@@ -41,11 +41,11 @@ create
feature {NONE} -- Initialization
- make (a_setup: CMS_SETUP)
+ make (a_api: CMS_API)
-- Build a CMS service with `a_setup' configuration.
do
- setup := a_setup
- configuration := a_setup.configuration
+ api := a_api
+ configuration := a_api.setup.configuration
initialize
end
@@ -103,36 +103,41 @@ feature -- Settings: router
--
local
l_module: CMS_MODULE
+ l_api: like api
+ l_router: like router
do
log.write_debug (generator + ".setup_router")
-- Configure root of api handler.
- configure_api_root
+
+ l_router := router
+ configure_api_root (l_router)
-- Include routes from modules.
+ l_api := api
across
modules as ic
loop
l_module := ic.item
- router.import (l_module.router)
+ l_router.import (l_module.router (l_api))
end
-- Configure files handler.
- configure_api_file_handler
+ configure_api_file_handler (l_router)
end
- configure_api_root
+ configure_api_root (a_router: WSF_ROUTER)
local
l_root_handler: CMS_ROOT_HANDLER
l_methods: WSF_REQUEST_METHODS
do
log.write_debug (generator + ".configure_api_root")
- create l_root_handler.make (setup)
+ create l_root_handler.make (api)
create l_methods
l_methods.enable_get
- router.handle_with_request_methods ("/", l_root_handler, l_methods)
- router.handle_with_request_methods ("", l_root_handler, l_methods)
+ a_router.handle_with_request_methods ("/", l_root_handler, l_methods)
+ a_router.handle_with_request_methods ("", l_root_handler, l_methods)
end
- configure_api_file_handler
+ configure_api_file_handler (a_router: WSF_ROUTER)
local
fhdl: WSF_FILE_SYSTEM_HANDLER
do
@@ -143,7 +148,7 @@ feature -- Settings: router
do
execute_default (ia_req, ia_res)
end)
- router.handle_with_request_methods ("/", fhdl, router.methods_GET)
+ a_router.handle_with_request_methods ("/", fhdl, router.methods_GET)
end
feature -- Execute Filter
@@ -162,22 +167,30 @@ feature -- Filters
local
f, l_filter: detachable WSF_FILTER
l_module: CMS_MODULE
+ l_api: like api
do
log.write_debug (generator + ".create_filter")
l_filter := Void
+
-- Maintenance
create {WSF_MAINTENANCE_FILTER} f
f.set_next (l_filter)
+ l_filter := f
+
+ -- Error Filter
+ create {CMS_ERROR_FILTER} f.make (api)
+ f.set_next (l_filter)
l_filter := f
-- Include filters from modules
+ l_api := api
across
modules as ic
loop
l_module := ic.item
if
l_module.is_enabled and then
- attached l_module.filters as l_m_filters
+ attached l_module.filters (l_api) as l_m_filters
then
across l_m_filters as f_ic loop
f := f_ic.item
@@ -207,11 +220,16 @@ feature -- Filters
f.set_next (Current)
end
-
feature -- Access
+ api: CMS_API
+ -- API service.
+
setup: CMS_SETUP
-- CMS setup.
+ do
+ Result := api.setup
+ end
configuration: CMS_CONFIGURATION
-- CMS configuration.
diff --git a/cms/src/service/cms_url_utilities.e b/cms/src/service/cms_url_utilities.e
new file mode 100644
index 0000000..8fff472
--- /dev/null
+++ b/cms/src/service/cms_url_utilities.e
@@ -0,0 +1,129 @@
+note
+ description: "Summary description for {CMS_URL_UTILITIES}."
+ author: ""
+ date: "$Date$"
+ revision: "$Revision$"
+
+deferred class
+ CMS_URL_UTILITIES
+
+inherit
+ CMS_REQUEST_UTIL
+
+feature -- Core
+
+ site_url: READABLE_STRING_8
+ deferred
+ end
+
+ base_url: detachable READABLE_STRING_8
+ -- Base url if any.
+ deferred
+ end
+
+ based_path (p: STRING): STRING
+ -- Path `p' in the context of the `base_url'
+ do
+ if attached base_url as l_base_url then
+ create Result.make_from_string (l_base_url)
+ if p.is_empty then
+ else
+ if p[1] = '/' then
+ Result.append (p.substring (2, p.count))
+ else
+ Result.append (p)
+ end
+ end
+ else
+ Result := p
+ end
+ end
+
+feature -- Url
+
+ absolute_url (a_path: STRING; opts: detachable CMS_API_OPTIONS): STRING
+ local
+ l_opts: detachable CMS_API_OPTIONS
+ do
+ l_opts := opts
+ if l_opts = Void then
+ create l_opts.make (1)
+ end
+ l_opts.force (True, "absolute")
+ Result := url (a_path, l_opts)
+ end
+
+ url (a_path: READABLE_STRING_8; opts: detachable CMS_API_OPTIONS): STRING
+ -- URL for path `a_path' and optional parameters from `opts'.
+ --| Options `opts' could be
+ --| - absolute: True|False => return absolute url
+ --| - query: string => append "?query"
+ --| - fragment: string => append "#fragment"
+ local
+ q,f: detachable STRING_8
+ l_abs: BOOLEAN
+ do
+ l_abs := False
+
+ if opts /= Void then
+ l_abs := opts.boolean_item ("absolute", l_abs)
+ if attached opts.item ("query") as l_query then
+ if attached {READABLE_STRING_8} l_query as s_value then
+ q := s_value
+ elseif attached {ITERABLE [TUPLE [key, value: READABLE_STRING_GENERAL]]} l_query as lst then
+ create q.make_empty
+ across
+ lst as c
+ loop
+ if q.is_empty then
+ else
+ q.append_character ('&')
+ end
+ q.append (url_encoded (c.item.key))
+ q.append_character ('=')
+ q.append (url_encoded (c.item.value))
+ end
+ end
+ end
+ if attached opts.string_item ("fragment") as s_frag then
+ f := s_frag
+ end
+ end
+ if l_abs then
+ if a_path.substring_index ("://", 1) = 0 then
+ create Result.make_from_string (site_url)
+ if a_path.is_empty then
+ elseif Result.ends_with ("/") then
+ if a_path[1] = '/' then
+ Result.append_string (a_path.substring (2, a_path.count))
+ else
+ Result.append_string (a_path)
+ end
+ else
+ if a_path[1] = '/' then
+ Result.append_string (a_path)
+ else
+ Result.append_character ('/')
+ Result.append_string (a_path)
+ end
+ end
+ else
+ Result := a_path
+ end
+ else
+ Result := based_path (a_path)
+ end
+ if q /= Void then
+ Result.append ("?" + q)
+ end
+ if f /= Void then
+ Result.append ("#" + f)
+ end
+ end
+
+ checked_url (a_url: READABLE_STRING_8): READABLE_STRING_8
+ do
+ Result := a_url
+ end
+
+end
diff --git a/cms/src/service/filter/cms_error_filter.e b/cms/src/service/filter/cms_error_filter.e
new file mode 100644
index 0000000..2c8c780
--- /dev/null
+++ b/cms/src/service/filter/cms_error_filter.e
@@ -0,0 +1,33 @@
+note
+ description: "Summary description for {CMS_ERROR_FILTER}."
+ date: "$Date$"
+ revision: "$Revision$"
+
+class
+ CMS_ERROR_FILTER
+
+inherit
+
+ WSF_URI_TEMPLATE_HANDLER
+ CMS_HANDLER
+ WSF_FILTER
+
+create
+ make
+
+feature -- Basic operations
+
+ execute (req: WSF_REQUEST; res: WSF_RESPONSE)
+ -- Execute the filter
+ do
+ if not api.error_handler.has_error then
+ log.write_information (generator + ".execute")
+ execute_next (req, res)
+ else
+ log.write_critical (generator + ".execute" + api.error_handler.as_string_representation )
+ (create {ERROR_500_CMS_RESPONSE}.make (req, res, api)).execute
+ api.error_handler.reset
+ end
+ end
+
+end
diff --git a/cms/src/service/handler/cms_handler.e b/cms/src/service/handler/cms_handler.e
index c6d2902..9de1552 100644
--- a/cms/src/service/handler/cms_handler.e
+++ b/cms/src/service/handler/cms_handler.e
@@ -19,20 +19,20 @@ inherit
feature {NONE} -- Initialization
- make (a_setup: CMS_SETUP)
+ make (a_api: CMS_API)
do
- setup := a_setup
+ api := a_api
end
feature -- Setup
setup: CMS_SETUP
+ do
+ Result := api.setup
+ end
feature -- API Service
- api_service: CMS_API_SERVICE
- do
- Result := setup.api_service
- end
+ api: CMS_API
end
diff --git a/cms/src/service/handler/cms_root_handler.e b/cms/src/service/handler/cms_root_handler.e
index fdb2783..cf1284d 100644
--- a/cms/src/service/handler/cms_root_handler.e
+++ b/cms/src/service/handler/cms_root_handler.e
@@ -48,7 +48,7 @@ feature -- HTTP Methods
do_get (req: WSF_REQUEST; res: WSF_RESPONSE)
--
do
- (create {HOME_CMS_RESPONSE}.make (req, res, setup,"layout2")).execute
+ (create {HOME_CMS_RESPONSE}.make (req, res, api)).execute
end
end
diff --git a/cms/src/service/response/cms_generic_response.e b/cms/src/service/response/cms_generic_response.e
index 380a391..371bc05 100644
--- a/cms/src/service/response/cms_generic_response.e
+++ b/cms/src/service/response/cms_generic_response.e
@@ -50,7 +50,6 @@ feature -- Responses
-- Handle not authorized.
local
h: HTTP_HEADER
- output: STRING
do
create h.make
h.put_content_type_text_html
diff --git a/cms/src/service/response/cms_response.e b/cms/src/service/response/cms_response.e
index 671c031..14894ab 100644
--- a/cms/src/service/response/cms_response.e
+++ b/cms/src/service/response/cms_response.e
@@ -1,5 +1,5 @@
note
- description: "Generic CMS Response, place to add HOOKS features as collaborators."
+ description: "Generic CMS Response.It builds the content to get process to render the output"
date: "$Date$"
revision: "$Revision$"
@@ -7,27 +7,45 @@ deferred class
CMS_RESPONSE
inherit
-
- CMS_REQUEST_UTIL
+ CMS_URL_UTILITIES
REFACTORING_HELPER
feature {NONE} -- Initialization
- make (req: WSF_REQUEST; res: WSF_RESPONSE; a_setup: like setup; a_template: like template)
+ make (req: WSF_REQUEST; res: WSF_RESPONSE; a_api: like api)
do
status_code := {HTTP_STATUS_CODE}.ok
- setup := a_setup
+ api := a_api
request := req
response := res
- template := a_template
create header.make
+ create values.make (3)
initialize
end
initialize
do
get_theme
+ create menu_system.make
+ initialize_block_region_settings
+ register_hooks
+ end
+
+ register_hooks
+ local
+ l_module: CMS_MODULE
+ l_available_modules: CMS_MODULE_COLLECTION
+ do
+ l_available_modules := setup.modules
+ across
+ l_available_modules as ic
+ loop
+ l_module := ic.item
+ if l_module.is_enabled then
+ l_module.register_hooks (Current)
+ end
+ end
end
feature -- Access
@@ -36,8 +54,14 @@ feature -- Access
response: WSF_RESPONSE
+ api: CMS_API
+ -- Current CMS API.
+
setup: CMS_SETUP
- -- Current setup
+ -- Current setup
+ do
+ Result := api.setup
+ end
status_code: INTEGER
@@ -50,8 +74,107 @@ feature -- Access
main_content: detachable STRING_8
- template: READABLE_STRING_32
- -- Current template.
+ additional_page_head_lines: detachable LIST [READABLE_STRING_8]
+ -- HTML>head>...extra lines
+
+feature -- URL utilities
+
+ is_front: BOOLEAN
+ -- Is current response related to "front" page?
+ local
+ l_path_info: READABLE_STRING_8
+ do
+ l_path_info := request.path_info
+ if attached setup.front_page_path as l_front_page_path then
+ Result := l_front_page_path.same_string (l_path_info)
+ else
+ if attached base_url as l_base_url then
+ Result := l_path_info.same_string (l_base_url)
+ else
+ Result := l_path_info.is_empty or else l_path_info.same_string ("/")
+ end
+ end
+ end
+
+ site_url: READABLE_STRING_8
+ do
+ Result := absolute_host (request, "")
+ end
+
+ base_url: detachable READABLE_STRING_8
+ -- Base url if any.
+ --| Usually it is Void, but it could be
+ --| /project/demo/
+ --| FIXME: for now, no way to change that. Always at the root "/"
+
+feature -- Access: CMS
+
+ site_name: STRING_32
+ do
+ Result := setup.site_name
+ end
+
+ front_page_url: READABLE_STRING_8
+ do
+ Result := request.absolute_script_url ("/")
+ end
+
+ values: CMS_VALUE_TABLE
+ -- Associated values indexed by string name.
+
+
+
+feature -- Permission
+ -- FIXME: to be implemented has_permissions and has_permission.
+
+feature -- Status
+ -- FIXME: to be implemented
+ -- is_from, is_module, has_js.
+
+
+feature -- Head customization
+
+ add_additional_head_line (s: READABLE_STRING_8; a_allow_duplication: BOOLEAN)
+ local
+ lst: like additional_page_head_lines
+ do
+ lst := additional_page_head_lines
+ if lst = Void then
+ create {ARRAYED_LIST [like additional_page_head_lines.item]} lst.make (1)
+ additional_page_head_lines := lst
+ end
+ if a_allow_duplication or else across lst as c all not c.item.same_string (s) end then
+ lst.extend (s)
+ end
+ end
+
+ add_style (a_href: STRING; a_media: detachable STRING)
+ local
+ s: STRING_8
+ do
+ s := "")
+ add_additional_head_line (s, False)
+ end
+
+ add_javascript_url (a_src: STRING)
+ local
+ s: STRING_8
+ do
+ s := ""
+ add_additional_head_line (s, False)
+ end
+
+ add_javascript_content (a_script: STRING)
+ local
+ s: STRING_8
+ do
+ s := ""
+ add_additional_head_line (s, True)
+ end
feature -- Element change
@@ -71,10 +194,499 @@ feature -- Element change
main_content := s
end
+ set_value (v: detachable ANY; k: READABLE_STRING_GENERAL)
+ -- Set value `v' associated with name `k'.
+ do
+ values.force (v, k)
+ end
+
+ unset_value (k: READABLE_STRING_GENERAL)
+ -- Unset value associated with name `k'.
+ do
+ values.remove (k)
+ end
+
+
+feature -- Logging
+
+ log (a_category: READABLE_STRING_8; a_message: READABLE_STRING_8; a_level: INTEGER; a_link: detachable CMS_LINK)
+ local
+-- l_log: CMS_LOG
+ do
+ debug
+ to_implement ("Add implemenatation")
+ end
+-- create l_log.make (a_category, a_message, a_level, Void)
+-- if a_link /= Void then
+-- l_log.set_link (a_link)
+-- end
+-- l_log.set_info (request.http_user_agent)
+-- service.storage.save_log (l_log)
+ end
+
+feature -- Formats
+
+ formats: CMS_FORMATS
+ once
+ create Result
+ end
+
+feature -- Menu
+
+ menu_system: CMS_MENU_SYSTEM
+
+ main_menu: CMS_MENU
+ obsolete
+ "Use `primary_menu' [Nov/2014]"
+ do
+ Result := primary_menu
+ end
+
+ primary_menu: CMS_MENU
+ do
+ Result := menu_system.primary_menu
+ end
+
+ management_menu: CMS_MENU
+ do
+ Result := menu_system.management_menu
+ end
+
+ navigation_menu: CMS_MENU
+ do
+ Result := menu_system.navigation_menu
+ end
+
+ user_menu: CMS_MENU
+ do
+ Result := menu_system.user_menu
+ end
+
+ primary_tabs: CMS_MENU
+ do
+ Result := menu_system.primary_tabs
+ end
+
+feature -- Blocks initialization
+
+ initialize_block_region_settings
+ local
+ l_table: like block_region_settings
+ do
+ fixme ("CHECK:Can we use the same structure as in theme.info?")
+ create regions.make_caseless (5)
+
+ fixme ("let the user choose ...")
+ create l_table.make_caseless (10)
+ l_table["top"] := "top"
+ l_table["header"] := "header"
+ l_table["highlighted"] := "highlighted"
+ l_table["help"] := "help"
+ l_table["content"] := "content"
+ l_table["footer"] := "footer"
+ l_table["management"] := "first_sidebar"
+ l_table["navigation"] := "first_sidebar"
+ l_table["user"] := "first_sidebar"
+ l_table["bottom"] := "page_bottom"
+ block_region_settings := l_table
+ end
+
+feature -- Blocks regions
+
+ regions: STRING_TABLE [CMS_BLOCK_REGION]
+ -- Layout regions, that contains blocks.
+
+ block_region_settings: STRING_TABLE [STRING]
+
+ block_region (b: CMS_BLOCK; a_default_region: detachable READABLE_STRING_8): CMS_BLOCK_REGION
+ -- Region associated with block `b', or else `a_default_region' if provided.
+ local
+ l_region_name: detachable READABLE_STRING_8
+ do
+ l_region_name := block_region_settings.item (b.name)
+ if l_region_name = Void then
+ if a_default_region /= Void then
+ l_region_name := a_default_region
+ else
+ -- Default .. put it in same named region
+ -- Maybe a bad idea
+
+ l_region_name := b.name.as_lower
+ end
+ end
+ if attached regions.item (l_region_name) as res then
+ Result := res
+ else
+ create Result.make (l_region_name)
+ regions.force (Result, l_region_name)
+ end
+ end
+
+
+feature -- Blocks
+
+ add_block (b: CMS_BLOCK; a_default_region: detachable READABLE_STRING_8)
+ -- Add block `b' to associated region or `a_default_region' if provided.
+ local
+ l_region: detachable like block_region
+ do
+ l_region := block_region (b, a_default_region)
+ l_region.extend (b)
+ end
+
+
+ get_blocks
+ do
+ fixme ("find a way to have this in configuration or database, and allow different order")
+ add_block (top_header_block, "top")
+ add_block (header_block, "header")
+ if attached message_block as m then
+ add_block (m, "content")
+ end
+ -- FIXME: avoid hardcoded html! should be only in theme.
+ add_block (create {CMS_CONTENT_BLOCK}.make_raw ("top_content_anchor", Void, "%N", formats.full_html), "content")
+ if attached page_title as l_page_title then
+ -- FIXME: avoid hardcoded html! should be only in theme.
+ add_block (create {CMS_CONTENT_BLOCK}.make_raw ("page_title", Void, "
"+ l_page_title +"
%N", formats.full_html), "content")
+ end
+ if attached primary_tabs_block as m then
+ add_block (m, "content")
+ end
+ add_block (content_block, "content")
+
+ if attached management_menu_block as l_block then
+ add_block (l_block, "first_sidebar")
+ end
+ if attached navigation_menu_block as l_block then
+ add_block (l_block, "first_sidebar")
+ end
+ if attached user_menu_block as l_block then
+ add_block (l_block, "first_sidebar")
+ end
+
+ if attached footer_block as l_block then
+ add_block (l_block, "footer")
+ end
+
+ hook_block_view
+ end
+
+ primary_menu_block: detachable CMS_MENU_BLOCK
+ do
+ if attached primary_menu as m and then not m.is_empty then
+ create Result.make (m)
+ end
+ end
+
+ management_menu_block: detachable CMS_MENU_BLOCK
+ do
+ if attached management_menu as m and then not m.is_empty then
+ create Result.make (m)
+ end
+ end
+
+ navigation_menu_block: detachable CMS_MENU_BLOCK
+ do
+ if attached navigation_menu as m and then not m.is_empty then
+ create Result.make (m)
+ end
+ end
+
+ user_menu_block: detachable CMS_MENU_BLOCK
+ do
+ if attached user_menu as m and then not m.is_empty then
+ create Result.make (m)
+ end
+ end
+
+ primary_tabs_block: detachable CMS_MENU_BLOCK
+ do
+ if attached primary_tabs as m and then not m.is_empty then
+ create Result.make (m)
+ end
+ end
+
+ top_header_block: CMS_CONTENT_BLOCK
+ local
+ s: STRING
+ do
+ create s.make_empty
+ create Result.make ("page_top", Void, s, formats.full_html)
+ Result.set_is_raw (True)
+ end
+
+ header_block: CMS_CONTENT_BLOCK
+ local
+ s: STRING
+ l_hb: STRING
+ do
+ create s.make_from_string (theme.menu_html (primary_menu, True))
+ create l_hb.make_empty
+ create Result.make ("header", Void, l_hb, formats.full_html)
+ Result.set_is_raw (True)
+ end
+
+ horizontal_primary_menu_html: STRING
+ do
+ create Result.make_empty
+ Result.append ("
")
+ end
+
+ message_html: detachable STRING
+ do
+ if attached message as m and then not m.is_empty then
+ Result := "
" + m + "
"
+ end
+ end
+
+ message_block: detachable CMS_CONTENT_BLOCK
+ do
+ if attached message as m and then not m.is_empty then
+ create Result.make ("message", Void, "
" + m + "
", formats.full_html)
+ Result.set_is_raw (True)
+ end
+ end
+
+ content_block: CMS_CONTENT_BLOCK
+ local
+ s: STRING
+ do
+ if attached main_content as l_content then
+ s := l_content
+ else
+ s := ""
+ debug
+ s := "No Content"
+ end
+ end
+ create Result.make ("content", Void, s, formats.full_html)
+ Result.set_is_raw (True)
+ end
+
+ made_with_html: STRING
+ do
+ create Result.make_empty
+ Result.append ("Made with EWF")
+ end
+
+ footer_block: CMS_CONTENT_BLOCK
+ do
+ create Result.make ("made_with", Void, made_with_html, Void)
+ end
+
+feature -- Hook: value alter
+
+ add_value_alter_hook (h: like value_alter_hooks.item)
+ local
+ lst: like value_alter_hooks
+ do
+ lst := value_alter_hooks
+ if lst = Void then
+ create lst.make (1)
+ value_alter_hooks := lst
+ end
+ if not lst.has (h) then
+ lst.force (h)
+ end
+ end
+
+ value_alter_hooks: detachable ARRAYED_LIST [CMS_HOOK_VALUE_ALTER]
+
+ call_value_alter_hooks (m: CMS_VALUE_TABLE)
+ do
+ if attached value_alter_hooks as lst then
+ across
+ lst as c
+ loop
+ c.item.value_alter (m, Current)
+ end
+ end
+ end
+
+feature -- Hook: menu_alter
+
+ add_menu_alter_hook (h: like menu_alter_hooks.item)
+ local
+ lst: like menu_alter_hooks
+ do
+ lst := menu_alter_hooks
+ if lst = Void then
+ create lst.make (1)
+ menu_alter_hooks := lst
+ end
+ if not lst.has (h) then
+ lst.force (h)
+ end
+ end
+
+ menu_alter_hooks: detachable ARRAYED_LIST [CMS_HOOK_MENU_ALTER]
+
+ call_menu_alter_hooks (m: CMS_MENU_SYSTEM )
+ do
+ if attached menu_alter_hooks as lst then
+ across
+ lst as c
+ loop
+ c.item.menu_alter (m, Current)
+ end
+ end
+ end
+
+feature -- Hook: form_alter
+
+ add_form_alter_hook (h: like form_alter_hooks.item)
+ local
+ lst: like form_alter_hooks
+ do
+ lst := form_alter_hooks
+ if lst = Void then
+ create lst.make (1)
+ form_alter_hooks := lst
+ end
+ if not lst.has (h) then
+ lst.force (h)
+ end
+ end
+
+ form_alter_hooks: detachable ARRAYED_LIST [CMS_HOOK_FORM_ALTER]
+
+ call_form_alter_hooks (f: CMS_FORM; a_form_data: detachable WSF_FORM_DATA; )
+ do
+ if attached form_alter_hooks as lst then
+ across
+ lst as c
+ loop
+ c.item.form_alter (f, a_form_data, Current)
+ end
+ end
+ end
+
+feature -- Hook: block
+
+ add_block_hook (h: like block_hooks.item)
+ local
+ lst: like block_hooks
+ do
+ lst := block_hooks
+ if lst = Void then
+ create lst.make (1)
+ block_hooks := lst
+ end
+ if not lst.has (h) then
+ lst.force (h)
+ end
+ end
+
+ block_hooks: detachable ARRAYED_LIST [CMS_HOOK_BLOCK]
+
+ hook_block_view
+ do
+ if attached block_hooks as lst then
+ across
+ lst as c
+ loop
+ across
+ c.item.block_list as blst
+ loop
+ c.item.get_block_view (blst.item, Current)
+ end
+ end
+ end
+ end
+
+
+feature -- Menu: change
+
+ add_to_main_menu (lnk: CMS_LINK)
+ obsolete
+ "use add_to_primary_menu [Nov/2014]"
+ do
+ add_to_primary_menu (lnk)
+ end
+
+ add_to_primary_menu (lnk: CMS_LINK)
+ do
+ add_to_menu (lnk, primary_menu)
+ end
+
+ add_to_menu (lnk: CMS_LINK; m: CMS_MENU)
+ do
+-- if attached {CMS_LOCAL_LINK} lnk as l_local then
+-- l_local.get_is_active (request)
+-- end
+ m.extend (lnk)
+ end
+
+feature -- Message
+
+ add_message (a_msg: READABLE_STRING_8; a_category: detachable READABLE_STRING_8)
+ local
+ m: like message
+ do
+ m := message
+ if m = Void then
+ create m.make (a_msg.count + 9)
+ message := m
+ end
+ if a_category /= Void then
+ m.append ("
")
+ else
+ m.append ("
")
+ end
+ m.append (a_msg + "
")
+ end
+
+ add_notice_message (a_msg: READABLE_STRING_8)
+ do
+ add_message (a_msg, "notice")
+ end
+
+ add_warning_message (a_msg: READABLE_STRING_8)
+ do
+ add_message (a_msg, "warning")
+ end
+
+ add_error_message (a_msg: READABLE_STRING_8)
+ do
+ add_message (a_msg, "error")
+ end
+
+ add_success_message (a_msg: READABLE_STRING_8)
+ do
+ add_message (a_msg, "success")
+ end
+
+ report_form_errors (fd: WSF_FORM_DATA)
+ require
+ has_error: not fd.is_valid
+ do
+ if attached fd.errors as errs then
+ across
+ errs as err
+ loop
+ if attached err.item as e then
+ if attached e.field as l_field then
+ if attached e.message as e_msg then
+ add_error_message (e_msg) --"Field [" + l_field.name + "] is invalid. " + e_msg)
+ else
+ add_error_message ("Field [" + l_field.name + "] is invalid.")
+ end
+ elseif attached e.message as e_msg then
+ add_error_message (e_msg)
+ end
+ end
+ end
+ end
+ end
+
+ message: detachable STRING_8
+
feature -- Theme
theme: CMS_THEME
- -- Current theme
+ -- Current theme
get_theme
local
@@ -86,7 +698,7 @@ feature -- Theme
create l_info.make_default
end
if l_info.engine.is_case_insensitive_equal_general ("smarty") then
- create {SMARTY_CMS_THEME} theme.make (setup, l_info, template)
+ create {SMARTY_CMS_THEME} theme.make (setup, l_info)
else
create {DEFAULT_CMS_THEME} theme.make (setup, l_info)
end
@@ -109,25 +721,180 @@ feature -- Generation
prepare (page: CMS_HTML_PAGE)
do
+ -- Menu
+ add_to_primary_menu (create {CMS_LOCAL_LINK}.make ("Home", "/"))
+ call_menu_alter_hooks (menu_system)
+ prepare_menu_system (menu_system)
+
+ -- Blocks
+ get_blocks
+ across
+ regions as reg_ic
+ loop
+ across
+ reg_ic.item.blocks as ic
+ loop
+ if attached {CMS_MENU_BLOCK} ic.item as l_menu_block then
+ recursive_get_active (l_menu_block.menu, request)
+ end
+ end
+ end
+
+ -- Values
common_prepare (page)
custom_prepare (page)
- end
- common_prepare (page: CMS_HTML_PAGE)
- do
- fixme ("Fix generacion common")
- page.register_variable (request.absolute_script_url (""), "host")
- page.register_variable (setup.is_web, "web")
- page.register_variable (setup.is_html, "html")
- if attached current_user_name (request) as l_user then
- page.register_variable (l_user, "user")
+ -- Cms values
+ call_value_alter_hooks (values)
+
+ -- Predefined values
+ page.register_variable (page, "page") -- DO NOT REMOVE
+
+ -- Values Associated with current Execution object.
+ across
+ values as ic
+ loop
+ page.register_variable (ic.item, ic.key)
+ end
+
+ -- Block rendering
+ across
+ regions as reg_ic
+ loop
+ across
+ reg_ic.item.blocks as ic
+ loop
+ page.add_to_region (theme.block_html (ic.item), reg_ic.item.name)
+ end
+ end
+
+ -- Additional lines in
+ if attached additional_page_head_lines as l_head_lines then
+ across
+ l_head_lines as hl
+ loop
+ page.head_lines.force (hl.item)
+ end
end
end
+ common_prepare (page: CMS_HTML_PAGE)
+ -- Common preparation for page `page'.
+ do
+ fixme ("Fix generation common")
+
+ -- Information
+ page.set_title (title)
+ debug ("cms")
+ if title = Void then
+ page.set_title ("CMS::" + request.path_info) --| FIXME: probably, should be removed and handled by theme.
+ end
+ end
+
+ -- Variables
+ page.register_variable (request.absolute_script_url (""), "site_url")
+ page.register_variable (request.absolute_script_url (""), "host") -- Same as `site_url'.
+ if attached current_user_name (request) as l_user then
+ page.register_variable (l_user, "user")
+ end
+ page.register_variable (title, "site_title")
+ page.set_is_front (is_front)
+
+ -- Variables/Setup
+ page.register_variable (setup.is_web, "web")
+ page.register_variable (setup.is_html, "html")
+
+ -- Variables/Misc
+
+-- FIXME: logo .. could be a settings of theme, managed by admin front-end/database.
+-- if attached logo_location as l_logo then
+-- page.register_variable (l_logo, "logo")
+-- end
+
+ -- Menu...
+ page.register_variable (horizontal_primary_menu_html, "primary_nav")
+ end
+
custom_prepare (page: CMS_HTML_PAGE)
+ -- Common preparation for page `page' that can be redefined by descendants.
do
end
+ prepare_menu_system (a_menu_system: CMS_MENU_SYSTEM)
+ do
+ across
+ a_menu_system as c
+ loop
+ prepare_links (c.item)
+ end
+ end
+
+ prepare_links (a_menu: CMS_LINK_COMPOSITE)
+ local
+ to_remove: ARRAYED_LIST [CMS_LINK]
+ do
+ create to_remove.make (0)
+ across
+ a_menu as c
+ loop
+ if attached {CMS_LOCAL_LINK} c.item as lm then
+-- if attached lm.permission_arguments as perms and then not has_permissions (perms) then
+-- to_remove.force (lm)
+-- else
+ -- if lm.permission_arguments is Void , this is permitted
+ get_local_link_active_status (lm)
+ if attached {CMS_LINK_COMPOSITE} lm as comp then
+ prepare_links (comp)
+ end
+-- end
+ elseif attached {CMS_LINK_COMPOSITE} c.item as comp then
+ prepare_links (comp)
+ end
+ end
+ across
+ to_remove as c
+ loop
+ a_menu.remove (c.item)
+ end
+ end
+
+ recursive_get_active (a_comp: CMS_LINK_COMPOSITE; req: WSF_REQUEST)
+ -- Update the active status recursively on `a_comp'.
+ local
+ ln: CMS_LINK
+ do
+ if attached a_comp.items as l_items then
+ across
+ l_items as ic
+ loop
+ ln := ic.item
+ if attached {CMS_LOCAL_LINK} ln as l_local then
+ get_local_link_active_status (l_local)
+ end
+ if (ln.is_expanded or ln.is_collapsed) and then attached {CMS_LINK_COMPOSITE} ln as l_comp then
+ recursive_get_active (l_comp, req)
+ end
+ end
+ end
+ end
+
+ get_local_link_active_status (a_lnk: CMS_LOCAL_LINK)
+ -- Get `a_lnk.is_active' value according to `request' data.
+ local
+ qs: STRING
+ l_is_active: BOOLEAN
+ do
+ create qs.make_from_string (request.percent_encoded_path_info)
+ l_is_active := qs.same_string (a_lnk.location)
+ if not l_is_active then
+ if attached request.query_string as l_query_string and then not l_query_string.is_empty then
+ qs.append_character ('?')
+ qs.append (l_query_string)
+ end
+ l_is_active := qs.same_string (a_lnk.location)
+ end
+ a_lnk.set_is_active (l_is_active)
+ end
feature -- Custom Variables
diff --git a/cms/src/service/response/error_500_cms_response.e b/cms/src/service/response/error_500_cms_response.e
index 24c908e..7bfea99 100644
--- a/cms/src/service/response/error_500_cms_response.e
+++ b/cms/src/service/response/error_500_cms_response.e
@@ -21,8 +21,8 @@ feature -- Generation
custom_prepare (page: CMS_HTML_PAGE)
do
page.register_variable (request.absolute_script_url (request.path_info), "request")
- page.register_variable ("500", "code")
- page.set_status_code (500)
+ page.set_status_code ({HTTP_STATUS_CODE}.internal_server_error)
+ page.register_variable (page.status_code.out, "code")
end
feature -- Execution
diff --git a/cms/src/service/response/home_cms_response.e b/cms/src/service/response/home_cms_response.e
index cf51ad9..78e9347 100644
--- a/cms/src/service/response/home_cms_response.e
+++ b/cms/src/service/response/home_cms_response.e
@@ -21,7 +21,7 @@ feature -- Generation
custom_prepare (page: CMS_HTML_PAGE)
do
Precursor (page)
- page.register_variable (setup.api_service.recent_nodes (0, 5), "nodes")
+ page.register_variable (api.recent_nodes (0, 5), "nodes")
end
feature -- Execution
@@ -29,7 +29,7 @@ feature -- Execution
process
-- Computed response message.
do
- set_title ("Home")
+ set_title (Void)
set_page_title (Void)
end
end
diff --git a/cms/src/service/response/not_implemented_error_cms_response.e b/cms/src/service/response/not_implemented_error_cms_response.e
new file mode 100644
index 0000000..2d37558
--- /dev/null
+++ b/cms/src/service/response/not_implemented_error_cms_response.e
@@ -0,0 +1,37 @@
+note
+ description: "Summary description for {NOT_IMPLEMENTED_ERROR_CMS_RESPONSE}."
+ date: "$Date$"
+ revision: "$Revision$"
+
+class
+ NOT_IMPLEMENTED_ERROR_CMS_RESPONSE
+
+inherit
+
+ CMS_RESPONSE
+ redefine
+ custom_prepare
+ end
+
+create
+ make
+
+feature -- Generation
+
+ custom_prepare (page: CMS_HTML_PAGE)
+ do
+ page.register_variable (request.absolute_script_url (request.path_info), "request")
+ page.register_variable ("501", "code")
+ page.set_status_code (501)
+ end
+
+feature -- Execution
+
+ process
+ -- Computed response message.
+ do
+ set_title ("Not Implemented")
+ set_page_title (Void)
+ end
+end
+
diff --git a/cms/src/theme/cms_html_page.e b/cms/src/theme/cms_html_page.e
index 5c6a5c0..3b06281 100644
--- a/cms/src/theme/cms_html_page.e
+++ b/cms/src/theme/cms_html_page.e
@@ -1,7 +1,8 @@
note
description: "Summary description for {CMS_HTML_PAGE}."
- date: "$Date$"
- revision: "$Revision$"
+ author: ""
+ date: "$Date: 2014-11-04 09:57:24 -0300 (ma. 04 de nov. de 2014) $"
+ revision: "$Revision: 96034 $"
class
CMS_HTML_PAGE
@@ -23,6 +24,7 @@ feature {NONE} -- Initialization
do
create regions.make (5)
language := "en"
+
status_code := {HTTP_STATUS_CODE}.ok
create header.make
create {ARRAYED_LIST [STRING]} head_lines.make (5)
@@ -36,7 +38,9 @@ feature -- Access
-- Optional page type.
-- such as "front", "about", ... that could be customized by themes.
- title: detachable STRING
+ is_front: BOOLEAN
+
+ title: detachable READABLE_STRING_32
language: STRING
@@ -57,6 +61,7 @@ feature -- Access
feature -- Status
+
status_code: INTEGER
feature -- Header
@@ -65,7 +70,7 @@ feature -- Header
feature -- Region
- regions: HASH_TABLE [STRING_8, STRING_8]
+ regions: STRING_TABLE [STRING_8]
-- header
-- content
-- footer
@@ -83,23 +88,14 @@ feature -- Region
end
end
- header_region: STRING_8
- do
- Result := region ("header")
- end
-
- content_region: STRING_8
- do
- Result := region ("content")
- end
-
- footer_region: STRING_8
- do
- Result := region ("content")
- end
-
feature -- Element change
+ set_is_front (b: BOOLEAN)
+ -- Set `is_front' to `b'.
+ do
+ is_front := b
+ end
+
register_variable (a_value: detachable ANY; k: READABLE_STRING_GENERAL)
do
variables.force (a_value, k)
@@ -118,41 +114,11 @@ feature -- Element change
end
end
- add_to_header_region (s: STRING)
- do
- add_to_region (s, "header")
- end
-
- add_to_content_region (s: STRING)
- do
- add_to_region (s, "content")
- end
-
- add_to_footer_region (s: STRING)
- do
- add_to_region (s, "footer")
- end
-
set_region (s: STRING; k: STRING)
do
regions.force (s, k)
end
- set_header_region (s: STRING)
- do
- set_region (s, "header")
- end
-
- set_content_region (s: STRING)
- do
- set_region (s, "content")
- end
-
- set_footer_region (s: STRING)
- do
- set_region (s, "footer")
- end
-
feature -- Element change
set_status_code (c: like status_code)
@@ -170,6 +136,50 @@ feature -- Element change
title := s
end
+ add_meta_name_content (a_name: STRING; a_content: STRING)
+ local
+ s: STRING_8
+ do
+ s := ""
+ head_lines.extend (s)
+ end
+
+ add_meta_http_equiv (a_http_equiv: STRING; a_content: STRING)
+ local
+ s: STRING_8
+ do
+ s := ""
+ head_lines.extend (s)
+ end
+
+ add_style (a_href: STRING; a_media: detachable STRING)
+ local
+ s: STRING_8
+ do
+ s := "")
+ head_lines.extend (s)
+ end
+
+ add_javascript_url (a_src: STRING)
+ local
+ s: STRING_8
+ do
+ s := ""
+ head_lines.extend (s)
+ end
+
+ add_javascript_content (a_script: STRING)
+ local
+ s: STRING_8
+ do
+ s := ""
+ head_lines.extend (s)
+ end
+
note
copyright: "2011-2014, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
diff --git a/cms/src/theme/cms_theme.e b/cms/src/theme/cms_theme.e
index 4557a61..6066077 100644
--- a/cms/src/theme/cms_theme.e
+++ b/cms/src/theme/cms_theme.e
@@ -1,12 +1,17 @@
note
description: "Summary description for {WSF_CMS_THEME}."
- author: ""
date: "$Date$"
revision: "$Revision$"
deferred class
CMS_THEME
+inherit
+ CMS_ENCODERS
+
+ REFACTORING_HELPER
+
+
feature {NONE} -- Access
setup: CMS_SETUP
@@ -14,19 +19,63 @@ feature {NONE} -- Access
feature -- Access
name: STRING
+ -- theme name.
deferred
end
regions: ARRAY [STRING]
+ -- theme's regions.
deferred
end
page_template: CMS_TEMPLATE
+ -- theme template page.
deferred
end
feature -- Conversion
+ menu_html (a_menu: CMS_MENU; is_horizontal: BOOLEAN): STRING_8
+ do
+ fixme ("Refactor HTML code to use the new Bootstrap theme template")
+ create Result.make_from_string ("
")
+ if is_horizontal then
+ Result.append ("
%N")
+ else
+ Result.append ("
%N")
+ end
+ across
+ a_menu as c
+ loop
+ append_cms_link_to (c.item, Result)
+ end
+ Result.append ("
%N")
+ Result.append ("
")
+ end
+
+ block_html (a_block: CMS_BLOCK): STRING_8
+ local
+ s: STRING
+ do
+ fixme ("Refactor HTML code to use the new Bootstrap theme template")
+ if attached {CMS_CONTENT_BLOCK} a_block as l_content_block and then l_content_block.is_raw then
+ create s.make_empty
+ if attached l_content_block.title as l_title then
+ s.append ("
")
+ end
+ Result := s
+ end
page_html (page: CMS_HTML_PAGE): STRING_8
-- Render `page' as html.
deferred
@@ -34,6 +83,41 @@ feature -- Conversion
feature {NONE} -- Implementation
+ append_cms_link_to (lnk: CMS_LINK; s: STRING_8)
+ local
+ cl: STRING
+ do
+ fixme ("Remove HTML from Eiffel")
+ create cl.make_empty
+ if lnk.is_active then
+ cl.append ("active ")
+ end
+ if lnk.is_expandable then
+ cl.append ("expandable ")
+ end
+ if lnk.is_expanded then
+ cl.append ("expanded ")
+ end
+ if cl.is_empty then
+ s.append ("
")
+ else
+ s.append ("
")
+ end
+ s.append ("" + html_encoded (lnk.title) + "")
+ if
+ (lnk.is_expanded or lnk.is_collapsed) and then
+ attached lnk.children as l_children
+ then
+ s.append ("
%N")
+ across
+ l_children as c
+ loop
+ append_cms_link_to (c.item, s)
+ end
+ s.append ("
")
+ end
+ s.append ("
")
+ end
note
copyright: "2011-2014, Jocelyn Fiat, Eiffel Software and others"
diff --git a/cms/src/theme/cms_theme_information.e b/cms/src/theme/cms_theme_information.e
index ee0800a..719b3c1 100644
--- a/cms/src/theme/cms_theme_information.e
+++ b/cms/src/theme/cms_theme_information.e
@@ -18,7 +18,7 @@ feature {NONE} -- Initialization
create items.make_caseless (1)
create regions.make (5)
across
- (<<"header", "content", "footer", "first_sidebar", "second_sidebar">>) as ic
+ (<<"top","header", "highlighted","help", "content", "footer", "first_sidebar", "second_sidebar", "bottom">>) as ic
loop
regions.force (ic.item, ic.item)
end
diff --git a/cms/src/theme/default_theme/default_cms_theme.e b/cms/src/theme/default_theme/default_cms_theme.e
index dcf4950..5cc4189 100644
--- a/cms/src/theme/default_theme/default_cms_theme.e
+++ b/cms/src/theme/default_theme/default_cms_theme.e
@@ -60,7 +60,6 @@ feature -- Conversion
prepare (page: CMS_HTML_PAGE)
do
--- page.add_style (url ("/theme/style.css", Void), Void)
end
page_html (page: CMS_HTML_PAGE): STRING_8
@@ -75,6 +74,11 @@ feature -- Conversion
Result := html_template.to_html (page)
end
+ navigation_template: detachable READABLE_STRING_GENERAL
+ -- navigation template name, if any.
+ do
+ end
+
feature {NONE} -- Internal
internal_page_template: detachable like page_template
diff --git a/cms/src/theme/smarty_theme/smarty_cms_html_page_inspector.e b/cms/src/theme/smarty_theme/smarty_cms_html_page_inspector.e
new file mode 100644
index 0000000..cbe3c4a
--- /dev/null
+++ b/cms/src/theme/smarty_theme/smarty_cms_html_page_inspector.e
@@ -0,0 +1,60 @@
+note
+ description: "Summary description for {SMARTY_CMS_HTML_PAGE_INSPECTOR}."
+ author: ""
+ date: "$Date: 2014-11-07 04:58:41 -0300 (vi. 07 de nov. de 2014) $"
+ revision: "$Revision: 96042 $"
+
+class
+ SMARTY_CMS_HTML_PAGE_INSPECTOR
+
+inherit
+ TEMPLATE_INSPECTOR
+ redefine
+ internal_data
+ end
+
+ CMS_ENCODERS
+
+create
+ register
+
+feature {TEMPLATE_ROUTINES}
+
+ internal_data (field_name: STRING; obj: detachable ANY): detachable CELL [detachable ANY]
+ -- Return object in a cell
+ -- If not handled by this inspector, return Void
+ local
+ l_fn: STRING
+ do
+ if attached {CMS_HTML_PAGE} obj as l_page then
+ l_fn := field_name.as_lower
+ if attached l_page.variables.item (l_fn) as v then
+ Result := cell_of (v)
+ elseif l_fn.is_case_insensitive_equal ("title") then
+ if attached l_page.title as l_title then
+ Result := cell_of (html_encoded (l_title))
+ else
+ Result := cell_of (Void)
+ end
+ elseif l_fn.is_case_insensitive_equal ("is_front") then
+ Result := cell_of (l_page.is_front)
+ elseif l_fn.starts_with_general ("region_") then
+ l_fn.remove_head (7) -- remove "region_"
+ Result := cell_of (l_page.region (l_fn))
+ elseif l_fn.is_case_insensitive_equal ("regions") then
+ Result := cell_of (l_page.regions)
+ end
+ end
+ end
+
+note
+ copyright: "2011-2014, Jocelyn Fiat, Eiffel Software and others"
+ license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
+ source: "[
+ Eiffel Software
+ 5949 Hollister Ave., Goleta, CA 93117 USA
+ Telephone 805-685-1006, Fax 805-685-6869
+ Website http://www.eiffel.com
+ Customer support http://support.eiffel.com
+ ]"
+end
diff --git a/cms/src/theme/smarty_theme/smarty_cms_page_template.e b/cms/src/theme/smarty_theme/smarty_cms_page_template.e
index b02fe15..d5b45ab 100644
--- a/cms/src/theme/smarty_theme/smarty_cms_page_template.e
+++ b/cms/src/theme/smarty_theme/smarty_cms_page_template.e
@@ -9,6 +9,8 @@ class
inherit
CMS_PAGE_TEMPLATE
+ CMS_ENCODERS
+
SHARED_TEMPLATE_CONTEXT
create
@@ -41,12 +43,13 @@ feature -- Access
variables.force (ic.item, ic.key)
end
+ -- FIXME: review variables !
if attached page.title as l_title then
- variables.force (l_title, "page_title")
- variables.force (l_title, "head_title")
+ variables.force (html_encoded (l_title), "head_title")
+ variables.force (html_encoded (l_title), "page_title")
else
+ variables.force ("CMS", "head_title")
variables.force ("", "page_title")
- variables.force ("", "head_title")
end
variables.force (page.language, "language")
@@ -55,7 +58,7 @@ feature -- Access
across
theme.regions as r
loop
- variables.force (page.region (r.item), r.item)
+ variables.force (page.region (r.item), "region_" + r.item)
end
end
diff --git a/cms/src/theme/smarty_theme/smarty_cms_regions_inspector.e b/cms/src/theme/smarty_theme/smarty_cms_regions_inspector.e
new file mode 100644
index 0000000..6325103
--- /dev/null
+++ b/cms/src/theme/smarty_theme/smarty_cms_regions_inspector.e
@@ -0,0 +1,47 @@
+note
+ description: "Summary description for {SMARTY_CMS_REGIONS_INSPECTOR}."
+ author: ""
+ date: "$Date: 2014-11-06 17:59:12 -0300 (ju. 06 de nov. de 2014) $"
+ revision: "$Revision: 96040 $"
+
+class
+ SMARTY_CMS_REGIONS_INSPECTOR
+
+inherit
+ TEMPLATE_INSPECTOR
+ redefine
+ internal_data
+ end
+
+create
+ register
+
+feature {TEMPLATE_ROUTINES}
+
+ internal_data (field_name: STRING; obj: detachable ANY): detachable CELL [detachable ANY]
+ -- Return object in a cell
+ -- If not handled by this inspector, return Void
+ local
+ l_fn: STRING
+ do
+ if attached {like {CMS_RESPONSE}.regions} obj as l_regions then
+ l_fn := field_name.as_lower
+ if l_fn.is_case_insensitive_equal ("count") then
+ Result := cell_of (l_regions.count)
+ elseif l_regions.has (l_fn) then
+ Result := cell_of (l_regions.item (l_fn))
+ end
+ end
+ end
+
+note
+ copyright: "2011-2014, Jocelyn Fiat, Eiffel Software and others"
+ license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
+ source: "[
+ Eiffel Software
+ 5949 Hollister Ave., Goleta, CA 93117 USA
+ Telephone 805-685-1006, Fax 805-685-6869
+ Website http://www.eiffel.com
+ Customer support http://support.eiffel.com
+ ]"
+end
diff --git a/cms/src/theme/smarty_theme/smarty_cms_theme.e b/cms/src/theme/smarty_theme/smarty_cms_theme.e
index 2b2e6a4..c69aeb0 100644
--- a/cms/src/theme/smarty_theme/smarty_cms_theme.e
+++ b/cms/src/theme/smarty_theme/smarty_cms_theme.e
@@ -15,11 +15,10 @@ create
feature {NONE} -- Initialization
- make (a_setup: like setup; a_info: like information; a_template: like template)
+ make (a_setup: like setup; a_info: like information;)
do
setup := a_setup
information := a_info
- template := a_template
if attached a_info.item ("template_dir") as s then
templates_directory := a_setup.theme_location.extended (s)
else
@@ -28,15 +27,12 @@ feature {NONE} -- Initialization
ensure
setup_set: setup = a_setup
information_set: information = a_info
- template_set: template = a_template
end
feature -- Access
name: STRING = "smarty-CMS"
- template: STRING;
-
templates_directory: PATH
information: CMS_THEME_INFORMATION
@@ -59,7 +55,7 @@ feature -- Access
i := i + 1
end
else
- l_regions := <<"header", "content", "footer", "first_sidebar", "second_sidebar">>
+ l_regions := <<"top","header", "content", "footer", "first_sidebar", "second_sidebar","bottom">>
end
internaL_regions := l_regions
end
@@ -72,7 +68,7 @@ feature -- Access
do
tpl := internal_page_template
if tpl = Void then
- create tpl.make (template, Current)
+ create tpl.make ("page", Current)
internal_page_template := tpl
end
Result := tpl
@@ -82,13 +78,42 @@ feature -- Conversion
prepare (page: CMS_HTML_PAGE)
do
+ page.register_variable (page, "page")
+ page.register_variable (page.regions, "regions")
+ across
+ page.regions as ic
+ loop
+ page.register_variable (ic.item, "region_" + ic.key)
+ end
end
page_html (page: CMS_HTML_PAGE): STRING_8
+ local
+ l_page_inspector: detachable SMARTY_CMS_HTML_PAGE_INSPECTOR
+ l_regions_inspector: detachable SMARTY_CMS_REGIONS_INSPECTOR
+ l_table_inspector: detachable STRING_TABLE_OF_STRING_INSPECTOR
do
prepare (page)
+ create l_page_inspector.register (page.generating_type)
+
+ if attached {CMS_RESPONSE} page.variables.item ("cms") as l_cms then
+ if attached l_cms.regions as l_regions then
+ create l_regions_inspector.register (l_regions.generating_type)
+ end
+ end
+
+ create l_table_inspector.register (({detachable STRING_TABLE [STRING]}).name)
page_template.prepare (page)
Result := page_template.to_html (page)
+
+ -- Clean template inspector.
+ if l_regions_inspector /= Void then
+ l_regions_inspector.unregister
+ end
+ if l_page_inspector /= Void then
+ l_page_inspector.unregister
+ end
+ l_table_inspector.unregister
end
feature {NONE} -- Internal
diff --git a/cms/src/theme/smarty_theme/string_table_of_string_inspector.e b/cms/src/theme/smarty_theme/string_table_of_string_inspector.e
new file mode 100644
index 0000000..4a61134
--- /dev/null
+++ b/cms/src/theme/smarty_theme/string_table_of_string_inspector.e
@@ -0,0 +1,47 @@
+note
+ description: "Summary description for {STRING_TABLE_OF_STRING_INSPECTOR}."
+ author: ""
+ date: "$Date: 2014-11-06 17:59:12 -0300 (ju. 06 de nov. de 2014) $"
+ revision: "$Revision: 96040 $"
+
+class
+ STRING_TABLE_OF_STRING_INSPECTOR
+
+inherit
+ TEMPLATE_INSPECTOR
+ redefine
+ internal_data
+ end
+
+create
+ register
+
+feature {TEMPLATE_ROUTINES}
+
+ internal_data (field_name: STRING; obj: detachable ANY): detachable CELL [detachable ANY]
+ -- Return object in a cell
+ -- If not handled by this inspector, return Void
+ local
+ l_fn: STRING
+ do
+ if attached {STRING_TABLE [STRING]} obj as l_regions then
+ l_fn := field_name.as_lower
+ if l_fn.is_case_insensitive_equal ("count") then
+ Result := cell_of (l_regions.count)
+ elseif attached l_regions.item (l_fn) as v then
+ Result := cell_of (v)
+ end
+ end
+ end
+
+note
+ copyright: "2011-2014, Jocelyn Fiat, Eiffel Software and others"
+ license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
+ source: "[
+ Eiffel Software
+ 5949 Hollister Ave., Goleta, CA 93117 USA
+ Telephone 805-685-1006, Fax 805-685-6869
+ Website http://www.eiffel.com
+ Customer support http://support.eiffel.com
+ ]"
+end
diff --git a/examples/api/roc_api.ecf b/examples/api/roc_api.ecf
index a68d4e1..02794df 100644
--- a/examples/api/roc_api.ecf
+++ b/examples/api/roc_api.ecf
@@ -22,6 +22,7 @@
+
diff --git a/examples/roc_api/modules/demo/cms_demo_module-safe.ecf b/examples/roc_api/modules/demo/cms_demo_module-safe.ecf
index dd678f2..a954561 100644
--- a/examples/roc_api/modules/demo/cms_demo_module-safe.ecf
+++ b/examples/roc_api/modules/demo/cms_demo_module-safe.ecf
@@ -12,6 +12,7 @@
+
diff --git a/examples/roc_api/modules/demo/cms_demo_module.e b/examples/roc_api/modules/demo/cms_demo_module.e
index aeabe7b..879a064 100644
--- a/examples/roc_api/modules/demo/cms_demo_module.e
+++ b/examples/roc_api/modules/demo/cms_demo_module.e
@@ -9,45 +9,91 @@ class
inherit
CMS_MODULE
+ redefine
+ register_hooks
+ end
+
+ CMS_HOOK_MENU_ALTER
+
+ CMS_HOOK_BLOCK
create
make
feature {NONE} -- Initialization
- make (a_config: CMS_SETUP)
+ make
do
name := "Demo module"
version := "1.0"
description := "Service to demonstrate and test cms system"
package := "demo"
- config := a_config
end
- config: CMS_SETUP
- -- Node configuration.
-
feature -- Access: router
- router: WSF_ROUTER
+ router (a_api: CMS_API): WSF_ROUTER
-- Node router.
do
create Result.make (2)
- map_uri_template_agent (Result, "/demo/", agent handle_demo)
- map_uri_template_agent (Result, "/book/{id}", agent handle_demo_entry)
+ map_uri_template_agent (Result, "/demo/", agent handle_demo (?,?,a_api))
+ map_uri_template_agent (Result, "/demo/{id}", agent handle_demo_entry (?,?,a_api))
+ end
+
+feature -- Hooks
+
+ register_hooks (a_response: CMS_RESPONSE)
+ do
+ a_response.add_menu_alter_hook (Current)
+ a_response.add_block_hook (Current)
+ end
+
+ block_list: ITERABLE [like {CMS_BLOCK}.name]
+ do
+ Result := <<"demo-info">>
+ end
+
+ get_block_view (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE)
+ local
+ b: CMS_CONTENT_BLOCK
+ mb: CMS_MENU_BLOCK
+ m: CMS_MENU
+ lnk: CMS_LOCAL_LINK
+ do
+ if a_block_id.is_case_insensitive_equal_general ("demo-info") then
+ if a_response.request.request_uri.starts_with ("/demo/") then
+ create m.make_with_title (a_block_id, "Demo", 2)
+ create lnk.make ("/demo/abc", a_response.url ("/demo/abc", Void))
+ m.extend (lnk)
+ create lnk.make ("/demo/123", a_response.url ("/demo/123", Void))
+ m.extend (lnk)
+ create mb.make (m)
+ a_response.add_block (mb, "sidebar_second")
+ end
+ end
+ end
+
+ menu_alter (a_menu_system: CMS_MENU_SYSTEM; a_response: CMS_RESPONSE)
+ local
+ lnk: CMS_LOCAL_LINK
+-- perms: detachable ARRAYED_LIST [READABLE_STRING_8]
+ do
+ create lnk.make ("Demo", "/demo/")
+ a_menu_system.primary_menu.extend (lnk)
end
feature -- Handler
handle_demo,
- handle_demo_entry (req: WSF_REQUEST; res: WSF_RESPONSE)
+ handle_demo_entry (req: WSF_REQUEST; res: WSF_RESPONSE; a_api: CMS_API)
local
- m: WSF_NOT_FOUND_RESPONSE
+ r: NOT_IMPLEMENTED_ERROR_CMS_RESPONSE
do
- create m.make (req)
- m.set_body ("Not yet implemented!")
- res.send (m)
+ create r.make (req, res, a_api)
+ r.set_main_content ("NODE module does not yet implement %"" + req.path_info + "%" ...")
+ r.add_error_message ("NODE Module: not yet implemented")
+ r.execute
end
feature -- Mapping helper: uri template
diff --git a/examples/roc_api/site/config/application_configuration.json b/examples/roc_api/site/config/application_configuration.json
index d493ed8..793f8ef 100644
--- a/examples/roc_api/site/config/application_configuration.json
+++ b/examples/roc_api/site/config/application_configuration.json
@@ -24,7 +24,7 @@
"backup_count":"4"
},
"server": {
- "mode":"api"
+ "mode":"html"
}
}
diff --git a/examples/roc_api/site/config/cms.ini b/examples/roc_api/site/config/cms.ini
index 27ebf1f..05a3774 100644
--- a/examples/roc_api/site/config/cms.ini
+++ b/examples/roc_api/site/config/cms.ini
@@ -3,4 +3,4 @@ site.name=EWF Web CMS
site.email=your@email.com
var-dir=var
files-dir=files
-theme=api
+theme=bootstrap
diff --git a/examples/roc_api/site/www/template/html/master2/content.tpl b/examples/roc_api/site/www/template/html/master2/content.tpl
deleted file mode 100644
index b18c5dd..0000000
--- a/examples/roc_api/site/www/template/html/master2/content.tpl
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum.
+
+
Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.
Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum.
+
+
Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.
+
+
+
+
+
+
+
+
+
diff --git a/examples/roc_api/site/www/themes/bootstrap/theme.info b/examples/roc_api/site/www/themes/bootstrap/theme.info
new file mode 100644
index 0000000..b084985
--- /dev/null
+++ b/examples/roc_api/site/www/themes/bootstrap/theme.info
@@ -0,0 +1,14 @@
+name=bootstrap
+engine=smarty
+author=jvelilla
+version=0.1
+regions[page_top] = Top
+regions[header] = Header
+regions[content] = Content
+regions[highlighted] = Highlighted
+regions[help] = Help
+regions[footer] = Footer
+regions[first_sidebar] = first sidebar
+regions[second_sidebar] = second sidebar
+regions[page_bottom] = Bottom
+navigation=default_nav
\ No newline at end of file
diff --git a/examples/roc_api/site/www/themes/bootstrap/tpl/help_section.tpl b/examples/roc_api/site/www/themes/bootstrap/tpl/help_section.tpl
new file mode 100644
index 0000000..b20cb47
--- /dev/null
+++ b/examples/roc_api/site/www/themes/bootstrap/tpl/help_section.tpl
@@ -0,0 +1 @@
+
Help Section
\ No newline at end of file
diff --git a/examples/roc_api/site/www/themes/bootstrap/tpl/highlighted_section.tpl b/examples/roc_api/site/www/themes/bootstrap/tpl/highlighted_section.tpl
new file mode 100644
index 0000000..fc75c0c
--- /dev/null
+++ b/examples/roc_api/site/www/themes/bootstrap/tpl/highlighted_section.tpl
@@ -0,0 +1 @@
+
Highlighted Section
diff --git a/examples/roc_api/site/www/themes/bootstrap/tpl/left_sidebar.tpl b/examples/roc_api/site/www/themes/bootstrap/tpl/left_sidebar.tpl
new file mode 100644
index 0000000..ee2ee4c
--- /dev/null
+++ b/examples/roc_api/site/www/themes/bootstrap/tpl/left_sidebar.tpl
@@ -0,0 +1,8 @@
+
diff --git a/examples/roc_api/site/www/themes/bootstrap/tpl/main_content.tpl b/examples/roc_api/site/www/themes/bootstrap/tpl/main_content.tpl
new file mode 100644
index 0000000..0df8def
--- /dev/null
+++ b/examples/roc_api/site/www/themes/bootstrap/tpl/main_content.tpl
@@ -0,0 +1,4 @@
+
Main Content Section
+
Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum.
+
+
Typi non habent claritatem insitam; est usus legentis in iis qui facit eorum claritatem. Investigationes demonstraverunt lectores legere me lius quod ii legunt saepius. Claritas est etiam processus dynamicus, qui sequitur mutationem consuetudium lectorum. Mirum est notare quam littera gothica, quam nunc putamus parum claram, anteposuerit litterarum formas humanitatis per seacula quarta decima et quinta decima. Eodem modo typi, qui nunc nobis videntur parum clari, fiant sollemnes in futurum.
\ No newline at end of file
diff --git a/examples/roc_api/site/www/themes/bootstrap/tpl/page_bottom.tpl b/examples/roc_api/site/www/themes/bootstrap/tpl/page_bottom.tpl
new file mode 100644
index 0000000..e69de29
diff --git a/examples/roc_api/site/www/themes/bootstrap/tpl/page_footer.tpl b/examples/roc_api/site/www/themes/bootstrap/tpl/page_footer.tpl
new file mode 100644
index 0000000..9c7ee8e
--- /dev/null
+++ b/examples/roc_api/site/www/themes/bootstrap/tpl/page_footer.tpl
@@ -0,0 +1,9 @@
+
\ No newline at end of file
diff --git a/examples/roc_api/site/www/themes/bootstrap/tpl/page_header.tpl b/examples/roc_api/site/www/themes/bootstrap/tpl/page_header.tpl
new file mode 100644
index 0000000..db83655
--- /dev/null
+++ b/examples/roc_api/site/www/themes/bootstrap/tpl/page_header.tpl
@@ -0,0 +1,34 @@
+
+{/if}
\ No newline at end of file
diff --git a/examples/roc_api/site/www/themes/bootstrap/tpl/page_top.tpl b/examples/roc_api/site/www/themes/bootstrap/tpl/page_top.tpl
new file mode 100644
index 0000000..e69de29
diff --git a/examples/roc_api/site/www/themes/bootstrap/tpl/primary_nav.tpl b/examples/roc_api/site/www/themes/bootstrap/tpl/primary_nav.tpl
new file mode 100644
index 0000000..221563a
--- /dev/null
+++ b/examples/roc_api/site/www/themes/bootstrap/tpl/primary_nav.tpl
@@ -0,0 +1,6 @@
+
\ No newline at end of file
diff --git a/examples/roc_api/site/www/themes/bootstrap/tpl/right_sidebar.tpl b/examples/roc_api/site/www/themes/bootstrap/tpl/right_sidebar.tpl
new file mode 100644
index 0000000..b0f6904
--- /dev/null
+++ b/examples/roc_api/site/www/themes/bootstrap/tpl/right_sidebar.tpl
@@ -0,0 +1,8 @@
+
\ No newline at end of file
diff --git a/examples/roc_api/site/www/themes/bootstrap/tpl/secondary_nav.tpl b/examples/roc_api/site/www/themes/bootstrap/tpl/secondary_nav.tpl
new file mode 100644
index 0000000..a40739c
--- /dev/null
+++ b/examples/roc_api/site/www/themes/bootstrap/tpl/secondary_nav.tpl
@@ -0,0 +1,7 @@
+