Compare commits

..

79 Commits

Author SHA1 Message Date
3fa29340b2 Updated code to follow review comments. 2015-05-12 20:01:14 +02:00
jvelilla
b1988d5fe7 Updated CMS_NODE_API, with status, not_published, published and trashed.
Removed class cms_node_constants.
Updated Form response to use permission scopes.
Updated sqlquery to retrieve user author.
Added logger info in cms_response
2015-05-11 23:51:25 -03:00
jvelilla
e767e1bc47 Updated table node to use status (1:not_published, 2:published, 3:trash )instead of deleted_at to implement soft deletes.
Updated queries to use the new status field.
Updated CMS_NODE with a new status attribute.
2015-05-11 16:38:51 -03:00
jvelilla
c2d0fbf445 Updated table nodes to support soft deletes using the new field
'deleted_at' as Datetime and give us free metadata.
Updated Sqlite builder to test different scenarios for users and roles.
Updated NODE_FORM_RESPONSE.edit_form feature to add a delete operation iff
there is a node ie node id >0 and the current user has delete permission on it.
Updated NODE_HANDLER.do_post to handle the operation "DELETE".
Updated queries to retrieve nodes filter by no logical deleted rows (ie. deleted_at is NULL).
Updated CMS_USER_API.has_permissions. (authenticated_user_role seems to generic).
2015-05-08 18:40:46 -03:00
fdff2bef36 Fixed compilation of autotests suites for sqlite and mysql.
TODO: reintroduce tests for node management.
2015-05-04 23:17:06 +02:00
1603086905 Fixed node editing workflow (especially creation/updating). 2015-04-30 19:46:18 +02:00
99b2fa9fdb Commented line registering the MYSQL storage builder,
since it reguires to setup MYSQL environment variable and so on.
So by default, we use sqlite, easier to run out of the box.
2015-04-30 19:38:17 +02:00
e17011de97 for backward compatibility alias CMS_LAYOUT to CMS_ENVIRONMENT 2015-04-30 10:05:04 +02:00
17fe37aedd Added {CMS_RESPONSE}.formats: CMS_FORMATS 2015-04-30 09:50:47 +02:00
dd3688fab8 Now node and basic_auth modules are standalone cms modules (as .ecf library)
Moved to complete void-safety
Use port 9090 for demo by configuration.
2015-04-29 23:27:36 +02:00
7771a452cf Moved src/modules under modules cluster. 2015-04-29 23:08:45 +02:00
6ff7a6493c Simplify CMS_SERVICE initialization, and CMS server (launcher).
Renamed "layout" lib as "app_env" with APPLICATION_ENVIRONMENT interface.
  applied changed to callers.
Added CMS_THEME.has_region (a_name): BOOLEAN to know if a region is declared in a defined theme.
2015-04-29 23:01:42 +02:00
0eb2b70d0f Cleaned the node module, to remove for now the REST api attempt.
This will be redone with care once the web cms is ready.
2015-04-29 20:02:09 +02:00
c982f0ea9c Implemented view node by content type (no more hardcoded cases).
Added CMS_NODE_TYPE as descendant of CMS_CONTENT_TYPE,
  in case we have content which is not a node in the future.
  (probably useless, but for now, this extra abstraction is harmful)
Moved all node related code under node module cluster.
Applied comments from Javier Velilla.
Code cleaning.
2015-04-29 17:28:33 +02:00
e8bb3790ba Removed unused variables. 2015-04-27 18:50:05 +02:00
e206c1e133 Code cleaning. 2015-04-27 18:48:51 +02:00
5582dd9058 Merge branch 'jvelilla-nodes' into nodes 2015-04-27 18:44:35 +02:00
jvelilla
d54cd6032f Added comments 2015-04-24 17:55:32 -03:00
jvelilla
8b24c86ff1 Updated Authentication JS, still work in progress 2015-04-23 11:43:57 -03:00
jvelilla
fc4c2e76b6 Added login form with Javascript (example).
Updated feature and class comments.
2015-04-22 18:40:36 -03:00
a56338ad17 Added blog module as example, this is far from being a real blog module.
but this is an example about on to add a new content type, and support it.
Fixed new node form workflow.

The current state is not final, it requires many changes, but for now, it implements a node editing workflow.
2015-04-15 22:32:38 +02:00
f2bb061488 Added support for log stored in CMS_STORAGE.
Added support for custom value stored in CMS_STORAGE.
Added optional css classes addition to CMS_BLOCK output.
Refactored storage, to manage node from node module code only (or mostly).

TODO: improved view for a cms node, for now hardcoded.
2015-04-15 16:39:03 +02:00
2b25c23977 Added helper function to CMS_RESPONSE, to deal with permissions. 2015-04-14 16:11:04 +02:00
ea2b5b87d3 Added helper functions to get uri path for a node, and other related resources.
Added description to cms content type.
Fixed initialization of node module to create test bed nodes.
2015-04-14 16:07:09 +02:00
133c243126 Implemented CMS storage for user and nodes.
Implemented role and permission storage.
Introduced the CMS_PARTIAL_NODE and CMS_PARTIAL_USER.
Added support for node storage extension
  - storage of data specific to each node content type,
  - in addition to the core CMS_NODE)
  - For now, only implemented for SQL storage.
Note: in current version, CMS_PAGE support is hard coded in the core,
    (as opposed to be only supported by the node module.)
Commented/removed for now, the Web API code to update node summary, title, via REST request.
2015-04-14 11:25:02 +02:00
Jocelyn Fiat
734f661add Merge pull request #21 from jvelilla/roc_jv_09042015
Added missing descriptions/comments
2015-04-10 10:50:52 +02:00
jvelilla
e41b0631d6 Added missing descriptions 2015-04-09 22:45:37 -03:00
jvelilla
98621cb265 Merge branch 'jocelyn-jfiat' 2015-04-09 21:44:52 -03:00
9a8683a139 Updated configuration of the example to use EiffelStore sqlite database by default. 2015-04-09 23:59:57 +02:00
f3c3407b0a Got rid of CMS_GENERIC_RESPONSE, and replace with CMS_RESPONSE_MESSAGE descendants.
Update node module to use new uri mapping, and cleaned dev purpose code.
2015-04-09 23:59:13 +02:00
20471923fd Fixed the basic auth logout by using the ://foo@hostname... workaround.
Added support for ?destination=... so that login or logout will return to previous visited page.
Revisited the sending of generic response such as access denied, unauthorized, redirection ...
Fixed support of CMS_RESPONSE.header which was  previously ignored.
Added support for CMS_RESPONSE.redirection: detachable READABLE_STRING_8, to allow easy url redirection.
Added CMS_NODE.make_empty
+ Cosmetic.
2015-04-09 23:54:14 +02:00
b235fb30a7 Updated design related to logger, to prepare move to SCOOP concurrency. 2015-04-02 21:15:05 +02:00
e94d860fd8 Commented "mysql" support to make it easier to compile at first. 2015-03-20 19:45:14 +01:00
bd6524ebe7 Fixed issue with ini config component and include functionality.
Added {CMS_SETUP}.cms_config_ini_name to define the CMS Configuration file name,
   and provide an easy way to change the name.
2015-03-09 19:27:30 +01:00
ca10c57b4b Added is_https: BOOLEAN query to CMS (on page, but also as 'is_https' value) 2015-02-16 20:14:45 +01:00
8d59d25ace Added weight into to the CMS_LINK and provide a `sort' feature for CMS_MENU and related.
Protected cms service from registering many time the same module type.
Moved library/persistence/implementation/* under library/persistence/.
Moved site/www/themes to site/themes
For SQLite storage driver, auto create sqlite db file using associated sql script (to be completed).
Added code in demo module to reuse storage for module purpose.
Always call sql_post_execution in sql_query and sql_change, and not anymore by the callers.
Removed is_web and is_html from {CMS_SETUP}, it was not used.
Reused SHARED_*_ENCODER in CMS_ENCODERS
Added CMS_API.logger rather than using directly the SHARED_LOGGER.log ...
Centralize the implementation of current_user in CMS_REQUEST_UTIL
Removed the inheritance on WSF_FILTER for node handlers, since it is useless and unused.
Added CMS_NODE_API and CMS_USER_API
Prefix html id for block generated html items with "block-", to avoid css name conflict on "main", "content" or similar.
Code cleaning
2015-02-16 13:01:06 +01:00
a810b1176c Revisited application layout, shared logger and relation with cms to avoid mixing various layout. 2015-02-05 10:28:46 +01:00
Jocelyn Fiat
e40f8ee4d2 Fixed location of logs folder. 2015-02-03 19:25:38 +01:00
Jocelyn Fiat
83af7f6a38 Fixed shared logger code (there was an issue on non Windows machine)
Now, it is possible to set logs folder from config file.
2015-02-03 19:19:27 +01:00
02368fe3d2 Removed unused local variable.
Updated SHARED_LOGGER to remove a few obsolete calls on json parser.
2015-01-30 19:40:10 +01:00
be0b5c23d2 Added debug output to CMS_BLOCK.
Updated SHARED_LOGGER to remove a few obsolete calls on json parser.
Added favicon.ico specific handling.
Fixed issue with theme and non raw block.
2015-01-30 19:37:12 +01:00
jvelilla
88ec1452d8 Added the new Schema for MySQL 2015-01-29 12:10:01 -03:00
5ddc2006e2 Moved library/src to src 2015-01-27 19:58:13 +01:00
d97c4b1a4a Merge branch 'master' of https://github.com/EiffelWebFramework/ROC 2015-01-27 19:49:49 +01:00
7d5869f3b9 Revisited the persistence layer.
Simplified schema to focus on user and node.
Now possible to have sqlite via ODBC and/or mysql support, and select using configuration file.
Updated demo example.
2015-01-27 19:48:37 +01:00
jvelilla
8c74c7a268 Updated log directory location if the argument `-d' is present. 2015-01-14 20:55:24 -03:00
db9e40cec4 Updated CMS_SERVICE to make the cms library complete void-safe.
Reviewed configuration related feature.
Renamed JSON_CONFIGURATION as APPLICATION_JSON_CONFIGURATION_HELPER to avoid confusion.
Updated CMS_DEFAULT_SETUP to use configuration from cms configuration library.
Added {CMS_API}.module_configuration (a_module_name: READABLE_STRING_GENERAL; a_name: detachable READABLE_STRING_GENERAL): detachable CONFIG_READER  to help getting access to configuration of a module (for now, only json and ini are supported, but in the future, this could support database layer directly)
Added CMS_HOOK_BLOCK_HELPER to reuse the template_block (..): ... function.
Cosmetic
Removed CMS_SETUP.smtp_server since for now, there is no need for such general setting.
Add header line "X-ServerEWF-App: CMS" as a simple way to know if request is processed by the CMS.
2015-01-14 18:25:26 +01:00
Javier Velilla
792880aa7a Update Module implementation 2015-01-02 10:43:17 -03:00
Javier Velilla
5ad8c680a6 Add your own Module 2014-12-31 08:06:54 -03:00
jvelilla
e2f02953f4 Refactor rename error_500_cms_response to internal_server_error_cms_response
Added bad_request_error_cms_response
Updated code example to use the new internal_server_error_cms_response instead of error_500_cms_response class.
Removed class error_500_cms_response.

Updated cms setup and configuration design:
  Removed CMS_SETUP.configuration: CMS_CONFIGURATION
  Removed CMS_CONFIGURATION and replaced it by using the configuration library.
  Added CMS_DEFAULT_SETUP.configuration: CONFIG_READER
  Addec CMS_SETUP.text_item (name): detachable READABLE_STRING_32 ...
    in order to access option not publish by the CMS_SETUP interface.
Removed CMS_SERVICE.configuration: CMS_CONFIGURATION since it was not used.

Moved configuration library from eiffel-lang to cms libraries.
Fixed issue related to ini config when parsing from string content,
  and also issue related to section included in file via @include.
Updated cms setup and configuration design:
  Removed CMS_SETUP.configuration: CMS_CONFIGURATION
  Removed CMS_CONFIGURATION and replaced it by using the configuration library.
  Added CMS_DEFAULT_SETUP.configuration: CONFIG_READER
  Addec CMS_SETUP.text_item (name): detachable READABLE_STRING_32 ...
    in order to access option not publish by the CMS_SETUP interface.
Removed CMS_SERVICE.configuration: CMS_CONFIGURATION since it was not used.
Improved the email service and related.
2014-12-19 18:03:52 -03:00
jvelilla
bd26deb6c1 Updated cms configuration file with an smtp server property.
Updated cms code to use the new property.
Removed title from the home response.
2014-12-17 09:16:19 -03:00
jvelilla
a9109ca8f7 Updated CMS_SMARTY_TEMPALTE_BLOCK, redefined out to be used by the logger.
Updated CMS_API, added wrapper features to access error_handler. has_error, reset, as_string_representation, hide
the actual error hanlder implementation.
Updated Error Filter with better logging.
2014-11-26 13:57:04 -03:00
09e5dc4032 Removed a few obsolete calls related to JSON library.
+ cosmetic
2014-11-20 15:14:34 +01:00
d082326784 Removed useless CMS_CUSTOM_SETUP. 2014-11-20 14:57:19 +01:00
51462829c7 reverted renaming to use `modules' for available modules.
Added CMS_SETUP.register_module (m) to avoid extending directly to the CMS_SETUP.modules
2014-11-20 14:53:54 +01:00
ba58fcdf75 Updated cms library with comments, and removed a few JSON obsolete calls. 2014-11-20 14:11:28 +01:00
Javier Velilla
d84f164dbd Update concepts.md
Updated concepts
2014-11-19 13:20:53 -03:00
jvelilla
c3d022ce46 Refactor raname {CMS_SETUP}.modules as {CMS_SETUP}.available_modules
Refactor raname {CMS_SETUP}.modules_enabled as {CMS_SETUP}.enabled_modules
Updated code to use the new features names.
2014-11-19 13:20:07 -03:00
jvelilla
aac01e093a Added {CMS_SETUP}.modules_enabled: CMS_MODULE_COLLECTION
Updated {CMS_SERVIDE}.intialize_modules to use the new feature {CMS_SETUP}.modules_enabled
Updated cms_hook_block description
2014-11-19 12:13:07 -03:00
jvelilla
fb62a1bb3e Merge branch 'roc_template' of https://github.com/jvelilla/ROC into roc_template 2014-11-19 11:50:56 -03:00
Javier Velilla
6162432d52 Update concepts.md
Updated Concepts table of contents
2014-11-19 11:32:59 -03:00
Javier Velilla
ebed52ae01 Update concepts.md
Updated concepts with Modules and Hooks
2014-11-19 11:16:02 -03:00
b58eeeac26 Added comments. 2014-11-19 13:34:42 +01:00
jvelilla
9169bdcd43 Removed shared_error from CMS_API
Added Missing theme and Missing tempalte classes.
Updated CMS_RESPONSE to handle missing template and send a 503 status code
with a raw response.
2014-11-19 09:22:31 -03:00
jvelilla
e36465f86d Update concepts.md
Added references to the important classes.
2014-11-18 09:26:52 -03:00
76190de218 Fixed non void-safe compilations, and cleaned .ecf files.
+Cosmetic
2014-11-18 10:05:50 +01:00
jvelilla
0edff7853b Removed default_theme.
Update theme and smarty theme description
2014-11-17 22:37:10 -03:00
jvelilla
e20a7af301 Merge pull request #15 from jvelilla/roc_template
Roc template
2014-11-17 13:08:33 -03:00
jvelilla
089b367c95 Update concepts.md
Updated default regions
2014-11-17 13:08:01 -03:00
jvelilla
503f2faf08 Update concepts.md
Updated
2014-11-17 13:03:13 -03:00
jvelilla
b887c13664 Renamed files and added tutorial document 2014-11-17 12:44:37 -03:00
jvelilla
bbfe063b5c Update CMS_concepts.md
Added table of contents
2014-11-17 12:26:58 -03:00
jvelilla
1a4e2935da Update README.md
Update readme file
2014-11-17 12:23:37 -03:00
jvelilla
c3a582f85c Added cms_concepts 2014-11-17 12:10:51 -03:00
8bfb66af30 Added cms_smarty_template_block
Added CMS_RESPONSE.module_assets_location and CMS_RESPONSE.module_assets_theme_location
    that help locating module related assets.
Added CMS_BLOCK.is_raw to abstract CMS_CONTENT_BLOCK.is_raw
2014-11-14 19:31:40 +01:00
6aad460b11 Updated ecf files, and added non void-safe .ecf files. 2014-11-14 14:20:01 +01:00
jvelilla
0dc12b82b8 Merge pull request #14 from jvelilla/roc_template
Update sqlite implemenation to make it compile
2014-11-14 08:26:06 -03:00
jvelilla
8047880c2b Update sqlite implemenation to make it compile 2014-11-13 23:46:02 -03:00
jvelilla
48283742aa Merge pull request #13 from jocelyn/minor_changes_20141113
Renamed {CMS_SETUP} theme_resource_location as theme_assets_location
2014-11-13 15:28:39 -03:00
341 changed files with 13881 additions and 8775 deletions

3
.gitignore vendored
View File

@@ -1,4 +1,5 @@
EIFGENs
*.swp
*.log*
*.rc
*.rc
*.bak

View File

@@ -25,7 +25,10 @@ The goal of the library is to provide the following features.
- doc -- Documentation.
**Documentation**
>[CMS design](https://github.com/EiffelWebFramework/ROC).
>[CMS concepts](https://github.com/EiffelWebFramework/ROC).
>[CMS concepts](/doc/concepts.md).
>[CMS design](/doc/design.md).
>[CMS tutorial](/doc/tutorial.md).

View File

@@ -2,32 +2,30 @@
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="cms" uuid="8CC0D052-57D1-4CAA-AFF1-448FA290734B" library_target="cms">
<target name="cms">
<root all_classes="true"/>
<option warning="true" full_class_checking="false" is_attached_by_default="true" void_safety="transitional" syntax="transitional">
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="false" is_attached_by_default="true" void_safety="all" syntax="transitional">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<mapping old_name="CMS_LAYOUT" new_name="CMS_ENVIRONMENT"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="cms_app_env" location=".\library\app_env\app_env-safe.ecf"/>
<library name="cms_model" location=".\library\model\cms_model-safe.ecf" readonly="false"/>
<library name="config" location=".\library\configuration\config-safe.ecf"/>
<library name="crypto" location="$ISE_LIBRARY\unstable\library\text\encryption\crypto\crypto-safe.ecf"/>
<library name="encoder" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\text\encoder\encoder-safe.ecf" readonly="false"/>
<library name="error" location="$ISE_LIBRARY\contrib\library\utility\general\error\error-safe.ecf"/>
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-safe.ecf"/>
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json-safe.ecf" readonly="false"/>
<library name="layout" location=".\library\layout\layout-safe.ecf"/>
<library name="model" location=".\library\model\cms_model-safe.ecf" readonly="false"/>
<library name="encoder" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\text\encoder\encoder-safe.ecf" readonly="false"/>
<library name="text_filter" location="$ISE_LIBRARY\unstable\library\text\text_filter\text_filter-safe.ecf"/>
<library name="error" location="$ISE_LIBRARY\contrib\library\utility\general\error\error-safe.ecf"/>
<library name="http_authorization" location="$ISE_LIBRARY\contrib\library\network\authentication\http_authorization\http_authorization-safe.ecf" readonly="false"/>
<library name="persistence_mysql" location=".\library\persistence\implementation\mysql\persistence_mysql-safe.ecf" readonly="false"/>
<library name="smarty" location="$ISE_LIBRARY\contrib\library\text\template\smarty\smarty-safe.ecf" readonly="false"/>
<library name="text_filter" location="$ISE_LIBRARY\unstable\library\text\text_filter\text_filter-safe.ecf"/>
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
<library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension-safe.ecf" readonly="false"/>
<library name="wsf_html" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf_html\wsf_html-safe.ecf" readonly="false"/>
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
<cluster name="src" location=".\library\src\" recursive="true">
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
</cluster>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
</system>

31
cms.ecf Normal file
View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="cms" uuid="8CC0D052-57D1-4CAA-AFF1-448FA290734B" library_target="cms">
<target name="cms">
<root all_classes="true"/>
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="false" void_safety="none" syntax="transitional">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<mapping old_name="CMS_LAYOUT" new_name="CMS_ENVIRONMENT"/>
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
<library name="config" location=".\library\configuration\config.ecf"/>
<library name="crypto" location="$ISE_LIBRARY\unstable\library\text\encryption\crypto\crypto.ecf"/>
<library name="encoder" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\text\encoder\encoder.ecf" readonly="false"/>
<library name="error" location="$ISE_LIBRARY\contrib\library\utility\general\error\error.ecf"/>
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http.ecf"/>
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json.ecf" readonly="false"/>
<library name="cms_app_env" location=".\library\app_env\app_env.ecf"/>
<library name="cms_model" location=".\library\model\cms_model.ecf" readonly="false"/>
<library name="smarty" location="$ISE_LIBRARY\contrib\library\text\template\smarty\smarty.ecf" readonly="false"/>
<library name="text_filter" location="$ISE_LIBRARY\unstable\library\text\text_filter\text_filter.ecf"/>
<library name="time" location="$ISE_LIBRARY\library\time\time.ecf"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf.ecf"/>
<library name="wsf_html" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf_html\wsf_html.ecf" readonly="false"/>
<library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension.ecf" readonly="false"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
</system>

View File

93
doc/concepts.md Normal file
View File

@@ -0,0 +1,93 @@
CMS Concepts
============
>Current implemented concepts
##### Table of Contents
1. [**Theme**](#theme)
2. [**Regions**](#regions)
- [**Default Page Layout**](#page_layout)
- [**Regions Holds blocks**](#regions_blocks)
3. [**Blocks**](#blocks)
4. [**Modules**](#modules)
5. [**Hooks**](#hooks)
<a name="theme"/>
Theme
-----
In a CMS , a theme is a collection of templates files (HTML, CSS, Images, etc ) that determine how a CMS web site looks. The goal of a theme is to let you change the look and feel of the site.
Eiffel CMS is inspired by Drupal, and use the same default region names as default drupal theme.
#### Important Classes
* [CMS_THEME] (/library/src/theme/cms_theme.e): Abstraction defining the interface of a CMS theme.
* [SMARTY_CMS_THEME] (/library/src/theme/smarty_theme/smarty_cms_theme.e): Theme implemented using the [Eiffel Smarty library] (https://github.com/eiffelhub/template-smarty).
* [CMS_TEMPLATE] (/library/src/theme/cms_template.e): Template Abstraction that contains theme, variables needed by template when rendering page as html. At the moment there is only one implementation SMARTY_CMS_PAGE_TEMPLATE. At the moment there is only one implementation [SMARTY_CMS_PAGE_TEMPLATE] (/library/src/theme/smarty_theme/smarty_cms_page_template.e).
<a name="regions"/>
Regions
-------
The layout of a CMS web page has predefined area called **regions**. The Eiffel CMS uses the same default regions as Drupal, so let's see them in the following image.
<a name="page_layout"/>
![default page layout](http://themery.com/sites/default/files/figure-15-10.png)
```
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
```
<a name="regions_blocks"/>
**A Region holds blocks**
**What goes inside regions?**
Generally, regions hold smaller piece of content called blocks. Blocks hold chunks of content, like the user login form, navigation menu or the information for the footer.
Regions are defined in a configuration file theme.info.
<a name="blocks"/>
CMS_BLOCK
---------
**What is a cms block?**
Blocks are chunk of content that can be created to display whatever you want, and then can be placed in various resgions in your template (theme) layout.
#### Important Classes
* [CMS_BLOCK] (/library/src/kernel/content/cms_block.e): The deferred class CMS_BLOCK provides an abstraction to describe content to be placed inside Regions.
* [CMS_CONTENT_BLOCK] (/library/src/kernel/content/cms_content_block.e): The class CMS_CONTENT_BLOCK describe how to provide generic content.
* [CMS_MENU_BLOCK](/library/src/kernel/content/cms_menu_block.e): The class CMS_MENU_BLOCK describe how to provides a menu of navigational links.
* [CMS_SMARTY_TEMPLATE_BLOCK] (/library/src/kernel/content/cms_smarty_templateblock.e) The class CMS_SMARTY_TEMPLATE_BLOCK describe how to use a CMS block with smarty template file content.
<a name="modules"/>
CMS_MODULES
-----------
**What is a cms module?**
Modules are piece of code that adds one or more features to your web site.
Modules can be plugged and combined to provide a web site customized to your needs. There are modules for many purposes, for example Administratiton, Basic Authentication, etc.
#### Important Classes
* [CMS_MODULE] (/library/src/modules/cms_module.e): The deferred class CMS_MODULE provides an abstraction to describe a generic module that add features to your web site.
* [CMS_RESPONSE](/library/src/service/response/cms_response.e). The deferred class CMS_RESPONSE provide an abstraction to builds the content to get process to render the output.
<a name="hooks">
CMS_HOOK
--------
Hooks is a mechanism which provide a way for modules to interact with each other and extending blocks of the current CMS.
* [CMS_HOOK] (/library/src/hooks/cms_hook.e): The deferred class CMS_HOOK is a marker interface for CMS Hook
* [CMS_HOOK_AUTO_REGISTER] (/library/src/hooks/cms_hook_auto_register.e): The deferred class provides an abstraction that when inheriting from this class, the declared hooks are automatically registered, otherwise, each descendant has to add it to the cms service itself.
* [CMS_HOOK_BLOCK](/library/src/hooks/cms_hook_block.e): The class CMS_HOOK_BLOCK describe a hook providing a way to alter a generic block.
* [CMS_HOOK_FORM_ALTER](/library/src/hooks/cms_hook_form_alter.e): The class CMS_HOOK_FORM_ATLER describe a hook providing a way to alter a form.
* [CMS_HOOK_MENU_ALTER](/library/src/hooks/cms_hook_menu_alter.e): The class CMS_HOOK_MENU_ATLER describe a hook providing a way to alter a menu.
* [CMS_HOOK_MENU_SYSTEM_ALTER](/library/src/hooks/cms_hook_menu_system_alter.e): The class CMS_HOOK_MENU_SYSTEM_ALTER describe a hook providing a way to alter the CMS menu system.
* [CMS_HOOK_VALUE_TABLE_ALTER](/library/src/hooks/cms_hook_value_table_alter.e):: The class CMS_HOOK_VALUE_TABLE_ALTER describe a hook providing a way to alter the value table for a response.

121
doc/tutorial.md Normal file
View File

@@ -0,0 +1,121 @@
CMS Tutorial
============
[Work in progress]
##### Table of Contents
[Getting Started](#init)
[Building your module](#module)
[Lifecycle](#cycle)
<a name="init"/>
Getting Started
-------------
<a name="module"/>
Building your own module
------------------------
A [Module](/doc/concepts.md#modules) as we already describe it, enable us to add functionallity based on your needs.
Here we will describe the basics steps to write your own modules.
* The first thing to do is inherit from the class [CMS_MODULE] () and redefine the register_hooks (2) feature.
* Implement (via inheritance) the needed [Hooks] (/doc/concepts.md#hooks).
* Define the module API through route definition. (1)
* Define the list of block to be handle by the current module (3).
* Render the block (4) (could be defined in Eiffel itself or using a template file (smarty)).
* API implementation (5).
```
class MY_NEW_MODULE
inherit
CMS_MODULE
redefine
register_hooks
end
CMS_HOOK_BLOCK
CMS_HOOK_MENU_SYSTEM_ALTER
create
make
feature {NONE} -- Initialization
make
-- Create current module
do
name := "new module"
version := "1.0"
description := "Eiffel new module"
package := "example"
end
feature -- Access: router
router (a_api: CMS_API): WSF_ROUTER
-- (1) Node router.
do
create Result.make (1)
Result.handle_with_request_methods ("/demo", create {WSF_URI_AGENT_HANDLER}.make (agent handle_demo (a_api, ?, ?)), Result.methods_head_get)
end
feature -- Hooks
register_hooks (a_response: CMS_RESPONSE)
do
-- (2)
a_response.subscribe_to_menu_system_alter_hook (Current)
a_response.subscribe_to_block_hook (Current)
end
block_list: ITERABLE [like {CMS_BLOCK}.name]
do
-- (3) List of block names, managed by current object.
end
get_block_view (a_block_id: READABLE_STRING_8; a_response: CMS_RESPONSE)
do
-- (4) Get block object identified by `a_block_id' and associate with `a_response'.
end
menu_system_alter (a_menu_system: CMS_MENU_SYSTEM; a_response: CMS_RESPONSE)
local
lnk: CMS_LOCAL_LINK
do
create lnk.make ("Demo", "/demo/")
a_menu_system.primary_menu.extend (lnk)
end
feature -- Handler
handle_demo (a_api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE;)
local
r: NOT_IMPLEMENTED_ERROR_CMS_RESPONSE
do
-- (5)
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
end
```
<a name="cycle"/>
Lifecycle
---------

View File

@@ -1,18 +1,28 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="demo" uuid="3643E657-BCBE-46AA-931B-71EAEA877A18" library_target="demo">
<description>Example/demo for Eiffel ROC CMS library</description>
<target name="common" abstract="true">
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="false" is_attached_by_default="true" void_safety="transitional" syntax="transitional">
<option warning="true" full_class_checking="false" is_attached_by_default="true" void_safety="all" syntax="transitional">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<setting name="concurrency" value="none"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="cms" location="..\..\cms-safe.ecf" readonly="false"/>
<library name="cms_app_env" location="..\..\library\app_env\app_env-safe.ecf" readonly="false"/>
<library name="cms_basic_auth_module" location="..\..\modules\basic_auth\basic_auth-safe.ecf" readonly="false"/>
<library name="cms_blog_module" location="modules\blog\cms_blog_module-safe.ecf" readonly="false"/>
<library name="cms_demo_module" location="modules\demo\cms_demo_module-safe.ecf" readonly="false"/>
<library name="layout" location="..\..\library\layout\layout-safe.ecf" readonly="false"/>
<library name="cms_model" location="..\..\library\model\cms_model-safe.ecf" readonly="false"/>
<library name="cms_node_module" location="..\..\modules\node\node-safe.ecf" readonly="false"/>
<!--
<library name="persistence_mysql" location="..\..\library\persistence\mysql\persistence_mysql-safe.ecf" readonly="false"/>
-->
<library name="persistence_sqlite" location="..\..\library\persistence\sqlite\persistence_sqlite-safe.ecf" readonly="false"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
<library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension-safe.ecf" readonly="false"/>
</target>
@@ -26,6 +36,7 @@
</target>
<target name="demo_nino" extends="common">
<root class="EWF_ROC_SERVER" feature="make_and_launch"/>
<setting name="concurrency" value="none"/>
<library name="default_nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\nino-safe.ecf"/>
<cluster name="launcher" location=".\launcher\default\" recursive="true"/>
<cluster name="src" location=".\src\" recursive="true"/>

View File

@@ -1,2 +1,2 @@
port=8099
#verbose=true
port=9090
#verbose=true

View File

@@ -6,8 +6,8 @@ note
you can customize APPLICATION_LAUNCHER
]"
date: "$Date: 2013-06-12 13:55:42 +0200 (mer., 12 juin 2013) $"
revision: "$Revision: 36 $"
date: "$Date: 2015-02-09 22:29:56 +0100 (lun., 09 févr. 2015) $"
revision: "$Revision: 96596 $"
deferred class
APPLICATION_LAUNCHER_I
@@ -16,7 +16,7 @@ feature -- Execution
launch (a_service: WSF_SERVICE; opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
local
launcher: WSF_SERVICE_LAUNCHER
launcher: WSF_DEFAULT_SERVICE_LAUNCHER
do
create {WSF_DEFAULT_SERVICE_LAUNCHER} launcher.make_and_launch (a_service, opts)
end

View File

@@ -0,0 +1,102 @@
note
description: "Summary description for {CMS_BLOG}."
date: "$Date$"
revision: "$Revision$"
class
CMS_BLOG
inherit
CMS_NODE
redefine
make_empty,
import_node
end
create
make_empty,
make
feature {NONE} -- Initialization
make_empty
do
Precursor
end
feature -- Conversion
import_node (a_node: CMS_NODE)
-- <Precursor>
do
Precursor (a_node)
if attached {CMS_BLOG} a_node as l_blog then
-- l_blog
end
end
feature -- Access
content_type: READABLE_STRING_8
once
Result := {CMS_BLOG_NODE_TYPE}.name
end
feature -- Access: content
summary: detachable READABLE_STRING_8
-- A short summary of the node.
content: detachable READABLE_STRING_8
-- Content of the node.
format: detachable READABLE_STRING_8
-- Format associated with `content' and `summary'.
-- For example: text, mediawiki, html, etc
tags: detachable ARRAYED_LIST [READABLE_STRING_32]
-- Optional tags
feature -- Element change
set_content (a_content: like content; a_summary: like summary; a_format: like format)
do
content := a_content
summary := a_summary
format := a_format
end
add_tag (a_tag: READABLE_STRING_32)
-- Set `parent' to `a_page'
require
not a_tag.is_whitespace
local
l_tags: like tags
do
l_tags := tags
if l_tags = Void then
create l_tags.make (1)
tags := l_tags
end
l_tags.force (a_tag)
end
set_tags_from_string (a_tags: READABLE_STRING_32)
local
t: STRING_32
do
tags := Void
across
a_tags.split (',') as ic
loop
t := ic.item
t.left_adjust
t.right_adjust
if not t.is_whitespace then
add_tag (t)
end
end
end
end

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="cms_blog_module" uuid="C92F6E1E-2222-4414-9B6E-AA680E324D42" library_target="cms_blog_module">
<target name="cms_blog_module">
<root all_classes="true"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="standard">
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="base_extension" location="$ISE_LIBRARY\library\base_extension\base_extension-safe.ecf"/>
<library name="cms" location="..\..\..\..\cms-safe.ecf" readonly="false"/>
<library name="cms_model" location="..\..\..\..\library\model\cms_model-safe.ecf" readonly="false"/>
<library name="cms_node_module" location="..\..\..\..\modules\node\node-safe.ecf" readonly="false"/>
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-safe.ecf"/>
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json-safe.ecf" readonly="false"/>
<library name="text_filter" location="$ISE_LIBRARY\unstable\library\text\text_filter\text_filter-safe.ecf"/>
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
<library name="wsf_html" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf_html\wsf_html-safe.ecf"/>
<library name="wsf_encoder" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\text\encoder\encoder-safe.ecf"/>
<cluster name="src" location=".\" recursive="true"/>
</target>
</system>

View File

@@ -0,0 +1,120 @@
note
description: "Summary description for {CMS_BLOG_MODULE}."
date: "$Date: 2015-02-13 13:08:13 +0100 (ven., 13 févr. 2015) $"
revision: "$Revision: 96616 $"
class
CMS_BLOG_MODULE
inherit
CMS_MODULE
redefine
register_hooks,
initialize,
is_installed,
install
end
CMS_HOOK_MENU_SYSTEM_ALTER
create
make
feature {NONE} -- Initialization
make
do
name := "Blog demo module"
version := "1.0"
description := "Service to demonstrate new node for blog"
package := "demo"
end
feature {CMS_API} -- Module Initialization
initialize (api: CMS_API)
-- <Precursor>
local
ct: CMS_BLOG_NODE_TYPE
do
Precursor (api)
if attached {CMS_NODE_API} api.module_api ({NODE_MODULE}) as l_node_api then
create ct
l_node_api.add_content_type (ct)
l_node_api.add_content_type_webform_manager (create {CMS_BLOG_NODE_TYPE_WEBFORM_MANAGER}.make (ct))
-- Add support for CMS_BLOG, which requires a storage extension to store the optional "tags" value
-- For now, we only have extension based on SQL statement.
if attached {CMS_NODE_STORAGE_SQL} l_node_api.node_storage as l_sql_node_storage then
l_sql_node_storage.register_node_storage_extension (create {CMS_NODE_STORAGE_SQL_BLOG_EXTENSION}.make (l_sql_node_storage))
end
end
end
feature {CMS_API} -- Module management
is_installed (api: CMS_API): BOOLEAN
-- Is Current module installed?
do
Result := attached api.storage.custom_value ("is_initialized", "module-" + name) as v and then v.is_case_insensitive_equal_general ("yes")
end
install (api: CMS_API)
local
sql: STRING
do
-- Schema
if attached {CMS_STORAGE_SQL_I} api.storage as l_sql_storage then
if not l_sql_storage.sql_table_exists ("blog_post_nodes") then
sql := "[
CREATE TABLE "blog_post_nodes"(
"nid" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK("nid">=0),
"revision" INTEGER,
"tags" VARCHAR(255)
);
]"
l_sql_storage.sql_execute_script (sql)
if l_sql_storage.has_error then
api.logger.put_error ("Could not initialize database for blog module", generating_type)
end
end
api.storage.set_custom_value ("is_initialized", "module-" + name, "yes")
end
end
feature -- Access: router
router (a_api: CMS_API): WSF_ROUTER
-- Node router.
do
create Result.make (1)
Result.handle_with_request_methods ("/blogs/", create {WSF_URI_AGENT_HANDLER}.make (agent handle_blogs (?,?, a_api)), Result.methods_get)
end
feature -- Hooks
register_hooks (a_response: CMS_RESPONSE)
do
a_response.subscribe_to_menu_system_alter_hook (Current)
end
menu_system_alter (a_menu_system: CMS_MENU_SYSTEM; a_response: CMS_RESPONSE)
local
lnk: CMS_LOCAL_LINK
do
create lnk.make ("Blogs", "/blogs/")
a_menu_system.primary_menu.extend (lnk)
end
feature -- Handler
handle_blogs (req: WSF_REQUEST; res: WSF_RESPONSE; a_api: CMS_API)
local
r: NOT_IMPLEMENTED_ERROR_CMS_RESPONSE
do
create r.make (req, res, a_api)
r.set_main_content ("Blog module is in development ...")
r.execute
end
end

View File

@@ -0,0 +1,63 @@
note
description: "Summary description for {CMS_BLOG_NODE_TYPE}."
date: "$Date$"
revision: "$Revision$"
class
CMS_BLOG_NODE_TYPE
inherit
CMS_NODE_TYPE [CMS_BLOG]
redefine
default_create
end
feature {NONE} -- Initialization
default_create
do
Precursor
create {ARRAYED_LIST [like available_formats.item]} available_formats.make (3)
available_formats.extend (create {PLAIN_TEXT_CONTENT_FORMAT})
available_formats.extend (create {FILTERED_HTML_CONTENT_FORMAT})
available_formats.extend (create {FULL_HTML_CONTENT_FORMAT})
end
feature -- Access
name: STRING = "blog"
-- Internal name.
title: STRING_32 = "Blog"
-- Human readable name.
description: STRING_32 = "Content published as a blog post."
-- Optional description
feature -- Access
available_formats: LIST [CONTENT_FORMAT]
-- Available formats for Current type.
feature -- Factory
new_node_with_title (a_title: READABLE_STRING_32; a_partial_node: detachable CMS_NODE): like new_node
-- New node with `a_title' and fill from partial `a_partial_node' if set.
do
create Result.make (a_title)
if a_partial_node /= Void then
Result.import_node (a_partial_node)
Result.set_title (a_title)
end
end
new_node (a_partial_node: detachable CMS_NODE): CMS_BLOG
-- New node based on partial `a_partial_node', or from none.
do
create Result.make_empty
if a_partial_node /= Void then
Result.import_node (a_partial_node)
end
end
end

View File

@@ -0,0 +1,109 @@
note
description: "Summary description for {CMS_BLOG_NODE_TYPE_WEBFORM_MANAGER}."
date: "$Date$"
revision: "$Revision$"
class
CMS_BLOG_NODE_TYPE_WEBFORM_MANAGER
inherit
CMS_NODE_TYPE_WEBFORM_MANAGER [CMS_BLOG]
redefine
content_type,
populate_form,
update_node,
new_node,
append_html_output_to
end
create
make
feature -- Access
content_type: CMS_BLOG_NODE_TYPE
-- Associated content type.
feature -- form
populate_form (response: NODE_RESPONSE; f: CMS_FORM; a_node: detachable CMS_NODE)
local
ti: WSF_FORM_TEXT_INPUT
s: STRING_32
do
Precursor (response, f, a_node)
create ti.make ("tags")
ti.set_label ("Tags")
ti.set_size (70)
if
a_node /= Void and then
attached {CMS_BLOG} a_node as a_blog and then
attached a_blog.tags as l_tags
then
create s.make_empty
across
l_tags as ic
loop
if not s.is_empty then
s.append_character (',')
end
s.append (ic.item)
end
ti.set_text_value (s)
end
ti.set_is_required (False)
f.extend (ti)
end
update_node (response: NODE_RESPONSE; fd: WSF_FORM_DATA; a_node: CMS_NODE)
do
Precursor (response, fd, a_node)
if attached fd.string_item ("tags") as l_tags then
if attached {CMS_BLOG} a_node as l_blog then
l_blog.set_tags_from_string (l_tags)
end
end
end
new_node (response: NODE_RESPONSE; fd: WSF_FORM_DATA; a_node: detachable like new_node): like content_type.new_node
-- <Precursor>
do
Result := Precursor (response, fd, a_node)
if attached fd.string_item ("tags") as l_tags then
Result.set_tags_from_string (l_tags)
end
end
feature -- Output
append_html_output_to (a_node: CMS_NODE; a_response: NODE_RESPONSE)
-- <Precursor>
local
s: STRING
do
Precursor (a_node, a_response)
if attached a_response.main_content as l_main_content then
s := l_main_content
else
create s.make_empty
end
if attached {CMS_BLOG} a_node as l_blog_post then
if attached l_blog_post.tags as l_tags then
s.append ("<div><strong>Tags:</strong> ")
across
l_tags as ic
loop
s.append ("<span class=%"tag%">")
s.append (a_response.html_encoded (ic.item))
s.append ("</span> ")
end
s.append ("</div>")
end
end
a_response.set_main_content (s)
end
end

View File

@@ -0,0 +1,115 @@
note
description: "Storage extension for Blog nodes."
date: "$Date$"
revision: "$Revision$"
class
CMS_NODE_STORAGE_SQL_BLOG_EXTENSION
inherit
CMS_NODE_STORAGE_EXTENSION [CMS_BLOG]
CMS_PROXY_STORAGE_SQL
rename
sql_storage as node_storage
redefine
node_storage
end
create
make
feature {NONE} -- Initialization
node_storage: CMS_NODE_STORAGE_SQL
-- <Precursor>
feature -- Access
content_type: STRING
once
Result := {CMS_BLOG_NODE_TYPE}.name
end
feature -- Persistence
store (a_node: CMS_BLOG)
local
l_parameters: STRING_TABLE [detachable ANY]
l_new_tags: detachable STRING_32
l_previous_tags: detachable STRING_32
l_update: BOOLEAN
do
error_handler.reset
if attached api as l_api then
l_api.logger.put_information (generator + ".store", Void)
end
create l_parameters.make (2)
l_parameters.put (a_node.id, "nid")
l_parameters.put (a_node.revision, "revision")
sql_query (sql_select_blog_data, l_parameters)
if not has_error then
if sql_rows_count = 1 then
l_previous_tags := sql_read_string_32 (3)
l_update := True
end
if attached a_node.tags as l_tags and then not l_tags.is_empty then
create l_new_tags.make (0)
across
l_tags as ic
loop
if not l_new_tags.is_empty then
l_new_tags.append_character (',')
end
l_new_tags.append (ic.item)
end
else
l_new_tags := Void
end
l_parameters.put (l_new_tags, "tags")
if l_update and l_new_tags /~ l_previous_tags then
sql_change (sql_update_blog_data, l_parameters)
elseif l_new_tags /= Void then
sql_change (sql_insert_blog_data, l_parameters)
else
-- no blog data, means everything is empty.
end
end
end
load (a_node: CMS_BLOG)
local
l_parameters: STRING_TABLE [ANY]
n: INTEGER
do
error_handler.reset
create l_parameters.make (2)
l_parameters.put (a_node.id, "nid")
l_parameters.put (a_node.revision, "revision")
sql_query (sql_select_blog_data, l_parameters)
if not has_error then
n := sql_rows_count
if n = 1 then
-- nid, revision, parent
if
attached sql_read_string_32 (3) as l_tags and then
not l_tags.is_whitespace
then
-- FIXME: find a simple way to access the declared content types.
a_node.set_tags_from_string (l_tags)
end
else
check unique_data: n = 0 end
end
end
end
feature -- SQL
sql_select_blog_data: STRING = "SELECT nid, revision, tags FROM blog_post_nodes WHERE nid =:nid AND revision=:revision;"
sql_insert_blog_data: STRING = "INSERT INTO blog_post_nodes (nid, revision, tags) VALUES (:nid, :revision, :tags);"
sql_update_blog_data: STRING = "UPDATE blog_post_nodes SET nid=:nid, revision=:revision, tags=:tags WHERE nid=:nid AND revision=:revision;"
end

View File

@@ -7,7 +7,7 @@
<exclude>/EIFGENs$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="transitional" syntax="standard">
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="standard">
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="base_extension" location="$ISE_LIBRARY\library\base_extension\base_extension-safe.ecf"/>

View File

@@ -1,8 +1,8 @@
note
description: "Summary description for {CMS_DEMO_MODULE}."
author: ""
date: "$Date$"
revision: "$Revision$"
date: "$Date: 2015-02-13 13:08:13 +0100 (ven., 13 févr. 2015) $"
revision: "$Revision: 96616 $"
class
CMS_DEMO_MODULE
@@ -10,7 +10,10 @@ class
inherit
CMS_MODULE
redefine
register_hooks
register_hooks,
initialize,
is_installed,
install
end
CMS_HOOK_MENU_SYSTEM_ALTER
@@ -30,13 +33,57 @@ feature {NONE} -- Initialization
package := "demo"
end
feature {CMS_API} -- Module Initialization
initialize (api: CMS_API)
-- <Precursor>
do
Precursor (api)
-- Add support for CMS_PAGE, which requires a storage extension to store the optional "parent" id.
-- For now, we only have extension based on SQL statement.
-- if attached {CMS_NODE_STORAGE_SQL} l_node_api.node_storage as l_sql_node_storage then
-- l_sql_node_storage.register_node_storage_extension (create {CMS_NODE_STORAGE_SQL_PAGE_EXTENSION}.make (l_sql_node_storage))
-- end
end
feature {CMS_API} -- Module management
is_installed (api: CMS_API): BOOLEAN
-- Is Current module installed?
do
Result := attached api.storage.custom_value ("is_initialized", "module-" + name) as v and then v.is_case_insensitive_equal_general ("yes")
end
install (api: CMS_API)
local
sql: STRING
do
-- Schema
if attached {CMS_STORAGE_SQL_I} api.storage as l_sql_storage then
if not l_sql_storage.sql_table_exists ("tb_demo") then
sql := "[
CREATE TABLE "tb_demo"(
"demo_id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK("demo_id">=0),
"name" VARCHAR(100) NOT NULL,
"value" TEXT
);
]"
l_sql_storage.sql_execute_script (sql)
if l_sql_storage.has_error then
api.logger.put_error ("Could not initialize database for demo module", generating_type)
end
end
api.storage.set_custom_value ("is_initialized", "module-" + name, "yes")
end
end
feature -- Access: router
router (a_api: CMS_API): WSF_ROUTER
-- Node router.
do
create Result.make (2)
map_uri_template_agent (Result, "/demo/", agent handle_demo (?,?,a_api))
map_uri_template_agent (Result, "/demo/{id}", agent handle_demo_entry (?,?,a_api))
end

View File

@@ -1,10 +1,13 @@
{
"database": {
"datasource": {
"driver": "MySQL",
"environment": "development"
"driver": "sqlite",
"environment": "sqlite"
},
"environments": {
"sqlite": {
"connection_string":"Driver=SQLite3 ODBC Driver;Database=./site/database.sqlite;LongNames=0;Timeout=1000;NoTXN=0;SyncPragma=NORMAL;StepAPI=0;"
},
"test": {
"connection_string":"Server=localhost;Port=3306;Database=cms_dev;Uid=root;Pwd=;"
},
@@ -29,4 +32,4 @@
}

View File

@@ -1,6 +1,11 @@
engine=smarty
site.name=EWF Web CMS
site.email=your@email.com
var-dir=var
files-dir=files
[layout]
root-dir=site/www
themes-dir=site/themes
[site]
name=Eiffel CMS
email=your@email.com
theme=bootstrap
[misc]
smtp=localhost

View File

@@ -0,0 +1,51 @@
BEGIN;
CREATE TABLE "users"(
"uid" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK("uid">=0),
"name" VARCHAR(100) NOT NULL,
"password" VARCHAR(100) NOT NULL,
"salt" VARCHAR(100) NOT NULL,
"email" VARCHAR(250) NOT NULL,
"status" INTEGER,
"created" DATETIME NOT NULL,
"signed" DATETIME,
CONSTRAINT "name"
UNIQUE("name")
);
CREATE TABLE "roles"(
"rid" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK("rid">=0),
"name" VARCHAR(100) NOT NULL,
CONSTRAINT "name"
UNIQUE("name")
);
CREATE TABLE "users_roles"(
"uid" INTEGER NOT NULL CHECK("uid">=0),
"rid" INTEGER NOT NULL CHECK("rid">=0)
);
CREATE TABLE "role_permissions"(
"rid" INTEGER NOT NULL CHECK("rid">=0),
"permission" VARCHAR(255) NOT NULL,
"module" VARCHAR(255)
);
CREATE TABLE "logs"(
"id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK("id">=0),
"category" VARCHAR(255) NOT NULL,
"level" INTEGER NOT NULL CHECK("level">=1),
"uid" INTEGER,
"message" TEXT NOT NULL,
"info" TEXT,
"link" TEXT,
"date" DATETIME NOT NULL
);
CREATE TABLE "custom_values"(
"type" VARCHAR(255) NOT NULL,
"name" VARCHAR(255) NOT NULL,
"value" VARCHAR(255) NOT NULL
);
COMMIT;

View File

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

View File

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

View File

@@ -0,0 +1,78 @@
ul.horizontal li {
display: inline-block;
}
#header #primary.menu ul li {
color: #555;
background-color: #fff;
padding: 10px;
margin: 0;
}
#header #primary.menu ul li a {
color: #555;
text-decoration: none;
}
#header #primary.menu ul li a:hover {
color: black;
}
#header #primary.menu ul.horizontal {
border-bottom: solid 1px #ddd;
}
#header #primary.menu ul.horizontal li {
border-top: solid 3px #fff;
}
#header #primary.menu ul.horizontal li:hover {
background-color: #ffe;
border-top: solid 3px #999;
}
#header #primary.menu ul.horizontal li.active {
font-weight: bold;
border-top: solid 3px #ddd;
background-color: #ddd;
}
#header #primary.menu ul.horizontal li.active:hover {
border-top: solid 3px blue;
}
#content {
margin-left: 20px;
}
#content #highlighted {
position: relative;
border: solid 1px #ddd;
background-color: #ffc;
width: 70%;
left: 15%;
right: 15%;
padding: 5px;
font-style: italic;
}
.sidebar {
padding: 5px;
margin: 3px;
border: solid 1px #ccc;
}
.sidebar#sidebar_first {
width: 250px;
float: left;
}
.sidebar#sidebar_second {
width: 250px;
float: right;
}
#primary-tabs ul.horizontal {
list-style-type: none;
}
#primary-tabs ul.horizontal li {
display: inline;
padding: 2px 5px;
border: solid 1px #ccf;
}
#primary-tabs ul.horizontal li.active {
border-color: #99f #99f #ddd;
border-style: solid solid none;
border-width: 2px 1px 0;
padding: 2px 7px 1px;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,307 @@
var ROC_AUTH = ROC_AUTH || { };
var loginURL = "/login";
var logoutURL = "/logoff";
var userAgent = navigator.userAgent.toLowerCase();
var firstLogIn = true;
ROC_AUTH.login = function() {
var form = document.forms[0];
var username = form.username.value;
var password = form.password.value;
//var host = form.host.value;
var origin = window.location.origin.concat(window.location.pathname);
var _login = function(){
if (document.getElementById('myModalFormId') !== null ) {
ROC_AUTH.remove ('myModalFormId');
}
if (username === "" || password === "") {
if (document.getElementById('myModalFormId') === null ) {
var newdiv = document.createElement('div');
newdiv.innerHTML = "<br>Invalid Credentials</br>";
newdiv.id = 'myModalFormId';
$("body").append(newdiv);
}
}else{
//Instantiate HTTP Request
var request = ((window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"));
request.open("GET", loginURL, true, username, password);
request.send(null);
//Process Response
request.onreadystatechange = function(){
if (request.readyState == 4) {
if (request.status==200) {
delete form;
window.location=origin;
}
else{
if (navigator.userAgent.toLowerCase().indexOf("firefox") != -1){
}
if (document.getElementById('myModalFormId') === null ) {
var newdiv = document.createElement('div');
newdiv.innerHTML = "<br>Invalid Credentials</br>";
newdiv.id = 'myModalFormId';
$("body").append(newdiv);
}
}
}
}
}
}
var userAgent = navigator.userAgent.toLowerCase();
if (userAgent.indexOf("firefox") != -1){ //TODO: check version number
if (firstLogIn) _login();
else logoff(_login);
}
else{
_login();
}
if (firstLogIn) firstLogIn = false;
};
ROC_AUTH.login_with_redirect = function() {
var form = document.forms[2];
var username = form.username.value;
var password = form.password.value;
var host = form.host.value;
var _login = function(){
var redirectURL = form.redirect && form.redirect.value || "";
$("#imgProgressRedirect").show();
if (document.getElementById('myModalFormId') !== null ) {
ROC_AUTH.remove ('myModalFormId');
}
if (username === "" || password === "") {
if (document.getElementById('myModalFormId') === null ) {
var newdiv = document.createElement('div');
newdiv.innerHTML = "<br>Invalid Credentials</br>";
newdiv.id = 'myModalFormId';
$("body").append(newdiv);
$("#imgProgressRedirect").hide();
}
}else{
//Instantiate HTTP Request
var request = ((window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"));
request.open("GET", host.concat(loginURL), true, username, password);
request.send(null);
//Process Response
request.onreadystatechange = function(){
if (request.readyState == 4) {
if (request.status==200) {
if (redirectURL === "") {
window.location=host.concat("/");
} else {
window.location=host.concat(redirectURL);
}
}
else{
if (navigator.userAgent.toLowerCase().indexOf("firefox") != -1){
}
if (document.getElementById('myModalFormId') === null ) {
var newdiv = document.createElement('div');
newdiv.innerHTML = "<br>Invalid Credentials</br>";
newdiv.id = 'myModalFormId';
$("body").append(newdiv);
$("#imgProgressRedirect").hide();
}
}
}
}
}
}
var userAgent = navigator.userAgent.toLowerCase();
if (userAgent.indexOf("firefox") != -1){ //TODO: check version number
if (firstLogIn) _login();
else logoff(_login);
}
else{
_login();
}
if (firstLogIn) firstLogIn = false;
};
ROC_AUTH.getQueryParameterByName = function (name) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
results = regex.exec(location.search);
return results === null ? " " : decodeURIComponent(results[1].replace(/\+/g, " "));
}
ROC_AUTH.logoff = function(callback){
var form = document.forms[0];
var host = form.host.value;
if (userAgent.indexOf("msie") != -1) {
document.execCommand("ClearAuthenticationCache");
}
else if (userAgent.indexOf("firefox") != -1){ //TODO: check version number
var request1 = new XMLHttpRequest();
var request2 = new XMLHttpRequest();
//Logout. Tell the server not to return the "WWW-Authenticate" header
request1.open("GET", host.concat(logoutURL) + "?prompt=false", true);
request1.send("");
request1.onreadystatechange = function(){
if (request1.readyState == 4) {
//Sign in with dummy credentials to clear the auth cache
request2.open("GET", host.concat(logoutURL), true, "logout", "logout");
request2.send("");
request2.onreadystatechange = function(){
if (request2.readyState == 4) {
if (callback!=null) { callback.call(); } else { window.location=host.concat(logoutURL);}
}
}
}
}
}
else {
var request = ((window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"));
request.open("GET", host.concat(logoutURL), true, "logout", "logout");
request.send("");
request.onreadystatechange = function(){
if (request.status==401 || request.status==403 ) { window.location=host.concat(logoutURL);
}
}
}
};
ROC_AUTH.remove = function (id)
{
var element = document.getElementById(id);
element.outerHTML = "";
delete element;
return;
};
$(document).ready(function() {
if (typeof String.prototype.contains != 'function') {
String.prototype.contains = function (str){
return this.indexOf(str) != -1;
};
}
ROC_AUTH.progressive_loging();
});
ROC_AUTH.progressive_loging = function () {
ROC_AUTH.login_href();
};
$(document).keypress(function(e) {
if ((e.which === 13) && (e.target.localName === 'input' && e.target.id === 'password')) {
ROC_AUTH.login();
}
});
ROC_AUTH.OnOneClick = function(event) {
event.preventDefault();
if ( document.forms[0] === undefined ) {
ROC_AUTH.create_form();
}
return false;
};
ROC_AUTH.login_href = function() {
var els = document.getElementsByTagName("a");
for (var i = 0, l = els.length; i < l; i++) {
var el = els[i];
if (el.href.contains("/basic_auth_login?destination")) {
loginURL = el.href;
var OneClick = el;
OneClick.addEventListener('click', ROC_AUTH.OnOneClick, false);
}
}
};
ROC_AUTH.create_form = function() {
// Fetching HTML Elements in Variables by ID.
var createform = document.createElement('form'); // Create New Element Form
createform.setAttribute("action", ""); // Setting Action Attribute on Form
createform.setAttribute("method", "post"); // Setting Method Attribute on Form
$("body").append(createform);
var heading = document.createElement('h2'); // Heading of Form
heading.innerHTML = "Login Form ";
createform.appendChild(heading);
var line = document.createElement('hr'); // Giving Horizontal Row After Heading
createform.appendChild(line);
var linebreak = document.createElement('br');
createform.appendChild(linebreak);
var namelabel = document.createElement('label'); // Create Label for Name Field
namelabel.innerHTML = "Username : "; // Set Field Labels
createform.appendChild(namelabel);
var inputelement = document.createElement('input'); // Create Input Field for UserName
inputelement.setAttribute("type", "text");
inputelement.setAttribute("name", "username");
inputelement.setAttribute("required","required");
createform.appendChild(inputelement);
var linebreak = document.createElement('br');
createform.appendChild(linebreak);
var passwordlabel = document.createElement('label'); // Create Label for Password Field
passwordlabel.innerHTML = "Password : ";
createform.appendChild(passwordlabel);
var passwordelement = document.createElement('input'); // Create Input Field for Password.
passwordelement.setAttribute("type", "password");
passwordelement.setAttribute("name", "password");
passwordelement.setAttribute("id", "password");
passwordelement.setAttribute("required","required");
createform.appendChild(passwordelement);
var passwordbreak = document.createElement('br');
createform.appendChild(passwordbreak);
var submitelement = document.createElement('button'); // Append Submit Button
submitelement.setAttribute("type", "button");
submitelement.setAttribute("onclick", "ROC_AUTH.login();");
submitelement.innerHTML = "Sign In ";
createform.appendChild(submitelement);
};

View File

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

View File

@@ -0,0 +1,83 @@
ul.horizontal {
li {
display: inline-block;
}
}
#header {
#primary.menu {
ul {
li {
color: #555;
a {
color: #555;
text-decoration: none;
&:hover { color: black; }
}
background-color: #fff;
padding: 10px;
margin: 0;
}
&.horizontal {
border-bottom: solid 1px #ddd;
li {
border-top: solid 3px #fff;
&:hover {
background-color: #ffe;
border-top: solid 3px #999;
}
&.active {
font-weight: bold;
border-top: solid 3px #ddd;
background-color: #ddd;
}
&.active:hover {
border-top: solid 3px blue;
}
}
}
}
}
}
#content {
margin-left: 20px;
#highlighted {
position: relative;
border: solid 1px #ddd;
background-color: #ffc;
width: 70%;
left: 15%;
right: 15%;
padding: 5px;
font-style: italic;
}
}
.sidebar {
padding: 5px;
margin: 3px;
border: solid 1px #ccc;
&#sidebar_first {
width: 250px;
float: left;
}
&#sidebar_second {
width: 250px;
float: right;
}
}
#primary-tabs {
ul.horizontal {
list-style-type: none;
li {
display: inline;
padding: 2px 5px;
border: solid 1px #ccf;
}
li.active {
border-color: #99f #99f #ddd;
border-style: solid solid none;
border-width: 2px 1px 0;
padding: 2px 7px 1px;
}
}
}

View File

@@ -0,0 +1,38 @@
{assign name="debug_enabled" value="True"/}
{if condition="$debug_enabled"}
<!-- start debug -->
{literal}
<style>
div.cms-debug>span {
position: absolute;
bottom: 5px;
right: 5px;
color: #ccc;
padding: 5px;
}
div.cms-debug:hover>span {
color: red;
}
div.cms-debug>span+ul {
display: none;
border: solid 2px red;
background-color: #ccc;
white-space: pre-wrap;
}
div.cms-debug:hover>span+ul {
display: block;
position: relative;
bottom: 5px;
left: 1%; right: 1%;
width: 98%;
}
</style>
{/literal}
<div class="cms-debug"><span>Show debug</span>
<ul>
{assign name="kpage" value="page"/}{assign name="kregions" value="regions"/}{foreach key="k" item="i" from="$page.variables"}{unless condition="$k ~ $kpage"}{unless condition="$k ~ $kregions"}<li><strong>{$k/}</strong>={htmlentities}{$i/}{/htmlentities}</li>{/unless}{/unless}
{/foreach}
</ul>
</div>
<!-- end debug -->
{/if}

View File

@@ -0,0 +1,79 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- EWF CMS -->
<link rel="stylesheet" href="{$site_url/}/theme/css/style.css">
<link rel="stylesheet" href="{$site_url/}/theme/css/node.css">
<script src="{$site_url/}/theme/js/jquery-1.10.2.min.js"></script>
<script src="{$site_url/}/theme/js/roc_auth.js"></script>
<!-- bootstrap framework -->
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap-theme.min.css">
<title>{$head_title/}</title>
</head>
<body>
<!-- Page Top -->
{if isset="$region_top"}
{$region_top/}
{/if}
<!-- Body -->
<div class='container-fluid'>
<!-- Page Header -->
<div id="header">
{if isset="$page.primary_nav"}
{$page.primary_nav/}
{/if}
</div>
<!-- General Page Content -->
<div id='content' class='row-fluid'>
<!-- Left Sidebar sidebar_first -->
{unless isempty="$page.region_sidebar_first"}
<div id="sidebar_first" class="sidebar">{$page.region_sidebar_first/}</div>
{/unless}
<!-- Right Sidebar sidebar_second-->
{unless isempty="$page.region_sidebar_second"}
<div id="sidebar_second" class="sidebar">{$page.region_sidebar_second/}</div>
{/unless}
<!-- Highlighted, Help, Content -->
<div class='span8 main'>
<!-- Highlighted Section -->
{unless isempty="$page.region_highlighted"}
<div id="highlighted">{$page.region_highlighted/}</div>
{/unless}
<!-- Help Section -->
{unless isempty="$page.region_help"}
<div id="help">{$page.region_help/}</div>
{/unless}
<!-- Main Content Section -->
{unless isempty="$page_title"}<h1 class="page-title">{$page_title/}</h1>{/unless}
{$page.region_content/}
</div>
</div>
</div>
<!--Page footer -->
{$page.region_footer/}
<!-- Page Bottom -->
{$page.region_bottom/}
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
{include file="debug.tpl"/}
</body>
</html>

View File

@@ -1,36 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
{include file="master2/head.tpl"/}
</head>
<body>
<!-- Site Navigation -->
{include file="master2/site_navigation.tpl"/}
<div class="container">
<hr>
<div class="row">
<main class="main">
{include file="master2/content.tpl"/}
</main>
</div>
</div>
<div id="footer">
<footer class="site-footer">
{include file="master2/footer.tpl"/}
</footer>
</div>
{if condition="$web"}
{include file="master2/optional_enhancement_js.tpl"/}
{/if}
{if condition="$html"}
{include file="master2/optional_enhancement_js.tpl"/}
{/if}
</body>
</html>

View File

@@ -1,40 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
{include file="master2/head.tpl"/}
</head>
<body>
<!-- Site Navigation -->
{include file="master2/site_navigation.tpl"/}
<!--<header class="main-navi">
{include file="master2/header.tpl"/}
</header> -->
<div class="container">
<hr>
<div class="row">
<main class="main">
{include file="master2/content.tpl"/}
</main>
</div>
</div>
<div id="footer">
<footer class="site-footer">
{include file="master2/footer.tpl"/}
</footer>
</div>
{if condition="$web"}
{include file="master2/optional_enhancement_js.tpl"/}
{/if}
{if condition="$html"}
{include file="master2/optional_enhancement_js.tpl"/}
{/if}
</body>
</html>

View File

@@ -1,5 +0,0 @@
<p>You have successfully signed out</p>
You may want to return
Press this neat little button:<a href="{$host/}/">Take Me Home </a>

View File

@@ -1,11 +0,0 @@
<div itemscope itemtype="http://schema.org/ItemList">
<h2 itemprop="name">Top most recent nodes</h2><br>
<meta itemprop="itemListOrder" content="Descending" />
{foreach from="$nodes" item="item"}
<div class="page-header">
<h3><span itemprop="itemListElement"><a href="{$host/}/node/{$item.id/}" rel="node"><strong>{$item.title/}</strong></a></span> <small>{$item.summary/} - {$item.publication_date_output/} </small></h3>
</div>
{/foreach}
</div>

View File

@@ -1,18 +0,0 @@
<h3> Error: {$code/} </h3>
{assign name="status400" value="400"/}
{assign name="status404" value="404"/}
{assign name="status500" value="500"/}
{if condition="$code ~ $status500"}
<p>Internal server error, for the request <strong>{$request/}</string> </p>
{/if}
{if condition="$code ~ $status404"}
<p> Resourse not found, for the request <strong>{$request/}</string> </p>
{/if}
{if condition="$code ~ $status400"}
<p> Bad request, the request <strong>{$request/}</string> is not valid</p>
{/if}

View File

@@ -1,7 +0,0 @@
<small>
<center>
<p class="text-muted"><a href="#" target="_blank" class="info">API Documentation </a>&nbsp;&nbsp;&nbsp;
<a href="#" target="_blank" class="info">Questions? Comments? Let us know! </a></p>
<p>© Copyright 2014 Eiffel Software -- <a href="#" target="_blank" class="info">Privacy Policy</a>
</center>
</small>

View File

@@ -1,10 +0,0 @@
<meta charset="utf-8">
<link rel="icon" href="{$host/}/static/images/favicon.ico">
<title>Eiffel RESTonCMS</title>
{if condition="$web"}
{include file="master2/optional_styling_css.tpl"/}
{/if}
{if condition="$html"}
{include file="master2/optional_styling_css.tpl"/}
{/if}

View File

@@ -1,2 +0,0 @@
<h1>RESTonCMS</h1>
<p>Tagline</p>

View File

@@ -1,5 +0,0 @@
<!--<ul>
<li class="main-navi-item"><a href="">Nav1</a></li>
<li><a href="">Nav2</a></li>
</ul>
-->

View File

@@ -1,5 +0,0 @@
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
{if condition="$web"}
<script src="{$host/}/static/js/roc.js"></script>
{/if}

View File

@@ -1,9 +0,0 @@
{if condition="$html"}
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
<link rel="stylesheet" href="http://getbootstrap.com/assets/css/docs.min.css">
{/if}
{if condition="$web"}
<link rel="stylesheet" href="{$host/}/static/css/bootstrap.css">
<link rel="stylesheet" href="{$host/}/static/css/dashboard.css">
{/if}

View File

@@ -1,27 +0,0 @@
<nav id="" class="navbar navbar-default navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="{$host/}" rel="home">Rest on CMS</a>
</div>
<div class="collapse navbar-collapse" id="navbarCollapse">
<ul class="nav navbar-nav">
<li class="ListOfNodes"><a title="Nodes" href="{$host/}/nodes" rel="node">List of Nodes</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
{if isset="$user"}
<li><a>{$user/}</a></li>
<li><a title="Node" href="{$host/}/node" rel="node">New Node</a></li>
<li><a title="Logoff" href="{$host/}/basic_auth_logoff" rel="logoff">Logoff</a></li>
{/if}
{unless isset="$user"}
<li><a title="Login" href="{$host/}/basic_auth_login" rel="login">Login</a></li>
<li><a title="Register" href="{$host/}/user" rel="register">Register</a></li>
{/unless}
</ul>
</div>
</div>
</nav>

View File

@@ -1,8 +0,0 @@
{if isset="$user"}
<a title="Logoff" class="" href="{$host/}/logoff">Logoff</a>
{/if}
{unless isset="$user"}
<a title="Login" class="" href="{$host/}/login">Login</a>
<a title="Register" class="" href="{$host/}/Register">Register</a>
{/unless}
<a title="Nodes" class="" href="{$host/}/nodes">List of Nodes</a>

View File

@@ -1,174 +0,0 @@
{if condition="html"}
<!DOCTYPE html>
<html lang="en">
<head>
{include file="master2/head.tpl"/}
</head>
<body>
{/if}
{unless condition="$web"}
<!-- Site Navigation -->
{include file="master2/site_navigation.tpl"/}
{/unless}
{if condition="html"}
<div class="container">
<hr>
<div class="row">
<main class="main">
{/if}
<div class="bs-docs-example">
{if condition="$web"}
<ul id="myTab" class="nav nav-tabs" role="tablist">
<li class=""><a href="#view" role="tab" data-toggle="tab">View</a></li>
<li class="active"><a href="#edit" role="tab" data-toggle="tab">Edit</a></li>
<li class=""><a href="#delete" role="tab" data-toggle="tab">Delete</a></li>
</ul>
{/if}
{if condition="$html"}
<ul id="myTab" class="nav nav-tabs" role="tablist">
<li class=""><a href="#view" role="tab" data-toggle="tab">View</a></li>
<li class="active"><a href="#edit" role="tab" data-toggle="tab">Edit</a></li>
<li class=""><a href="#delete" role="tab" data-toggle="tab">Delete</a></li>
</ul>
{/if}
<div id="myTabContent" class="tab-content">
<div class="tab-pane" id="view">
{if isset="$node"}
<hr>
<div class="container-fluid">
<div class="row" itemscope itemtype="http://schema.org/Article">
<div class="row">
<div class="col-sm-6 col-md-4 col-lg-3"><h1><span itemprop="name">{$node.title/}</span></h1></div>
</div>
<div class="row">
<div class="col-sm-6 col-md-4 col-lg-3"><span itemprop="text">{$node.content/}<span></div>
</div>
</div>
</div>
{/if}
</div>
<div class="tab-pane fade active in" id="edit">
{if isset="$user"}
<hr>
<div class="container-fluid">
<div class="col-xs-12" itemscope itemtype="http://schema.org/Article">
{if isset="$node"}
<form class="form-inline well" action="{$host/}/node/{$node.id/}" itemprop="url" method="POST">
<input type="hidden" name="method" value="PUT">
{/if}
{unless isset="$node"}
<form class="form-inline well" action="{$host/}/node" itemprop="url" method="POST">
{/unless/}
<fieldset>
<legend>Edit Node</legend>
<div class="span3">
<p>Add or Edit a Node</p>
</div>
<div class="row">
<div class="col-xs-1">
{if isset="$node"}
<label><span itemprop="name"><a href="{$host/}/node/{$node.id/}/title" rel="node">Title:</a></span></label>
{/if}
{unless isset="$node"}
<label><span itemprop="name">Title:</span> </label>
{/unless}
</div>
<div class="col-xs-7">
<input id="title" type="text" class="form-control" name="title" placeholder="Title" required value="{$node.title/}"/>
</div>
</div>
<div class="row">
<div class="col-xs-1">
{if isset="$node"}
<label> <span itemprop="description"><a href="{$host/}/node/{$node.id/}/summary" rel="node">Summary:</a></span></label>
{/if}
{unless isset="$node"}
<label> <span itemprop="description">Summary:</span></label>
{/unless}
</div>
<div class="col-xs-7">
<textarea id="summary" rows="3" class="form-control" cols="100" name="summary" placeholder="Node summary" required>{$node.summary/}</textarea>
</div>
</div>
<div class="row">
<div class="col-xs-1">
{if isset="$node"}
<label> <span itemprop="text"><a href="{$host/}/node/{$node.id/}/content" rel="node">Content</a></span> </label>
{/if}
{unless isset="$node"}
<label> <span itemprop="text">Content:</span> </label>
{/unless}
</div>
<div class="col-xs-7">
<textarea id="content" rows="25" cols="100" class="form-control" name="content" placeholder="Node content" required>{$node.content/}</textarea>
</div>
</div>
<div>
<label>
<span>&nbsp;</span>
<input type="Submit" value="Send" />
</label>
</div>
</fieldset>
</form>
</div>
{/if}
</div>
</div>
<div class="tab-pane" id="delete">
{if isset="$user"}
<hr>
<div class="container-fluid">
{if isset="$node"}
<form action="{$host/}/node/{$node.id/}" method="POST" class="">
<input type="hidden" name="method" value="DELETE">
<fieldset>
<legend>Delete Node</legend>
<div>
<label>
<span>&nbsp;</span>
<input type="Submit" value="Delete" />
</label>
</div>
</fieldset>
</form>
{/if}
</div>
{/if}
</div>
</div>
</div>
{if condition="html"}
</main>
</div>
</div>
{/if}
{if condition="html"}
<div id="footer">
<footer class="site-footer">
{include file="master2/footer.tpl"/}
</footer>
</div>
{include file="master2/optional_enhancement_js.tpl"/}
</body>
</html>
{/if}

View File

@@ -1,70 +0,0 @@
{if condition="html"}
<!DOCTYPE html>
<html lang="en">
<head>
{include file="master2/head.tpl"/}
</head>
<body>
{/if}
{unless condition="$web"}
<!-- Site Navigation -->
{include file="master2/site_navigation.tpl"/}
{/unless}
{if condition="html"}
<div class="container">
<hr>
<div class="row">
<main class="main">
{/if}
<div class="container-fluid">
<div class="col-xs-12" itemscope itemtype="http://schema.org/Article">
<form class="form-inline well" action="{$host/}/node/{$id/}/content" method="POST" class="">
<input type="hidden" name="method" value="PUT">
<fieldset>
<legend>Edit Node Content</legend>
<div class="row">
<div class="col-xs-1">
<label> <span itemprop="text">Content:</span> </label>
</div>
<div class="col-xs-7">
<textarea id="content" rows="25" cols="100" class="form-control" name="content" placeholder="Node content" required>{$node_content/}</textarea>
</div>
</div>
<div>
<label>
<span>&nbsp;</span>
<input type="Submit" value="Update" />
</label>
</div>
</fieldset>
</form>
</div>
</div>
{if condition="html"}
</main>
</div>
</div>
{/if}
{if condition="html"}
<div id="footer">
<footer class="site-footer">
{include file="master2/footer.tpl"/}
</footer>
</div>
{include file="master2/optional_enhancement_js.tpl"/}
</body>
</html>
{/if}

View File

@@ -1,71 +0,0 @@
{if condition="html"}
<!DOCTYPE html>
<html lang="en">
<head>
{include file="master2/head.tpl"/}
</head>
<body>
{/if}
{unless condition="$web"}
<!-- Site Navigation -->
{include file="master2/site_navigation.tpl"/}
{/unless}
{if condition="html"}
<div class="container">
<hr>
<div class="row">
<main class="main">
{/if}
<div class="container-fluid">
<div class="col-xs-12" itemscope itemtype="http://schema.org/Article">
<form class="form-inline well" action="{$host/}/node/{$id/}/summary" method="POST">
<input type="hidden" name="method" value="PUT">
<fieldset>
<legend>Edit Node Summary</legend>
<div class="row">
<div class="col-xs-1">
<label> <span itemprop="text">Summary:</span> </label>
</div>
<div class="col-xs-7">
<textarea id="summary" rows="3" cols="80" name="summary" placeholder="Node summary" required>{$node_summary/}</textarea>
</div>
</div>
<div>
<label>
<span>&nbsp;</span>
<input type="Submit" value="Send" />
</label>
</div>
</fieldset>
</form>
</div>
</div>
{if condition="html"}
</main>
</div>
</div>
{/if}
{if condition="html"}
<div id="footer">
<footer class="site-footer">
{include file="master2/footer.tpl"/}
</footer>
</div>
{include file="master2/optional_enhancement_js.tpl"/}
</body>
</html>
{/if}

View File

@@ -1,70 +0,0 @@
{if condition="html"}
<!DOCTYPE html>
<html lang="en">
<head>
{include file="master2/head.tpl"/}
</head>
<body>
{/if}
{unless condition="$web"}
<!-- Site Navigation -->
{include file="master2/site_navigation.tpl"/}
{/unless}
{if condition="html"}
<div class="container">
<hr>
<div class="row">
<main class="main">
{/if}
<div class="container-fluid">
<div class="col-xs-12" itemscope itemtype="http://schema.org/Article">
<form class="form-inline well" action="{$host/}/node/{$id/}/title" method="POST">
<input type="hidden" name="method" value="PUT">
<fieldset>
<legend>Edit Node Title</legend>
<div class="row">
<div class="col-xs-1">
<label> <span itemprop="text">Title:</span> </label>
</div>
<div class="col-xs-7">
<input id="title" type="text" name="title" placeholder="Title" required value="{$node_title/}"/>
</div>
</div>
<div>
<label>
<span>&nbsp;</span>
<input type="Submit" value="Send" />
</label>
</div>
</fieldset>
</form>
</div>
</div>
{if condition="html"}
</main>
</div>
</div>
{/if}
{if condition="html"}
<div id="footer">
<footer class="site-footer">
{include file="master2/footer.tpl"/}
</footer>
</div>
{include file="master2/optional_enhancement_js.tpl"/}
</body>
</html>
{/if}

View File

@@ -1,52 +0,0 @@
{if condition="html"}
<!DOCTYPE html>
<html lang="en">
<head>
{include file="master2/head.tpl"/}
</head>
<body>
{/if}
{unless condition="$web"}
<!-- Site Navigation -->
{include file="master2/site_navigation.tpl"/}
{/unless}
{if condition="html"}
<div class="container">
<hr>
<div class="row">
<main class="main">
{/if}
<div itemscope itemtype="http://schema.org/ItemList">
<h2 itemprop="name">List nodes</h2><br>
<meta itemprop="itemListOrder" content="Descending" />
{foreach from="$nodes" item="item"}
<div class="page-header">
<h3><span itemprop="itemListElement"><a href="{$host/}/node/{$item.id/}" rel="node"><strong>{$item.title/}</strong></a></span> <small>{$item.summary/} -{$item.publication_date_output/} </small></h3>
</div>
{/foreach}
</div>
{if condition="html"}
</main>
</div>
</div>
{/if}
{if condition="html"}
<div id="footer">
<footer class="site-footer">
{include file="master2/footer.tpl"/}
</footer>
</div>
{include file="master2/optional_enhancement_js.tpl"/}
</body>
</html>
{/if}

View File

@@ -1,100 +0,0 @@
{if condition="html"}
<!DOCTYPE html>
<html lang="en">
<head>
{include file="master2/head.tpl"/}
</head>
<body>
{/if}
{unless condition="$web"}
<!-- Site Navigation -->
{include file="master2/site_navigation.tpl"/}
{/unless}
{if condition="html"}
<div class="container">
<hr>
<div class="row">
<main class="main">
{/if}
<div class="container-fluid">
<div class="col-xs-12" itemscope itemtype="http://schema.org/Person">
<form class="form-inline well" action="{$host/}/user" data-rel="user-register" method="POST" >
<fieldset>
<legend>Register</legend>
<div class="span3">
<p>Register new user</p>
</div>
<div class="row">
<div class="col-xs-2">
<label><span itemprop="name">Username:</span> </label>
</div>
<div class="col-xs-7">
<input id="username" type="text" name="username" placeholder="Username" required/>
</div>
</div>
<div class="row" itemscope itemtype="http://schema.org/Text">
<div class="col-xs-2">
<label><span itemprop="accessCode">Password:</span> </label>
</div>
<div class="col-xs-7">
<input id="password" type="password" name="password" placeholder="Password" required/>
</div>
</div>
<div class="row" itemscope itemtype="http://schema.org/Text">
<div class="col-xs-2">
<label><span itemprop="accessCode">Re-type Password:</span> </label>
</div>
<div class="col-xs-7">
<input id="check_password" type="password" name="check_password" placeholder="Password" required/>
</div>
</div>
<div class="row">
<div class="col-xs-2">
<label><span itemprop="email">Email:</span> </label>
</div>
<div class="col-xs-7">
<input id="email" type="email" name="email" placeholder="Email" required/>
</div>
s</div>
<div>
<label>
<span>&nbsp;</span>
<input type="Submit" value="Send" />
</label>
</div>
</fieldset>
</form>
</div>
</div>
{if condition="html"}
</main>
</div>
</div>
{/if}
{if condition="html"}
<div id="footer">
<footer class="site-footer">
{include file="master2/footer.tpl"/}
</footer>
</div>
{include file="master2/optional_enhancement_js.tpl"/}
</body>
</html>
{/if}

View File

@@ -1,9 +0,0 @@
name=api
engine=smarty
author=jvelilla
version=0.1
regions[header] = Header
regions[content] = Content
regions[footer] = Footer
regions[first_sidebar] = first sidebar
regions[second_sidebar] = second sidebar

View File

@@ -1,84 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>ROC- Layout with defualt Regions</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<style type="text/css">
</style>
<!-- Latest compiled and minified CSS -->
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap-theme.min.css">
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
</head>
<body>
<head>
<title>{$head_title/}</title>
</head>
<body>
<!-- Page Top -->
{if isset="$region_top"}
{$region_top/}
{/if}
<!-- Body -->
<div class='container-fluid'>
<!-- Page Header -->
<div id="header">
{if isset="$page.primary_nav"}
{$page.primary_nav/}
{/if}
</div>
<!-- General Page Content -->
<div id='content' class='row-fluid'>
<!-- Left Sidebar sidebar_first -->
{unless empty="$page.region_sidebar_first"}
<div style="float: left;">
{$page.region_sidebar_first/}
</div>
{/unless}
<!-- Highlighted, Help, Content -->
<div class='span8 main'>
<!-- Highlighted Section -->
{$page.region_highlighted/}
<!-- Help Section -->
{$page.region_help/}
<!-- Main Content Section -->
{unless empty="$page_title"}<h1 class="page-title">{$page_title/}</h1>{/unless}
{$page.region_content/}
</div>
<!-- Right Sidebar sidebar_second-->
{unless empty="$page.region_sidebar_second"}
<div style="float: right;">
{$page.region_sidebar_second/}
</div>
{/unless}
</div>
</div>
<!--Page footer -->
{$page.region_footer/}
<!-- Page Bottom -->
{$page.region_bottom/}
</body>
<script type="text/javascript">
</script>
</body>
</html>

View File

@@ -1,108 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>ROC- Layout with defualt Regions</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet">
<style type="text/css">
</style>
<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<script src="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>
</head>
<body>
<head>
<title>ROC CMS - A responsive layout</title>
</head>
<body>
<!-- Page Top -->
<!-- Page Header -->
<div class='container-fluid'>
<h1>ROC Layout with Defaul Regions</h1>
<div class="navbar navbar-default navbar-fixed-top" role="navigation">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
</button>
<a class="navbar-brand" href="https://www2.eiffel.com/beta" itemprop="home" rel="home">Eiffel Support Site</a>
</div>
<div class="navbar-collapse collapse" itemscope="itemscope" itemtype="https://www2.eiffel.com/beta/profile/esa_api.xml#report" >
<ul class="nav navbar-nav navbar-left">
<li><a href="https://www2.eiffel.com/beta/reports" class="active" itemprop="all" rel="all">Reports</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li><a href="https://www2.eiffel.com/beta/register" itemprop="register" rel="register">Register</a></li>
<!--<li><a class="login pull-right" data-toggle="modal" data-target="#myModalSignIn">Sign In</a></li> <! Custome Modal -->
<li id="login_pe" ><a href="https://www2.eiffel.com/beta/login" itemprop="login" rel="login">Sign In</a></li> <!-- Custome Modal -->
</ul>
<!--form class="navbar-form navbar-right">
<input type="text" class="form-control" placeholder="Search..."/>
</form -->
</div>
</div>
<div id='content' class='row-fluid'>
<!-- Highlighted-->
<!-- Left Side Bard sidebar_first -->
<div class='span2 sidebar'>
<h3>Left Sidebar</h3>
<ul class="nav nav-tabs nav-stacked">
<li><a href='#'>Another Link 1</a></li>
<li><a href='#'>Another Link 2</a></li>
<li><a href='#'>Another Link 3</a></li>
</ul>
</div>
<!-- Highlighted, Help, Content -->
<div class='span8 main'>
<h1>Highlighted Section</h1>
<h2>Help Section</h2>
<h2>Main Content Section</h2>
<p>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.<p>
<p>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.</p>
</div>
<!-- Left Side Bard sidebar_second-->
<div class='span2 sidebar'>
<h3>Right Sidebar</h3>
<ul class="nav nav-tabs nav-stacked">
<li><a href='#'>Another Link 1</a></li>
<li><a href='#'>Another Link 2</a></li>
<li><a href='#'>Another Link 3</a></li>
</ul>
</div>
</div>
</div>
<!--Page footer -->
<div id="footer">
<small>
<center>
<p class="text-muted"><a href="#" target="_blank" class="info">ROC Documentation </a>&nbsp;&nbsp;&nbsp;
<a href="http://www.eiffel.com/company/contact/" target="_blank" class="info">Questions? Comments? Let us know! </a></p>
<p>© Copyright 2014 Eiffel Software -- <a href="#" target="_blank" class="info">Privacy Policy</a>
</center>
</small>
</div>
<!-- Page Bottom -->
</body>
<script type="text/javascript">
</script>
</body>
</html>

View File

@@ -1,135 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>ROC- Layout with defualt Regions</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap.min.css">
<style type="text/css">
</style>
<!-- Latest compiled and minified CSS -->
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/css/bootstrap-theme.min.css">
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
</head>
<body>
<head>
<title>ROC CMS - A responsive layout</title>
</head>
<body>
<!-- Page Top -->
<!-- Page Header -->
<!-- <div class='container-fluid'>
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> <span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button> <a class="navbar-brand" href="#">Eiffel ROC</a>
</div>
<ul class="nav navbar-nav navbar-left">
<li> <a href="#about">Home</a>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li> <a href="#about">About</a>
</li>
<li> <a href="#services">Service</a>
</li>
<li> <a href="#portfolio" class="">Portfolio</a>
</li>
</ul>
</div>
-->
<div class="container-fluid">
<div class="navbar navbar-default" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
</button>
<a class="navbar-brand" href="https://www2.eiffel.com/beta" itemprop="home" rel="home">Eiffel Support Site</a>
</div>
<div class="navbar-collapse collapse" itemscope="itemscope" itemtype="https://www2.eiffel.com/beta/profile/esa_api.xml#report" >
<ul class="nav navbar-nav navbar-left">
<li><a href="https://www2.eiffel.com/beta/reports" class="active" itemprop="all" rel="all">Reports</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li><a href="https://www2.eiffel.com/beta/register" itemprop="register" rel="register">Register</a></li>
<li id="login_pe" ><a href="https://www2.eiffel.com/beta/login" itemprop="login" rel="login">Sign In</a></li> <!-- Custome Modal -->
</ul>
</div>
</div>
</div>
<div id='content' class='row-fluid'>
<!-- Highlighted-->
<!-- Left Side Bard sidebar_first -->
<div class="sidebar col-sm-2 col-md-2">
<h3>Left Sidebar</h3>
<ul class="nav nav-tabs nav-stacked">
<li><a href="#">Another Link 1</a></li>
<li><a href="#">Another Link 2</a></li>
<li><a href="#">Another Link 3</a></li>
</ul>
</div>
<!-- Highlighted, Help, Content -->
<div class="main col-sm-8 col-md-8">
<h1>Highlighted Section</h1>
<h2>Help Section</h2>
<h2>Main Content Section</h2>
<p>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.<p>
<p>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.</p>
</div>
<!-- Left Side Bard sidebar_second-->
<div class="sidebar col-sm-2 col-md-2">
<h3>Right Sidebar</h3>
<ul class="nav nav-tabs nav-stacked">
<li><a href="#">Another Link 1</a></li>
<li><a href="#">Another Link 2</a></li>
<li><a href="#">Another Link 3</a></li>
</ul>
</div>
</div>
</div>
<!--Page footer -->
<div id="footer">
<small>
<center>
<p class="text-muted"><a href="#" target="_blank" class="info">ROC Documentation </a>&nbsp;&nbsp;&nbsp;
<a href="http://www.eiffel.com/company/contact/" target="_blank" class="info">Questions? Comments? Let us know! </a></p>
<p>© Copyright 2014 Eiffel Software -- <a href="#" target="_blank" class="info">Privacy Policy</a>
</center>
</small>
</div>
<!-- Page Bottom -->
</body>
<script type="text/javascript">
</script>
</body>
</html>

View File

@@ -1,12 +0,0 @@
{include file="tpl/page-header.tpl"/}
<div id="main-wrapper">
<div id="main">
<div id="first_sidebar" class="sidebar {if isset="$first_sidebar_css_class"}{$first_sidebar_css_class/}{/if}">{if isset="$first_sidebar"}{$first_sidebar/}{/if}</div>
<div id="content" class="{if isset="$content_css_class"}{$content_css_class/}{/if}">
Welcome ... this is the front page
{if isset="$content"}{$content/}{/if}
</div>
<div id="second_sidebar" class="sidebar {if isset="$second_sidebar_css_class"}{$second_sidebar_css_class/}{/if}">{if isset="$second_sidebar"}{$second_sidebar/}{/if}</div>
</div>
</div>
{include file="tpl/page-footer.tpl"/}

View File

@@ -1,11 +0,0 @@
{include file="tpl/page-header.tpl"/}
<div id="main-wrapper">
<div id="main">
<div id="first_sidebar" class="sidebar {if isset="$first_sidebar_css_class"}{$first_sidebar_css_class/}{/if}">{if isset="$first_sidebar"}{$first_sidebar/}{/if}</div>
<div id="content" class="{if isset="$content_css_class"}{$content_css_class/}{/if}">
{if isset="$content"}{$content/}{/if}
</div>
<div id="second_sidebar" class="sidebar {if isset="$second_sidebar_css_class"}{$second_sidebar_css_class/}{/if}">{if isset="$second_sidebar"}{$second_sidebar/}{/if}</div>
</div>
</div>
{include file="tpl/page-footer.tpl"/}

View File

@@ -1,91 +0,0 @@
/*
* EWF CMS javascript based on JQuery
*/
/**
* Override jQuery.fn.init to guard against XSS attacks.
*
* See http://bugs.jquery.com/ticket/9521
*/
(function () {
var jquery_init = jQuery.fn.init;
jQuery.fn.init = function (selector, context, rootjQuery) {
// If the string contains a "#" before a "<", treat it as invalid HTML.
if (selector && typeof selector === 'string') {
var hash_position = selector.indexOf('#');
if (hash_position >= 0) {
var bracket_position = selector.indexOf('<');
if (bracket_position > hash_position) {
throw 'Syntax error, unrecognized expression: ' + selector;
}
}
}
return jquery_init.call(this, selector, context, rootjQuery);
};
jQuery.fn.init.prototype = jquery_init.prototype;
})();
var EWFCMS = EWFCMS || { };
EWFCMS.toggleFieldset = function(fieldset) {
if ($(fieldset).is('.collapsed')) {
var content = $('> div:not(.action)', fieldset);
$(fieldset).removeClass('collapsed');
content.hide();
content.slideDown( {
duration: 'fast',
easing: 'linear',
complete: function() {
//Drupal.collapseScrollIntoView(this.parentNode);
this.parentNode.animating = false;
$('div.action', fieldset).show();
},
step: function() {
// Scroll the fieldset into view
//Drupal.collapseScrollIntoView(this.parentNode);
}
});
} else {
var content = $('> div:not(.action)', fieldset).slideUp('fast', function() {
$(this.parentNode).addClass('collapsed');
this.parentNode.animating = false;
});
}
};
jQuery(document).ready(function(){
//$('.collapsed').hide();
$('fieldset.collapsible > legend').each(function() {
var fieldset = $(this.parentNode);
// turn legen into clickable link and wrap contents
var text = this.innerHTML;
$(this).empty()
.append($('<a href="#">'+ text + '</a>').click(function() {
var fieldset = $(this).parents('fieldset:first')[0];
if (!fieldset.animating) {
fieldset.animating = true;
EWFCMS.toggleFieldset(fieldset);
}
return false;
}
))
.after($('<div class="fieldset-wrapper"></div>')
.append(fieldset.children(':not(legend):not(.action)')))
.addClass('collapse-processed');
});
$('fieldset.collapsed').each(function() {
$(this).removeClass('collapsed');
EWFCMS.toggleFieldset(this);
});
});
jQuery(document).ready(function(){
$('#tabs').tabs();
});
//jQuery(document).ready(function(){
//$('#second_sidebar').hide();
//});

Binary file not shown.

Before

Width:  |  Height:  |  Size: 786 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 B

View File

@@ -1,251 +0,0 @@
body { margin: 0; background-color: #eeeeff;}
div#header { background-color: #003; color: #fff; border: solid 1px #003; padding: 0px; margin: 0px;}
div#header img#logo { float: left; margin: 5px 15px 5px 10px; }
div#header div#title {font-size: 180%; font-weight: bold; margin-top: 10px; }
ul.horizontal {
list-style-type: none;
}
ul.horizontal li {
display: inline;
padding: 0 5px 0 5px;
}
div#menu-bar li.active {
border: solid 1px #ff0;
color: #ff0;
}
div#menu-bar li:hover {
background-color: #fff;
color: #00f;
}
div#menu-bar li a {
text-decoration: none;
color: #fff;
}
div#menu-bar li:hover a {
color: #00f;
font-style: bold;
}
div#primary-tabs li {
color: #00f;
padding: 2px 5px 2px 5px;
background-color: #eee;
border: solid 1px #ccf;
}
div#primary-tabs li.active {
padding: 2px 7px 1px 7px;
border-top: solid 2px #99f;
border-left: solid 1px #99f;
border-right: solid 1px #99f;
border-bottom: 0;
background-color: #fff;
color: #00f;
}
div#primary-tabs li:hover {
background-color: #fff;
color: #00f;
}
div#primary-tabs li a {
text-decoration: none;
color: #00f;
}
div#primary-tabs li:hover a {
color: #00f;
font-style: bold;
}
div#menu-first { margin-left: 20%; color: #ccf; background-color: #003; }
div#menu-first a { color: #ccf; }
div#menu-second { color: #99f; background-color: #333; }
div#menu-second a { color: #99f; }
div#main-wrapper {
clear: both;
display: block;
height: 0;
}
div#main { margin: 0; padding: 0; clear: both; height:0; display: block; }
div#content {
padding: 5px 3px 5px 20px;
margin-top: 10px;
min-width: 60%;
display: inline;
float: left;
position: relative;
background-color: #ffffff;
padding-bottom: 30px;
}
div#first_sidebar {
width: 20%;
margin: 5px;
padding: 5px;
display: inline;
float: left;
position: relative;
}
div#second_sidebar {
width: 20%;
margin: 5px;
padding: 5px;
display: inline;
float: left;
position: relative;
background-color: #eee;
}
div.sidebar div.block {
margin-bottom: 5px;
padding: 0;
border: dotted 1px #999;
background-color: #fff;
}
div.sidebar div.block div.title {
padding: 3px 3px 3px 3px;
font-weight: bold;
background-color: #dedede;
border-bottom: dotted 1px #999;
}
div.sidebar div.block div.inside {
margin: 3px;
}
div#footer { margin: 10px 0 10px 0; clear: both; display: block; text-align: center; padding: 10px; border-top: solid 1px #00f; color: #fff; background-color: #333;}
div#footer a { color: #ff0; }
form div.error {
border-top: dotted 1px #f00;
border-bottom: dotted 1px #f00;
border-left: solid 3px #f00;
}
div.node div.title {
font-weight: bold;
font-size: 110%;
border-bottom: dotted 1 px #009;
}
div.description {
font-style: italic;
font-color: #999;
}
div.node-wrapper {
margin: 5px 2px 5px 2px;
border: dotted 1px #dddddd;
padding: 5px 3px 5px 3px;
}
div.node div.title {
font-weight: bold;
font-size: 110%;
border-bottom: dotted 1 px #009;
float: left;
}
div.node div.description {
text-align: right;
}
div.node div.inner {
padding: 5px 5px 5px 10px;
border-top: dotted 1px #dddddd;
}
form#user-login {
border: dotted 1px #099;
display: inline-block;
padding: 10px;
margin: 10px;
}
form#user-login>div {
margin-bottom: 10px;
}
form#user-login .input {
float: left;
}
form#user-login img.logo {
}
div#message {
border: solid 1px #fc0;
background-color: #fed;
color: #000;
padding: 5px;
margin: 5px;
}
div#message li {
padding-left: 5px;
margin-left: 3px;
}
div#message li.success {
color: #003300;
background-color: #ccffcc;
}
div#message li.error {
color: #330000;
background-color: #ff9494;
}
div#message li.warning {
color: #aa2200;
background-color: #ffcc99;
}
div.columns {
margin-top: 10px;
display: inline-block;
clear: both;
}
div.columns>* {
padding-left: 10px;
padding-top: 5px;
border-top: dotted 1px #999;
border-left: dotted 1px #999;
margin-left: 1px;
margin-right: 10px;
float: left;
}
/* Link */
a {
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
div.menu ul.vertical {
margin: 0;
padding-left: 10px;
list-style-type: none;
}
div.menu ul.vertical ul {
border-left: solid 3px #eee;
list-style-type: none;
margin: 0;
padding-left: 5px;
margin-left: 5px;
margin-bottom: 5px;
}
/* Fieldset and collapsible */
fieldset.collapsible legend a {
padding-left: 15px;
background: url(menu-expanded.png) 5px 75% no-repeat;
}
fieldset.collapsed legend a {
padding-left: 15px;
background: url(menu-collapsed.png) 5px 50% no-repeat;
}
fieldset.collapsed {
border: none;
border-top: dotted 1px #000;
}

View File

@@ -1,10 +0,0 @@
name=smarty
engine=smarty
author=jfiat
version=0.1
;template_dir=templates
regions[header] = Header
regions[content] = Content
regions[footer] = Footer
regions[first_sidebar] = first sidebar
regions[second_sidebar] = second sidebar

View File

@@ -1,6 +0,0 @@
<div id="footer">{if isset="$footer"}{$footer/}{/if}</div>
</div>
</div>
{if isset="$page_bottom"}{$page_bottom/}{/if}
</body>
</html>

View File

@@ -1,14 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN" "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="{$language/}" lang="{$language/}" version="XHTML+RDFa 1.0" dir="ltr">
<head>
{if isset="$head"}{$head/}{/if}
<title>{$head_title/}</title>
{if isset="$styles"}{$styles/}{/if}
{if isset="$scripts"}{$scripts/}{/if}
{if isset="$head_lines"}{$head_lines/}{/if}
</head>
<div id="page-wrapper">
<div id="page">
<div id="header">
{$header/}
</div>

View File

@@ -2,8 +2,8 @@ note
description: "[
application service
]"
date: "$Date$"
revision: "$Revision$"
date: "$Date: 2015-02-09 22:29:56 +0100 (lun., 09 févr. 2015) $"
revision: "$Revision: 96596 $"
class
EWF_ROC_SERVER
@@ -23,7 +23,7 @@ inherit
REFACTORING_HELPER
ARGUMENTS
SHARED_EXECUTION_ENVIRONMENT
SHARED_LOGGER
@@ -41,26 +41,24 @@ feature {NONE} -- Initialization
initialize
-- Initialize current service.
do
-- Launcher
Precursor
create {WSF_SERVICE_LAUNCHER_OPTIONS_FROM_INI} service_options.make_from_file ("demo.ini")
initialize_cms (cms_setup)
-- CMS
initialize_cms
end
feature -- Service
cms_service: CMS_SERVICE
-- cms service.
-- cms service.
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
do
cms_service.execute (req, res)
end
feature -- Layout
layout: CMS_LAYOUT
-- cms layout.
feature {NONE} -- Launch operation
launcher: APPLICATION_LAUNCHER
@@ -71,7 +69,7 @@ feature {NONE} -- Launch operation
l_message: STRING
do
if not l_retry then
log.write_debug (generator + ".launch")
write_debug_log (generator + ".launch")
launcher.launch (a_service, opts)
else
-- error hanling.
@@ -91,8 +89,8 @@ feature {NONE} -- Launch operation
l_message.append ("The application crash without available information")
l_message.append ("%N%N")
end
-- send email shutdown
log.write_debug (generator + ".launch shutdown")
-- notify shutdown
write_debug_log (generator + ".launch shutdown")
end
rescue
l_retry := True
@@ -101,29 +99,29 @@ feature {NONE} -- Launch operation
feature -- CMS Initialization
cms_setup: CMS_CUSTOM_SETUP
do
if attached separate_character_option_value ('d') as l_dir then
log.write_debug (generator + ".cms_setup using a command line argument -d " + l_dir )
create layout.make_with_path (create {PATH}.make_from_string (l_dir))
else
log.write_debug (generator + ".cms_setup using current directory" )
create layout.make_default
end
create Result.make (layout)
setup_storage (Result)
end
initialize_cms (a_setup: CMS_SETUP)
initialize_cms
local
cms: CMS_SERVICE
api: CMS_API
l_setup: CMS_DEFAULT_SETUP
utf: UTF_CONVERTER
cms_env: CMS_ENVIRONMENT
do
log.write_debug (generator + ".initialize_cms")
setup_modules (a_setup)
create api.make (a_setup)
create cms.make (api)
cms_service := cms
-- Application Environment initialization
if attached execution_environment.arguments.separate_character_option_value ('d') as l_dir then
create cms_env.make_with_directory_name (l_dir)
else
create cms_env.make_default
end
initialize_logger (cms_env)
-- CMS Setup
write_debug_log (generator + ".initialize_cms / SETUP based directory=%"" + utf.escaped_utf_32_string_to_utf_8_string_8 (cms_env.path.name) + "%"")
create l_setup.make (cms_env)
-- CMS
write_debug_log (generator + ".initialize_cms / CMS")
setup_storage (l_setup)
setup_modules (l_setup)
create cms_service.make (l_setup)
end
feature -- CMS setup
@@ -133,20 +131,35 @@ feature -- CMS setup
local
m: CMS_MODULE
do
create {BASIC_AUTH_MODULE} m.make
create {NODE_MODULE} m.make (a_setup)
m.enable
a_setup.modules.extend (m)
a_setup.register_module (m)
create {BASIC_AUTH_MODULE} m.make
if not a_setup.module_with_same_type_registered (m) then
m.enable
a_setup.register_module (m)
end
create {CMS_DEBUG_MODULE} m.make
m.enable
a_setup.register_module (m)
create {CMS_DEMO_MODULE} m.make
m.enable
a_setup.modules.extend (m)
a_setup.register_module (m)
create {CMS_BLOG_MODULE} m.make
m.enable
a_setup.register_module (m)
end
setup_storage (a_setup: CMS_SETUP)
-- Setup storage by declaring storage builder.
do
debug ("refactor_fixme")
to_implement ("To implement custom storage")
end
-- a_setup.storage_drivers.force (create {CMS_STORAGE_MYSQL_BUILDER}.make, "mysql")
a_setup.storage_drivers.force (create {CMS_STORAGE_SQLITE_BUILDER}.make, "sqlite")
end
end

13
library/app_env/Readme.md Normal file
View File

@@ -0,0 +1,13 @@
Application Environment Library
===============================
Define a generic application environment to be re-used by different applications.
site/
doc/
logs/
www/
assets
template
theme
config/

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="app_env" uuid="7AE9E48B-5A15-43F8-B99A-04F4185DED6B" library_target="app_env">
<description>Application Environment (layout, configuration, logger, database, ...)</description>
<target name="app_env">
<root all_classes="true"/>
<option warning="true" void_safety="all">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<setting name="console_application" value="true"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json-safe.ecf" readonly="false"/>
<library name="logging" location="$ISE_LIBRARY\library\runtime\logging\logging-safe.ecf"/>
<library name="thread" location="$ISE_LIBRARY\library\thread\thread-safe.ecf"/>
<cluster name="src" location=".\src\" recursive="true">
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
</cluster>
</target>
</system>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="app_env" uuid="7AE9E48B-5A15-43F8-B99A-04F4185DED6B" library_target="app_env">
<description>Application Environment (layout, configuration, logger, database, ...)</description>
<target name="app_env">
<root all_classes="true"/>
<option warning="true" void_safety="none">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<setting name="console_application" value="true"/>
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json.ecf" readonly="false"/>
<library name="logging" location="$ISE_LIBRARY\library\runtime\logging\logging.ecf"/>
<library name="thread" location="$ISE_LIBRARY\library\thread\thread.ecf"/>
<cluster name="src" location=".\src\" recursive="true">
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
</cluster>
</target>
</system>

View File

@@ -1,6 +1,6 @@
note
description: "[
Application layout
Application environment (layout, ...)
Related to file system locations such as
- configuration locations
- application
@@ -11,15 +11,19 @@ note
- templates (html, Collection+JSON, ...)
- ...
]"
date: "$Date$"
revision: "$Revision$"
date: "$Date: 2015-02-05 10:25:53 +0100 (jeu., 05 févr. 2015) $"
revision: "$Revision: 96584 $"
class
APPLICATION_LAYOUT
APPLICATION_ENVIRONMENT
inherit
SHARED_EXECUTION_ENVIRONMENT
create
make_default,
make_with_path
make_with_path,
make_with_directory_name
feature {NONE} -- Initialization
@@ -37,6 +41,34 @@ feature {NONE} -- Initialization
-- Create a layour based on a path `p'.
do
path := p.absolute_path.canonical_path
initialize_name
end
make_with_directory_name (a_dirname: READABLE_STRING_GENERAL)
-- Create a layour based on a path `p'.
do
make_with_path (create {PATH}.make_from_string (a_dirname))
end
initialize_name
-- Initialize `name'.
local
p: PATH
s: STRING_32
do
create p.make_from_string (execution_environment.arguments.command_name)
if attached p.entry as e then
p := e
end
create s.make_from_string (p.name)
if attached p.extension as l_extension then
s.remove_tail (l_extension.count + 1)
end
if s.is_whitespace then
set_name ({STRING_8} "app")
else
set_name (s)
end
end
feature -- Access
@@ -44,6 +76,17 @@ feature -- Access
path: PATH
-- Root location.
name: IMMUTABLE_STRING_32
-- Application name, default is "app"
feature -- Change
set_name (a_name: READABLE_STRING_GENERAL)
-- Set `name' from `a_name'.
do
create name.make_from_string_general (a_name)
end
feature -- Access: internal
config_path: PATH
@@ -163,6 +206,6 @@ feature {NONE} -- Implementation
-- Directory for templates (HTML, etc).
;note
copyright: "2011-2014, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
copyright: "2011-2015, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end

View File

@@ -0,0 +1,23 @@
note
description: "See {APPLICATION_ENVIRONMENT}."
date: "$Date$"
revision: "$Revision$"
class
APPLICATION_LAYOUT
obsolete
"Use APPLICATION_ENVIRONMENT [April/2015]"
inherit
APPLICATION_ENVIRONMENT
create
make_default,
make_with_path,
make_with_directory_name
note
copyright: "2011-2015, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end

View File

@@ -0,0 +1,119 @@
note
description: "Provide access to json configuration"
date: "$Date: 2015-01-27 19:15:02 +0100 (mar., 27 janv. 2015) $"
revision: "$Revision: 96542 $"
class
APPLICATION_JSON_CONFIGURATION_HELPER
feature -- Application Configuration
new_smtp_configuration (a_path: PATH): READABLE_STRING_32
-- Build a new database configuration.
local
l_parser: JSON_PARSER
do
Result := ""
if attached json_file_from (a_path) as json_file then
l_parser := new_json_parser (json_file)
l_parser.parse_content
if
l_parser.is_valid and then
attached {JSON_OBJECT} l_parser.parsed_json_value as jv and then
attached {JSON_OBJECT} jv.item ("smtp") as l_smtp and then
attached {JSON_STRING} l_smtp.item ("server") as l_server
then
Result := l_server.item
end
end
end
new_database_configuration (a_path: PATH): detachable DATABASE_CONFIGURATION
-- Build a new database configuration.
local
l_parser: JSON_PARSER
do
if attached json_file_from (a_path) as json_file then
l_parser := new_json_parser (json_file)
l_parser.parse_content
if
l_parser.is_valid and then
attached {JSON_OBJECT} l_parser.parsed_json_value as jv and then
attached {JSON_OBJECT} jv.item ("database") as l_database and then
attached {JSON_OBJECT} l_database.item ("datasource") as l_datasource and then
attached {JSON_STRING} l_datasource.item ("driver") as l_driver and then
attached {JSON_STRING} l_datasource.item ("environment") as l_envrionment and then
attached {JSON_OBJECT} l_database.item ("environments") as l_environments and then
attached {JSON_OBJECT} l_environments.item (l_envrionment.item) as l_environment_selected and then
attached {JSON_STRING} l_environment_selected.item ("connection_string") as l_connection_string
then
create Result.make (l_driver.item, l_connection_string.unescaped_string_32)
end
end
end
new_logger_level_configuration (a_path: PATH): READABLE_STRING_32
-- Retrieve a new logger level configuration.
-- By default, level is set to `DEBUG'.
local
l_parser: JSON_PARSER
do
Result := "DEBUG"
if attached json_file_from (a_path) as json_file then
l_parser := new_json_parser (json_file)
l_parser.parse_content
if
l_parser.is_valid and then
attached {JSON_OBJECT} l_parser.parsed_json_value as jv and then
attached {JSON_OBJECT} jv.item ("logger") as l_logger and then
attached {JSON_STRING} l_logger.item ("level") as l_level
then
Result := l_level.item
end
end
end
new_database_configuration_test (a_path: PATH): detachable DATABASE_CONFIGURATION
-- Build a new database configuration for testing purposes.
local
l_parser: JSON_PARSER
do
if attached json_file_from (a_path) as json_file then
l_parser := new_json_parser (json_file)
l_parser.parse_content
if
l_parser.is_valid and then
attached {JSON_OBJECT} l_parser.parsed_json_value as jv and then
l_parser.is_parsed and then
attached {JSON_OBJECT} jv.item ("database") as l_database and then
attached {JSON_OBJECT} l_database.item ("datasource") as l_datasource and then
attached {JSON_STRING} l_datasource.item ("driver") as l_driver and then
attached {JSON_STRING} l_datasource.item ("environment") as l_envrionment and then
attached {JSON_STRING} l_datasource.item ("trusted") as l_trusted and then
attached {JSON_OBJECT} l_database.item ("environments") as l_environments and then
attached {JSON_OBJECT} l_environments.item ("test") as l_environment_selected and then
attached {JSON_STRING} l_environment_selected.item ("connection_string") as l_connection_string and then
attached {JSON_STRING} l_environment_selected.item ("name") as l_name
then
create Result.make (l_driver.item, l_connection_string.unescaped_string_8)
end
end
end
feature {NONE} -- JSON
json_file_from (a_fn: PATH): detachable STRING
do
Result := (create {JSON_FILE_READER}).read_json_from (a_fn.name.out)
end
new_json_parser (a_string: STRING): JSON_PARSER
do
create Result.make_with_string (a_string)
end
note
copyright: "2011-2015, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end

View File

@@ -0,0 +1,97 @@
note
description: "Object that represent Database configuration settings"
date: "$Date: 2015-02-09 22:29:56 +0100 (lun., 09 févr. 2015) $"
revision: "$Revision: 96596 $"
class
DATABASE_CONFIGURATION
create
make
feature {NONE} -- Initialization
make (a_driver: READABLE_STRING_32; a_connection: READABLE_STRING_32)
-- Create a database configuration setting: `driver' with `a_driver',
-- `database_string' with `a_connection'.
do
driver := a_driver
database_string := a_connection
ensure
driver_set: driver = a_driver
server_set: database_string = a_connection
end
feature -- Access
driver: READABLE_STRING_32
--Database driver.
database_string: READABLE_STRING_32
-- Database connection.
connection_string: READABLE_STRING_32
-- Connection string
do
Result := {STRING_32} "Driver={" + driver + {STRING_32} "};" + database_string
end
item (a_param: READABLE_STRING_GENERAL): detachable READABLE_STRING_32
local
s: READABLE_STRING_32
lower_s: READABLE_STRING_32
i,j: INTEGER
k: STRING_32
do
create k.make_from_string_general (a_param)
k.to_lower
s := database_string
lower_s := s.as_lower
i := lower_s.substring_index (k + {STRING_32} "=", 1)
if i > 0 then
if i = 1 or else s[i-1] = ';' then
j := s.index_of (';', i + k.count + 1)
if j = 0 then
j := s.count + 1
end
Result := s.substring (i + k.count + 1, j - 1)
end
end
end
server_name: detachable READABLE_STRING_32
do
Result := item ("Server")
end
port: INTEGER
do
if
attached item ("Port") as l_port and then
l_port.is_integer
then
Result := l_port.to_integer
end
end
database_name: detachable READABLE_STRING_32
do
Result := item ("Database")
end
user_id: detachable READABLE_STRING_32
do
Result := item ("Uid")
end
user_password: detachable READABLE_STRING_32
do
Result := item ("Pwd")
end
note
copyright: "2011-2015, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end

View File

@@ -1,7 +1,7 @@
note
description: "Object that represents Logger configuration settings"
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
revision: "$Revision: 95678 $"
date: "$Date: 2015-02-03 19:11:23 +0100 (mar., 03 févr. 2015) $"
revision: "$Revision: 96575 $"
class
LOGGER_CONFIGURATION
@@ -29,6 +29,7 @@ feature -- Initialization
do
backup_count := 4
level := Log_debug
location := Void
ensure then
backup_count_set: backup_count = 4
level_set: level = Log_debug
@@ -36,6 +37,9 @@ feature -- Initialization
feature -- Access
location: detachable PATH
-- Location for logs files, if none use default logs location.
backup_count: NATURAL
-- Max number of backup files.
-- When 0, no backup files are created, and the log file is simply truncated when it becomes larger than `max_file_size'.
@@ -46,6 +50,21 @@ feature -- Access
feature -- Element Change
set_location (a_location: detachable PATH)
-- Set `location' to `a_location'.
do
location := a_location
ensure
location_set: a_location ~ location
end
set_location_with_string (a_location: READABLE_STRING_GENERAL)
require
a_location /= Void and then not a_location.is_whitespace
do
set_location (create {PATH}.make_from_string (a_location))
end
set_backup_count (a_backup: NATURAL)
-- Set backup_count to `a_backup'.
do
@@ -78,6 +97,6 @@ feature -- Element Change
end
end
note
copyright: "2011-2014, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
copyright: "2011-2015, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end

View File

@@ -56,10 +56,10 @@ feature -- Element Settings
l_message.append ("An unknown exception was raised.")
end
set_last_error (l_message, a_location)
log.write_critical (generator + ".set_last_error_from_exception " + l_message)
write_critical_log (generator + ".set_last_error_from_exception " + l_message)
else
set_last_error ("Generic error", "")
log.write_critical (generator + ".set_last_error_from_exception Generic Error")
write_critical_log (generator + ".set_last_error_from_exception Generic Error")
end
rescue
l_retried := True
@@ -75,7 +75,7 @@ feature -- Element Settings
attached_location: a_location /= Void
do
create last_error.make (a_message, a_location)
log.write_critical (generator + ".set_last_error " + a_message)
write_critical_log (generator + ".set_last_error " + a_message)
successful := False
ensure
last_error_set: attached last_error
@@ -103,6 +103,6 @@ feature -- Element Settings
successful: successful
end
note
copyright: "2011-2014, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
copyright: "2011-2015, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end

View File

@@ -0,0 +1,188 @@
note
description: "Object to log messages for a specific application. "
date: "$Date$"
revision: "$Revision$"
class
LOGGER
inherit
ANY
LOG_PRIORITY_CONSTANTS
export
{NONE} all
end
SHARED_EXECUTION_ENVIRONMENT
export
{NONE} all
end
create
make,
make_with_environment,
make_with_layout
feature {NONE} -- Initialization
make
-- Initialize a logger object.
do
create log.make
end
make_with_environment (app: APPLICATION_ENVIRONMENT)
-- Initialize a logger object with an application environment `app'.
do
make
apply_environment (app)
end
make_with_layout (app: APPLICATION_ENVIRONMENT)
-- Initialize a logger object with an application layout `app'.
obsolete
"Use make_with_environment"
do
make_with_environment (app)
end
feature -- Change
apply_environment (app: APPLICATION_ENVIRONMENT)
do
initialize_logger (app, log)
end
feature {NONE} -- Internal
log: LOGGING_FACILITY
feature -- Logging
put_information (a_message: separate READABLE_STRING_8)
-- Put message `a_message' to the log at information level.
do
log.write_information (create {STRING}.make_from_separate (a_message))
end
put_error (a_message: separate READABLE_STRING_8)
-- Put message `a_message' to the log at error level.
do
log.write_error (create {STRING}.make_from_separate (a_message))
end
put_warning (a_message: separate READABLE_STRING_8)
-- Put message `a_message' to the log at warning level.
do
log.write_warning (create {STRING}.make_from_separate (a_message))
end
put_critical (a_message: separate READABLE_STRING_8)
-- Put message `a_message' to the log at critical level.
do
log.write_critical (create {STRING}.make_from_separate (a_message))
end
put_alert (a_message: separate READABLE_STRING_8)
-- Put message `a_message' to the log at alert level.
do
log.write_alert (create {STRING}.make_from_separate (a_message))
end
put_debug (a_message: separate READABLE_STRING_8)
-- Put message `a_message' to the log at debug level.
do
log.write_debug (create {STRING}.make_from_separate (a_message))
end
feature {NONE} -- Implementation
initialize_logger (app: APPLICATION_ENVIRONMENT; a_log: like log)
local
l_log_writer_file: LOG_ROLLING_WRITER_FILE
l_log_writer: LOG_WRITER
l_logs_path: detachable PATH
l_logger_config: LOGGER_CONFIGURATION
ut: FILE_UTILITIES
do
l_logger_config := new_logger_level_configuration (app.application_config_path)
l_logs_path := l_logger_config.location
if l_logs_path = Void then
l_logs_path := app.logs_path
end
if ut.directory_path_exists (l_logs_path) then
create l_log_writer_file.make_at_location (l_logs_path.extended (app.name).appended_with_extension ("log"))
l_log_writer_file.set_max_file_size ({NATURAL_64} 1024 * 1204)
l_log_writer_file.set_max_backup_count (l_logger_config.backup_count)
l_log_writer := l_log_writer_file
else
-- Should we create the directory anyway ?
create {LOG_WRITER_NULL} l_log_writer
end
set_logger_level (l_log_writer, l_logger_config.level)
a_log.register_log_writer (l_log_writer)
end
set_logger_level (a_log_writer: LOG_WRITER; a_priority: INTEGER)
-- Setup the logger level based on `a_priority'
do
if a_priority = log_debug then
a_log_writer.enable_debug_log_level
elseif a_priority = Log_emergency then
a_log_writer.enable_emergency_log_level
elseif a_priority = Log_alert then
a_log_writer.enable_alert_log_level
elseif a_priority = Log_critical then
a_log_writer.enable_critical_log_level
elseif a_priority = Log_error then
a_log_writer.enable_error_log_level
elseif a_priority = Log_warning then
a_log_writer.enable_warning_log_level
elseif a_priority = Log_notice then
a_log_writer.enable_notice_log_level
elseif a_priority = Log_information then
a_log_writer.enable_information_log_level
else
a_log_writer.enable_unkno_log_level
end
end
new_logger_level_configuration (a_path: PATH): LOGGER_CONFIGURATION
-- Retrieve a new logger level configuration.
-- By default, level is set to `DEBUG'.
local
l_parser: JSON_PARSER
ut: FILE_UTILITIES
do
create Result
if
ut.file_path_exists (a_path) and then
attached (create {JSON_FILE_READER}).read_json_from (a_path.name) as json_file
then
create l_parser.make_with_string (json_file)
l_parser.parse_content
if
l_parser.is_valid and then
attached l_parser.parsed_json_object as jv and then
attached {JSON_OBJECT} jv.item ("logger") as l_logger
then
if attached {JSON_STRING} l_logger.item ("location") as l_location then
Result.set_location_with_string (l_location.item)
end
if attached {JSON_STRING} l_logger.item ("backup_count") as l_count then
if l_count.item.is_natural then
Result.set_backup_count (l_count.item.to_natural)
end
end
if attached {JSON_STRING} l_logger.item ("level") as l_level then
Result.set_level (l_level.item)
end
end
end
end
note
copyright: "2011-2015, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end

View File

@@ -22,7 +22,7 @@ feature -- Access
register_log_writer (a_log_writer: LOG_WRITER)
-- -- Register the non-default log writer `a_log_writer'.
-- Register the non-default log writer `a_log_writer'.
do
logging.register_log_writer (a_log_writer)
end
@@ -67,7 +67,6 @@ feature -- Output
rescue
l_retry := True
retry
end
write_emergency (msg: STRING)
@@ -135,6 +134,6 @@ feature -- Output
retry
end
note
copyright: "2011-2014, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
copyright: "2011-2015, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end

View File

@@ -0,0 +1,116 @@
note
description: "Provides logger information"
date: "$Date: 2015-02-05 10:25:53 +0100 (jeu., 05 févr. 2015) $"
revision: "$Revision: 96584 $"
class
SHARED_LOGGER
inherit
LOG_PRIORITY_CONSTANTS
SHARED_EXECUTION_ENVIRONMENT
feature -- Logger
logger: separate LOGGER
-- `log' facility (once per process)
-- that could be shared between threads
-- without reinitializing it.
do
Result := logger_cell_item (logger_cell)
end
logger_cell: separate CELL [separate LOGGER]
once ("PROCESS")
create Result.put (create {separate LOGGER}.make)
end
logger_cell_item (a_cell: like logger_cell): separate LOGGER
do
Result := a_cell.item
end
feature -- Logging
write_debug_log (m: READABLE_STRING_8)
do
write_debug_log_to (m, logger)
end
write_information_log (m: READABLE_STRING_8)
do
write_information_log_to (m, logger)
end
write_warning_log (m: READABLE_STRING_8)
do
write_warning_log_to (m, logger)
end
write_error_log (m: READABLE_STRING_8)
do
write_error_log_to (m, logger)
end
write_critical_log (m: READABLE_STRING_8)
do
write_critical_log_to (m, logger)
end
write_alert_log (m: READABLE_STRING_8)
do
write_alert_log_to (m, logger)
end
feature {NONE} -- Logger: separate implementation
write_debug_log_to (m: READABLE_STRING_8; a_log: like logger)
do
a_log.put_debug (m)
end
write_information_log_to (m: READABLE_STRING_8; a_log: like logger)
do
a_log.put_information (m)
end
write_warning_log_to (m: READABLE_STRING_8; a_log: like logger)
do
a_log.put_warning (m)
end
write_error_log_to (m: READABLE_STRING_8; a_log: like logger)
do
a_log.put_error (m)
end
write_critical_log_to (m: READABLE_STRING_8; a_log: like logger)
do
a_log.put_critical (m)
end
write_alert_log_to (m: READABLE_STRING_8; a_log: like logger)
do
a_log.put_alert (m)
end
feature {NONE} -- Implementation
initialize_logger (app: APPLICATION_ENVIRONMENT)
local
l_logger: LOGGER
do
create l_logger.make_with_environment (app)
set_logger_to (l_logger, logger_cell)
end
set_logger_to (a_logger: separate LOGGER; a_cell: like logger_cell)
do
a_cell.replace (a_logger)
end
note
copyright: "2011-2015, Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="config" uuid="A3762109-D650-40A1-B55A-7D236A17903F" library_target="config">
<target name="config">
<root all_classes="true"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="standard">
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json-safe.ecf"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
</system>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="config" uuid="A3762109-D650-40A1-B55A-7D236A17903F" library_target="config">
<target name="config">
<root all_classes="true"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="false" void_safety="none" syntax="standard">
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json.ecf"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
</system>

View File

@@ -0,0 +1,10 @@
${NOTE_KEYWORD}
copyright: "2011-${YEAR}, 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
]"

View File

@@ -0,0 +1,121 @@
note
description: "Summary description for {CONFIG_READER}."
author: ""
date: "$Date: 2014-12-18 16:37:11 +0100 (jeu., 18 déc. 2014) $"
revision: "$Revision: 96383 $"
deferred class
CONFIG_READER
inherit
SHARED_EXECUTION_ENVIRONMENT
feature -- Status report
has_item (k: READABLE_STRING_GENERAL): BOOLEAN
-- Has item associated with key `k'?
deferred
end
has_error: BOOLEAN
-- Has error?
--| Syntax error, source not found, ...
deferred
end
feature -- Query
resolved_text_item (k: READABLE_STRING_GENERAL): detachable READABLE_STRING_32
-- String item associated with key `k' and expanded to resolved variables ${varname}.
do
if attached text_item (k) as s then
Result := resolved_expression (s)
end
end
text_item (k: READABLE_STRING_GENERAL): detachable READABLE_STRING_32
-- String item associated with key `k'.
deferred
end
integer_item (k: READABLE_STRING_GENERAL): INTEGER
-- Integer item associated with key `k'.
deferred
ensure
not has_item (k) implies Result = 0
end
feature {NONE} -- Implementation
resolved_items: detachable STRING_TABLE [READABLE_STRING_32]
-- Resolved items indexed by expression.
resolved_expression (exp: READABLE_STRING_GENERAL): STRING_32
-- Resolved `exp' using `Current' or else environment variables.
local
i,n,b,e: INTEGER
k: detachable READABLE_STRING_GENERAL
c: CHARACTER_32
l_resolved_items: like resolved_items
l_text: detachable READABLE_STRING_GENERAL
do
from
i := 1
n := exp.count
create Result.make (n)
until
i > n
loop
c := exp[i]
if i + 1 < n and then c = '$' and then exp[i+1] = '{' then
b := i + 2
e := exp.index_of ('}', b) - 1
if e > 0 then
k := exp.substring (b, e)
l_text := Void
l_resolved_items := resolved_items
if
l_resolved_items /= Void and then
attached l_resolved_items.item (k) as s
then
-- Already resolved, reuse value.
l_text := s
elseif attached text_item (k) as s then
-- has such item
l_text := s
elseif attached execution_environment.item (k) as v then
-- Or from environment
l_text := v
else
l_text := exp.substring (i, e + 1)
end
i := e + 1
Result.append_string_general (l_text)
else
Result.extend (c)
end
else
Result.extend (c)
end
i := i + 1
end
end
feature -- Duplication
sub_config (k: READABLE_STRING_GENERAL): detachable CONFIG_READER
-- Configuration representing a subset of Current for key `k'.
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

Some files were not shown because too many files have changed in this diff Show More