zena 0.15.2 → 0.16.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +20 -0
- data/CREDITS +27 -0
- data/Capfile +3 -0
- data/DEVELOPERS +46 -0
- data/History.txt +15 -0
- data/MIT-LICENSE +19 -0
- data/Rakefile +44 -0
- data/TODO +24 -0
- data/TODO_ZENA_1_0 +23 -0
- data/app/controllers/application_controller.rb +3 -0
- data/app/controllers/documents_controller.rb +22 -56
- data/app/controllers/nodes_controller.rb +42 -27
- data/app/controllers/pings_controller.rb +19 -0
- data/app/controllers/relations_controller.rb +5 -1
- data/app/controllers/sites_controller.rb +1 -46
- data/app/controllers/user_sessions_controller.rb +47 -0
- data/app/controllers/users_controller.rb +1 -0
- data/app/controllers/versions_controller.rb +25 -7
- data/app/controllers/virtual_classes_controller.rb +1 -1
- data/app/helpers/application_helper.rb +1 -1
- data/app/models/comment.rb +2 -1
- data/app/models/contact_content.rb +2 -2
- data/app/models/data_entry.rb +5 -6
- data/app/models/document.rb +14 -10
- data/app/models/document_content.rb +4 -6
- data/app/models/iformat.rb +2 -2
- data/app/models/image_content.rb +6 -9
- data/app/models/node.rb +106 -164
- data/app/models/page.rb +0 -20
- data/app/models/site.rb +42 -12
- data/app/models/template.rb +3 -8
- data/app/models/template_content.rb +2 -0
- data/app/models/text_document.rb +13 -8
- data/app/models/user.rb +47 -100
- data/app/models/user_session.rb +4 -0
- data/app/models/version.rb +1 -1
- data/app/views/comments/create.rjs +3 -3
- data/app/views/comments/edit.rjs +1 -1
- data/app/views/comments/update.rjs +1 -1
- data/app/views/nodes/_import_results.rhtml +1 -1
- data/app/views/nodes/create.rjs +3 -3
- data/app/views/templates/document_create_tabs/_file.rhtml +1 -2
- data/app/views/templates/document_create_tabs/_import.rhtml +7 -2
- data/app/views/templates/edit_tabs/_document.rhtml +1 -3
- data/app/views/templates/edit_tabs/_image.rhtml +1 -3
- data/app/views/versions/_tr.rhtml +1 -1
- data/app/views/versions/edit.rhtml +2 -26
- data/bin/zena +6 -1
- data/bricks/delayed_job/README +18 -0
- data/bricks/delayed_job/migrate/20091104191643_create_delayed_jobs_table.rb +19 -0
- data/bricks/delayed_job/misc/init.rb +8 -0
- data/bricks/delayed_job/misc/tasks.rb +2 -0
- data/bricks/math/patch/application_helper.rb +1 -1
- data/bricks/sphinx/MIT-LICENSE +19 -0
- data/bricks/sphinx/README +19 -0
- data/bricks/sphinx/lib/use_sphinx.rb +78 -0
- data/bricks/sphinx/migrate/20091102171258_add_delta_for_sphinx.rb +9 -0
- data/bricks/sphinx/misc/deploy.rb +20 -0
- data/bricks/sphinx/misc/sphinx.yml +12 -0
- data/bricks/sphinx/misc/tasks.rb +21 -0
- data/bricks/sphinx/patch/node.rb +8 -0
- data/bricks/tags/lib/has_tags.rb +5 -3
- data/bricks/tags/test/zafu/tags.yml +13 -1
- data/config/bricks.yml +35 -0
- data/config/deploy.rb +8 -1
- data/config/environment.rb +1 -1
- data/config/environments/production.rb +1 -1
- data/config/gems.yml +28 -5
- data/config/sphinx.yml +12 -0
- data/db/init/base/skins/default/Node-+popupLayout.zafu +1 -16
- data/db/migrate/20091026161708_add_persistence_token.rb +13 -0
- data/db/migrate/20091101184952_add_session_table.rb +16 -0
- data/db/migrate/20091123175137_add_single_access_token.rb +9 -0
- data/db/migrate/20091124161608_rebuild_fullpath.rb +11 -0
- data/db/schema.rb +21 -8
- data/doc/README_FOR_APP +24 -0
- data/doc/fixtures.graffle +19568 -0
- data/doc/fixtures.pdf +0 -0
- data/doc/template/LICENSE +184 -0
- data/doc/template/README +37 -0
- data/doc/template/allison.css +283 -0
- data/doc/template/allison.js +307 -0
- data/doc/template/allison.rb +260 -0
- data/doc/template/cache/BODY +588 -0
- data/doc/template/cache/CLASS_INDEX +4 -0
- data/doc/template/cache/CLASS_PAGE +1 -0
- data/doc/template/cache/FILE_INDEX +4 -0
- data/doc/template/cache/FILE_PAGE +1 -0
- data/doc/template/cache/FONTS +1 -0
- data/doc/template/cache/FR_INDEX_BODY +1 -0
- data/doc/template/cache/IMGPATH +1 -0
- data/doc/template/cache/INDEX +1 -0
- data/doc/template/cache/JAVASCRIPT +307 -0
- data/doc/template/cache/METHOD_INDEX +4 -0
- data/doc/template/cache/METHOD_LIST +1 -0
- data/doc/template/cache/SRC_PAGE +1 -0
- data/doc/template/cache/STYLE +283 -0
- data/doc/template/cache/URL +1 -0
- data/doc/zafu_changes.yml +29 -0
- data/lib/base_additions.rb +1 -1
- data/lib/bricks.rb +9 -0
- data/lib/bricks/loader.rb +86 -0
- data/lib/bricks/requirements_validation.rb +71 -0
- data/lib/tasks/zena.rake +42 -4
- data/lib/zafu/action.rb +285 -0
- data/lib/zafu/ajax.rb +93 -0
- data/lib/zafu/attributes.rb +117 -0
- data/lib/zafu/calendar.rb +159 -0
- data/lib/zafu/context.rb +330 -0
- data/lib/zafu/core/html.rb +102 -0
- data/lib/zafu/core/move_to_parser.rb +167 -0
- data/lib/zafu/dates.rb +58 -0
- data/lib/zafu/display.rb +502 -0
- data/lib/zafu/eval.rb +66 -0
- data/lib/zafu/experimental.rb +66 -0
- data/lib/zafu/i18n.rb +64 -0
- data/lib/zafu/meta.rb +25 -0
- data/lib/zafu/refactor.rb +73 -0
- data/lib/zafu/support/context.rb +265 -0
- data/lib/zafu/support/dom.rb +145 -0
- data/lib/zafu/support/erb.rb +62 -0
- data/lib/zafu/support/flow.rb +401 -0
- data/lib/zafu/support/forms.rb +461 -0
- data/lib/zafu/support/links.rb +306 -0
- data/lib/zafu_parser.rb +26 -2
- data/lib/zena.rb +34 -15
- data/lib/zena/acts/multiversion.rb +2 -2
- data/lib/zena/acts/secure.rb +41 -30
- data/lib/zena/app.rb +7 -10
- data/lib/zena/controller/test_case.rb +12 -7
- data/lib/zena/crypto_provider/initial.rb +15 -0
- data/lib/zena/db.rb +6 -1
- data/lib/zena/deploy.rb +34 -6
- data/lib/zena/deploy/logrotate_app.rhtml +9 -0
- data/lib/zena/deploy/logrotate_host.rhtml +34 -0
- data/lib/zena/deploy/template.rb +1 -9
- data/lib/zena/foxy_parser.rb +1 -1
- data/lib/zena/info.rb +3 -1
- data/lib/zena/migrator.rb +1 -1
- data/lib/zena/parser.rb +12 -4
- data/lib/zena/parser/zazen_rules.rb +6 -6
- data/lib/zena/parser/zena_rules.rb +1 -7
- data/lib/zena/routes.rb +5 -5
- data/lib/zena/test_controller.rb +7 -2
- data/lib/zena/unit/test_case.rb +6 -8
- data/lib/zena/use/ajax.rb +10 -10
- data/lib/zena/use/authlogic.rb +93 -0
- data/lib/zena/use/dyn_attributes.rb +5 -0
- data/lib/zena/use/html_tags.rb +16 -34
- data/lib/zena/use/i18n.rb +4 -1
- data/lib/zena/use/node_query_finders.rb +8 -4
- data/lib/zena/use/refactor.rb +8 -20
- data/lib/zena/use/relations.rb +1 -0
- data/lib/zena/use/rendering.rb +4 -2
- data/lib/zena/use/search.rb +52 -0
- data/lib/zena/use/test_helper.rb +27 -28
- data/lib/zena/use/upload.rb +188 -0
- data/lib/zena/use/urls.rb +16 -14
- data/lib/zena/use/zafu.rb +16 -63
- data/lib/zena/use/zazen.rb +8 -8
- data/lib/zena/view/test_case.rb +8 -4
- data/locale/en/LC_MESSAGES/zena.mo +0 -0
- data/locale/en/zena.po +3 -3
- data/public/.htaccess +40 -0
- data/public/javascripts/upload-progress.js +17 -8
- data/public/javascripts/zena.js +8 -2
- data/public/stylesheets/popup.css +1 -0
- data/script/about +3 -0
- data/script/apache_logging +25 -0
- data/script/breakpointer +3 -0
- data/script/console +3 -0
- data/script/dbconsole +3 -0
- data/script/destroy +3 -0
- data/script/generate +3 -0
- data/script/performance/benchmarker +3 -0
- data/script/performance/profiler +3 -0
- data/script/plugin +3 -0
- data/script/process/inspector +3 -0
- data/script/process/reaper +3 -0
- data/script/process/spawner +3 -0
- data/script/runner +3 -0
- data/script/server +3 -0
- data/script/set_revision +29 -0
- data/spec/controllers/versions_controller_spec.rb +11 -0
- data/test/fixtures/files/Node-test.zafu +1 -1
- data/test/functional/nodes_controller_test.rb +25 -0
- data/test/functional/pings_controller_test.rb +8 -0
- data/test/functional/user_sessions_controller_test.rb +59 -0
- data/test/functional/users_controller_test.rb +81 -19
- data/test/helpers/node_query/filters.yml +5 -0
- data/test/helpers/node_query_test.rb +3 -3
- data/test/integration/multiple_hosts_test.rb +1 -1
- data/test/integration/navigation_test.rb +1 -1
- data/test/sites/complex/users.yml +1 -1
- data/test/sites/ocean/users.yml +3 -3
- data/test/sites/zena/users.yml +5 -4
- data/test/test_zena.rb +38 -38
- data/test/unit/cached_page_test.rb +2 -2
- data/test/unit/comment_test.rb +0 -1
- data/test/unit/document_test.rb +23 -11
- data/test/unit/helpers/ping_helper_test.rb +4 -0
- data/test/unit/multiversion_test.rb +24 -16
- data/test/unit/node_test.rb +32 -93
- data/test/unit/note_test.rb +9 -0
- data/test/unit/page_test.rb +2 -2
- data/test/unit/secure_test.rb +2 -12
- data/test/unit/site_test.rb +43 -24
- data/test/unit/template_test.rb +45 -3
- data/test/unit/text_document_test.rb +4 -3
- data/test/unit/user_test.rb +13 -33
- data/test/unit/zena/db_test.rb +8 -0
- data/test/unit/zena/parser/zazen.yml +4 -4
- data/test/unit/zena/use/dates_view_methods_test.rb +2 -1
- data/test/unit/zena/use/html_tags_test.rb +12 -4
- data/test/unit/zena/use/refactor_test.rb +4 -3
- data/test/unit/zena/use/rendering_test.rb +1 -0
- data/test/unit/zena/use/upload_test.rb +76 -0
- data/test/unit/zena/use/urls_test.rb +4 -0
- data/test/unit/zena/use/zafu_test.rb +8 -0
- data/test/unit/zena/workflow/status_version_test.rb +6 -0
- data/test/unit/zena/zena_tags/ajax.yml +4 -4
- data/test/unit/zena/zena_tags/basic.yml +21 -10
- data/test/unit/zena/zena_tags/relations.yml +0 -6
- data/test/unit/zena/zena_tags/rubyless.yml +35 -0
- data/test/unit/zena/zena_tags/zazen.yml +4 -4
- data/test/unit/zena/zena_tags_test.rb +36 -4
- data/vendor/TextMate/Zena.tmbundle/Commands/Run all yaml tests.tmCommand +1 -1
- data/vendor/TextMate/Zena.tmbundle/Commands/Run focused yaml test.tmCommand +2 -3
- data/vendor/TextMate/Zena.tmbundle/Support/RubyMate/catch_exception.rb +39 -0
- data/vendor/TextMate/Zena.tmbundle/Support/RubyMate/run_script.rb +102 -58
- data/vendor/TextMate/Zena.tmbundle/Support/RubyMate/stdin_dialog.rb +14 -0
- data/vendor/TextMate/Zena.tmbundle/info.plist +2 -0
- data/zena.gemspec +2085 -0
- metadata +265 -90
- data/app/controllers/sessions_controller.rb +0 -41
- data/app/views/sites/zena_up.html.erb +0 -11
- data/config/database.yml +0 -40
- data/db/production.sqlite3 +0 -0
- data/lib/bricks/patcher.rb +0 -68
- data/lib/zena/parser/zena_tags.rb +0 -3562
- data/lib/zena/use/authentification.rb +0 -120
- data/public/images/ext/contact_pv.png +0 -0
- data/public/images/ext/other_pv.png +0 -0
- data/public/images/ext/page_pv.png +0 -0
- data/public/images/ext/page_tiny.png +0 -0
- data/public/images/ext/pdf_pv.png +0 -0
- data/public/images/ext/post_pv.png +0 -0
- data/public/images/ext/post_tiny.png +0 -0
- data/public/images/ext/project_pv.png +0 -0
- data/public/images/ext/project_tiny.png +0 -0
- data/public/images/ext/tag_pv.png +0 -0
- data/public/images/ext/zip_pv.png +0 -0
- data/tasks/ann.rake +0 -80
- data/tasks/bones.rake +0 -20
- data/tasks/gem.rake +0 -201
- data/tasks/git.rake +0 -40
- data/tasks/notes.rake +0 -27
- data/tasks/post_load.rake +0 -34
- data/tasks/rdoc.rake +0 -51
- data/tasks/rubyforge.rake +0 -55
- data/tasks/setup.rb +0 -292
- data/tasks/spec.rake +0 -54
- data/tasks/svn.rake +0 -47
- data/tasks/test.rake +0 -40
- data/tasks/zentest.rake +0 -36
- data/test/fixtures/comments.yml +0 -126
- data/test/fixtures/contact_contents.yml +0 -132
- data/test/fixtures/data_entries.yml +0 -65
- data/test/fixtures/discussions.yml +0 -48
- data/test/fixtures/document_contents.yml +0 -108
- data/test/fixtures/dyn_attributes.yml +0 -66
- data/test/fixtures/groups.yml +0 -86
- data/test/fixtures/groups_users.yml +0 -81
- data/test/fixtures/iformats.yml +0 -29
- data/test/fixtures/links.yml +0 -313
- data/test/fixtures/nodes.yml +0 -2592
- data/test/fixtures/relations.yml +0 -126
- data/test/fixtures/sites.yml +0 -58
- data/test/fixtures/template_contents.yml +0 -172
- data/test/fixtures/users.yml +0 -167
- data/test/fixtures/versions.yml +0 -1911
- data/test/fixtures/virtual_classes.yml +0 -87
- data/test/fixtures/zips.yml +0 -15
- data/test/functional/sessions_controller_test.rb +0 -73
@@ -1,41 +0,0 @@
|
|
1
|
-
=begin rdoc
|
2
|
-
Create, destroy sessions by letting users login and logout. When the user does not login, he/she is considered to be the anonymous user.
|
3
|
-
=end
|
4
|
-
class SessionsController < ApplicationController
|
5
|
-
skip_before_filter :authorize
|
6
|
-
|
7
|
-
def new
|
8
|
-
respond_to do |format|
|
9
|
-
format.html do
|
10
|
-
@node = visitor.site.root_node
|
11
|
-
render_and_cache :mode => '+login'
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def create
|
17
|
-
if user = User.login(params[:login], params[:password], request.host)
|
18
|
-
successful_login(user)
|
19
|
-
else
|
20
|
-
failed_login _("Invalid login or password.")
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
# Clears session information and redirects to home page.
|
25
|
-
def destroy
|
26
|
-
reset_session
|
27
|
-
if request.referer =~ %r{(http://#{visitor.site.host}:\d*/)#{AUTHENTICATED_PREFIX}(.*)}
|
28
|
-
redirect_to $1 + visitor.lang + $2
|
29
|
-
else
|
30
|
-
redirect_to :controller => 'nodes', :action => 'index', :prefix => visitor.lang
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
protected
|
35
|
-
|
36
|
-
def failed_login(message)
|
37
|
-
session[:user] = nil
|
38
|
-
flash[:error] = message
|
39
|
-
redirect_to '/login'
|
40
|
-
end
|
41
|
-
end
|
@@ -1,11 +0,0 @@
|
|
1
|
-
<% if @state == :wait -%>
|
2
|
-
<h2><%= _('Updating...') %></h2>
|
3
|
-
<p><%= _('Please wait while the code is updated and the site restarts (page reloads every 30s).') %></p>
|
4
|
-
<% elsif @state == :done -%>
|
5
|
-
<h2><%= _('Up to date') %></h2>
|
6
|
-
<p><%= _('Your site is running the latest version of zena.') %> (<%= Zena::VERSION %> r<%= @target_rev %>)</p>
|
7
|
-
<% else -%>
|
8
|
-
<h2><%= _('Update') %></h2>
|
9
|
-
<p><%= sprintf(_('Your site is running rev %i, newest revision is %i.'), @current_rev, @target_rev) %></p>
|
10
|
-
<p><%= link_to(_('Update'), :action => 'zena_up', :run => 'start', :rev => @target_rev) %></p>
|
11
|
-
<% end -%>
|
data/config/database.yml
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
# Enter database configuration information here (rename this file "database.yml").
|
2
|
-
# You do not need to do any of this if you use capistraon (see config/deploy.rg).
|
3
|
-
# MySQL
|
4
|
-
login: &dev_login
|
5
|
-
adapter: mysql
|
6
|
-
socket: /tmp/mysql.sock
|
7
|
-
username: root
|
8
|
-
password:
|
9
|
-
|
10
|
-
development:
|
11
|
-
database: zena_dev
|
12
|
-
encoding: utf8
|
13
|
-
<<: *dev_login
|
14
|
-
|
15
|
-
# Warning: The database defined as "test" will be erased and
|
16
|
-
# re-generated from your development database when you run "rake".
|
17
|
-
# Do not set this db to the same as development or production.
|
18
|
-
test:
|
19
|
-
database: zena_test
|
20
|
-
encoding: utf8
|
21
|
-
<<: *dev_login
|
22
|
-
|
23
|
-
# FIXME: use in memory sqlite3 for testing
|
24
|
-
#test:
|
25
|
-
# adapter: sqlite3
|
26
|
-
# database: db/test.sqlite3
|
27
|
-
# pool: 5
|
28
|
-
# timeout: 5000
|
29
|
-
#
|
30
|
-
production:
|
31
|
-
database: zena_dev
|
32
|
-
encoding: utf8
|
33
|
-
<<: *dev_login
|
34
|
-
|
35
|
-
#production:
|
36
|
-
# adapter: sqlite3
|
37
|
-
# database: db/production.sqlite3
|
38
|
-
# pool: 5
|
39
|
-
# timeout: 5000
|
40
|
-
#
|
data/db/production.sqlite3
DELETED
Binary file
|
data/lib/bricks/patcher.rb
DELETED
@@ -1,68 +0,0 @@
|
|
1
|
-
module Bricks
|
2
|
-
class Patcher
|
3
|
-
class << self
|
4
|
-
def bricks_folders
|
5
|
-
@bricks_folders ||= [File.join(Zena::ROOT, 'bricks'), File.join(RAILS_ROOT, 'bricks')].uniq.reject {|f| !File.exist?(f)}
|
6
|
-
end
|
7
|
-
|
8
|
-
def models_paths
|
9
|
-
bricks_folders.map {|f| Dir["#{f}/**/models"] }.flatten
|
10
|
-
end
|
11
|
-
|
12
|
-
def libs_paths
|
13
|
-
bricks_folders.map {|f| Dir["#{f}/**/lib"] }.flatten
|
14
|
-
end
|
15
|
-
|
16
|
-
def foreach_brick(&block)
|
17
|
-
bricks_folders.each do |bricks_folder|
|
18
|
-
next unless File.exist?(bricks_folder)
|
19
|
-
Dir.entries(bricks_folder).sort.each do |brick|
|
20
|
-
next if brick =~ /\A\./
|
21
|
-
block.call(File.join(bricks_folder, brick))
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def apply_patches(file_name = nil)
|
27
|
-
file_name ||= caller[0].split('/').last.split(':').first
|
28
|
-
foreach_brick do |brick_path|
|
29
|
-
patch_file = File.join(brick_path, 'patch', file_name)
|
30
|
-
if File.exist?(patch_file)
|
31
|
-
load patch_file
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def load_bricks
|
37
|
-
# load all libraries in bricks
|
38
|
-
libs_paths.each do |lib_path|
|
39
|
-
Dir.foreach(lib_path) do |f|
|
40
|
-
next unless f =~ /\A.+\.rb\Z/
|
41
|
-
require File.join(lib_path, f)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
# FIXME: do we really need to load these now, load_path isn't enough ?
|
46
|
-
models_paths.each do |models_path|
|
47
|
-
Dir.foreach(models_path) do |f|
|
48
|
-
next unless f =~ /\A.+\.rb\Z/
|
49
|
-
require File.join(models_path, f)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def load_zafu(mod)
|
55
|
-
foreach_brick do |brick_path|
|
56
|
-
brick_name = File.basename(brick_path)
|
57
|
-
zafu_path = File.join(brick_path, 'zafu')
|
58
|
-
next unless File.exist?(zafu_path)
|
59
|
-
Dir.foreach(zafu_path) do |rules_name|
|
60
|
-
next if rules_name =~ /\A\./
|
61
|
-
load File.join(zafu_path, rules_name)
|
62
|
-
end
|
63
|
-
mod.send(:include, eval("Bricks::#{brick_name.capitalize}::Zafu"))
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
@@ -1,3562 +0,0 @@
|
|
1
|
-
=begin
|
2
|
-
Thoughts for ajax related stuff cleanup (dom_id, erb_dom_id, ...)
|
3
|
-
|
4
|
-
When we open a list context:
|
5
|
-
- we change the context_dom_id => unique name => "page"
|
6
|
-
|
7
|
-
When we open a single context (do_var, each, block):
|
8
|
-
- we change the context_dom_id => unique name with id => "page_{parent_id}"
|
9
|
-
|
10
|
-
Any 'id' is set with:
|
11
|
-
- "{context_dom_id}_{id}" => 'page_34' (if not in list) or 'page_12_34' if in list.
|
12
|
-
|
13
|
-
|
14
|
-
List in list (initial node zip = 12):
|
15
|
-
context_dom_id dom_id (context_erb_dom_id, erb_dom_id)
|
16
|
-
<ul> page_12 page_12 [pages in='site'] new unique name
|
17
|
-
<li id='page_12_13'> page_12 page_12_13 [each] expand_with(:context_dom_id => 'page_13')
|
18
|
-
<ul> page_13
|
19
|
-
<li id='page_13_23'/> page_13 page_13_23 [each]
|
20
|
-
<li id='page_13_24'/> page_13 page_13_24 [each]
|
21
|
-
<li id='page_13_25'/> page_13 page_13_25 [each]
|
22
|
-
</ul>
|
23
|
-
</li>
|
24
|
-
<li id='page_12_14'> page_12 page_12_14 [each] expand_with(:context_dom_id => 'page_14')
|
25
|
-
<ul>
|
26
|
-
<li id='page_14_23'/> page_14 page_14_23 [each] expand_with(:context_dom_id => 'page_23')
|
27
|
-
<li id='page_14_27'/> page_14 page_14_27 [each] ...
|
28
|
-
</ul>
|
29
|
-
</li>
|
30
|
-
</ul>
|
31
|
-
|
32
|
-
<div id='page1_12'> page1_12 page1_12 [block] new unique name
|
33
|
-
<ul>
|
34
|
-
<li id='page1_12_24'/> page1_12 page1_12_24 [each]
|
35
|
-
<li id='page1_12_32'/> page1_12 page1_12_32 [each]
|
36
|
-
</ul>
|
37
|
-
</div>
|
38
|
-
=end
|
39
|
-
|
40
|
-
require 'yaml'
|
41
|
-
|
42
|
-
module Zena
|
43
|
-
module Parser
|
44
|
-
include RubyLess::SafeClass
|
45
|
-
# Zafu tags used to display / edit nodes and versions
|
46
|
-
module ZenaTags
|
47
|
-
PSEUDO_ATTRIBUTES = {
|
48
|
-
'now' => 'Time.now',
|
49
|
-
'start.id' => '(params[:s] || @node[:zip])',
|
50
|
-
'nil' => 'nil',
|
51
|
-
}
|
52
|
-
|
53
|
-
class << self
|
54
|
-
def inline_methods(*args)
|
55
|
-
args.each do |name|
|
56
|
-
class_eval <<-END
|
57
|
-
def r_#{name}
|
58
|
-
"<%= #{name}(:node=>\#{node}\#{params_to_erb(@params)}) %>"
|
59
|
-
end
|
60
|
-
END
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def direct_methods(*args)
|
65
|
-
args.each do |name|
|
66
|
-
class_eval <<-END
|
67
|
-
def r_#{name}
|
68
|
-
helper.#{name}
|
69
|
-
end
|
70
|
-
END
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
inline_methods :login_link, :visitor_link, :search_box, :show_menu, :show_path, :lang_links
|
75
|
-
direct_methods :uses_datebox
|
76
|
-
|
77
|
-
def before_render
|
78
|
-
return unless super
|
79
|
-
|
80
|
-
@var = nil # reset var counter
|
81
|
-
|
82
|
-
if key = @params[:store]
|
83
|
-
set_stored(Node, key, node)
|
84
|
-
end
|
85
|
-
|
86
|
-
if key = @params[:store_date]
|
87
|
-
set_stored(Date, key, current_date)
|
88
|
-
end
|
89
|
-
@anchor_param = @params[:anchor]
|
90
|
-
|
91
|
-
true
|
92
|
-
end
|
93
|
-
|
94
|
-
def do_method(sym)
|
95
|
-
method = sym
|
96
|
-
pre, post = '', ''
|
97
|
-
|
98
|
-
# do we need recursion ?
|
99
|
-
inc = descendant('include')
|
100
|
-
if inc && inc.params[:part] == @name
|
101
|
-
@context["#{@name}_method".to_sym] = method_name = template_url[1..-1].gsub(/[\/-]/,'_')
|
102
|
-
pre << "<% def #{method_name}(depth, node, list); return '' if depth > #{inc.params[:depth] ? [inc.params[:depth].to_i,30].min : 5}; _erbout = '' -%>"
|
103
|
-
post << "<% _erbout; end -%><%= #{method_name}(0,#{node},#{list || "[#{node}]"}) %>"
|
104
|
-
@context[:node] = 'node'
|
105
|
-
@context[:list] = 'list'
|
106
|
-
end
|
107
|
-
|
108
|
-
if @context[:make_form]
|
109
|
-
res = case method
|
110
|
-
when :r_title
|
111
|
-
make_input(:name => 'v_title')
|
112
|
-
when :r_link
|
113
|
-
make_input(:name => (@params[:attr] || 'v_title'))
|
114
|
-
when :r_show
|
115
|
-
make_input(:name => (@params[:attr] || @params[:tattr]), :date => @params[:date])
|
116
|
-
when :r_text
|
117
|
-
make_textarea(:name => 'v_text')
|
118
|
-
when :r_summary
|
119
|
-
make_textarea(:name => 'v_summary')
|
120
|
-
when :r_zazen
|
121
|
-
make_textarea(:name => @params[:attr])
|
122
|
-
else
|
123
|
-
if node_kind_of?(DataEntry) && @method.to_s =~ /node_/
|
124
|
-
# select node_id
|
125
|
-
"<%= select_id('#{base_class.to_s.underscore}', '#{@method}_id') %>"
|
126
|
-
end
|
127
|
-
end
|
128
|
-
res = "<#{@html_tag || 'div'} class='zazen'>#{res}</#{@html_tag || 'div'}>" if [:r_summary, :r_text].include?(sym)
|
129
|
-
end
|
130
|
-
|
131
|
-
|
132
|
-
res ||= super(method)
|
133
|
-
"#{pre}#{res}#{post}"
|
134
|
-
end
|
135
|
-
|
136
|
-
|
137
|
-
def after_render(text)
|
138
|
-
if @anchor_param
|
139
|
-
@params[:anchor] = @anchor_param # set back in case of double rendering so it is computed again
|
140
|
-
res = r_anchor + super
|
141
|
-
else
|
142
|
-
res = super
|
143
|
-
end
|
144
|
-
res
|
145
|
-
end
|
146
|
-
|
147
|
-
# Our special version of r_expand_with tag with "set_" parsing.
|
148
|
-
def r_expand_with
|
149
|
-
hash = {}
|
150
|
-
@params.each do |k,v|
|
151
|
-
if k.to_s =~ /^set_(.+)$/
|
152
|
-
# TODO: DRY with render_html_tag
|
153
|
-
k = $1
|
154
|
-
value, static = parse_attributes_in_value(v, :erb => false)
|
155
|
-
hash["exp_#{k}"] = static ? value.inspect : "\"#{value}\""
|
156
|
-
else
|
157
|
-
hash["exp_#{k}"] = v.inspect
|
158
|
-
end
|
159
|
-
end
|
160
|
-
@params = {}
|
161
|
-
expand_with(hash)
|
162
|
-
end
|
163
|
-
|
164
|
-
def r_show
|
165
|
-
if attr_or_date = @params[:attr_or_date]
|
166
|
-
# using [var] shortcut. Can be either a date or an attribute/var
|
167
|
-
if attr_or_date == 'current_date' || attr_or_date =~ /_at$/
|
168
|
-
@params[:date] = attr_or_date
|
169
|
-
else
|
170
|
-
@params[:attr] = attr_or_date
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
|
-
if var_name = @params[:var]
|
175
|
-
return parser_error("var #{@params[:var].inspect} not set") unless @context[:vars] && @context[:vars].include?(var_name)
|
176
|
-
attribute_method = "set_#{var_name}"
|
177
|
-
elsif @params[:eval]
|
178
|
-
return unless attribute_method = parse_eval_parameter(@params[:eval])
|
179
|
-
elsif @params[:tattr]
|
180
|
-
attribute_method = "_(#{node_attribute(@params[:tattr], :else=>@params[:else], :default=>@params[:default])})"
|
181
|
-
elsif @params[:attr]
|
182
|
-
attribute_method = node_attribute(@params[:attr], :else=>@params[:else], :default=>@params[:default])
|
183
|
-
elsif p = @params[:param]
|
184
|
-
return "<%= params[#{p.to_sym.inspect}] %>"
|
185
|
-
elsif @params[:date]
|
186
|
-
# date can be any attribute v_created_at or updated_at etc.
|
187
|
-
# TODO format with @params[:format] and @params[:tformat] << translated format
|
188
|
-
# TODO: test
|
189
|
-
if @params[:tformat]
|
190
|
-
format = _(@params[:tformat])
|
191
|
-
elsif @params[:format]
|
192
|
-
format = @params[:format]
|
193
|
-
else
|
194
|
-
format = "%Y-%m-%d"
|
195
|
-
end
|
196
|
-
|
197
|
-
tz = ''
|
198
|
-
lang = ''
|
199
|
-
if tz_name = @params[:time_zone]
|
200
|
-
tz_list = @params.reject {|k,v| !(k.to_s =~ /^time_zone\d*$/)}.to_a.sort {|a,b| a[0].to_s <=> b[0].to_s }.map do |k,tz_name|
|
201
|
-
if tz_name =~ /^\[(\w+)\]$/
|
202
|
-
node_attribute($1)
|
203
|
-
else
|
204
|
-
begin
|
205
|
-
TZInfo::Timezone.get(tz_name)
|
206
|
-
rescue TZInfo::InvalidTimezoneIdentifier
|
207
|
-
return parser_error("invalid timezone #{tz_name.inspect}")
|
208
|
-
end
|
209
|
-
tz_name.inspect
|
210
|
-
end
|
211
|
-
end
|
212
|
-
tz = ", #{tz_list.join(' || ')}"
|
213
|
-
end
|
214
|
-
if lang = @params[:lang]
|
215
|
-
tz = ', nil' if tz == ''
|
216
|
-
lang = ", #{lang.inspect}"
|
217
|
-
end
|
218
|
-
attribute_method = "format_date(#{node_attribute(@params[:date])}, #{format.inspect}#{tz}#{lang})"
|
219
|
-
elsif @context[:trans]
|
220
|
-
# error
|
221
|
-
return "no attribute for 'show'".inspect
|
222
|
-
else
|
223
|
-
return parser_error("missing attribute")
|
224
|
-
end
|
225
|
-
|
226
|
-
if !@params[:date] && fmt = @params[:format]
|
227
|
-
begin
|
228
|
-
# test argument
|
229
|
-
sprintf(fmt, 123.45)
|
230
|
-
rescue ArgumentError
|
231
|
-
return parser_error("incorect format #{fmt.inspect}")
|
232
|
-
end
|
233
|
-
if fmt =~ /%[\d\.]*f/
|
234
|
-
modifier = ".to_f"
|
235
|
-
elsif fmt =~ /%[\d\.]*i/
|
236
|
-
modifier = ".to_i"
|
237
|
-
else
|
238
|
-
modifier = ''
|
239
|
-
end
|
240
|
-
|
241
|
-
if @params[:zero] == 'hide'
|
242
|
-
attribute_method = "sprintf_unless_zero(#{fmt.inspect}, #{attribute_method}#{modifier})"
|
243
|
-
else
|
244
|
-
attribute_method = "sprintf(#{fmt.inspect}, #{attribute_method}#{modifier})"
|
245
|
-
end
|
246
|
-
end
|
247
|
-
|
248
|
-
|
249
|
-
if @context[:trans]
|
250
|
-
# TODO: what do we do here with gsubs, url ?
|
251
|
-
return attribute_method
|
252
|
-
end
|
253
|
-
|
254
|
-
if gsub = @params[:gsub]
|
255
|
-
if gsub =~ /\A\/(.+)\/(.+)\/\Z/
|
256
|
-
value = $2
|
257
|
-
key = $1.gsub(/\#([\{\$\@])/,'# \1') # FIXME: SECURITY.
|
258
|
-
# Please note that .gsub(/#([\{\$\@])/,'\#\1') won't work, since '\#{blah}' will become '\\#{blah}' and 'blah' will be evaluated.
|
259
|
-
regexp_ok = begin
|
260
|
-
output = StringIO.open('','w')
|
261
|
-
$stderr = output
|
262
|
-
re = /#{key}/
|
263
|
-
output.string !~ /warning:/
|
264
|
-
rescue
|
265
|
-
false
|
266
|
-
ensure
|
267
|
-
$stderr = STDERR
|
268
|
-
false
|
269
|
-
end
|
270
|
-
|
271
|
-
if regexp_ok
|
272
|
-
attribute_method = "#{attribute_method}.to_s.gsub(/#{key}/,#{value.inspect})"
|
273
|
-
else
|
274
|
-
# invalid regexp
|
275
|
-
return parser_error("invalid gsub #{gsub.inspect}")
|
276
|
-
end
|
277
|
-
else
|
278
|
-
# error
|
279
|
-
return parser_error("invalid gsub #{gsub.inspect}")
|
280
|
-
end
|
281
|
-
end
|
282
|
-
|
283
|
-
if @params[:actions]
|
284
|
-
actions = "<%= node_actions(:node=>#{node}#{params_to_erb(:actions=>@params[:actions], :publish_after_save=>auto_publish_param)}) %>"
|
285
|
-
else
|
286
|
-
actions = ''
|
287
|
-
end
|
288
|
-
|
289
|
-
attribute = @params[:attr] || @params[:tattr] || @params[:date]
|
290
|
-
|
291
|
-
if (@params[:edit_preview] || @params[:ep]) == 'true'
|
292
|
-
@html_tag_params[:id] = "#{attribute}#{erb_node_id}"
|
293
|
-
@html_tag ||= 'span'
|
294
|
-
end
|
295
|
-
|
296
|
-
if @params[:edit] == 'true' && !['url','path'].include?(attribute)
|
297
|
-
"<% if #{node}.can_write? -%><span class='show_edit' id='#{erb_dom_id("_#{attribute}")}'>#{actions}<%= link_to_remote(#{attribute_method}, :url => edit_node_path(#{node_id}) + \"?attribute=#{attribute}&dom_id=#{dom_id("_#{attribute}")}#{auto_publish_param(true)}\", :method => :get) %></span><% else -%>#{actions}<%= #{attribute_method} %><% end -%>"
|
298
|
-
else
|
299
|
-
"#{actions}<%= #{attribute_method} %>"
|
300
|
-
end
|
301
|
-
end
|
302
|
-
|
303
|
-
def r_zazen
|
304
|
-
attribute = @params[:attr] || @params[:tattr]
|
305
|
-
limit = @params[:limit] ? ", :limit=>#{@params[:limit].to_i}" : ""
|
306
|
-
if @context[:trans]
|
307
|
-
# TODO: what do we do here with dates ?
|
308
|
-
return "#{node_attribute(attribute)}"
|
309
|
-
elsif @params[:tattr]
|
310
|
-
return "<%= zazen(_(#{node_attribute(attribute)})#{limit}, :node=>#{node(Node)}) %>"
|
311
|
-
elsif @params[:attr]
|
312
|
-
if output_format == 'html'
|
313
|
-
res = "<%= zazen(#{node_attribute(attribute)}#{limit}, :node=>#{node(Node)}) %>"
|
314
|
-
else
|
315
|
-
return "<%= zazen(#{node_attribute(attribute)}#{limit}, :node=>#{node(Node)}, :output=>#{output_format.inspect}) %>"
|
316
|
-
end
|
317
|
-
elsif @params[:date]
|
318
|
-
# date can be any attribute v_created_at or updated_at etc.
|
319
|
-
# TODO format with @params[:format] and @params[:tformat] << translated format
|
320
|
-
else
|
321
|
-
# error
|
322
|
-
end
|
323
|
-
|
324
|
-
@html_tag ||= 'div'
|
325
|
-
|
326
|
-
add_html_class('zazen')
|
327
|
-
|
328
|
-
if (@params[:edit_preview] || @params[:ep]) == 'true'
|
329
|
-
@html_tag_params[:id] = "#{attribute}#{erb_node_id}"
|
330
|
-
end
|
331
|
-
|
332
|
-
if @params[:edit] == 'true' && !['url','path'].include?(attribute)
|
333
|
-
edit_text = _('edit')
|
334
|
-
@html_tag_params[:id] = erb_dom_id("_#{attribute}")
|
335
|
-
res = "<% if #{node}.can_write? -%><span class='zazen_edit'><%= link_to_remote(#{edit_text.inspect}, :url => edit_node_path(#{node_id}) + \"?attribute=#{attribute}&dom_id=#{dom_id("_#{attribute}")}#{auto_publish_param(true)}&zazen=true\", :method => :get) %></span><% end -%>#{res}"
|
336
|
-
else
|
337
|
-
res
|
338
|
-
end
|
339
|
-
end
|
340
|
-
|
341
|
-
# TODO: test, rename ?
|
342
|
-
def r_search_results
|
343
|
-
do_list("@nodes")
|
344
|
-
end
|
345
|
-
|
346
|
-
|
347
|
-
def r_set
|
348
|
-
return parser_error("'var' missing") unless var_name = @params[:var]
|
349
|
-
return parser_error("bad value for 'var' (#{var_name.inspect})") unless var_name =~ /^[a-zA-Z_]+$/
|
350
|
-
return '' unless @context[:set]
|
351
|
-
if @params[:value]
|
352
|
-
out "<% set_#{var_name} = #{@params[:value].inspect} -%>"
|
353
|
-
# TODO: isn't @context[:vars] = @params[:value].inspect missing here ?
|
354
|
-
elsif @params[:eval]
|
355
|
-
return unless eval_string = parse_eval_parameter(@params[:eval])
|
356
|
-
out "<% set_#{var_name} = #{eval_string} -%>"
|
357
|
-
else
|
358
|
-
out "<% set_#{var_name} = capture do %>"
|
359
|
-
out expand_with(:set => false) # do not propagate
|
360
|
-
out "<% end -%>"
|
361
|
-
end
|
362
|
-
end
|
363
|
-
|
364
|
-
|
365
|
-
# TODO: write a test (please)
|
366
|
-
# FIXME: we should use a single way to change a whole context into a template (applies to 'each', 'form', 'block'). Then 'swap' could use the 'each' block.
|
367
|
-
# Define a block of elements to be used by ajax calls (edit/filter)
|
368
|
-
def r_block
|
369
|
-
if @context[:block] == self
|
370
|
-
# called from self (storing template)
|
371
|
-
@context.reject! do |k,v|
|
372
|
-
# FIXME: reject all stored elements in a better way then this
|
373
|
-
k.kind_of?(String) && k =~ /\ANode_\w/
|
374
|
-
end
|
375
|
-
@html_tag_done = false
|
376
|
-
@html_tag_params.merge!(:id=>erb_dom_id)
|
377
|
-
@context[:scope_node] = node if @context[:scope_node]
|
378
|
-
out expand_with(:node => node)
|
379
|
-
if @method == 'drop' && !@context[:make_form]
|
380
|
-
out drop_javascript
|
381
|
-
end
|
382
|
-
else
|
383
|
-
if parent.method == 'each' && @method == parent.single_child_method
|
384
|
-
# use parent as block
|
385
|
-
# FIXME: will not work with block as distant target...
|
386
|
-
# do nothing
|
387
|
-
else
|
388
|
-
@html_tag ||= 'div'
|
389
|
-
new_dom_scope
|
390
|
-
|
391
|
-
unless @context[:make_form]
|
392
|
-
# STORE TEMPLATE ========
|
393
|
-
|
394
|
-
context_bak = @context.dup # avoid side effects when rendering the same block
|
395
|
-
ignore_list = @method == 'block' ? ['form'] : [] # do not show the form in the normal template of a block
|
396
|
-
template = expand_block(self, :block=>self, :list=>false, :saved_template=>true, :ignore => ignore_list)
|
397
|
-
@context = context_bak
|
398
|
-
@result = ''
|
399
|
-
out helper.save_erb_to_url(template, template_url)
|
400
|
-
|
401
|
-
# STORE FORM ============
|
402
|
-
if edit = descendant('edit')
|
403
|
-
publish_after_save = (edit.params[:publish] == 'true')
|
404
|
-
if form = descendant('form')
|
405
|
-
# USE BLOCK FORM ========
|
406
|
-
form_text = expand_block(form, :saved_template=>true, :publish_after_save => publish_after_save)
|
407
|
-
else
|
408
|
-
# MAKE A FORM FROM BLOCK ========
|
409
|
-
form = self.dup
|
410
|
-
form.method = 'form'
|
411
|
-
form_text = expand_block(form, :make_form => true, :list => false, :saved_template => true, :publish_after_save => publish_after_save)
|
412
|
-
end
|
413
|
-
out helper.save_erb_to_url(form_text, form_url)
|
414
|
-
end
|
415
|
-
end
|
416
|
-
|
417
|
-
# RENDER
|
418
|
-
@html_tag_done = false
|
419
|
-
@html_tag_params.merge!(:id=>erb_dom_id)
|
420
|
-
end
|
421
|
-
|
422
|
-
out expand_with
|
423
|
-
if @method == 'drop' && !@context[:make_form]
|
424
|
-
out drop_javascript
|
425
|
-
end
|
426
|
-
end
|
427
|
-
end
|
428
|
-
|
429
|
-
# TODO: test
|
430
|
-
def r_filter
|
431
|
-
if upd = @params[:update]
|
432
|
-
return unless block = find_target(upd)
|
433
|
-
else
|
434
|
-
return parser_error("missing 'block' in same parent") unless parent && block = parent.descendant('block')
|
435
|
-
end
|
436
|
-
return parser_error("cannot use 's' as key (used by start_node)") if @params[:key] == 's'
|
437
|
-
out "<%= form_remote_tag(:url => zafu_node_path(#{node_id}), :method => :get, :html => {:id => \"#{dom_id}_f\"}) %><div class='hidden'><input type='hidden' name='t_url' value='#{block.template_url}'/><input type='hidden' name='dom_id' value='#{block.erb_dom_id}'/>#{start_node_s_param(:input)}</div><div class='wrapper'>"
|
438
|
-
if @blocks == []
|
439
|
-
out "<input type='text' name='#{@params[:key] || 'f'}' value='<%= params[#{(@params[:key] || 'f').to_sym.inspect}] %>'/>"
|
440
|
-
else
|
441
|
-
out expand_with(:in_filter => true)
|
442
|
-
end
|
443
|
-
out "</div></form>"
|
444
|
-
if @params[:live] || @params[:update]
|
445
|
-
out "<%= observe_form( \"#{dom_id}_f\" , :method => :get, :frequency => 1, :submit =>\"#{dom_id}_f\", :url => zafu_node_path(#{node_id})) %>"
|
446
|
-
end
|
447
|
-
end
|
448
|
-
|
449
|
-
# swap an attribute
|
450
|
-
# TODO: test
|
451
|
-
def r_swap
|
452
|
-
if upd = @params[:update]
|
453
|
-
if upd == '_page'
|
454
|
-
block = nil
|
455
|
-
elsif block = find_target(upd)
|
456
|
-
# ok
|
457
|
-
if ancestor('block') || ancestor('each')
|
458
|
-
upd_both = '&upd_both=true'
|
459
|
-
else
|
460
|
-
upd_both = ''
|
461
|
-
end
|
462
|
-
else
|
463
|
-
return
|
464
|
-
end
|
465
|
-
elsif ancestor('block') || ancestor('each')
|
466
|
-
# ancestor: ok
|
467
|
-
block = self
|
468
|
-
elsif parent && block = parent.descendant('block')
|
469
|
-
# sibling: ok
|
470
|
-
upd_both = ''
|
471
|
-
else
|
472
|
-
return parser_error("missing 'block' in same parent")
|
473
|
-
end
|
474
|
-
|
475
|
-
states = ((@params[:states] || 'todo, done') + ' ').split(',').map(&:strip)
|
476
|
-
|
477
|
-
query_params = "node[#{@params[:attr]}]=\#{#{states.inspect}[ ((#{states.inspect}.index(#{node_attribute(@params[:attr])}.to_s) || 0)+1) % #{states.size}]}#{upd_both}"
|
478
|
-
out link_to_update(block, :query_params => query_params, :method => :put, :html_params => get_html_params(@params, :link))
|
479
|
-
end
|
480
|
-
|
481
|
-
def r_load
|
482
|
-
if dict = @params[:dictionary]
|
483
|
-
dict_content, absolute_url, doc = self.class.get_template_text(dict, @options[:helper], @options[:current_folder])
|
484
|
-
return parser_error("dictionary #{dict.inspect} not found") unless doc
|
485
|
-
@context[:dict] ||= {}
|
486
|
-
begin
|
487
|
-
definitions = YAML::load(dict_content)
|
488
|
-
definitions['translations'].each do |elem|
|
489
|
-
@context[:dict][elem[0]] = elem[1]
|
490
|
-
end
|
491
|
-
rescue
|
492
|
-
return parser_error("invalid dictionary content #{dict.inspect}")
|
493
|
-
end
|
494
|
-
else
|
495
|
-
return parser_error("missing 'dictionary'")
|
496
|
-
end
|
497
|
-
expand_with
|
498
|
-
end
|
499
|
-
|
500
|
-
def r_trans
|
501
|
-
static = true
|
502
|
-
if @params[:text]
|
503
|
-
text = @params[:text]
|
504
|
-
elsif @params[:attr]
|
505
|
-
text = "#{node_attribute(@params[:attr])}"
|
506
|
-
static = false
|
507
|
-
else
|
508
|
-
res = []
|
509
|
-
text = ""
|
510
|
-
@blocks.each do |b|
|
511
|
-
if b.kind_of?(String)
|
512
|
-
res << b.inspect
|
513
|
-
text << b
|
514
|
-
elsif ['show', 'current_date'].include?(b.method)
|
515
|
-
res << expand_block(b, :trans=>true)
|
516
|
-
static = false
|
517
|
-
else
|
518
|
-
# ignore
|
519
|
-
end
|
520
|
-
end
|
521
|
-
unless static
|
522
|
-
text = res.join(' + ')
|
523
|
-
end
|
524
|
-
end
|
525
|
-
if static
|
526
|
-
_(text)
|
527
|
-
else
|
528
|
-
"<%= _(#{text}) %>"
|
529
|
-
end
|
530
|
-
end
|
531
|
-
|
532
|
-
alias r_t r_trans
|
533
|
-
|
534
|
-
def r_anchor(obj=node)
|
535
|
-
"<a name='#{anchor_name(@anchor_param, obj)}'></a>"
|
536
|
-
end
|
537
|
-
|
538
|
-
def anchor_name(p, obj=node)
|
539
|
-
if p =~ /\[(.+)\]/
|
540
|
-
"<%= #{node_attribute($1)} %>"
|
541
|
-
else
|
542
|
-
"#{base_class.to_s.underscore}#{erb_node_id(obj)}"
|
543
|
-
end
|
544
|
-
end
|
545
|
-
|
546
|
-
def r_content_for_layout
|
547
|
-
"<% if content_for_layout = yield -%><%= content_for_layout %><% else -%>" +
|
548
|
-
expand_with +
|
549
|
-
"<% end -%>"
|
550
|
-
end
|
551
|
-
|
552
|
-
def r_title_for_layout
|
553
|
-
"<% if @title_for_layout -%><%= @title_for_layout %><% elsif @node && !@node.new_record? -%><%= @node.rootpath %><% elsif @node.parent -%><%= @node.parent.rootpath %><% else -%>" +
|
554
|
-
expand_with +
|
555
|
-
"<% end -%>"
|
556
|
-
end
|
557
|
-
|
558
|
-
def r_check_lang
|
559
|
-
text = @params[:text] || expand_with
|
560
|
-
klass = @params[:class] || @html_tag_params[:class]
|
561
|
-
text = nil if text.blank?
|
562
|
-
klas = nil if klass.blank?
|
563
|
-
@html_tag_done = true
|
564
|
-
"#{@space_before}<%= check_lang(#{node},:text=>#{text.inspect},:class=>#{klass.inspect},:wrap=>#{@html_tag.inspect}) %>"
|
565
|
-
end
|
566
|
-
|
567
|
-
def r_title
|
568
|
-
if node_kind_of?(Version)
|
569
|
-
node = "#{self.node}.node"
|
570
|
-
elsif node_kind_of?(Node)
|
571
|
-
node = self.node
|
572
|
-
else
|
573
|
-
return parser_error('title','only works with nodes')
|
574
|
-
end
|
575
|
-
title_params = {}
|
576
|
-
|
577
|
-
title_params[:check_lang] = @params[:check_lang] if @params.include?(:check_lang)
|
578
|
-
|
579
|
-
if @params[:link]
|
580
|
-
value, static = parse_attributes_in_value(@params[:link], :erb => false)
|
581
|
-
link_param = ", :link=>\"#{value}\""
|
582
|
-
else
|
583
|
-
link_param = ''
|
584
|
-
end
|
585
|
-
|
586
|
-
res = "<%= show_title(:node=>#{node}#{link_param}#{params_to_erb(title_params)}"
|
587
|
-
if @params[:text]
|
588
|
-
res << ", :text=>#{@params[:text].inspect}"
|
589
|
-
elsif @params[:attr]
|
590
|
-
res << ", :text=>#{node_attribute(@params[:attr])}"
|
591
|
-
end
|
592
|
-
|
593
|
-
if @params.include?(:project)
|
594
|
-
res << ", :project=>#{@params[:project] == 'true'}"
|
595
|
-
end
|
596
|
-
res << ")"
|
597
|
-
if @params[:actions]
|
598
|
-
res << " + node_actions(:node=>#{node}#{params_to_erb(:actions=>@params[:actions], :publish_after_save=>auto_publish_param)})"
|
599
|
-
end
|
600
|
-
res << "%>"
|
601
|
-
if @params[:status] == 'true' || (@params[:status].nil? && @params[:actions])
|
602
|
-
@html_tag ||= 'span'
|
603
|
-
add_html_class("s<%= #{node}.version.status %>")
|
604
|
-
end
|
605
|
-
res
|
606
|
-
end
|
607
|
-
|
608
|
-
# TODO: test
|
609
|
-
def r_actions
|
610
|
-
out expand_with
|
611
|
-
out "<%= node_actions(:node=>#{node}#{params_to_erb(:actions=>@params[:select], :publish_after_save=>auto_publish_param)}) %>"
|
612
|
-
end
|
613
|
-
|
614
|
-
# TODO: test
|
615
|
-
def r_admin_links
|
616
|
-
"<%= show_link(:admin_links).join('</#{@html_tag}><#{@html_tag}>') %>"
|
617
|
-
end
|
618
|
-
|
619
|
-
def r_text
|
620
|
-
text = @params[:text] ? @params[:text].inspect : "#{node_attribute('v_text')}"
|
621
|
-
limit = @params[:limit] ? ", :limit=>#{@params[:limit].to_i}" : ""
|
622
|
-
|
623
|
-
@html_tag ||= 'div'
|
624
|
-
|
625
|
-
if @html_tag_params[:id]
|
626
|
-
# add a sub-div
|
627
|
-
pre = "<div id='v_text#{erb_node_id}'>"
|
628
|
-
post = "</div>"
|
629
|
-
else
|
630
|
-
pre = post = ''
|
631
|
-
@html_tag_params[:id] = "v_text#{erb_node_id}"
|
632
|
-
end
|
633
|
-
|
634
|
-
add_html_class('zazen')
|
635
|
-
|
636
|
-
unless @params[:empty] == 'true'
|
637
|
-
out "#{pre}<% if #{node}.kind_of?(TextDocument); l = #{node}.content_lang -%>"
|
638
|
-
out "<%= zazen(\"<code\#{l ? \" lang='\#{l}'\" : ''} class=\\'full\\'>\#{#{text}}</code>\") %>"
|
639
|
-
out "<% else -%>"
|
640
|
-
out "<%= zazen(#{text}#{limit}, :node=>#{node(Node)}) %>"
|
641
|
-
out "<% end -%>#{post}"
|
642
|
-
else
|
643
|
-
out "#{pre}#{post}"
|
644
|
-
end
|
645
|
-
end
|
646
|
-
|
647
|
-
def r_inspect
|
648
|
-
out ["params: #{@params.inspect}",
|
649
|
-
"name: #{@context[:name]}",
|
650
|
-
"node: #{node}",
|
651
|
-
"list: #{list}"].join("<br/>")
|
652
|
-
end
|
653
|
-
|
654
|
-
# TODO: replace with a more general 'zazen' or 'show' with id ?
|
655
|
-
def r_summary
|
656
|
-
limit = @params[:limit] ? ", :limit=>#{@params[:limit].to_i}" : ""
|
657
|
-
@html_tag ||= 'div'
|
658
|
-
if @html_tag_params[:id]
|
659
|
-
# add a sub-div
|
660
|
-
pre = "<div id='v_summary#{erb_node_id}'>"
|
661
|
-
post = "</div>"
|
662
|
-
else
|
663
|
-
pre = post = ''
|
664
|
-
@html_tag_params[:id] = "v_summary#{erb_node_id}"
|
665
|
-
end
|
666
|
-
|
667
|
-
add_html_class('zazen')
|
668
|
-
|
669
|
-
unless @params[:or]
|
670
|
-
text = @params[:text] ? @params[:text].inspect : node_attribute('v_summary')
|
671
|
-
out "#{pre}<%= zazen(#{text}#{limit}, :node=>#{node(Node)}) %>#{post}"
|
672
|
-
else
|
673
|
-
limit ||= ', :limit => 2'
|
674
|
-
first_name = 'v_summary'
|
675
|
-
first = node_attribute(first_name)
|
676
|
-
|
677
|
-
second_name = @params[:or].gsub(/[^a-z_]/,'') # FIXME: ist this still needed ? (ERB injection)
|
678
|
-
second = node_attribute(second_name)
|
679
|
-
out "#{pre}<% if #{first} != '' %>"
|
680
|
-
out "<%= zazen(#{first}, :node=>#{node(Node)}) %>"
|
681
|
-
out "<% else %>"
|
682
|
-
out "<%= zazen(#{second}#{limit}, :node=>#{node(Node)}) %>"
|
683
|
-
out "<% end %>#{post}"
|
684
|
-
end
|
685
|
-
end
|
686
|
-
|
687
|
-
def r_show_author
|
688
|
-
if @params[:size] == 'large'
|
689
|
-
out "#{_("posted by")} <b><%= #{node}.author.fullname %></b>"
|
690
|
-
out "<% if #{node}[:user_id] != #{node}.version[:user_id] -%>"
|
691
|
-
out "<% if #{node}[:ref_lang] != #{node}.version[:lang] -%>"
|
692
|
-
out "#{_("traduction by")} <b><%= #{node}.version.author.fullname %></b>"
|
693
|
-
out "<% else -%>"
|
694
|
-
out "#{_("modified by")} <b><%= #{node}.version.author.fullname %></b>"
|
695
|
-
out "<% end"
|
696
|
-
out " end -%>"
|
697
|
-
out " #{_("on")} <%= format_date(#{node}.version.updated_at, #{_('short_date').inspect}) %>."
|
698
|
-
if @params[:traductions] == 'true'
|
699
|
-
out " #{_("Traductions")} : <span class='traductions'><%= helper.traductions(:node=>#{node}).join(', ') %></span>"
|
700
|
-
end
|
701
|
-
else
|
702
|
-
out "<b><%= #{node}.version.author.initials %></b> - <%= format_date(#{node}.version.updated_at, #{_('short_date').inspect}) %>"
|
703
|
-
if @params[:traductions] == 'true'
|
704
|
-
out " <span class='traductions'>(<%= helper.traductions(:node=>#{node}).join(', ') %>)</span>"
|
705
|
-
end
|
706
|
-
end
|
707
|
-
end
|
708
|
-
|
709
|
-
def r_comments_to_publish
|
710
|
-
open_context("visitor.comments_to_publish", :node_class => [Comment])
|
711
|
-
end
|
712
|
-
|
713
|
-
def r_to_publish
|
714
|
-
open_context("visitor.to_publish", :node_class => [Version])
|
715
|
-
end
|
716
|
-
|
717
|
-
def r_proposed
|
718
|
-
open_context("visitor.proposed", :node_class => [Version])
|
719
|
-
end
|
720
|
-
|
721
|
-
def r_redactions
|
722
|
-
open_context("visitor.redactions", :node_class => [Version])
|
723
|
-
end
|
724
|
-
|
725
|
-
def r_edit
|
726
|
-
|
727
|
-
if @context[:dom_prefix]
|
728
|
-
# ajax
|
729
|
-
if @context[:in_form]
|
730
|
-
# cancel button
|
731
|
-
@context[:form_cancel] || ''
|
732
|
-
else
|
733
|
-
# edit button
|
734
|
-
|
735
|
-
# TODO: show 'reply' instead of 'edit' in comments if visitor != author
|
736
|
-
out link_to_update(self, :default_text => _('edit'), :url => "\#{edit_#{base_class.to_s.underscore}_path(#{node_id})}", :html_params => get_html_params(@params, :link), :method => :get, :cond => "#{node}.can_write?", :else => :void)
|
737
|
-
end
|
738
|
-
else
|
739
|
-
# FIXME: we could link to some html page to edit the item.
|
740
|
-
""
|
741
|
-
end
|
742
|
-
end
|
743
|
-
|
744
|
-
alias r_cancel r_edit
|
745
|
-
|
746
|
-
def r_textarea
|
747
|
-
out make_textarea(@html_tag_params.merge(@params))
|
748
|
-
@html_tag_done = true
|
749
|
-
end
|
750
|
-
|
751
|
-
|
752
|
-
# <r:select name='klass' root_class='...'/>
|
753
|
-
# <r:select name='parent_id' values='projects in site'/>
|
754
|
-
# TODO: optimization (avoid loading full AR to only use [id, name])
|
755
|
-
def r_select
|
756
|
-
html_attributes, attribute = get_input_params()
|
757
|
-
return parser_error("missing name") unless attribute
|
758
|
-
if value = @params[:selected]
|
759
|
-
# FIXME: DRY with html_attributes
|
760
|
-
value = value.gsub(/\[([^\]]+)\]/) do
|
761
|
-
node_attr = $1
|
762
|
-
res = node_attribute(node_attr)
|
763
|
-
"\#{#{res}}"
|
764
|
-
end
|
765
|
-
selected = value.inspect
|
766
|
-
elsif @context[:in_filter]
|
767
|
-
selected = "params[#{attribute.to_sym.inspect}].to_s"
|
768
|
-
else
|
769
|
-
selected = "#{node_attribute(attribute)}.to_s"
|
770
|
-
end
|
771
|
-
html_id = html_attributes[:id] ? " id='#{html_attributes[:id]}'" : ''
|
772
|
-
if @context[:in_filter]
|
773
|
-
select_tag = "<select#{html_id} name='#{attribute}'>"
|
774
|
-
else
|
775
|
-
select_tag = "<select#{html_id} name='#{base_class.to_s.underscore}[#{attribute}]'>"
|
776
|
-
end
|
777
|
-
|
778
|
-
if klass = @params[:root_class]
|
779
|
-
class_opts = {}
|
780
|
-
class_opts[:without] = @params[:without] if @params[:without]
|
781
|
-
# do not use 'selected' if the node is not new
|
782
|
-
"#{select_tag}<%= options_for_select(Node.classes_for_form(:class => #{klass.inspect}#{params_to_erb(class_opts)}), (#{node}.new_record? ? #{selected} : #{node}.klass)) %></select>"
|
783
|
-
elsif @params[:type] == 'time_zone'
|
784
|
-
# <r:select name='d_tz' type='time_zone'/>
|
785
|
-
"#{select_tag}<%= options_for_select(TZInfo::Timezone.all_identifiers, #{selected}) %></select>"
|
786
|
-
elsif options_list = get_options_for_select
|
787
|
-
"#{select_tag}<%= options_for_select(#{options_list}, #{selected}) %></select>"
|
788
|
-
else
|
789
|
-
parser_error("missing 'nodes', 'root_class' or 'values'")
|
790
|
-
end
|
791
|
-
end
|
792
|
-
|
793
|
-
|
794
|
-
def r_input
|
795
|
-
html_attributes, attribute = get_input_params()
|
796
|
-
case @params[:type]
|
797
|
-
when 'select' # FIXME: why is this only for classes ?
|
798
|
-
out parser_error("please use [select] here")
|
799
|
-
r_select
|
800
|
-
when 'date_box', 'date'
|
801
|
-
return parser_error("date_box without name") unless attribute
|
802
|
-
input_id = @context[:dom_prefix] ? ", :id=>\"#{dom_id}_#{attribute}\"" : ''
|
803
|
-
"<%= date_box '#{base_class.to_s.underscore}', #{attribute.inspect}, :size=>15#{@context[:in_add] ? ", :value=>''" : ''}#{input_id} %>"
|
804
|
-
when 'id'
|
805
|
-
return parser_error("select id without name") unless attribute
|
806
|
-
name = "#{attribute}_id" unless attribute[-3..-1] == '_id'
|
807
|
-
input_id = @context[:erb_dom_id] ? ", :input_id =>\"#{erb_dom_id}_#{attribute}\"" : ''
|
808
|
-
"<%= select_id('#{base_class.to_s.underscore}', #{attribute.inspect}#{input_id}) %>"
|
809
|
-
when 'time_zone'
|
810
|
-
out parser_error("please use [select] here")
|
811
|
-
r_select
|
812
|
-
when 'submit'
|
813
|
-
@html_tag = 'input'
|
814
|
-
@html_tag_params[:type] = @params[:type]
|
815
|
-
@html_tag_params[:text] = @params[:text] if @params[:text]
|
816
|
-
@html_tag_params.merge!(html_attributes)
|
817
|
-
render_html_tag(nil)
|
818
|
-
else
|
819
|
-
# 'text', 'hidden', ...
|
820
|
-
@html_tag = 'input'
|
821
|
-
@html_tag_params[:type] = @params[:type] || 'text'
|
822
|
-
if checked = html_attributes.delete(:checked)
|
823
|
-
@html_tag_params.merge!(html_attributes)
|
824
|
-
render_html_tag(nil, checked)
|
825
|
-
else
|
826
|
-
@html_tag_params.merge!(html_attributes)
|
827
|
-
render_html_tag(nil)
|
828
|
-
end
|
829
|
-
end
|
830
|
-
end
|
831
|
-
|
832
|
-
def r_form_tag
|
833
|
-
# replace <form> with constructed form
|
834
|
-
"#{@context[:form_tag]}#{expand_with(:form_tag => nil)}</form>"
|
835
|
-
end
|
836
|
-
|
837
|
-
# TODO: add parent_id into the form !
|
838
|
-
# TODO: add <div style="margin:0;padding:0"><input name="_method" type="hidden" value="put" /></div> if method == put
|
839
|
-
# FIXME: use <r:form href='self'> or <r:form action='...'>
|
840
|
-
def r_form
|
841
|
-
hidden_fields = {}
|
842
|
-
set_fields = []
|
843
|
-
id_hash = {:class => @html_tag_params[:class] || @params[:class] || 'form'}
|
844
|
-
var_name = base_class.to_s.underscore
|
845
|
-
(descendants('input') + descendants('select')).each do |tag|
|
846
|
-
set_fields << "#{var_name}[#{tag.params[:name]}]"
|
847
|
-
end
|
848
|
-
|
849
|
-
if @context[:dom_prefix] || @params[:update]
|
850
|
-
# ajax
|
851
|
-
if @context[:in_add]
|
852
|
-
# inline form used to create new elements: set values to '' and 'parent_id' from context
|
853
|
-
id_hash[:id] = "#{erb_dom_id}_form"
|
854
|
-
id_hash[:style] = "display:none;"
|
855
|
-
|
856
|
-
cancel = "<p class='btn_x'><a href='#' onclick='[\"#{erb_dom_id}_add\", \"#{erb_dom_id}_form\"].each(Element.toggle);return false;'>#{_('btn_x')}</a></p>\n"
|
857
|
-
form = "<%= form_remote_tag(:url => #{base_class.to_s.underscore.pluralize}_path, :html => {:id => \"#{dom_id}_form_t\"}) %>\n"
|
858
|
-
else
|
859
|
-
# saved form
|
860
|
-
|
861
|
-
id_hash[:id] = erb_dom_id
|
862
|
-
|
863
|
-
cancel = !@context[:dom_prefix] ? "" : <<-END_TXT
|
864
|
-
<% if #{node}.new_record? -%>
|
865
|
-
<p class='btn_x'><a href='#' onclick='[\"<%= params[:dom_id] %>_add\", \"<%= params[:dom_id] %>_form\"].each(Element.toggle);return false;'>#{_('btn_x')}</a></p>
|
866
|
-
<% else -%>
|
867
|
-
<p class='btn_x'><%= link_to_remote(#{_('btn_x').inspect}, :url => #{base_class.to_s.underscore}_path(#{node_id}) + \"/zafu?t_url=#{CGI.escape(template_url)}&dom_id=\#{params[:dom_id]}#{@context[:need_link_id] ? "&link_id=\#{#{node}.link_id}" : ''}\", :method => :get) %></p>
|
868
|
-
<% end -%>
|
869
|
-
END_TXT
|
870
|
-
form =<<-END_TXT
|
871
|
-
<% if #{node}.new_record? -%>
|
872
|
-
<%= form_remote_tag(:url => #{base_class.to_s.underscore.pluralize}_path, :html => {:id => \"\#{params[:dom_id]}_form_t\"}) %>
|
873
|
-
<% else -%>
|
874
|
-
<%= form_remote_tag(:url => #{base_class.to_s.underscore}_path(#{node_id}), :method => :put, :html => {:id => \"#{dom_id}_form_t\"}) %>
|
875
|
-
<% end -%>
|
876
|
-
END_TXT
|
877
|
-
end
|
878
|
-
|
879
|
-
if (descendants('input') || []).select{|elem| elem.params[:type] == 'submit'} != []
|
880
|
-
# has submit
|
881
|
-
else
|
882
|
-
hidden_submit = "<input type='submit'/>" # hidden submit for Firefox compatibility
|
883
|
-
end
|
884
|
-
|
885
|
-
hidden_fields['link_id'] = "<%= #{node}.link_id %>" if @context[:need_link_id]
|
886
|
-
|
887
|
-
if @params[:update] || (@context[:add] && @context[:add].params[:update])
|
888
|
-
upd = @params[:update] || @context[:add].params[:update]
|
889
|
-
if target = find_target(upd)
|
890
|
-
hidden_fields['u_url'] = target.template_url
|
891
|
-
hidden_fields['udom_id'] = target.erb_dom_id
|
892
|
-
hidden_fields['u_id'] = "<%= #{@context[:parent_node]}.zip %>" if @context[:in_add]
|
893
|
-
hidden_fields['s'] = start_node_s_param(:value)
|
894
|
-
end
|
895
|
-
elsif (block = ancestor('block')) && node_kind_of?(DataEntry)
|
896
|
-
# updates template url
|
897
|
-
hidden_fields['u_url'] = block.template_url
|
898
|
-
hidden_fields['udom_id'] = block.erb_dom_id
|
899
|
-
end
|
900
|
-
|
901
|
-
hidden_fields['t_url'] = template_url
|
902
|
-
if t_id = @params[:t_id]
|
903
|
-
hidden_fields['t_id'] = parse_attributes_in_value(t_id)
|
904
|
-
end
|
905
|
-
|
906
|
-
erb_dom_id = @context[:saved_template] ? '<%= params[:dom_id] %>' : self.erb_dom_id
|
907
|
-
|
908
|
-
hidden_fields['dom_id'] = erb_dom_id
|
909
|
-
|
910
|
-
if node_kind_of?(Node)
|
911
|
-
hidden_fields['node[parent_id]'] = "<%= #{@context[:in_add] ? "#{@context[:parent_node]}.zip" : "#{node}.parent_zip"} %>"
|
912
|
-
elsif node_kind_of?(Comment)
|
913
|
-
# FIXME: the "... || '@node'" is a hack and I don't understand why it's needed...
|
914
|
-
hidden_fields['node_id'] = "<%= #{@context[:parent_node] || '@node'}.zip %>"
|
915
|
-
elsif node_kind_of?(DataEntry)
|
916
|
-
hidden_fields["data_entry[#{@context[:data_root]}_id]"] = "<%= #{@context[:in_add] ? @context[:parent_node] : "#{node}.#{@context[:data_root]}"}.zip %>"
|
917
|
-
end
|
918
|
-
|
919
|
-
if add_block = @context[:add]
|
920
|
-
params = add_block.params
|
921
|
-
[:after, :before, :top, :bottom].each do |sym|
|
922
|
-
if params[sym]
|
923
|
-
hidden_fields['position'] = sym.to_s
|
924
|
-
if params[sym] == 'self'
|
925
|
-
if sym == :before
|
926
|
-
hidden_fields['reference'] = "#{erb_dom_id}_add"
|
927
|
-
else
|
928
|
-
hidden_fields['reference'] = "#{erb_dom_id}_form"
|
929
|
-
end
|
930
|
-
else
|
931
|
-
hidden_fields['reference'] = params[sym]
|
932
|
-
end
|
933
|
-
break
|
934
|
-
end
|
935
|
-
end
|
936
|
-
if params[:done] == 'focus'
|
937
|
-
if params[:focus]
|
938
|
-
hidden_fields['done'] = "'$(\"#{erb_dom_id}_#{@params[:focus]}\").focus();'"
|
939
|
-
else
|
940
|
-
hidden_fields['done'] = "'$(\"#{erb_dom_id}_form_t\").focusFirstElement();'"
|
941
|
-
end
|
942
|
-
elsif params[:done]
|
943
|
-
hidden_fields['done'] = CGI.escape(params[:done]) # .gsub("NODE_ID", @node.zip).gsub("PARENT_ID", @node.parent_zip)
|
944
|
-
end
|
945
|
-
else
|
946
|
-
# ajax form, not in 'add'
|
947
|
-
hidden_fields['done'] = CGI.escape(@params[:done]) if @params[:done]
|
948
|
-
end
|
949
|
-
else
|
950
|
-
# no ajax
|
951
|
-
# FIXME
|
952
|
-
cancel = "" # link to normal node ?
|
953
|
-
form = "<form method='post' action='/nodes/#{erb_node_id}'><div style='margin:0;padding:0'><input name='_method' type='hidden' value='put' /></div>"
|
954
|
-
end
|
955
|
-
|
956
|
-
if node_kind_of?(Node) && (@params[:klass] || @context[:klass])
|
957
|
-
hidden_fields['node[klass]'] = @params[:klass] || @context[:klass]
|
958
|
-
end
|
959
|
-
|
960
|
-
if node_kind_of?(Node) && @params[:mode]
|
961
|
-
hidden_fields['mode'] = @params[:mode]
|
962
|
-
end
|
963
|
-
|
964
|
-
hidden_fields['node[v_status]'] = Zena::Status[:pub] if @context[:publish_after_save] || auto_publish_param
|
965
|
-
|
966
|
-
form << "<div class='hidden'>"
|
967
|
-
hidden_fields.each do |k,v|
|
968
|
-
next if set_fields.include?(k)
|
969
|
-
v = "'#{v}'" unless v.kind_of?(String) && ['"', "'"].include?(v[0..0])
|
970
|
-
form << "<input type='hidden' name='#{k}' value=#{v}/>\n"
|
971
|
-
end
|
972
|
-
form << hidden_submit << "\n" if hidden_submit
|
973
|
-
form << "</div>"
|
974
|
-
|
975
|
-
form << "<%= error_messages_for(#{node}) %>"
|
976
|
-
|
977
|
-
if !descendant('cancel') && !descendant('edit')
|
978
|
-
if !descendant('form_tag')
|
979
|
-
# add a descendant before blocks.
|
980
|
-
blocks_bak = @blocks
|
981
|
-
@blocks = @blocks.dup
|
982
|
-
@blocks = [make(:void, :method=>'void', :text=>cancel)] + blocks_bak
|
983
|
-
else
|
984
|
-
form = cancel + form
|
985
|
-
cancel = ''
|
986
|
-
end
|
987
|
-
end
|
988
|
-
|
989
|
-
if descendant('form_tag')
|
990
|
-
res = expand_with(:form_tag => form, :in_form => true, :form_cancel => cancel, :erb_dom_id => erb_dom_id, :dom_id => dom_id)
|
991
|
-
else
|
992
|
-
res = form + expand_with(:in_form => true, :form_cancel => cancel, :erb_dom_id => erb_dom_id, :dom_id => dom_id) + '</form>'
|
993
|
-
end
|
994
|
-
|
995
|
-
@blocks = blocks_bak if blocks_bak
|
996
|
-
|
997
|
-
@html_tag_done = false
|
998
|
-
@html_tag_params.merge!(id_hash)
|
999
|
-
out render_html_tag(res)
|
1000
|
-
end
|
1001
|
-
|
1002
|
-
# <r:checkbox role='collaborator_for' values='projects' in='site'/>"
|
1003
|
-
# TODO: implement checkbox in the same spirit as 'r_select'
|
1004
|
-
def r_checkbox
|
1005
|
-
return parser_error("missing 'nodes'") unless values = @params[:values] || @params[:nodes]
|
1006
|
-
return parser_error("missing 'role'") unless role = (@params[:role] || @params[:name])
|
1007
|
-
attribute = @params[:attr] || 'name'
|
1008
|
-
if role =~ /(.*)_ids?\Z/
|
1009
|
-
role = $1
|
1010
|
-
end
|
1011
|
-
meth = role.singularize
|
1012
|
-
|
1013
|
-
if values =~ /^\d+\s*($|,)/
|
1014
|
-
# ids
|
1015
|
-
# TODO generate the full query instead of using secure.
|
1016
|
-
values = values.split(',').map{|v| v.to_i}
|
1017
|
-
list_finder = "(secure(Node) { Node.find(:all, :conditions => 'zip IN (#{values.join(',')})') })"
|
1018
|
-
else
|
1019
|
-
# relation
|
1020
|
-
list_finder, klass = build_finder_for(:all, values)
|
1021
|
-
return unless list_finder
|
1022
|
-
return parser_error("invalid class (#{klass})") unless klass.ancestors.include?(Node)
|
1023
|
-
end
|
1024
|
-
out "<% if (#{list_var} = #{list_finder}) && (#{list_var}_relation = #{node}.relation_proxy(#{role.inspect})) -%>"
|
1025
|
-
out "<% if #{list_var}_relation.unique? -%>"
|
1026
|
-
|
1027
|
-
out "<% #{list_var}_id = #{list_var}_relation.other_id -%>"
|
1028
|
-
out "<div class='input_radio'><% #{list_var}.each do |#{var}| -%>"
|
1029
|
-
out "<span><input type='radio' name='node[#{meth}_id]' value='#{erb_node_id(var)}'<%= #{list_var}_id == #{var}[:id] ? \" checked='checked'\" : '' %>/> <%= #{node_attribute(attribute, :node=>var)} %></span> "
|
1030
|
-
out "<% end -%></div>"
|
1031
|
-
out "<input type='radio' name='node[#{meth}_id]' value=''/> #{_('none')}"
|
1032
|
-
|
1033
|
-
out "<% else -%>"
|
1034
|
-
|
1035
|
-
out "<% #{list_var}_ids = #{list_var}_relation.other_ids -%>"
|
1036
|
-
out "<div class='input_checkbox'><% #{list_var}.each do |#{var}| -%>"
|
1037
|
-
out "<span><input type='checkbox' name='node[#{meth}_ids][]' value='#{erb_node_id(var)}'<%= #{list_var}_ids.include?(#{var}[:id]) ? \" checked='checked'\" : '' %>/> <%= #{node_attribute(attribute, :node=>var)} %></span> "
|
1038
|
-
out "<% end -%></div>"
|
1039
|
-
out "<input type='hidden' name='node[#{meth}_ids][]' value=''/>"
|
1040
|
-
|
1041
|
-
out "<% end -%><% end -%>"
|
1042
|
-
end
|
1043
|
-
|
1044
|
-
alias r_radio r_checkbox
|
1045
|
-
|
1046
|
-
# TODO: test
|
1047
|
-
def r_add
|
1048
|
-
return parser_error("should not be called from within 'each'") if parent.method == 'each'
|
1049
|
-
return '' if @context[:make_form]
|
1050
|
-
|
1051
|
-
# why is node = @node (which we need) but we are supposed to have Comments ?
|
1052
|
-
# FIXME: during rewrite, replace 'node' by 'node(klass = node_class)' so the ugly lines below would be
|
1053
|
-
# if node_kind_of?(Comment)
|
1054
|
-
# out "<% if #{node(Node)}.can_comment? -%>"
|
1055
|
-
# Refs #198.
|
1056
|
-
if node_kind_of?(Comment)
|
1057
|
-
out "<% if #{node}.can_comment? -%>"
|
1058
|
-
else
|
1059
|
-
out "<% if #{node}.can_write? -%>"
|
1060
|
-
end
|
1061
|
-
|
1062
|
-
unless descendant('add_btn')
|
1063
|
-
# add a descendant between self and blocks.
|
1064
|
-
blocks = @blocks.dup
|
1065
|
-
@blocks = []
|
1066
|
-
add_btn = make(:void, :method=>'add_btn', :params=>@params.dup, :text=>'')
|
1067
|
-
add_btn.blocks = blocks
|
1068
|
-
remove_instance_variable(:@all_descendants)
|
1069
|
-
end
|
1070
|
-
|
1071
|
-
if @context[:form] && @context[:dom_prefix]
|
1072
|
-
# ajax add
|
1073
|
-
|
1074
|
-
@html_tag_params.merge!(:id => "#{erb_dom_id}_add")
|
1075
|
-
@html_tag_params[:class] ||= 'btn_add'
|
1076
|
-
if @params[:focus]
|
1077
|
-
focus = "$(\"#{erb_dom_id}_#{@params[:focus]}\").focus();"
|
1078
|
-
else
|
1079
|
-
focus = "$(\"#{erb_dom_id}_form_t\").focusFirstElement();"
|
1080
|
-
end
|
1081
|
-
|
1082
|
-
out render_html_tag("#{expand_with(:onclick=>"[\"#{erb_dom_id}_add\", \"#{erb_dom_id}_form\"].each(Element.toggle);#{focus}return false;")}")
|
1083
|
-
|
1084
|
-
if node_kind_of?(Node)
|
1085
|
-
# FIXME: BUG if we set <r:form klass='Post'/> the user cannot select class with menu...
|
1086
|
-
klass = @context[:klass] || 'Node'
|
1087
|
-
# FIXME: inspect '@context[:form]' to see if it contains v_klass ?
|
1088
|
-
out "<% if #{var}_new = secure(Node) { Node.new_from_class(#{klass.inspect}) } -%>"
|
1089
|
-
else
|
1090
|
-
out "<% if #{var}_new = #{node_class}.new -%>"
|
1091
|
-
end
|
1092
|
-
|
1093
|
-
if @context[:form].method == 'form'
|
1094
|
-
out expand_block(@context[:form], :in_add => true, :no_ignore => ['form'], :add=>self, :node => "#{var}_new", :parent_node => node, :klass => klass, :publish_after_save => auto_publish_param)
|
1095
|
-
else
|
1096
|
-
# build form from 'each'
|
1097
|
-
out expand_block(@context[:form], :in_add => true, :no_ignore => ['form'], :add=>self, :make_form => true, :node => "#{var}_new", :parent_node => node, :klass => klass, :publish_after_save => auto_publish_param)
|
1098
|
-
end
|
1099
|
-
out "<% end -%>"
|
1100
|
-
else
|
1101
|
-
# no ajax
|
1102
|
-
@html_tag_params[:class] ||= 'btn_add' if @html_tag
|
1103
|
-
out render_html_tag(expand_with)
|
1104
|
-
end
|
1105
|
-
out "<% end -%>"
|
1106
|
-
@html_tag_done = true
|
1107
|
-
end
|
1108
|
-
|
1109
|
-
def r_add_btn
|
1110
|
-
if @params[:text]
|
1111
|
-
text = @params[:text]
|
1112
|
-
text = "<div>#{text}</div>" unless @html_tag
|
1113
|
-
elsif @params[:trans]
|
1114
|
-
text = _(@params[:trans])
|
1115
|
-
text = "<div>#{text}</div>" unless @html_tag
|
1116
|
-
elsif @blocks != []
|
1117
|
-
text = expand_with
|
1118
|
-
else
|
1119
|
-
text = node_class == Comment ? _("btn_add_comment") : _("btn_add")
|
1120
|
-
end
|
1121
|
-
|
1122
|
-
out "<a href='#' onclick='#{@context[:onclick]}'>#{text}</a>"
|
1123
|
-
end
|
1124
|
-
|
1125
|
-
# Show html to add open a popup window to add a document.
|
1126
|
-
# TODO: inline ajax for upload ?
|
1127
|
-
def r_add_document
|
1128
|
-
return parser_error("only works with nodes (not with #{node_class})") unless node_kind_of?(Node)
|
1129
|
-
@html_tag_params[:class] ||= 'btn_add'
|
1130
|
-
res = "<a href='/documents/new?parent_id=#{erb_node_id}' onclick='uploader=window.open(\"/documents/new?parent_id=#{erb_node_id}\", \"upload\", \"width=400,height=300\");return false;'>#{_('btn_add_doc')}</a>"
|
1131
|
-
"<% if #{node}.can_write? -%>#{render_html_tag(res)}<% end -%>"
|
1132
|
-
end
|
1133
|
-
|
1134
|
-
#if RAILS_ENV == 'test'
|
1135
|
-
# def r_test
|
1136
|
-
# inspect
|
1137
|
-
# end
|
1138
|
-
#end
|
1139
|
-
|
1140
|
-
def r_drop
|
1141
|
-
if parent.method == 'each' && @method == parent.single_child_method
|
1142
|
-
parent.add_html_class('drop')
|
1143
|
-
else
|
1144
|
-
@html_tag_params[:class] ||= 'drop'
|
1145
|
-
end
|
1146
|
-
r_block
|
1147
|
-
end
|
1148
|
-
|
1149
|
-
def drop_javascript
|
1150
|
-
hover = @params[:hover]
|
1151
|
-
change = @params[:change]
|
1152
|
-
|
1153
|
-
if role = @params[:set] || @params[:add]
|
1154
|
-
query_params = ["node[#{role}_id]=[id]"]
|
1155
|
-
else
|
1156
|
-
query_params = []
|
1157
|
-
# set='icon_for=[id], v_status='50', v_title='[v_title]'
|
1158
|
-
@params.each do |k, v|
|
1159
|
-
next if [:hover, :change, :done].include?(k)
|
1160
|
-
value, static = parse_attributes_in_value(v, :erb => false, :skip_node_attributes => true)
|
1161
|
-
key = change == 'params' ? "params[#{k}]" : "node[#{k}]"
|
1162
|
-
query_params << "#{key}=#{CGI.escape(value)}"
|
1163
|
-
end
|
1164
|
-
return parser_error("missing parameters to set values") if query_params == []
|
1165
|
-
end
|
1166
|
-
|
1167
|
-
query_params << "change=#{change}" if change == 'receiver'
|
1168
|
-
query_params << "t_url=#{CGI.escape(template_url)}"
|
1169
|
-
query_params << "dom_id=#{erb_dom_id}"
|
1170
|
-
query_params << start_node_s_param(:erb)
|
1171
|
-
query_params << "done=#{CGI.escape(@params[:done])}" if @params[:done]
|
1172
|
-
|
1173
|
-
"<script type='text/javascript'>
|
1174
|
-
//<![CDATA[
|
1175
|
-
Droppables.add('#{erb_dom_id}', {hoverclass:'#{hover || 'drop_hover'}', onDrop:function(element){new Ajax.Request('/nodes/#{erb_node_id}/drop?#{query_params.join('&')}', {asynchronous:true, evalScripts:true, method:'put', parameters:'drop=' + encodeURIComponent(element.id)})}})
|
1176
|
-
//]]>
|
1177
|
-
</script>"
|
1178
|
-
end
|
1179
|
-
|
1180
|
-
def r_draggable
|
1181
|
-
new_dom_scope
|
1182
|
-
@html_tag ||= 'div'
|
1183
|
-
case @params[:revert]
|
1184
|
-
when 'move'
|
1185
|
-
revert_effect = 'Element.move'
|
1186
|
-
when 'remove'
|
1187
|
-
revert_effect = 'Element.remove'
|
1188
|
-
else
|
1189
|
-
revert_effect = 'Element.move'
|
1190
|
-
end
|
1191
|
-
|
1192
|
-
res, drag_handle = set_drag_handle_and_id(expand_with, @params, :id => erb_dom_id)
|
1193
|
-
|
1194
|
-
out render_html_tag(res)
|
1195
|
-
|
1196
|
-
if drag_handle
|
1197
|
-
out "<script type='text/javascript'>\n//<![CDATA[\n
|
1198
|
-
new Draggable('#{erb_dom_id}', {ghosting:true, revert:true, revertEffect:#{revert_effect}, handle:$('#{erb_dom_id}').select('.#{drag_handle}')[0]});\n//]]>\n</script>"
|
1199
|
-
else
|
1200
|
-
out "<script type='text/javascript'>\n//<![CDATA[\nZena.draggable('#{erb_dom_id}',0,true,true,#{revert_effect})\n//]]>\n</script>"
|
1201
|
-
end
|
1202
|
-
end
|
1203
|
-
|
1204
|
-
def r_unlink
|
1205
|
-
return "" if @context[:make_form]
|
1206
|
-
opts = {}
|
1207
|
-
|
1208
|
-
if upd = @params[:update]
|
1209
|
-
if upd == '_page'
|
1210
|
-
target = nil
|
1211
|
-
elsif target = find_target(upd)
|
1212
|
-
# ok
|
1213
|
-
else
|
1214
|
-
return
|
1215
|
-
end
|
1216
|
-
elsif target = ancestor('block')
|
1217
|
-
# ok
|
1218
|
-
else
|
1219
|
-
target = self
|
1220
|
-
end
|
1221
|
-
|
1222
|
-
if node_kind_of?(Node)
|
1223
|
-
opts[:cond] = "#{node}.can_write? && #{node}.link_id"
|
1224
|
-
opts[:url] = "/nodes/\#{#{node_id}}/links/\#{#{node}.link_id}"
|
1225
|
-
elsif node_kind_of?(Link)
|
1226
|
-
opts[:url] = "/nodes/\#{#{node}.this_zip}/links/\#{#{node}.zip}"
|
1227
|
-
end
|
1228
|
-
|
1229
|
-
opts[:method] = :delete
|
1230
|
-
opts[:default_text] = _('btn_tiny_del')
|
1231
|
-
opts[:html_params] = get_html_params({:class => 'unlink'}.merge(@params), :link)
|
1232
|
-
|
1233
|
-
out link_to_update(target, opts)
|
1234
|
-
|
1235
|
-
#tag_to_remote
|
1236
|
-
#"<%= tag_to_remote({:url => node_path(#{node_id}) + \"#{opts[:method] != :put ? '/zafu' : ''}?#{action.join('&')}\", :method => #{opts[:method].inspect}}) %>"
|
1237
|
-
# out "<a class='#{@params[:class] || 'unlink'}' href='/nodes/#{erb_node_id}/links/<%= #{node}.link_id %>?#{action}' onclick=\"new Ajax.Request('/nodes/#{erb_node_id}/links/<%= #{node}.link_id %>?#{action}', {asynchronous:true, evalScripts:true, method:'delete'}); return false;\">"
|
1238
|
-
# if !@blocks.empty?
|
1239
|
-
# inner = expand_with
|
1240
|
-
# else
|
1241
|
-
# inner = _('btn_tiny_del')
|
1242
|
-
# end
|
1243
|
-
# out "#{inner}</a><% else -%>#{inner}<% end -%>"
|
1244
|
-
#elsif node_kind_of?(DataEntry)
|
1245
|
-
# text = get_text_for_erb
|
1246
|
-
# if text.blank?
|
1247
|
-
# text = _('btn_tiny_del')
|
1248
|
-
# end
|
1249
|
-
# out "<%= link_to_remote(#{text.inspect}, {:url => \"/data_entries/\#{#{node}[:id]}?dom_id=#{dom_id}#{upd_url}\", :method => :delete}, :class=>#{(@params[:class] || 'unlink').inspect}) %>"
|
1250
|
-
#end
|
1251
|
-
end
|
1252
|
-
|
1253
|
-
# Group elements in a list. Use :order to specify order.
|
1254
|
-
def r_group
|
1255
|
-
return parser_error("cannot be used outside of a list") unless list_var = @context[:list]
|
1256
|
-
return parser_error("missing 'by' clause") unless key = @params[:by]
|
1257
|
-
|
1258
|
-
sort_key = @params[:sort] || 'name'
|
1259
|
-
if node_kind_of?(DataEntry) && DataEntry::NodeLinkSymbols.include?(key.to_sym)
|
1260
|
-
key = "#{key}_id"
|
1261
|
-
sort_block = "{|e| (e.#{key} || {})[#{sort_key.to_sym.inspect}]}"
|
1262
|
-
group_array = "group_array(#{list_var}) {|e| e.#{key}}"
|
1263
|
-
elsif node_kind_of?(Node)
|
1264
|
-
if ['project', 'parent', 'section'].include?(key)
|
1265
|
-
sort_block = "{|e| (e.#{key} || {})[#{sort_key.to_sym.inspect}]}"
|
1266
|
-
group_array = "group_array(#{list_var}) {|e| e.#{key}_id}"
|
1267
|
-
end
|
1268
|
-
end
|
1269
|
-
|
1270
|
-
group_array ||= "group_array(#{list_var}) {|e| #{node_attribute(key, :node => 'e')}}"
|
1271
|
-
|
1272
|
-
if sort_block
|
1273
|
-
out "<% grp_#{list_var} = sort_array(#{group_array}) #{sort_block} -%>"
|
1274
|
-
else
|
1275
|
-
out "<% grp_#{list_var} = #{group_array} -%>"
|
1276
|
-
end
|
1277
|
-
|
1278
|
-
if descendant('each_group')
|
1279
|
-
out expand_with(:group => "grp_#{list_var}")
|
1280
|
-
else
|
1281
|
-
@context[:group] = "grp_#{list_var}"
|
1282
|
-
r_each_group
|
1283
|
-
end
|
1284
|
-
end
|
1285
|
-
|
1286
|
-
|
1287
|
-
# Compute statistics on elements in the current list context.
|
1288
|
-
def r_stat
|
1289
|
-
return parser_error("must be used inside a list context") unless list
|
1290
|
-
find = @params[:find] || @params[:date] || 'count'
|
1291
|
-
key = @params[:of] || @params[:from] || 'value'
|
1292
|
-
case find
|
1293
|
-
when 'sum'
|
1294
|
-
value = "#{list}.flatten.inject(0) {|#{var}_sum,#{var}| #{var}_sum + #{node_attribute(key, :node => var)}.to_f}"
|
1295
|
-
when 'min'
|
1296
|
-
value = "#{node_attribute(key, :node => "min_array(#{list}) {|e| #{node_attribute(key, :node => 'e')}}")}"
|
1297
|
-
when 'max'
|
1298
|
-
value = "#{node_attribute(key, :node => "max_array(#{list}) {|e| #{node_attribute(key, :node => 'e')}}")}"
|
1299
|
-
when 'count'
|
1300
|
-
return "<%= #{list}.size %>"
|
1301
|
-
end
|
1302
|
-
if @params[:date]
|
1303
|
-
# FIXME: DRY (r_show)
|
1304
|
-
if @params[:tformat]
|
1305
|
-
format = _(@params[:tformat])
|
1306
|
-
elsif @params[:format]
|
1307
|
-
format = @params[:format]
|
1308
|
-
else
|
1309
|
-
format = "%Y-%m-%d"
|
1310
|
-
end
|
1311
|
-
"<%= #{list}==[] ? '' : format_date(#{value}, #{format.inspect}) %>"
|
1312
|
-
elsif format = @params[:format]
|
1313
|
-
|
1314
|
-
if @params[:zero] == 'hide'
|
1315
|
-
"<%= #{list}==[] ? '' : sprintf_unless_zero(#{@params[:format].inspect}, #{value}) %>"
|
1316
|
-
else
|
1317
|
-
"<%= #{list}==[] ? '' : sprintf(#{@params[:format].inspect}, #{value}) %>"
|
1318
|
-
end
|
1319
|
-
else
|
1320
|
-
"<%= #{list}==[] ? '' : #{value} %>"
|
1321
|
-
end
|
1322
|
-
end
|
1323
|
-
|
1324
|
-
def r_each_group
|
1325
|
-
return parser_error("must be used inside a group context") unless group = @context[:group]
|
1326
|
-
if join = @params[:join]
|
1327
|
-
join = join.gsub(/<([^%])/, '<\1').gsub(/([^%])>/, '\1>')
|
1328
|
-
out "<% #{group}.each_index do |#{list_var}_index| -%>"
|
1329
|
-
out "<%= #{list_var}=#{group}[#{list_var}_index]; #{var} = #{list_var}[0]; #{list_var}_index > 0 ? #{join.inspect} : '' %>"
|
1330
|
-
else
|
1331
|
-
out "<% #{group}.each do |#{list_var}|; #{var} = #{list_var}[0]; -%>"
|
1332
|
-
end
|
1333
|
-
out render_html_tag(expand_with(:group => nil, :list => list_var, :node => var, :scope_node => var))
|
1334
|
-
out "<% end -%>"
|
1335
|
-
end
|
1336
|
-
|
1337
|
-
def r_each
|
1338
|
-
is_draggable = @params[:draggable] == 'true' || @params[:drag_handle]
|
1339
|
-
|
1340
|
-
if descendant('edit') || descendant('unlink') || descendant('swap') || ['block', 'drop'].include?(single_child_method) || is_draggable
|
1341
|
-
id_hash = {:id => erb_dom_id}
|
1342
|
-
else
|
1343
|
-
id_hash = nil
|
1344
|
-
end
|
1345
|
-
|
1346
|
-
|
1347
|
-
if @context[:make_form]
|
1348
|
-
# use the elements inside 'each' loop to produce the edit form
|
1349
|
-
r_form
|
1350
|
-
elsif @context[:list]
|
1351
|
-
# normal rendering: not the start of a saved template
|
1352
|
-
if is_draggable || descendant('unlink')
|
1353
|
-
out "<% #{var}_dom_ids = [] -%>"
|
1354
|
-
end
|
1355
|
-
|
1356
|
-
@params[:alt_class] ||= @html_tag_params.delete(:alt_class)
|
1357
|
-
# FIXME: add alt_reverse='true' to start counting from bottom (if order last on top...)
|
1358
|
-
if @params[:alt_class] || @params[:join]
|
1359
|
-
join = @params[:join] || ''
|
1360
|
-
join = join.gsub(/<([^%])/, '<\1').gsub(/([^%])>/, '\1>')
|
1361
|
-
out "<% #{var}_max_index = #{list}.size - 1 -%>" if @params[:alt_reverse]
|
1362
|
-
out "<% #{list}.each_with_index do |#{var},#{var}_index| -%>"
|
1363
|
-
|
1364
|
-
if join_clause = @params[:join_if]
|
1365
|
-
set_stored(Node, 'prev', "#{var}_prev")
|
1366
|
-
cond = get_test_condition(var, :test=>join_clause)
|
1367
|
-
out "<%= #{var}_prev = #{list}[#{var}_index - 1]; (#{var}_index > 0 && #{cond}) ? #{join.inspect} : '' %>"
|
1368
|
-
else
|
1369
|
-
out "<%= #{var}_index > 0 ? #{join.inspect} : '' %>"
|
1370
|
-
end
|
1371
|
-
|
1372
|
-
if alt_class = @params[:alt_class]
|
1373
|
-
alt_test = @params[:alt_reverse] == 'true' ? "(#{var}_max_index - #{var}_index) % 2 != 0" : "#{var}_index % 2 != 0"
|
1374
|
-
if html_class = @html_tag_params.delete(:class)
|
1375
|
-
html_append = " class='#{html_class}<%= #{alt_test} ? #{(' ' + alt_class).inspect} : '' %>'"
|
1376
|
-
else
|
1377
|
-
html_append = "<%= #{alt_test} ? ' class=#{alt_class.inspect}' : '' %>"
|
1378
|
-
end
|
1379
|
-
else
|
1380
|
-
html_append = nil
|
1381
|
-
end
|
1382
|
-
else
|
1383
|
-
out "<% #{list}.each do |#{var}| -%>"
|
1384
|
-
html_append = nil
|
1385
|
-
end
|
1386
|
-
|
1387
|
-
if is_draggable
|
1388
|
-
out "<% #{var}_dom_ids << \"#{dom_id}\" -%>"
|
1389
|
-
end
|
1390
|
-
|
1391
|
-
out r_anchor(var) if @anchor_param # insert anchor inside the each loop
|
1392
|
-
@params[:anchor] = @anchor_param # set back in case we double render
|
1393
|
-
@anchor_param = nil
|
1394
|
-
|
1395
|
-
res, drag_handle = set_drag_handle_and_id(expand_with(:node => var, :scope_node => var), @params, id_hash)
|
1396
|
-
|
1397
|
-
out render_html_tag(res, html_append)
|
1398
|
-
|
1399
|
-
out "<% end -%>"
|
1400
|
-
|
1401
|
-
if is_draggable
|
1402
|
-
if drag_handle
|
1403
|
-
out "<script type='text/javascript'>\n//<![CDATA[\n<%= #{var}_dom_ids.inspect %>.each(function(dom_id, index) {
|
1404
|
-
new Draggable(dom_id, {ghosting:true, revert:true, handle:$(dom_id).select('.#{drag_handle}')[0]});
|
1405
|
-
});\n//]]>\n</script>"
|
1406
|
-
else
|
1407
|
-
out "<script type='text/javascript'>\n//<![CDATA[\n<%= #{var}_dom_ids.inspect %>.each(Zena.draggable)\n//]]>\n</script>"
|
1408
|
-
end
|
1409
|
-
end
|
1410
|
-
|
1411
|
-
elsif @context[:saved_template]
|
1412
|
-
# render to start a saved template
|
1413
|
-
res, drag_handle = set_drag_handle_and_id(expand_with(:scope_node => node), @params, id_hash)
|
1414
|
-
|
1415
|
-
out render_html_tag(res)
|
1416
|
-
|
1417
|
-
if is_draggable
|
1418
|
-
if drag_handle
|
1419
|
-
out "<script type='text/javascript'>\n//<![CDATA[\nnew Draggable('#{erb_dom_id}', {ghosting:true, revert:true, handle:$('#{erb_dom_id}').select('.#{drag_handle}')[0]});\n//]]>\n</script>"
|
1420
|
-
else
|
1421
|
-
out "<script type='text/javascript'>\n//<![CDATA[\nZena.draggable('#{erb_dom_id}')\n//]]>\n</script>"
|
1422
|
-
end
|
1423
|
-
end
|
1424
|
-
else
|
1425
|
-
# TODO: make a single list ?
|
1426
|
-
@context[:list] = "[#{node}]"
|
1427
|
-
r_each
|
1428
|
-
end
|
1429
|
-
end
|
1430
|
-
|
1431
|
-
def r_case
|
1432
|
-
out "<% if false -%>"
|
1433
|
-
out expand_with(:in_if=>true, :only=>['when', 'else'], :html_tag => @html_tag, :html_tag_params => @html_tag_params)
|
1434
|
-
@html_tag_done = true
|
1435
|
-
out "<% end -%>"
|
1436
|
-
end
|
1437
|
-
|
1438
|
-
# TODO: test
|
1439
|
-
def r_if
|
1440
|
-
cond = get_test_condition
|
1441
|
-
return parser_error("condition error") unless cond
|
1442
|
-
|
1443
|
-
if cond == 'true'
|
1444
|
-
return expand_with(:in_if => false)
|
1445
|
-
elsif cond == 'false'
|
1446
|
-
if descendant('else') || descendant('elsif')
|
1447
|
-
return expand_with(:in_if=>true, :only=>['elsif', 'else'])
|
1448
|
-
else
|
1449
|
-
@html_tag_done = true
|
1450
|
-
return ''
|
1451
|
-
end
|
1452
|
-
end
|
1453
|
-
|
1454
|
-
out "<% if #{cond} -%>"
|
1455
|
-
out render_html_tag(expand_with(:in_if=>false))
|
1456
|
-
out expand_with(:in_if=>true, :only=>['elsif', 'else'], :html_tag => @html_tag, :html_tag_params => @html_tag_params)
|
1457
|
-
out "<% end -%>"
|
1458
|
-
end
|
1459
|
-
|
1460
|
-
def r_else
|
1461
|
-
if @context[:in_if]
|
1462
|
-
@html_tag = @context[:html_tag]
|
1463
|
-
@html_tag_params = @context[:html_tag_params] || {}
|
1464
|
-
out "<% elsif true -%>"
|
1465
|
-
if @params[:text]
|
1466
|
-
out render_html_tag(@params[:text])
|
1467
|
-
else
|
1468
|
-
out render_html_tag(expand_with(:in_if=>false, :only => nil)) # do not propagate :only from ancestor 'if' clause
|
1469
|
-
end
|
1470
|
-
else
|
1471
|
-
""
|
1472
|
-
end
|
1473
|
-
end
|
1474
|
-
|
1475
|
-
def r_elsif
|
1476
|
-
return '' unless @context[:in_if]
|
1477
|
-
@html_tag = @context[:html_tag]
|
1478
|
-
@html_tag_params = @context[:html_tag_params] || {}
|
1479
|
-
cond = get_test_condition
|
1480
|
-
return parser_error("condition error") unless cond
|
1481
|
-
out "<% elsif #{cond} -%>"
|
1482
|
-
out render_html_tag(expand_with(:in_if=>false, :only => nil)) # do not propagate :only from ancestor 'if' clause
|
1483
|
-
end
|
1484
|
-
|
1485
|
-
def r_when
|
1486
|
-
r_elsif
|
1487
|
-
end
|
1488
|
-
|
1489
|
-
# be carefull, this gives a list of 'versions', not 'nodes'
|
1490
|
-
def r_traductions
|
1491
|
-
if @params[:except]
|
1492
|
-
case @params[:except]
|
1493
|
-
when 'current'
|
1494
|
-
opts = "(:conditions=>\"lang != '#{helper.lang}'\")"
|
1495
|
-
else
|
1496
|
-
# list of lang
|
1497
|
-
# TODO: test
|
1498
|
-
langs = @params[:except].split(',').map{|l| l.gsub(/[^a-z]/,'').strip }
|
1499
|
-
opts = "(:conditions=>\"lang NOT IN ('#{langs.join("','")}')\")"
|
1500
|
-
end
|
1501
|
-
elsif @params[:only]
|
1502
|
-
# TODO: test
|
1503
|
-
case @params[:only]
|
1504
|
-
when 'current'
|
1505
|
-
opts = "(:conditions=>\"lang = '#{helper.lang}'\")"
|
1506
|
-
else
|
1507
|
-
# list of lang
|
1508
|
-
# TODO: test
|
1509
|
-
langs = @params[:only].split(',').map{|l| l.gsub(/[^a-z]/,'').strip }
|
1510
|
-
opts = "(:conditions=>\"lang IN ('#{langs.join("','")}')\")"
|
1511
|
-
end
|
1512
|
-
else
|
1513
|
-
opts = ""
|
1514
|
-
end
|
1515
|
-
out "<% if #{list_var} = #{node}.traductions#{opts} -%>"
|
1516
|
-
out expand_with(:list=>list_var, :node_class => Version)
|
1517
|
-
out "<% end -%>"
|
1518
|
-
end
|
1519
|
-
|
1520
|
-
# TODO: test
|
1521
|
-
def r_show_traductions
|
1522
|
-
"<% if #{list_var} = #{node}.traductions -%>"
|
1523
|
-
"#{_("Traductions:")} <span class='traductions'><%= #{list_var}.join(', ') %></span>"
|
1524
|
-
"<%= traductions(:node=>#{node}).join(', ') %>"
|
1525
|
-
end
|
1526
|
-
|
1527
|
-
def r_node
|
1528
|
-
@method = @params[:select] || 'node' # 'node' is for version.node
|
1529
|
-
r_unknown
|
1530
|
-
end
|
1531
|
-
|
1532
|
-
# icon or first image (defined using build_finder_for instead of zafu_known_context for performance reasons).
|
1533
|
-
def r_icon
|
1534
|
-
if !@params[:in] && !@params[:where] && !@params[:from] && !@params[:find]
|
1535
|
-
finder, klass = build_finder_for(:first, 'icon', @params.merge(:or => 'image', :order => 'l_id desc, position asc, name asc', :group => 'id,l_id'))
|
1536
|
-
return unless finder
|
1537
|
-
return parser_error("invalid class (#{klass})") unless klass.ancestors.include?(Node)
|
1538
|
-
do_var(finder, :node_class => klass)
|
1539
|
-
else
|
1540
|
-
r_unknown
|
1541
|
-
end
|
1542
|
-
end
|
1543
|
-
|
1544
|
-
def r_date
|
1545
|
-
select = @params[:select]
|
1546
|
-
case select
|
1547
|
-
when 'main'
|
1548
|
-
expand_with(:date=>'main_date')
|
1549
|
-
when 'now'
|
1550
|
-
expand_with(:date=>'Time.now')
|
1551
|
-
else
|
1552
|
-
if select =~ /^\d{4}-\d{1,2}-\d{1,2}$/
|
1553
|
-
begin
|
1554
|
-
d = Date.parse(select)
|
1555
|
-
expand_with(:date=>select.inspect)
|
1556
|
-
rescue
|
1557
|
-
parser_error("invalid date '#{select}' should be 'YYYY-MM-DD'")
|
1558
|
-
end
|
1559
|
-
elsif date = find_stored(Date, select)
|
1560
|
-
if date[0..0] == '"'
|
1561
|
-
begin
|
1562
|
-
d = Date.parse(date[1..-2])
|
1563
|
-
expand_with(:date=>date)
|
1564
|
-
rescue
|
1565
|
-
parser_error("invalid date #{select} (#{date}) should be 'YYYY-MM-DD'")
|
1566
|
-
end
|
1567
|
-
else
|
1568
|
-
expand_with(:date=>select)
|
1569
|
-
end
|
1570
|
-
elsif select =~ /\[(.*)\]/
|
1571
|
-
date, static = parse_attributes_in_value(select, :erb => false)
|
1572
|
-
expand_with(:date => "\"#{date}\"")
|
1573
|
-
else
|
1574
|
-
parser_error("bad parameter '#{select}'")
|
1575
|
-
end
|
1576
|
-
end
|
1577
|
-
end
|
1578
|
-
|
1579
|
-
def r_javascripts
|
1580
|
-
if @params[:list].nil?
|
1581
|
-
list = %w{ prototype effects tablekit zena }
|
1582
|
-
elsif @params[:list] == 'all'
|
1583
|
-
list = %w{ prototype effects dragdrop tablekit zena }
|
1584
|
-
else
|
1585
|
-
list = @params[:list].split(',').map{|e| e.strip}
|
1586
|
-
end
|
1587
|
-
helper.javascript_include_tag(*list)
|
1588
|
-
end
|
1589
|
-
|
1590
|
-
def r_stylesheets
|
1591
|
-
if @params[:list] == 'all' || @params[:list].nil?
|
1592
|
-
list = %w{ zena code }
|
1593
|
-
else
|
1594
|
-
list = @params[:list].split(',').map{|e| e.strip}
|
1595
|
-
end
|
1596
|
-
list << {:media => @params[:media]} if @params[:media]
|
1597
|
-
helper.stylesheet_link_tag(*list)
|
1598
|
-
end
|
1599
|
-
|
1600
|
-
def r_flash_messages
|
1601
|
-
type = @params[:show] || 'both'
|
1602
|
-
"<div id='messages'>" +
|
1603
|
-
if (type == 'notice' || type == 'both')
|
1604
|
-
"<% if flash[:notice] -%><div id='notice' class='flash' onclick='new Effect.Fade(\"error\")'><%= flash[:notice] %></div><% end -%>"
|
1605
|
-
else
|
1606
|
-
''
|
1607
|
-
end +
|
1608
|
-
if (type == 'error' || type == 'both')
|
1609
|
-
"<% if flash[:error] -%><div id='error' class='flash' onclick='new Effect.Fade(\"error\")'><%= flash[:error] %></div><% end -%>"
|
1610
|
-
else
|
1611
|
-
''
|
1612
|
-
end +
|
1613
|
-
"</div>"
|
1614
|
-
end
|
1615
|
-
|
1616
|
-
# Shows a 'made with zena' link or logo. ;-) Thanks for using this !
|
1617
|
-
# TODO: test and add translation.
|
1618
|
-
# <r:zena show='logo'/> or <r:zena show='text'/> == <r:zena/>
|
1619
|
-
def r_zena
|
1620
|
-
if logo = @params[:logo]
|
1621
|
-
# FIXME
|
1622
|
-
case logo
|
1623
|
-
when 'tiny'
|
1624
|
-
else
|
1625
|
-
end
|
1626
|
-
else
|
1627
|
-
text = case @params[:type]
|
1628
|
-
when 'riding'
|
1629
|
-
_("riding zena")
|
1630
|
-
when 'peace'
|
1631
|
-
_("in peace with zena")
|
1632
|
-
when 'garden'
|
1633
|
-
_("a zen garden")
|
1634
|
-
else
|
1635
|
-
_("made with zena")
|
1636
|
-
end
|
1637
|
-
"<a class='zena' href='http://zenadmin.org' title='zena <%= Zena::VERSION %>'>#{text}</a>"
|
1638
|
-
end
|
1639
|
-
end
|
1640
|
-
|
1641
|
-
def r_design
|
1642
|
-
if @params[:by]
|
1643
|
-
by = "<a href='#{@params[:href]}'>#{@params[:by]}</a>"
|
1644
|
-
else
|
1645
|
-
by = expand_with(:trans => true)
|
1646
|
-
end
|
1647
|
-
unless skin = @params[:skin]
|
1648
|
-
skin = helper.instance_variable_get(:@controller).instance_variable_get(:@skin_name)
|
1649
|
-
end
|
1650
|
-
skin = "<i>#{skin}</i>" unless skin.blank?
|
1651
|
-
_("%{skin}, design by %{name}") % {:name => by, :skin => skin}
|
1652
|
-
end
|
1653
|
-
|
1654
|
-
# creates a link. Options are:
|
1655
|
-
# :href (node, parent, project, root)
|
1656
|
-
# :tattr (translated attribute used as text link)
|
1657
|
-
# :attr (attribute used as text link)
|
1658
|
-
# <r:link href='node'><r:trans attr='lang'/></r:link>
|
1659
|
-
# <r:link href='node' tattr='lang'/>
|
1660
|
-
# <r:link update='dom_id'/>
|
1661
|
-
# <r:link page='next'/> <r:link page='previous'/> <r:link page='list'/>
|
1662
|
-
def r_link
|
1663
|
-
if @params[:page]
|
1664
|
-
pagination_links
|
1665
|
-
else
|
1666
|
-
make_link
|
1667
|
-
end
|
1668
|
-
end
|
1669
|
-
|
1670
|
-
def make_link(options = {})
|
1671
|
-
query_params = options[:query_params] || {}
|
1672
|
-
default_text = options[:default_text]
|
1673
|
-
params = @params.dup
|
1674
|
-
|
1675
|
-
opts = {}
|
1676
|
-
if upd = params.delete(:update)
|
1677
|
-
return unless remote_target = find_target(upd)
|
1678
|
-
end
|
1679
|
-
|
1680
|
-
if href = params.delete(:href)
|
1681
|
-
if lnode = find_stored(Node, href)
|
1682
|
-
# using stored node
|
1683
|
-
else
|
1684
|
-
lnode, klass = build_finder_for(:first, href, {})
|
1685
|
-
return unless lnode
|
1686
|
-
return parser_error("invalid class (#{klass})") unless klass.ancestors.include?(Node)
|
1687
|
-
end
|
1688
|
-
else
|
1689
|
-
# obj
|
1690
|
-
if node_class == Version
|
1691
|
-
lnode = "#{node}.node"
|
1692
|
-
opts[:lang] = "#{node}.lang"
|
1693
|
-
elsif node_kind_of?(Node)
|
1694
|
-
lnode = node
|
1695
|
-
else
|
1696
|
-
lnode = @context[:previous_node]
|
1697
|
-
end
|
1698
|
-
end
|
1699
|
-
|
1700
|
-
if fmt = params.delete(:format)
|
1701
|
-
if fmt == 'data'
|
1702
|
-
opts[:format] = "#{node}.c_ext"
|
1703
|
-
else
|
1704
|
-
opts[:format] = fmt.inspect
|
1705
|
-
end
|
1706
|
-
end
|
1707
|
-
|
1708
|
-
if mode = params.delete(:mode)
|
1709
|
-
opts[:mode] = mode.inspect
|
1710
|
-
end
|
1711
|
-
|
1712
|
-
if sharp = params.delete(:sharp)
|
1713
|
-
opts[:sharp] = sharp.inspect
|
1714
|
-
end
|
1715
|
-
|
1716
|
-
if sharp_in = params.delete(:in)
|
1717
|
-
finder, klass = build_finder_for(:first, sharp_in, {})
|
1718
|
-
return unless finder
|
1719
|
-
return parser_error("invalid class (#{klass})") unless klass.ancestors.include?(Node)
|
1720
|
-
opts[:sharp_in] = finder
|
1721
|
-
end
|
1722
|
-
|
1723
|
-
if @html_tag && @html_tag != 'a'
|
1724
|
-
# FIXME: can we remove this ?
|
1725
|
-
# html attributes do not belong to anchor
|
1726
|
-
pre_space = ''
|
1727
|
-
html_params = {}
|
1728
|
-
else
|
1729
|
-
html_params = get_html_params(params.merge(@html_tag_params), :link)
|
1730
|
-
pre_space = @space_before || ''
|
1731
|
-
@html_tag_done = true
|
1732
|
-
end
|
1733
|
-
|
1734
|
-
(params.keys - [:style, :class, :id, :rel, :name, :anchor, :attr, :tattr, :trans, :text, :page]).each do |k|
|
1735
|
-
next if k.to_s =~ /if_|set_/
|
1736
|
-
query_params[k] = params[k]
|
1737
|
-
end
|
1738
|
-
|
1739
|
-
# TODO: merge these two query_params cleanup things into something cleaner.
|
1740
|
-
if remote_target
|
1741
|
-
# ajax
|
1742
|
-
query_params_list = []
|
1743
|
-
query_params.each do |k,v|
|
1744
|
-
if k == :date
|
1745
|
-
if v == 'current_date'
|
1746
|
-
str = "\#{#{current_date}}"
|
1747
|
-
elsif v =~ /\A\d/
|
1748
|
-
str = CGI.escape(v.gsub('"',''))
|
1749
|
-
elsif v =~ /\[/
|
1750
|
-
attribute, static = parse_attributes_in_value(v.gsub('"',''), :erb => false)
|
1751
|
-
str = static ? CGI.escape(attribute) : "\#{CGI.escape(\"#{attribute}\")}"
|
1752
|
-
else
|
1753
|
-
str = "\#{CGI.escape(#{node_attribute(v)})}"
|
1754
|
-
end
|
1755
|
-
else
|
1756
|
-
attribute, static = parse_attributes_in_value(v.gsub('"',''), :erb => false)
|
1757
|
-
str = static ? CGI.escape(attribute) : "\#{CGI.escape(\"#{attribute}\")}"
|
1758
|
-
end
|
1759
|
-
query_params_list << "#{k.to_s.gsub('"','')}=#{str}"
|
1760
|
-
end
|
1761
|
-
pre_space + link_to_update(remote_target, :node_id => "#{lnode}.zip", :query_params => query_params_list, :default_text => default_text, :html_params => html_params)
|
1762
|
-
else
|
1763
|
-
# direct link
|
1764
|
-
query_params.each do |k,v|
|
1765
|
-
if k == :date
|
1766
|
-
if v == 'current_date'
|
1767
|
-
query_params[k] = current_date
|
1768
|
-
elsif v =~ /\A\d/
|
1769
|
-
query_params[k] = v.inspect
|
1770
|
-
elsif v =~ /\[/
|
1771
|
-
attribute, static = parse_attributes_in_value(v.gsub('"',''), :erb => false)
|
1772
|
-
query_params[k] = "\"#{attribute}\""
|
1773
|
-
else
|
1774
|
-
query_params[k] = node_attribute(v)
|
1775
|
-
end
|
1776
|
-
else
|
1777
|
-
attribute, static = parse_attributes_in_value(v.gsub('"',''), :erb => false)
|
1778
|
-
query_params[k] = "\"#{attribute}\""
|
1779
|
-
end
|
1780
|
-
end
|
1781
|
-
|
1782
|
-
query_params.merge!(opts)
|
1783
|
-
|
1784
|
-
opts_str = ''
|
1785
|
-
query_params.keys.sort {|a,b| a.to_s <=> b.to_s }.each do |k|
|
1786
|
-
opts_str << ",:#{k.to_s.gsub(/[^a-z_A-Z_]/,'')}=>#{query_params[k]}"
|
1787
|
-
end
|
1788
|
-
|
1789
|
-
opts_str += ", :host => #{@context["exp_host"]}" if @context["exp_host"]
|
1790
|
-
|
1791
|
-
pre_space + "<a#{params_to_html(html_params)} href='<%= zen_path(#{lnode}#{opts_str}) %>'>#{text_for_link(default_text)}</a>"
|
1792
|
-
end
|
1793
|
-
end
|
1794
|
-
|
1795
|
-
# <r:link page='next'/> <r:link page='previous'/> <r:link page='list'/>
|
1796
|
-
def pagination_links
|
1797
|
-
return parser_error("not in pagination scope") unless pagination_key = @context[:paginate]
|
1798
|
-
case @params[:page]
|
1799
|
-
when 'previous'
|
1800
|
-
out "<% if set_#{pagination_key}_previous = (set_#{pagination_key} > 1 ? set_#{pagination_key} - 1 : nil) -%>"
|
1801
|
-
@context[:vars] ||= []
|
1802
|
-
@context[:vars] << "#{pagination_key}_previous"
|
1803
|
-
out make_link(:default_text => "<%= set_#{pagination_key}_previous %>", :query_params => {pagination_key => "[#{pagination_key}_previous]"})
|
1804
|
-
if descendant('else')
|
1805
|
-
out expand_with(:in_if => true, :only => ['else', 'elsif'])
|
1806
|
-
end
|
1807
|
-
out "<% end -%>"
|
1808
|
-
when 'next'
|
1809
|
-
out "<% if set_#{pagination_key}_next = (set_#{pagination_key}_count - set_#{pagination_key} > 0 ? set_#{pagination_key} + 1 : nil) -%>"
|
1810
|
-
@context[:vars] ||= []
|
1811
|
-
@context[:vars] << "#{pagination_key}_next"
|
1812
|
-
out make_link(:default_text => "<%= set_#{pagination_key}_next %>", :query_params => {pagination_key => "[#{pagination_key}_next]"})
|
1813
|
-
if descendant('else')
|
1814
|
-
out expand_with(:in_if => true, :only => ['else', 'elsif'])
|
1815
|
-
end
|
1816
|
-
out "<% end -%>"
|
1817
|
-
when 'list'
|
1818
|
-
@context[:vars] ||= []
|
1819
|
-
@context[:vars] << "#{pagination_key}_page"
|
1820
|
-
if @blocks == [] || (@blocks.size == 1 && !@blocks.first.kind_of?(String) && @blocks.first.method == 'else')
|
1821
|
-
# add a default block
|
1822
|
-
if tag = @params[:tag]
|
1823
|
-
open_tag = "<#{tag}>"
|
1824
|
-
close_tag = "</#{tag}>"
|
1825
|
-
else
|
1826
|
-
open_tag = close_tag = ''
|
1827
|
-
end
|
1828
|
-
link_params = {}
|
1829
|
-
@params.each do |k,v|
|
1830
|
-
next if [:tag, :page, :join, :page_count].include?(k)
|
1831
|
-
link_params[k] = v
|
1832
|
-
end
|
1833
|
-
text = "#{open_tag}<r:link #{params_to_html(link_params)} #{pagination_key}='[#{pagination_key}_page]' do='[#{pagination_key}_page]'/>#{close_tag}"
|
1834
|
-
@blocks = [make(:void, :method=>'void', :text=>text)]
|
1835
|
-
remove_instance_variable(:@all_descendants)
|
1836
|
-
end
|
1837
|
-
|
1838
|
-
if !descendant('else')
|
1839
|
-
@blocks += [make(:void, :method=>'void', :text=>"<r:else>#{open_tag}<r:show var='#{pagination_key}_page'/>#{close_tag}</r:else>")]
|
1840
|
-
remove_instance_variable(:@all_descendants)
|
1841
|
-
end
|
1842
|
-
|
1843
|
-
out "<% page_numbers(set_#{pagination_key}, set_#{pagination_key}_count, #{(@params[:join] || ' ').inspect}, #{@params[:page_count] ? @params[:page_count].to_i : 'nil'}) do |set_#{pagination_key}_page, #{pagination_key}_page_join| %>"
|
1844
|
-
out "<%= #{pagination_key}_page_join %>"
|
1845
|
-
out "<% if set_#{pagination_key}_page != set_#{pagination_key} -%>"
|
1846
|
-
out expand_with(:in_if => true)
|
1847
|
-
out "<% end; end -%>"
|
1848
|
-
else
|
1849
|
-
parser_error("unkown 'page' option #{@params[:page].inspect} should be ('previous', 'next' or 'list')")
|
1850
|
-
end
|
1851
|
-
end
|
1852
|
-
|
1853
|
-
def r_img
|
1854
|
-
return unless node_kind_of?(Node)
|
1855
|
-
if @params[:src]
|
1856
|
-
finder, klass = build_finder_for(:first, @params[:src])
|
1857
|
-
return unless finder
|
1858
|
-
return parser_error("invalid class (#{klass})") unless klass.ancestors.include?(Node)
|
1859
|
-
img = finder
|
1860
|
-
else
|
1861
|
-
img = node
|
1862
|
-
end
|
1863
|
-
mode = @params[:mode] || 'std'
|
1864
|
-
# FIXME: replace this call by something that integrates better with html_tag_params and such.
|
1865
|
-
res = "img_tag(#{img}, :mode=>#{mode.inspect}"
|
1866
|
-
[:class, :alt_src, :id, :border, :style].each do |k|
|
1867
|
-
res += ", :#{k}=>#{@params[k].inspect}" if @params[k]
|
1868
|
-
end
|
1869
|
-
res += ", :host => #{@context["exp_host"]}" if @context["exp_host"]
|
1870
|
-
res += ")"
|
1871
|
-
if @params[:link]
|
1872
|
-
finder, klass = build_finder_for(:first, @params[:link])
|
1873
|
-
return unless finder
|
1874
|
-
return parser_error("invalid class (#{klass})") unless klass.ancestors.include?(Node)
|
1875
|
-
|
1876
|
-
opts_str = @context["exp_host"] ? ", :host => #{@context["exp_host"]}" : ""
|
1877
|
-
|
1878
|
-
"<a href='<%= zen_path(#{finder}#{opts_str}) %>'><%= #{res} %></a>"
|
1879
|
-
else
|
1880
|
-
"<%= #{res} %>"
|
1881
|
-
end
|
1882
|
-
end
|
1883
|
-
|
1884
|
-
def r_calendar
|
1885
|
-
if @context[:block] == self
|
1886
|
-
# called from self (storing template / rendering)
|
1887
|
-
if role = @params[:assign_as]
|
1888
|
-
assign_calendar(role)
|
1889
|
-
else
|
1890
|
-
display_calendar
|
1891
|
-
end
|
1892
|
-
else
|
1893
|
-
# This is called first to prepare calendar
|
1894
|
-
if @params[:assign_as]
|
1895
|
-
fld = 'date'
|
1896
|
-
table_name = 'links'
|
1897
|
-
else
|
1898
|
-
fld = @params[:date] || 'event_at'
|
1899
|
-
if ['log_at', 'created_at', 'updated_at', 'event_at'].include?(fld) # TODO: use rubyless to learn type
|
1900
|
-
table_name = 'nodes'
|
1901
|
-
elsif fld == 'l_date'
|
1902
|
-
fld = 'date'
|
1903
|
-
table_name = 'links'
|
1904
|
-
else
|
1905
|
-
return parser_error("Invalid 'date' value for calendar (#{fld.inspect}).")
|
1906
|
-
end
|
1907
|
-
end
|
1908
|
-
|
1909
|
-
@date_scope = "TABLE_NAME[#{table_name}].#{fld} >= '\#{start_date.strftime('%Y-%m-%d')}' AND TABLE_NAME[#{table_name}].#{fld} <= '\#{end_date.strftime('%Y-%m-%d')}'"
|
1910
|
-
|
1911
|
-
new_dom_scope
|
1912
|
-
|
1913
|
-
# SAVED TEMPLATE
|
1914
|
-
template = expand_block(self, :block => self, :saved_template => true)
|
1915
|
-
out helper.save_erb_to_url(template, template_url)
|
1916
|
-
|
1917
|
-
# INLINE
|
1918
|
-
out expand_block(self, :block => self, :saved_template => false)
|
1919
|
-
end
|
1920
|
-
end
|
1921
|
-
|
1922
|
-
def display_calendar
|
1923
|
-
size = (params[:size] || 'large').to_sym
|
1924
|
-
finder = params[:select] || 'notes in project'
|
1925
|
-
|
1926
|
-
if @blocks == []
|
1927
|
-
# add a default <r:link/> block
|
1928
|
-
if size == :tiny
|
1929
|
-
@blocks = [make(:void, :method=>'void', :text=>"<em do='link' date='current_date' do='[current_date]' format='%d'/><r:else do='[current_date]' format='%d'/>")]
|
1930
|
-
else
|
1931
|
-
@blocks = [make(:void, :method=>'void', :text=>"<span do='show' date='current_date' format='%d'/><ul><li do='each' do='link' attr='name'/></ul><r:else do='[current_date]' format='%d'/>")]
|
1932
|
-
end
|
1933
|
-
remove_instance_variable(:@all_descendants)
|
1934
|
-
elsif !descendant('else')
|
1935
|
-
@blocks += [make(:void, :method=>'void', :text=>"<r:else do='[current_date]' format='%d'/>")]
|
1936
|
-
remove_instance_variable(:@all_descendants)
|
1937
|
-
end
|
1938
|
-
|
1939
|
-
@html_tag_done = false
|
1940
|
-
@html_tag_params[:id] = erb_dom_id
|
1941
|
-
@html_tag_params[:class] ||= "#{size}cal"
|
1942
|
-
@html_tag ||= 'div'
|
1943
|
-
|
1944
|
-
finder, klass = build_finder_for(:all, finder, @params, [@date_scope])
|
1945
|
-
return unless finder
|
1946
|
-
return parser_error("invalid class (#{klass})") unless klass.ancestors.include?(Node)
|
1947
|
-
|
1948
|
-
cell_code = "<% if #{list_var} = nodes_#{list_var}[cal_#{list_var}.strftime('%Y-%m-%d %H')] -%>#{expand_with(:in_if => true, :list => list_var, :date => "cal_#{list_var}", :saved_template => nil, :dom_prefix => nil, :in_calendar => true)}<% end -%>"
|
1949
|
-
|
1950
|
-
render_html_tag(calendar_code(finder, "", cell_code, "", params))
|
1951
|
-
end
|
1952
|
-
|
1953
|
-
# manage links from @node ---- reference ----> ...
|
1954
|
-
# <div do='calendar' assign='reference' to='main' split_hours='12' />
|
1955
|
-
def assign_calendar(as_role)
|
1956
|
-
size = (params[:size] || 'large').to_sym
|
1957
|
-
@html_tag_done = false
|
1958
|
-
@html_tag_params[:id] = erb_dom_id
|
1959
|
-
@html_tag_params[:class] ||= "#{size}cal"
|
1960
|
-
@html_tag ||= 'div'
|
1961
|
-
if rel = RelationProxy.find_by_role(as_role.singularize)
|
1962
|
-
role = rel.this_role
|
1963
|
-
else
|
1964
|
-
return parser_error("Invalid role #{as_role.inspect}.")
|
1965
|
-
end
|
1966
|
-
finder, klass = build_finder_for(:all, role, @params, [@date_scope])
|
1967
|
-
return unless finder
|
1968
|
-
return parser_error("invalid class (#{klass})") unless klass.ancestors.include?(Node)
|
1969
|
-
|
1970
|
-
# SAVED TEMPLATE ========
|
1971
|
-
template_url = self.template_url + 'cell'
|
1972
|
-
template = "<%= cal_assign_cell(@node, #{role.inspect}, #{@params[:used].inspect}) %>"
|
1973
|
-
out helper.save_erb_to_url(template, template_url)
|
1974
|
-
|
1975
|
-
# we call update on node 'B'
|
1976
|
-
# A (main)
|
1977
|
-
# ... B (other node)
|
1978
|
-
# calendar (in B context) ---- role --->
|
1979
|
-
|
1980
|
-
cell_prefix_code = "<span><%= day_#{list_var}.strftime('%d').to_i -%></span><ul>"
|
1981
|
-
cell_code = "<%= #{list_var} = nodes_#{list_var}[cal_#{list_var}.strftime('%Y-%m-%d %H')]; #{node}.linked_node = #{list_var} ? #{list_var}.first : nil; cal_assign_cell(#{node}, #{role.inspect}, #{@params[:used].inspect}, params[:s] || @node.zip, cal_#{list_var}, #{template_url.inspect}) %>"
|
1982
|
-
cell_postfix_code = "</ul>"
|
1983
|
-
render_html_tag(calendar_code(finder, cell_prefix_code, cell_code, cell_postfix_code, params))
|
1984
|
-
end
|
1985
|
-
|
1986
|
-
def calendar_code(finder, cell_prefix_code, cell_code, cell_postfix_code, params)
|
1987
|
-
type = params[:type] ? params[:type].to_sym : :month
|
1988
|
-
size = (params[:size] || 'large').to_sym
|
1989
|
-
ref_date = params[:assign_as] ? 'l_date' : (params[:date] || 'event_at')
|
1990
|
-
|
1991
|
-
case type
|
1992
|
-
when :month
|
1993
|
-
title = "\"\#{_(Date::MONTHNAMES[main_date.mon])} \#{main_date.year}\""
|
1994
|
-
prev_date = "\#{main_date.advance(:months => -1).strftime(\"%Y-%m-%d\")}"
|
1995
|
-
next_date = "\#{main_date.advance(:months => 1).strftime(\"%Y-%m-%d\")}"
|
1996
|
-
when :week
|
1997
|
-
title = "\"\#{_(Date::MONTHNAMES[main_date.mon])} \#{main_date.year}\""
|
1998
|
-
prev_date = "\#{main_date.advance(:days => -7).strftime(\"%Y-%m-%d\")}"
|
1999
|
-
next_date = "\#{main_date.advance(:days => +7).strftime(\"%Y-%m-%d\")}"
|
2000
|
-
else
|
2001
|
-
return parser_error("invalid type (should be 'month' or 'week')")
|
2002
|
-
end
|
2003
|
-
|
2004
|
-
if hours = @params[:split_hours]
|
2005
|
-
hours = hours.split(',').map{|l| l.to_i}
|
2006
|
-
hours << 0
|
2007
|
-
hours = hours.uniq.sort
|
2008
|
-
# I feel all this would be much better if we could use "each_group" but then how do we access hours ?
|
2009
|
-
week_code = "<% week.step(week+6,1) do |day_#{list_var}| -%>
|
2010
|
-
<td<%= cal_class(day_#{list_var},#{current_date}) %>>#{cell_prefix_code}<% #{hours.inspect}.each do |set_hour|; cal_#{list_var} = Time.utc(day_#{list_var}.year,day_#{list_var}.month,day_#{list_var}.day,set_hour) -%>#{cell_code}<% end -%>#{cell_postfix_code}</td>
|
2011
|
-
<% end -%>"
|
2012
|
-
(@context[:vars] ||= []) << "hour"
|
2013
|
-
else
|
2014
|
-
hours = nil
|
2015
|
-
week_code = "<% week.step(week+6,1) do |day_#{list_var}| -%>
|
2016
|
-
<td<%= cal_class(day_#{list_var},#{current_date}) %>><% cal_#{list_var} = Time.utc(day_#{list_var}.year,day_#{list_var}.month,day_#{list_var}.day) -%>#{cell_prefix_code}#{cell_code}#{cell_postfix_code}</td>
|
2017
|
-
<% end -%>"
|
2018
|
-
end
|
2019
|
-
|
2020
|
-
res = <<-END_TXT
|
2021
|
-
<h3 class='title'>
|
2022
|
-
<span><%= link_to_remote(#{_('img_prev_page').inspect}, :url => #{base_class.to_s.underscore}_path(#{node_id}) + \"/zafu?t_url=#{CGI.escape(template_url)}&dom_id=#{dom_id}&date=#{prev_date}&#{start_node_s_param(:string)}\", :method => :get) %></span>
|
2023
|
-
<span class='date'><%= link_to_remote(#{title}, :url => #{base_class.to_s.underscore}_path(#{node_id}) + \"/zafu?t_url=#{CGI.escape(template_url)}&dom_id=#{dom_id}&#{start_node_s_param(:string)}\", :method => :get) %></span>
|
2024
|
-
<span><%= link_to_remote(#{_('img_next_page').inspect}, :url => #{base_class.to_s.underscore}_path(#{node_id}) + \"/zafu?t_url=#{CGI.escape(template_url)}&dom_id=#{dom_id}&date=#{next_date}&#{start_node_s_param(:string)}\", :method => :get) %></span>
|
2025
|
-
</h3>
|
2026
|
-
<table cellspacing='0' class='#{size}cal#{@params[:assign_as] ? " assign" : ''}'>
|
2027
|
-
<tr class='head'><%= cal_day_names(#{size.inspect}) %></tr>
|
2028
|
-
<% start_date, end_date = cal_start_end(#{current_date}, #{type.inspect}) -%>
|
2029
|
-
<% cal_weeks(#{ref_date.to_sym.inspect}, #{finder}, start_date, end_date, #{hours.inspect}) do |week, nodes_#{list_var}| -%>
|
2030
|
-
<tr class='body'>
|
2031
|
-
#{week_code}
|
2032
|
-
</tr>
|
2033
|
-
<% end -%>
|
2034
|
-
</table>
|
2035
|
-
END_TXT
|
2036
|
-
end
|
2037
|
-
|
2038
|
-
# part caching
|
2039
|
-
def r_cache
|
2040
|
-
kpath = @params[:kpath] || Page.kpath
|
2041
|
-
out "<% #{cache} = Cache.with(visitor.id, visitor.group_ids, #{kpath.inspect}, #{helper.send(:lang).inspect}, #{template_url.inspect}) do capture do %>"
|
2042
|
-
out expand_with
|
2043
|
-
out "<% end; end %><%= #{cache} %>"
|
2044
|
-
end
|
2045
|
-
|
2046
|
-
# recursion
|
2047
|
-
def r_include
|
2048
|
-
return '' if @context[:saved_template]
|
2049
|
-
return super if @params[:template] || !@params[:part]
|
2050
|
-
part = @params[:part].gsub(/[^a-zA-Z_]/,'')
|
2051
|
-
method_name = @context["#{part}_method".to_sym]
|
2052
|
-
return parser_error("no parent named '#{part}'") unless method_name
|
2053
|
-
"<%= #{method_name}(depth+1,#{node},#{list}) %>"
|
2054
|
-
end
|
2055
|
-
|
2056
|
-
# use all other tags as relations
|
2057
|
-
def r_unknown
|
2058
|
-
@params[:select] = @method
|
2059
|
-
r_context
|
2060
|
-
end
|
2061
|
-
|
2062
|
-
# Enter a new context (<r:context find='all' method='pages'>). This is the same as '<r:pages>...</r:pages>'). It is
|
2063
|
-
# considered better style to use '<r:pages>...</r:pages>' instead of the more general '<r:context>' because the tags
|
2064
|
-
# give a clue on the context at start and end. Another way to open a context is the 'do' syntax: "<div do='pages'>...</div>".
|
2065
|
-
# FIXME: 'else' clause has been removed, find a solution to put it back.
|
2066
|
-
def r_context
|
2067
|
-
# DRY ! (build_finder_for, block)
|
2068
|
-
return parser_error("missing 'method' parameter") unless method = @params[:select]
|
2069
|
-
|
2070
|
-
context = node_class.zafu_known_contexts[method]
|
2071
|
-
if context && @params.keys == [:select]
|
2072
|
-
open_context("#{node}.#{method}", context)
|
2073
|
-
elsif node_kind_of?(Node)
|
2074
|
-
count = ['first','all','count'].include?(@params[:find]) ? @params[:find].to_sym : nil
|
2075
|
-
count ||= Node.plural_relation?(method) ? :all : :first
|
2076
|
-
finder, klass, query = build_finder_for(count, method, @params)
|
2077
|
-
return unless finder
|
2078
|
-
if node_kind_of?(Node) && !klass.ancestors.include?(Node)
|
2079
|
-
# moving out of node: store last Node
|
2080
|
-
@context[:previous_node] = node
|
2081
|
-
end
|
2082
|
-
if count == :all
|
2083
|
-
# plural
|
2084
|
-
do_list( finder, query, :node_class => klass)
|
2085
|
-
# elsif count == :count
|
2086
|
-
# "<%= #{build_finder_for(count, method, @params)} %>"
|
2087
|
-
else
|
2088
|
-
# singular
|
2089
|
-
do_var( finder, :node_class => klass)
|
2090
|
-
end
|
2091
|
-
else
|
2092
|
-
"unknown relation (#{method}) for #{node_class} class"
|
2093
|
-
end
|
2094
|
-
end
|
2095
|
-
|
2096
|
-
def open_context(finder, context)
|
2097
|
-
klass = context[:node_class]
|
2098
|
-
# hack to store last 'Node' context until we fix node(Node) stuff:
|
2099
|
-
previous_node = node_kind_of?(Node) ? node : @context[:previous_node]
|
2100
|
-
if klass.kind_of?(Array)
|
2101
|
-
# plural
|
2102
|
-
do_list( finder, nil, context.merge(:node_class => klass[0], :previous_node => previous_node) )
|
2103
|
-
else
|
2104
|
-
# singular
|
2105
|
-
do_var( finder, context.merge(:previous_node => previous_node) )
|
2106
|
-
end
|
2107
|
-
end
|
2108
|
-
|
2109
|
-
# Prepare stylesheet and xml content for xsl-fo post-processor
|
2110
|
-
def r_fop
|
2111
|
-
return parser_error("missing 'stylesheet' argument") unless @params[:stylesheet]
|
2112
|
-
# get stylesheet text
|
2113
|
-
xsl_content, absolute_url, doc = self.class.get_template_text(@params[:stylesheet], @options[:helper], @options[:current_folder])
|
2114
|
-
return parser_error("stylesheet #{@params[:stylesheet].inspect} not found") unless doc
|
2115
|
-
|
2116
|
-
template_url = (self.template_url.split('/')[0..-2] + ['_main.xsl']).join('/')
|
2117
|
-
helper.save_erb_to_url(xsl_content, template_url)
|
2118
|
-
out "<?xml version='1.0' encoding='utf-8'?>\n"
|
2119
|
-
out "<!-- xsl_id:#{doc[:id] } -->\n" if doc
|
2120
|
-
out expand_with
|
2121
|
-
end
|
2122
|
-
|
2123
|
-
# Prepare content for LateX post-processor
|
2124
|
-
def r_latex
|
2125
|
-
out "% latex\n"
|
2126
|
-
# all content inside this will be informed to render for Latex output
|
2127
|
-
out expand_with(:output_format => 'latex')
|
2128
|
-
end
|
2129
|
-
|
2130
|
-
def r_debug
|
2131
|
-
return '' unless @context[:dev]
|
2132
|
-
add_html_class('debug')
|
2133
|
-
out "<p>#{@params[:title]}</p>" if @params[:title]
|
2134
|
-
(@params[:show] || '').split(',').map(&:strip).each do |what|
|
2135
|
-
case what
|
2136
|
-
when 'params'
|
2137
|
-
out "<pre><%= params.inspect %></pre>"
|
2138
|
-
else
|
2139
|
-
parser_error("invalid element to show. Options are ['params'].")
|
2140
|
-
end
|
2141
|
-
end
|
2142
|
-
out expand_with
|
2143
|
-
end
|
2144
|
-
|
2145
|
-
# ================== HELPER METHODS ================
|
2146
|
-
|
2147
|
-
# Create an sql query to open a new context (passes its arguments to HasRelations#build_find)
|
2148
|
-
def build_finder_for(count, rel, params=@params, raw_filters = [])
|
2149
|
-
if (context = node_class.zafu_known_contexts[rel]) && !params[:in] && !params[:where] && !params[:from] && !params[:order] && raw_filters == []
|
2150
|
-
klass = context[:node_class]
|
2151
|
-
|
2152
|
-
if klass.kind_of?(Array) && count == :all
|
2153
|
-
return ["#{node}.#{rel}", klass[0]]
|
2154
|
-
else
|
2155
|
-
return [(count == :all ? "[#{node}.#{rel}]" : "#{node}.#{rel}"), klass]
|
2156
|
-
end
|
2157
|
-
end
|
2158
|
-
|
2159
|
-
rel ||= 'self'
|
2160
|
-
if (count == :first)
|
2161
|
-
if rel == 'self'
|
2162
|
-
return [node, node_class]
|
2163
|
-
elsif rel == 'main'
|
2164
|
-
return ["@node", Node]
|
2165
|
-
elsif rel == 'root'
|
2166
|
-
return ["(secure(Node) { Node.find(#{current_site[:root_id]})})", Node]
|
2167
|
-
elsif rel == 'start'
|
2168
|
-
return ["start_node", Node]
|
2169
|
-
elsif rel == 'visitor'
|
2170
|
-
return ["visitor.contact", Node]
|
2171
|
-
elsif rel =~ /^\d+$/
|
2172
|
-
return ["(secure(Node) { Node.find_by_zip(#{rel.inspect})})", Node]
|
2173
|
-
elsif node_name = find_stored(Node, rel)
|
2174
|
-
return [node_name, Node]
|
2175
|
-
elsif rel[0..0] == '/'
|
2176
|
-
rel = rel[1..-1]
|
2177
|
-
return ["(secure(Node) { Node.find_by_path(#{rel.inspect})})", Node]
|
2178
|
-
end
|
2179
|
-
end
|
2180
|
-
|
2181
|
-
pseudo_sql, add_raw_filters = make_pseudo_sql(rel, params)
|
2182
|
-
raw_filters += add_raw_filters if add_raw_filters
|
2183
|
-
|
2184
|
-
# FIXME: stored should be clarified and managed in a single way through links and contexts.
|
2185
|
-
# <r:void store='foo'>...
|
2186
|
-
# <r:link href='foo'/>
|
2187
|
-
# <r:pages from='foo'/> <-- this is just a matter of changing node parameter
|
2188
|
-
# <r:pages from='site' project='foo'/>
|
2189
|
-
# <r:img link='foo'/>
|
2190
|
-
# ...
|
2191
|
-
|
2192
|
-
if node_kind_of?(Node)
|
2193
|
-
node_name = @context[:parent_node] || node
|
2194
|
-
else
|
2195
|
-
node_name = @context[:previous_node]
|
2196
|
-
end
|
2197
|
-
|
2198
|
-
# make sure we do not use a new record in a find query:
|
2199
|
-
query = Node.build_find(count, pseudo_sql, :node_name => node_name, :raw_filters => raw_filters, :ref_date => "\#{#{current_date}}")
|
2200
|
-
|
2201
|
-
unless query.valid?
|
2202
|
-
out parser_error(query.errors.join(' '), pseudo_sql.join(', '))
|
2203
|
-
return nil
|
2204
|
-
end
|
2205
|
-
|
2206
|
-
|
2207
|
-
if count == :count
|
2208
|
-
out "<%= #{query.finder(:count)} %>"
|
2209
|
-
return nil
|
2210
|
-
end
|
2211
|
-
|
2212
|
-
klass = query.main_class
|
2213
|
-
|
2214
|
-
if params[:else]
|
2215
|
-
# FIXME: else not working with zafu_known_contexts
|
2216
|
-
finder, else_class, else_query = build_finder_for(count, params[:else], {})
|
2217
|
-
if finder && (else_query.nil? || else_query.valid?) && (else_class == klass || klass.ancestors.include?(else_class) || else_class.ancestors.include?(klass))
|
2218
|
-
["(#{query.finder(count)} || #{finder})", klass, query]
|
2219
|
-
else
|
2220
|
-
[query.finder(count), query.main_class, query]
|
2221
|
-
end
|
2222
|
-
else
|
2223
|
-
[query.finder(count), query.main_class, query]
|
2224
|
-
end
|
2225
|
-
end
|
2226
|
-
|
2227
|
-
# Build pseudo sql from the parameters
|
2228
|
-
# comments where ... from ... in ... order ... limit
|
2229
|
-
def make_pseudo_sql(rel, params=@params)
|
2230
|
-
parts = [rel.dup]
|
2231
|
-
filters = []
|
2232
|
-
|
2233
|
-
if params[:from]
|
2234
|
-
parts << params[:from]
|
2235
|
-
|
2236
|
-
key_counter = 1
|
2237
|
-
while sub_part = params["from#{key_counter}".to_sym]
|
2238
|
-
key_counter += 1
|
2239
|
-
parts << sub_part
|
2240
|
-
end
|
2241
|
-
end
|
2242
|
-
|
2243
|
-
if params[:where]
|
2244
|
-
parts[0] << " where #{params[:where]}"
|
2245
|
-
end
|
2246
|
-
|
2247
|
-
if params[:in]
|
2248
|
-
parts[-1] << " in #{params[:in]}"
|
2249
|
-
end
|
2250
|
-
|
2251
|
-
if group = params[:group]
|
2252
|
-
parts[-1] << " group by #{group}" unless parts[0] =~ /group by/
|
2253
|
-
end
|
2254
|
-
|
2255
|
-
if order = params[:order]
|
2256
|
-
parts[-1] << " order by #{order}" unless parts[0] =~ /order by/
|
2257
|
-
end
|
2258
|
-
|
2259
|
-
if paginate = params[:paginate]
|
2260
|
-
page_size = params[:limit].to_i
|
2261
|
-
page_size = 20 if page_size < 1
|
2262
|
-
parts[-1] << " limit #{page_size} paginate #{paginate.gsub(/[^a-z_A-Z]/,'')}"
|
2263
|
-
else
|
2264
|
-
[:limit, :offset].each do |k|
|
2265
|
-
next unless params[k]
|
2266
|
-
parts[-1] << " #{k} #{params[k]}" unless parts[0] =~ / #{k} /
|
2267
|
-
end
|
2268
|
-
end
|
2269
|
-
|
2270
|
-
finders = [parts.join(' from ')]
|
2271
|
-
if params[:or]
|
2272
|
-
finders << params[:or]
|
2273
|
-
|
2274
|
-
key_counter = 1
|
2275
|
-
while sub_or = params["or#{key_counter}".to_sym]
|
2276
|
-
key_counter += 1
|
2277
|
-
finders << sub_or
|
2278
|
-
end
|
2279
|
-
else
|
2280
|
-
or_clause = nil
|
2281
|
-
end
|
2282
|
-
|
2283
|
-
return [finders, parse_raw_filters(params)]
|
2284
|
-
end
|
2285
|
-
|
2286
|
-
# Parse special filters
|
2287
|
-
def parse_raw_filters(params)
|
2288
|
-
filters = []
|
2289
|
-
|
2290
|
-
if value = params[:author]
|
2291
|
-
if stored = find_stored(User, value)
|
2292
|
-
filters << "TABLE_NAME.user_id = '\#{#{stored}.id}'"
|
2293
|
-
elsif value == 'current'
|
2294
|
-
filters << "TABLE_NAME.user_id = '\#{#{node}[:user_id]}'"
|
2295
|
-
elsif value == 'visitor'
|
2296
|
-
filters << "TABLE_NAME.user_id = '\#{visitor[:id]}'"
|
2297
|
-
elsif value =~ /\A\d+\Z/
|
2298
|
-
filters << "TABLE_NAME.user_id = '#{value.to_i}'"
|
2299
|
-
elsif value =~ /\A[\w\/]+\Z/
|
2300
|
-
# TODO: path, not implemented yet
|
2301
|
-
end
|
2302
|
-
end
|
2303
|
-
|
2304
|
-
if value = params[:project]
|
2305
|
-
if stored = find_stored(Node, value)
|
2306
|
-
filters << "TABLE_NAME.project_id = '\#{#{stored}.get_project_id}'"
|
2307
|
-
elsif value == 'current'
|
2308
|
-
filters << "TABLE_NAME.project_id = '\#{#{node}.get_project_id}'"
|
2309
|
-
elsif value =~ /\A\d+\Z/
|
2310
|
-
filters << "TABLE_NAME.project_id = '#{value.to_i}'"
|
2311
|
-
elsif value =~ /\A[\w\/]+\Z/
|
2312
|
-
# TODO: path, not implemented yet
|
2313
|
-
end
|
2314
|
-
end
|
2315
|
-
|
2316
|
-
if value = params[:section]
|
2317
|
-
if stored = find_stored(Node, value)
|
2318
|
-
filters << "TABLE_NAME.section_id = '\#{#{stored}.get_section_id}'"
|
2319
|
-
elsif value == 'current'
|
2320
|
-
filters << "TABLE_NAME.section_id = '\#{#{node}.get_section_id}'"
|
2321
|
-
elsif value =~ /\A\d+\Z/
|
2322
|
-
filters << "TABLE_NAME.section_id = '#{value.to_i}'"
|
2323
|
-
elsif value =~ /\A[\w\/]+\Z/
|
2324
|
-
# not implemented yet
|
2325
|
-
end
|
2326
|
-
end
|
2327
|
-
|
2328
|
-
[:updated, :created, :event, :log].each do |k|
|
2329
|
-
if value = params[k]
|
2330
|
-
# current, same are synonym for 'today'
|
2331
|
-
filters << date_condition(value,"TABLE_NAME.#{k}_at",current_date)
|
2332
|
-
end
|
2333
|
-
end
|
2334
|
-
|
2335
|
-
filters == [] ? nil : filters
|
2336
|
-
end
|
2337
|
-
|
2338
|
-
# helpers
|
2339
|
-
# get current output format
|
2340
|
-
def output_format
|
2341
|
-
@context[:output_format] || 'html'
|
2342
|
-
end
|
2343
|
-
|
2344
|
-
# find the current node name in the context
|
2345
|
-
def node(klass = self.node_class)
|
2346
|
-
if klass == self.node_class
|
2347
|
-
(@context[:saved_template] && @context[:main_node]) ? "@#{base_class.to_s.underscore}" : (@context[:node] || '@node')
|
2348
|
-
elsif klass == Node
|
2349
|
-
@context[:previous_node] || '@node'
|
2350
|
-
else
|
2351
|
-
# ?
|
2352
|
-
out parser_error("could not find node_name for #{klass} (current class is #{node_class})")
|
2353
|
-
'@node'
|
2354
|
-
end
|
2355
|
-
end
|
2356
|
-
|
2357
|
-
def erb_node_id(obj = node)
|
2358
|
-
if node_kind_of?(Version)
|
2359
|
-
"<%= #{obj}.node.zip %>.<%= #{obj}.number %>"
|
2360
|
-
else
|
2361
|
-
"<%= #{node_id(obj)} %>"
|
2362
|
-
end
|
2363
|
-
end
|
2364
|
-
|
2365
|
-
def node_id(obj = node)
|
2366
|
-
"#{obj}.zip"
|
2367
|
-
end
|
2368
|
-
|
2369
|
-
def current_date
|
2370
|
-
@context[:date] || 'main_date'
|
2371
|
-
end
|
2372
|
-
|
2373
|
-
def var
|
2374
|
-
return @var if @var
|
2375
|
-
if node =~ /^var(\d+)$/
|
2376
|
-
@var = "var#{$1.to_i + 1}"
|
2377
|
-
else
|
2378
|
-
@var = "var1"
|
2379
|
-
end
|
2380
|
-
end
|
2381
|
-
|
2382
|
-
def cache
|
2383
|
-
return @cache if @cache
|
2384
|
-
if @context[:cache] =~ /^cache(\d+)$/
|
2385
|
-
@cache = "cache#{$1.to_i + 1}"
|
2386
|
-
else
|
2387
|
-
@cache = "cache1"
|
2388
|
-
end
|
2389
|
-
end
|
2390
|
-
|
2391
|
-
def list_var
|
2392
|
-
return @list_var if @list_var
|
2393
|
-
if (list || "") =~ /^list(\d+)$/
|
2394
|
-
@list_var = "list#{$1.to_i + 1}"
|
2395
|
-
else
|
2396
|
-
@list_var = "list1"
|
2397
|
-
end
|
2398
|
-
end
|
2399
|
-
|
2400
|
-
# Class of the current 'node' object (can be Version, Comment, Node, DataEntry, etc)
|
2401
|
-
def node_class
|
2402
|
-
@context[:node_class] || Node
|
2403
|
-
end
|
2404
|
-
|
2405
|
-
def base_class
|
2406
|
-
if node_kind_of?(Node)
|
2407
|
-
Node
|
2408
|
-
elsif node_kind_of?(Version)
|
2409
|
-
Version
|
2410
|
-
else
|
2411
|
-
node_class
|
2412
|
-
end
|
2413
|
-
end
|
2414
|
-
|
2415
|
-
def node_kind_of?(ancestor)
|
2416
|
-
node_class.ancestors.include?(ancestor)
|
2417
|
-
end
|
2418
|
-
|
2419
|
-
def list
|
2420
|
-
@context[:list]
|
2421
|
-
end
|
2422
|
-
|
2423
|
-
def helper
|
2424
|
-
@options[:helper]
|
2425
|
-
end
|
2426
|
-
|
2427
|
-
def params_to_erb(params, initial_comma = true)
|
2428
|
-
res = initial_comma ? [""] : []
|
2429
|
-
params.each do |k,v|
|
2430
|
-
if v =~ /<%=/ && !(v =~ /"/)
|
2431
|
-
# replace by #{}
|
2432
|
-
val = v.gsub('#{', '# {').gsub(/<%=(.*?)%>/,'#{\1}')
|
2433
|
-
res << "#{k.inspect}=>\"#{val}\""
|
2434
|
-
else
|
2435
|
-
res << "#{k.inspect}=>#{v.inspect}"
|
2436
|
-
end
|
2437
|
-
end
|
2438
|
-
res.join(', ')
|
2439
|
-
end
|
2440
|
-
|
2441
|
-
def do_var(var_finder=nil, opts={})
|
2442
|
-
clear_dom_scope
|
2443
|
-
if var_finder == 'nil'
|
2444
|
-
out "<% if nil -%>"
|
2445
|
-
elsif var_finder
|
2446
|
-
out "<% if #{var} = #{var_finder} -%>"
|
2447
|
-
end
|
2448
|
-
|
2449
|
-
if descendant('unlink')
|
2450
|
-
@html_tag ||= 'div'
|
2451
|
-
new_dom_scope
|
2452
|
-
@html_tag_params[:id] = erb_dom_id
|
2453
|
-
end
|
2454
|
-
|
2455
|
-
res = expand_with(opts.merge(:node=>var, :in_if => false))
|
2456
|
-
|
2457
|
-
if var_finder
|
2458
|
-
res += expand_with(opts.merge(:in_if => true, :only => ['else', 'elsif'], :html_tag_params => @html_tag_params, :html_tag => @html_tag))
|
2459
|
-
end
|
2460
|
-
out render_html_tag(res)
|
2461
|
-
out "<% end -%>" if var_finder
|
2462
|
-
end
|
2463
|
-
|
2464
|
-
def do_list(list_finder, query = nil, opts={})
|
2465
|
-
clear_dom_scope
|
2466
|
-
|
2467
|
-
@context.merge!(opts) # pass options from 'zafu_known_contexts' to @context
|
2468
|
-
|
2469
|
-
if (each_block = descendant('each')) && (each_block.descendant('edit') || descendant('add') || descendant('add_document') || (descendant('swap') && descendant('swap').parent.method != 'block') || ['block', 'drop'].include?(each_block.single_child_method))
|
2470
|
-
new_dom_scope
|
2471
|
-
# ajax, build template. We could merge the following code with 'r_block'.
|
2472
|
-
add_block = descendant('add')
|
2473
|
-
form_block = descendant('form') || each_block
|
2474
|
-
|
2475
|
-
@context[:need_link_id] = form_block.need_link_id
|
2476
|
-
|
2477
|
-
out "<% if (#{list_var} = #{list_finder}) || (#{node}.#{node_kind_of?(Comment) ? "can_comment?" : "can_write?"} && #{list_var}=[]) -%>"
|
2478
|
-
if query && (pagination_key = query.pagination_key)
|
2479
|
-
out "<% set_#{pagination_key}_nodes = #{query.finder(:count)}; set_#{pagination_key}_count = (set_#{pagination_key}_nodes / #{query.page_size.to_f}).ceil; set_#{pagination_key} = [1,params[:#{pagination_key}].to_i].max -%>"
|
2480
|
-
@context[:paginate] = pagination_key
|
2481
|
-
@context[:vars] ||= []
|
2482
|
-
@context[:vars] << "#{pagination_key}_nodes"
|
2483
|
-
@context[:vars] << "#{pagination_key}_count"
|
2484
|
-
@context[:vars] << "#{pagination_key}"
|
2485
|
-
end
|
2486
|
-
|
2487
|
-
# should we publish ?
|
2488
|
-
publish_after_save ||= form_block ? form_block.params[:publish] : nil
|
2489
|
-
publish_after_save ||= descendant('edit') ? descendant('edit').params[:publish] : nil
|
2490
|
-
|
2491
|
-
# class name for create form
|
2492
|
-
klass = add_block ? add_block.params[:klass] : nil
|
2493
|
-
klass ||= form_block ? form_block.params[:klass] : nil
|
2494
|
-
|
2495
|
-
# INLINE ==========
|
2496
|
-
# 'r_add' needs the form when rendering. Send with :form.
|
2497
|
-
out render_html_tag(expand_with(:list=>list_var, :in_if => false, :form=>form_block, :publish_after_save => publish_after_save, :ignore => ['form'], :klass => klass))
|
2498
|
-
out expand_with(:in_if=>true, :only=>['elsif', 'else'], :html_tag => @html_tag, :html_tag_params => @html_tag_params)
|
2499
|
-
out "<% end -%>"
|
2500
|
-
|
2501
|
-
# SAVED TEMPLATE ========
|
2502
|
-
template = expand_block(each_block, :list=>false, :klass => klass, :saved_template => true)
|
2503
|
-
out helper.save_erb_to_url(template, template_url)
|
2504
|
-
|
2505
|
-
# FORM ============
|
2506
|
-
if each_block != form_block
|
2507
|
-
form = expand_block(form_block, :klass => klass, :add=>add_block, :publish_after_save => publish_after_save, :saved_template => true)
|
2508
|
-
else
|
2509
|
-
form = expand_block(form_block, :klass => klass, :add=>add_block, :make_form=>true, :publish_after_save => publish_after_save, :saved_template => true)
|
2510
|
-
end
|
2511
|
-
out helper.save_erb_to_url(form, form_url)
|
2512
|
-
else
|
2513
|
-
# no form, render, edit and add are not ajax
|
2514
|
-
if descendant('add') || descendant('add_document')
|
2515
|
-
out "<% if (#{list_var} = #{list_finder}) || (#{node}.#{node_kind_of?(Comment) ? "can_comment?" : "can_write?"} && #{list_var}=[]) -%>"
|
2516
|
-
elsif list_finder != 'nil'
|
2517
|
-
out "<% if #{list_var} = #{list_finder} -%>"
|
2518
|
-
else
|
2519
|
-
out "<% if nil -%>"
|
2520
|
-
end
|
2521
|
-
|
2522
|
-
if query && (pagination_key = query.pagination_key)
|
2523
|
-
out "<% set_#{pagination_key}_nodes = #{query.finder(:count)}; set_#{pagination_key}_count = (set_#{pagination_key}_nodes / #{query.page_size.to_f}).ceil; set_#{pagination_key} = [1,params[:#{pagination_key}].to_i].max -%>"
|
2524
|
-
@context[:paginate] = pagination_key
|
2525
|
-
@context[:vars] ||= []
|
2526
|
-
@context[:vars] << "#{pagination_key}_nodes"
|
2527
|
-
@context[:vars] << "#{pagination_key}_count"
|
2528
|
-
@context[:vars] << "#{pagination_key}"
|
2529
|
-
end
|
2530
|
-
|
2531
|
-
out render_html_tag(expand_with(:list=>list_var, :in_if => false))
|
2532
|
-
out expand_with(:in_if=>true, :only=>['elsif', 'else'], :html_tag => @html_tag, :html_tag_params => @html_tag_params)
|
2533
|
-
out "<% end -%>"
|
2534
|
-
end
|
2535
|
-
end
|
2536
|
-
|
2537
|
-
def _(text)
|
2538
|
-
if @context[:dict]
|
2539
|
-
@context[:dict][text] || helper.send(:_,text)
|
2540
|
-
else
|
2541
|
-
helper.send(:_,text)
|
2542
|
-
end
|
2543
|
-
end
|
2544
|
-
|
2545
|
-
# Find a block to update on the page
|
2546
|
-
def find_target(name)
|
2547
|
-
# find dom_id / template_url
|
2548
|
-
target = nil
|
2549
|
-
root.descendants('block').each do |b|
|
2550
|
-
if b.name == name
|
2551
|
-
target = b
|
2552
|
-
break
|
2553
|
-
end
|
2554
|
-
end
|
2555
|
-
out parser_error("could not find a block named '#{name}'") if target.nil?
|
2556
|
-
target
|
2557
|
-
end
|
2558
|
-
|
2559
|
-
# DOM id for the current context
|
2560
|
-
def dom_id(suffix='')
|
2561
|
-
return "\#{dom_id(#{node})}" if @context && (@context[:saved_template] && @context[:main_node])
|
2562
|
-
if @context && scope_node = @context[:scope_node]
|
2563
|
-
res = "#{dom_prefix}_\#{#{scope_node}.zip}"
|
2564
|
-
else
|
2565
|
-
res = dom_prefix
|
2566
|
-
end
|
2567
|
-
if (method == 'each' || method == 'each_group') && !@context[:make_form]
|
2568
|
-
"#{res}_\#{#{var}.zip}"
|
2569
|
-
elsif @context && @context[:in_calendar]
|
2570
|
-
"#{res}_\#{#{current_date}.to_i}"
|
2571
|
-
elsif method == 'unlink' || method == 'edit'
|
2572
|
-
target = nil
|
2573
|
-
parent = self.parent
|
2574
|
-
while parent
|
2575
|
-
if ['block', 'each', 'context', 'icon'].include?(parent.method)
|
2576
|
-
target = parent
|
2577
|
-
break
|
2578
|
-
end
|
2579
|
-
parent = parent.parent
|
2580
|
-
end
|
2581
|
-
target ? target.dom_id(suffix) : (res + suffix)
|
2582
|
-
else
|
2583
|
-
res + suffix
|
2584
|
-
end
|
2585
|
-
end
|
2586
|
-
|
2587
|
-
def erb_dom_id(suffix='')
|
2588
|
-
return "<%= dom_id(#{node}) %>" if @context && (@context[:saved_template] && @context[:main_node])
|
2589
|
-
if @context && scope_node = @context[:scope_node]
|
2590
|
-
res = "#{dom_prefix}_<%= #{scope_node}.zip %>"
|
2591
|
-
else
|
2592
|
-
res = dom_prefix
|
2593
|
-
end
|
2594
|
-
if (method == 'each' || method == 'each_group') && !@context[:make_form]
|
2595
|
-
"#{res}_<%= #{var}.zip %>"
|
2596
|
-
elsif method == 'draggable'
|
2597
|
-
"#{res}_<%= #{node}.zip %>"
|
2598
|
-
elsif @context && @context[:in_calendar]
|
2599
|
-
"#{res}_<%= #{current_date}.to_i %>"
|
2600
|
-
elsif method == 'unlink'
|
2601
|
-
target = nil
|
2602
|
-
parent = self.parent
|
2603
|
-
while parent
|
2604
|
-
if ['block', 'each', 'context', 'icon'].include?(parent.method)
|
2605
|
-
target = parent
|
2606
|
-
break
|
2607
|
-
end
|
2608
|
-
parent = parent.parent
|
2609
|
-
end
|
2610
|
-
target ? target.erb_dom_id(suffix) : (res + suffix)
|
2611
|
-
else
|
2612
|
-
res + suffix
|
2613
|
-
end
|
2614
|
-
end
|
2615
|
-
|
2616
|
-
# Unique template_url, ending with dom_id
|
2617
|
-
def template_url
|
2618
|
-
"#{@options[:root]}/#{dom_prefix}"
|
2619
|
-
end
|
2620
|
-
|
2621
|
-
def form_url
|
2622
|
-
template_url + '_form'
|
2623
|
-
end
|
2624
|
-
|
2625
|
-
# Return parameter value accessor
|
2626
|
-
def get_param(key)
|
2627
|
-
"params[:#{key}]"
|
2628
|
-
end
|
2629
|
-
|
2630
|
-
def context
|
2631
|
-
return @context if @context
|
2632
|
-
# not rendered yet, find first parent with context
|
2633
|
-
@context = parent ? parent.context : {}
|
2634
|
-
end
|
2635
|
-
|
2636
|
-
# prefix for DOM id
|
2637
|
-
def dom_prefix
|
2638
|
-
(@context ? @context[:dom_prefix] : nil) || (@dom_prefix ||= unique_name)
|
2639
|
-
end
|
2640
|
-
|
2641
|
-
# use our own scope
|
2642
|
-
def clear_dom_scope
|
2643
|
-
@context.delete(:make_form) # should not propagate
|
2644
|
-
@context.delete(:main_node) # should not propagate
|
2645
|
-
end
|
2646
|
-
|
2647
|
-
# create our own ajax DOM scope
|
2648
|
-
def new_dom_scope
|
2649
|
-
clear_dom_scope
|
2650
|
-
@context.delete(:saved_template) # should not propagate on fresh template
|
2651
|
-
@context.delete(:dom_prefix) # should not propagate on fresh template
|
2652
|
-
@context[:main_node] = true # the current context will be rendered with a fresh '@node'
|
2653
|
-
@context[:dom_prefix] = self.dom_prefix
|
2654
|
-
end
|
2655
|
-
|
2656
|
-
# Return a different name on each call
|
2657
|
-
def unique_name(base = context_name)
|
2658
|
-
root.next_name_index(base, base == @name).gsub(/[^\d\w\/]/,'_')
|
2659
|
-
end
|
2660
|
-
|
2661
|
-
def context_name
|
2662
|
-
@name || if @context
|
2663
|
-
@context[:name] || 'list'
|
2664
|
-
elsif parent
|
2665
|
-
parent.context_name
|
2666
|
-
else
|
2667
|
-
'root'
|
2668
|
-
end
|
2669
|
-
end
|
2670
|
-
|
2671
|
-
def next_name_index(key, own_id = false)
|
2672
|
-
@next_name_index ||= {}
|
2673
|
-
if @next_name_index[key]
|
2674
|
-
@next_name_index[key] += 1
|
2675
|
-
key + @next_name_index[key].to_s
|
2676
|
-
elsif own_id
|
2677
|
-
@next_name_index[key] = 0
|
2678
|
-
key
|
2679
|
-
else
|
2680
|
-
@next_name_index[key] = 1
|
2681
|
-
key + '1'
|
2682
|
-
end
|
2683
|
-
end
|
2684
|
-
|
2685
|
-
def add_params(text, opts={}, inner = '')
|
2686
|
-
text.sub(/\A([^<]*)<(\w+)(( .*?)[^%]|)>/) do
|
2687
|
-
# we must set the first tag id
|
2688
|
-
before = $1
|
2689
|
-
tag = $2
|
2690
|
-
params = parse_params($3)
|
2691
|
-
opts.each do |k,v|
|
2692
|
-
next unless v
|
2693
|
-
params[k] = v
|
2694
|
-
end
|
2695
|
-
"#{before}<#{tag}#{params_to_html(params)}>#{inner}"
|
2696
|
-
end
|
2697
|
-
end
|
2698
|
-
|
2699
|
-
# TODO: RUBYLESS
|
2700
|
-
def get_test_condition(node = self.node, params = @params)
|
2701
|
-
tests = []
|
2702
|
-
params.each do |k,v|
|
2703
|
-
if k.to_s =~ /^(or_|)([a-zA-Z_]+)(\d*)$/
|
2704
|
-
k = $2.to_sym
|
2705
|
-
end #tagged undocumented
|
2706
|
-
if [:kind_of, :klass, :status, :lang, :can, :tagged, :node, :in, :visitor, :has].include?(k)
|
2707
|
-
tests << [k, v]
|
2708
|
-
elsif k == :test
|
2709
|
-
if v =~ /\s/
|
2710
|
-
tests << [:test, v]
|
2711
|
-
else
|
2712
|
-
tests << [:attribute, v]
|
2713
|
-
end
|
2714
|
-
end
|
2715
|
-
end
|
2716
|
-
|
2717
|
-
|
2718
|
-
tests.map! do |type,value|
|
2719
|
-
case type
|
2720
|
-
when :kind_of
|
2721
|
-
"#{node}.vkind_of?(#{value.inspect})"
|
2722
|
-
when :klass
|
2723
|
-
klass = begin Module::const_get(value) rescue "NilClass" end
|
2724
|
-
"#{node}.klass == #{value.inspect}"
|
2725
|
-
when :status
|
2726
|
-
"#{node}.version.status == #{Zena::Status[value.to_sym]}"
|
2727
|
-
when :tagged
|
2728
|
-
# TODO: undocumented: remove and use rubyless !
|
2729
|
-
"#{node}.tagged[#{value.inspect}]"
|
2730
|
-
when :lang
|
2731
|
-
"#{node}.version.lang == #{value.inspect}"
|
2732
|
-
when :can
|
2733
|
-
# TODO: test
|
2734
|
-
case value
|
2735
|
-
when 'write', 'edit'
|
2736
|
-
"#{node}.can_write?"
|
2737
|
-
when 'drive', 'publish'
|
2738
|
-
"#{node}.can_drive?"
|
2739
|
-
else
|
2740
|
-
nil
|
2741
|
-
end
|
2742
|
-
when :has
|
2743
|
-
case value
|
2744
|
-
when 'discussion'
|
2745
|
-
"#{node}.discussion"
|
2746
|
-
else
|
2747
|
-
nil
|
2748
|
-
end
|
2749
|
-
when :test
|
2750
|
-
parse_condition(value, node)
|
2751
|
-
when :attribute
|
2752
|
-
'!' + node_attribute(value, :node => node) + '.blank?'
|
2753
|
-
when :node
|
2754
|
-
if node_kind_of?(Node)
|
2755
|
-
value, node_name = get_attribute_and_node(value)
|
2756
|
-
node_name ||= '@node'
|
2757
|
-
if value
|
2758
|
-
case value
|
2759
|
-
when 'main'
|
2760
|
-
"#{node}[:id] == #{node_name}[:id]"
|
2761
|
-
when 'start'
|
2762
|
-
"#{node}[:zip] == (params[:s] || @node[:zip]).to_i"
|
2763
|
-
when 'parent'
|
2764
|
-
"#{node}[:id] == #{node_name}[:parent_id]"
|
2765
|
-
when 'project'
|
2766
|
-
"#{node}[:id] == #{node_name}[:project_id]"
|
2767
|
-
when 'section'
|
2768
|
-
"#{node}[:id] == #{node_name}[:section_id]"
|
2769
|
-
when 'ancestor'
|
2770
|
-
"#{node_name}.fullpath =~ /\\A\#{#{node}.fullpath}/"
|
2771
|
-
else
|
2772
|
-
if stored = find_stored(Node, value)
|
2773
|
-
"#{node}[:id] == #{stored}[:id]"
|
2774
|
-
else
|
2775
|
-
nil
|
2776
|
-
end
|
2777
|
-
end
|
2778
|
-
else
|
2779
|
-
# bad node_name
|
2780
|
-
nil
|
2781
|
-
end
|
2782
|
-
else
|
2783
|
-
nil
|
2784
|
-
end
|
2785
|
-
when :in
|
2786
|
-
if @context["in_#{value}".to_sym] # FIXME: || ancestors.include?(value) ==> ancestors is a list of zafu tags, not a list of names !
|
2787
|
-
'true'
|
2788
|
-
else
|
2789
|
-
'false'
|
2790
|
-
end
|
2791
|
-
when :visitor
|
2792
|
-
if value == 'anon'
|
2793
|
-
"visitor.is_anon?"
|
2794
|
-
else
|
2795
|
-
nil
|
2796
|
-
end
|
2797
|
-
else
|
2798
|
-
nil
|
2799
|
-
end
|
2800
|
-
end.compact!
|
2801
|
-
tests == [] ? nil : tests.join(' || ')
|
2802
|
-
end
|
2803
|
-
|
2804
|
-
def parse_condition_error(clause, rest, res)
|
2805
|
-
out parser_error("invalid clause #{clause.inspect} near \"#{res[-2..-1]}#{rest[0..1]}\"")
|
2806
|
-
end
|
2807
|
-
|
2808
|
-
def parse_condition(clause, node_name)
|
2809
|
-
rest = clause.strip
|
2810
|
-
types = [:par_open, :value, :bool_op, :op, :par_close]
|
2811
|
-
allowed = [:par_open, :value]
|
2812
|
-
par_count = 0
|
2813
|
-
uses_bool_op = false
|
2814
|
-
segment = [] # value op value
|
2815
|
-
after_value = lambda { segment.size == 3 ? [:bool_op, :par_close] : [:op, :bool_op, :par_close]}
|
2816
|
-
res = ""
|
2817
|
-
while rest != ''
|
2818
|
-
# puts rest.inspect
|
2819
|
-
if rest =~ /\A\s+/
|
2820
|
-
rest = rest[$&.size..-1]
|
2821
|
-
elsif rest[0..0] == '('
|
2822
|
-
unless allowed.include?(:par_open)
|
2823
|
-
parse_condition_error(clause, rest, res)
|
2824
|
-
return nil
|
2825
|
-
end
|
2826
|
-
res << '('
|
2827
|
-
rest = rest[1..-1]
|
2828
|
-
par_count += 1
|
2829
|
-
elsif rest[0..0] == ')'
|
2830
|
-
unless allowed.include?(:par_close)
|
2831
|
-
parse_condition_error(clause, rest, res)
|
2832
|
-
return nil
|
2833
|
-
end
|
2834
|
-
res << ')'
|
2835
|
-
rest = rest[1..-1]
|
2836
|
-
par_count -= 1
|
2837
|
-
if par_count < 0
|
2838
|
-
parse_condition_error(clause, rest, res)
|
2839
|
-
return nil
|
2840
|
-
end
|
2841
|
-
allowed = [:bool_op]
|
2842
|
-
elsif rest =~ /\A(lt|le|eq|ne|ge|gt)\s+/
|
2843
|
-
unless allowed.include?(:op)
|
2844
|
-
parse_condition_error(clause, rest, res)
|
2845
|
-
return nil
|
2846
|
-
end
|
2847
|
-
op = $1.strip
|
2848
|
-
rest = rest[op.size..-1]
|
2849
|
-
op = {'lt' => '<', 'le' => '<=', 'eq' => '==', 'ne' => '!=', 'ge' => '>=', 'gt' => '>'}[op]
|
2850
|
-
segment << [op, :op]
|
2851
|
-
allowed = [:value]
|
2852
|
-
elsif rest =~ /\A("|')([^\1]*?)\1/
|
2853
|
-
# string
|
2854
|
-
unless allowed.include?(:value)
|
2855
|
-
parse_condition_error(clause, rest, res)
|
2856
|
-
return nil
|
2857
|
-
end
|
2858
|
-
rest = rest[$&.size..-1]
|
2859
|
-
segment << [$2.inspect, :string]
|
2860
|
-
allowed = after_value.call
|
2861
|
-
elsif rest =~ /\A(-?\d+)/
|
2862
|
-
# number
|
2863
|
-
unless allowed.include?(:value)
|
2864
|
-
parse_condition_error(clause, rest, res)
|
2865
|
-
return nil
|
2866
|
-
end
|
2867
|
-
rest = rest[$&.size..-1]
|
2868
|
-
segment << [$1, :number]
|
2869
|
-
allowed = after_value.call
|
2870
|
-
elsif rest =~ /\A(and|or)/
|
2871
|
-
unless allowed.include?(:bool_op)
|
2872
|
-
parse_condition_error(clause, rest, res)
|
2873
|
-
return nil
|
2874
|
-
end
|
2875
|
-
uses_bool_op = true
|
2876
|
-
rest = rest[$&.size..-1]
|
2877
|
-
res << " #{$1} "
|
2878
|
-
allowed = [:par_open, :value]
|
2879
|
-
elsif rest =~ /\A([\w:\.\-]+)/
|
2880
|
-
# variable
|
2881
|
-
unless allowed.include?(:value)
|
2882
|
-
parse_condition_error(clause, rest, res)
|
2883
|
-
return nil
|
2884
|
-
end
|
2885
|
-
rest = rest[$&.size..-1]
|
2886
|
-
fld = $1
|
2887
|
-
unless node_attr = node_attribute(fld, :node => node_name)
|
2888
|
-
parser_error("invalid field #{fld.inspect}")
|
2889
|
-
return nil
|
2890
|
-
end
|
2891
|
-
segment << [node_attr, :var]
|
2892
|
-
allowed = after_value.call
|
2893
|
-
else
|
2894
|
-
parse_condition_error(clause, rest, res)
|
2895
|
-
return nil
|
2896
|
-
end
|
2897
|
-
if segment.size == 3
|
2898
|
-
toi = (segment[1][0] =~ /(>|<)/ || (segment[0][1] == :number || segment[2][1] == :number))
|
2899
|
-
segment.map! do |part, type|
|
2900
|
-
if type == :var
|
2901
|
-
toi ? "#{part}.to_i" : part
|
2902
|
-
elsif type == :string
|
2903
|
-
toi ? part[1..-2].to_i : part
|
2904
|
-
else
|
2905
|
-
part
|
2906
|
-
end
|
2907
|
-
end
|
2908
|
-
res << segment.join(" ")
|
2909
|
-
segment = []
|
2910
|
-
end
|
2911
|
-
end
|
2912
|
-
|
2913
|
-
if par_count > 0
|
2914
|
-
parser_error("invalid clause #{clause.inspect}: missing closing ')'")
|
2915
|
-
return nil
|
2916
|
-
elsif allowed.include?(:value)
|
2917
|
-
parser_error("invalid clause #{clause.inspect}")
|
2918
|
-
return nil
|
2919
|
-
else
|
2920
|
-
return uses_bool_op ? "(#{res})" : res
|
2921
|
-
end
|
2922
|
-
end
|
2923
|
-
|
2924
|
-
# Block visibility of descendance with 'do_list'.
|
2925
|
-
def public_descendants
|
2926
|
-
all = super
|
2927
|
-
if ['context', 'each', 'block'].include?(self.method)
|
2928
|
-
# do not propagate 'form',etc up
|
2929
|
-
all.reject do |k,v|
|
2930
|
-
['form','unlink'].include?(k)
|
2931
|
-
end
|
2932
|
-
elsif ['if', 'case'].include?(self.method)
|
2933
|
-
all.reject do |k,v|
|
2934
|
-
['else', 'elsif', 'when'].include?(k)
|
2935
|
-
end
|
2936
|
-
else
|
2937
|
-
all
|
2938
|
-
end
|
2939
|
-
end
|
2940
|
-
|
2941
|
-
def single_child_method
|
2942
|
-
return @single_child_method if defined?(@single_child_method)
|
2943
|
-
@single_child_method = if @blocks.size == 1
|
2944
|
-
single_child = @blocks[0]
|
2945
|
-
return nil if single_child.kind_of?(String)
|
2946
|
-
single_child.html_tag ? nil : single_child.method
|
2947
|
-
else
|
2948
|
-
nil
|
2949
|
-
end
|
2950
|
-
end
|
2951
|
-
|
2952
|
-
def get_attribute_and_node(str)
|
2953
|
-
if str =~ /([^\.]+)\.(.+)/
|
2954
|
-
node_name = $1
|
2955
|
-
node_attr = $2
|
2956
|
-
if att_node = find_stored(Node, node_name)
|
2957
|
-
return [node_attr, att_node, Node]
|
2958
|
-
elsif node_name == 'main'
|
2959
|
-
return [node_attr, '@node', Node]
|
2960
|
-
elsif node_name == 'visitor'
|
2961
|
-
return [node_attr, 'visitor.contact', Contact]
|
2962
|
-
elsif node_name == 'site'
|
2963
|
-
return [node_attr, 'current_site', Site]
|
2964
|
-
else
|
2965
|
-
out parser_error("invalid node name #{node_name.inspect} in attribute #{str.inspect}")
|
2966
|
-
return [nil]
|
2967
|
-
end
|
2968
|
-
else
|
2969
|
-
return [str]
|
2970
|
-
end
|
2971
|
-
end
|
2972
|
-
|
2973
|
-
def parse_attributes_in_value(v, opts = {})
|
2974
|
-
opts = {:erb => true}.merge(opts)
|
2975
|
-
static = true
|
2976
|
-
|
2977
|
-
use_node = @var || node
|
2978
|
-
res = v.gsub(/\[([^\]]+)\]/) do
|
2979
|
-
static = false
|
2980
|
-
res = nil
|
2981
|
-
attribute = $1
|
2982
|
-
|
2983
|
-
if opts[:skip_node_attributes]
|
2984
|
-
if attribute =~ /^param:(\w+)$/
|
2985
|
-
attribute = get_param($1)
|
2986
|
-
elsif attribute == 'current_date'
|
2987
|
-
attribute = current_date
|
2988
|
-
else
|
2989
|
-
res = "[#{attribute}]"
|
2990
|
-
end
|
2991
|
-
else
|
2992
|
-
attribute = node_attribute(attribute, :node => use_node )
|
2993
|
-
end
|
2994
|
-
|
2995
|
-
res ||= if opts[:erb]
|
2996
|
-
"<%= #{attribute} %>"
|
2997
|
-
else
|
2998
|
-
"\#{#{attribute}}"
|
2999
|
-
end
|
3000
|
-
res
|
3001
|
-
end
|
3002
|
-
[res, static]
|
3003
|
-
end
|
3004
|
-
|
3005
|
-
def node_attribute(str, opts={})
|
3006
|
-
|
3007
|
-
if @context[:vars] && @context[:vars].include?(str)
|
3008
|
-
return "set_#{str}"
|
3009
|
-
end
|
3010
|
-
|
3011
|
-
res = PSEUDO_ATTRIBUTES[str]
|
3012
|
-
return res if res
|
3013
|
-
return current_date if str == 'current_date'
|
3014
|
-
return get_param($1) if str =~ /^param:(\w+)$/
|
3015
|
-
|
3016
|
-
attribute, att_node, klass = get_attribute_and_node(str)
|
3017
|
-
|
3018
|
-
return 'nil' unless attribute
|
3019
|
-
|
3020
|
-
|
3021
|
-
att_node ||= opts[:node] || node
|
3022
|
-
klass ||= opts[:node_class] || node_class
|
3023
|
-
|
3024
|
-
real_attribute = attribute =~ /\Ad_/ ? attribute : attribute.gsub(/\A(|[\w_]+)id(s?)\Z/, '\1zip\2')
|
3025
|
-
|
3026
|
-
res = if klass.ancestors.include?(Node)
|
3027
|
-
if ['url','path'].include?(real_attribute)
|
3028
|
-
# pseudo attribute 'url'
|
3029
|
-
params = {}
|
3030
|
-
params[:mode] = @params[:mode] if @params[:mode]
|
3031
|
-
params[:format] = @params[:format] if @params[:format]
|
3032
|
-
"zen_#{real_attribute}(#{node}#{params_to_erb(params)})"
|
3033
|
-
elsif type = safe_method_type([real_attribute])
|
3034
|
-
type[:method]
|
3035
|
-
elsif type = klass.safe_method_type([real_attribute])
|
3036
|
-
"#{att_node}.#{type[:method]}"
|
3037
|
-
else
|
3038
|
-
"#{att_node}.safe_read(#{real_attribute.inspect})"
|
3039
|
-
end
|
3040
|
-
elsif type = klass.safe_method_type([real_attribute])
|
3041
|
-
"#{att_node}.#{type[:method]}"
|
3042
|
-
else
|
3043
|
-
# unknown class, resolve at runtime
|
3044
|
-
"#{att_node}.safe_read(#{real_attribute.inspect})"
|
3045
|
-
end
|
3046
|
-
|
3047
|
-
res = "(#{res} || #{node_attribute(opts[:else])})" if opts[:else]
|
3048
|
-
res = "(#{res} || #{opts[:default].inspect})" if opts[:default]
|
3049
|
-
res
|
3050
|
-
end
|
3051
|
-
|
3052
|
-
# Add a class name to the html_tag
|
3053
|
-
def add_html_class(class_name)
|
3054
|
-
if klass = @html_tag_params[:class]
|
3055
|
-
@html_tag_params[:class] = "#{class_name} #{klass}"
|
3056
|
-
else
|
3057
|
-
@html_tag_params[:class] = class_name
|
3058
|
-
end
|
3059
|
-
end
|
3060
|
-
|
3061
|
-
def render_html_tag(text,*append)
|
3062
|
-
append ||= []
|
3063
|
-
return text if @html_tag_done
|
3064
|
-
set_params = {}
|
3065
|
-
if_params = {}
|
3066
|
-
@params.each do |k,v|
|
3067
|
-
if k.to_s =~ /^t?set_/
|
3068
|
-
set_params[k] = v
|
3069
|
-
end
|
3070
|
-
end
|
3071
|
-
tag_class = @html_tag_params[:class] || @params[:class]
|
3072
|
-
if node_kind_of?(Node)
|
3073
|
-
|
3074
|
-
if @context[:make_form]
|
3075
|
-
node_name = node
|
3076
|
-
elsif (@method == 'each' || @method == 'each_group') && @context[:list]
|
3077
|
-
node_name = var
|
3078
|
-
elsif @method == 'context'
|
3079
|
-
node_name = @var || node
|
3080
|
-
else
|
3081
|
-
node_name = node
|
3082
|
-
end
|
3083
|
-
|
3084
|
-
class_cond = nil
|
3085
|
-
@params.each do |k,v|
|
3086
|
-
if k.to_s =~ /^(.+)_if$/
|
3087
|
-
klass = $1
|
3088
|
-
cond = get_test_condition(node_name, :test => v)
|
3089
|
-
elsif k.to_s =~ /^(.+)_if_(test|node|kind_of|klass|status|lang|can|in)$/
|
3090
|
-
klass = $1
|
3091
|
-
cond = get_test_condition(node_name, $2.to_sym => v)
|
3092
|
-
end
|
3093
|
-
if cond
|
3094
|
-
class_cond = "#{cond} ? \" class='#{klass}'\" : #{class_cond}" # (x = 3) ? "class='foo'" :
|
3095
|
-
end
|
3096
|
-
end
|
3097
|
-
|
3098
|
-
if class_cond
|
3099
|
-
append << "<%= #{class_cond}\"#{tag_class ? " class='#{tag_class}'" : ""}\" %>"
|
3100
|
-
@html_tag_params.delete(:class)
|
3101
|
-
end
|
3102
|
-
end
|
3103
|
-
|
3104
|
-
@html_tag = 'div' if !@html_tag && (set_params != {} || @html_tag_params != {})
|
3105
|
-
|
3106
|
-
bak = @html_tag_params.dup
|
3107
|
-
@html_tag_params = get_html_params(set_params.merge(@html_tag_params), @html_tag)
|
3108
|
-
res = super(text,*append)
|
3109
|
-
@html_tag_params = bak
|
3110
|
-
res
|
3111
|
-
end
|
3112
|
-
|
3113
|
-
def link_to_update(target, opts = {})
|
3114
|
-
method = opts[:method] || :get
|
3115
|
-
|
3116
|
-
html_params = opts[:html_params] || {}
|
3117
|
-
node_id = opts[:node_id] || self.node_id
|
3118
|
-
|
3119
|
-
url = opts[:url] || "/#{base_class.to_s.pluralize.underscore}/\#{#{node_id}}#{method == :get ? '/zafu' : ''}"
|
3120
|
-
opts[:cond] ||= "#{node}.can_write?" if method != :get
|
3121
|
-
|
3122
|
-
query_params = [opts[:query_params]].flatten.compact
|
3123
|
-
|
3124
|
-
if method == :get
|
3125
|
-
if target
|
3126
|
-
query_params << "t_url=#{CGI.escape(target.template_url)}"
|
3127
|
-
query_params << "dom_id=#{target.dom_id}"
|
3128
|
-
else
|
3129
|
-
query_params << "dom_id=_page"
|
3130
|
-
end
|
3131
|
-
else
|
3132
|
-
query_params << "t_url=#{CGI.escape(template_url)}" if method != :delete
|
3133
|
-
|
3134
|
-
query_params << "dom_id=#{dom_id}"
|
3135
|
-
if target != self
|
3136
|
-
if target
|
3137
|
-
query_params << "u_url=#{CGI.escape(target.template_url)}"
|
3138
|
-
query_params << "udom_id=#{target.dom_id}"
|
3139
|
-
else
|
3140
|
-
query_params << "udom_id=_page"
|
3141
|
-
end
|
3142
|
-
end
|
3143
|
-
end
|
3144
|
-
|
3145
|
-
query_params << "link_id=\#{#{node}.link_id}" if @context[:need_link_id] && node_kind_of?(Node)
|
3146
|
-
query_params << "node[v_status]=#{Zena::Status[:pub]}" if @params[:publish] # FIXME: this acts like publish = 'force'
|
3147
|
-
query_params << start_node_s_param(:string)
|
3148
|
-
|
3149
|
-
res = ''
|
3150
|
-
res += "<% if #{opts[:cond]} -%>" if opts[:cond]
|
3151
|
-
res += "<%= tag_to_remote({:url => \"#{url}?#{query_params.join('&')}\", :method => #{method.inspect}}#{params_to_erb(html_params)}) %>"
|
3152
|
-
res += text_for_link(opts[:default_text])
|
3153
|
-
res += "</a>"
|
3154
|
-
if opts[:cond]
|
3155
|
-
if opts[:else] != :void
|
3156
|
-
res += "<% else -%>"
|
3157
|
-
res += text_for_link(opts[:default_text])
|
3158
|
-
end
|
3159
|
-
res += "<% end -%>"
|
3160
|
-
end
|
3161
|
-
res
|
3162
|
-
end
|
3163
|
-
|
3164
|
-
def text_for_link(default = nil)
|
3165
|
-
if @blocks.size > 1 || (@blocks.size == 1 && !(@blocks.first.kind_of?(String) || ['else','elsif'].include?(@blocks.first.method)))
|
3166
|
-
expand_with
|
3167
|
-
elsif default
|
3168
|
-
default
|
3169
|
-
elsif erb_text = get_text_for_erb(@params, false, :string)
|
3170
|
-
erb_text
|
3171
|
-
elsif node_kind_of?(Node)
|
3172
|
-
"<%= #{node}.version.title %>"
|
3173
|
-
elsif node_kind_of?(Version)
|
3174
|
-
"<%= #{node}.title %>"
|
3175
|
-
elsif node_kind_of?(Link)
|
3176
|
-
"<%= #{node}.name %>"
|
3177
|
-
else
|
3178
|
-
_('edit')
|
3179
|
-
end
|
3180
|
-
end
|
3181
|
-
|
3182
|
-
def get_text_for_erb(params = @params, use_blocks = true, context = :erb)
|
3183
|
-
string_context = context == :string
|
3184
|
-
if params[:attr]
|
3185
|
-
string_context ? "<%= #{node_attribute(params[:attr])} %>" : node_attribute(params[:attr])
|
3186
|
-
elsif params[:tattr]
|
3187
|
-
string_context ? "<%= _(#{node_attribute(params[:tattr])}) %>" : "_(#{node_attribute(params[:tattr])})"
|
3188
|
-
elsif params[:trans]
|
3189
|
-
string_context ? _(params[:trans]) : _(params[:trans]).inspect
|
3190
|
-
elsif params[:text]
|
3191
|
-
string_context ? params[:text] : params[:text].inspect
|
3192
|
-
elsif use_blocks && @blocks != []
|
3193
|
-
res = []
|
3194
|
-
text = ""
|
3195
|
-
static = true
|
3196
|
-
@blocks.each do |b|
|
3197
|
-
# FIXME: this is a little too hacky
|
3198
|
-
if b.kind_of?(String)
|
3199
|
-
res << b.inspect
|
3200
|
-
text << b
|
3201
|
-
elsif ['show', 'img'].include?(b.method)
|
3202
|
-
res << expand_block(b, :trans=>true)
|
3203
|
-
static = false
|
3204
|
-
elsif ['rename_asset', 'trans'].include?(b.method)
|
3205
|
-
# FIXME: if a trans contains non-static: static should become false
|
3206
|
-
res << expand_block(b).inspect
|
3207
|
-
text << expand_block(b)
|
3208
|
-
else
|
3209
|
-
# ignore
|
3210
|
-
end
|
3211
|
-
end
|
3212
|
-
if static
|
3213
|
-
# "just plain text"
|
3214
|
-
string_context ? text : text.inspect
|
3215
|
-
else
|
3216
|
-
# function(...) + "blah" + function()
|
3217
|
-
string_context ? "<%= #{res.join(' + ')} %>" : res.join(' + ')
|
3218
|
-
end
|
3219
|
-
else
|
3220
|
-
nil
|
3221
|
-
end
|
3222
|
-
end
|
3223
|
-
|
3224
|
-
def get_input_params(params = @params)
|
3225
|
-
res = {}
|
3226
|
-
if res[:name] = (params[:name] || params[:date])
|
3227
|
-
if res[:name] =~ /\A([\w_]+)\[(.*?)\]/
|
3228
|
-
attribute, sub_attr = $1, $2
|
3229
|
-
else
|
3230
|
-
attribute = res[:name]
|
3231
|
-
end
|
3232
|
-
|
3233
|
-
unless @context[:in_filter] || attribute == 's'
|
3234
|
-
if sub_attr
|
3235
|
-
res[:name] = "#{base_class.to_s.underscore}[#{attribute}][#{sub_attr}]"
|
3236
|
-
else
|
3237
|
-
res[:name] = "#{base_class.to_s.underscore}[#{attribute}]"
|
3238
|
-
end
|
3239
|
-
end
|
3240
|
-
|
3241
|
-
if sub_attr
|
3242
|
-
if (nattr = node_attribute(attribute)) != 'nil'
|
3243
|
-
nattr = "#{nattr}[#{sub_attr.inspect}]"
|
3244
|
-
end
|
3245
|
-
else
|
3246
|
-
nattr = node_attribute(attribute)
|
3247
|
-
end
|
3248
|
-
|
3249
|
-
if sub_attr && params[:type] == 'checkbox' && !params[:value]
|
3250
|
-
# Special case when we have a sub_attribute: default value for "tagged[foobar]" is "foobar"
|
3251
|
-
params[:value] = sub_attr
|
3252
|
-
end
|
3253
|
-
|
3254
|
-
if @context[:in_add]
|
3255
|
-
res[:value] = (params[:value] || params[:set_value]) ? ["'#{ helper.fquote(params[:value])}'"] : ["''"]
|
3256
|
-
elsif @context[:in_filter]
|
3257
|
-
res[:value] = attribute ? ["'<%= fquote params[#{attribute.to_sym.inspect}] %>'"] : ["''"]
|
3258
|
-
elsif params[:value]
|
3259
|
-
res[:value] = ["'#{ helper.fquote(params[:value])}'"]
|
3260
|
-
else
|
3261
|
-
if nattr != 'nil'
|
3262
|
-
res[:value] = ["'<%= fquote #{nattr} %>'"]
|
3263
|
-
else
|
3264
|
-
res[:value] = ["''"]
|
3265
|
-
end
|
3266
|
-
end
|
3267
|
-
end
|
3268
|
-
|
3269
|
-
if @context[:dom_prefix]
|
3270
|
-
res[:id] = "#{erb_dom_id}_#{attribute}"
|
3271
|
-
else
|
3272
|
-
res[:id] = params[:id] if params[:id]
|
3273
|
-
end
|
3274
|
-
|
3275
|
-
if params[:type] == 'checkbox' && nattr
|
3276
|
-
if value = params[:value]
|
3277
|
-
res[:checked] = "<%= #{nattr} == #{value.inspect} ? \" checked='checked'\" : '' %>"
|
3278
|
-
else
|
3279
|
-
res[:checked] = "<%= #{nattr}.blank? ? '' : \" checked='checked'\" %>"
|
3280
|
-
end
|
3281
|
-
end
|
3282
|
-
|
3283
|
-
[:size, :style, :class].each do |k|
|
3284
|
-
res[k] = params[k] if params[k]
|
3285
|
-
end
|
3286
|
-
|
3287
|
-
return [res, attribute]
|
3288
|
-
end
|
3289
|
-
|
3290
|
-
def get_html_params(params, tag_type)
|
3291
|
-
res = {}
|
3292
|
-
params.each do |k,v|
|
3293
|
-
next unless v
|
3294
|
-
if k.to_s =~ /\A(t?)set_(.+)$/
|
3295
|
-
key = $2
|
3296
|
-
trans = $1 == 't'
|
3297
|
-
value, static = parse_attributes_in_value(v, :erb => !trans)
|
3298
|
-
|
3299
|
-
if trans
|
3300
|
-
if static
|
3301
|
-
value = ["'#{_(value)}'"] # array so it is not escaped on render
|
3302
|
-
else
|
3303
|
-
value = ["'<%= _(\"#{value}\") %>'"] # FIXME: use dict ! array so it is not escaped on render
|
3304
|
-
end
|
3305
|
-
end
|
3306
|
-
res[key.to_sym] = value
|
3307
|
-
elsif tag_type == :link && ![:style, :class, :id, :title].include?(k)
|
3308
|
-
# bad html parameter for links (some keys for link tags are used as query parameters)
|
3309
|
-
# filter out
|
3310
|
-
else
|
3311
|
-
res[k] ||= v
|
3312
|
-
end
|
3313
|
-
end
|
3314
|
-
|
3315
|
-
if params[:anchor]
|
3316
|
-
@anchor_param = nil
|
3317
|
-
res[:name] = anchor_name(params[:anchor], node)
|
3318
|
-
end
|
3319
|
-
|
3320
|
-
res
|
3321
|
-
end
|
3322
|
-
|
3323
|
-
def get_options_for_select
|
3324
|
-
if nodes = @params[:nodes]
|
3325
|
-
# TODO: dry with r_checkbox
|
3326
|
-
if nodes =~ /^\d+\s*($|,)/
|
3327
|
-
# ids
|
3328
|
-
# TODO: optimization generate the full query instead of using secure.
|
3329
|
-
nodes = nodes.split(',').map{|v| v.to_i}
|
3330
|
-
nodes = "(secure(Node) { Node.find(:all, :conditions => 'zip IN (#{nodes.join(',')})') })"
|
3331
|
-
else
|
3332
|
-
# relation
|
3333
|
-
nodes, klass = build_finder_for(:all, nodes)
|
3334
|
-
return unless nodes
|
3335
|
-
return parser_error("invalid class (#{klass})") unless klass.ancestors.include?(Node)
|
3336
|
-
end
|
3337
|
-
set_attr = @params[:attr] || 'id'
|
3338
|
-
show_attr = @params[:show] || 'name'
|
3339
|
-
options_list = "[['','']] + (#{nodes} || []).map{|r| [#{node_attribute(show_attr, :node => 'r', :node_class => Node)}, #{node_attribute(set_attr, :node => 'r', :node_class => Node)}.to_s]}"
|
3340
|
-
elsif values = @params[:values]
|
3341
|
-
options_list = values.split(',').map(&:strip)
|
3342
|
-
|
3343
|
-
if show = @params[:show]
|
3344
|
-
show_values = show.split(',').map(&:strip)
|
3345
|
-
elsif show = @params[:tshow]
|
3346
|
-
show_values = show.split(',').map do |s|
|
3347
|
-
_(s.strip)
|
3348
|
-
end
|
3349
|
-
end
|
3350
|
-
|
3351
|
-
if show_values
|
3352
|
-
options_list.each_index do |i|
|
3353
|
-
options_list[i] = [show_values[i], options_list[i]]
|
3354
|
-
end
|
3355
|
-
end
|
3356
|
-
options_list.inspect
|
3357
|
-
end
|
3358
|
-
end
|
3359
|
-
|
3360
|
-
def parse_eval_parameter(str)
|
3361
|
-
# evaluate an expression. Can only contain vars, '(', ')', '*', '+', '/', '-', '[attr]'
|
3362
|
-
# FIXME: SECURITY (audit this)
|
3363
|
-
vars = @context[:vars] || []
|
3364
|
-
parts = str.split(/\s+/)
|
3365
|
-
res = []
|
3366
|
-
test = []
|
3367
|
-
parts.each do |p|
|
3368
|
-
if p =~ /\[([\w_]+)\]/
|
3369
|
-
test << 1
|
3370
|
-
res << (node_attribute($1) + '.to_f')
|
3371
|
-
elsif p =~ /^[a-zA-Z_]+$/
|
3372
|
-
unless vars.include?(p)
|
3373
|
-
out parser_error("var #{p.inspect} not set in eval")
|
3374
|
-
return nil
|
3375
|
-
end
|
3376
|
-
test << 1
|
3377
|
-
res << "set_#{p}.to_f"
|
3378
|
-
elsif ['(', ')', '*', '+', '/', '-'].include?(p)
|
3379
|
-
res << p
|
3380
|
-
test << p
|
3381
|
-
elsif p =~ /^[0-9\.]+$/
|
3382
|
-
res << p
|
3383
|
-
test << p
|
3384
|
-
else
|
3385
|
-
out parser_error("bad argument #{p.inspect} in eval")
|
3386
|
-
return nil
|
3387
|
-
end
|
3388
|
-
end
|
3389
|
-
begin
|
3390
|
-
begin
|
3391
|
-
eval test.join(' ')
|
3392
|
-
rescue
|
3393
|
-
# rescue evaluation error
|
3394
|
-
out parser_error("error in eval")
|
3395
|
-
return nil
|
3396
|
-
end
|
3397
|
-
"(#{res.join(' ')})"
|
3398
|
-
rescue SyntaxError => err
|
3399
|
-
# rescue compilation error
|
3400
|
-
out parser_error("compilation error in eval")
|
3401
|
-
return nil
|
3402
|
-
end
|
3403
|
-
end
|
3404
|
-
|
3405
|
-
def find_stored(klass, key)
|
3406
|
-
if "#{klass}_#{key}" == "Node_start_node"
|
3407
|
-
# main node before ajax stuff (the one in browser url)
|
3408
|
-
"start_node"
|
3409
|
-
else
|
3410
|
-
@context["#{klass}_#{key}"]
|
3411
|
-
end
|
3412
|
-
end
|
3413
|
-
|
3414
|
-
def set_stored(klass, key, obj)
|
3415
|
-
@context["#{klass}_#{key}"] = obj
|
3416
|
-
end
|
3417
|
-
|
3418
|
-
# transform a 'show' tag into an input field.
|
3419
|
-
def make_input(params = @params)
|
3420
|
-
input, attribute = get_input_params(params)
|
3421
|
-
return parser_error("missing 'name'") unless attribute
|
3422
|
-
return '' if attribute == 'parent_id' # set with 'r_form'
|
3423
|
-
return '' if ['url','path'].include?(attribute) # cannot be set with a form
|
3424
|
-
if params[:date]
|
3425
|
-
input_id = @context[:dom_prefix] ? ", :id=>\"#{dom_id}_#{attribute}\"" : ''
|
3426
|
-
return "<%= date_box('#{base_class.to_s.underscore}', #{params[:date].inspect}#{input_id}) %>"
|
3427
|
-
end
|
3428
|
-
input_id = @context[:dom_prefix] ? " id='#{erb_dom_id}_#{attribute}'" : ''
|
3429
|
-
"<input type='#{params[:type] || 'text'}'#{input_id} name='#{input[:name]}' value=#{input[:value]}/>"
|
3430
|
-
end
|
3431
|
-
|
3432
|
-
# transform a 'zazen' tag into a textarea input field.
|
3433
|
-
def make_textarea(params)
|
3434
|
-
return parser_error("missing 'name'") unless name = params[:name]
|
3435
|
-
if name =~ /\A([\w_]+)\[(.*?)\]/
|
3436
|
-
attribute = $2
|
3437
|
-
else
|
3438
|
-
attribute = name
|
3439
|
-
name = "#{base_class.to_s.underscore}[#{attribute}]"
|
3440
|
-
end
|
3441
|
-
return '' if attribute == 'parent_id' # set with 'r_form'
|
3442
|
-
|
3443
|
-
if @blocks == [] || @blocks == ['']
|
3444
|
-
if @context[:in_add]
|
3445
|
-
value = ''
|
3446
|
-
else
|
3447
|
-
value = attribute ? "<%= #{node_attribute(attribute)} %>" : ""
|
3448
|
-
end
|
3449
|
-
else
|
3450
|
-
value = expand_with
|
3451
|
-
end
|
3452
|
-
html_id = @context[:dom_prefix] ? " id='#{erb_dom_id}_#{attribute}'" : ''
|
3453
|
-
"<textarea#{html_id} name='#{name}'>#{value}</textarea>"
|
3454
|
-
end
|
3455
|
-
|
3456
|
-
def default_focus_field
|
3457
|
-
if (input_fields = descendants('input')) != []
|
3458
|
-
field = input_fields.first.params[:name]
|
3459
|
-
elsif (show_fields = descendants('show')) != []
|
3460
|
-
field = show_fields.first.params[:attr]
|
3461
|
-
elsif node_kind_of?(Node)
|
3462
|
-
field = 'v_title'
|
3463
|
-
else
|
3464
|
-
field = 'text'
|
3465
|
-
end
|
3466
|
-
end
|
3467
|
-
|
3468
|
-
# Returns true if a form/edit needs to keep track of link_id (l_status or l_comment used).
|
3469
|
-
def need_link_id
|
3470
|
-
if (input_fields = (descendants('input') + descendants('select'))) != []
|
3471
|
-
input_fields.each do |f|
|
3472
|
-
return true if f.params[:name] =~ /\Al_/
|
3473
|
-
end
|
3474
|
-
elsif (show_fields = descendants('show')) != []
|
3475
|
-
show_fields.each do |f|
|
3476
|
-
return true if f.params[:attr] =~ /\Al_/
|
3477
|
-
end
|
3478
|
-
end
|
3479
|
-
return false
|
3480
|
-
end
|
3481
|
-
|
3482
|
-
def start_node_s_param(type = :input)
|
3483
|
-
if type == :input
|
3484
|
-
"<input type='hidden' name='s' value='<%= params[:s] || @node[:zip] %>'/>"
|
3485
|
-
elsif type == :erb
|
3486
|
-
"s=<%= params[:s] || @node[:zip] %>"
|
3487
|
-
elsif type == :value
|
3488
|
-
"<%= params[:s] || @node[:zip] %>"
|
3489
|
-
else
|
3490
|
-
"s=\#{params[:s] || @node[:zip]}"
|
3491
|
-
end
|
3492
|
-
end
|
3493
|
-
|
3494
|
-
def parser_error(message, tag=@method)
|
3495
|
-
"<span class='parser_error'>[#{tag}] #{message}</span>"
|
3496
|
-
end
|
3497
|
-
|
3498
|
-
# Used by [each] and [draggable] to insert 'id' and drag handle span
|
3499
|
-
def set_drag_handle_and_id(text, params, id_hash)
|
3500
|
-
res, drag_handle = text, nil
|
3501
|
-
if params[:drag_handle]
|
3502
|
-
drag_handle = params[:drag_handle] == 'true' ? 'drag_handle' : params[:drag_handle]
|
3503
|
-
if text =~ /class\s*=\s*['"]#{drag_handle}/
|
3504
|
-
# nothing to do
|
3505
|
-
insert = ''
|
3506
|
-
else
|
3507
|
-
insert = "<span class='#{drag_handle}'> </span>"
|
3508
|
-
end
|
3509
|
-
else
|
3510
|
-
insert = ''
|
3511
|
-
end
|
3512
|
-
|
3513
|
-
res = insert + text
|
3514
|
-
|
3515
|
-
if id_hash
|
3516
|
-
@html_tag ||= 'div'
|
3517
|
-
@html_tag_params.merge!(id_hash)
|
3518
|
-
end
|
3519
|
-
|
3520
|
-
[res, drag_handle]
|
3521
|
-
end
|
3522
|
-
|
3523
|
-
def expand_with(acontext={})
|
3524
|
-
# set variables
|
3525
|
-
context = nil
|
3526
|
-
pre = ''
|
3527
|
-
@blocks.each do |block|
|
3528
|
-
next if block.kind_of?(String) || block.method != 'set'
|
3529
|
-
@context[:vars] ||= []
|
3530
|
-
context ||= @context.merge(acontext).merge(:set => true)
|
3531
|
-
pre << expand_block(block, context)
|
3532
|
-
@context[:vars] << block.params[:var]
|
3533
|
-
end
|
3534
|
-
|
3535
|
-
pre + super
|
3536
|
-
end
|
3537
|
-
|
3538
|
-
def auto_publish_param(in_string = false)
|
3539
|
-
if in_string
|
3540
|
-
['true','force'].include?(@params[:publish]) ? "&publish=#{@params[:publish]}" : ''
|
3541
|
-
else
|
3542
|
-
@params[:publish]
|
3543
|
-
end
|
3544
|
-
end
|
3545
|
-
|
3546
|
-
# This is used by zafu and it's a mess.
|
3547
|
-
# ref_date can be a string ('2005-05-03') or ruby ('Time.now'). It should not come uncleaned from evil web.
|
3548
|
-
def date_condition(date_cond, field, ref_date='today')
|
3549
|
-
if date_cond == 'today' || ref_date == 'today'
|
3550
|
-
ref_date = Zena::Db::NOW
|
3551
|
-
elsif ref_date =~ /(\d{4}-\d{1,2}-\d{1,2}( \d{1,2}:\d{1,2}(:\d{1,2})?)?)/
|
3552
|
-
ref_date = "'#{$1}'"
|
3553
|
-
elsif ref_date =~ /\A"/
|
3554
|
-
ref_date = "'\#{format_date(#{ref_date})}'"
|
3555
|
-
else
|
3556
|
-
ref_date = "'\#{#{ref_date}.strftime('%Y-%m-%d %H:%M:%S')}'"
|
3557
|
-
end
|
3558
|
-
Zena::Db.date_condition(date_cond, field, ref_date)
|
3559
|
-
end
|
3560
|
-
end # ZenaTags
|
3561
|
-
end # Parser
|
3562
|
-
end # Zena
|