Compare commits

...

44 Commits

Author SHA1 Message Date
04df6b85f0 Removed unused local variables. 2015-11-12 18:48:37 +01:00
79d30ee3a7 Added export of core data, such as users, path_aliases, custom_values.
Added export of node revisions.
2015-11-12 18:19:06 +01:00
a5973c9c8a Added exportation solution via CMS_HOOK_EXPORT.
Updated blocks settings for demo example project.
2015-11-10 10:30:10 +01:00
420051cd14 Redesigned hooks system (moving from CMS_RESPONSE to CMS_API).
Indeed, hooks does not require RESPONSE interface,
   and should be setup before, at the system level (i.e CMS_API)
Added exportation solution via CMS_HOOK_EXPORT.
Updated blocks settings for demo example project.
2015-11-09 21:07:02 +01:00
6b3ff6f980 Fixed list item computation for ini file, especially with included ini file. 2015-11-02 21:07:26 +01:00
360855a558 Fixed recent_changes module to allow alias of recent_changes blocks.
Factorized code in CMS_RESPONSE by reusing add_block.
2015-11-02 18:54:30 +01:00
6aaec0be9f Fixed table item computation for ini file, especially with included ini file. 2015-11-02 18:10:27 +01:00
cb6d13b5f7 Updated gcse library to use unique own uuid in ecf file. 2015-11-02 14:38:36 +01:00
951c977892 Use relative paths from google_search ecf files to other local cms library .ecf files. 2015-11-02 14:33:14 +01:00
2a4ebfa12e Updated google search libary ecf files to have better void-safe .ecf file. 2015-11-02 14:22:41 +01:00
955852747a Include google_search engine in example/demo installation script. 2015-11-02 11:18:45 +01:00
23fe22cad1 Google search module:
- cleanup unwanted file
- fixed bad indentation in html template.
2015-11-02 11:16:54 +01:00
da4b36869a Include the launcher during installation (install.bat). 2015-11-02 10:50:27 +01:00
5624892ebc Updated code related to cache management in CMS core and modules. 2015-11-02 10:50:05 +01:00
jvelilla
e40a7969fa Merge branch 'jvelilla-roc_gcse' 2015-10-26 10:51:51 -03:00
jvelilla
67fdd357df Merge branch 'master' of https://github.com/EiffelWebFramework/ROC into roc_gcse
Conflicts:
	examples/demo/demo-safe.ecf
2015-10-23 16:48:25 -03:00
5b0ab76434 Fixed more unicode issues, or being more flexible when loading from database. 2015-10-20 19:02:04 +02:00
a84f86d7a2 Addressed various unicode related issues.
Note this is using recent changes from text_filter library.
2015-10-20 18:49:40 +02:00
3f4e70b98c Updated roc tools, and associated scripts.
Also include Eiffel Store ODBC persistence.
2015-10-20 11:29:16 +02:00
782e9397a3 Added missing sql_finalize which is used to cleanup as early as possible the last statement when it is not needed anymore. 2015-10-19 23:33:17 +02:00
f51ddc9796 Extracted launcher code into cms/launcher/... libraries.
(mostly to help new project based on ROC CMS).
Renamed and simplified the roc cms server launcher, and the related cms execution.
Updated cms.ini and extract blocks related management into blocks.ini.
Added debug clauses for cms sqlite3 storage.
2015-10-19 22:50:48 +02:00
a260bbc2c5 Removed obsolete usage of {TYPE}.attempt from CMS_MODULE_COLLECTION. 2015-10-19 20:50:47 +02:00
eb5ae32e46 Added persistence support for Eiffel sqlite3 wrapper.
Updated existing persistency solution to be more generic to any db solution.
2015-10-19 11:24:22 +02:00
7fcacad5eb Use extended type support from EiffelStore to handle STRING_32, and other extended types. 2015-10-19 11:20:04 +02:00
7c99f2dc83 Added recent_changes.ecf 2015-10-18 20:47:33 +02:00
57430193e3 Fixed compilation of CMS_FILE_BLOCK. 2015-10-18 19:24:43 +02:00
62bf58ce6d Added support for block options for the feed aggregator blocks.
Updated weight for primary_tabs block.
2015-10-17 00:17:59 +02:00
23c395513b Fixed handling of block and optional block.
- All blocks behavior can be specified and overwritten via the configuaration.
  - And optional block are not displayed by default.
2015-10-16 23:46:18 +02:00
d2d86ecdf2 Added notion of block options, declared in cms.ini as
[blocks]
    {block_id}.options[name]=value
    {block_id}.options[size]=123
2015-10-16 23:11:44 +02:00
e90f82387f Added notion of alias block, to provide a way to include a block content in mutiple regions. 2015-10-16 23:02:47 +02:00
05472abdd7 Improved block condition "path:..." by allowing wildchar.
Added weight data to CMS_BLOCK to be able to sort the block lists,
  and thus order the display of blocks.
Set negative weight for various core block, so that they appear first as expected.
The weight can be set and overwritten in cms.ini , by pref  blocks.{block_id}.weight=integer_weight.
2015-10-16 17:22:22 +02:00
jvelilla
193760b34f Remove unneeded file. 2015-10-14 11:57:06 -03:00
jvelilla
9263f31521 Renamed module name to google_search (custom_search)
Clean code.
Updated google custom search to handle quota limit and no query submit.
Updated encoding issues for input searches: like "void safe" and "void + safe".
2015-10-14 11:51:59 -03:00
jvelilla
454d92f85b Merge https://github.com/EiffelWebFramework/ROC into roc_gcse 2015-10-14 11:45:33 -03:00
788cf3738d Fixed compilation of CMS_BLOCK_LOCATION_CONDITION (not used for now). 2015-10-14 14:20:55 +02:00
jvelilla
0e63c14613 Added Module Custom Search
Added Google custom search library
Added HTTP client extension libaray
Updated demo example to use the Module Custom Search
2015-10-13 10:23:30 -03:00
f6185612b2 Fixed compilation issue. 2015-10-12 19:42:09 +02:00
d37f45d958 Include block caches clearing during "clear_cache" hook invocation. 2015-10-12 19:39:41 +02:00
872f2a177d For now, only clear feed aggregation cache if clear all cache is requested. 2015-10-12 19:22:37 +02:00
3ed2f410d9 Added feeds.json example in feed_aggregator module folder. 2015-10-12 19:15:09 +02:00
1b451ef142 Moved the feeds.json example in associated module files. 2015-10-12 19:12:42 +02:00
50146985de Added CMS_HOOK_CACHE, and admin cache.
Prepared evolution of feed module, by allowing json object to list feeds locations.
   The associated key will be used to identify the location, and have category filter by location.
2015-10-12 19:03:12 +02:00
8cdf9ba973 Updated demo feed info. 2015-10-12 19:00:46 +02:00
8044f7d52b Implemented feed aggregation filtering based on categories. 2015-10-12 15:53:50 +02:00
123 changed files with 4967 additions and 438 deletions

View File

@@ -1,5 +1,5 @@
<?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">
<target name="cms">
<root all_classes="true"/>
<file_rule>
@@ -14,14 +14,16 @@
<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_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="cms_config" location=".\library\configuration\config-safe.ecf"/>
<library name="cms_model" location=".\library\model\cms_model-safe.ecf" readonly="false"/>
<library name="crypto" location="$ISE_LIBRARY\unstable\library\text\encryption\crypto\crypto-safe.ecf"/>
<library name="encoder" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\text\encoder\encoder-safe.ecf" readonly="false"/>
<library name="error" location="$ISE_LIBRARY\contrib\library\utility\general\error\error-safe.ecf"/>
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-safe.ecf"/>
<library name="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="kmp_matcher" location="$ISE_LIBRARY\library\text\regexp\kmp_matcher\kmp_matcher-safe.ecf"/>
<library name="net" location="$ISE_LIBRARY\library\net\net-safe.ecf"/>
<library name="notification_mailer" location="$ISE_LIBRARY\contrib\library\runtime\process\notification_email\notification_email-safe.ecf"/>
<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"/>
@@ -30,7 +32,6 @@
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
<library name="wsf_extension" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf_extension-safe.ecf" readonly="false"/>
<library name="wsf_html" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf_html\wsf_html-safe.ecf" readonly="false"/>
<library name="net" location="$ISE_LIBRARY\library\net\net-safe.ecf"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
</system>

View File

@@ -15,14 +15,16 @@
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
<library name="base_extension" location="$ISE_LIBRARY\library\base_extension\base_extension.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="cms_config" location=".\library\configuration\config.ecf"/>
<library name="cms_model" location=".\library\model\cms_model.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" readonly="false"/>
<library name="error" location="$ISE_LIBRARY\contrib\library\utility\general\error\error.ecf"/>
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http.ecf"/>
<library name="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="kmp_matcher" location="$ISE_LIBRARY\library\text\regexp\kmp_matcher\kmp_matcher.ecf"/>
<library name="net" location="$ISE_LIBRARY\library\net\net.ecf"/>
<library name="notification_mailer" location="$ISE_LIBRARY\contrib\library\runtime\process\notification_email\notification_email.ecf"/>
<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"/>
@@ -31,7 +33,6 @@
<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_html" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf_html\wsf_html.ecf" readonly="false"/>
<library name="net" location="$ISE_LIBRARY\library\net\net.ecf"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
</system>

View File

@@ -1,7 +1,8 @@
<?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-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="demo" uuid="3643E657-BCBE-46AA-931B-71EAEA877A18" library_target="demo">
<description>Example/demo for Eiffel ROC CMS library</description>
<target name="common" abstract="true">
<root class="DEMO_CMS_SERVER" feature="make_and_launch"/>
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
@@ -12,7 +13,12 @@
</option>
<setting name="concurrency" value="thread"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="cms" location="..\..\cms-safe.ecf" readonly="false"/>
<library name="cms" location="..\..\cms-safe.ecf" readonly="false">
<option>
<assertions precondition="true" postcondition="true" supplier_precondition="true"/>
</option>
</library>
<library name="cms_admin_module" location="..\..\modules\admin\admin-safe.ecf" readonly="false"/>
<library name="cms_app_env" location="..\..\library\app_env\app_env-safe.ecf" readonly="false"/>
<library name="cms_auth_module" location="..\..\modules\auth\auth-safe.ecf" readonly="false"/>
<library name="cms_basic_auth_module" location="..\..\modules\basic_auth\basic_auth-safe.ecf" readonly="false"/>
@@ -20,38 +26,37 @@
<library name="cms_demo_module" location="modules\demo\cms_demo_module-safe.ecf" readonly="false"/>
<library name="cms_email_service" location="..\..\library\email\email-safe.ecf" readonly="false"/>
<library name="cms_feed_aggregator_module" location="..\..\modules\feed_aggregator\feed_aggregator-safe.ecf" readonly="false"/>
<library name="cms_google_search_module" location="..\..\modules\google_search\google_search-safe.ecf" readonly="false" use_application_options="true"/>
<library name="cms_model" location="..\..\library\model\cms_model-safe.ecf" readonly="false"/>
<library name="cms_node_module" location="..\..\modules\node\node-safe.ecf" readonly="false"/>
<library name="cms_oauth_20_module" location="..\..\modules\oauth20\oauth20-safe.ecf" readonly="false"/>
<library name="cms_openid_module" location="..\..\modules\openid\openid-safe.ecf" readonly="false"/>
<library name="cms_admin_module" location="..\..\modules\admin\admin-safe.ecf" readonly="false"/>
<library name="cms_recent_changes_module" location="..\..\modules\recent_changes\recent_changes-safe.ecf" readonly="false"/>
<library name="persistence_store_odbc" location="..\..\library\persistence\store_odbc\store_odbc-safe.ecf" readonly="false"/>
<library name="persistence_sqlite3" location="..\..\library\persistence\sqlite3\sqlite3-safe.ecf" readonly="false">
<option>
<assertions/>
</option>
</library>
<library name="persistence_store_odbc" location="..\..\library\persistence\store_odbc\store_odbc-safe.ecf" />
<!--
<library name="persistence_store_mysql" location="..\..\library\persistence\store_mysql\store_mysql-safe.ecf" readonly="false"/>
<library name="persistence_store_mysql" location="..\..\library\persistence\store_mysql\store_mysql-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"/>
</target>
<target name="demo_any" extends="common">
<root class="EWF_ROC_SERVER" feature="make_and_launch"/>
<setting name="concurrency" value="thread"/>
<library name="cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\cgi-safe.ecf"/>
<library name="libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\libfcgi-safe.ecf"/>
<library name="nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\nino-safe.ecf"/>
<library name="standalone" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\standalone-safe.ecf"/>
<cluster name="launcher" location=".\launcher\any\" recursive="true"/>
<library name="any_launcher" location="..\..\launcher\any-safe.ecf" readonly="false"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
<target name="demo_standalone" extends="common">
<root class="EWF_ROC_SERVER" feature="make_and_launch"/>
<option debug="true">
<debug name="dbglog" enabled="true"/>
</option>
<setting name="concurrency" value="thread"/>
<setting name="concurrency" value="scoop"/>
<variable name="httpd_ssl_disabled" value="true"/>
<library name="default_standalone" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\standalone-safe.ecf"/>
<cluster name="launcher" location=".\launcher\default\" recursive="true"/>
<library name="standalone_launcher" location="..\..\launcher\standalone-safe.ecf" readonly="false"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
<target name="demo_standalone_none" extends="demo_standalone">
@@ -63,25 +68,14 @@
<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"/>
<library name="cgi_launcher" location="..\..\launcher\cgi-safe.ecf" readonly="false"/>
<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"/>
<library name="libfcgi_launcher" location="..\..\launcher\libfcgi-safe.ecf" readonly="false"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
<target name="demo" extends="demo_standalone">

View File

@@ -11,3 +11,4 @@ set ROC_CMS_DIR=%~dp0
%ROC_CMD% install --module ..\..\modules\openid --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\recent_changes --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\feed_aggregator --dir %ROC_CMS_DIR%
%ROC_CMD% install --module ..\..\modules\google_search --dir %ROC_CMS_DIR%

View File

@@ -0,0 +1,25 @@
### Blocks settings
#navigation.region=sidebar_first
#navigation.condition=is_front
management.conditions[]=path:admin*
management.conditions[]=is_front
#Feeds
feed.news.weight=3
feed.news.region=feed_news
feed.news.region=content
feed.news.condition=is_front
feed.forum.weight=2
feed.forum.region=feed_forum
feed.forum.region=content
feed.forum.condition=is_front
feed.forum.options[size]=5
#Updates
recent_changes.region=content
recent_changes.condition=is_front
recent_changes.title=Updates
recent_changes.options[size]=4

View File

@@ -9,9 +9,9 @@ email=your@email.com
theme=bootstrap
[mailer]
smtp=localhost:25
#smtp=localhost:25
#sendmail=/usr/bin/sendmail
#output=@stderr
output=@stderr
[modules]
# Module status
@@ -21,30 +21,10 @@ smtp=localhost:25
# for each module, this can be overwritten with
# module_name= on or off
*=all
admin=on
auth=on
basic_auth=on
blog=on
debug=on
demo=on
node=on
oauth20=on
openid=on
[blocks]
#navigation.region=sidebar_first
feed.eiffel.region=feed_eiffel
feed.eiffel.condition=is_front
feed.forum.region=feed_forum
feed.forum.condition=is_front
feed.stackoverflow.region=feed_stackoverflow
feed.stackoverflow.condition=is_front
#management.condition=is_front
#navigation.condition=is_front
@include=blocks.ini
[admin]
# CMS Installation, are accessible by "all", "none" or uppon "permission". (default is none)
installation_access=permission
installation_access=all

View File

@@ -1,10 +1,15 @@
{
"database": {
"datasource": {
"driver": "odbc",
"environment": "odbc-sqlite"
"driver": "sqlite3",
"environment": "sqlite3",
"-driver": "odbc",
"-environment": "odbc-sqlite"
},
"environments": {
"sqlite3": {
"connection_string":"Database=./site/database.sqlite3;"
},
"odbc-sqlite": {
"connection_string":"Driver=SQLite3 ODBC Driver;Database=./site/database.sqlite;LongNames=0;Timeout=1000;NoTXN=0;SyncPragma=NORMAL;StepAPI=0;"
},

View File

@@ -1,28 +0,0 @@
{
"ids": ["eiffel", "forum"],
"feeds": {
"eiffel": {
"title": "Eiffel related posts.",
"expiration": "21600",
"size": 10,
"locations": [
"https://bertrandmeyer.com/feed/",
"https://room.eiffel.com/blog/feed",
"https://room.eiffel.com/article/feed",
"https://room.eiffel.com/library/feed"
]
, "categories": ["Eiffel"]
,"option_description": "enabled"
},
"forum": {
"title": "Eiffel Forum",
"expiration": "21600",
"size": 10,
"locations": [
"https://groups.google.com/forum/feed/eiffel-users/msgs/atom.xml?num=15".
"http://stackoverflow.com/feeds/tag?tagnames=eiffel&sort=newest"
]
,"option_description": "enabled"
}
}
}

View File

@@ -0,0 +1,28 @@
{
"ids": ["news", "forum"],
"feeds": {
"news": {
"title": "Eiffel related posts",
"expiration": "21600",
"size": 5,
"locations": [
"https://bertrandmeyer.com/feed/",
"https://room.eiffel.com/blog/feed",
"https://room.eiffel.com/article/feed",
"https://room.eiffel.com/library/feed"
]
, "categories": ["Eiffel"]
,"option_description": "enabled"
},
"forum": {
"title": "Eiffel Forum",
"expiration": "21600",
"size": 5,
"locations": [
"https://groups.google.com/forum/feed/eiffel-users/msgs/atom.xml?num=15",
"http://stackoverflow.com/feeds/tag?tagnames=eiffel&sort=newest"
]
,"option_description": "enabled"
}
}
}

View File

@@ -0,0 +1,6 @@
{
"gcse": {
"cx":"",
"secret_key":""
}
}

View File

@@ -0,0 +1,40 @@
<section>
<header>
<h2>Results for <kbd>{$result.current_page.search_terms/}</kbd></h2>
</header>
<!-- list of results -->
<ol start="{$result.current_page.start_index/}">
<!-- Item result -->
{foreach from="$result.items" item="item"}
<li>
<article>
<header>
<h3>
<cite>
<a href="{$item.link/}">{$item.title/}</a>
</cite>
</h3>
</header>
<blockquote cite="{$item.link/}">
<p>{$item.html_snippet/}</p>
<footer>
<p><abbr title="Uniform Resource Locator">Source</abbr> <a href="{$item.link/}">{$item.display_link/}</a></p>
</footer>
</blockquote>
</article>
</li>
{/foreach}
</ol>
<ul class="cms-page-links">
{if isset="$result.previous_page"}
<li><a href="{$site_url/}gcse/?q={$result.previous_page.search_terms/}&amp;start={$result.previous_page.start_index/}&amp;num={$result.previous_page.count/}">Previous</a></li>
{/if}
{if isset="$result.next_page"}
<li><a href="{$site_url/}gcse/?q={$result.next_page.search_terms/}&amp;start={$result.next_page.start_index/}&amp;num={$result.next_page.count/}">Next</a></li>
{/if}
</ul>
</section>

View File

@@ -0,0 +1,8 @@
$(document).ready(function() {
$('#gcse_search_form').submit(function() {
window.open('', 'formpopup', 'width=600,height=600,resizeable,scrollbars');
this.target = 'formpopup';
});
});

View File

@@ -5,9 +5,10 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- EWF CMS -->
<link rel="stylesheet" href="{$site_url/}theme/css/style.css">
<!-- jQuery dep -->
<script src="{$site_url/}theme/js/jquery-1.10.2.min.js"></script>
<script src="{$site_url/}theme/js/popup_search.js"></script>
{if isset="$head"}{$head/}{/if}
{if isset="$styles"}{$styles/}{/if}
@@ -36,7 +37,17 @@
{$page.primary_nav/}
{/if}
</div>
<!-- Page search -->
<div class="row">
<div class="col-md-2 col-md-offset-9">
<form action="{$site_url/}gcse" class="search-form" id="gcse_search_form">
<div class="form-group has-feedback">
<input type="search" class="form-control" name="q" id="gcse_search" placeholder="search">
<span class="glyphicon glyphicon-search form-control-feedback"></span>
</div>
</form>
</div>
</div>
<!-- General Page Content -->
<div id='content' class='row-fluid'>
<!-- Left Sidebar sidebar_first -->
@@ -63,8 +74,8 @@
{unless isempty="$page_title"}<h1 class="page-title">{$page_title/}</h1>{/unless}
{$page.region_content/}
{if condition="$page.is_front"}
{if isset="$page.region_feed_eiffel"}
<div class="column" style="width: 45%; float: left">{$page.region_feed_eiffel/}</div>
{if isset="$page.region_feed_news"}
<div class="column" style="width: 45%; float: left">{$page.region_feed_news/}</div>
{/if}
{if isset="$page.region_feed_forum"}
<div class="column" style="width: 45%; float: left">{$page.region_feed_forum/}</div>

View File

@@ -1,31 +1,21 @@
note
description: "Summary description for {EWF_ROC_SERVER_EXECUTION}."
description: "[
CMS Execution for the demo server.
]"
date: "$Date$"
revision: "$Revision$"
class
EWF_ROC_SERVER_EXECUTION
DEMO_CMS_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
@@ -39,17 +29,17 @@ feature {NONE} -- Initialization
create Result.make (l_env)
end
feature -- CMS setup
feature -- CMS storage
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_SQLITE3_BUILDER}.make, "sqlite3")
-- 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
feature -- CMS modules
setup_modules (a_setup: CMS_SETUP)
-- Setup additional modules.
local
@@ -92,6 +82,9 @@ feature -- CMS setup
create {CMS_DEMO_MODULE} m.make
a_setup.register_module (m)
create {GOOGLE_CUSTOM_SEARCH_MODULE} m.make
a_setup.register_module (m)
end
end

View File

@@ -0,0 +1,18 @@
note
description: "[
DEMO application server.
]"
date: "$Date: 2015-02-09 22:29:56 +0100 (lun., 09 févr. 2015) $"
revision: "$Revision: 96596 $"
class
DEMO_CMS_SERVER
inherit
ROC_CMS_LAUNCHER [DEMO_CMS_EXECUTION]
create
make_and_launch
end

10
launcher/README.txt Normal file
View File

@@ -0,0 +1,10 @@
Collection of ROC CMS launcher ready to use.
- Include any-safe.ecf to use any of cgi, libfcgi or standalone connector.
- Include standalone-safe.ecf to use standalone connector.
- Include libfcgi-safe.ecf to use libfcgi connector.
- Include cgi-safe.ecf to use cgi connector.
In application, the root class need to inherit from ROC_CMS_LAUNCHER with adapted CMS_EXECUTION
descendant.

18
launcher/any-safe.ecf Normal file
View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<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="launcher" uuid="6FDCA393-AFC3-436B-A58A-870923967C86" library_target="launcher">
<target name="common" abstract="true">
<root all_classes="true"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="cms" location="..\cms-safe.ecf"/>
<library name="cms_app_env" location="..\library\app_env\app_env-safe.ecf" readonly="false"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
</target>
<target name="launcher" extends="common">
<library name="cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\cgi-safe.ecf"/>
<library name="libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\libfcgi-safe.ecf"/>
<library name="nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\nino-safe.ecf"/>
<library name="standalone" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\standalone-safe.ecf"/>
<cluster name="src" location=".\" recursive="false"/>
<cluster name="launcher" location=".\any\" recursive="true"/>
</target>
</system>

19
launcher/any.ecf Normal file
View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<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="launcher" uuid="6FDCA393-AFC3-436B-A58A-870923967C86" library_target="launcher">
<target name="common" abstract="true">
<root all_classes="true"/>
<option void_safety="none" />
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
<library name="cms" location="..\cms.ecf"/>
<library name="cms_app_env" location="..\library\app_env\app_env.ecf" readonly="false"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf.ecf"/>
</target>
<target name="launcher" extends="common">
<library name="cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\cgi.ecf"/>
<library name="libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\libfcgi.ecf"/>
<library name="nino" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\nino.ecf"/>
<library name="standalone" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\standalone.ecf"/>
<cluster name="src" location=".\" recursive="false"/>
<cluster name="launcher" location=".\any\" recursive="true"/>
</target>
</system>

View File

@@ -0,0 +1,19 @@
note
description: "[
Effective class for APPLICATION_LAUNCHER_I
You can put modification in this class
]"
date: "$Date: 2013-06-12 13:55:42 +0200 (mer., 12 juin 2013) $"
revision: "$Revision: 36 $"
class
APPLICATION_LAUNCHER [G -> WSF_EXECUTION create make end]
inherit
APPLICATION_LAUNCHER_I [G]
feature -- Custom
end

View File

@@ -0,0 +1,127 @@
note
description: "[
Specific application launcher
DO NOT EDIT THIS CLASS
you can customize APPLICATION_LAUNCHER
]"
date: "$Date: 2013-06-12 13:55:42 +0200 (mer., 12 juin 2013) $"
revision: "$Revision: 36 $"
deferred class
APPLICATION_LAUNCHER_I [G -> WSF_EXECUTION create make end]
inherit
SHARED_EXECUTION_ENVIRONMENT
feature -- Execution
launch (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
local
nature: like launcher_nature
do
nature := launcher_nature
if nature = Void then
launch_standalone (opts)
elseif nature = nature_standalone then
launch_standalone (opts)
elseif nature = nature_nino then
launch_nino (opts)
elseif nature = nature_cgi then
launch_cgi (opts)
elseif nature = nature_libfcgi then
launch_libfcgi (opts)
else
-- bye bye
(create {EXCEPTIONS}).die (-1)
end
end
feature {NONE} -- Access
launcher_nature: detachable READABLE_STRING_8
-- Initialize the launcher nature
-- either cgi, libfcgi, or nino.
--| We could extend with more connector if needed.
--| and we could use WSF_DEFAULT_SERVICE_LAUNCHER to configure this at compilation time.
local
p: PATH
ext: detachable READABLE_STRING_32
do
create p.make_from_string (execution_environment.arguments.command_name)
if attached p.entry as l_entry then
ext := l_entry.extension
end
if ext /= Void then
if ext.same_string (nature_standalone) then
Result := nature_standalone
end
if ext.same_string (nature_nino) then
Result := nature_nino
end
if ext.same_string (nature_cgi) then
Result := nature_cgi
end
if ext.same_string (nature_libfcgi) or else ext.same_string ("fcgi") then
Result := nature_libfcgi
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
feature {NONE} -- nino
nature_nino: STRING = "nino"
launch_nino (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
local
launcher: WSF_NINO_SERVICE_LAUNCHER [G]
do
create launcher.make_and_launch (opts)
end
feature {NONE} -- cgi
nature_cgi: STRING = "cgi"
launch_cgi (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
local
launcher: WSF_CGI_SERVICE_LAUNCHER [G]
do
create launcher.make_and_launch (opts)
end
feature {NONE} -- libfcgi
nature_libfcgi: STRING = "libfcgi"
launch_libfcgi (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
local
launcher: WSF_LIBFCGI_SERVICE_LAUNCHER [G]
do
create launcher.make_and_launch (opts)
end
feature -- Default
default_nature: STRING
do
Result := nature_standalone
end
end

15
launcher/cgi-safe.ecf Normal file
View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<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="cgi_launcher" uuid="0FE4F1D0-BB70-4C7F-A66E-B27F1D718109" library_target="cgi_launcher">
<target name="common" abstract="true">
<root all_classes="true"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="cms" location="..\cms-safe.ecf"/>
<library name="cms_app_env" location="..\library\app_env\app_env-safe.ecf" readonly="false"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
</target>
<target name="cgi_launcher" extends="common">
<library name="default_cgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\cgi-safe.ecf"/>
<cluster name="src" location=".\" recursive="false"/>
<cluster name="launcher" location=".\default\" recursive="true"/>
</target>
</system>

View File

@@ -0,0 +1,19 @@
note
description: "[
Effective class for APPLICATION_LAUNCHER_I
You can put modification in this class
]"
date: "$Date: 2013-06-12 13:55:42 +0200 (mer., 12 juin 2013) $"
revision: "$Revision: 36 $"
class
APPLICATION_LAUNCHER [G -> WSF_EXECUTION create make end]
inherit
APPLICATION_LAUNCHER_I [G]
feature -- Custom
end

View File

@@ -0,0 +1,26 @@
note
description: "[
Specific application launcher
DO NOT EDIT THIS CLASS
you can customize APPLICATION_LAUNCHER
]"
date: "$Date: 2015-02-09 22:29:56 +0100 (lun., 09 févr. 2015) $"
revision: "$Revision: 96596 $"
deferred class
APPLICATION_LAUNCHER_I [G -> WSF_EXECUTION create make end]
feature -- Execution
launch (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
local
launcher: WSF_DEFAULT_SERVICE_LAUNCHER [G]
do
create launcher.make_and_launch (opts)
end
end

15
launcher/libfcgi-safe.ecf Normal file
View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<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="libfcgi_launcher" uuid="04D7D1EA-059B-4024-B0DE-BBB57AB2D00C" library_target="libfcgi_launcher">
<target name="common" abstract="true">
<root all_classes="true"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="cms" location="..\cms-safe.ecf"/>
<library name="cms_app_env" location="..\library\app_env\app_env-safe.ecf" readonly="false"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
</target>
<target name="libfcgi_launcher" extends="common">
<library name="default_libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\libfcgi-safe.ecf"/>
<cluster name="src" location=".\" recursive="false"/>
<cluster name="launcher" location=".\default\" recursive="true"/>
</target>
</system>

16
launcher/libfcgi.ecf Normal file
View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<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="libfcgi_launcher" uuid="04D7D1EA-059B-4024-B0DE-BBB57AB2D00C" library_target="libfcgi_launcher">
<target name="common" abstract="true">
<root all_classes="true"/>
<option void_safety="none" />
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
<library name="cms" location="..\cms.ecf"/>
<library name="cms_app_env" location="..\library\app_env\app_env.ecf" readonly="false"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf.ecf"/>
</target>
<target name="libfcgi_launcher" extends="common">
<library name="default_libfcgi" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\libfcgi.ecf"/>
<cluster name="src" location=".\" recursive="false"/>
<cluster name="launcher" location=".\default\" recursive="true"/>
</target>
</system>

View File

@@ -1,12 +1,12 @@
note
description: "[
application service
Reusable ROC CMS launcher.
]"
date: "$Date: 2015-02-09 22:29:56 +0100 (lun., 09 févr. 2015) $"
revision: "$Revision: 96596 $"
class
EWF_ROC_SERVER
ROC_CMS_LAUNCHER [G -> CMS_EXECUTION create make end]
inherit
WSF_LAUNCHABLE_SERVICE
@@ -37,16 +37,27 @@ feature {NONE} -- Initialization
-- Initialize current service.
local
env: CMS_ENVIRONMENT
l_app_name: detachable READABLE_STRING_32
do
Precursor
create {WSF_SERVICE_LAUNCHER_OPTIONS_FROM_INI} service_options.make_from_file ("demo.ini")
create env.make_default
l_app_name := optional_application_name
if l_app_name = Void then
l_app_name := env.name
end
create {WSF_SERVICE_LAUNCHER_OPTIONS_FROM_INI} service_options.make_from_file (l_app_name + ".ini")
initialize_logger (env)
end
optional_application_name: detachable READABLE_STRING_32
-- Optional application name.
--| Redefine if needed.
do
end
feature {NONE} -- Launch operation
launcher: APPLICATION_LAUNCHER [EWF_ROC_SERVER_EXECUTION]
launcher: APPLICATION_LAUNCHER [G]
launch (opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
local
@@ -70,7 +81,7 @@ feature {NONE} -- Launch operation
l_message.append ("%N%N")
end
else
l_message.append ("The application crash without available information")
l_message.append ("The application crashed without information.")
l_message.append ("%N%N")
end
-- send email shutdown

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<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="standalone_launcher" uuid="F42660A9-26C2-466B-A63C-C7823C808BE7" library_target="standalone_launcher">
<target name="common" abstract="true">
<root all_classes="true"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="cms" location="..\cms-safe.ecf"/>
<library name="cms_app_env" location="..\library\app_env\app_env-safe.ecf" readonly="false"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>
</target>
<target name="standalone_launcher" extends="common">
<library name="default_standalone" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\standalone-safe.ecf"/>
<library name="standalone" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\standalone-safe.ecf"/>
<cluster name="src" location=".\" recursive="false"/>
<cluster name="launcher" location=".\default\" recursive="true"/>
</target>
</system>

17
launcher/standalone.ecf Normal file
View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<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="standalone_launcher" uuid="F42660A9-26C2-466B-A63C-C7823C808BE7" library_target="standalone_launcher">
<target name="common" abstract="true">
<root all_classes="true"/>
<option void_safety="none" />
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
<library name="cms" location="..\cms.ecf"/>
<library name="cms_app_env" location="..\library\app_env\app_env.ecf" readonly="false"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf.ecf"/>
</target>
<target name="standalone_launcher" extends="common">
<library name="default_standalone" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\default\standalone.ecf"/>
<library name="standalone" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\connector\standalone.ecf"/>
<cluster name="src" location=".\" recursive="false"/>
<cluster name="launcher" location=".\default\" recursive="true"/>
</target>
</system>

View File

@@ -442,7 +442,17 @@ feature {NONE} -- Implementation
j := k.index_of (']', i + 1)
if j = i + 1 then -- ends_with "[]"
k.keep_head (i - 1)
if attached {LIST [STRING_8]} items.item (k) as l_list then
if
a_section_prefix /= Void and then
attached {LIST [STRING_8]} items.item (a_section_prefix + {STRING_32} "." + k) as l_list
then
lst := l_list
elseif
attached last_section_name as l_section_prefix and then
attached {LIST [STRING_8]} items.item (l_section_prefix + {STRING_32} "." + k) as l_list
then
lst := l_list
elseif attached {LIST [STRING_8]} items.item (k) as l_list then
lst := l_list
else
create {ARRAYED_LIST [STRING_8]} lst.make (1)
@@ -456,7 +466,17 @@ feature {NONE} -- Implementation
sk.left_adjust
sk.right_adjust
k.keep_head (i - 1)
if attached {STRING_TABLE [STRING_8]} items.item (k) as l_table then
if
a_section_prefix /= Void and then
attached {STRING_TABLE [STRING_8]} items.item (a_section_prefix + {STRING_32} "." + k) as l_table
then
tb := l_table
elseif
attached last_section_name as l_section_prefix and then
attached {STRING_TABLE [STRING_8]} items.item (l_section_prefix + {STRING_32} "." + k) as l_table
then
tb := l_table
elseif attached {STRING_TABLE [STRING_8]} items.item (k) as l_table then
tb := l_table
else
create tb.make (1)

4
library/gcse/Readme.md Normal file
View File

@@ -0,0 +1,4 @@
Google Custom Search Engine Eiffel Lbrary
Based on https://developers.google.com/custom-search/json-api/v1/using_rest

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<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="gcse" uuid="81645CEF-4651-45CF-A890-B126E4A6D78C" library_target="gcse">
<target name="gcse">
<root all_classes="true"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<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="http_client_extension" location="..\http_client_extension\http_client_extension-safe.ecf" readonly="false"/>
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json-safe.ecf" readonly="false"/>
<library name="wsf_encoder" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\text\encoder\encoder-safe.ecf"/>
<cluster name="gcse" location=".\src\" recursive="true"/>
</target>
</system>

21
library/gcse/gcse.ecf Normal file
View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<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="gcse" uuid="81645CEF-4651-45CF-A890-B126E4A6D78C" library_target="gcse">
<target name="gcse">
<root all_classes="true"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<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="http_client_extension" location="..\http_client_extension\http_client_extension.ecf" readonly="false"/>
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json.ecf" readonly="false"/>
<library name="wsf_encoder" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\text\encoder\encoder.ecf"/>
<cluster name="gcse" location=".\src\" recursive="true"/>
</target>
</system>

10
library/gcse/license.lic Normal file
View File

@@ -0,0 +1,10 @@
${NOTE_KEYWORD}
copyright: "2011-${YEAR} Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"

236
library/gcse/src/gcse_api.e Normal file
View File

@@ -0,0 +1,236 @@
note
description: "[
Simple API to call Google Custome Search Engine
Example call:
GET https://www.googleapis.com/customsearch/v1?key=INSERT_YOUR_API_KEY&cx=017576662512468239146:omuauf_lfve&q=lectures
]"
date: "$Date: 2015-10-09 08:11:07 -0300 (vi., 09 oct. 2015) $"
revision: "$Revision: 97973 $"
EIS: "name=Google Custom Search Engine", "src=https://developers.google.com/custom-search/json-api/v1/using_rest", "protocol=uri"
class
GCSE_API
create
make
feature {NONE} -- Initialization
make (a_query_parameters: GCSE_QUERY_PARAMETERS)
-- Create an object GCSE with query_parameters `a_query_parameters'
do
query_parameter := a_query_parameters
ensure
query_parameters_set: query_parameter = a_query_parameters
end
feature -- Access
base_uri: STRING_8 = "https://www.googleapis.com/customsearch/v1"
-- Google custom search base URI.
query_parameter: GCSE_QUERY_PARAMETERS
-- Google custom search parameters.
last_result: detachable GCSE_RESPONSE
-- Search results.
feature -- Status Reports
errors: detachable LIST [READABLE_STRING_8]
-- optional list of error messages.
feature -- API
search
-- Search
local
l_parser: JSON_PARSER
l_gcse_response: detachable GCSE_RESPONSE
do
-- Data format for the response.
-- At the moment we are using the default value: json
-- but it's possible to define atom response using the alt parameter.
last_result := Void
if attached get as l_response then
create l_gcse_response
l_gcse_response.set_status (l_response.status)
l_gcse_response.set_status_nessage (l_response.status_message)
if attached l_response.body as l_body then
create l_parser.make_with_string (l_body)
l_parser.parse_content
if l_response.status = 200 and then l_parser.is_parsed and then attached {JSON_OBJECT} l_parser.parsed_json_object as jv then
-- Queries
if attached {JSON_OBJECT} jv.item (queries_key) as jqueries then
-- Next Page
if attached {GCSE_PAGE} query_page (next_page_key, jqueries) as l_page then
l_gcse_response.set_next_page (l_page)
end
-- Current Page
if attached {GCSE_PAGE} query_page (request_key, jqueries) as l_page then
l_gcse_response.set_current_page (l_page)
end
-- Previous Page
if attached {GCSE_PAGE} query_page (previous_page_key, jqueries) as l_page then
l_gcse_response.set_previous_page (l_page)
end
end
if attached {JSON_ARRAY} jv.item (items_key) as jitems then
across jitems as ic loop
if attached{JSON_OBJECT} ic.item as j_item then
l_gcse_response.add_item (item (j_item))
end
end
end
else
put_error (l_body)
end
else
put_error (l_response.status.out)
end
else
put_error ("unknown")
end
last_result := l_gcse_response
end
feature {NONE} -- REST API
get: detachable RESPONSE
-- Reading Data.
local
l_request: REQUEST
do
create l_request.make ("GET", new_uri)
Result := l_request.execute
end
feature {NONE} -- Implementation
new_uri: STRING_8
-- new uri (BaseUri?key=secret_value&cx=a_cx_id&q=a_query
-- ?key=INSERT_YOUR_API_KEY&cx=017576662512468239146:omuauf_lfve&q=lectures
-- full template BaseUri?q={searchTerms}&num={count?}&start={startIndex?}&lr={language?}&
-- safe={safe?}&cx={cx?}&cref={cref?}&sort={sort?}&filter={filter?}&gl={gl?}&cr={cr?}&
-- googlehost={googleHost?}&c2coff={disableCnTwTranslation?}&hq={hq?}&hl={hl?}&siteSearch={siteSearch?}&
-- siteSearchFilter={siteSearchFilter?}&exactTerms={exactTerms?}&excludeTerms={excludeTerms?}&linkSite={linkSite?}&
-- orTerms={orTerms?}&relatedSite={relatedSite?}&dateRestrict={dateRestrict?}&lowRange={lowRange?}&highRange={highRange?}&
-- searchType={searchType}&fileType={fileType?}&rights={rights?}&imgSize={imgSize?}&imgType={imgType?}&
-- imgColorType={imgColorType?}&imgDominantColor={imgDominantColor?}&alt=json"
do
create Result.make_from_string (base_uri)
Result.append ("?key=")
Result.append (query_parameter.secret)
Result.append ("&cx=")
Result.append (query_parameter.cx)
Result.append ("&q=")
Result.append (query_parameter.query)
-- num
if attached query_parameter.num as l_num then
Result.append ("&num=")
Result.append (l_num)
end
if attached query_parameter.start as l_start then
Result.append ("&start=")
Result.append (l_start)
end
end
put_error (a_message: READABLE_STRING_GENERAL)
-- put error message `a_message'.
local
l_errors: like errors
utf: UTF_CONVERTER
do
l_errors := errors
if l_errors = Void then
create {ARRAYED_LIST [STRING]} l_errors.make (1)
errors := l_errors
end
l_errors.force (utf.utf_32_string_to_utf_8_string_8 (a_message))
end
item (a_item: JSON_OBJECT): GCSE_PAGE_ITEM
-- Google Result Metadata Item.
do
create Result
if attached {JSON_STRING} a_item.item ("kind") as l_kind then
Result.set_kind (l_kind.item)
end
if attached {JSON_STRING} a_item.item ("title") as l_title then
Result.set_title (l_title.item)
end
if attached {JSON_STRING} a_item.item ("htmlTitle") as l_htmltitle then
Result.set_html_title (l_htmltitle.unescaped_string_32)
end
if attached {JSON_STRING} a_item.item ("link") as l_link then
Result.set_link (l_link.item)
end
if attached {JSON_STRING} a_item.item ("displayLink") as l_display_link then
Result.set_display_link (l_display_link.item)
end
if attached {JSON_STRING} a_item.item ("snippet") as l_snippet then
Result.set_snippet (l_snippet.unescaped_string_8)
end
if attached {JSON_STRING} a_item.item ("htmlSnippet") as l_html_snippet then
Result.set_html_snippet (l_html_snippet.unescaped_string_32)
end
if attached {JSON_STRING} a_item.item ("formattedUrl") as l_formatted_url then
Result.set_formatted_url (l_formatted_url.item)
end
end
query_page (a_page_key: JSON_STRING; a_queries: JSON_OBJECT): detachable GCSE_PAGE
-- Google result medata query. Return a query page based for a query with page key `a_page_key', if any.
do
if
attached {JSON_ARRAY} a_queries.item (a_page_key) as jquerypage and then
jquerypage.count > 0 and then
attached {JSON_OBJECT} jquerypage.i_th (1) as jpage
then
create Result
if attached {JSON_STRING} jpage.item ("title") as l_title then
Result.set_title (l_title.item)
end
if attached {JSON_STRING} jpage.item ("totalResults") as l_results then
Result.set_total_results (l_results.item.to_integer)
end
if attached {JSON_STRING} jpage.item ("searchTerms") as l_search_terms then
Result.set_search_terms (l_search_terms.item)
end
-- TODO check if we should use INTEGER_64
if attached {JSON_NUMBER} jpage.item ("count") as l_count then
Result.set_count (l_count.integer_64_item.as_integer_32)
end
if attached {JSON_NUMBER} jpage.item ("startIndex") as l_index then
Result.set_start_index (l_index.integer_64_item.as_integer_32)
end
end
end
feature {NONE} -- JSON Keys
queries_key: STRING = "queries"
next_page_key: STRING = "nextPage"
request_key: STRING = "request"
previous_page_key: STRING = "previousPage"
items_key: STRING = "items"
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)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,118 @@
note
description: "Represent metadata describing the query for the current set of results."
date: "$Date: 2015-10-09 08:11:07 -0300 (vi., 09 oct. 2015) $"
revision: "$Revision: 97973 $"
class
GCSE_PAGE
inherit
DEBUG_OUTPUT
feature -- Access
search_terms: detachable STRING_8
-- search term
title: detachable STRING_8
-- Search title.
total_results: INTEGER
-- Search total results.
count: INTEGER
-- Rows per page.
start_index: INTEGER
-- Page index.
feature -- Element change
set_search_terms (a_search_terms: like search_terms)
-- Assign `search_terms' with `a_search_terms'.
do
search_terms := a_search_terms
ensure
search_terms_assigned: search_terms = a_search_terms
end
feature -- Change element
set_title (a_title: like title)
-- Set title with `a_title'
do
title := a_title
ensure
title_set: title = a_title
end
set_total_results (a_total_results: like total_results)
-- Set total_results with `a_total_results'.
do
total_results := a_total_results
ensure
total_results_set: total_results = a_total_results
end
set_count (a_count: like count)
-- Set count with `a_count'.
do
count := a_count
ensure
count_set: count = a_count
end
set_start_index (a_start_index: like start_index)
-- Set start_index with `a_start_index'.
do
start_index := a_start_index
ensure
start_index_set: start_index = a_start_index
end
feature -- Status report
debug_output: STRING_8
-- <Precursor>
do
create Result.make_from_string ("%NPage details%N")
if attached title as l_title then
Result.append ("Title:")
Result.append (l_title)
Result.append_character ('%N')
end
if attached search_terms as l_search_tearm then
Result.append ("Search Tearm:")
Result.append (l_search_tearm)
Result.append_character ('%N')
end
Result.append ("Count:")
Result.append (count.out)
Result.append_character ('%N')
Result.append ("Total Result:")
Result.append (count.out)
Result.append_character ('%N')
Result.append ("Count:")
Result.append (total_results.out)
Result.append_character ('%N')
Result.append ("Start index:")
Result.append (start_index.out)
Result.append_character ('%N')
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)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,209 @@
note
description: "Represent a search result, include the URL, title and text snippets that describe the result"
date: "$Date: 2015-10-09 08:11:07 -0300 (vi., 09 oct. 2015) $"
revision: "$Revision: 97973 $"
class
GCSE_PAGE_ITEM
inherit
DEBUG_OUTPUT
feature -- Access
html_formatted_url: detachable STRING_8
-- Html formatted url of this result
formatted_url: detachable STRING_8
-- Formatted url of this result
cache_id: detachable STRING_8
-- Cache id of this result
html_snippet: detachable STRING_8
-- Html snippet of this request
snippet: detachable STRING_8
-- Snippet of this result
display_link: detachable STRING_8
-- Display link of this result
link: detachable STRING_8
-- link of this result
html_title: detachable STRING_8
-- html title of result
title: detachable STRING_8
-- title of result.
kind: detachable STRING_8
-- Kind of actual search result.
page_map: detachable GCSE_PAGE_MAP
-- Page map
--! Not supported for now.
feature -- Element change
set_html_formatted_url (a_html_formatted_url: like html_formatted_url)
-- Assign `html_formatted_url' with `a_html_formatted_url'.
do
html_formatted_url := a_html_formatted_url
ensure
html_formatted_url_assigned: html_formatted_url = a_html_formatted_url
end
set_formatted_url (a_formatted_url: like formatted_url)
-- Assign `formatted_url' with `a_formatted_url'.
do
formatted_url := a_formatted_url
ensure
formatted_url_assigned: formatted_url = a_formatted_url
end
set_cache_id (a_cache_id: like cache_id)
-- Assign `cache_id' with `a_cache_id'.
do
cache_id := a_cache_id
ensure
cache_id_assigned: cache_id = a_cache_id
end
set_html_snippet (a_html_snippet: like html_snippet)
-- Assign `html_snippet' with `a_html_snippet'.
do
html_snippet := a_html_snippet
ensure
html_snippet_assigned: html_snippet = a_html_snippet
end
set_snippet (a_snippet: like snippet)
-- Assign `snippet' with `a_snippet'.
do
snippet := a_snippet
ensure
snippet_assigned: snippet = a_snippet
end
set_display_link (a_display_link: like display_link)
-- Assign `display_link' with `a_display_link'.
do
display_link := a_display_link
ensure
display_link_assigned: display_link = a_display_link
end
set_link (a_link: like link)
-- Assign `link' with `a_link'.
do
link := a_link
ensure
link_assigned: link = a_link
end
set_html_title (a_html_title: like html_title)
-- Assign `html_title' with `a_html_title'.
do
html_title := a_html_title
ensure
html_title_assigned: html_title = a_html_title
end
set_title (a_title: like title)
-- Assign `title' with `a_title'.
do
title := a_title
ensure
title_assigned: title = a_title
end
set_kind (a_kind: like kind)
-- Assign `kind' with `a_kind'.
do
kind := a_kind
ensure
kind_assigned: kind = a_kind
end
set_page_map (a_map: like page_map)
-- Assign `kind' with `a_kind'.
do
page_map := a_map
ensure
page_map_assigned: page_map = a_map
end
feature -- Output
debug_output: STRING_8
-- <Precursor>
do
create Result.make_from_string ("%NPage Item details%N")
if attached title as l_title then
Result.append ("Title:")
Result.append (l_title)
Result.append_character ('%N')
end
if attached kind as l_kind then
Result.append ("Kind:")
Result.append (l_kind)
Result.append_character ('%N')
end
if attached html_title as l_html_title then
Result.append ("Html title:")
Result.append (l_html_title)
Result.append_character ('%N')
end
if attached link as l_link then
Result.append ("Link:")
Result.append (l_link)
Result.append_character ('%N')
end
if attached display_link as l_display_link then
Result.append ("Display link:")
Result.append (l_display_link)
Result.append_character ('%N')
end
if attached snippet as l_snippet then
Result.append ("Snippet:")
Result.append (l_snippet)
Result.append_character ('%N')
end
if attached html_snippet as l_html_snippet then
Result.append ("Html snippet:")
Result.append (l_html_snippet)
Result.append_character ('%N')
end
if attached cache_id as l_cache_id then
Result.append ("Cache_id:")
Result.append (l_cache_id)
Result.append_character ('%N')
end
if attached formatted_url as l_formatted_url then
Result.append ("Formatted url:")
Result.append (l_formatted_url)
Result.append_character ('%N')
end
if attached html_formatted_url as l_html_formatted_url then
Result.append ("Html formatted url:")
Result.append (l_html_formatted_url)
Result.append_character ('%N')
end
end
note
copyright: "2011-2015 Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,41 @@
note
description: "[
Represent a google page map
"pagemap": {
"cse_image": [
{
"src": "https://www.eiffel.org/portal/files/userpictures/picture-40.jpg"
}
],
"cse_thumbnail": [
{
"width": "81",
"height": "61",
"src": "https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcRnC-RKzps6BFItx_MLYBVskFI7U6u0y3VJBInomPYEF5sO6gkip94mLw"
}
]
}
]"
date: "$Date: 2015-10-09 08:11:07 -0300 (vi., 09 oct. 2015) $"
revision: "$Revision: 97973 $"
EIS: "name=PageMaps", "src=https://developers.google.com/custom-search/docs/structured_data#pagemaps", "protocol=url"
class
GCSE_PAGE_MAP
feature -- Access
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)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,238 @@
note
description: "[
Represent google custom search parameters
Example url template
"template": "https://www.googleapis.com/customsearch/v1?q={searchTerms}&num={count?}&start={startIndex?}&lr={language?}&safe={safe?}&cx={cx?}&cref={cref?}&sort={sort?}&filter={filter?}&gl={gl?}&cr={cr?}&googlehost={googleHost?}&c2coff={disableCnTwTranslation?}&hq={hq?}&hl={hl?}&siteSearch={siteSearch?}&siteSearchFilter={siteSearchFilter?}&exactTerms={exactTerms?}&excludeTerms={excludeTerms?}&linkSite={linkSite?}&orTerms={orTerms?}&relatedSite={relatedSite?}&dateRestrict={dateRestrict?}&lowRange={lowRange?}&highRange={highRange?}&searchType={searchType}&fileType={fileType?}&rights={rights?}&imgSize={imgSize?}&imgType={imgType?}&imgColorType={imgColorType?}&imgDominantColor={imgDominantColor?}&alt=json"
]"
optional_parameters: "[
Optional parameters
c2coff string Enables or disables Simplified and Traditional Chinese Search.
The default value for this parameter is 0 (zero), meaning that the feature is enabled. Supported values are:
1: Disabled
0: Enabled (default)
cr string Restricts search results to documents originating in a particular country.
You may use Boolean operators in the cr parameter's value.
Google Search determines the country of a document by analyzing:
the top-level domain (TLD) of the document's URL
the geographic location of the Web server's IP address
See the Country Parameter Values page for a list of valid values for this parameter.
cref string The URL of a linked custom search engine specification to use for this request.
Does not apply for Google Site Search
If both cx and cref are specified, the cx value is used
cx string The custom search engine ID to use for this request.
If both cx and cref are specified, the cx value is used.
dateRestrict string Restricts results to URLs based on date. Supported values include:
d[number]: requests results from the specified number of past days.
w[number]: requests results from the specified number of past weeks.
m[number]: requests results from the specified number of past months.
y[number]: requests results from the specified number of past years.
exactTerms string Identifies a phrase that all documents in the search results must contain.
excludeTerms string Identifies a word or phrase that should not appear in any documents in the search results.
fileType string Restricts results to files of a specified extension. A list of file types indexable by Google can be found in Webmaster Tools Help Center.
filter string Controls turning on or off the duplicate content filter.
See Automatic Filtering for more information about Google's search results filters. Note that host crowding filtering applies only to multi-site searches.
By default, Google applies filtering to all search results to improve the quality of those results.
Acceptable values are:
"0": Turns off duplicate content filter.
"1": Turns on duplicate content filter.
gl string Geolocation of end user.
The gl parameter value is a two-letter country code. The gl parameter boosts search results whose country of origin matches the parameter value. See the Country Codes page for a list of valid values.
Specifying a gl parameter value should lead to more relevant results. This is particularly true for international customers and, even more specifically, for customers in English- speaking countries other than the United States.
googlehost string The local Google domain (for example, google.com, google.de, or google.fr) to use to perform the search.
highRange string
Specifies the ending value for a search range.
Use lowRange and highRange to append an inclusive search range of lowRange...highRange to the query.
hl string Sets the user interface language.
Explicitly setting this parameter improves the performance and the quality of your search results.
See the Interface Languages section of Internationalizing Queries and Results Presentation for more information, and Supported Interface Languages for a list of supported languages.
hq string Appends the specified query terms to the query, as if they were combined with a logical AND operator.
imgColorType string Returns black and white, grayscale, or color images: mono, gray, and color.
Acceptable values are:
"color": color
"gray": gray
"mono": mono
imgDominantColor string Returns images of a specific dominant color.
Acceptable values are:
"black": black
"blue": blue
"brown": brown
"gray": gray
"green": green
"pink": pink
"purple": purple
"teal": teal
"white": white
"yellow": yellow
imgSize string Returns images of a specified size.
Acceptable values are:
"huge": huge
"icon": icon
"large": large
"medium": medium
"small": small
"xlarge": xlarge
"xxlarge": xxlarge
imgType string Returns images of a type.
Acceptable values are:
"clipart": clipart
"face": face
"lineart": lineart
"news": news
"photo": photo
linkSite string Specifies that all search results should contain a link to a particular URL
lowRange string Specifies the starting value for a search range.
Use lowRange and highRange to append an inclusive search range of lowRange...highRange to the query.
lr string Restricts the search to documents written in a particular language (e.g., lr=lang_ja).
Acceptable values are:
"lang_ar": Arabic
"lang_bg": Bulgarian
"lang_ca": Catalan
"lang_cs": Czech
"lang_da": Danish
"lang_de": German
"lang_el": Greek
"lang_en": English
"lang_es": Spanish
"lang_et": Estonian
"lang_fi": Finnish
"lang_fr": French
"lang_hr": Croatian
"lang_hu": Hungarian
"lang_id": Indonesian
"lang_is": Icelandic
"lang_it": Italian
"lang_iw": Hebrew
"lang_ja": Japanese
"lang_ko": Korean
"lang_lt": Lithuanian
"lang_lv": Latvian
"lang_nl": Dutch
"lang_no": Norwegian
"lang_pl": Polish
"lang_pt": Portuguese
"lang_ro": Romanian
"lang_ru": Russian
"lang_sk": Slovak
"lang_sl": Slovenian
"lang_sr": Serbian
"lang_sv": Swedish
"lang_tr": Turkish
"lang_zh-CN": Chinese (Simplified)
"lang_zh-TW": Chinese (Traditional)
orTerms string Provides additional search terms to check for in a document, where each document in the search results must contain at least one of the additional search terms.
relatedSite string Specifies that all search results should be pages that are related to the specified URL.
rights string Filters based on licensing. Supported values include: cc_publicdomain, cc_attribute, cc_sharealike, cc_noncommercial, cc_nonderived, and combinations of these.
safe string Search safety level.
Acceptable values are:
"high": Enables highest level of SafeSearch filtering.
"medium": Enables moderate SafeSearch filtering.
"off": Disables SafeSearch filtering. (default)
searchType string Specifies the search type: image. If unspecified, results are limited to webpages.
Acceptable values are:
"image": custom image search.
siteSearch string Specifies all search results should be pages from a given site.
siteSearchFilter string Controls whether to include or exclude results from the site named in the siteSearch parameter.
Acceptable values are:
"e": exclude
"i": include
sort string The sort expression to apply to the results.
]"
date: "$Date: 2015-10-08 07:51:29 -0300 (ju., 08 oct. 2015) $"
revision: "$Revision: 97966 $"
EIS: "GCSE parameters", "src=https://developers.google.com/custom-search/json-api/v1/reference/cse/list", "protocol=URI"
class
GCSE_QUERY_PARAMETERS
create
make
feature {NONE} -- Initialization
make (a_secret_key, a_cx, a_query: READABLE_STRING_8)
-- Create an object GCSE_QUERY_PARAMETERS with secret key `a_secret_key' and a custom search engine id `a_cx'.
-- and query `a_query'.
do
-- TODO
-- At the moment the API only use cx as Google Custom Search id.
-- Custom search engine ID - Use either cx or cref to specify the custom search engine you want to use to perform this search
secret := a_secret_key
cx := a_cx
query := a_query
ensure
secret_set: secret.same_string (a_secret_key)
cx_set: cx.same_string (a_cx)
query_set: query.same_string (a_query)
end
feature -- Access : Required Parameters
secret: READABLE_STRING_8
-- Required. The shared key between your site and Google Custom Search Engine.
cx: READABLE_STRING_8
-- Custom search engine id to perform this search.
query: READABLE_STRING_8
-- Search query, query parameter to specify your search expression.
feature -- Optional Parameters
num : detachable STRING_8
-- Number of search results to return.
-- Valid values are integers between 1 and 10, inclusive.
start: detachable STRING_8
-- The index of the first result to return.
feature -- Change Elements
set_num (a_num: READABLE_STRING_8)
require
is_number: a_num.is_integer
valid_range: a_num.to_integer >= 1 and then a_num.to_integer <= 10
do
num := a_num
ensure
num_set: num = a_num
valid_rage_set: attached num as l_num and then l_num.to_integer >= 1 and then l_num.to_integer <= 10
end
set_start (a_start: READABLE_STRING_8)
require
is_number: a_start.is_integer
valid_start: a_start.to_integer >= 1
do
start := a_start
ensure
start_set: start = a_start
valid_start_set: attached start as l_start and then l_start.to_integer >= 1
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)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,115 @@
note
description: "[
Represent search request metadata
URL: search template used for the current results.
Queries: current, next and previous page.
Context
Search infromation
Items: array of actual search results.
]"
date: "$Date: 2015-10-08 07:51:29 -0300 (ju., 08 oct. 2015) $"
revision: "$Revision: 97966 $"
class
GCSE_RESPONSE
--! TODO
--! All suppport for for url, context and search information.
feature -- Access
current_page: detachable GCSE_PAGE
-- Metadata describing the query for the current set of results.
-- This role is always present in the response.
-- It is always an array with just one element.
next_page: detachable GCSE_PAGE
-- Metadata describing the query to use for the next page of results.
-- This role is not present if the current results are the last page. Note: This API returns up to the first 100 results only.
-- When present, it is always a array with just one element.
previous_page: detachable GCSE_PAGE
-- Metadata describing the query to use for the previous page of results.
-- Not present if the current results are the first page.
-- When present, it is always a array with just one element.
items: detachable LIST [GCSE_PAGE_ITEM]
-- Contains the actual search results. The search results include the URL, title and text snippets that describe the result.
feature -- Change Element
set_current_page (a_page: GCSE_PAGE)
-- Set `current_page' with `a_page'.
do
current_page := a_page
ensure
current_page_set: current_page = a_page
end
set_next_page (a_page: GCSE_PAGE)
-- Set `next_page' with `a_page'.
do
next_page := a_page
ensure
next_page_set: next_page = a_page
end
set_previous_page (a_page: GCSE_PAGE)
-- Set `previous_page' with `a_page'.
do
previous_page := a_page
ensure
previous_page_set: previous_page = a_page
end
add_item (a_item: GCSE_PAGE_ITEM)
-- Add item `a_item' to the list of items.
local
l_items: like items
do
l_items := items
if l_items = Void then
create {ARRAYED_LIST[GCSE_PAGE_ITEM]}l_items.make (10)
items := l_items
end
l_items.force (a_item)
end
feature -- Acess: HTTP Response
status: INTEGER
-- HTTP status code.
status_message: detachable READABLE_STRING_8
-- associated textual phrase for the response status.
feature -- Change Element: HTTP Response
set_status (a_status: like status)
-- Set `status' with `a_status'.
do
status := a_status
ensure
status_set: status = a_status
end
set_status_nessage (a_message: like status_message)
-- Set `status_message' with `a_message'.
do
status_message := a_message
ensure
status_message_set: status_message = a_message
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)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,80 @@
note
description : "test application root class"
date : "$Date: 2015-10-08 07:51:29 -0300 (ju., 08 oct. 2015) $"
revision : "$Revision: 97966 $"
class
APPLICATION
inherit
ARGUMENTS
create
make
feature {NONE} -- Initialization
make
-- Run application.
local
gcse: GCSE_API
l_parameters: GCSE_QUERY_PARAMETERS
do
create l_parameters.make (key, cx, "scoop")
create gcse.make (l_parameters)
gcse.search
if attached {GCSE_RESPONSE} gcse.last_result as l_result then
if attached l_result.current_page as l_page then
print ("Current Page%N")
print (l_page.to_string)
end
if attached l_result.next_page as l_page then
print ("Next Page%N")
print (l_page.to_string)
end
if attached l_result.previous_page as l_page then
print ("Previous Page%N")
print (l_page.to_string)
end
if attached l_result.items as l_items then
print ("Number of items:" + l_items.count.out)
across l_items as ic loop print (ic.item.to_string) end
end
if attached l_result.next_page as l_page then
l_parameters.set_start (l_page.start_index.out)
gcse.search
end
end
if attached {GCSE_RESPONSE} gcse.last_result as l_result then
if attached l_result.current_page as l_page then
print ("Current Page%N")
print (l_page.to_string)
end
if attached l_result.next_page as l_page then
print ("Next Page%N")
print (l_page.to_string)
end
if attached l_result.previous_page as l_page then
print ("Previous Page%N")
print (l_page.to_string)
end
if attached l_result.items as l_items then
print ("Number of items:" + l_items.count.out)
across l_items as ic loop print (ic.item.to_string) end
end
end
end
feature {NONE} -- Implementation
Key: STRING = "AIzaSyBKAXNofo-RqZb6kUmpbiCwPEy7n7-E51k"
cx : STRING = "015017565055626880074:9gdgp1fvt-g"
end

View File

@@ -0,0 +1,31 @@
note
description: "[
Eiffel tests that can be executed by testing tool.
]"
author: "EiffelStudio test wizard"
date: "$Date: 2015-10-08 07:51:29 -0300 (ju., 08 oct. 2015) $"
revision: "$Revision: 97966 $"
testing: "type/manual"
class
GCSE_API_TEST_SET
inherit
EQA_TEST_SET
feature -- Test routines
feature {NONE} -- Implementation
has_error (l_captcha: GCSE_API; a_error: READABLE_STRING_32): BOOLEAN
do
if attached l_captcha.errors as l_errors then
l_errors.compare_objects
Result := l_errors.has (a_error)
end
end
end

View File

@@ -0,0 +1,21 @@
<?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="test">
<target name="test">
<root class="APPLICATION" feature="make"/>
<option warning="true" void_safety="transitional">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<setting name="console_application" value="true"/>
<precompile name="base_pre" location="$ISE_PRECOMP\base-safe.ecf"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="gcse" location="..\gcse-safe.ecf" readonly="false"/>
<library name="testing" location="$ISE_LIBRARY\library\testing\testing-safe.ecf"/>
<cluster name="test" location=".\" recursive="true">
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
</cluster>
</target>
</system>

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<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="http_client_extension" uuid="EA6A381D-2E78-448C-8A6D-B71759F1082E" library_target="http_client_extension">
<target name="http_client_extension">
<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="base_extension" location="$ISE_LIBRARY\library\base_extension\base_extension-safe.ecf"/>
<library name="curl" location="$ISE_LIBRARY\library\cURL\cURL-safe.ecf"/>
<library name="encoder" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\text\encoder\encoder-safe.ecf"/>
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-safe.ecf"/>
<library name="http_client" location="$ISE_LIBRARY\contrib\library\network\http_client\http_client-safe.ecf"/>
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json-safe.ecf" readonly="false"/>
<library name="uri" location="$ISE_LIBRARY\library\text\uri\uri-safe.ecf"/>
<cluster name="http_client_extension" location=".\src\" recursive="true">
<file_rule>
<exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
</cluster>
</target>
</system>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<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="http_client_extension" uuid="DD90A4FA-1B7F-4C8C-A739-AE67D6F40384" library_target="http_client_extension">
<target name="http_client_extension">
<root all_classes="true"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<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="base_extension" location="$ISE_LIBRARY\library\base_extension\base_extension.ecf"/>
<library name="curl" location="$ISE_LIBRARY\library\cURL\cURL.ecf"/>
<library name="encoder" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\text\encoder\encoder.ecf"/>
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http.ecf"/>
<library name="http_client" location="$ISE_LIBRARY\contrib\library\network\http_client\http_client.ecf"/>
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json.ecf" readonly="false"/>
<library name="uri" location="$ISE_LIBRARY\library\text\uri\uri.ecf"/>
<cluster name="http_client_extension" location=".\src\" recursive="true"/>
</target>
</system>

View File

@@ -0,0 +1,199 @@
note
description: "Represent an HTTP request."
date: "$Date: 2015-10-08 07:51:29 -0300 (ju., 08 oct. 2015) $"
revision: "$Revision: 97966 $"
class
REQUEST
inherit
HTTP_CONSTANTS
create
make
feature {NONE} -- Initialization
make (a_method: READABLE_STRING_8; a_uri: READABLE_STRING_8)
require
valid_http_method: is_http_method (a_method)
valid_uri: is_valid_uri (a_uri)
do
verb := a_method
uri := a_uri
create headers.make (5)
ensure
ver_set: verb = a_method
uri_set: uri = a_uri
end
feature -- Status Report
is_valid_uri (a_uri: READABLE_STRING_8): BOOLEAN
local
l_uri: URI
do
create l_uri.make_from_string (a_uri)
Result := l_uri.is_valid
end
query_string: detachable READABLE_STRING_8
local
l_uri: URI
do
create l_uri.make_from_string (uri)
Result := l_uri.query
end
sanitized_url: READABLE_STRING_8
-- Returns the URL without the query string part
local
l_uri: URI
do
create l_uri.make_from_string (uri)
l_uri.remove_query
Result := l_uri.string
ensure
sanitized: not as_uri (Result).has_query
end
is_http_method (a_method: READABLE_STRING_GENERAL): BOOLEAN
do
if a_method.same_string (method_connect) then
Result := True
elseif a_method.same_string (method_delete) then
Result := True
elseif a_method.same_string (method_get) then
Result := True
elseif a_method.same_string (method_head) then
Result := True
elseif a_method.same_string (method_options) then
Result := True
elseif a_method.same_string (method_patch) then
Result := True
elseif a_method.same_string (method_post) then
Result := True
elseif a_method.same_string (method_put) then
Result := True
elseif a_method.same_string (method_trace) then
Result := True
end
end
feature -- Constants
content_type_header_name: STRING_8 = "Content-Type";
default_content_type: STRING
once
Result := application_json
end
feature -- Access
uri: READABLE_STRING_8
verb: READABLE_STRING_8
headers: STRING_TABLE [READABLE_STRING_8]
payload: detachable READABLE_STRING_8
executor: detachable REQUEST_EXECUTOR
feature -- Change Element
add_payload (a_payload: like payload)
do
payload := a_payload
ensure
payload_set: attached payload as l_payload implies l_payload = a_payload
end
add_header (key: READABLE_STRING_8; value: READABLE_STRING_8)
do
headers.force (value, key)
end
feature -- Execute
execute: detachable RESPONSE
do
initialize_executor
Result := execute_request
end
initialize_executor
do
create executor.make (uri, verb)
end
feature {NONE} -- Implementation
execute_request: detachable RESPONSE
do
if attached executor as l_executor then
-- add headers
add_headers (l_executor)
if verb.same_string (method_put) or else verb.same_string (method_post) or else verb.same_string (method_patch) then
l_executor.set_body (body_contents)
end
if not l_executor.context_executor.headers.has (content_type_header_name) then
l_executor.context_executor.add_header (content_type_header_name, default_content_type)
end
if attached l_executor.execute as l_response then
create Result.make (l_response)
end
end
end
feature {NONE} -- Implementation
add_headers (a_executor: REQUEST_EXECUTOR)
local
l_context_executor: HTTP_CLIENT_REQUEST_CONTEXT
s: READABLE_STRING_GENERAL
utf: UTF_CONVERTER
do
l_context_executor := a_executor.context_executor
across
headers as ic
loop
s := ic.key
if s.is_valid_as_string_8 then
l_context_executor.add_header (s.as_string_8, ic.item)
else
l_context_executor.add_header (utf.utf_32_string_to_utf_8_string_8 (s), ic.item)
end
end
end
body_contents: READABLE_STRING_8
do
if attached payload as l_payload then
Result := l_payload
else
Result := ""
end
end
as_uri (a_string: READABLE_STRING_8): URI
require
is_valid_uri: is_valid_uri (a_string)
do
create Result.make_from_string (a_string)
end
note
copyright: "2011-2015 Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,97 @@
note
description: "Executes an HTTP request"
date: "$Date: 2015-10-08 07:51:29 -0300 (ju., 08 oct. 2015) $"
revision: "$Revision: 97966 $"
class
REQUEST_EXECUTOR
inherit
HTTP_CLIENT_HELPER
HTTP_CONSTANTS
create
make
feature {NONE} -- Initialization
make (a_url: READABLE_STRING_8; a_method: READABLE_STRING_8)
do
set_base_url (a_url)
verb := a_method
ensure
base_url_set: base_url.same_string (a_url)
method_set: verb.same_string (a_method)
end
set_base_url (a_url: READABLE_STRING_8)
-- Set base_url with `a_url'
local
s: STRING
do
create s.make_from_string (a_url)
s.left_adjust
s.right_adjust
base_url := s
ensure
base_url_set: a_url.has_substring (base_url)
end
feature -- Access
verb: READABLE_STRING_8
-- HTTP METHOD (Get, Post, ...)
body: detachable READABLE_STRING_8
-- body content
feature -- Element Change
set_body (a_body: like body)
-- Set body with `a_body'.
do
body := a_body
ensure
body_set: body = a_body
end
feature -- Execute
execute: detachable HTTP_CLIENT_RESPONSE
-- Http executor
do
if verb.same_string (method_connect) then
Result := Void -- not supported for now
elseif verb.same_string (method_delete) then
Result := execute_delete ("")
elseif verb.same_string (method_get) then
Result := execute_get ("")
elseif verb.same_string (method_head) then
Result := Void
elseif verb.same_string (method_options) then
Result := Void
elseif verb.same_string (method_patch) then
Result := execute_patch ("", body)
elseif verb.same_string (method_post) then
Result := execute_post ("", body)
elseif verb.same_string (method_put) then
Result := execute_put ("", body)
elseif verb.same_string (method_trace) then
Result := Void
end
end
note
copyright: "2011-2015 Javier Velilla, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,57 @@
note
description: "Represent and HTTP Response"
date: "$Date: 2015-10-08 07:51:29 -0300 (ju., 08 oct. 2015) $"
revision: "$Revision: 97966 $"
class
RESPONSE
create
make
feature {NONE} --Initialization
make (a_response: HTTP_CLIENT_RESPONSE)
do
http_response := a_response
body := a_response.body
status := a_response.status
headers := a_response.headers
status_message := a_response.status_line
error_message := a_response.error_message
ensure
http_reponse_set: http_response = a_response
headers_set: headers = a_response.headers
status_set: status = a_response.status
status_message_set: status_message = a_response.status_line
error_message_set: error_message = a_response.error_message
end
feature -- Access
status: INTEGER
status_message: detachable READABLE_STRING_8
error_message: detachable READABLE_STRING_8
body: detachable READABLE_STRING_8
headers: LIST [TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_8]]
feature {NONE} -- Implementation
http_response: HTTP_CLIENT_RESPONSE;
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)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -0,0 +1,99 @@
note
description: "Wrapper class for HTTP_CLIENT_SESSION"
date: "$Date: 2015-10-08 07:51:29 -0300 (ju., 08 oct. 2015) $"
revision: "$Revision: 97966 $"
deferred class
HTTP_CLIENT_HELPER
feature -- Access
http_session: detachable HTTP_CLIENT_SESSION
get_http_session
local
h: LIBCURL_HTTP_CLIENT
b: like base_url
do
create h.make
b := base_url
if b = Void then
b := ""
end
if attached {HTTP_CLIENT_SESSION} h.new_session (base_url) as sess then
http_session := sess
sess.set_timeout (-1)
sess.set_connect_timeout (-1)
sess.set_is_insecure (True)
sess.set_any_auth_type
debug ("curl")
sess.set_is_debug (True)
end
debug ("proxy8888")
sess.set_proxy ("127.0.0.1", 8888) --| inspect traffic with http://www.fiddler2.com/
end
end
end
feature -- HTTP client helpers
execute_get (command_name: READABLE_STRING_8): detachable HTTP_CLIENT_RESPONSE
do
get_http_session
if attached http_session as sess then
Result := sess.get (command_name, context_executor)
end
end
execute_post (command_name: READABLE_STRING_8; data: detachable READABLE_STRING_8): detachable HTTP_CLIENT_RESPONSE
do
get_http_session
if attached http_session as sess then
Result := sess.post (command_name, context_executor, data)
end
end
execute_delete (command_name: READABLE_STRING_8): detachable HTTP_CLIENT_RESPONSE
do
get_http_session
if attached http_session as sess then
Result := sess.delete (command_name, context_executor)
end
end
execute_put (command_name: READABLE_STRING_8; data: detachable READABLE_STRING_8): detachable HTTP_CLIENT_RESPONSE
do
get_http_session
if attached http_session as sess then
Result := sess.put (command_name, context_executor, data)
end
end
execute_patch (command_name: READABLE_STRING_8; data: detachable READABLE_STRING_8): detachable HTTP_CLIENT_RESPONSE
do
get_http_session
if attached http_session as sess then
Result := sess.patch (command_name, context_executor, data)
end
end
context_executor: HTTP_CLIENT_REQUEST_CONTEXT
-- request context for each request
once
create Result.make
end
base_url: STRING;
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)"
source: "[
Eiffel Software
5949 Hollister Ave., Goleta, CA 93117 USA
Telephone 805-685-1006, Fax 805-685-6869
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
end

View File

@@ -86,8 +86,23 @@ feature -- Query
sql_post_execution
end
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'.
sql_finalize
-- <Precursor>
do
-- N/A
end
sql_insert (a_sql_statement: STRING; a_params: detachable STRING_TABLE [detachable ANY])
-- <Precursor>
do
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.execute_change
sql_post_execution
end
sql_modify (a_sql_statement: STRING; a_params: detachable STRING_TABLE [detachable ANY])
-- <Precursor>
do
check_sql_query_validity (a_sql_statement, a_params)
db_handler.set_query (create {DATABASE_QUERY}.data_reader (a_sql_statement, a_params))
@@ -133,4 +148,32 @@ feature -- Query
end
end
sql_read_integer_32 (a_index: INTEGER): INTEGER_32
-- Retrieved value at `a_index' position in `item'.
local
l_item: like sql_item
do
l_item := sql_item (a_index)
if attached {INTEGER_32} l_item as i then
Result := i
elseif attached {INTEGER_32_REF} l_item as l_value then
Result := l_value.item
else
check is_integer_32: False end
end
end
sql_read_date_time (a_index: INTEGER): detachable DATE_TIME
-- Retrieved value at `a_index' position in `item'.
local
l_item: like sql_item
do
l_item := sql_item (a_index)
if attached {DATE_TIME} l_item as dt then
Result := dt
else
check is_date_time_or_null: l_item = Void end
end
end
end

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<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="persistence_sqlite3" uuid="4E536C92-A09F-4305-8230-2EC5ABC51416" library_target="persistence_sqlite3">
<target name="persistence_sqlite3">
<root all_classes="true"/>
<option warning="true" void_safety="all">
<assertions precondition="true" supplier_precondition="true"/>
</option>
<setting name="console_application" value="true"/>
<library name="app_env" location="..\..\app_env\app_env-safe.ecf"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="cms" location="..\..\..\cms-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"/>
<library name="error" location="$ISE_LIBRARY\contrib\library\utility\general\error\error-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="model" location="..\..\model\cms_model-safe.ecf"/>
<library name="sqlite3" location="$ISE_LIBRARY\unstable\library\persistency\database\sqlite3\sqlite-safe.ecf" readonly="false">
<option msil_application_optimize="false">
<assertions precondition="true" supplier_precondition="true"/>
</option>
</library>
<library name="thread" location="$ISE_LIBRARY\library\thread\thread-safe.ecf"/>
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
<cluster name="persistence_sqlite" location=".\src\" recursive="true">
<file_rule>
<exclude>/old$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
</cluster>
</target>
</system>

View File

@@ -0,0 +1,450 @@
note
description: "Summary description for {CMS_STORAGE_MYSQL}."
date: "$Date: 2015-02-09 22:29:56 +0100 (lun., 09 févr. 2015) $"
revision: "$Revision: 96596 $"
class
CMS_STORAGE_SQLITE3
inherit
CMS_STORAGE_SQL
redefine
sql_read_date_time, sql_read_integer_32,
sql_read_string_32
end
CMS_CORE_STORAGE_SQL_I
redefine
sql_read_date_time, sql_read_integer_32,
sql_read_string_32
end
CMS_USER_STORAGE_SQL_I
redefine
sql_read_date_time, sql_read_integer_32,
sql_read_string_32
end
SQLITE_BIND_ARG_MARSHALLER
REFACTORING_HELPER
create
make
feature {NONE} -- Initialization
make (db: SQLITE_DATABASE)
do
sqlite := db
create error_handler.make
end
sqlite: SQLITE_DATABASE
-- Associated SQLite database.
feature -- Status report
is_initialized: BOOLEAN
-- Is storage initialized?
do
Result := has_user
end
feature -- Status report
is_available: BOOLEAN
-- Is storage available?
do
Result := sqlite.is_interface_usable
end
feature -- Basic operation
close
-- Close/disconnect current storage.
do
sqlite.close
end
feature -- Execution
transaction_depth: INTEGER
sql_begin_transaction
-- Start a database transtaction.
do
if transaction_depth = 0 then
sqlite.begin_transaction (False)
end
transaction_depth := transaction_depth + 1
debug ("roc_storage")
print ("# sql_begin_transaction (depth="+ transaction_depth.out +").%N")
end
end
sql_rollback_transaction
-- Rollback updates in the database.
do
if sqlite.is_in_transaction then
sqlite.rollback
end
transaction_depth := transaction_depth - 1
debug ("roc_storage")
print ("# sql_rollback_transaction (depth="+ transaction_depth.out +").%N")
end
end
sql_commit_transaction
-- Commit updates in the database.
do
if sqlite.is_in_transaction then
sqlite.commit
end
transaction_depth := transaction_depth - 1
debug ("roc_storage")
print ("# sql_commit_transaction (depth="+ transaction_depth.out +").%N")
end
end
sql_post_execution
-- Post database execution.
-- note: execute after each `sql_query' and `sql_change'.
do
debug ("roc_storage")
print ("# sql_post_execution.%N")
end
-- FIXME
if sqlite.has_error then
write_critical_log (generator + ".post_execution Error occurred!")
end
end
feature -- Operation
last_statement: detachable SQLITE_STATEMENT
last_sqlite_result_cursor: detachable SQLITE_STATEMENT_ITERATION_CURSOR
sql_query (a_sql_statement: STRING; a_params: detachable STRING_TABLE [detachable ANY])
-- <Precursor>
local
st: SQLITE_QUERY_STATEMENT
do
debug ("roc_storage")
print ("> sql_query (" +a_sql_statement + ").%N")
end
last_sqlite_result_cursor := Void
create st.make (a_sql_statement, sqlite)
last_statement := st
if st.is_compiled then
if a_params /= Void then
check st.has_arguments end
last_sqlite_result_cursor := st.execute_new_with_arguments (sqlite_arguments (a_params))
else
last_sqlite_result_cursor := st.execute_new
end
else
error_handler.add_custom_error (1, "invalid query", "query compilation failed!")
end
debug ("roc_storage")
print ("< sql_query (" +a_sql_statement + ").%N")
end
end
sql_finalize
-- Finalize sql query (i.e destroy previous query statement.
do
debug ("roc_storage")
print ("> sql_finalize.%N")
end
if attached last_statement as st then
st.cleanup
end
if attached last_sqlite_result_cursor as cur then
if cur.statement /= last_statement then
check should_not_occurs: False end
cur.statement.cleanup
end
last_sqlite_result_cursor := Void
end
last_statement := Void
debug ("roc_storage")
print ("< sql_finalize.%N")
end
end
sql_insert (a_sql_statement: STRING; a_params: detachable STRING_TABLE [detachable ANY])
-- <Precursor>
local
st: SQLITE_INSERT_STATEMENT
do
debug ("roc_storage")
print ("> sql_insert (" +a_sql_statement + ").%N")
end
last_sqlite_result_cursor := Void
create st.make (a_sql_statement, sqlite)
last_statement := st
if st.is_compiled then
if a_params /= Void then
check st.has_arguments end
last_sqlite_result_cursor := st.execute_new_with_arguments (sqlite_arguments (a_params))
else
last_sqlite_result_cursor := st.execute_new
end
else
error_handler.add_custom_error (1, "invalid query", "query compilation failed!")
end
debug ("roc_storage")
print ("< sql_insert (" +a_sql_statement + ").%N")
end
end
sql_modify (a_sql_statement: STRING; a_params: detachable STRING_TABLE [detachable ANY])
-- <Precursor>
local
st: SQLITE_MODIFY_STATEMENT
do
debug ("roc_storage")
print ("> sql_modify (" +a_sql_statement + ").%N")
end
last_sqlite_result_cursor := Void
create st.make (a_sql_statement, sqlite)
last_statement := st
if st.is_compiled then
if a_params /= Void then
check st.has_arguments end
last_sqlite_result_cursor := st.execute_new_with_arguments (sqlite_arguments (a_params))
else
last_sqlite_result_cursor := st.execute_new
end
else
error_handler.add_custom_error (1, "invalid query", "query compilation failed!")
end
debug ("roc_storage")
print ("< sql_modify (" +a_sql_statement + ").%N")
end
end
sqlite_arguments (a_params: STRING_TABLE [detachable ANY]): ARRAYED_LIST [SQLITE_BIND_ARG [ANY]]
local
k: READABLE_STRING_GENERAL
k8: STRING
utf: UTF_CONVERTER
do
create Result.make (a_params.count)
across
a_params as ic
loop
k := ic.key
if k.is_valid_as_string_8 then
k8 := k.as_string_8
else
k8 := utf.utf_32_string_to_utf_8_string_8 (k)
end
if attached {DATE_TIME} ic.item as dt then
Result.force (new_binding_argument (date_time_to_string (dt), ":" + k8))
elseif attached {READABLE_STRING_32} ic.item as s32 then
Result.force (new_binding_argument (utf.utf_32_string_to_utf_8_string_8 (s32), ":" + k8))
else
Result.force (new_binding_argument (ic.item, ":" + k8))
end
end
end
date_time_to_string (dt: DATE_TIME): STRING
do
create Result.make (16)
Result.append_integer (dt.year)
Result.append_character ('-')
if dt.month <= 9 then
Result.append_character ('0')
end
Result.append_integer (dt.month)
Result.append_character ('-')
if dt.day <= 9 then
Result.append_character ('0')
end
Result.append_integer (dt.day)
Result.append_character (' ')
if dt.hour <= 9 then
Result.append_character ('0')
end
Result.append_integer (dt.hour)
Result.append_character (':')
if dt.minute <= 9 then
Result.append_character ('0')
end
Result.append_integer (dt.minute)
Result.append_character (':')
if dt.second <= 9 then
Result.append_character ('0')
end
Result.append_integer (dt.second)
end
string_to_date_time (a_string: READABLE_STRING_GENERAL): DATE_TIME
local
y,m,d: INTEGER
h,min,sec: INTEGER
s: detachable READABLE_STRING_GENERAL
i,j: INTEGER
do
i := 1
-- YYYY
j := a_string.index_of ('-', i)
s := a_string.substring (i, j - 1)
y := s.to_integer
i := j + 1
-- /MM
j := a_string.index_of ('-', i)
s := a_string.substring (i, j - 1)
m := s.to_integer
i := j + 1
-- /DD
j := a_string.index_of (' ', i)
s := a_string.substring (i, j - 1)
d := s.to_integer
i := j + 1
-- %THour
j := a_string.index_of (':', i)
s := a_string.substring (i, j - 1)
h := s.to_integer
i := j + 1
-- :Min
j := a_string.index_of (':', i)
s := a_string.substring (i, j - 1)
min := s.to_integer
i := j + 1
-- :Sec
j := a_string.count + 1
s := a_string.substring (i, j - 1)
sec := s.to_integer
create Result.make (y,m,d,h,min,sec)
end
feature -- Access
sql_start
-- <Precursor>.
do
-- sqlite cursor `last_sqlite_result_cursor', already at first position if any.
end
sql_after: BOOLEAN
-- <Precursor>.
do
if attached last_sqlite_result_cursor as l_cursor then
Result := l_cursor.after
end
end
sql_forth
-- <Precursor>.
do
if attached last_sqlite_result_cursor as l_cursor then
l_cursor.forth
end
end
sql_valid_item_index (a_index: INTEGER): BOOLEAN
local
l_row: SQLITE_RESULT_ROW
do
if attached last_sqlite_result_cursor as l_cursor then
l_row := l_cursor.item
Result := a_index > 0 and a_index.to_natural_32 <= l_row.count
end
end
sql_item (a_index: INTEGER): detachable ANY
local
l_row: SQLITE_RESULT_ROW
do
if attached last_sqlite_result_cursor as l_cursor then
l_row := l_cursor.item
Result := l_row.value (a_index.to_natural_32)
end
end
sql_read_string_32 (a_index: INTEGER): detachable STRING_32
-- <Precursor>
local
utf: UTF_CONVERTER
do
Result := Precursor (a_index)
if Result = Void then
if attached sql_read_string (a_index) as s8 then
Result := utf.utf_8_string_8_to_string_32 (s8)
end
end
end
sql_read_integer_32 (a_index: INTEGER): INTEGER_32
-- Retrieved value at `a_index' position in `item'.
local
l_item: like sql_item
i64: INTEGER_64
do
l_item := sql_item (a_index)
if attached {INTEGER_32} l_item as i then
Result := i
elseif attached {INTEGER_32_REF} l_item as l_value then
Result := l_value.item
else
if attached {INTEGER_64} l_item as i then
i64 := i
elseif attached {INTEGER_64_REF} l_item as l_value then
i64 := l_value.item
else
check is_integer_32: False end
end
if i64 <= {INTEGER_32}.max_value then
Result := i64.to_integer_32
else
check is_integer_32: False end
end
end
end
sql_read_date_time (a_index: INTEGER): detachable DATE_TIME
-- Retrieved value at `a_index' position in `item'.
local
l_item: like sql_item
do
l_item := sql_item (a_index)
if attached {DATE_TIME} l_item as dt then
Result := dt
elseif attached {READABLE_STRING_GENERAL} l_item as s then
Result := string_to_date_time (s)
else
check is_date_time_nor_null: l_item = Void end
end
end
feature -- Conversion
sql_statement (a_statement: STRING): STRING
-- <Precursor>.
local
i: INTEGER
do
Result := a_statement
from
i := 1
until
i = 0
loop
i := a_statement.substring_index ("AUTO_INCREMENT", i)
if i > 0 then
if Result = a_statement then
create Result.make_from_string (a_statement)
end
Result.remove (i + 4)
i := i + 14
end
end
end
end

View File

@@ -0,0 +1,90 @@
note
description: "[
Objects that ...
]"
author: "$Author: jfiat $"
date: "$Date: 2015-02-13 13:08:13 +0100 (ven., 13 févr. 2015) $"
revision: "$Revision: 96616 $"
class
CMS_STORAGE_SQLITE3_BUILDER
inherit
CMS_STORAGE_SQL_BUILDER
create
make
feature {NONE} -- Initialization
make
-- Initialize `Current'.
do
end
feature -- Factory
storage (a_setup: CMS_SETUP; a_error_handler: ERROR_HANDLER): detachable CMS_STORAGE_SQLITE3
local
s: detachable READABLE_STRING_32
p: PATH
db: detachable SQLITE_DATABASE
l_source: SQLITE_FILE_SOURCE
i,j: INTEGER
do
if
attached (create {APPLICATION_JSON_CONFIGURATION_HELPER}).new_database_configuration (a_setup.environment.application_config_path) as l_database_config
then
if l_database_config.driver.is_case_insensitive_equal ("sqlite3") then
s := l_database_config.database_string
i := s.substring_index ("Database=", 1)
if i > 0 then
i := s.index_of ('=', i) + 1
j := s.index_of (';', i)
if j = 0 then
j := s.count + 1
end
create p.make_from_string (s.substring (i, j - 1))
else
create p.make_from_string (s)
end
if attached reuseable_connection.item as d then
if p.same_as (d.path) then
db := d.database
end
end
if db = Void or else db.is_closed then
create l_source.make (p.name)
create db.make (l_source)
if l_source.exists then
db.open_read_write
else
db.open_create_read_write
end
end
if not db.is_closed then
db.set_busy_timeout (1_000) -- FIXME
create Result.make (db)
-- set_map_zero_null_value (False) --| This way we map 0 to 0, instead of Null as default.
if Result.is_available then
if not Result.is_initialized then
initialize (a_setup, Result)
end
end
else
a_error_handler.add_custom_error (0, "Could not connect to the ODBC storage", Void)
end
else
-- Wrong mapping between storage name and storage builder!
end
end
end
reuseable_connection: CELL [detachable TUPLE [path: PATH; database: SQLITE_DATABASE]]
once
create Result.put (Void)
end
end

View File

@@ -35,6 +35,7 @@ feature -- Factory
if conn.is_connected then
create Result.make (conn)
set_map_zero_null_value (False) --| This way we map 0 to 0, instead of Null as default.
set_use_extended_types (True) --| Use extended types: STRING_32 etc.
if Result.is_available then
if not Result.is_initialized then
initialize (a_setup, Result)

View File

@@ -48,6 +48,7 @@ feature -- Factory
if conn.is_connected then
create Result.make_with_driver (conn, l_database_config.item ("Driver"))
set_map_zero_null_value (False) --| This way we map 0 to 0, instead of Null as default.
set_use_extended_types (True) --| Use extended types: STRING_32 etc.
if Result.is_available then
if not Result.is_initialized then
initialize (a_setup, Result)

View File

@@ -53,6 +53,9 @@ feature -- Access: router
l_user_handler: CMS_USER_HANDLER
l_role_handler: CMS_ROLE_HANDLER
l_admin_cache_handler: CMS_ADMIN_CACHE_HANDLER
l_admin_export_handler: CMS_ADMIN_EXPORT_HANDLER
l_uri_mapping: WSF_URI_MAPPING
do
create l_admin_handler.make (a_api)
@@ -67,6 +70,14 @@ feature -- Access: router
create l_uri_mapping.make_trailing_slash_ignored ("/admin/roles", l_roles_handler)
a_router.map (l_uri_mapping, a_router.methods_get_post)
create l_admin_cache_handler.make (a_api)
create l_uri_mapping.make_trailing_slash_ignored ("/admin/cache", l_admin_cache_handler)
a_router.map (l_uri_mapping, a_router.methods_get_post)
create l_admin_export_handler.make (a_api)
create l_uri_mapping.make_trailing_slash_ignored ("/admin/export", l_admin_export_handler)
a_router.map (l_uri_mapping, a_router.methods_get_post)
create l_user_handler.make (a_api)
a_router.handle ("/admin/add/user", l_user_handler, a_router.methods_get_post)
a_router.handle ("/admin/user/{id}", l_user_handler, a_router.methods_get)
@@ -91,6 +102,10 @@ feature -- Security
Result.force ("admin roles")
Result.force ("admin modules")
Result.force ("install modules")
Result.force ("admin core caches")
Result.force ("clear blocks cache")
Result.force ("admin export")
Result.force ("export core")
end
feature -- Hooks
@@ -120,6 +135,13 @@ feature -- Hooks
lnk.set_permission_arguments (<<"manage " + {CMS_ADMIN_MODULE}.name>>)
a_menu_system.management_menu.extend (lnk)
end
-- Per module cache permission!
create lnk.make ("Cache", "admin/cache")
a_menu_system.management_menu.extend (lnk)
-- Per module export permission!
create lnk.make ("Export", "admin/export")
a_menu_system.management_menu.extend (lnk)
end
note

View File

@@ -0,0 +1,93 @@
note
description: "[
Administrate cache functionality.
]"
date: "$Date$"
revision: "$Revision$"
class
CMS_ADMIN_CACHE_HANDLER
inherit
CMS_HANDLER
WSF_URI_HANDLER
rename
new_mapping as new_uri_mapping
end
WSF_RESOURCE_HANDLER_HELPER
redefine
do_get,
do_post
end
REFACTORING_HELPER
create
make
feature -- Execution
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
-- Execute request handler
do
execute_methods (req, res)
end
do_get (req: WSF_REQUEST; res: WSF_RESPONSE)
local
l_response: CMS_RESPONSE
s: STRING
f: CMS_FORM
do
create {GENERIC_VIEW_CMS_RESPONSE} l_response.make (req, res, api)
f := clear_cache_web_form (l_response)
create s.make_empty
f.append_to_html (create {CMS_TO_WSF_THEME}.make (l_response, l_response.theme), s)
l_response.set_main_content (s)
l_response.execute
end
do_post (req: WSF_REQUEST; res: WSF_RESPONSE)
local
l_response: CMS_RESPONSE
s: STRING
f: CMS_FORM
do
create {GENERIC_VIEW_CMS_RESPONSE} l_response.make (req, res, api)
f := clear_cache_web_form (l_response)
f.process (l_response)
if
attached f.last_data as fd and then
fd.is_valid
then
if attached fd.string_item ("op") as l_op and then l_op.same_string (text_clear_all_caches) then
l_response.hooks.invoke_clear_cache (Void, l_response)
l_response.add_notice_message ("Caches cleared (if allowed)!")
else
fd.report_error ("Invalid form data!")
end
end
create s.make_empty
f.append_to_html (create {CMS_TO_WSF_THEME}.make (l_response, l_response.theme), s)
l_response.set_main_content (s)
l_response.execute
end
feature -- Widget
clear_cache_web_form (a_response: CMS_RESPONSE): CMS_FORM
local
but: WSF_FORM_SUBMIT_INPUT
do
create Result.make (a_response.url (a_response.location, Void), "form_clear_cache")
create but.make_with_text ("op", text_clear_all_caches)
Result.extend (but)
end
feature -- Interface text.
text_clear_all_caches: STRING_32 = "Clear all caches"
end

View File

@@ -0,0 +1,116 @@
note
description: "[
Administrate export functionality.
]"
date: "$Date$"
revision: "$Revision$"
class
CMS_ADMIN_EXPORT_HANDLER
inherit
CMS_HANDLER
WSF_URI_HANDLER
rename
new_mapping as new_uri_mapping
end
WSF_RESOURCE_HANDLER_HELPER
redefine
do_get,
do_post
end
REFACTORING_HELPER
create
make
feature -- Execution
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
-- Execute request handler
do
execute_methods (req, res)
end
do_get (req: WSF_REQUEST; res: WSF_RESPONSE)
local
l_response: CMS_RESPONSE
s: STRING
f: CMS_FORM
do
create {GENERIC_VIEW_CMS_RESPONSE} l_response.make (req, res, api)
f := exportation_web_form (l_response)
create s.make_empty
f.append_to_html (create {CMS_TO_WSF_THEME}.make (l_response, l_response.theme), s)
l_response.set_main_content (s)
l_response.execute
end
do_post (req: WSF_REQUEST; res: WSF_RESPONSE)
local
l_response: CMS_RESPONSE
s: STRING
f: CMS_FORM
l_exportation_parameters: CMS_EXPORT_PARAMETERS
do
create {GENERIC_VIEW_CMS_RESPONSE} l_response.make (req, res, api)
f := exportation_web_form (l_response)
f.process (l_response)
if
attached f.last_data as fd and then
fd.is_valid
then
if attached fd.string_item ("op") as l_op and then l_op.same_string (text_export_all_data) then
if attached fd.string_item ("folder") as l_folder then
create l_exportation_parameters.make (api.site_location.extended ("export").extended (l_folder))
else
create l_exportation_parameters.make (api.site_location.extended ("export").extended ((create {DATE_TIME}.make_now_utc).formatted_out ("yyyy-[0]mm-[0]dd---hh24-[0]mi-[0]ss")))
end
l_response.hooks.invoke_export_to (Void, l_exportation_parameters, l_response)
l_response.add_notice_message ("All data exported (if allowed)!")
create s.make_empty
across
l_exportation_parameters.logs as ic
loop
s.append (ic.item)
s.append ("<br/>")
s.append_character ('%N')
end
l_response.add_notice_message (s)
else
fd.report_error ("Invalid form data!")
end
end
create s.make_empty
f.append_to_html (create {CMS_TO_WSF_THEME}.make (l_response, l_response.theme), s)
l_response.set_main_content (s)
l_response.execute
end
feature -- Widget
exportation_web_form (a_response: CMS_RESPONSE): CMS_FORM
local
f_name: WSF_FORM_TEXT_INPUT
but: WSF_FORM_SUBMIT_INPUT
do
create Result.make (a_response.url (a_response.location, Void), "export_all_data")
Result.extend_raw_text ("Export CMS data to ")
create f_name.make_with_text ("folder", (create {DATE_TIME}.make_now_utc).formatted_out ("yyyy-[0]mm-[0]dd---hh24-[0]mi-[0]ss"))
f_name.set_label ("Export folder name")
f_name.set_description ("Folder name under 'exports' folder.")
f_name.set_is_required (True)
Result.extend (f_name)
create but.make_with_text ("op", text_export_all_data)
Result.extend (but)
end
feature -- Interface text.
text_export_all_data: STRING_32 = "Export all data"
end

View File

@@ -93,7 +93,7 @@ feature -- HTTP Methods
s.append ("<a href=%"")
s.append (req.absolute_script_url ("/admin/role/" + u.id.out))
s.append ("%">")
s.append (u.name)
s.append (html_encoded (u.name))
s.append ("</a>")
s.append ("</li>%N")
end

View File

@@ -106,7 +106,7 @@ feature -- HTTP Methods
s.append ("<a href=%"")
s.append (req.absolute_script_url ("/admin/user/"+u.id.out))
s.append ("%">")
s.append (u.name)
s.append (html_encoded (u.name))
s.append ("</a>")
s.append ("</li>%N")
end

View File

@@ -123,6 +123,7 @@ feature -- Hooks configuration
lnk.set_weight (98)
a_menu_system.primary_menu.extend (lnk)
end
end
feature -- Handler

View File

@@ -50,10 +50,10 @@ feature -- Access
feature -- Access: node
summary: detachable READABLE_STRING_8
summary: detachable READABLE_STRING_32
-- A short summary of the node.
content: detachable READABLE_STRING_8
content: detachable READABLE_STRING_32
-- Content of the node.
format: detachable READABLE_STRING_8

View File

@@ -97,6 +97,21 @@ feature -- Access node
Result := nodes_to_blogs (blog_storage.blogs_from_user_limited (a_user, a_limit, a_offset))
end
feature -- Conversion
full_blog_node (a_blog: CMS_BLOG): CMS_BLOG
-- If `a_blog' is partial, return the full blog node from `a_blog',
-- otherwise return directly `a_blog'.
require
a_blog_set: a_blog /= Void
do
if attached {CMS_BLOG} node_api.full_node (a_blog) as l_full_blog then
Result := l_full_blog
else
Result := a_blog
end
end
feature {NONE} -- Helpers
nodes_to_blogs (a_nodes: LIST [CMS_NODE]): ARRAYED_LIST [CMS_BLOG]

View File

@@ -14,6 +14,8 @@
<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="error" location="$ISE_LIBRARY\contrib\library\utility\general\error\error-safe.ecf"/>
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-safe.ecf"/>
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json-safe.ecf" readonly="false"/>
<library name="text_filter" location="$ISE_LIBRARY\unstable\library\text\text_filter\text_filter-safe.ecf"/>

View File

@@ -22,6 +22,10 @@ inherit
CMS_HOOK_RESPONSE_ALTER
CMS_HOOK_EXPORT
CMS_EXPORT_NODE_UTILITIES
create
make
@@ -153,6 +157,7 @@ feature -- Hooks
do
a_response.hooks.subscribe_to_menu_system_alter_hook (Current)
a_response.hooks.subscribe_to_response_alter_hook (Current)
a_response.hooks.subscribe_to_export_hook (Current)
end
response_alter (a_response: CMS_RESPONSE)
@@ -168,4 +173,74 @@ feature -- Hooks
create lnk.make ("Blogs", "blogs/")
a_menu_system.primary_menu.extend (lnk)
end
export_to (a_export_id_list: detachable ITERABLE [READABLE_STRING_GENERAL]; a_export_parameters: CMS_EXPORT_PARAMETERS; a_response: CMS_RESPONSE)
-- Export data identified by `a_export_id_list',
-- or export all data if `a_export_id_list' is Void.
local
n: CMS_BLOG
p: PATH
d: DIRECTORY
f: PLAIN_TEXT_FILE
lst: LIST [CMS_BLOG]
do
if
a_export_id_list = Void
or else across a_export_id_list as ic some ic.item.same_string ("blog") end
then
if
a_response.has_permissions (<<"export any node", "export blog">>) and then
attached blog_api as l_blog_api
then
lst := l_blog_api.blogs_order_created_desc
a_export_parameters.log ("Exporting " + lst.count.out + " blogs")
across
lst as ic
loop
n := l_blog_api.full_blog_node (ic.item)
a_export_parameters.log (n.content_type + " #" + n.id.out)
p := a_export_parameters.location.extended ("nodes").extended (n.content_type).extended (n.id.out)
create d.make_with_path (p.parent)
if not d.exists then
d.recursive_create_dir
end
create f.make_with_path (p)
if not f.exists or else f.is_access_writable then
f.open_write
f.put_string (json_to_string (blog_node_to_json (n)))
f.close
end
-- Revisions.
if
attached node_api as l_node_api and then
attached l_node_api.node_revisions (n) as l_revisions and then l_revisions.count > 1
then
a_export_parameters.log (n.content_type + " " + l_revisions.count.out + " revisions.")
p := a_export_parameters.location.extended ("nodes").extended (n.content_type).extended (n.id.out)
create d.make_with_path (p)
if not d.exists then
d.recursive_create_dir
end
across
l_revisions as revs_ic
loop
if attached {CMS_BLOG} revs_ic.item as l_blog then
create f.make_with_path (p.extended ("rev-" + n.revision.out).appended_with_extension ("json"))
if not f.exists or else f.is_access_writable then
f.open_write
f.put_string (json_to_string (blog_node_to_json (l_blog)))
end
f.close
end
end
end
end
end
end
end
blog_node_to_json (a_blog: CMS_BLOG): JSON_OBJECT
do
Result := node_to_json (a_blog)
end
end

View File

@@ -83,17 +83,18 @@ feature -- Persistence
if l_update then
if l_has_modif then
sql_change (sql_update_node_data, l_parameters)
sql_modify (sql_update_node_data, l_parameters)
end
else
if l_has_modif then
sql_change (sql_insert_node_data, l_parameters)
sql_insert (sql_insert_node_data, l_parameters)
else
-- no page data, means everything is empty.
-- FOR NOW: always record row
-- sql_change (sql_insert_node_data, l_parameters)
end
end
sql_finalize
end
end
@@ -116,7 +117,8 @@ feature -- Persistence
if a_node.has_id then
create l_parameters.make (1)
l_parameters.put (a_node.id, "nid")
sql_change (sql_delete_node_data, l_parameters)
sql_modify (sql_delete_node_data, l_parameters)
sql_finalize
end
end
@@ -136,18 +138,21 @@ feature {NONE} -- Implementation
l_parameters.put (a_node.revision, "revision")
sql_query (sql_select_node_data, l_parameters)
if not has_error then
n := sql_rows_count
if n = 1 then
if not sql_after then
-- nid, revision, tags
l_rev := sql_read_integer_64 (2)
l_tags := sql_read_string_32 (3)
if l_tags /= Void then
Result := [l_rev, l_tags]
end
else
check unique_data: n = 0 end
sql_forth
if not sql_after then
check unique_data: n = 0 end
Result := Void
end
end
end
sql_finalize
ensure
accepted_revision: Result /= Void implies Result.revision <= a_node.revision
end

View File

@@ -230,9 +230,9 @@ feature -- HTML Output
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))
f.append_formatted_to (l_summary, a_output)
else
a_output.append (page.formats.default_format.formatted_output (l_summary))
page.formats.default_format.append_formatted_to (l_summary, a_output)
end
a_output.append ("<br />")
a_output.append (page.link ("See more...", lnk.location, Void))

View File

@@ -123,7 +123,7 @@ feature -- HTML Output
do
a_output.append ("<h2>Posts from ")
if attached user as l_user then
a_output.append (l_user.name)
a_output.append (html_encoded (l_user.name))
else
a_output.append ("unknown user")
end

View File

@@ -6,8 +6,12 @@ note
deferred class
CMS_BLOG_STORAGE_I
inherit
CMS_NODE_STORAGE_I
feature -- Error Handling
error_handler: ERROR_HANDLER
-- Error handler.
deferred
end
feature -- Access

View File

@@ -23,9 +23,10 @@ feature -- Access
error_handler.reset
write_information_log (generator + ".blogs_count")
sql_query (sql_select_blog_count, Void)
if sql_rows_count = 1 then
if not has_error and not sql_after then
Result := sql_read_integer_64 (1)
end
sql_finalize
end
blogs_count_from_user (a_user: CMS_USER) : INTEGER_64
@@ -38,9 +39,10 @@ feature -- Access
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
if not has_error and not sql_after then
Result := sql_read_integer_64 (1)
end
sql_finalize
end
blogs: LIST [CMS_NODE]
@@ -62,6 +64,7 @@ feature -- Access
end
sql_forth
end
sql_finalize
end
blogs_limited (a_limit: NATURAL_32; a_offset: NATURAL_32): LIST [CMS_NODE]
@@ -88,6 +91,7 @@ feature -- Access
end
sql_forth
end
sql_finalize
end
blogs_from_user_limited (a_user: CMS_USER; a_limit: NATURAL_32; a_offset: NATURAL_32): LIST [CMS_NODE]
@@ -115,6 +119,7 @@ feature -- Access
end
sql_forth
end
sql_finalize
end
feature {NONE} -- Queries

View File

@@ -45,6 +45,15 @@ feature -- Access
description_enabled: BOOLEAN
-- Display description?
feature -- Status report
has_category_filter: BOOLEAN
-- Is there any category filtering?
-- i.e via `included_categories'
do
Result := attached included_categories as cats and then not cats.is_empty
end
feature -- Element change
set_description (a_desc: detachable READABLE_STRING_GENERAL)
@@ -99,6 +108,10 @@ feature -- Element change
feature -- Status report
is_included (e: FEED_ITEM): BOOLEAN
-- Is `e' included in final aggregation?
-- i.e: related to `included_categories'
-- note that if `e' has no category, it is included by default,
-- even if `included_categories' is defined.
do
Result := True
if attached e.categories as e_cats then

View File

@@ -20,7 +20,7 @@ feature -- Access
agg: FEED_AGGREGATION
l_feed_id: READABLE_STRING_32
l_title: detachable READABLE_STRING_GENERAL
l_location_list: detachable LIST [READABLE_STRING_32]
l_locations: detachable STRING_TABLE [READABLE_STRING_8]
utf: UTF_CONVERTER
l_table: like internal_aggregations
do
@@ -36,16 +36,28 @@ feature -- Access
l_ids as ic
loop
l_feed_id := ic.item
l_location_list := cfg.text_list_item ({STRING_32} "feeds." + l_feed_id + ".locations")
create l_locations.make (1)
if attached cfg.text_list_item ({STRING_32} "feeds." + l_feed_id + ".locations") as l_location_list then
across
l_location_list as loc_ic
loop
l_locations.force (utf.utf_32_string_to_utf_8_string_8 (loc_ic.item), loc_ic.item)
end
end
if attached cfg.text_table_item ({STRING_32} "feeds." + l_feed_id + ".locations") as l_location_table then
across
l_location_table as loc_tb_ic
loop
l_locations.force (utf.utf_32_string_to_utf_8_string_8 (loc_tb_ic.item), loc_tb_ic.key)
end
end
if
attached cfg.text_item ({STRING_32} "feeds." + l_feed_id + ".location") as l_location
then
if l_location_list = Void then
create {ARRAYED_LIST [READABLE_STRING_32]} l_location_list.make (1)
end
l_location_list.force (l_location)
l_locations.force (utf.utf_32_string_to_utf_8_string_8 (l_location), l_location)
end
if l_location_list /= Void and then not l_location_list.is_empty then
if l_locations /= Void and then not l_locations.is_empty then
l_title := cfg.text_item ({STRING_32} "feeds." + l_feed_id + ".title")
if l_title = Void then
l_title := l_feed_id
@@ -62,10 +74,10 @@ feature -- Access
end
end
if attached cfg.text_item ({STRING_32} "feeds." + l_feed_id + ".option_description") as l_description_opt then
agg.set_description_enabled (not l_description_opt.is_case_insensitive_equal_general ("disabled"))
agg.set_description_enabled (not l_description_opt.is_case_insensitive_equal_general ("disabled"))
end
across
l_location_list as loc_ic
l_locations as loc_ic
loop
agg.locations.force (utf.utf_32_string_to_utf_8_string_8 (loc_ic.item))
end
@@ -113,16 +125,11 @@ feature -- Operation
aggregation_feed (agg: FEED_AGGREGATION): detachable FEED
-- Feed from aggregation `agg'.
local
fac: FEED_DEFAULT_PARSERS
f: detachable FEED
do
create fac
across
agg.locations as ic
loop
if attached new_http_client_session (ic.item).get ("", Void).body as res then
f := fac.feed_from_string (res)
if attached feed (ic.item) as f then
if Result /= Void then
if f /= Void then
Result := Result + f

View File

@@ -1,7 +1,7 @@
note
description: "CMS module bringing support for feed aggregation."
date: "$Date: 2015-02-13 13:08:13 +0100 (ven., 13 févr. 2015) $"
revision: "$Revision: 96616 $"
date: "$Date$"
revision: "$Revision$"
class
FEED_AGGREGATOR_MODULE
@@ -23,6 +23,8 @@ inherit
CMS_HOOK_MENU_SYSTEM_ALTER
CMS_HOOK_CACHE
create
make
@@ -44,9 +46,13 @@ feature -- Access
-- List of permission ids, used by this module, and declared.
do
Result := Precursor
Result.force ("manage feed aggregator")
Result.force (permission__manage_feed_aggregator)
Result.force (permission__clear_feed_cache)
end
permission__manage_feed_aggregator: STRING = "manage feed aggregator"
permission__clear_feed_cache: STRING = "clear feed cache"
feature {CMS_API} -- Module Initialization
initialize (api: CMS_API)
@@ -181,10 +187,29 @@ feature -- Hooks configuration
a_response.hooks.subscribe_to_block_hook (Current)
a_response.hooks.subscribe_to_response_alter_hook (Current)
a_response.hooks.subscribe_to_menu_system_alter_hook (Current)
a_response.hooks.subscribe_to_cache_hook (Current)
end
feature -- Hook
clear_cache (a_cache_id_list: detachable ITERABLE [READABLE_STRING_GENERAL]; a_response: CMS_RESPONSE)
-- <Precursor>.
local
p: PATH
dir: DIRECTORY
do
if a_response.has_permissions (<<permission__clear_feed_cache, permission__manage_feed_aggregator>>) then
if a_cache_id_list = Void then
-- Clear all cache.
p := a_response.api.files_location.extended (".cache").extended (name)
create dir.make_with_path (p)
if dir.exists then
dir.recursive_delete
end
end
end
end
block_list: ITERABLE [like {CMS_BLOCK}.name]
-- List of block names, managed by current object.
local
@@ -211,6 +236,7 @@ feature -- Hook
s: READABLE_STRING_8
b: CMS_CONTENT_BLOCK
pref: STRING
nb: INTEGER
do
if attached feed_aggregator_api as l_feed_api then
pref := "feed."
@@ -219,7 +245,15 @@ feature -- Hook
else
s := a_block_id
end
if attached feed_to_html (s, 0, True, a_response) as l_content then
nb := 0
if
attached a_response.block_options (a_block_id) as l_options and then
attached {READABLE_STRING_GENERAL} l_options.item ("size") as l_size and then
l_size.is_integer
then
nb := l_size.to_integer
end
if attached feed_to_html (s, nb, True, a_response) as l_content then
create b.make (a_block_id, Void, l_content, Void)
b.set_is_raw (True)
a_response.add_block (b, "feed_" + s)
@@ -280,6 +314,19 @@ feature -- Hook
vis.set_footer (s)
if attached l_feed_api.aggregation_feed (l_agg) as l_feed then
if l_agg.has_category_filter and attached l_feed.items as lst then
from
lst.start
until
lst.after
loop
if not l_agg.is_included (lst.item_for_iteration) then
lst.remove
else
lst.forth
end
end
end
l_feed.accept (vis)
end
l_cache.put (Result)
@@ -300,7 +347,7 @@ feature -- Hook
-- for related response `a_response'.
do
a_menu_system.navigation_menu.extend (create {CMS_LOCAL_LINK}.make ("Feeds", "feed_aggregation/"))
if a_response.has_permission ("manage feed aggregator") then
if a_response.has_permission (permission__manage_feed_aggregator) then
a_menu_system.management_menu.extend (create {CMS_LOCAL_LINK}.make ("Feeds (admin)", "admin/feed_aggregator/"))
end
end

View File

@@ -0,0 +1,28 @@
{
"ids": ["news", "forum"],
"feeds": {
"news": {
"title": "Eiffel related posts",
"expiration": "21600",
"size": 5,
"locations": [
"https://bertrandmeyer.com/feed/",
"https://room.eiffel.com/blog/feed",
"https://room.eiffel.com/article/feed",
"https://room.eiffel.com/library/feed"
]
, "categories": ["Eiffel"]
,"option_description": "enabled"
},
"forum": {
"title": "Eiffel Forum",
"expiration": "21600",
"size": 5,
"locations": [
"https://groups.google.com/forum/feed/eiffel-users/msgs/atom.xml?num=15",
"http://stackoverflow.com/feeds/tag?tagnames=eiffel&sort=newest"
]
,"option_description": "enabled"
}
}
}

View File

@@ -0,0 +1 @@
Google Custom Search Module.

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<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="google_search" uuid="054E9C5C-ACCB-4A4D-B825-6C574AEC30A9" library_target="google_search">
<target name="google_search">
<root all_classes="true"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="cms" location="..\..\cms-safe.ecf" readonly="false"/>
<library name="cms_app_env" location="..\..\library\app_env\app_env-safe.ecf" readonly="false"/>
<library name="cms_config" location="..\..\library\configuration\config-safe.ecf"/>
<library name="error" location="$ISE_LIBRARY\contrib\library\utility\general\error\error-safe.ecf"/>
<library name="google_cse" location="..\..\library\gcse\gcse-safe.ecf"/>
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http-safe.ecf"/>
<library name="net" location="$ISE_LIBRARY\library\net\net-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_encoder" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\text\encoder\encoder-safe.ecf"/>
<cluster name="src" location="src\" recursive="true"/>
</target>
</system>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="google_search" uuid="054E9C5C-ACCB-4A4D-B825-6C574AEC30A9" library_target="google_search">
<target name="google_search">
<root all_classes="true"/>
<option is_attached_by_default="false" void_safety="none">
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
<library name="cms" location="..\..\cms.ecf" readonly="false"/>
<library name="cms_app_env" location="..\..\library\app_env\app_env.ecf" readonly="false"/>
<library name="cms_config" location="..\..\library\configuration\config.ecf"/>
<library name="error" location="$ISE_LIBRARY\contrib\library\utility\general\error\error.ecf"/>
<library name="google_cse" location="..\..\library\gcse\gcse.ecf"/>
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http.ecf"/>
<library name="net" location="$ISE_LIBRARY\library\net\net.ecf"/>
<library name="time" location="$ISE_LIBRARY\library\time\time.ecf"/>
<library name="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf.ecf"/>
<library name="wsf_encoder" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\text\encoder\encoder.ecf"/>
<cluster name="src" location="src\" recursive="true"/>
</target>
</system>

View File

@@ -0,0 +1,6 @@
{
"gcse": {
"cx":"",
"secret_key":""
}
}

View File

@@ -0,0 +1,40 @@
<section>
<header>
<h2>Results for <kbd>{$result.current_page.search_terms/}</kbd></h2>
</header>
<!-- list of results -->
<ol start="{$result.current_page.start_index/}">
<!-- Item result -->
{foreach from="$result.items" item="item"}
<li>
<article>
<header>
<h3>
<cite>
<a href="{$item.link/}">{$item.title/}</a>
</cite>
</h3>
</header>
<blockquote cite="{$item.link/}">
<p>{$item.html_snippet/}</p>
<footer>
<p><abbr title="Uniform Resource Locator">Source</abbr> <a href="{$item.link/}">{$item.display_link/}</a></p>
</footer>
</blockquote>
</article>
</li>
{/foreach}
</ol>
<ul class="cms-page-links">
{if isset="$result.previous_page"}
<li><a href="{$site_url/}gcse/?q={$result.previous_page.search_terms/}&amp;start={$result.previous_page.start_index/}&amp;num={$result.previous_page.count/}">Previous</a></li>
{/if}
{if isset="$result.next_page"}
<li><a href="{$site_url/}gcse/?q={$result.next_page.search_terms/}&amp;start={$result.next_page.start_index/}&amp;num={$result.next_page.count/}">Next</a></li>
{/if}
</ul>
</section>

View File

@@ -0,0 +1,150 @@
note
description: "[
Module providing Google Custom Search functionality.
]"
date: "$Date: 2015-10-09 20:50:01 -0300 (vi. 09 de oct. de 2015) $"
revision: "$Revision: 97982 $"
class
GOOGLE_CUSTOM_SEARCH_MODULE
inherit
CMS_MODULE
CMS_HOOK_BLOCK_HELPER
SHARED_EXECUTION_ENVIRONMENT
export
{NONE} all
end
REFACTORING_HELPER
SHARED_LOGGER
create
make
feature {NONE} -- Initialization
make
-- Create current module
do
version := "1.0"
description := "Google custome search module"
package := "search"
end
feature -- Access
name: STRING = "google_search"
-- <Precursor>
feature -- Router
setup_router (a_router: WSF_ROUTER; a_api: CMS_API)
-- Router configuration.
do
a_router.handle ("/gcse", create {WSF_URI_AGENT_HANDLER}.make (agent handle_search (a_api, ?, ?)), a_router.methods_head_get)
end
feature -- Recaptcha
gcse_secret_key (api: CMS_API): detachable READABLE_STRING_8
-- Get recaptcha security key.
local
utf: UTF_CONVERTER
do
if attached api.module_configuration (Current, Void) as cfg then
if
attached cfg.text_item ("gcse.secret_key") as l_recaptcha_key and then
not l_recaptcha_key.is_empty
then
Result := utf.utf_32_string_to_utf_8_string_8 (l_recaptcha_key)
end
end
end
gcse_cx_key (api: CMS_API): detachable READABLE_STRING_8
-- Get recaptcha security key.
local
utf: UTF_CONVERTER
do
if attached api.module_configuration (Current, Void) as cfg then
if
attached cfg.text_item ("gcse.cx") as l_recaptcha_key and then
not l_recaptcha_key.is_empty
then
Result := utf.utf_32_string_to_utf_8_string_8 (l_recaptcha_key)
end
end
end
feature -- Handler
handle_search (api: CMS_API; req: WSF_REQUEST; res: WSF_RESPONSE)
local
r: CMS_RESPONSE
l_parameters:GCSE_QUERY_PARAMETERS
l_search: GCSE_API
do
-- TODO handle errors!!!
write_debug_log (generator + ".handle_search")
create {GENERIC_VIEW_CMS_RESPONSE} r.make (req, res, api)
if
attached {WSF_STRING} req.query_parameter ("q") as l_query and then
not l_query.value.is_empty
then
if
attached gcse_cx_key (api) as l_cx and then
attached gcse_secret_key (api) as l_key
then
create l_parameters.make (l_key, l_cx, l_query.url_encoded_value )
if
attached {WSF_STRING} req.query_parameter ("start") as l_index and then
attached {WSF_STRING} req.query_parameter ("num") as l_num
then
l_parameters.set_start (l_index.value)
l_parameters.set_num (l_num.value)
end
create l_search.make (l_parameters)
l_search.search
if
attached l_search.last_result as l_result and then
l_result.status = 200
then
if attached template_block (Current, "search", r) as l_tpl_block then
l_tpl_block.set_value (l_result, "result")
r.add_block (l_tpl_block, "content")
end
else
-- Quota limit (403 status code) or not results.
google_search_site (req, r, l_query)
end
else
-- If no key are provided, at least output google search result page.
google_search_site (req, r, l_query)
end
else
r.add_message ("No query submitted", Void)
end
r.execute
end
feature {NONE} -- Helper
google_search_site (req: WSF_REQUEST; res: CMS_RESPONSE; query: WSF_STRING)
-- Workaround to output google search result page
-- If no key are provided or if GCSE reached the quota limit.
local
l_url_encoder: URL_ENCODER
do
create l_url_encoder
if req.is_https then
res.set_redirection ("https://www.google.com/search?sitesearch=" + l_url_encoder.general_encoded_string (res.absolute_url ("", Void)) + "&q=" + query.url_encoded_value)
else
res.set_redirection ("http://www.google.com/search?sitesearch=" + l_url_encoder.general_encoded_string (res.absolute_url ("", Void)) + "&q=" + query.url_encoded_value)
end
end
end

View File

@@ -330,6 +330,14 @@ feature -- Access: Node
end
end
nodes_of_type (a_node_type: CMS_CONTENT_TYPE): LIST [CMS_NODE]
-- List of nodes of type `a_node_type'.
do
Result := node_storage.nodes_of_type (a_node_type)
ensure
expected_type: across Result as ic all ic.item.content_type.same_string (a_node_type.name) end
end
feature -- Access: page/book outline
children (a_node: CMS_NODE): detachable LIST [CMS_NODE]

View File

@@ -25,6 +25,10 @@ inherit
CMS_RECENT_CHANGES_HOOK
CMS_HOOK_EXPORT
CMS_EXPORT_NODE_UTILITIES
create
make
@@ -147,6 +151,7 @@ feature -- Access
do
Result := Precursor
Result.force ("create any node")
Result.force ("export any node")
if attached node_api as l_node_api then
across
@@ -173,6 +178,8 @@ feature -- Access
Result.force ("view unpublished " + l_type_name)
Result.force ("view revisions own " + l_type_name)
Result.force ("export " + l_type_name)
end
end
Result.force ("view trash")
@@ -230,6 +237,7 @@ feature -- Hooks
a_response.hooks.subscribe_to_menu_system_alter_hook (Current)
a_response.hooks.subscribe_to_block_hook (Current)
a_response.hooks.subscribe_to_response_alter_hook (Current)
a_response.hooks.subscribe_to_export_hook (Current)
-- Module specific hook, if available.
a_response.hooks.subscribe_to_hook (Current, {CMS_RECENT_CHANGES_HOOK})
@@ -353,4 +361,94 @@ feature -- Hooks
end
end
export_to (a_export_id_list: detachable ITERABLE [READABLE_STRING_GENERAL]; a_export_parameters: CMS_EXPORT_PARAMETERS; a_response: CMS_RESPONSE)
-- Export data identified by `a_export_id_list',
-- or export all data if `a_export_id_list' is Void.
local
l_node_type: CMS_CONTENT_TYPE
n: CMS_NODE
p: PATH
d: DIRECTORY
f: PLAIN_TEXT_FILE
lst: LIST [CMS_NODE]
do
if attached node_api as l_node_api then
across
l_node_api.node_types as types_ic
loop
l_node_type := types_ic.item
if
a_response.has_permissions (<<"export any node", "export " + l_node_type.name>>) and then
l_node_type.name.same_string_general ("page") and then
( a_export_id_list = Void
or else across a_export_id_list as ic some ic.item.same_string (l_node_type.name) end
)
then
-- For now, handle only page from this node module.
lst := l_node_api.nodes_of_type (l_node_type)
a_export_parameters.log ("Exporting " + lst.count.out + " nodes of type " + l_node_type.name)
p := a_export_parameters.location.extended ("nodes").extended (l_node_type.name)
create d.make_with_path (p)
if not d.exists then
d.recursive_create_dir
end
across
lst as ic
loop
n := l_node_api.full_node (ic.item)
a_export_parameters.log (l_node_type.name + " #" + n.id.out + " rev=" + n.revision.out)
create f.make_with_path (p.extended (n.id.out).appended_with_extension ("json"))
if not f.exists or else f.is_access_writable then
f.open_write
if attached {CMS_PAGE} n as l_page then
f.put_string (json_to_string (page_node_to_json (l_page)))
else
f.put_string (json_to_string (node_to_json (n)))
end
f.close
end
-- Revisions.
if attached l_node_api.node_revisions (n) as l_revisions and then l_revisions.count > 1 then
a_export_parameters.log (l_node_type.name + " " + l_revisions.count.out + " revisions.")
p := a_export_parameters.location.extended ("nodes").extended (l_node_type.name).extended (n.id.out)
create d.make_with_path (p)
if not d.exists then
d.recursive_create_dir
end
across
l_revisions as revs_ic
loop
n := revs_ic.item
create f.make_with_path (p.extended ("rev-" + n.revision.out).appended_with_extension ("json"))
if not f.exists or else f.is_access_writable then
f.open_write
if attached {CMS_PAGE} n as l_page then
f.put_string (json_to_string (page_node_to_json (l_page)))
else
f.put_string (json_to_string (node_to_json (n)))
end
f.close
end
end
end
end
end
end
end
end
page_node_to_json (a_page: CMS_PAGE): JSON_OBJECT
local
j: JSON_OBJECT
do
Result := node_to_json (a_page)
if attached a_page.parent as l_parent_page then
create j.make_empty
j.put_string (l_parent_page.content_type, "type")
j.put_integer (l_parent_page.id, "nid")
Result.put (j, "parent")
end
end
end

View File

@@ -103,12 +103,12 @@ feature -- Access
-- Full title of the node.
-- Required!
summary: detachable READABLE_STRING_8
summary: detachable READABLE_STRING_32
-- A short summary of the node.
deferred
end
content: detachable READABLE_STRING_8
content: detachable READABLE_STRING_32
-- Content of the node.
deferred
end

View File

@@ -33,10 +33,10 @@ feature -- Access: code
feature -- Access: content
summary: detachable READABLE_STRING_8
summary: detachable READABLE_STRING_32
-- A short summary of the node.
content: detachable READABLE_STRING_8
content: detachable READABLE_STRING_32
-- Content of the node.
format: detachable READABLE_STRING_8

View File

@@ -44,10 +44,10 @@ feature -- Access
feature -- Access: content
summary: detachable READABLE_STRING_8
summary: detachable READABLE_STRING_32
-- A short summary of the node.
content: detachable READABLE_STRING_8
content: detachable READABLE_STRING_32
-- Content of the node.
format: detachable READABLE_STRING_8

View File

@@ -0,0 +1,55 @@
note
description: "[
Routines usefull during node exportation (see {CMS_HOOK_EXPORT}).
]"
date: "$Date$"
revision: "$Revision$"
class
CMS_EXPORT_NODE_UTILITIES
inherit
CMS_EXPORT_JSON_UTILITIES
feature -- Access
node_to_json (n: CMS_NODE): JSON_OBJECT
local
jo,j_author: JSON_OBJECT
do
create Result.make_empty
Result.put_string (n.content_type, "type")
Result.put_integer (n.id, "nid")
Result.put_integer (n.revision, "revision")
Result.put_string (n.title, "title")
put_date_into_json (n.creation_date, "creation_date", Result)
put_date_into_json (n.modification_date, "modification_date", Result)
put_date_into_json (n.publication_date, "publication_date", Result)
Result.put_integer (n.status, "status")
if attached n.author as u then
create j_author.make
j_author.put_integer (u.id, "uid")
j_author.put_string (u.name, "name")
Result.put (j_author, "author")
end
create jo.make_empty
if attached n.format as l_format then
jo.put_string (l_format, "format")
end
if attached n.summary as s then
jo.put_string (s, "summary")
end
if attached n.content as s then
jo.put_string (s, "content")
end
Result.put (jo, "data")
if attached n.link as lnk then
create jo.make_empty
jo.put_string (lnk.title, "title")
jo.put_string (lnk.location, "location")
jo.put_integer (lnk.weight, "weight")
Result.put (jo, "link")
end
end
end

View File

@@ -100,6 +100,7 @@ feature -- Forms ...
local
ti: WSF_FORM_TEXT_INPUT
l_uri: detachable READABLE_STRING_8
l_iri: detachable READABLE_STRING_32
do
-- Path alias
create ti.make ("path_alias")
@@ -111,7 +112,8 @@ feature -- Forms ...
if attached a_node.link as lnk then
l_uri := lnk.location
else
l_uri := percent_encoder.percent_decoded_string (response.api.location_alias (response.node_api.node_path (a_node)))
l_iri := percent_encoder.percent_decoded_string (response.api.location_alias (response.node_api.node_path (a_node)))
l_uri := l_iri.to_string_8
end
ti.set_text_value (l_uri)
ti.set_description ("Optionally specify an alternative URL path by which this content can be accessed. For example, type 'about' when writing an about page. Use a relative path or the URL alias won't work.")
@@ -151,10 +153,9 @@ feature -- Forms ...
end
end
update_node (response: NODE_RESPONSE; fd: WSF_FORM_DATA; a_node: CMS_NODE)
local
b,s: detachable READABLE_STRING_8
b,s: detachable READABLE_STRING_32
f: detachable CONTENT_FORMAT
do
if attached fd.integer_item ("id") as l_id and then l_id > 0 then
@@ -193,7 +194,7 @@ feature -- Forms ...
new_node (response: NODE_RESPONSE; fd: WSF_FORM_DATA; a_node: detachable CMS_NODE): G
-- <Precursor>
local
b,s: detachable READABLE_STRING_8
b,s: detachable READABLE_STRING_32
f: detachable CONTENT_FORMAT
l_node: detachable like new_node
do
@@ -304,7 +305,7 @@ feature -- Output
s.append ("<div class=%"info%"> ")
if attached a_node.author as l_author then
s.append (" by ")
s.append (l_author.name)
s.append (a_response.html_encoded (l_author.name))
end
if attached a_node.modification_date as l_modified then
s.append (" (modified: ")
@@ -321,9 +322,9 @@ feature -- Output
-- if attached a_node.summary as l_summary then
-- s.append ("<p class=%"summary%">")
-- if attached node_api.cms_api.format (a_node.format) as f then
-- s.append (f.formatted_output (l_summary))
-- append_formatted_output (l_content, f, s)
-- else
-- s.append (a_response.formats.default_format.formatted_output (l_summary))
-- append_formatted_output (l_content, a_response.formats.default_format, s)
-- end
-- s.append ("</p>")
@@ -333,9 +334,9 @@ feature -- Output
if attached a_node.content as l_content then
s.append ("<p class=%"content%">")
if attached node_api.cms_api.format (a_node.format) as f then
s.append (f.formatted_output (l_content))
append_formatted_output (l_content, f, s)
else
s.append (a_response.formats.default_format.formatted_output (l_content))
append_formatted_output (l_content, a_response.formats.default_format, s)
end
s.append ("</p>")
@@ -346,5 +347,15 @@ feature -- Output
a_response.set_main_content (s)
end
append_formatted_output (a_content: READABLE_STRING_GENERAL; a_format: CONTENT_FORMAT; a_output: STRING_8)
-- Format `a_content' with format `a_format'.
do
if a_content.is_valid_as_string_8 then
a_output.append (a_format.formatted_output (a_content.to_string_8))
else
a_format.append_formatted_to (a_content, a_output)
end
end
end

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<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="node" uuid="C7114DD4-FA92-4AE5-A209-0FFC45E44257" library_target="node">
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="node" uuid="C7114DD4-FA92-4AE5-A209-0FFC45E44257" library_target="node">
<target name="node">
<root all_classes="true"/>
<file_rule>
@@ -7,7 +7,7 @@
<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" is_obsolete_routine_type="true" void_safety="all" syntax="transitional">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
@@ -17,6 +17,7 @@
<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_authorization" location="$ISE_LIBRARY\contrib\library\web\authentication\http_authorization\http_authorization-safe.ecf" readonly="false"/>
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json-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="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf-safe.ecf"/>

View File

@@ -17,6 +17,7 @@
<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_authorization" location="$ISE_LIBRARY\contrib\library\network\authentication\http_authorization\http_authorization.ecf" readonly="false"/>
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json.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="wsf" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf\wsf.ecf"/>

View File

@@ -127,6 +127,26 @@ feature -- Access
deferred
end
nodes_of_type (a_node_type: CMS_CONTENT_TYPE): LIST [CMS_NODE]
-- List of nodes of type `a_node_type'.
--| Redefine to optimize!
do
Result := nodes
from
Result.start
until
Result.after
loop
if Result.item.content_type.same_string (a_node_type.name) then
Result.forth
else
Result.remove
end
end
ensure
expected_type: across Result as ic all ic.item.content_type.same_string (a_node_type.name) end
end
feature -- Access: outline
children (a_node: CMS_NODE): detachable LIST [CMS_NODE]

View File

@@ -12,6 +12,9 @@ inherit
CMS_PROXY_STORAGE_SQL
CMS_NODE_STORAGE_I
redefine
nodes_of_type
end
CMS_STORAGE_SQL_I
@@ -28,12 +31,12 @@ feature -- Access
error_handler.reset
write_information_log (generator + ".nodes_count")
sql_query (sql_select_nodes_count, Void)
if sql_rows_count = 1 then
if not has_error and not sql_after then
Result := sql_read_natural_64 (1)
end
sql_finalize
end
nodes: LIST [CMS_NODE]
-- List of nodes.
do
@@ -53,6 +56,7 @@ feature -- Access
end
sql_forth
end
sql_finalize
end
node_revisions (a_node: CMS_NODE): LIST [CMS_NODE]
@@ -80,6 +84,7 @@ feature -- Access
end
sql_forth
end
sql_finalize
end
trashed_nodes (a_user: detachable CMS_USER): LIST [CMS_NODE]
@@ -109,6 +114,7 @@ feature -- Access
end
sql_forth
end
sql_finalize
end
recent_nodes (a_lower: INTEGER; a_count: INTEGER): LIST [CMS_NODE]
@@ -135,6 +141,7 @@ feature -- Access
end
sql_forth
end
sql_finalize
end
recent_node_changes_before (a_lower: INTEGER; a_count: INTEGER; a_date: DATE_TIME): LIST [CMS_NODE]
@@ -163,6 +170,7 @@ feature -- Access
end
sql_forth
end
sql_finalize
end
node_by_id (a_id: INTEGER_64): detachable CMS_NODE
@@ -175,9 +183,10 @@ feature -- Access
create l_parameters.make (1)
l_parameters.put (a_id, "nid")
sql_query (sql_select_node_by_id, l_parameters)
if sql_rows_count = 1 then
if not has_error and not sql_after then
Result := fetch_node
end
sql_finalize
end
node_by_id_and_revision (a_node_id, a_revision: INTEGER_64): detachable CMS_NODE
@@ -191,9 +200,10 @@ feature -- Access
l_parameters.put (a_node_id, "nid")
l_parameters.put (a_revision, "revision")
sql_query (sql_select_node_by_id_and_revision, l_parameters)
if sql_rows_count = 1 then
if not has_error and not sql_after then
Result := fetch_node
end
sql_finalize
end
node_author (a_node: CMS_NODE): detachable CMS_USER
@@ -207,9 +217,10 @@ feature -- Access
l_parameters.put (a_node.id, "nid")
l_parameters.put (a_node.revision, "revision")
sql_query (Select_user_author, l_parameters)
if sql_rows_count >= 1 then
if not has_error and not sql_after then
Result := fetch_author
end
sql_finalize
end
last_inserted_node_id: INTEGER_64
@@ -218,9 +229,10 @@ feature -- Access
error_handler.reset
write_information_log (generator + ".last_inserted_node_id")
sql_query (Sql_last_insert_node_id, Void)
if sql_rows_count = 1 then
if not has_error and not sql_after then
Result := sql_read_integer_64 (1)
end
sql_finalize
end
last_inserted_node_revision (a_node: detachable CMS_NODE): INTEGER_64
@@ -234,15 +246,20 @@ feature -- Access
create l_parameters.make (1)
l_parameters.force (a_node.id, "nid")
sql_query (Sql_last_insert_node_revision_for_nid, l_parameters)
if sql_rows_count = 1 then
if not has_error and not sql_after then
if sql_item (1) /= Void then
Result := sql_read_integer_64 (1)
end
sql_forth
if not sql_after then
check no_more_than_one: False end
end
end
sql_finalize
end
-- if Result = 0 and not has_error then --| include the case a_node = Void
-- sql_query (Sql_last_insert_node_revision, Void)
-- if sql_rows_count = 1 then
-- if not has_error and not sql_after then
-- if sql_item (1) /= Void then
-- Result := sql_read_integer_64 (1)
-- end
@@ -250,6 +267,33 @@ feature -- Access
-- end
end
nodes_of_type (a_node_type: CMS_CONTENT_TYPE): 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 + ".nodes_of_type")
create l_parameters.make (1)
l_parameters.put (a_node_type.name, "node_type")
from
sql_query (sql_select_nodes_of_type, l_parameters)
sql_start
until
sql_after
loop
if attached fetch_node as l_node then
check expected_node_type: l_node.content_type.same_string (a_node_type.name) end
Result.force (l_node)
end
sql_forth
end
sql_finalize
end
feature -- Access: outline
children (a_node: CMS_NODE): detachable LIST [CMS_NODE]
@@ -275,6 +319,7 @@ feature -- Access: outline
end
sql_forth
end
sql_finalize
end
available_parents_for_node (a_node: CMS_NODE): LIST [CMS_NODE]
@@ -300,6 +345,7 @@ feature -- Access: outline
end
sql_forth
end
sql_finalize
end
feature -- Change: Node
@@ -328,7 +374,8 @@ feature -- Change: Node
l_parameters.put (create {DATE_TIME}.make_now_utc, "changed")
l_parameters.put ({CMS_NODE_API}.trashed, "status")
l_parameters.put (a_id, "nid")
sql_change (sql_trash_node, l_parameters)
sql_modify (sql_trash_node, l_parameters)
sql_finalize
end
delete_node_base (a_node: CMS_NODE)
@@ -343,11 +390,13 @@ feature -- Change: Node
error_handler.reset
create l_parameters.make (1)
l_parameters.put (a_node.id, "nid")
sql_change (sql_delete_node, l_parameters)
sql_modify (sql_delete_node, l_parameters)
sql_finalize
-- we remove node_revisions and pages.
-- Check: maybe we need a transaction.
sql_change (sql_delete_node_revisions, l_parameters)
sql_modify (sql_delete_node_revisions, l_parameters)
sql_finalize
if not error_handler.has_error then
extended_delete (a_node)
@@ -368,7 +417,8 @@ feature -- Change: Node
l_parameters.put (l_time, "changed")
l_parameters.put ({CMS_NODE_API}.not_published, "status")
l_parameters.put (a_id, "nid")
sql_change (sql_restore_node, l_parameters)
sql_modify (sql_restore_node, l_parameters)
sql_finalize
end
@@ -412,7 +462,9 @@ feature {NONE} -- Implementation
create l_copy_parameters.make (2)
l_copy_parameters.force (a_node.id, "nid")
-- l_copy_parameters.force (l_rev - 1, "revision")
sql_change (sql_copy_node_to_revision, l_copy_parameters)
sql_insert (sql_copy_node_to_revision, l_copy_parameters)
sql_finalize
if not has_error then
a_node.set_revision (l_rev)
@@ -420,7 +472,8 @@ feature {NONE} -- Implementation
-- Update
l_parameters.put (a_node.id, "nid")
l_parameters.put (a_node.revision, "revision")
sql_change (sql_update_node, l_parameters)
sql_modify (sql_update_node, l_parameters)
sql_finalize
if not error_handler.has_error then
a_node.set_modification_date (now)
@@ -431,7 +484,9 @@ feature {NONE} -- Implementation
l_parameters.put (a_node.creation_date, "created")
l_parameters.put (l_rev, "revision")
sql_change (sql_insert_node, l_parameters)
sql_insert (sql_insert_node, l_parameters)
sql_finalize
if not error_handler.has_error then
a_node.set_modification_date (now)
a_node.set_id (last_inserted_node_id)
@@ -470,6 +525,10 @@ feature {NONE} -- Queries
-- SQL Query to retrieve all nodes.
--| note: {CMS_NODE_API}.trashed = -1
sql_select_nodes_of_type: STRING = "SELECT nid, revision, type, title, summary, content, format, author, publish, created, changed, status FROM nodes WHERE status != -1 AND type=:node_type ;"
-- SQL Query to retrieve all nodes of type :node_type.
--| note: {CMS_NODE_API}.trashed = -1
sql_select_node_revisions: STRING = "SELECT nodes.nid, node_revisions.revision, nodes.type, node_revisions.title, node_revisions.summary, node_revisions.content, node_revisions.format, node_revisions.author, nodes.publish, nodes.created, node_revisions.changed, node_revisions.status FROM nodes INNER JOIN node_revisions ON nodes.nid = node_revisions.nid WHERE nodes.nid = :nid AND node_revisions.revision < :revision ORDER BY node_revisions.revision DESC;"
-- SQL query to get node revisions (missing the latest one).
@@ -550,7 +609,7 @@ feature {NONE} -- Implementation
if attached sql_read_string_32 (5) as l_summary then
Result.set_summary (l_summary)
end
if attached sql_read_string (6) as l_content then
if attached sql_read_string_32 (6) as l_content then
Result.set_content (l_content)
end
if attached sql_read_string (7) as l_format then

View File

@@ -73,17 +73,18 @@ feature -- Persistence
if l_update then
if l_has_modif then
sql_change (sql_update_node_data, l_parameters)
sql_modify (sql_update_node_data, l_parameters)
end
else
if l_has_modif then
sql_change (sql_insert_node_data, l_parameters)
sql_insert (sql_insert_node_data, l_parameters)
else
-- no page data, means everything is empty.
-- FOR NOW: always record row
sql_change (sql_insert_node_data, l_parameters)
sql_insert (sql_insert_node_data, l_parameters)
end
end
sql_finalize
end
end
@@ -121,7 +122,8 @@ feature -- Persistence
if a_node.has_id then
create l_parameters.make (1)
l_parameters.put (a_node.id, "nid")
sql_change (sql_delete_node_data, l_parameters)
sql_modify (sql_delete_node_data, l_parameters)
sql_finalize
end
end
@@ -139,14 +141,19 @@ feature {NONE} -- Implementation
l_parameters.put (a_node.revision, "revision")
sql_query (sql_select_node_data, l_parameters)
if not has_error then
n := sql_rows_count
if n = 1 then
if not sql_after then
-- nid, revision, parent
Result := [sql_read_integer_64 (2), sql_read_integer_64 (3)]
sql_forth
if not sql_after then
check unique_data: n = 0 end
Result := Void
end
else
check unique_data: n = 0 end
end
end
sql_finalize
ensure
accepted_revision: Result /= Void implies Result.revision <= a_node.revision
end

View File

@@ -121,6 +121,7 @@ feature {CMS_API} -- Module management
end
l_sql_storage.sql_forth
end
l_sql_storage.sql_finalize
across l_consumers as ic loop
if not l_sql_storage.sql_table_exists (ic.item) then
if attached l_sql_storage.sql_script_content (api.module_resource_location (Current, (create {PATH}.make_from_string ("scripts")).extended ("oauth2_table.sql.tpl"))) as sql then
@@ -131,6 +132,7 @@ feature {CMS_API} -- Module management
end
end
end
l_sql_storage.sql_finalize
Precursor {CMS_MODULE}(api)
end
end

View File

@@ -53,11 +53,15 @@ feature -- Access User Outh
create l_string.make_from_string (select_user_oauth2_template_by_id)
l_string.replace_substring_all ("$table_name", oauth2_sql_table_name (a_consumer))
sql_query (l_string, l_parameters)
if sql_rows_count = 1 then
if not has_error and not sql_after then
Result := fetch_user
else
check no_more_than_one: sql_rows_count = 0 end
sql_forth
if not sql_after then
check no_more_than_one: False end
Result := Void
end
end
sql_finalize
end
user_oauth2_by_email (a_email: like {CMS_USER}.email; a_consumer: READABLE_STRING_GENERAL): detachable CMS_USER
@@ -73,11 +77,15 @@ feature -- Access User Outh
create l_string.make_from_string (select_user_oauth2_template_by_email)
l_string.replace_substring_all ("$table_name", oauth2_sql_table_name (a_consumer))
sql_query (l_string, l_parameters)
if sql_rows_count = 1 then
if not has_error and not sql_after then
Result := fetch_user
else
check no_more_than_one: sql_rows_count = 0 end
sql_forth
if not sql_after then
check no_more_than_one: False end
Result := Void
end
end
sql_finalize
end
user_oauth2_by_token (a_token: READABLE_STRING_GENERAL; a_consumer: READABLE_STRING_GENERAL): detachable CMS_USER
@@ -93,11 +101,15 @@ feature -- Access User Outh
create l_string.make_from_string (select_user_by_oauth2_template_token)
l_string.replace_substring_all ("$table_name", oauth2_sql_table_name (a_consumer))
sql_query (l_string, l_parameters)
if sql_rows_count = 1 then
if not has_error and not sql_after then
Result := fetch_user
else
check no_more_than_one: sql_rows_count = 0 end
sql_forth
if not sql_after then
check no_more_than_one: False end
Result := Void
end
end
sql_finalize
end
@@ -122,6 +134,7 @@ feature --Access: Consumers
sql_forth
end
end
sql_finalize
end
oauth_consumer_by_name (a_name: READABLE_STRING_8): detachable CMS_OAUTH_20_CONSUMER
@@ -134,11 +147,15 @@ feature --Access: Consumers
create l_parameters.make (1)
l_parameters.put (a_name, "name")
sql_query (sql_oauth_consumer_name, l_parameters)
if sql_rows_count = 1 then
if not has_error and not sql_after then
Result := fetch_consumer
else
check no_more_than_one: sql_rows_count = 0 end
sql_forth
if not sql_after then
check no_more_than_one: False end
Result := Void
end
end
sql_finalize
end
oauth_consumer_by_callback (a_callback: READABLE_STRING_8): detachable CMS_OAUTH_20_CONSUMER
@@ -151,11 +168,15 @@ feature --Access: Consumers
create l_parameters.make (1)
l_parameters.put (a_callback, "name")
sql_query (sql_oauth_consumer_callback, l_parameters)
if sql_rows_count = 1 then
if not has_error and not sql_after then
Result := fetch_consumer
else
check no_more_than_one: sql_rows_count = 0 end
sql_forth
if not sql_after then
check no_more_than_one: False end
Result := Void
end
end
sql_finalize
end
feature -- Change: User OAuth
@@ -181,8 +202,9 @@ feature -- Change: User OAuth
create l_string.make_from_string (sql_insert_oauth2_template)
l_string.replace_substring_all ("$table_name", oauth2_sql_table_name (a_consumer))
sql_change (l_string, l_parameters)
sql_insert (l_string, l_parameters)
sql_commit_transaction
sql_finalize
end
update_user_oauth2 (a_token: READABLE_STRING_GENERAL; a_user_profile: READABLE_STRING_32; a_user: CMS_USER; a_consumer: READABLE_STRING_GENERAL )
@@ -202,8 +224,9 @@ feature -- Change: User OAuth
create l_string.make_from_string (sql_update_oauth2_template)
l_string.replace_substring_all ("$table_name", oauth2_sql_table_name (a_consumer))
sql_change (l_string, l_parameters)
sql_modify (l_string, l_parameters)
sql_commit_transaction
sql_finalize
end
remove_user_oauth2 (a_user: CMS_USER; a_consumer: READABLE_STRING_GENERAL)
@@ -221,8 +244,9 @@ feature -- Change: User OAuth
create l_string.make_from_string (sql_remove_oauth2_template)
l_string.replace_substring_all ("$table_name", oauth2_sql_table_name (a_consumer))
sql_change (l_string, l_parameters)
sql_modify (l_string, l_parameters)
sql_commit_transaction
sql_finalize
end
feature {NONE} -- Implementation OAuth Consumer
@@ -342,7 +366,7 @@ feature {NONE} -- User OAuth2
Sql_remove_oauth2_template: STRING = "DELETE FROM $table_name WHERE uid =:uid;"
Sql_oauth_consumers: STRING = "SELECT name FROM oauth2_consumers";
Sql_oauth_consumers: STRING = "SELECT name FROM oauth2_consumers;"
Sql_oauth2_table_prefix: STRING = "oauth2_"

View File

@@ -33,11 +33,15 @@ feature -- Access User Outh
l_parameters.put (a_uid, "uid")
l_parameters.put (a_identity, "identity")
sql_query (Select_user_openid_by_id, l_parameters)
if sql_rows_count = 1 then
if not has_error and not sql_after then
Result := fetch_user
else
check no_more_than_one: sql_rows_count = 0 end
sql_forth
if not sql_after then
check no_more_than_one: False end
Result := Void
end
end
sql_finalize
end
user_openid_by_identity (a_identity: READABLE_STRING_GENERAL): detachable CMS_USER
@@ -50,14 +54,19 @@ feature -- Access User Outh
create l_parameters.make (1)
l_parameters.put (a_identity, "identity")
sql_query (Select_user_by_openid_identity, l_parameters)
if sql_rows_count = 1 then
if not has_error and not sql_after then
Result := fetch_user
sql_forth
if not sql_after then
check no_more_than_one: False end
Result := Void
end
else
check no_more_than_one: sql_rows_count = 0 end
check no_more_than_one: False end
end
sql_finalize
end
feature --Access: Consumers
openid_consumers: LIST [STRING]
@@ -79,6 +88,7 @@ feature --Access: Consumers
sql_forth
end
end
sql_finalize
end
openid_consumer_by_name (a_name: READABLE_STRING_8): detachable CMS_OPENID_CONSUMER
@@ -91,11 +101,14 @@ feature --Access: Consumers
create l_parameters.make (1)
l_parameters.put (a_name, "name")
sql_query (sql_openid_consumer_name, l_parameters)
if sql_rows_count = 1 then
if not has_error and not sql_after then
Result := fetch_consumer
else
check no_more_than_one: sql_rows_count = 0 end
sql_forth
if not sql_after then
check no_more_than_one: False end
end
end
sql_finalize
end
feature -- Change: User OAuth
@@ -114,8 +127,9 @@ feature -- Change: User OAuth
l_parameters.put (a_user.id, "uid")
l_parameters.put (a_identity, "identity")
l_parameters.put (create {DATE_TIME}.make_now_utc, "utc_date")
sql_change (Sql_insert_openid, l_parameters)
sql_insert (Sql_insert_openid, l_parameters)
sql_commit_transaction
sql_finalize
end
feature {NONE} -- Implementation OAuth Consumer

View File

@@ -70,6 +70,7 @@ feature -- Hook
b: CMS_CONTENT_BLOCK
s, l_content: STRING
gen: FEED_TO_XHTML_VISITOR
nb: NATURAL_32
do
if a_block_id.same_string_general ("recent_changes") then
create l_content.make (1024)
@@ -81,10 +82,19 @@ feature -- Hook
s.append_string ("</li>")
gen.set_footer (s)
recent_changes_feed (a_response, 10, Void).accept (gen)
nb := 10
if
attached a_response.block_options (a_block_id) as l_options and then
attached {READABLE_STRING_GENERAL} l_options.item ("size") as l_size and then
l_size.is_integer
then
nb := l_size.to_natural_32
end
recent_changes_feed (a_response, nb, Void).accept (gen)
create b.make (a_block_id, Void, l_content, Void)
a_response.put_block (b, Void, False)
a_response.add_block (b, Void)
end
end

View File

@@ -0,0 +1,26 @@
<?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="recent_changes" uuid="1C3893A3-46FC-4E60-86AE-37CB7939BC7F" library_target="recent_changes">
<target name="recent_changes">
<root all_classes="true"/>
<file_rule>
<exclude>/EIFGENs$</exclude>
<exclude>/CVS$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" void_safety="none" syntax="transitional">
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
<library name="base_extension" location="$ISE_LIBRARY\library\base_extension\base_extension.ecf"/>
<library name="time" location="$ISE_LIBRARY\library\time\time.ecf"/>
<library name="cms" location="..\..\cms.ecf"/>
<library name="cms_model" location="..\..\library\model\cms_model.ecf" readonly="false"/>
<library name="error" location="$ISE_LIBRARY\contrib\library\utility\general\error\error.ecf"/>
<library name="feed" location="$ISE_LIBRARY\contrib\library\text\parser\feed\feed.ecf"/>
<library name="http" location="$ISE_LIBRARY\contrib\library\network\protocol\http\http.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_html" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\wsf_html\wsf_html.ecf" readonly="false"/>
<cluster name="src" location=".\" recursive="true"/>
</target>
</system>

View File

@@ -0,0 +1,31 @@
note
description: "[
Hook providing cache related management facilities.
]"
date: "$Date: 2014-11-19 20:00:19 +0100 (mer., 19 nov. 2014) $"
revision: "$Revision: 96123 $"
deferred class
CMS_HOOK_CACHE
inherit
CMS_HOOK
feature -- Hook
clear_cache (a_cache_id_list: detachable ITERABLE [READABLE_STRING_GENERAL]; a_response: CMS_RESPONSE)
-- Clear caches identified by `a_cache_id_list',
-- or clear all caches if `a_cache_id_list' is Void.
deferred
end
cache_identifiers: detachable ITERABLE [like {CMS_BLOCK}.name]
-- Optional list of cache id, if any.
do
-- To redefine if needed.
end
note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end

View File

@@ -104,7 +104,6 @@ feature -- Hook: menu_alter
end
end
feature -- Hook: form_alter
subscribe_to_form_alter_hook (h: CMS_HOOK_FORM_ALTER)
@@ -139,12 +138,15 @@ feature -- Hook: block
invoke_block (a_response: CMS_RESPONSE)
-- Invoke block hook for response `a_response' in order to get block from modules.
local
bl: READABLE_STRING_8
bl, l_alias: READABLE_STRING_8
bl_optional: BOOLEAN
l_ok: BOOLEAN
l_block_cache: detachable TUPLE [block: CMS_CACHE_BLOCK; region: READABLE_STRING_8; expired: BOOLEAN]
l_alias_table: detachable STRING_TABLE [LIST [READABLE_STRING_8]] --| block_id => [alias_ids..]
l_origin_block: detachable CMS_BLOCK
do
if attached subscribers ({CMS_HOOK_BLOCK}) as lst then
l_alias_table := a_response.block_alias_table
across
lst as c
loop
@@ -152,18 +154,13 @@ feature -- Hook: block
across
h.block_list as blst
loop
l_ok := False
bl := blst.item
bl_optional := bl.count > 0 and bl[1] = '?'
if bl_optional then
bl := bl.substring (2, bl.count)
if a_response.is_block_included (bl, False) then
l_ok := True
end
else
l_ok := True
end
if l_ok then
if a_response.is_block_included (bl, not bl_optional) then
l_block_cache := a_response.block_cache (bl)
if l_block_cache /= Void and then not l_block_cache.expired then
a_response.add_block (l_block_cache.block, l_block_cache.region)
@@ -171,12 +168,89 @@ feature -- Hook: block
h.get_block_view (bl, a_response)
end
end
if
l_alias_table /= Void and then
attached l_alias_table.item (bl) as l_aliases
then
across
l_aliases as aliases_ic
loop
l_alias := aliases_ic.item
l_origin_block := a_response.blocks.item (bl)
if l_origin_block = Void then
h.get_block_view (bl, a_response)
l_origin_block := a_response.blocks.item (bl)
if l_origin_block /= Void then
-- Previously, it was not included.
-- Computed only to include alias
-- then remove `l_origin_block'.
a_response.remove_block (l_origin_block)
end
end
if l_origin_block /= Void then
a_response.add_block (create {CMS_ALIAS_BLOCK}.make_with_block (l_alias, l_origin_block), Void)
end
end
end
end
end
end
end
end
feature -- Hook: cache
subscribe_to_cache_hook (h: CMS_HOOK_CACHE)
-- Add `h' as subscriber of cache hooks CMS_HOOK_CACHE,
-- and response `a_response'.
do
subscribe_to_hook (h, {CMS_HOOK_CACHE})
end
invoke_clear_cache (a_cache_id_list: detachable ITERABLE [READABLE_STRING_GENERAL]; a_response: CMS_RESPONSE)
-- Invoke cache hook for identifiers `a_cache_id_list'.
do
if attached subscribers ({CMS_HOOK_CACHE}) as lst then
across
lst as c
loop
if attached {CMS_HOOK_CACHE} c.item as h then
h.clear_cache (a_cache_id_list, a_response)
end
end
a_response.clear_cache (a_cache_id_list)
end
end
feature -- Hook: export
subscribe_to_export_hook (h: CMS_HOOK_EXPORT)
-- Add `h' as subscriber of export hooks CMS_HOOK_EXPORT.
do
subscribe_to_hook (h, {CMS_HOOK_EXPORT})
end
invoke_export_to (a_export_id_list: detachable ITERABLE [READABLE_STRING_GENERAL]; a_export_parameters: CMS_EXPORT_PARAMETERS; a_response: CMS_RESPONSE)
-- Invoke response alter hook for response `a_response'.
local
d: DIRECTORY
do
if attached subscribers ({CMS_HOOK_EXPORT}) as lst then
create d.make_with_path (a_export_parameters.location)
if not d.exists then
d.recursive_create_dir
end
across
lst as ic
loop
if attached {CMS_HOOK_EXPORT} ic.item as h then
h.export_to (a_export_id_list, a_export_parameters, a_response)
end
end
end
end
note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"

View File

@@ -0,0 +1,42 @@
note
description: "[
Usefull routines to export to JSON.
]"
date: "$Date$"
revision: "$Revision$"
class
CMS_EXPORT_JSON_UTILITIES
feature -- Access
put_string_into_json (st: detachable READABLE_STRING_GENERAL; a_key: JSON_STRING; j: JSON_OBJECT)
do
if st /= Void then
j.put_string (st, a_key)
end
end
put_date_into_json (dt: detachable DATE_TIME; a_key: JSON_STRING; j: JSON_OBJECT)
local
hd: HTTP_DATE
do
if dt /= Void then
create hd.make_from_date_time (dt)
j.put_integer (hd.timestamp, a_key)
end
end
json_to_string (j: JSON_VALUE): STRING
local
pp: JSON_PRETTY_STRING_VISITOR
do
create Result.make_empty
create pp.make (Result)
j.accept (pp)
end
note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end

View File

@@ -0,0 +1,43 @@
note
description: "[
Parameters used by CMS_HOOK_EXPORT subscribers.
]"
date: "$Date$"
revision: "$Revision$"
class
CMS_EXPORT_PARAMETERS
create
make
feature {NONE} -- Initialization
make (a_location: PATH)
do
location := a_location
create logs.make (10)
end
feature -- Access
location: PATH
-- Location of export folder.
feature -- Logs
logs: ARRAYED_LIST [READABLE_STRING_8]
-- Associated exportation logs.
log (m: READABLE_STRING_8)
-- Add message `m' into `logs'.
do
logs.force (m)
end
invariant
note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end

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