Compare commits

...

96 Commits

Author SHA1 Message Date
c3133c65a1 Merge remote-tracking branch 'jvelilla/roc_email' into ewf_v1
Conflicts:
	cms.ecf
	examples/demo/demo-safe.ecf
	examples/demo/site/scripts/user.sql
	examples/demo/src/ewf_roc_server.e
2015-06-18 19:17:16 +02:00
jvelilla
9e51df1e01 Updated OAUTH consumer using STRING_8 instead of STRING_32 2015-06-18 12:35:56 -03:00
967871e427 Removed inheritance from obsolete classes. 2015-06-18 14:46:22 +02:00
73e0098c4d Removed persistence sqlite folder which is now obsolete. 2015-06-18 14:23:30 +02:00
b4407378db Fixing compilations for test suites related to persistency. 2015-06-18 14:07:41 +02:00
f619727997 Fixed persistency layer.
Now we have ODBC .. that accepts various connection string (including SQLite, MySQL,...)
  And EiffelStore+MySQL.
Updated sql scripts to work with MySQL, and SQLite.
Added a sql_statement (s: STRING): STRING that converts ROC sql statement to fit the underlying database engine.
 mostly to adapt incompatibilities such as AUTO_INCREMENT for MySQL and AUTOINCREMENT for SQLite
 by default SQL script should be written following MySQL SQL syntax.
Warning: to use ODBC persistence driver, it has to be installed on the target machine.
2015-06-18 13:55:05 +02:00
e37dbb0a62 Merge branch 'blog_ewf_v1' into ewf_v1 2015-06-16 21:07:40 +02:00
Jocelyn Fiat
53491274dc Merged CMS based on concurrent EWF (i.e ewf_v1) with blog branch. 2015-06-15 11:27:44 +02:00
jvelilla
afced59b0c Updated Login Module.
- Refactor raname classes and features.
        - Clean code.
2015-06-11 21:50:27 -03:00
21800e71d3 Removed obsolete calls.
Updated code to make it clear what is the resource, and what is the associated module resource path.
2015-06-11 23:03:34 +02:00
jvelilla
18732a9532 Updated Login Module.
- OAUTH LOGIN: is generic based on a new OAUTH_20_GENERIC_API
        - Storage (at the moment only SQL) for OAUTH_CONSUMER configuration.
        - OAUTH login and callback are generic.
        - Added a OAUTH_20_GENERIC_API.
        - Added scripts and templates to build the new OAUTH tables.
        - Fixed CMS_STORAGE_SQL_I.check_sql_query_validity issue.
        - Extended CMS_STORAGE_SQL_I, to execute scripts with paramerters.
        - Updated filter, now it's generic for every OAUTH consumer.
2015-06-11 10:01:36 -03:00
0fc1cb68ad Apply recent changes from EWF v1 2015-06-10 18:39:41 +02:00
0b8bee3404 favor EiffelThread for now, while waiting for SCOOP to be fully ready. 2015-06-10 11:06:58 +02:00
53a602d33c Removed CMS_SERVICE
Updated install.bat script
2015-06-10 09:43:04 +02:00
jvelilla
f652aa8a15 Update Login Module.
- Updated routes relative to /account/
     - Updated emails with template support.
     - Updated cookie to support the new route.
     - Updated smarty block templates to use the new path.
2015-06-09 19:44:52 -03:00
5578a9e622 Adapted ROC CMS to concurrent EWF.
Revisited the shared logger to reduced number of useless calls.
2015-06-09 19:42:37 +02:00
jvelilla
e188625c43 Update Login Module.
- Added an API to mange user OAuth authentication.
   - Updated the Filter to use the new API.
   - Updated the Module to initialize if it needed the storages needed by the login module.
   - Updated gmail callback to use the new API.
   - Added a Persistence Layer

CMS_USER_API
   - clean api and related persistence code.
2015-06-08 18:32:34 -03:00
jvelilla
96ba3c35a2 OAuth2 Gmail
Added OAuth2 GMAIL loggin/logout support.
      Added OAuth2 Gmail filter.
LoginModule
      Updated LoginModule with OAuth2 Gmail support.
Persitence
      Extended user persitance api with OAuth2 gmail features.
      (TODO refactor persistance as an user extention)
2015-06-08 12:58:33 -03:00
jvelilla
181c32a895 Update: refactor get_block_view. 2015-06-05 19:12:10 -03:00
jvelilla
032cc5bdcb Updated CMS with Login Module.
-- The module handle basic_auth (at the moment).
     -- Handle login, logout, register user, activate/reactivate an account, password recovery.
     -- Send notification emails.

CMS Updates
     -- Added a new service: email.
     -- Updated Basic Auth Module to handle logout based on the browser type.
     -- Updated persistence layer to save and remove and query activation token and password token.
     -- Updated CMS_USER to handle status {active, not_active, trashed}.
     -- Updated MySQL scripts to be in sync with SQLite scripts
2015-06-05 18:39:27 -03:00
b8cfff487a Removed dependency from pagination to cms_data_query_parameters
TODO: review and fix any NATURAL_64 truncation.
2015-06-02 15:56:27 +02:00
af8f410684 Updated the CMS pagination component.
Harmonized count type to NATURAL_64 for recent_nodes (more to do later).
Fix get is active code.
2015-06-02 15:39:08 +02:00
cede341301 Merged remote-tracking branch 'jvelilla/roc_pg' into pagination
Renamed pagination related classes, and moved them to cms library under "support" cluster.
2015-05-31 22:43:19 +02:00
70d53b3ef1 Provide a default CMS_MODULE.is_installed: BOOLEAN implementation based on storage of custom value.
Now use CMS_MODULE.is_initialized: BOOLEAN as precondition of many routines.
Instantiation of node storage is now done in NODE_MODULE and not any more in CMS_NODE_API.
CMS_NODE_API can be instantiated only by NODE_MODULE.
2015-05-29 19:20:31 +02:00
jvelilla
f056b43ddc Updated CMS PAGINATION with the last Jocelyn's suggestion.
Added a node pagination helper, to build the html links and header related to
pagination.
2015-05-29 09:25:28 -03:00
c871eae10e Renamed node_api and node_storage by blog_api and blog_storage in related CMS_BLOG_* classes. Mainly to avoid confusion with NODE_ classes.
Merged CMS_BLOG_CONFIG with CMS_BLOG_API.
In CMS_BLOG_API, prefer argument of type CMS_USER, rather than using directly user id.
Added a CMS_EDITOR_CONTENT_FORMAT for now, to be the format editable by the WYSIWYG editor.
Added CMS_MODULE.is_initialized: BOOLEAN to equip router, and module_api with expected preconditions.

Fixed typo, especially in log output.
Corrected a few routine names such as add_authors that should not be a function according to its name.
Converted various function returning html content, to procedure appending html content to an output string to minimize temporary string object creation.
Cosmetic: added spaces to make code easier to read, and indentation.
2015-05-27 19:00:32 +02:00
jvelilla
957ca96bc5 Updated code based on comments. 2015-05-27 11:26:49 -03:00
jvelilla
ad9dd01f22 Update based on comments 2015-05-26 20:25:45 -03:00
jvelilla
323ac598d0 Updated code based on comments 2015-05-26 20:24:05 -03:00
Dario Bösch
e35893fdb9 Integrated the CKEditor
#7 and #8: The class CMS_EDITOR generates javascript code that replaces a textarea with a wysiwyg editor. Only a few methods have to be implemented by the subclasses, for example by CMD_EDITOR_CKEDITOR. The class CMS_FORM_TEXTAREA extends WSF_FORM_TEXTAREA with features to include the javascript from CMS_EDITOR. The most complex usage is shown in CMS_NODE_TYPE_WEBFORM_MANAGER, where the textarea is only replaced if "full_html" is selected as the desired body format. This works dynamically on the browser side as soon as the user selects another format.
2015-05-23 21:11:39 +02:00
b77c5cd93c Added abstraction of cms storage on file system. (mostly helpers features). 2015-05-22 23:04:09 +02:00
77f52388c1 Improved site_url and base_url interface and initialization.
Added CMS_CUSTOM_RESPONSE_MESSAGE interface to send easily simple response message.
Updated CMS_RESPONSE to use CMS_CUSTOM_RESPONSE_MESSAGE
2015-05-22 22:37:18 +02:00
Dario Bösch
e8ff313c28 added some commments 2015-05-22 17:58:46 +02:00
Dario Bösch
0bd75e7c59 Added list of posts of a specific user
Similar to the blog handler the blog user handler routes /blogs/users/{id}. Pagination is implemented as well
2015-05-22 17:31:30 +02:00
Dario Bösch
9b169f70a7 page_number global in blog_handler 2015-05-22 15:43:29 +02:00
Dario Bösch
601b88ab36 blog handler optimized, blog user handler created 2015-05-22 15:34:32 +02:00
Dario Bösch
2b0e1a2b84 Improved structure of blog handler 2015-05-22 14:39:43 +02:00
Dario Bösch
db77c4024d created blog.scss, added link to blogs/{user}
Later we will list all posts of a user under the route blogs/{user}
2015-05-22 14:04:00 +02:00
Dario Bösch
261aeca300 Bugfix: Author was hidden
I had to add the authors to each post after getting the list. Made a helper feature add_authors.
2015-05-22 12:34:30 +02:00
Dario Bösch
027463a910 #3: added pagination links at bottom of the blog page 2015-05-22 12:02:33 +02:00
Dario Bösch
a4c50adefa #3: Calculate and show number of total pages 2015-05-22 11:48:20 +02:00
Dario Bösch
1f61126d22 Configuration File added
Created CMS_BLOG_CONFIG at moved the feature entries_per_page to this new class. The blog hander inherits from the config class
2015-05-22 11:30:54 +02:00
Dario Bösch
fb196735b6 #3: Routet page and limited entries
The blog module routes /blog/{page} and the blog handler limits the entries per page (given as a feature) and sets the offsets according to the given page number
2015-05-22 11:17:34 +02:00
jvelilla
306b39ab78 Updated code based on Jocelyn's suggestions. 2015-05-21 16:46:06 -03:00
Dario Bösch
802ad0626e Bugfix: wrong API in initialisation of blog module 2015-05-21 16:10:07 +02:00
Dario Bösch
470b1b2e05 Restructured Blog Module
All blog handlers and storage classes are detached from the nodes module. All files of the blog module are in the modules/blog folder
2015-05-21 16:04:58 +02:00
Dario Bösch
57c2a7bccd Removed the summary from the detail page 2015-05-21 14:12:01 +02:00
Dario Bösch
4dd980963a Moved filter of nodes of type blog to the node storage layer.
This is more efficient because the result set from the query will be smaller and it will be easier to implement the pagination
2015-05-21 14:06:08 +02:00
Dario Bösch
6a782e412d #2 Structure of list of posts (blog)Ordered the posts by creation date. For this, I added a field to the nodes storage and api. Show the creation date and author. Styled the post and added a more link to the detail page 2015-05-21 12:03:09 +02:00
Dario Bösch
0e0cd131a5 #1: Added the summary field to all nodes. It gets saved if we edit the node. On a node page the summary is shown first, then the main content. In the blog list the title and the summry is shown 2015-05-21 10:18:03 +02:00
jvelilla
53f3162b4a Inital page builder implementation to add paging support to cms_nodes. 2015-05-19 18:40:57 -03:00
036013a0a2 Use CMS local location (i.e relative) and not url for cms local links. 2015-05-19 22:02:56 +02:00
Dario Bösch
202253e414 Added summary field in edit and add mode of a node 2015-05-19 17:28:37 +02:00
50da24d1af Added support for base_url (i.e the CMS can be hosted on the root, or sub folder).
Local paths are relative to cms site url (i.e no starting slash).
Favor CMS_RESPONSE.absolute_url and url .. instead of using directly WSF_REQUEST.absolute_script_url and script_url.
Handled unicode truncation issue for logger.
Code cleaning.
2015-05-19 13:50:39 +02:00
91457080fd Added support for base_url (i.e the CMS can be hosted on the root, or sub folder).
Local paths are relative to cms site url (i.e no starting slash).
Favor CMS_RESPONSE.absolute_url and url .. instead of using directly WSF_REQUEST.absolute_script_url and script_url.
Handled unicode truncation issue for logger.
Code cleaning.
2015-05-19 13:44:08 +02:00
51699f3bd3 updated db schema 2015-05-19 12:25:16 +02:00
Dario Bösch
f72fcce440 Link fix 2015-05-18 15:40:47 +02:00
Dario Bösch
f48f09bfdf Bugfix (blog disappeared as create option) 2015-05-18 14:49:21 +02:00
Dario Bösch
35b186cec8 gitignore 2015-05-18 14:39:49 +02:00
Dario Bösch
c65265b025 added blog handler that lists all blog entries 2015-05-18 14:36:24 +02:00
jvelilla
77bb1fe123 Merge branch 'jvelilla-roc_trash' 2015-05-17 12:14:01 -03:00
jvelilla
e4e2d662b8 Renaming revert string to restore. 2015-05-15 13:10:12 -03:00
jvelilla
f0668e660e refactor rename NODE_HANLDER.do_restore instead of do_revert. 2015-05-15 11:34:21 -03:00
jvelilla
68fb21a4c1 Fixed typo 2015-05-15 11:01:59 -03:00
jvelilla
3b90d522f9 Refactor rename: using trashed_nodes instead of trash_nodes. 2015-05-15 10:44:04 -03:00
jvelilla
1c59a65983 Updated code based on Jocelyn suggestions. 2015-05-15 09:40:18 -03:00
jvelilla
9fbadac7ac Added trash feature: Remove or revert a node.
Added Handler to show the current trash nodes for a given user.
An admin can see all the trash nodes.
Updated storage to handle trash and revert nodes.
2015-05-14 11:07:15 -03:00
jvelilla
57bf5ad0dc Added delete option as a tab only if the current user has permissions to delete the
current resource
2015-05-13 15:17:19 -03:00
jvelilla
988f32c6c4 Merge branch 'master' of https://github.com/EiffelWebFramework/ROC into roc_trash
Conflicts:
	modules/node/handler/node_form_response.e
2015-05-13 12:38:25 -03:00
jvelilla
44d14c4100 delete with tabs 2015-05-13 12:27:02 -03:00
29ef17226b Added support for path_aliases.
Refactored CMS_MODULE.router (..): WSF_ROUTER design,
  to create only one router object of type CMS_ROUTER.
Added optional CMS_NODE.link: CMS_LOCAL_LINK
Reviewed permissions related to node module.
Refactor and add CMS_STORAGE_SQL(_BUILDER) abstractions
   for implementation relying only on SQL statements.
Factorized sql builder initialization (to work for sqlite and mysql storage builders).
Added CMS_RESPONSE.formatted_string (a_text: READABLE_STRING_GENERAL; args: TUPLE): STRING_32
Added function "translation", but not implemented for now.
Updated indexing notes and comments.
Code cleaning.
2015-05-13 17:11:39 +02:00
9514f1de9c Updated SQLITE builder using GLOBAL_SETTINGS to map 0 to 0, by default 0 -> NULL
Updated CMS_NODE_API, with status, not_published, published and trashed.
Updated Form response to use permission scopes.
Updated sqlquery to retrieve user author.
Added logger info in cms_response
Updated CMS_NODE with a new status attribute.
Updated table nodes to support trashing (or soft deletes) of node using the new status field
Updated Sqlite builder to test different scenarios for users and roles.
Updated NODE_FORM_RESPONSE.edit_form feature to add a delete operation
  if 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. status is trashed).


Signed-off-by: jvelilla <javier.hector@gmail.com>
2015-05-12 22:02:23 +02: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
268 changed files with 14758 additions and 3977 deletions

4
.gitignore vendored
View File

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

View File

@@ -2,31 +2,33 @@
<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"> <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"> <target name="cms">
<root all_classes="true"/> <root all_classes="true"/>
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="false" is_attached_by_default="true" void_safety="all" syntax="transitional"> <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"/> <assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option> </option>
<mapping old_name="CMS_LAYOUT" new_name="CMS_ENVIRONMENT"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/> <library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="cms_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="config" location=".\library\configuration\config-safe.ecf"/>
<library name="crypto" location="$ISE_LIBRARY\unstable\library\text\encryption\crypto\crypto-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="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="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="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-safe.ecf"/>
<library name="http_authorization" location="$ISE_LIBRARY\contrib\library\network\authentication\http_authorization\http_authorization-safe.ecf" readonly="false"/> <library name="i18n" location="$ISE_LIBRARY\library\i18n\i18n-safe.ecf"/>
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json-safe.ecf" readonly="false"/> <library name="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="cms_model" location=".\library\model\cms_model-safe.ecf" readonly="false"/>
<library name="smarty" location="$ISE_LIBRARY\contrib\library\text\template\smarty\smarty-safe.ecf" readonly="false"/> <library name="smarty" location="$ISE_LIBRARY\contrib\library\text\template\smarty\smarty-safe.ecf" readonly="false"/>
<library name="text_filter" location="$ISE_LIBRARY\unstable\library\text\text_filter\text_filter-safe.ecf"/> <library name="text_filter" location="$ISE_LIBRARY\unstable\library\text\text_filter\text_filter-safe.ecf"/>
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/> <library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
<library name="uri_template" location="$ISE_LIBRARY\contrib\library\text\parser\uri_template\uri_template-safe.ecf"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/> <library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
<library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension-safe.ecf" readonly="false"/> <library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension-safe.ecf" readonly="false"/>
<library name="wsf_html" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf_html\wsf_html-safe.ecf" readonly="false"/> <library name="wsf_html" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf_html\wsf_html-safe.ecf" readonly="false"/>
<cluster name="src" location=".\src\" recursive="true"> <library name="net" location="$ISE_LIBRARY\library\net\net-safe.ecf"/>
<file_rule> <cluster name="src" location=".\src\" recursive="true"/>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
</cluster>
</target> </target>
</system> </system>

25
cms.ecf
View File

@@ -1,32 +1,35 @@
<?xml version="1.0" encoding="ISO-8859-1"?> <?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="cms" uuid="8CC0D052-57D1-4CAA-AFF1-448FA290734B" library_target="cms"> <system xmlns="http://www.eiffel.com/developers/xml/configuration-1-14-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-14-0 http://www.eiffel.com/developers/xml/configuration-1-14-0.xsd" name="cms" uuid="8CC0D052-57D1-4CAA-AFF1-448FA290734B" library_target="cms">
<description>ROC CMS library</description>
<target name="cms"> <target name="cms">
<root all_classes="true"/> <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"> <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"/> <assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option> </option>
<mapping old_name="CMS_LAYOUT" new_name="CMS_ENVIRONMENT"/>
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/> <library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
<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="config" location=".\library\configuration\config.ecf"/> <library name="config" location=".\library\configuration\config.ecf"/>
<library name="crypto" location="$ISE_LIBRARY\unstable\library\text\encryption\crypto\crypto.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="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="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="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http.ecf"/>
<library name="http_authorization" location="$ISE_LIBRARY\contrib\library\network\authentication\http_authorization\http_authorization.ecf" readonly="false"/> <library name="i18n" location="$ISE_LIBRARY\library\i18n\i18n.ecf"/>
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json.ecf" readonly="false"/> <library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json.ecf" readonly="false"/>
<library name="layout" location=".\library\layout\layout.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="smarty" location="$ISE_LIBRARY\contrib\library\text\template\smarty\smarty.ecf" readonly="false"/>
<library name="text_filter" location="$ISE_LIBRARY\unstable\library\text\text_filter\text_filter.ecf"/> <library name="text_filter" location="$ISE_LIBRARY\unstable\library\text\text_filter\text_filter.ecf"/>
<library name="time" location="$ISE_LIBRARY\library\time\time.ecf"/> <library name="time" location="$ISE_LIBRARY\library\time\time.ecf"/>
<library name="uri_template" location="$ISE_LIBRARY\contrib\library\text\parser\uri_template\uri_template.ecf"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf.ecf"/> <library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf.ecf"/>
<library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension.ecf" readonly="false"/> <library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension.ecf" readonly="false"/>
<library name="wsf_html" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf_html\wsf_html.ecf" readonly="false"/> <library name="wsf_html" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf_html\wsf_html.ecf" readonly="false"/>
<cluster name="src" location=".\src\" recursive="true"> <library name="net" location="$ISE_LIBRARY\library\net\net.ecf"/>
<file_rule> <cluster name="src" location=".\src\" recursive="true"/>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
</cluster>
</target> </target>
</system> </system>

View File

@@ -1,54 +1,81 @@
<?xml version="1.0" encoding="ISO-8859-1"?> <?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="demo" uuid="3643E657-BCBE-46AA-931B-71EAEA877A18" library_target="demo"> <system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="demo" uuid="3643E657-BCBE-46AA-931B-71EAEA877A18" library_target="demo">
<target name="common" abstract="true"> <description>Example/demo for Eiffel ROC CMS library</description>
<file_rule> <target name="common" abstract="true">
<exclude>/EIFGENs$</exclude> <file_rule>
<exclude>/CVS$</exclude> <exclude>/EIFGENs$</exclude>
<exclude>/.svn$</exclude> <exclude>/CVS$</exclude>
</file_rule> <exclude>/.svn$</exclude>
<option warning="true" full_class_checking="false" is_attached_by_default="true" void_safety="transitional" syntax="transitional"> </file_rule>
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/> <option debug="true" warning="true" full_class_checking="false" is_attached_by_default="true" void_safety="all" syntax="transitional">
</option> <debug name="dbglog" enabled="true"/>
<setting name="concurrency" value="none"/> </option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/> <setting name="concurrency" value="thread"/>
<library name="cms" location="..\..\cms-safe.ecf" readonly="false"/> <library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="cms_demo_module" location="modules\demo\cms_demo_module-safe.ecf" readonly="false"/> <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_app_env" location="..\..\library\app_env\app_env-safe.ecf" readonly="false"/>
<library name="layout" location="..\..\library\layout\layout-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="persistence_mysql" location="..\..\library\persistence\mysql\persistence_mysql-safe.ecf" readonly="false"/> <library name="cms_demo_module" location="modules\demo\cms_demo_module-safe.ecf" readonly="false"/>
--> <library name="cms_model" location="..\..\library\model\cms_model-safe.ecf" readonly="false"/>
<library name="persistence_sqlite" location="..\..\library\persistence\sqlite\persistence_sqlite-safe.ecf" readonly="false"/> <library name="cms_login_module" location="..\..\modules\login\login-safe.ecf" readonly="false"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/> <library name="cms_node_module" location="..\..\modules\node\node-safe.ecf" readonly="false"/>
<library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension-safe.ecf" readonly="false"/> <library name="persistence_store_mysql" location="..\..\library\persistence\store_mysql\store_mysql-safe.ecf" readonly="false"/>
</target> <library name="persistence_store_odbc" location="..\..\library\persistence\store_odbc\store_odbc-safe.ecf" readonly="false"/>
<target name="demo_any" extends="common"> <library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
<root class="EWF_ROC_SERVER" feature="make_and_launch"/> <library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension-safe.ecf" readonly="false"/>
<library name="cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\cgi-safe.ecf"/> </target>
<library name="libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\libfcgi-safe.ecf"/> <target name="demo_any" extends="common">
<library name="nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\nino-safe.ecf"/> <root class="EWF_ROC_SERVER" feature="make_and_launch"/>
<cluster name="launcher" location=".\launcher\any\" recursive="true"/> <setting name="concurrency" value="thread"/>
<cluster name="src" location=".\src\" recursive="true"/> <library name="cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\cgi-safe.ecf"/>
</target> <library name="libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\libfcgi-safe.ecf"/>
<target name="demo_nino" extends="common"> <library name="nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\nino-safe.ecf"/>
<root class="EWF_ROC_SERVER" feature="make_and_launch"/> <library name="standalone" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\standalone-safe.ecf"/>
<setting name="concurrency" value="none"/> <cluster name="launcher" location=".\launcher\any\" recursive="true"/>
<library name="default_nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\nino-safe.ecf"/> <cluster name="src" location=".\src\" recursive="true"/>
<cluster name="launcher" location=".\launcher\default\" recursive="true"/> </target>
<cluster name="src" location=".\src\" recursive="true"/> <target name="demo_standalone" extends="common">
</target> <root class="EWF_ROC_SERVER" feature="make_and_launch"/>
<target name="demo_cgi" extends="common"> <option debug="true">
<root class="EWF_ROC_SERVER" feature="make_and_launch"/> <debug name="dbglog" enabled="true"/>
<library name="default_cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\cgi-safe.ecf"/> </option>
<cluster name="launcher" location=".\launcher\default\" recursive="true"/> <variable name="httpd_ssl_disabled" value="true"/><!-- for now ... due to issue with libcurl+eiffelnet ssl -->
<cluster name="src" location=".\src\" recursive="true"/> <setting name="concurrency" value="thread"/>
</target> <library name="default_standalone" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\standalone-safe.ecf"/>
<target name="demo_libfcgi" extends="common"> <cluster name="launcher" location=".\launcher\default\" recursive="true"/>
<root class="EWF_ROC_SERVER" feature="make_and_launch"/> <cluster name="src" location=".\src\" recursive="true"/>
<library name="default_libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\libfcgi-safe.ecf"/> </target>
<cluster name="launcher" location=".\launcher\default\" recursive="true"/> <target name="demo_standalone_none" extends="demo_standalone">
<cluster name="src" location=".\src\" recursive="true"/> <setting name="concurrency" value="none"/>
</target> </target>
<target name="demo" extends="demo_nino"> <target name="demo_standalone_mt" extends="demo_standalone">
</target> <setting name="concurrency" value="thread"/>
</target>
<target name="demo_standalone_scoop" extends="demo_standalone">
<setting name="concurrency" value="scoop"/>
</target>
<target name="demo_nino" extends="common">
<root class="EWF_ROC_SERVER" feature="make_and_launch"/>
<setting name="concurrency" value="none"/>
<library name="default_nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\nino-safe.ecf"/>
<cluster name="launcher" location=".\launcher\default\" recursive="true"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
<target name="demo_cgi" extends="common">
<root class="EWF_ROC_SERVER" feature="make_and_launch"/>
<setting name="concurrency" value="none"/>
<library name="default_cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\cgi-safe.ecf"/>
<cluster name="launcher" location=".\launcher\default\" recursive="true"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
<target name="demo_libfcgi" extends="common">
<root class="EWF_ROC_SERVER" feature="make_and_launch"/>
<setting name="concurrency" value="none"/>
<library name="default_libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\libfcgi-safe.ecf"/>
<cluster name="launcher" location=".\launcher\default\" recursive="true"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
<target name="demo" extends="demo_standalone">
</target>
</system> </system>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +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="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_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension-safe.ecf" readonly="false"/>
<library name="wsf_encoder" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\text\encoder\encoder-safe.ecf"/>
<cluster name="src" location=".\" recursive="true"/>
</target>
</system>

View File

@@ -0,0 +1,150 @@
note
description: "Displays all posts (pages with type blog). It's possible to list posts by user."
author: "Dario B<>sch <daboesch@student.ethz.ch>"
date: "$Date: 2015-05-22 15:13:00 +0100 (lun., 18 mai 2015) $"
revision: "$Revision 96616$"
class
CMS_BLOG_MODULE
inherit
CMS_MODULE
rename
module_api as blog_api
redefine
register_hooks,
initialize,
install,
blog_api
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 blog_api.make (api, l_node_api)
node_api := l_node_api
-- Depends on {NODE_MODULE}
create ct
l_node_api.add_content_type (ct)
l_node_api.add_content_type_webform_manager (create {CMS_BLOG_NODE_TYPE_WEBFORM_MANAGER}.make (ct))
-- 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
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 AUTO_INCREMENT 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
Precursor (api)
end
end
feature {CMS_API} -- Access: API
blog_api: detachable CMS_BLOG_API
-- <Precursor>
node_api: detachable CMS_NODE_API
feature -- Access: router
setup_router (a_router: WSF_ROUTER; a_api: CMS_API)
-- <Precursor>
do
if attached blog_api as l_blog_api then
configure_web (a_api, l_blog_api, a_router)
else
-- Issue with api/dependencies,
-- thus Current module should not be used!
-- thus no url mapping
end
end
configure_web (a_api: CMS_API; a_blog_api: CMS_BLOG_API; a_router: WSF_ROUTER)
-- Configure router mapping for web interface.
local
l_blog_handler: BLOG_HANDLER
l_blog_user_handler: BLOG_USER_HANDLER
l_uri_mapping: WSF_URI_MAPPING
do
-- TODO: for now, focused only on web interface, add REST api later. [2015-May-18]
create l_blog_handler.make (a_api, a_blog_api)
create l_blog_user_handler.make (a_api, a_blog_api)
-- Let the class BLOG_HANDLER handle the requests on "/blogs"
create l_uri_mapping.make_trailing_slash_ignored ("/blogs", l_blog_handler)
a_router.map_with_request_methods (l_uri_mapping, a_router.methods_get)
-- We can add a page number after /blogs/ to get older posts
a_router.handle_with_request_methods ("/blogs/page/{page}", l_blog_handler, a_router.methods_get)
-- If a user id is given route with blog user handler
--| FIXME: maybe /user/{user}/blogs/ would be better.
a_router.handle_with_request_methods ("/blogs/user/{user}", l_blog_user_handler, a_router.methods_get)
-- If a user id is given we also want to allow different pages
--| FIXME: what about /user/{user}/blogs/?page={page} ?
a_router.handle_with_request_methods ("/blogs/user/{user}/page/{page}", l_blog_user_handler, a_router.methods_get)
end
feature -- Hooks
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
-- Add the link to the blog to the main menu
create lnk.make ("Blogs", "blogs/")
a_menu_system.primary_menu.extend (lnk)
end
end

View File

@@ -0,0 +1,64 @@
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 (4)
available_formats.extend (create {PLAIN_TEXT_CONTENT_FORMAT})
available_formats.extend (create {FILTERED_HTML_CONTENT_FORMAT})
available_formats.extend (create {FULL_HTML_CONTENT_FORMAT})
available_formats.extend (create {CMS_EDITOR_CONTENT_FORMAT})
end
feature -- Access
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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -7,7 +7,7 @@
<exclude>/EIFGENs$</exclude> <exclude>/EIFGENs$</exclude>
<exclude>/.svn$</exclude> <exclude>/.svn$</exclude>
</file_rule> </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> </option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/> <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="base_extension" location="$ISE_LIBRARY\library\base_extension\base_extension-safe.ecf"/>

View File

@@ -10,7 +10,10 @@ class
inherit inherit
CMS_MODULE CMS_MODULE
redefine redefine
register_hooks register_hooks,
initialize,
is_installed,
install
end end
CMS_HOOK_MENU_SYSTEM_ALTER CMS_HOOK_MENU_SYSTEM_ALTER
@@ -30,14 +33,58 @@ feature {NONE} -- Initialization
package := "demo" package := "demo"
end 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 AUTO_INCREMENT 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 feature -- Access: router
router (a_api: CMS_API): WSF_ROUTER setup_router (a_router: WSF_ROUTER; a_api: CMS_API)
-- Node router. -- <Precursor>
do do
create Result.make (2) map_uri_template_agent (a_router, "/demo/", agent handle_demo (?,?,a_api))
map_uri_template_agent (Result, "/demo/", agent handle_demo (?,?,a_api)) map_uri_template_agent (a_router, "/demo/{id}", agent handle_demo_entry (?,?,a_api))
map_uri_template_agent (Result, "/demo/{id}", agent handle_demo_entry (?,?,a_api))
end end
feature -- Hooks feature -- Hooks
@@ -63,9 +110,9 @@ feature -- Hooks
if a_block_id.is_case_insensitive_equal_general ("demo-info") then if a_block_id.is_case_insensitive_equal_general ("demo-info") then
if a_response.request.request_uri.starts_with ("/demo/") then if a_response.request.request_uri.starts_with ("/demo/") then
create m.make_with_title (a_block_id, "Demo", 2) create m.make_with_title (a_block_id, "Demo", 2)
create lnk.make ("/demo/abc", a_response.url ("/demo/abc", Void)) create lnk.make ("demo: abc", "demo/abc")
m.extend (lnk) m.extend (lnk)
create lnk.make ("/demo/123", a_response.url ("/demo/123", Void)) create lnk.make ("demo: 123", "demo/123")
m.extend (lnk) m.extend (lnk)
create mb.make (m) create mb.make (m)
a_response.add_block (mb, "sidebar_second") a_response.add_block (mb, "sidebar_second")
@@ -78,46 +125,20 @@ feature -- Hooks
lnk: CMS_LOCAL_LINK lnk: CMS_LOCAL_LINK
-- perms: detachable ARRAYED_LIST [READABLE_STRING_8] -- perms: detachable ARRAYED_LIST [READABLE_STRING_8]
do do
create lnk.make ("Demo", "/demo/") create lnk.make ("Demo", "demo/")
a_menu_system.primary_menu.extend (lnk) a_menu_system.primary_menu.extend (lnk)
end end
feature -- Handler feature -- Handler
initialize_module (a_api: CMS_API)
local
sql: STRING
do
if attached {CMS_STORAGE_SQL} a_api.storage as sql_db then
sql_db.sql_query ("select count(*) from tb_demo;", Void)
if sql_db.has_error then
-- Initialize db for demo module
sql := "[
CREATE TABLE "tb_demo"(
"did" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK("did">=0),
"name" VARCHAR(100) NOT NULL,
"value" TEXT
);
]"
sql_db.reset_error
sql_db.sql_change (sql, Void)
if sql_db.has_error then
a_api.logger.put_error ("Could not initialize database for demo module", generating_type)
end
end
end
end
handle_demo, handle_demo,
handle_demo_entry (req: WSF_REQUEST; res: WSF_RESPONSE; a_api: CMS_API) handle_demo_entry (req: WSF_REQUEST; res: WSF_RESPONSE; a_api: CMS_API)
local local
r: NOT_IMPLEMENTED_ERROR_CMS_RESPONSE r: NOT_IMPLEMENTED_ERROR_CMS_RESPONSE
do do
initialize_module (a_api)
create r.make (req, res, a_api) create r.make (req, res, a_api)
r.set_main_content ("NODE module does not yet implement %"" + req.path_info + "%" ...") r.set_main_content ("DEMO module does not yet implement %"" + req.path_info + "%" ...")
r.add_error_message ("NODE Module: not yet implemented") r.add_error_message ("DEMO Module: not yet implemented")
r.execute r.execute
end end

View File

@@ -1,15 +1,18 @@
{ {
"database": { "database": {
"datasource": { "datasource": {
"driver": "sqlite", "driver": "odbc",
"environment": "sqlite" "environment": "odbc-sqlite"
}, },
"environments": { "environments": {
"sqlite": { "odbc-sqlite": {
"connection_string":"Driver=SQLite3 ODBC Driver;Database=./site/database.sqlite;LongNames=0;Timeout=1000;NoTXN=0;SyncPragma=NORMAL;StepAPI=0;" "connection_string":"Driver=SQLite3 ODBC Driver;Database=./site/database.sqlite;LongNames=0;Timeout=1000;NoTXN=0;SyncPragma=NORMAL;StepAPI=0;"
}, },
"test": { "odbc-mysql": {
"connection_string":"Server=localhost;Port=3306;Database=cms_dev;Uid=root;Pwd=;" "connection_string":"Driver=mysql ODBC Driver;Server=localhost;Port=3306;Database=roc;Uid=roc;Pwd=roc;"
},
"mysql": {
"connection_string":"Driver=mysql;Server=localhost;Port=3306;Database=roc;Uid=roc;Pwd=roc;"
}, },
"development": { "development": {
"connection_string":"Server=localhost;Port=3306;Database=cms_dev;Uid=root;Pwd=;" "connection_string":"Server=localhost;Port=3306;Database=cms_dev;Uid=root;Pwd=;"
@@ -23,7 +26,8 @@
"server": "localhost" "server": "localhost"
}, },
"logger": { "logger": {
"level":"debug", "level":"error",
"type":"stderr",
"backup_count":"4" "backup_count":"4"
}, },
"server": { "server": {

View File

@@ -0,0 +1,18 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Activation</title>
<meta name="description" content="Activation">
<meta name="author" content="ROC CMS">
</head>
<body>
<p>Thank you for registering at <a href="$host">ROC CMS</a></p>
<p>To complete your registration, please click on this link to activate your account:<p>
<p><a href="$link">$link</a></p>
<p>Thank you for joining us.</p>
</body>
</html>

View File

@@ -0,0 +1,17 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>New Password</title>
<meta name="description" content="New Password">
<meta name="author" content="ROC CMS">
</head>
<body>
<p>You have required a new password at <a href="...">ROC CMS</a></p>
<p>To complete your request, please click on this link to genereate a new password:<p>
<p><a href="$link">$link</a></p>
</body>
</html>

View File

@@ -0,0 +1,18 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>New Activation</title>
<meta name="description" content="New Activation token">
<meta name="author" content="ROC CMS">
</head>
<body>
<p>You have request a new activation token at<a href="...">ROC CMS</a></p>
<p>To complete your registration, please click on this link to activate your account:<p>
<p><a href="$link">$link</a></p>
<p>Thank you for joining us.</p>
</body>
</html>

View File

@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Welcome</title>
<meta name="description" content="Welcome">
<meta name="author" content="ROC CMS">
</head>
<body>
<p>Welcome to<a href="...">ROC CMS</a></p>
<p>Thank you for joining us.</p>
</body>
</html>

View File

@@ -0,0 +1,8 @@
{
"email": "webmaster@example.com",
"subjet_register": "Thank you for regitering with us, activate account",
"subjet_activate": "New account ativation token",
"subjet_password": "Password Recovery!!!",
"subjet_oauth": "Welcome",
"smtp": "127.0.0.1"
}

View File

@@ -0,0 +1,7 @@
{
"api_secret":"ADD_YOUR_SECRET_KEY",
"api_key":"ADD_YOUR_PUBLIC_KEY",
"scope": "email",
"api_revoke":"https://accounts.google.com/o/oauth2/revoke?token=$ACCESS_TOKEN",
"protected_resource_url":"https://www.googleapis.com/plus/v1/people/me"
}

View File

@@ -0,0 +1,23 @@
CREATE TABLE `logs`(
`id` INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL,
`category` VARCHAR(255) NOT NULL,
`level` INTEGER NOT NULL,
`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` TEXT
);
CREATE TABLE `path_aliases`(
`pid` INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL,
`source` VARCHAR(255) NOT NULL,
`alias` VARCHAR(255) NOT NULL,
`lang` VARCHAR(12)
);

View File

@@ -0,0 +1,22 @@
CREATE TABLE nodes (
`nid` INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT UNIQUE,
`revision` INTEGER,
`type` TEXT NOT NULL,
`title` VARCHAR(255) NOT NULL,
`summary` TEXT,
`content` TEXT,
`format` VARCHAR(128),
`author` INTEGER,
`publish` DATETIME,
`created` DATETIME NOT NULL,
`changed` DATETIME NOT NULL,
`status` INTEGER
);
CREATE TABLE page_nodes(
`nid` INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL,
`revision` INTEGER,
`parent` INTEGER
);

View File

@@ -0,0 +1,18 @@
CREATE TABLE `oauth2_consumers`(
`cid` INTEGER PRIMARY KEY NOT NULL CHECK(`cid`>=0),
`name` VARCHAR(255) NOT NULL,
`api_secret` TEXT NOT NULL,
`api_key` TEXT NOT NULL,
`scope` VARCHAR (100) NOT NULL,
`protected_resource_url` VARCHAR (255) NOT NULL,
`callback_name` VARCHAR(255) NOT NULL,
`extractor` VARCHAR(50) NOT NULL,
`authorize_url` VARCHAR (255) NOT NULL,
`endpoint` VARCHAR (255) NOT NULL,
CONSTRAINT `cid`
UNIQUE(`cid`),
CONSTRAINT `name`
UNIQUE(`name`)
);

View File

@@ -0,0 +1,7 @@
-- Change the values `TO_COMPLETE` based on your API.
-- API SECTET KEY AND API PUBLIC KEY
INSERT INTO `oauth2_consumers` ("name", "api_secret", "api_key", "scope", "protected_resource_url", "callback_name", "extractor", "authorize_url", "endpoint")
VALUES ("google", 'TO-COMPLETE', 'TO-COMPLETE', 'email', 'https://www.googleapis.com/plus/v1/people/me', "callback_google", "json","https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=$CLIENT_ID&redirect_uri=$REDIRECT_URI","https://accounts.google.com/o/oauth2/token");
INSERT INTO "oauth2_consumers" ("name", "api_secret", "api_key", "scope", "protected_resource_url", "callback_name", "extractor", "authorize_url", "endpoint" )
VALUES ("facebook", 'TO-COMPLETE', 'TO-COMPLETE', 'email', 'https://graph.facebook.com/me', "callback_facebook","text","https://www.facebook.com/dialog/oauth?response_type=code&client_id=$CLIENT_ID&redirect_uri=$REDIRECT_URI","https://graph.facebook.com/oauth/access_token");

View File

@@ -0,0 +1,10 @@
CREATE TABLE :table_name (
`uid` INTEGER PRIMARY KEY NOT NULL CHECK(`uid`>=0),
`access_token` TEXT NOT NULL,
`created` DATETIME NOT NULL,
`details` TEXT NOT NULL,
CONSTRAINT `uid`
UNIQUE(`uid`)
);

View File

@@ -1,34 +0,0 @@
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 "users_roles"(
"rid" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK("rid">=0),
"role" VARCHAR(100) NOT NULL,
CONSTRAINT "role"
UNIQUE("role")
);
CREATE TABLE "nodes"(
"nid" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK("nid">=0),
"version" INTEGER,
"type" INTEGER,
"title" VARCHAR(255) NOT NULL,
"summary" TEXT NOT NULL,
"content" MEDIUMTEXT NOT NULL,
"author" INTEGER,
"publish" DATETIME,
"created" DATETIME NOT NULL,
"changed" DATETIME NOT NULL
);
COMMIT;

View File

@@ -0,0 +1,48 @@
CREATE TABLE `users`(
`uid` INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL,
`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 AUTO_INCREMENT NOT NULL,
`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,
`permission` VARCHAR(255) NOT NULL,
`module` VARCHAR(255)
);
CREATE TABLE "users_activations" (
"aid" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK ("aid" >= 0),
"token" VARCHAR(255) NOT NULL,
"uid" INTEGER NOT NULL CHECK ("uid" >= 0),
"created" DATETIME NOT NULL,
CONSTRAINT "token" UNIQUE ("token")
);
CREATE TABLE "users_password_recovery" (
"aid" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK ("aid" >= 0),
"token" VARCHAR(255) NOT NULL,
"uid" INTEGER NOT NULL CHECK ("uid" >= 0),
"created" DATETIME NOT NULL,
CONSTRAINT "token" UNIQUE ("token")
);

View File

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

View File

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

View File

@@ -37,6 +37,16 @@ ul.horizontal li {
#content { #content {
margin-left: 20px; 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 { .sidebar {
padding: 5px; padding: 5px;
@@ -51,3 +61,18 @@ ul.horizontal li {
width: 250px; width: 250px;
float: right; 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;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 994 B

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,321 @@
var ROC_AUTH = ROC_AUTH || { };
var loginURL = "/basic_auth_login";
var logoutURL = "/basic_auth_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);
};
var password = document.getElementById("password")
, confirm_password = document.getElementById("confirm_password");
ROC_AUTH.validatePassword =function(){
if(password.value != confirm_password.value) {
confirm_password.setCustomValidity("Passwords Don't Match");
} else {
confirm_password.setCustomValidity('');
}
}
password.onchange = ROC_AUTH.validatePassword();
confirm_password.onkeyup = ROC_AUTH.validatePassword;

View File

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

View File

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

View File

@@ -41,6 +41,16 @@ ul.horizontal {
} }
#content { #content {
margin-left: 20px; 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 { .sidebar {
padding: 5px; padding: 5px;
@@ -55,3 +65,19 @@ ul.horizontal {
float: right; 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

@@ -1,14 +1,38 @@
{assign name="debug_enabled" value="True"/} {assign name="debug_enabled" value="True"/}
{if condition="$debug_enabled"} {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> <ul>
{assign name="kpage" value="page"/} {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}
{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>={$i/}</li>
{/unless}
{/unless}
{/foreach} {/foreach}
</ul> </ul>
</div>
<!-- end debug -->
{/if} {/if}

View File

@@ -0,0 +1,34 @@
<div class="primary-tabs">
{unless isset="$user"}
<h3>Login or <a href="/account/roc-register">Register</a></h3>
<div>
<div>
<form action method="POST">
<div>
<input type="text" name="username" required>
<label>Username</label>
</div>
<div>
<input type="password" name="password" required>
<label>Password</label>
</div>
<button type="button" onclick="ROC_AUTH.login();">Login</button>
</form>
</div>
</div>
<div>
<div>
<p>
<a href="/account/new-password">Forgot password?</a>
</p>
</div>
</div>
<div>
{foreach item="item" from="$oauth_consumers"}
<a href="/account/login-with-oauth/{$item/}">Login with {$item/}</a><br>
{/foreach}
</div>
{/unless}
</div>

View File

@@ -0,0 +1,16 @@
<div>
<form action="/account/new-password" method="post">
<fieldset>
<legend>Require new password</legend>
<div>
<input type="email" id="email" name="email" value="{$email/}" required/>
<label for="email">Email</label>
{if isset="$error_email"}
<span><i>{$error_email/}</i></span> <br>
{/if}
<br>
</div>
<button type="submit">Send</button>
</fieldset>
</form>
</div>

View File

@@ -0,0 +1,3 @@
<div>
<p>We have send you a new token code, check your email to generate a new password</p>
</div>

View File

@@ -0,0 +1,3 @@
<div>
<p>We have send you a new activation code, check your email to activate your account.</p>
</div>

View File

@@ -0,0 +1,3 @@
<div>
<p>Thanks for register, check your email to activate your account.</p>
</div>

View File

@@ -0,0 +1,3 @@
<div>
<p>You new password has been saved!</p>
</div>

View File

@@ -0,0 +1,19 @@
<div>
<form action="/account/reactivate" method="post">
<fieldset>
<legend>Reactivate Form</legend>
<div>
<input type="email" id="email" name="email" value="{$email/}" required/>
<label for="email">Email</label>
{if isset="$error_email"}
<span><i>{$error_email/}</i></span> <br>
{/if}
<br>
{if isset="$is_active"}
<span><i>{$is_active/}</i></span> <br>
{/if}
</div>
<button type="submit">Reactivate</button>
</fieldset>
</form>
</div>

View File

@@ -0,0 +1,28 @@
<div>
<form action="/account/roc-register" method="post">
<fieldset>
<legend>Register Form</legend>
<div>
<input type="text" id="name" name="name" value="{$name/}" required autofocus />
<label for="name">Name</label>
{if isset="$error_name"}
<span><i>{$error_name/}</i></span> <br>
{/if}
</div>
<div>
<input type="password" id="password" name="password" value="" required/>
<label for="password">Password</label>
</div>
<div>
<input type="email" id="email" name="email" value="{$email/}" required/>
<label for="email">Email</label>
{if isset="$error_email"}
<span><i>{$error_email/}</i></span> <br>
{/if}
</div>
<button type="submit">Register</button>
</fieldset>
</form>
</div>

View File

@@ -0,0 +1,28 @@
<div>
<form action="/account/reset-password" method="post">
<fieldset>
<legend>Generate New Password Form</legend>
<div>
<input type="text" id="token" name="token" value="{$token/}" required />
<label for="token">Token</label>
{if isset="$error_token"}
<span><i>{$error_token/}</i></span> <br>
{/if}
</div>
<div>
<input type="password" id="password" name="password" value="" required/>
<label for="password">Password</label>
</div>
<div>
<input type="password" id="confirm_password" name="confirm_password" value="" required/>
<label for="password">Confirm Password</label>
</div>
<button type="submit">Confirm</button>
{if isset="$error_password"}
<span><i>{$error_password/}</i></span> <br>
{/if}
</fieldset>
</form>
</div>

View File

@@ -1,10 +1,18 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<!-- EWF CMS --> <!-- EWF CMS -->
<link rel="stylesheet" href="{$site_url/}/theme/css/style.css"> <link rel="stylesheet" href="{$site_url/}theme/css/style.css">
<link rel="stylesheet" href="{$site_url/}theme/css/node.css">
<!-- CMS Blog Module -->
<link rel="stylesheet" href="{$site_url/}theme/css/blog.css">
<script src="{$site_url/}theme/js/jquery-1.10.2.min.js"></script>
<script src="{$site_url/}theme/js/roc_auth.js"></script>
<!-- bootstrap framework --> <!-- bootstrap framework -->
<!-- Latest compiled and minified CSS --> <!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
@@ -53,7 +61,7 @@
<!-- Main Content Section --> <!-- Main Content Section -->
{unless isempty="$page_title"}<h1 class="page-title">{$page_title/}</h1>{/unless} {unless isempty="$page_title"}<h1 class="page-title">{$page_title/}</h1>{/unless}
{$page.region_content/} {$page.region_content/}
</div> </div>
</div> </div>
@@ -70,8 +78,6 @@
<!-- Latest compiled and minified JavaScript --> <!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
<!--
{include file="debug.tpl"/} {include file="debug.tpl"/}
-->
</body> </body>
</html> </html>

View File

@@ -16,11 +16,6 @@ inherit
initialize initialize
end end
WSF_SERVICE
redefine
execute
end
REFACTORING_HELPER REFACTORING_HELPER
SHARED_EXECUTION_ENVIRONMENT SHARED_EXECUTION_ENVIRONMENT
@@ -40,39 +35,26 @@ feature {NONE} -- Initialization
initialize initialize
-- Initialize current service. -- Initialize current service.
local
env: CMS_ENVIRONMENT
do do
Precursor Precursor
create {WSF_SERVICE_LAUNCHER_OPTIONS_FROM_INI} service_options.make_from_file ("demo.ini") create {WSF_SERVICE_LAUNCHER_OPTIONS_FROM_INI} service_options.make_from_file ("demo.ini")
initialize_cms (cms_setup) create env.make_default
initialize_logger (env)
end end
feature -- 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 feature {NONE} -- Launch operation
launcher: APPLICATION_LAUNCHER launcher: APPLICATION_LAUNCHER [EWF_ROC_SERVER_EXECUTION]
launch (a_service: WSF_SERVICE; opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS) launch (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
local local
l_retry: BOOLEAN l_retry: BOOLEAN
l_message: STRING l_message: STRING
do do
if not l_retry then if not l_retry then
write_debug_log (generator + ".launch") launcher.launch (opts)
launcher.launch (a_service, opts)
else else
-- error hanling. -- error hanling.
create l_message.make (1024) create l_message.make (1024)
@@ -92,68 +74,11 @@ feature {NONE} -- Launch operation
l_message.append ("%N%N") l_message.append ("%N%N")
end end
-- send email shutdown -- send email shutdown
write_debug_log (generator + ".launch shutdown")
end end
rescue rescue
l_retry := True l_retry := True
retry retry
end end
feature -- CMS Initialization
cms_setup: CMS_DEFAULT_SETUP
local
utf: UTF_CONVERTER
do
if attached execution_environment.arguments.separate_character_option_value ('d') as l_dir then
create layout.make_with_directory_name (l_dir)
else
create layout.make_default
end
initialize_logger (layout)
write_debug_log (generator + ".cms_setup based directory %"" + utf.escaped_utf_32_string_to_utf_8_string_8 (layout.path.name) + "%"")
create Result.make (layout)
setup_storage (Result)
end
initialize_cms (a_setup: CMS_SETUP)
local
cms: CMS_SERVICE
api: CMS_API
do
write_debug_log (generator + ".initialize_cms")
setup_modules (a_setup)
create api.make (a_setup)
create cms.make (api)
cms_service := cms
end
feature -- CMS setup
setup_modules (a_setup: CMS_SETUP)
-- Setup additional modules.
local
m: CMS_MODULE
do
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_DEMO_MODULE} m.make
m.enable
a_setup.register_module (m)
end
setup_storage (a_setup: CMS_SETUP)
do
debug ("refactor_fixme")
to_implement ("To implement custom storage")
end
-- a_setup.storage_drivers.force (create {CMS_STORAGE_MYSQL_BUILDER}.make, "mysql")
a_setup.storage_drivers.force (create {CMS_STORAGE_SQLITE_BUILDER}.make, "sqlite")
end
end end

View File

@@ -0,0 +1,85 @@
note
description: "Summary description for {EWF_ROC_SERVER_EXECUTION}."
date: "$Date$"
revision: "$Revision$"
class
EWF_ROC_SERVER_EXECUTION
inherit
CMS_EXECUTION
redefine
initialize
end
REFACTORING_HELPER
SHARED_LOGGER
create
make
feature {NONE} -- Initialization
initialize
do
Precursor
end
initial_cms_setup: CMS_DEFAULT_SETUP
-- CMS setup.
local
l_env: CMS_ENVIRONMENT
do
if attached execution_environment.arguments.separate_character_option_value ('d') as l_dir then
create l_env.make_with_directory_name (l_dir)
else
create l_env.make_default
end
create Result.make (l_env)
end
feature -- CMS setup
setup_storage (a_setup: CMS_SETUP)
do
debug ("refactor_fixme")
to_implement ("To implement custom storage")
end
-- a_setup.storage_drivers.force (create {CMS_STORAGE_STORE_MYSQL_BUILDER}.make, "mysql")
a_setup.storage_drivers.force (create {CMS_STORAGE_STORE_ODBC_BUILDER}.make, "odbc")
end
setup_modules (a_setup: CMS_SETUP)
-- Setup additional modules.
local
m: CMS_MODULE
do
create {NODE_MODULE} m.make (a_setup)
m.enable
a_setup.register_module (m)
create {CMS_AUTHENTICATION_MODULE} m.make
m.enable
a_setup.register_module (m)
create {BASIC_AUTH_MODULE} m.make
if not a_setup.module_with_same_type_registered (m) then
m.enable
a_setup.register_module (m)
end
create {CMS_DEBUG_MODULE} m.make
m.enable
a_setup.register_module (m)
create {CMS_DEMO_MODULE} m.make
m.enable
a_setup.register_module (m)
create {CMS_BLOG_MODULE} m.make
m.enable
a_setup.register_module (m)
end
end

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

@@ -1,26 +1,17 @@
<?xml version="1.0" encoding="ISO-8859-1"?> <?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="persistence_sqlite" uuid="8FD9D3B3-5FC1-495F-A05D-0205EC966841" library_target="persistence_sqlite"> <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">
<target name="persistence_sqlite"> <description>Application Environment (layout, configuration, logger, database, ...)</description>
<target name="app_env">
<root all_classes="true"/> <root all_classes="true"/>
<option warning="true" void_safety="none"> <option warning="true" void_safety="none">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/> <assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option> </option>
<setting name="console_application" value="true"/> <setting name="console_application" value="true"/>
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/> <library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
<library name="cms" location="..\..\..\cms.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"/>
<library name="error" location="$ISE_LIBRARY\contrib\library\utility\general\error\error.ecf"/>
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json.ecf" readonly="false"/> <library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json.ecf" readonly="false"/>
<library name="layout" location="..\..\layout\layout.ecf"/>
<library name="logging" location="$ISE_LIBRARY\library\runtime\logging\logging.ecf"/> <library name="logging" location="$ISE_LIBRARY\library\runtime\logging\logging.ecf"/>
<library name="model" location="..\..\model\cms_model.ecf"/>
<library name="odbc" location="$ISE_LIBRARY\library\store\dbms\rdbms\odbc\odbc.ecf"/>
<library name="store" location="$ISE_LIBRARY\library\store\store.ecf" readonly="false"/>
<library name="thread" location="$ISE_LIBRARY\library\thread\thread.ecf"/> <library name="thread" location="$ISE_LIBRARY\library\thread\thread.ecf"/>
<library name="time" location="$ISE_LIBRARY\library\time\time.ecf"/> <cluster name="src" location=".\src\" recursive="true">
<cluster name="common" location="..\implementation\store\" recursive="true"/>
<cluster name="persistence_sqlite" location=".\src\" recursive="true">
<file_rule> <file_rule>
<exclude>/EIFGENs$</exclude> <exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude> <exclude>/CVS$</exclude>

View File

@@ -1,6 +1,6 @@
note note
description: "[ description: "[
Application layout Application environment (layout, ...)
Related to file system locations such as Related to file system locations such as
- configuration locations - configuration locations
- application - application
@@ -15,7 +15,7 @@ note
revision: "$Revision: 96584 $" revision: "$Revision: 96584 $"
class class
APPLICATION_LAYOUT APPLICATION_ENVIRONMENT
inherit inherit
SHARED_EXECUTION_ENVIRONMENT SHARED_EXECUTION_ENVIRONMENT

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

@@ -30,6 +30,7 @@ feature -- Initialization
backup_count := 4 backup_count := 4
level := Log_debug level := Log_debug
location := Void location := Void
type := {STRING_32} "null"
ensure then ensure then
backup_count_set: backup_count = 4 backup_count_set: backup_count = 4
level_set: level = Log_debug level_set: level = Log_debug
@@ -48,6 +49,9 @@ feature -- Access
level: INTEGER level: INTEGER
-- Logger level. -- Logger level.
type: IMMUTABLE_STRING_32
-- Type of logging.
feature -- Element Change feature -- Element Change
set_location (a_location: detachable PATH) set_location (a_location: detachable PATH)
@@ -65,6 +69,15 @@ feature -- Element Change
set_location (create {PATH}.make_from_string (a_location)) set_location (create {PATH}.make_from_string (a_location))
end end
set_type_with_string (a_type: detachable READABLE_STRING_GENERAL)
do
if a_type /= Void and then not a_type.is_whitespace then
create type.make_from_string_general (a_type)
else
create type.make_from_string_general ("null")
end
end
set_backup_count (a_backup: NATURAL) set_backup_count (a_backup: NATURAL)
-- Set backup_count to `a_backup'. -- Set backup_count to `a_backup'.
do do

View File

@@ -1,6 +1,5 @@
note note
description: "Summary description for {LOGGER}." description: "Object to log messages for a specific application. "
author: ""
date: "$Date$" date: "$Date$"
revision: "$Revision$" revision: "$Revision$"
@@ -22,24 +21,35 @@ inherit
create create
make, make,
make_with_environment,
make_with_layout make_with_layout
feature {NONE} -- Initialization feature {NONE} -- Initialization
make make
-- Initialize a logger object.
do do
create log.make create log.make
end end
make_with_layout (app: APPLICATION_LAYOUT) make_with_environment (app: separate APPLICATION_ENVIRONMENT)
-- Initialize a logger object with an application environment `app'.
do do
make make
apply_layout (app) 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 end
feature -- Change feature -- Change
apply_layout (app: APPLICATION_LAYOUT) apply_environment (app: separate APPLICATION_ENVIRONMENT)
do do
initialize_logger (app, log) initialize_logger (app, log)
end end
@@ -48,69 +58,107 @@ feature {NONE} -- Internal
log: LOGGING_FACILITY log: LOGGING_FACILITY
feature -- Settings
level: INTEGER
feature -- Logging feature -- Logging
put_information (a_message: separate READABLE_STRING_8) put_debug (a_message: separate READABLE_STRING_8)
-- Put message `a_message' to the log at debug level.
do do
log.write_information (create {STRING}.make_from_separate (a_message)) if level >= log_debug then
log.write_debug (create {STRING}.make_from_separate (a_message))
end
end end
put_error (a_message: separate READABLE_STRING_8) put_information (a_message: separate READABLE_STRING_8)
-- Put message `a_message' to the log at information level.
do do
log.write_error (create {STRING}.make_from_separate (a_message)) if level >= log_information then
log.write_information (create {STRING}.make_from_separate (a_message))
end
end end
put_warning (a_message: separate READABLE_STRING_8) put_warning (a_message: separate READABLE_STRING_8)
-- Put message `a_message' to the log at warning level.
do do
log.write_warning (create {STRING}.make_from_separate (a_message)) if level >= log_warning then
log.write_warning (create {STRING}.make_from_separate (a_message))
end
end
put_error (a_message: separate READABLE_STRING_8)
-- Put message `a_message' to the log at error level.
do
if level >= log_error then
log.write_error (create {STRING}.make_from_separate (a_message))
end
end end
put_critical (a_message: separate READABLE_STRING_8) put_critical (a_message: separate READABLE_STRING_8)
-- Put message `a_message' to the log at critical level.
do do
log.write_critical (create {STRING}.make_from_separate (a_message)) if level >= log_critical then
log.write_critical (create {STRING}.make_from_separate (a_message))
end
end end
put_alert (a_message: separate READABLE_STRING_8) put_alert (a_message: separate READABLE_STRING_8)
-- Put message `a_message' to the log at alert level.
do do
log.write_alert (create {STRING}.make_from_separate (a_message)) if level >= log_alert then
end log.write_alert (create {STRING}.make_from_separate (a_message))
end
put_debug (a_message: separate READABLE_STRING_8)
do
log.write_debug (create {STRING}.make_from_separate (a_message))
end end
feature {NONE} -- Implementation feature {NONE} -- Implementation
initialize_logger (app: APPLICATION_LAYOUT; a_log: like log) initialize_logger (app: separate APPLICATION_ENVIRONMENT; a_log: like log)
local local
l_log_writer_file: LOG_ROLLING_WRITER_FILE l_log_writer_file: LOG_ROLLING_WRITER_FILE
l_log_writer: LOG_WRITER l_log_writer: detachable LOG_WRITER
l_logs_path: detachable PATH l_logs_path: detachable PATH
l_logger_config: LOGGER_CONFIGURATION l_logger_config: LOGGER_CONFIGURATION
ut: FILE_UTILITIES ut: FILE_UTILITIES
p: PATH
l_name: IMMUTABLE_STRING_32
do do
l_logger_config := new_logger_level_configuration (app.application_config_path) create l_name.make_from_separate (app.name)
l_logs_path := l_logger_config.location create p.make_from_separate (app.application_config_path)
if l_logs_path = Void then -- l_name := app.name
l_logs_path := app.logs_path -- p := app.application_config_path
l_logger_config := new_logger_level_configuration (p)
if l_logger_config.type.is_case_insensitive_equal_general ("file") then
l_logs_path := l_logger_config.location
if l_logs_path = Void then
create l_logs_path.make_from_separate (app.logs_path)
end
if ut.directory_path_exists (l_logs_path) then
create l_log_writer_file.make_at_location (l_logs_path.extended (l_name).appended_with_extension ("log"))
l_log_writer_file.set_max_file_size ({NATURAL_64} 1024 * 1204)
l_log_writer_file.set_max_backup_count (l_logger_config.backup_count)
l_log_writer := l_log_writer_file
else
-- Should we create the directory anyway ?
end
elseif l_logger_config.type.is_case_insensitive_equal_general ("stderr") then
create {LOG_WRITER_STDERR} l_log_writer
end end
if ut.directory_path_exists (l_logs_path) then if l_log_writer = Void then
create l_log_writer_file.make_at_location (l_logs_path.extended (app.name).appended_with_extension ("log"))
l_log_writer_file.set_max_file_size ({NATURAL_64} 1024 * 1204)
l_log_writer_file.set_max_backup_count (l_logger_config.backup_count)
l_log_writer := l_log_writer_file
else
-- Should we create the directory anyway ?
create {LOG_WRITER_NULL} l_log_writer create {LOG_WRITER_NULL} l_log_writer
set_logger_level (l_log_writer, log_notice)
else
set_logger_level (l_log_writer, 0) -- None
end end
set_logger_level (l_log_writer, l_logger_config.level)
a_log.register_log_writer (l_log_writer) a_log.register_log_writer (l_log_writer)
end end
set_logger_level (a_log_writer: LOG_WRITER; a_priority: INTEGER) set_logger_level (a_log_writer: LOG_WRITER; a_priority: INTEGER)
-- Setup the logger level based on `a_priority' -- Setup the logger level based on `a_priority'
do do
level := a_priority
if a_priority = log_debug then if a_priority = log_debug then
a_log_writer.enable_debug_log_level a_log_writer.enable_debug_log_level
elseif a_priority = Log_emergency then elseif a_priority = Log_emergency then
@@ -151,6 +199,9 @@ feature {NONE} -- Implementation
attached l_parser.parsed_json_object as jv and then attached l_parser.parsed_json_object as jv and then
attached {JSON_OBJECT} jv.item ("logger") as l_logger attached {JSON_OBJECT} jv.item ("logger") as l_logger
then then
if attached {JSON_STRING} l_logger.item ("type") as l_type then
Result.set_type_with_string (l_type.item)
end
if attached {JSON_STRING} l_logger.item ("location") as l_location then if attached {JSON_STRING} l_logger.item ("location") as l_location then
Result.set_location_with_string (l_location.item) Result.set_location_with_string (l_location.item)
end end

View File

@@ -22,7 +22,7 @@ feature -- Access
register_log_writer (a_log_writer: LOG_WRITER) 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 do
logging.register_log_writer (a_log_writer) logging.register_log_writer (a_log_writer)
end end

View File

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

View File

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

View File

@@ -1,21 +1,3 @@
<?xml version="1.0" encoding="ISO-8859-1"?> <?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="layout" uuid="7AE9E48B-5A15-43F8-B99A-04F4185DED6B" library_target="layout"> <redirection 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" uuid="7AE9E48B-5A15-43F8-B99A-04F4185DED6B" location="..\app_env\app_env-safe.ecf">
<target name="layout"> </redirection>
<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

@@ -1,21 +1,3 @@
<?xml version="1.0" encoding="ISO-8859-1"?> <?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="layout" uuid="7AE9E48B-5A15-43F8-B99A-04F4185DED6B" library_target="layout"> <redirection 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" uuid="7AE9E48B-5A15-43F8-B99A-04F4185DED6B" location="..\app_env\app_env.ecf">
<target name="layout"> </redirection>
<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,15 +0,0 @@
note
description: "[
Interface defining a CMS content type.
]"
status: "draft"
date: "$Date$"
revision: "$Revision$"
class
CMS_CONTENT_TYPE
note
copyright: "2011-2014, 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,200 +0,0 @@
note
description: "[
CMS abstraction for CMS content entity, named "node".
]"
status: "draft"
date: "$Date: 2015-01-27 19:15:02 +0100 (mar., 27 janv. 2015) $"
revision: "$Revision: 96542 $"
class
CMS_NODE
inherit
REFACTORING_HELPER
create
make,
make_empty
feature{NONE} -- Initialization
make_empty
-- Create empty node.
do
make ({STRING_32} "", {STRING_32} "", {STRING_32} "")
end
make (a_content: READABLE_STRING_32; a_summary: READABLE_STRING_32; a_title: READABLE_STRING_32)
-- Create current node with `a_content', `a_summary' and `a_title'.
local
l_time: DATE_TIME
do
create l_time.make_now_utc
set_content (a_content)
set_summary (a_summary)
set_title (a_title)
set_creation_date (l_time)
set_modification_date (l_time)
set_publication_date (l_time)
debug ("refactor_fixme")
fixme ("Remove default harcoded format")
end
set_format ("HTML")
debug ("refactor_fixme")
fixme ("Remove default harcoded content type")
end
set_content_type ("Page")
ensure
content_set: content = a_content
summary_set: summary = a_summary
title_set: title = a_title
end
feature -- Access
id: INTEGER_64 assign set_id
-- Unique id.
content: READABLE_STRING_32
-- Content of the node.
summary: READABLE_STRING_32
-- A short summary of the node.
title: READABLE_STRING_32
-- Full title of the node.
modification_date: DATE_TIME
-- When the node was updated.
creation_date: DATE_TIME
-- When the node was created.
publication_date: DATE_TIME
-- When the node was published.
publication_date_output: READABLE_STRING_32
-- Formatted output.
format: READABLE_STRING_32
-- Format associated with `body'.
-- For example: text, mediawiki, html, etc
content_type: READABLE_STRING_32
-- Associated content type name.
-- Page, Article, Blog, News, etc.
author: detachable CMS_USER
-- Author of current node.
feature -- status report
has_id: BOOLEAN
-- Has unique identifier?
do
Result := id > 0
end
feature -- Element change
set_content (a_content: like content)
-- Assign `content' with `a_content'.
do
content := a_content
ensure
content_assigned: content = a_content
end
set_summary (a_summary: like summary)
-- Assign `summary' with `a_summary'.
do
summary := a_summary
ensure
summary_assigned: summary = a_summary
end
set_title (a_title: like title)
-- Assign `title' with `a_title'.
do
title := a_title
ensure
title_assigned: title = a_title
end
set_modification_date (a_modification_date: like modification_date)
-- Assign `modification_date' with `a_modification_date'.
do
modification_date := a_modification_date
ensure
modification_date_assigned: modification_date = a_modification_date
end
set_creation_date (a_creation_date: like creation_date)
-- Assign `creation_date' with `a_creation_date'.
do
creation_date := a_creation_date
ensure
creation_date_assigned: creation_date = a_creation_date
end
set_publication_date (a_publication_date: like publication_date)
-- Assign `publication_date' with `a_publication_date'.
do
publication_date := a_publication_date
publication_date_output := publication_date.formatted_out ("yyyy/[0]mm/[0]dd")
ensure
publication_date_assigned: publication_date = a_publication_date
end
set_content_type (a_content_type: like content_type)
-- Assign `content_type' with `a_content_type'.
do
content_type := a_content_type
ensure
content_type_assigned: content_type = a_content_type
end
set_format (a_format: like format)
-- Assign `format' with `a_format'.
do
format := a_format
ensure
format_assigned: format = a_format
end
set_id (an_id: like id)
-- Assign `id' with `an_id'.
do
id := an_id
ensure
id_assigned: id = an_id
end
set_author (u: like author)
-- Assign 'author' with `u'
do
author := u
ensure
auther_set: author = u
end
-- add_collaborator (a_user: CMS_USER)
-- -- Add collaborator `a_user' to the collaborators list.
-- local
-- lst: like collaborators
-- do
-- lst := collaborators
-- if lst = Void then
-- create {ARRAYED_SET [CMS_USER]} lst.make (1)
-- collaborators := lst
-- end
-- lst.force (a_user)
-- 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

@@ -25,15 +25,13 @@ create
feature {NONE} -- Initialization feature {NONE} -- Initialization
make (a_title: detachable like title; a_location: like location) make (a_title: detachable READABLE_STRING_GENERAL; a_location: like location)
-- Create current local link with optional title `a_title' and location `a_location'. -- Create current local link with optional title `a_title' and location `a_location'.
require
is_valid_local_location_argument: not a_location.starts_with_general ("/")
do do
if a_title /= Void then
title := a_title
else
title := a_location
end
location := a_location location := a_location
set_title (a_title)
end end
feature -- Access feature -- Access
@@ -75,6 +73,16 @@ feature -- Status report
feature -- Element change feature -- Element change
set_title (a_title: detachable READABLE_STRING_GENERAL)
-- Set `title' to `a_title' or `location'.
do
if a_title /= Void then
title := a_title.as_string_32
else
title := location.as_string_32
end
end
add_link (lnk: CMS_LINK) add_link (lnk: CMS_LINK)
-- <Precursor> -- <Precursor>
local local

View File

@@ -62,6 +62,7 @@ feature -- Status report
end end
has (lnk: CMS_LINK): BOOLEAN has (lnk: CMS_LINK): BOOLEAN
-- Has the current Menu a link `lnk'.
do do
across across
items as ic items as ic
@@ -87,6 +88,7 @@ feature -- Element change
end end
set_title (t: like title) set_title (t: like title)
-- Set `title' with `t'.
do do
title := t title := t
end end

View File

@@ -0,0 +1,127 @@
note
description: "Summary description for {CMS_LOG}."
date: "$Date$"
revision: "$Revision$"
class
CMS_LOG
create
make
feature {NONE} -- Initialization
make (a_category: like category; a_message: like message; a_level: like level; a_date: detachable like date)
do
category := a_category
message := a_message
set_level (a_level)
if a_date = Void then
create date.make_now_utc
else
date := a_date
end
end
make_with_id (a_id: like id; a_category: like category; a_message: like message; a_level: like level; a_date: detachable like date)
do
id := a_id
make (a_category, a_message, a_level, a_date)
end
feature -- Access
id: INTEGER
-- Unique identifier of Current.
category: READABLE_STRING_8
-- Associated title (optional).
message: READABLE_STRING_8
-- Log message
level: INTEGER
-- Severity level
level_name: STRING
do
Result := level_to_string (level)
end
info: detachable READABLE_STRING_8
link: detachable CMS_LINK
date: DATE_TIME
feature -- status report
has_id: BOOLEAN
do
Result := id > 0
end
feature -- Change
set_id (a_id: like id)
require
not has_id
do
id := a_id
end
set_level (a_level: like level)
do
if a_level = 0 then
level := level_notice
else
level := a_level
end
end
set_link (lnk: like link)
do
link := lnk
end
set_info (inf: like info)
do
info := inf
end
feature -- Constants
level_to_string (a_level: INTEGER): STRING
do
inspect a_level
when level_emergency then
Result := "emergency"
when level_alert then
Result := "alert"
when level_critical then
Result := "critical"
when level_error then
Result := "error"
when level_warning then
Result := "warning"
when level_notice then
Result := "notice"
when level_info then
Result := "info"
when level_debug then
Result := "debug"
else
Result := "level-" + a_level.out
end
end
level_emergency: INTEGER = 1
level_alert: INTEGER = 2
level_critical: INTEGER = 3
level_error: INTEGER = 4
level_warning: INTEGER = 5
level_notice: INTEGER = 6
level_info: INTEGER = 7
level_debug: INTEGER = 8
end

View File

@@ -0,0 +1,19 @@
note
description: "Partial CMS USER."
date: "$Date$"
revision: "$Revision$"
class
CMS_PARTIAL_USER
inherit
CMS_USER
create
make,
make_with_id -- MAYBE: export to CMS_STORAGE
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

@@ -27,6 +27,7 @@ feature {NONE} -- Initialization
initialize initialize
ensure ensure
name_set: name = a_name name_set: name = a_name
status_not_active: status = not_active
end end
make_with_id (a_id: INTEGER_64) make_with_id (a_id: INTEGER_64)
@@ -38,11 +39,13 @@ feature {NONE} -- Initialization
initialize initialize
ensure ensure
id_set: id = a_id id_set: id = a_id
status_not_active: status = not_active
end end
initialize initialize
do do
create creation_date.make_now_utc create creation_date.make_now_utc
mark_not_active
end end
feature -- Access feature -- Access
@@ -71,6 +74,18 @@ feature -- Access
last_login_date: detachable DATE_TIME last_login_date: detachable DATE_TIME
-- User last login. -- User last login.
status: INTEGER
-- Associated status for the current user.
-- default: not_active
-- active
-- trashed
feature -- Roles
roles: detachable LIST [CMS_USER_ROLE]
-- If set, list of roles for current user.
feature -- Access: data feature -- Access: data
data: detachable STRING_TABLE [detachable ANY] data: detachable STRING_TABLE [detachable ANY]
@@ -113,6 +128,12 @@ feature -- Status report
Result := other /= Void and then id = other.id Result := other /= Void and then id = other.id
end end
is_active: BOOLEAN
-- is the current user active?
do
Result := status = {CMS_USER}.active
end
feature -- Change element feature -- Change element
set_id (a_id: like id) set_id (a_id: like id)
@@ -189,6 +210,14 @@ feature -- Change element
set_last_login_date (create {DATE_TIME}.make_now_utc) set_last_login_date (create {DATE_TIME}.make_now_utc)
end end
feature -- Element change: roles
set_roles (lst: like roles)
-- Set `roles' to `lst'.
do
roles := lst
end
feature -- Change element: data feature -- Change element: data
set_data_item (k: READABLE_STRING_GENERAL; d: like data_item) set_data_item (k: READABLE_STRING_GENERAL; d: like data_item)
@@ -212,11 +241,57 @@ feature -- Change element: data
end end
end end
feature -- Status change
mark_not_active
-- Set status to not_active
do
set_status (not_active)
ensure
status_not_active: status = not_active
end
mark_active
-- Set status to active.
do
set_status (active)
ensure
status_active: status = active
end
mark_trashed
-- Set status to trashed.
do
set_status (trashed)
ensure
status_trash: status = trashed
end
set_status (a_status: like status)
-- Assign `status' with `a_status'.
do
status := a_status
ensure
status_set: status = a_status
end
feature -- User status
not_active: INTEGER = 0
-- The user is not active.
active: INTEGER = 1
-- The user is active
Trashed: INTEGER = -1
-- The user is trashed (soft delete), ready to be deleted/destroyed from storage.
invariant invariant
id_or_name_set: id > 0 or else not name.is_whitespace id_or_name_set: id > 0 or else not name.is_whitespace
note 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)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end end

View File

@@ -22,15 +22,25 @@ create
feature {NONE} -- Initialization feature {NONE} -- Initialization
make_with_id (a_id: like id; a_name: like name) make_with_id (a_id: like id)
-- Create current role with role id `a_id'.
do do
id := a_id id := a_id
make (a_name) name := {STRING_32} ""
initialize
end end
make (a_name: like name) make (a_name: like name)
-- Create current role with name `a_name'.
require
a_name_valid: not a_name.is_whitespace
do do
name := a_name name := a_name
initialize
end
initialize
do
create {ARRAYED_LIST [READABLE_STRING_8]} permissions.make (0) create {ARRAYED_LIST [READABLE_STRING_8]} permissions.make (0)
end end
@@ -42,10 +52,10 @@ feature -- Status report
Result := id > 0 Result := id > 0
end end
has_permission (p: READABLE_STRING_8): BOOLEAN has_permission (p: READABLE_STRING_GENERAL): BOOLEAN
-- Has permission `p'? -- Has permission `p'?
do do
Result := across permissions as c some c.item.is_case_insensitive_equal (p) end Result := across permissions as c some p.is_case_insensitive_equal (c.item) end
end end
feature -- Access feature -- Access
@@ -53,7 +63,7 @@ feature -- Access
id: INTEGER id: INTEGER
-- Unique id associated with Current role. -- Unique id associated with Current role.
name: READABLE_STRING_8 name: READABLE_STRING_32
-- Name of Current role. -- Name of Current role.
permissions: LIST [READABLE_STRING_8] permissions: LIST [READABLE_STRING_8]
@@ -115,6 +125,6 @@ feature -- Permission change
end end
note 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)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end end

View File

@@ -1,6 +1,5 @@
note note
description: "Summary description for {CMS_STORAGE_STORE_SQL}." description: "Storage based on Eiffel Store component."
author: ""
date: "$Date: 2015-02-13 13:08:13 +0100 (ven., 13 févr. 2015) $" date: "$Date: 2015-02-13 13:08:13 +0100 (ven., 13 févr. 2015) $"
revision: "$Revision: 96616 $" revision: "$Revision: 96616 $"
@@ -8,8 +7,6 @@ deferred class
CMS_STORAGE_STORE_SQL CMS_STORAGE_STORE_SQL
inherit inherit
CMS_STORAGE
CMS_STORAGE_SQL CMS_STORAGE_SQL
feature {NONE} -- Initialization feature {NONE} -- Initialization
@@ -25,7 +22,6 @@ feature {NONE} -- Initialization
create {DATABASE_HANDLER_IMPL} db_handler.make (a_connection) create {DATABASE_HANDLER_IMPL} db_handler.make (a_connection)
create error_handler.make create error_handler.make
-- error_handler.add_synchronization (db_handler.database_error_handler)
end end
feature -- Status report feature -- Status report
@@ -36,6 +32,15 @@ feature -- Status report
Result := connection.is_connected Result := connection.is_connected
end end
feature -- Basic operation
close
-- <Precursor>
-- Disconnect from SQL database.
do
connection.disconnect
end
feature {NONE} -- Implementation feature {NONE} -- Implementation
db_handler: DATABASE_HANDLER db_handler: DATABASE_HANDLER
@@ -55,21 +60,25 @@ feature -- Query
end end
sql_begin_transaction sql_begin_transaction
-- <Precursor>
do do
connection.begin_transaction connection.begin_transaction
end end
sql_rollback_transaction sql_rollback_transaction
-- <Precursor>
do do
connection.rollback connection.rollback
end end
sql_commit_transaction sql_commit_transaction
-- <Precursor>
do do
connection.commit connection.commit
end end
sql_query (a_sql_statement: STRING; a_params: detachable STRING_TABLE [detachable ANY]) sql_query (a_sql_statement: STRING; a_params: detachable STRING_TABLE [detachable ANY])
-- Execute an sql query `a_sql_statement' with the params `a_params'.
do do
check_sql_query_validity (a_sql_statement, a_params) check_sql_query_validity (a_sql_statement, a_params)
db_handler.set_query (create {DATABASE_QUERY}.data_reader (a_sql_statement, a_params)) db_handler.set_query (create {DATABASE_QUERY}.data_reader (a_sql_statement, a_params))
@@ -78,6 +87,7 @@ feature -- Query
end end
sql_change (a_sql_statement: STRING; a_params: detachable STRING_TABLE [detachable ANY]) sql_change (a_sql_statement: STRING; a_params: detachable STRING_TABLE [detachable ANY])
-- Execute an sql query change `a_sql_statement' with the params `a_params'.
do do
check_sql_query_validity (a_sql_statement, a_params) check_sql_query_validity (a_sql_statement, a_params)
db_handler.set_query (create {DATABASE_QUERY}.data_reader (a_sql_statement, a_params)) db_handler.set_query (create {DATABASE_QUERY}.data_reader (a_sql_statement, a_params))
@@ -109,6 +119,11 @@ feature -- Query
db_handler.forth db_handler.forth
end end
sql_valid_item_index (a_index: INTEGER): BOOLEAN
do
Result := attached {DB_TUPLE} db_handler.item as l_item and then l_item.valid_index (a_index)
end
sql_item (a_index: INTEGER): detachable ANY sql_item (a_index: INTEGER): detachable ANY
do do
if attached {DB_TUPLE} db_handler.item as l_item and then l_item.count >= a_index then if attached {DB_TUPLE} db_handler.item as l_item and then l_item.count >= a_index then

View File

@@ -0,0 +1,16 @@
note
description: "[
Common ancestor for builders responsible to instantiate storage based
on Eiffel Store storage.
]"
author: "$Author: jfiat $"
date: "$Date: 2015-02-13 13:08:13 +0100 (ven., 13 févr. 2015) $"
revision: "$Revision: 96616 $"
deferred class
CMS_STORAGE_STORE_SQL_BUILDER
inherit
CMS_STORAGE_SQL_BUILDER
end

View File

@@ -8,16 +8,16 @@ deferred class
feature -- Database access feature -- Database access
hostname: STRING = "" default_hostname: STRING = ""
-- Database hostname. -- Database hostname.
username: STRING = "" default_username: STRING = ""
-- Database username. -- Database username.
password: STRING = "" default_password: STRING = ""
-- Database password. -- Database password.
database_name: STRING = "EiffelDB" default_database_name: STRING = "EiffelDB"
-- Database name. -- Database name.
is_keep_connection: BOOLEAN is_keep_connection: BOOLEAN

View File

@@ -12,27 +12,7 @@ inherit
feature {NONE} -- Initialization feature {NONE} -- Initialization
make_common login (a_username: STRING; a_password: STRING; a_hostname: STRING; a_database_name: STRING; connection: BOOLEAN)
-- Create a database handler with common settings.
deferred
ensure
db_application_not_void: db_application /= Void
db_control_not_void: db_control /= Void
end
make_basic ( a_database_name: STRING)
-- Create a database handler with common settings and
-- set database_name with `a_database_name'.
require
database_name_not_void: a_database_name /= Void
database_name_not_empty: not a_database_name.is_empty
deferred
ensure
db_application_not_void: db_application /= Void
db_control_not_void: db_control /= Void
end
make (a_username: STRING; a_password: STRING; a_hostname: STRING; a_database_name: STRING; connection: BOOLEAN)
-- Create a database handler with user `a_username', password `a_password', -- Create a database handler with user `a_username', password `a_password',
-- host `a_hostname', database_name `a_database_name', and keep_connection `connection'. -- host `a_hostname', database_name `a_database_name', and keep_connection `connection'.
@@ -59,6 +39,26 @@ feature {NONE} -- Initialization
db_control_not_void: db_control /= Void db_control_not_void: db_control /= Void
end end
login_with_default
-- Create a database handler with common settings.
deferred
ensure
db_application_not_void: db_application /= Void
db_control_not_void: db_control /= Void
end
login_with_database_name ( a_database_name: STRING)
-- Create a database handler with common settings and
-- set database_name with `a_database_name'.
require
database_name_not_void: a_database_name /= Void
database_name_not_empty: not a_database_name.is_empty
deferred
ensure
db_application_not_void: db_application /= Void
db_control_not_void: db_control /= Void
end
feature -- Database Setup feature -- Database Setup
db_application: DATABASE_APPL [DATABASE] db_application: DATABASE_APPL [DATABASE]
@@ -168,7 +168,7 @@ feature -- Error Handling
database_error_handler: DATABASE_ERROR_HANDLER database_error_handler: DATABASE_ERROR_HANDLER
-- Error handler. -- Error handler.
feature -- Status Report feature -- Status Report
has_error: BOOLEAN has_error: BOOLEAN
@@ -179,11 +179,11 @@ feature -- Status Report
feature -- Helper feature -- Helper
exception_as_error (a_e: like {EXCEPTION_MANAGER}.last_exception) exception_as_error (a_exception: like {EXCEPTION_MANAGER}.last_exception)
-- Record exception as an error. -- Record exception `a_exception' as an error.
do do
if attached a_e as l_e and then attached l_e.trace as l_trace then if a_exception /= Void and then attached a_exception.trace as l_trace then
database_error_handler.add_error_details (l_e.code, once "Exception", l_trace.as_string_32) database_error_handler.add_error_details (a_exception.code, once "Exception", l_trace)
end end
end end

View File

@@ -15,11 +15,11 @@ inherit
end end
create create
make, make_common, make_basic login, login_with_default, login_with_database_name
feature -- Initialization feature -- Initialization
make_common login_with_default
-- Create a database handler for ODBC with common settings. -- Create a database handler for ODBC with common settings.
do do
create database_error_handler.make create database_error_handler.make
@@ -30,18 +30,18 @@ feature -- Initialization
create db_control.make create db_control.make
end end
make (a_username: STRING; a_password: STRING; a_hostname: STRING; a_database_name: STRING; connection: BOOLEAN) login (a_username: STRING; a_password: STRING; a_hostname: STRING; a_database_name: STRING; connection: BOOLEAN)
-- Create a database handler for ODBC. -- Create a database handler for ODBC.
do do
make_common login_with_default
end end
make_basic (a_database_name: STRING) login_with_database_name (a_database_name: STRING)
-- Create a database handler for ODBC. -- Create a database handler for ODBC.
do do
make_common login_with_default
end end
@@ -49,7 +49,7 @@ feature -- Initialization
-- Login with `a_connection_string' -- Login with `a_connection_string'
-- and immediately connect to database. -- and immediately connect to database.
do do
make_common login_with_default
end end

View File

@@ -7,117 +7,97 @@ class
DATABASE_CONNECTION_ODBC DATABASE_CONNECTION_ODBC
inherit inherit
DATABASE_CONNECTION DATABASE_CONNECTION
redefine redefine
db_application db_application
end end
SHARED_LOGGER
create create
make, make_common, make_basic, login_with_connection_string login, login_with_default, login_with_database_name, login_with_connection_string
feature -- Initialization feature -- Initialization
make_common login (a_username: STRING; a_password: STRING; a_hostname: STRING; a_database_name: STRING; a_keep_connection: BOOLEAN)
-- Create a database handler for ODBC with common settings.
local
l_retried: BOOLEAN
do
create db_application.login (username, password)
create database_error_handler.make
if not l_retried then
db_application.set_hostname (hostname)
db_application.set_data_source (database_name)
db_application.set_base
create db_control.make
keep_connection := is_keep_connection
if keep_connection then
connect
end
else
create db_control.make
end
rescue
create db_control.make
-- set_last_error_from_exception ("Connection execution")
-- write_critical_log (generator + ".make_common:" + last_error_message)
if is_connected then
disconnect
end
l_retried := True
retry
end
make_basic (a_database_name: STRING)
-- Create a database handler and
-- set database_name to `a_database_name'.
local
l_retried: BOOLEAN
do
create db_application.login (username, password)
create database_error_handler.make
if not l_retried then
db_application.set_hostname (hostname)
db_application.set_data_source (a_database_name)
db_application.set_base
create db_control.make
keep_connection := is_keep_connection
if keep_connection then
connect
end
else
create db_control.make
end
rescue
create db_control.make
-- set_last_error_from_exception ("Connection execution")
-- write_critical_log (generator + ".make_common:" + last_error_message)
if is_connected then
disconnect
end
l_retried := True
retry
end
make (a_username: STRING; a_password: STRING; a_hostname: STRING; a_database_name: STRING; connection: BOOLEAN)
-- Create a database handler for ODBC and set `username' to `a_username', -- Create a database handler for ODBC and set `username' to `a_username',
-- `password' to `a_password' -- `password' to `a_password'
-- `database_name' to `a_database_name' -- `database_name' to `a_database_name'
-- `connection' to `a_connection' -- `keep_connection' to `a_keep_connection'
local
retried: BOOLEAN
l_database_error_handler: detachable like database_error_handler
do do
create database_error_handler.make create l_database_error_handler.make
database_error_handler := l_database_error_handler
create db_application.login (a_username, a_password) create db_application.login (a_username, a_password)
db_application.set_hostname (a_hostname) if not retried then
db_application.set_data_source (a_database_name) db_application.set_hostname (a_hostname)
db_application.set_base db_application.set_data_source (a_database_name)
create db_control.make db_application.set_base
keep_connection := connection create db_control.make
if keep_connection then keep_connection := a_keep_connection
connect if keep_connection then
connect
end
else
create db_control.make
if is_connected then
disconnect
end
end end
rescue
if l_database_error_handler = Void then
create l_database_error_handler.make
end
database_error_handler := l_database_error_handler
exception_as_error ((create {EXCEPTION_MANAGER}).last_exception)
retried := True
retry
end
login_with_default
-- Create a database handler for ODBC with common settings.
do
login_with_database_name (default_database_name)
end
login_with_database_name (a_database_name: STRING)
-- Create a database handler and
-- set database_name to `a_database_name'.
do
login (default_username, default_password, default_hostname, default_database_name, is_keep_connection)
end end
login_with_connection_string (a_string: STRING) login_with_connection_string (a_string: STRING)
-- Login with `a_connection_string'and immediately connect to database. -- Login with `a_connection_string'and immediately connect to database.
local
retried: BOOLEAN
l_database_error_handler: detachable like database_error_handler
do do
write_debug_log (generator +".login_with_connection_string") create l_database_error_handler.make
database_error_handler := l_database_error_handler
create db_application.login_with_connection_string (a_string) create db_application.login_with_connection_string (a_string)
create database_error_handler.make if not retried then
db_application.set_base db_application.set_base
create db_control.make create db_control.make
write_debug_log (generator +".login_with_connection_string, is_keep_connection? "+ is_keep_connection.out ) keep_connection := is_keep_connection
keep_connection := is_keep_connection if keep_connection then
if keep_connection then connect
connect end
if not db_control.is_ok then else
write_critical_log (generator +".login_with_connection_string:"+ db_control.error_code.out ) create db_control.make
write_critical_log (generator +".login_with_connection_string:"+ db_control.error_message_32 ) if is_connected then
disconnect
end end
write_debug_log (generator +".login_with_connection_string, After connect, is_connected? "+ is_connected.out)
end end
rescue
if l_database_error_handler = Void then
create l_database_error_handler.make
end
database_error_handler := l_database_error_handler
exception_as_error ((create {EXCEPTION_MANAGER}).last_exception)
retried := True
retry
end end
feature -- Databse Connection feature -- Databse Connection

View File

@@ -1,35 +0,0 @@
<?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="persistence_mysql" uuid="DC757CBD-D8C4-44D6-A07F-C1148D8D233E" library_target="persistence_mysql">
<target name="persistence_mysql">
<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="cms" location="..\..\..\cms.ecf" readonly="false"/>
<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"/>
<library name="error" location="$ISE_LIBRARY\contrib\library\utility\general\error\error.ecf"/>
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json.ecf" readonly="false"/>
<library name="layout" location="..\..\layout\layout.ecf"/>
<library name="logging" location="$ISE_LIBRARY\library\runtime\logging\logging.ecf"/>
<library name="model" location="..\..\model\cms_model.ecf"/>
<library name="mysql" location="$ISE_LIBRARY\library\store\dbms\rdbms\mysql\mysql.ecf"/>
<library name="store" location="$ISE_LIBRARY\library\store\store.ecf" readonly="false"/>
<library name="thread" location="$ISE_LIBRARY\library\thread\thread.ecf"/>
<library name="time" location="$ISE_LIBRARY\library\time\time.ecf"/>
<cluster name="common" location="..\implementation\store\" recursive="true">
<file_rule>
<exclude>/database/database_connection_odbc.e</exclude>
</file_rule>
</cluster>
<cluster name="persistence_mysql" location=".\src\" recursive="true">
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
</cluster>
</target>
</system>

View File

@@ -1,3 +0,0 @@
To build the MySQL schema use the schema.sql script.
The other script will be deleted soon.

View File

@@ -1 +0,0 @@
Added Stored Procedures

View File

@@ -0,0 +1,30 @@
BEGIN;
CREATE TABLE `logs` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`category` VARCHAR(255) NOT NULL,
`level` int(11) NOT NULL,
`uid` int(11) DEFAULT NULL,
`message` text NOT NULL,
`info` text,
`link` text,
`date` datetime NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `custom_values` (
`type` VARCHAR(255) NOT NULL,
`name` VARCHAR(255) NOT NULL,
`value` VARCHAR(255) NOT NULL
);
CREATE TABLE `path_aliases` (
`pid` int(11) NOT NULL AUTO_INCREMENT,
`source` varchar(255) NOT NULL,
`alias` varchar(255) NOT NULL,
`lang` varchar(12) DEFAULT NULL,
PRIMARY KEY (`pid`)
);
COMMIT;

View File

@@ -1,163 +0,0 @@
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';
-- -----------------------------------------------------
-- Schema mydb
-- -----------------------------------------------------
-- -----------------------------------------------------
-- Schema cms_dev
-- -----------------------------------------------------
CREATE SCHEMA IF NOT EXISTS `cms_dev` DEFAULT CHARACTER SET latin1 ;
USE `cms_dev` ;
-- -----------------------------------------------------
-- Table `cms_dev`.`users`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `cms_dev`.`users` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`username` VARCHAR(100) NOT NULL,
`password` VARCHAR(100) NOT NULL,
`salt` VARCHAR(100) NOT NULL,
`email` VARCHAR(250) NOT NULL,
`creation_date` DATETIME NULL DEFAULT NULL,
`last_login_date` DATETIME NULL DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `username` (`username` ASC))
ENGINE = InnoDB
AUTO_INCREMENT = 2
DEFAULT CHARACTER SET = latin1;
-- -----------------------------------------------------
-- Table `cms_dev`.`nodes`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `cms_dev`.`nodes` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`publication_date` DATE NOT NULL,
`creation_date` DATE NOT NULL,
`modification_date` DATE NOT NULL,
`title` VARCHAR(255) NOT NULL,
`summary` TEXT NOT NULL,
`content` MEDIUMTEXT NOT NULL,
`author_id` INT(10) UNSIGNED NULL DEFAULT NULL,
`version` INT(10) UNSIGNED ZEROFILL NULL DEFAULT NULL,
`editor_id` INT(10) UNSIGNED NULL DEFAULT NULL,
PRIMARY KEY (`id`),
INDEX `fk_nodes_users1_idx` (`author_id` ASC),
INDEX `fk_nodes_users2_idx` (`editor_id` ASC),
CONSTRAINT `fk_nodes_users1`
FOREIGN KEY (`author_id`)
REFERENCES `cms_dev`.`users` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_nodes_users2`
FOREIGN KEY (`editor_id`)
REFERENCES `cms_dev`.`users` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
AUTO_INCREMENT = 11
DEFAULT CHARACTER SET = latin1;
-- -----------------------------------------------------
-- Table `cms_dev`.`roles`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `cms_dev`.`roles` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`role` VARCHAR(100) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `role` (`role` ASC))
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;
-- -----------------------------------------------------
-- Table `cms_dev`.`permissions`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `cms_dev`.`permissions` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(45) NOT NULL,
`roles_id` INT(10) UNSIGNED NOT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `name_UNIQUE` (`name` ASC),
INDEX `fk_permissions_roles1_idx` (`roles_id` ASC),
CONSTRAINT `fk_permissions_roles1`
FOREIGN KEY (`roles_id`)
REFERENCES `cms_dev`.`roles` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;
-- -----------------------------------------------------
-- Table `cms_dev`.`profiles`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `cms_dev`.`profiles` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`key` VARCHAR(45) NOT NULL,
`value` VARCHAR(100) NULL DEFAULT NULL,
`users_id` INT(10) UNSIGNED NOT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `key_UNIQUE` (`key` ASC),
INDEX `fk_profiles_users1_idx` (`users_id` ASC),
CONSTRAINT `fk_profiles_users1`
FOREIGN KEY (`users_id`)
REFERENCES `cms_dev`.`users` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;
-- -----------------------------------------------------
-- Table `cms_dev`.`users_nodes`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `cms_dev`.`users_nodes` (
`users_id` INT(10) UNSIGNED NOT NULL,
`nodes_id` INT(10) UNSIGNED NOT NULL,
PRIMARY KEY (`users_id`, `nodes_id`),
INDEX `fk_users_has_nodes_nodes1_idx` (`nodes_id` ASC),
INDEX `fk_users_has_nodes_users_idx` (`users_id` ASC),
CONSTRAINT `fk_users_has_nodes_nodes1`
FOREIGN KEY (`nodes_id`)
REFERENCES `cms_dev`.`nodes` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_users_has_nodes_users`
FOREIGN KEY (`users_id`)
REFERENCES `cms_dev`.`users` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;
-- -----------------------------------------------------
-- Table `cms_dev`.`users_roles`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `cms_dev`.`users_roles` (
`users_id` INT(10) UNSIGNED NOT NULL,
`roles_id` INT(10) UNSIGNED NOT NULL,
PRIMARY KEY (`users_id`, `roles_id`),
INDEX `fk_users_has_roles_roles1_idx` (`roles_id` ASC),
INDEX `fk_users_has_roles_users1_idx` (`users_id` ASC),
CONSTRAINT `fk_users_has_roles_roles1`
FOREIGN KEY (`roles_id`)
REFERENCES `cms_dev`.`roles` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_users_has_roles_users1`
FOREIGN KEY (`users_id`)
REFERENCES `cms_dev`.`users` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;
SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;

View File

@@ -0,0 +1,24 @@
BEGIN;
CREATE TABLE nodes (
nid INTEGER PRIMARY KEY AUTO_INCREMENT 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 AUTO_INCREMENT NOT NULL CHECK( nid >=0),
revision INTEGER,
parent INTEGER
);
COMMIT;

View File

@@ -1,72 +0,0 @@
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';
-- -----------------------------------------------------
-- Schema mydb
-- -----------------------------------------------------
-- -----------------------------------------------------
-- Schema roc_cms
-- -----------------------------------------------------
DROP SCHEMA IF EXISTS `roc_cms` ;
CREATE SCHEMA IF NOT EXISTS `roc_cms` DEFAULT CHARACTER SET latin1 ;
USE `roc_cms` ;
-- -----------------------------------------------------
-- Table `roc_cms`.`nodes`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `roc_cms`.`nodes` ;
CREATE TABLE IF NOT EXISTS `roc_cms`.`nodes` (
`nid` INT(11) NOT NULL AUTO_INCREMENT,
`version` INT(11) NULL DEFAULT NULL,
`type` INT(11) NULL DEFAULT NULL,
`title` VARCHAR(255) NOT NULL,
`summary` TEXT NOT NULL,
`content` MEDIUMTEXT NOT NULL,
`author` INT(11) NULL DEFAULT NULL,
`publish` DATETIME NULL DEFAULT NULL,
`created` DATETIME NOT NULL,
`changed` DATETIME NOT NULL,
PRIMARY KEY (`nid`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;
-- -----------------------------------------------------
-- Table `roc_cms`.`users`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `roc_cms`.`users` ;
CREATE TABLE IF NOT EXISTS `roc_cms`.`users` (
`uid` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(100) NOT NULL,
`password` VARCHAR(100) NOT NULL,
`salt` VARCHAR(100) NOT NULL,
`email` VARCHAR(250) NOT NULL,
`status` INT(11) NULL DEFAULT NULL,
`created` DATETIME NOT NULL,
`signed` DATETIME NULL DEFAULT NULL,
PRIMARY KEY (`uid`),
UNIQUE INDEX `name` (`name` ASC))
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;
-- -----------------------------------------------------
-- Table `roc_cms`.`users_roles`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `roc_cms`.`users_roles` ;
CREATE TABLE IF NOT EXISTS `roc_cms`.`users_roles` (
`rid` INT(11) NOT NULL AUTO_INCREMENT,
`role` VARCHAR(100) NOT NULL,
PRIMARY KEY (`rid`),
UNIQUE INDEX `role` (`role` ASC))
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;
SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;

View File

@@ -1,14 +0,0 @@
DROP TABLE IF EXISTS nodes;
CREATE TABLE nodes
(
id smallint unsigned NOT NULL auto_increment,
publication_date date NOT NULL, #When the article was published
creation_date date NOT NULL, #When the article was created
modification_date date NOT NULL, #When the article was updated
title varchar(255) NOT NULL, #Full title of the article
summary text NOT NULL, #A short summary of the articule
content mediumtext NOT NULL, #The HTML content of the article
PRIMARY KEY (ID)
);

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