zena 1.2.2 → 1.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +25 -0
- data/app/controllers/documents_controller.rb +3 -25
- data/app/controllers/nodes_controller.rb +34 -24
- data/app/controllers/user_sessions_controller.rb +5 -4
- data/app/controllers/versions_controller.rb +44 -17
- data/app/models/acl.rb +2 -7
- data/app/models/group.rb +6 -2
- data/app/models/link.rb +14 -0
- data/app/models/node.rb +2 -2
- data/app/models/site.rb +13 -4
- data/app/models/text_document.rb +1 -1
- data/app/models/user.rb +11 -2
- data/app/models/virtual_class.rb +1 -1
- data/app/views/groups/_form.rhtml +6 -6
- data/app/views/nodes/render_error.rhtml +15 -0
- data/app/views/templates/document_create_tabs/_file.rhtml +1 -1
- data/app/views/templates/document_create_tabs/_import.rhtml +1 -1
- data/app/views/templates/document_create_tabs/_template.rhtml +1 -1
- data/app/views/templates/document_create_tabs/_text_document.rhtml +1 -1
- data/app/views/templates/edit_tabs/_title.rhtml +1 -1
- data/app/views/zafu/default/Node-admin.zafu +1 -1
- data/bricks/acls/zena/test/integration/acl_integration_test.rb +2 -2
- data/bricks/acls/zena/test/unit/acl_test.rb +2 -1
- data/bricks/fs_skin/zena/migrate/20110702010330_add_fs_skin_to_idx_templates.rb +1 -0
- data/bricks/fs_skin/zena/skins/blog/img/style.css +4 -4
- data/bricks/grid/lib/bricks/grid.rb +9 -3
- data/bricks/passenger/zena/deploy.rb +2 -1
- data/bricks/pdf/lib/bricks/pdf.rb +1 -1
- data/bricks/tags/zena/test/zafu/tags.yml +5 -1
- data/bricks/zena/zena/migrate/20120904071601_change_link_status_to_float.rb +13 -0
- data/config/bricks.yml +10 -10
- data/config/deploy.rb +1 -5
- data/config/gems.yml +2 -2
- data/db/init/base/skins/default/Node.zafu +7 -3
- data/db/init/base/skins/default/notes.zafu +3 -1
- data/lib/zafu/all.rb +0 -9
- data/lib/zafu/compiler.rb +0 -4
- data/lib/zafu/controller_methods.rb +0 -2
- data/lib/zafu/handler.rb +0 -5
- data/lib/zafu/markup.rb +4 -6
- data/lib/zafu/ordered_hash.rb +3 -2
- data/lib/zafu/parsing_rules.rb +1 -3
- data/lib/zafu/process/ajax.rb +4 -2
- data/lib/zafu/process/context.rb +34 -4
- data/lib/zafu/process/forms.rb +2 -2
- data/lib/zafu/process/ruby_less_processing.rb +5 -10
- data/lib/zafu/template.rb +0 -2
- data/lib/zafu/test_helper.rb +0 -2
- data/lib/zafu/view_methods.rb +0 -1
- data/lib/zafu.rb +1 -1
- data/lib/zena/acts/secure_node.rb +5 -4
- data/lib/zena/console.rb +19 -17
- data/lib/zena/core_ext/string.rb +3 -2
- data/lib/zena/deploy/app_init.rhtml +6 -1
- data/lib/zena/deploy/httpd.rhtml +16 -13
- data/lib/zena/deploy/stats.vhost.rhtml +1 -1
- data/lib/zena/deploy/vhost.rhtml +31 -11
- data/lib/zena/deploy/vhost_ssl_redir.rhtml +12 -0
- data/lib/zena/deploy/vhost_www.rhtml +1 -1
- data/lib/zena/deploy.rb +55 -11
- data/lib/zena/info.rb +1 -1
- data/lib/zena/parser/zazen_rules.rb +18 -9
- data/lib/zena/routes.rb +1 -3
- data/lib/zena/site_worker.rb +8 -1
- data/lib/zena/use/ajax.rb +29 -3
- data/lib/zena/use/ancestry.rb +2 -1
- data/lib/zena/use/authlogic.rb +12 -18
- data/lib/zena/use/context.rb +1 -1
- data/lib/zena/use/dates.rb +28 -18
- data/lib/zena/use/display.rb +49 -7
- data/lib/zena/use/forms.rb +51 -18
- data/lib/zena/use/html_tags.rb +6 -6
- data/lib/zena/use/i18n.rb +13 -4
- data/lib/zena/use/image_builder.rb +2 -0
- data/lib/zena/use/query_builder.rb +39 -14
- data/lib/zena/use/query_link.rb +57 -0
- data/lib/zena/use/query_node.rb +68 -32
- data/lib/zena/use/relations.rb +25 -15
- data/lib/zena/use/rendering.rb +66 -15
- data/lib/zena/use/upload.rb +34 -5
- data/lib/zena/use/urls.rb +28 -25
- data/lib/zena/use/version_hash.rb +14 -2
- data/lib/zena/use/zafu_safe_definitions.rb +72 -3
- data/lib/zena/use/zazen.rb +16 -4
- data/lib/zena.rb +1 -0
- data/public/javascripts/grid.js +213 -64
- data/public/javascripts/raphael.js +10 -0
- data/public/javascripts/zena.js +146 -22
- data/public/stylesheets/reset.css +12 -12
- data/public/stylesheets/zena.css +1 -1
- data/test/custom_queries/complex.host.yml +19 -0
- data/test/fixtures/files/TestNode.zafu +40 -4
- data/test/functional/nodes_controller_test.rb +84 -39
- data/test/functional/versions_controller_test.rb +2 -2
- data/test/integration/navigation_test.rb +61 -35
- data/test/integration/query_node/basic.yml +7 -7
- data/test/integration/query_node/comments.yml +1 -1
- data/test/integration/query_node/complex.yml +3 -3
- data/test/integration/query_node/filters.yml +32 -8
- data/test/integration/query_node/idx_key_value.yml +10 -10
- data/test/integration/query_node/idx_scope.yml +7 -7
- data/test/integration/query_node/relations.yml +4 -4
- data/test/integration/zafu_compiler/ajax.yml +19 -11
- data/test/integration/zafu_compiler/apphelper.yml +1 -1
- data/test/integration/zafu_compiler/asset.yml +2 -2
- data/test/integration/zafu_compiler/comments.yml +1 -1
- data/test/integration/zafu_compiler/dates.yml +1 -1
- data/test/integration/zafu_compiler/display.yml +49 -21
- data/test/integration/zafu_compiler/eval.yml +4 -4
- data/test/integration/zafu_compiler/forms.yml +25 -11
- data/test/integration/zafu_compiler/i18n.yml +5 -0
- data/test/integration/zafu_compiler/meta.yml +3 -3
- data/test/integration/zafu_compiler/query.yml +27 -9
- data/test/integration/zafu_compiler/relations.yml +9 -9
- data/test/integration/zafu_compiler/roles.yml +6 -6
- data/test/integration/zafu_compiler/rubyless.yml +7 -2
- data/test/integration/zafu_compiler/safe_definitions.yml +33 -4
- data/test/integration/zafu_compiler/security.yml +46 -1
- data/test/integration/zafu_compiler/urls.yml +28 -13
- data/test/integration/zafu_compiler/user.yml +12 -7
- data/test/integration/zafu_compiler/zafu_attributes.yml +1 -1
- data/test/integration/zafu_compiler/zazen.yml +5 -5
- data/test/integration/zafu_compiler_test.rb +18 -0
- data/test/selenium/Filter/filter3.rsel +20 -0
- data/test/selenium/Filter/filter4.rsel +20 -0
- data/test/sites/zena/versions.yml +2 -0
- data/test/unit/exif_data_test.rb +6 -1
- data/test/unit/group_test.rb +18 -3
- data/test/unit/node_test.rb +0 -7
- data/test/unit/project_test.rb +4 -0
- data/test/unit/relation_proxy_test.rb +2 -2
- data/test/unit/remote_test.rb +0 -9
- data/test/unit/role_test.rb +1 -1
- data/test/unit/string_hash_test.rb +1 -1
- data/test/unit/text_document_test.rb +13 -13
- data/test/unit/zena/use/html_tags_test.rb +6 -6
- data/test/unit/zena/use/rendering_test.rb +20 -10
- data/test/unit/zena/use/urls_test.rb +21 -18
- data/test/unit/zena/use/zafu_template_test.rb +0 -5
- data/test/unit/zena/use/zazen_test.rb +25 -25
- data/zena.gemspec +63 -57
- metadata +136 -130
- data/test/functional/nodes_controller_commit_test.rb +0 -67
data/lib/zena/use/display.rb
CHANGED
|
@@ -13,6 +13,8 @@ module Zena
|
|
|
13
13
|
|
|
14
14
|
module ImageTags
|
|
15
15
|
include Common
|
|
16
|
+
IMG_TAG_EXTRA_RE = %r{UUID|(PATH)_([a-z]+)\.([a-z]+)}
|
|
17
|
+
IMG_TAG_EXTRA_JS = %r{\[JS\](.*?)\[/JS\]}
|
|
16
18
|
|
|
17
19
|
# This is used by _crop.rhtml
|
|
18
20
|
def crop_formats(obj)
|
|
@@ -48,7 +50,7 @@ module Zena
|
|
|
48
50
|
return img_tag(icon, opts.merge(:alt_src => nil))
|
|
49
51
|
end
|
|
50
52
|
end
|
|
51
|
-
|
|
53
|
+
|
|
52
54
|
# 3. generic icon
|
|
53
55
|
res ||= generic_img_tag(obj, opts)
|
|
54
56
|
|
|
@@ -67,6 +69,30 @@ module Zena
|
|
|
67
69
|
# <img> tag definition to show an Image / mp3 document
|
|
68
70
|
# FIXME: this should live inside zafu
|
|
69
71
|
def asset_img_tag(obj, opts)
|
|
72
|
+
if img_tag = obj.prop["img_tag_#{opts[:mode] || 'std'}"]
|
|
73
|
+
# Hand made image tag
|
|
74
|
+
if img_tag.kind_of?(String)
|
|
75
|
+
# We use code to make it raw.
|
|
76
|
+
uuid = "img#{UUIDTools::UUID.random_create.to_s.gsub('-','')[0..6]}"
|
|
77
|
+
tag = img_tag.gsub(IMG_TAG_EXTRA_RE) do
|
|
78
|
+
if $& == 'UUID'
|
|
79
|
+
uuid
|
|
80
|
+
elsif $1 == 'PATH'
|
|
81
|
+
zen_path(obj, :mode => $2, :format => $3)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
tag.gsub!(IMG_TAG_EXTRA_JS) do
|
|
85
|
+
self.js_data << $1
|
|
86
|
+
''
|
|
87
|
+
end
|
|
88
|
+
return raw_content(tag)
|
|
89
|
+
end
|
|
90
|
+
elsif img_tag = obj.prop["img_tag"]
|
|
91
|
+
if img_tag.kind_of?(Hash) && img_tag = img_tag[opts[:mode] || 'std']
|
|
92
|
+
return raw_content(img_tag.gsub('UUID', "img#{UUIDTools::UUID.random_create.to_s.gsub('-','')[0..6]}"))
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
70
96
|
if obj.kind_of?(Image)
|
|
71
97
|
res = {}
|
|
72
98
|
format = Iformat[opts[:mode]] || Iformat['std']
|
|
@@ -208,7 +234,7 @@ module Zena
|
|
|
208
234
|
include ImageTags
|
|
209
235
|
include RubyLess
|
|
210
236
|
safe_method [:sprintf, String, Number] => {:class => String, :method => 'sprintf'}
|
|
211
|
-
safe_method [:search_box, {:ajax => String, :type => String}] => String
|
|
237
|
+
safe_method [:search_box, {:ajax => String, :type => String}] => {:class => String, :method => 'search_box', :html_safe => true}
|
|
212
238
|
safe_context [:admin_links, {:list => String}] => [String]
|
|
213
239
|
|
|
214
240
|
# Return sprintf formated entry. Return '' for values eq to zero.
|
|
@@ -432,6 +458,7 @@ module Zena
|
|
|
432
458
|
:class => String,
|
|
433
459
|
:method => 'zazen',
|
|
434
460
|
:accept_nil => true,
|
|
461
|
+
:html_safe => true,
|
|
435
462
|
:append_hash => {:node => ::RubyLess::TypedString.new(node.to_s, :class => node.klass)}
|
|
436
463
|
}
|
|
437
464
|
else
|
|
@@ -488,6 +515,7 @@ module Zena
|
|
|
488
515
|
end
|
|
489
516
|
|
|
490
517
|
def extract_label(res, attribute)
|
|
518
|
+
return res if @params[:type] == 'hidden'
|
|
491
519
|
attribute ||= @params[:param]
|
|
492
520
|
if (label = param(:label) || param(:tlabel)) && attribute
|
|
493
521
|
case label
|
|
@@ -517,13 +545,13 @@ module Zena
|
|
|
517
545
|
|
|
518
546
|
# ??? <r:h do='foasfa'/> ?
|
|
519
547
|
# def r_h
|
|
520
|
-
# out "<%=
|
|
548
|
+
# out "<%=h ??? %>"
|
|
521
549
|
# end
|
|
522
550
|
|
|
523
551
|
# Insert javascript asset tags
|
|
524
552
|
def r_javascripts
|
|
525
553
|
if @params[:list] == 'all' || @params[:list].nil?
|
|
526
|
-
list = %w{ prototype effects dragdrop window zena grid }
|
|
554
|
+
list = %w{ prototype effects dragdrop window zena grid upload-progress }
|
|
527
555
|
else
|
|
528
556
|
list = @params[:list].split(',').map{|e| e.strip}
|
|
529
557
|
end
|
|
@@ -570,7 +598,7 @@ module Zena
|
|
|
570
598
|
# Insert stylesheet asset tags
|
|
571
599
|
def r_stylesheets
|
|
572
600
|
if @params[:list] == 'all' || @params[:list].nil?
|
|
573
|
-
list = %w{ reset window zena code grid }
|
|
601
|
+
list = %w{ reset window zena code grid upload-progress }
|
|
574
602
|
else
|
|
575
603
|
list = @params[:list].split(',').map{|e| e.strip}
|
|
576
604
|
end
|
|
@@ -698,10 +726,24 @@ module Zena
|
|
|
698
726
|
|
|
699
727
|
# Also used by rubyless_expand
|
|
700
728
|
def show_string(method)
|
|
701
|
-
if
|
|
729
|
+
if method.kind_of?(RubyLess::TypedString)
|
|
730
|
+
if lit = method.literal
|
|
731
|
+
if method.opts[:html_safe]
|
|
732
|
+
lit
|
|
733
|
+
elsif param(:h) == 'false'
|
|
734
|
+
erb_escape(lit)
|
|
735
|
+
else
|
|
736
|
+
::ERB::Util.html_escape(lit)
|
|
737
|
+
end
|
|
738
|
+
elsif param(:h) == 'false' || method.opts[:html_safe]
|
|
739
|
+
"<%= #{method} %>"
|
|
740
|
+
else
|
|
741
|
+
"<%=h #{method} %>"
|
|
742
|
+
end
|
|
743
|
+
elsif param(:h) == 'false'
|
|
702
744
|
"<%= #{method} %>"
|
|
703
745
|
else
|
|
704
|
-
"<%=
|
|
746
|
+
"<%=h #{method} %>"
|
|
705
747
|
end
|
|
706
748
|
end
|
|
707
749
|
|
data/lib/zena/use/forms.rb
CHANGED
|
@@ -238,8 +238,16 @@ module Zena
|
|
|
238
238
|
error_messages = r_errors + "\n"
|
|
239
239
|
end
|
|
240
240
|
|
|
241
|
-
|
|
242
|
-
|
|
241
|
+
html_id = "#{node.dom_prefix}_form_t".inspect
|
|
242
|
+
if descendant('upload_field')
|
|
243
|
+
uuid = UUIDTools::UUID.random_create.to_s.gsub('-','')
|
|
244
|
+
set_context_var('upload', 'uuid', uuid)
|
|
245
|
+
upload_html = ", :multipart => true, :onsubmit => %Q{submitUploadForm(#{html_id}, '#{uuid}');}"
|
|
246
|
+
upload_url = "'#{Zena::Use::Upload::UPLOAD_KEY}' => '#{uuid}'"
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
opts[:form_tag] = %Q{
|
|
250
|
+
<% form_for(:#{node.form_name}, #{node}, :url => #{node}.new_record? ? #{node.form_name.pluralize}_path(#{upload_url}) : #{node.form_name}_path(#{node}.zip#{upload_url ? ", #{upload_url}" : ""}), :html => {:method => #{node}.new_record? ? :post : :put, :id => #{html_id}#{upload_html}}) do |f| %>
|
|
243
251
|
#{error_messages}}
|
|
244
252
|
end
|
|
245
253
|
|
|
@@ -247,6 +255,8 @@ module Zena
|
|
|
247
255
|
end
|
|
248
256
|
|
|
249
257
|
def form_hidden_fields(opts)
|
|
258
|
+
dom_name = node.dom_prefix || dom_name
|
|
259
|
+
|
|
250
260
|
hidden_fields = super
|
|
251
261
|
add_params = @context[:add] ? @context[:add].params : {}
|
|
252
262
|
set_fields = []
|
|
@@ -317,15 +327,17 @@ module Zena
|
|
|
317
327
|
break
|
|
318
328
|
end
|
|
319
329
|
end
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
else
|
|
330
|
+
|
|
331
|
+
if params[:done]
|
|
332
|
+
if params[:done] == 'focus'
|
|
324
333
|
hidden_fields['done'] = "'$(\"#{erb_dom_id}_form_t\").focusFirstElement();'"
|
|
334
|
+
else
|
|
335
|
+
done = RubyLess.translate_string(self, params[:done])
|
|
325
336
|
end
|
|
326
|
-
elsif params[:
|
|
327
|
-
done =
|
|
337
|
+
elsif params[:focus]
|
|
338
|
+
hidden_fields['done'] = "'$(\"#{erb_dom_id}_#{params[:focus]}\").focus();'"
|
|
328
339
|
end
|
|
340
|
+
|
|
329
341
|
else
|
|
330
342
|
# ajax form, not in 'add'
|
|
331
343
|
done = RubyLess.translate_string(self, @params[:done])
|
|
@@ -338,6 +350,13 @@ module Zena
|
|
|
338
350
|
end
|
|
339
351
|
hidden_fields['done'] = done
|
|
340
352
|
end
|
|
353
|
+
elsif upd = @params.delete(:preview)
|
|
354
|
+
hidden_fields['t_url'] = template_url(upd)
|
|
355
|
+
hidden_fields['dom_id'] = upd
|
|
356
|
+
hidden_fields['s'] = "<%= start_node_zip %>"
|
|
357
|
+
loading = @params[:loading]
|
|
358
|
+
loading = 'Zena.loading' if loading == 'true'
|
|
359
|
+
out "<% filter_form(#{node}, \"#{dom_name}_form_t\", #{loading.inspect}, '#{upd}') %>"
|
|
341
360
|
else
|
|
342
361
|
# no ajax
|
|
343
362
|
cancel = "" # link to normal node ?
|
|
@@ -398,6 +417,10 @@ module Zena
|
|
|
398
417
|
|
|
399
418
|
hidden_fields
|
|
400
419
|
end
|
|
420
|
+
|
|
421
|
+
def r_upload_field
|
|
422
|
+
"<%= upload_field(:uuid => #{get_context_var('upload', 'uuid').inspect}, :dom => #{node.dom_prefix.inspect}) %>"
|
|
423
|
+
end
|
|
401
424
|
|
|
402
425
|
def r_textarea
|
|
403
426
|
html_attributes, attribute = get_input_params()
|
|
@@ -436,9 +459,15 @@ module Zena
|
|
|
436
459
|
attribute = param
|
|
437
460
|
else
|
|
438
461
|
return parser_error("missing name") unless attribute
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
462
|
+
# {:value=>"<%= fquote((@node.prop['settings'] ? @node.prop['settings'][\"foo\"] : nil)) %>", :name=>"node[settings][foo]"}
|
|
463
|
+
# "settings_foo"
|
|
464
|
+
|
|
465
|
+
|
|
466
|
+
if selected = @params[:value] || @params[:selected]
|
|
467
|
+
selected = ::RubyLess.translate(self, selected)
|
|
468
|
+
unless selected.klass <= String
|
|
469
|
+
selected = "#{selected}.to_s"
|
|
470
|
+
end
|
|
442
471
|
elsif @context[:in_filter]
|
|
443
472
|
selected = "param_value(#{attribute.inspect}).to_s"
|
|
444
473
|
elsif %w{parent_id}.include?(attribute)
|
|
@@ -448,18 +477,21 @@ module Zena
|
|
|
448
477
|
elsif attribute =~ /^(.*)_id$/
|
|
449
478
|
# relation
|
|
450
479
|
selected = "#{node}.rel[#{$1.inspect}].other_zip.to_s"
|
|
451
|
-
elsif
|
|
452
|
-
selected
|
|
480
|
+
elsif selected = html_attributes[:value]
|
|
481
|
+
if selected =~ /\A<%= .*?\((.+)\)\s*%>/
|
|
482
|
+
# remove <%= %>
|
|
483
|
+
selected = "#{$1}.to_s"
|
|
484
|
+
else
|
|
485
|
+
selected = selected.inspect
|
|
486
|
+
end
|
|
453
487
|
else
|
|
454
|
-
#
|
|
455
|
-
selected = "
|
|
488
|
+
# FIXME: This would not work for a [asdf][asdf] hash property type...
|
|
489
|
+
selected = ::RubyLess.translate(self, "this.#{attribute}")
|
|
456
490
|
end
|
|
457
491
|
end
|
|
458
492
|
|
|
459
493
|
if @context[:in_filter] || @params[:param]
|
|
460
494
|
html_attributes[:name] = attribute
|
|
461
|
-
else
|
|
462
|
-
html_attributes[:name] = "#{node.form_name}[#{attribute}]"
|
|
463
495
|
end
|
|
464
496
|
html_attributes.delete(:value)
|
|
465
497
|
select_tag = Zafu::Markup.new('select', html_attributes)
|
|
@@ -480,7 +512,7 @@ module Zena
|
|
|
480
512
|
end
|
|
481
513
|
end
|
|
482
514
|
end
|
|
483
|
-
select_tag.wrap "<%= options_for_select(#{options_list.inspect},
|
|
515
|
+
select_tag.wrap "<%= options_for_select(#{options_list.inspect}, #{selected}) %>"
|
|
484
516
|
elsif @params[:type] == 'time_zone'
|
|
485
517
|
# <r:select name='d_tz' type='time_zone'/>
|
|
486
518
|
select_tag.wrap "<%= options_for_select(TZInfo::Timezone.all_identifiers, #{selected}) %>"
|
|
@@ -802,6 +834,7 @@ module Zena
|
|
|
802
834
|
show_values = translate_list(show)
|
|
803
835
|
else
|
|
804
836
|
tprefix = @params[:tprefix] || @params[:name] || @params[:param]
|
|
837
|
+
tprefix = tprefix.gsub('[','_').gsub(']','')
|
|
805
838
|
if tprefix == 'false'
|
|
806
839
|
tprefix = ''
|
|
807
840
|
else
|
data/lib/zena/use/html_tags.rb
CHANGED
|
@@ -6,9 +6,9 @@ module Zena
|
|
|
6
6
|
|
|
7
7
|
module FormTags
|
|
8
8
|
#TODO: test
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
# Return the list of groups from the visitor for forms
|
|
10
|
+
def form_groups
|
|
11
|
+
@form_groups ||= Group.find(:all, :select=>'id, name', :conditions=>"id IN (#{visitor.group_ids.join(',')})", :order=>"name ASC").collect {|p| [p.name, p.id]}
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
#TODO: test
|
|
@@ -163,7 +163,7 @@ module Zena
|
|
|
163
163
|
include LinkTags
|
|
164
164
|
include RubyLess
|
|
165
165
|
|
|
166
|
-
safe_method [:flash_messages] => String
|
|
166
|
+
safe_method [:flash_messages] => {:class => String, :method => 'flash_messages', :html_safe => true}
|
|
167
167
|
# TODO: replace 'flash_messages' with a FlashHash context or a list
|
|
168
168
|
# of Flash messages.
|
|
169
169
|
|
|
@@ -171,11 +171,11 @@ module Zena
|
|
|
171
171
|
type = opts[:show] || 'both'
|
|
172
172
|
|
|
173
173
|
if (type == 'notice' || type == 'both') && flash[:notice]
|
|
174
|
-
notice = "<div class='auto_fade notice' onclick='new Effect.Fade(this)'>#{flash[:notice]}</div>"
|
|
174
|
+
notice = "<div class='auto_fade notice' onclick='new Effect.Fade(this)'>#{::ERB::Util.html_escape(flash[:notice])}</div>"
|
|
175
175
|
end
|
|
176
176
|
|
|
177
177
|
if (type == 'error' || type == 'both') && flash[:error ]
|
|
178
|
-
error = "<div class='error' onclick='new Effect.Fade(this)'>#{flash[:error]}</div>"
|
|
178
|
+
error = "<div class='error' onclick='new Effect.Fade(this)'>#{::ERB::Util.html_escape(flash[:error])}</div>"
|
|
179
179
|
end
|
|
180
180
|
|
|
181
181
|
if page = opts[:page]
|
data/lib/zena/use/i18n.rb
CHANGED
|
@@ -14,7 +14,7 @@ module Zena
|
|
|
14
14
|
include RubyLess
|
|
15
15
|
|
|
16
16
|
# never returns nil
|
|
17
|
-
safe_method [:get, String] => {:class => String, :accept_nil => true}
|
|
17
|
+
safe_method [:get, String] => {:class => String, :accept_nil => true, :html_safe => true}
|
|
18
18
|
|
|
19
19
|
def initialize(node_id, static = nil)
|
|
20
20
|
@node_id = node_id
|
|
@@ -27,6 +27,7 @@ module Zena
|
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
def get_without_loading(key, use_global = true)
|
|
30
|
+
# SECURITY: We consider all strings in dictionaries as SAFE.
|
|
30
31
|
@dict[key] || (use_global && ApplicationController.send(:_, key))
|
|
31
32
|
end
|
|
32
33
|
|
|
@@ -205,7 +206,7 @@ module Zena
|
|
|
205
206
|
module ViewMethods
|
|
206
207
|
include RubyLess
|
|
207
208
|
|
|
208
|
-
safe_method [:lang_links, {:wrap => String, :join => String}] => String
|
|
209
|
+
safe_method [:lang_links, {:wrap => String, :join => String}] => {:class => String, :method => 'lang_links', :html_safe => true}
|
|
209
210
|
|
|
210
211
|
def self.included(base)
|
|
211
212
|
base.send(:alias_method_chain, :will_paginate, :i18n) if base.respond_to?(:will_paginate)
|
|
@@ -349,13 +350,21 @@ module Zena
|
|
|
349
350
|
{ :class => String,
|
|
350
351
|
:method => "#{dict}.get",
|
|
351
352
|
:accept_nil => true,
|
|
352
|
-
:
|
|
353
|
+
:html_safe => true,
|
|
354
|
+
:pre_processor => Proc.new {|this, str|
|
|
355
|
+
t = erb_escape(trans(str))
|
|
356
|
+
RubyLess::TypedString.new(t.inspect, :html_safe => true, :literal => t, :class => String)
|
|
357
|
+
}
|
|
353
358
|
}
|
|
354
359
|
else
|
|
355
360
|
{ :class => String,
|
|
356
361
|
:method => 'trans',
|
|
357
362
|
:accept_nil => true,
|
|
358
|
-
:
|
|
363
|
+
:html_safe => true,
|
|
364
|
+
:pre_processor => Proc.new {|this, str|
|
|
365
|
+
t = erb_escape(trans(str))
|
|
366
|
+
RubyLess::TypedString.new(t.inspect, :html_safe => true, :literal => t, :class => String)
|
|
367
|
+
}
|
|
359
368
|
}
|
|
360
369
|
end
|
|
361
370
|
end
|
|
@@ -4,8 +4,12 @@ module Zena
|
|
|
4
4
|
DATE_FIELD_REGEXP = %r{\d+[\.-/]\d+[\.-/]\d+}
|
|
5
5
|
module ViewMethods
|
|
6
6
|
include RubyLess
|
|
7
|
+
# Pseudo string comming from params.
|
|
7
8
|
safe_method [:query_parse, String] => {:class => String, :accept_nil => true}
|
|
8
|
-
safe_method :
|
|
9
|
+
safe_method [:query_parse, Hash] => {:class => String, :accept_nil => true}
|
|
10
|
+
safe_method [:query_parse, String, Hash] => {:class => String, :accept_nil => true}
|
|
11
|
+
|
|
12
|
+
safe_method :query_errors => {:class => String, :nil => true, :html_safe => true}
|
|
9
13
|
|
|
10
14
|
def find_node_by_zip(zip)
|
|
11
15
|
return nil unless zip
|
|
@@ -17,7 +21,7 @@ module Zena
|
|
|
17
21
|
end
|
|
18
22
|
|
|
19
23
|
def query(class_name, node_name, pseudo_sql, opts = {})
|
|
20
|
-
type = opts[:type] || :find
|
|
24
|
+
type = opts[:type] || (opts[:find] == :count ? :count : :find)
|
|
21
25
|
@query_errors = nil
|
|
22
26
|
if klass = VirtualClass[class_name]
|
|
23
27
|
begin
|
|
@@ -28,13 +32,16 @@ module Zena
|
|
|
28
32
|
# mixed in and strangely RubyLess cannot access the helpers from 'self'.
|
|
29
33
|
:rubyless_helper => zafu_helper.helpers
|
|
30
34
|
)
|
|
35
|
+
|
|
36
|
+
# Node.logger.warn eval(query.to_s(type == :count ? :count : :find), opts[:binding] || binding)
|
|
37
|
+
|
|
31
38
|
if type == :count
|
|
32
39
|
return klass.do_find(:count, eval(query.to_s(:count), opts[:binding] || binding))
|
|
33
40
|
else
|
|
34
41
|
return klass.do_find(opts[:find] || :all, eval(query.to_s, opts[:binding] || binding))
|
|
35
42
|
end
|
|
36
43
|
rescue ::QueryBuilder::Error => err
|
|
37
|
-
@query_errors = "<span class='query'>#{pseudo_sql}</span> <span class='error'>#{err}</span>"
|
|
44
|
+
@query_errors = "<span class='query'>#{::ERB::Util.html_escape(pseudo_sql)}</span> <span class='error'>#{::ERB::Util.html_escape(err)}</span>"
|
|
38
45
|
end
|
|
39
46
|
end
|
|
40
47
|
# error
|
|
@@ -43,13 +50,15 @@ module Zena
|
|
|
43
50
|
|
|
44
51
|
# Takes a hash of parameters and builds query arguments for SQLiss
|
|
45
52
|
# the query ends up like ' AND param_name = "foo" AND param_name > 35'...
|
|
46
|
-
def query_parse(params)
|
|
53
|
+
def query_parse(params, opts = {})
|
|
54
|
+
ignore_params = (opts[:ignore] || '').split(',').map(&:strip)
|
|
47
55
|
params ||= {}
|
|
48
56
|
res = []
|
|
49
57
|
if params.kind_of?(String)
|
|
50
58
|
return params
|
|
51
59
|
elsif params.kind_of?(Hash)
|
|
52
60
|
params.each do |k,v|
|
|
61
|
+
next if ignore_params.include?(k.to_s)
|
|
53
62
|
clause = query_build_clause(k,v)
|
|
54
63
|
res << clause unless clause.blank?
|
|
55
64
|
end
|
|
@@ -77,7 +86,6 @@ module Zena
|
|
|
77
86
|
end
|
|
78
87
|
|
|
79
88
|
if arg =~ DATE_FIELD_REGEXP
|
|
80
|
-
# FIXME: Use to_utc and date function in Zena::Db
|
|
81
89
|
arg = query_parse_dates(arg)
|
|
82
90
|
first = arg.first
|
|
83
91
|
end
|
|
@@ -107,8 +115,10 @@ module Zena
|
|
|
107
115
|
|
|
108
116
|
def query_parse_dates(str)
|
|
109
117
|
str.gsub(DATE_FIELD_REGEXP) do |date_str|
|
|
110
|
-
|
|
111
|
-
|
|
118
|
+
# Consider params as coming from the visitor's timezone.
|
|
119
|
+
if time = parse_date(date_str)
|
|
120
|
+
# We now have an UTC field.
|
|
121
|
+
time.strftime("'%Y-%m-%d %H:%M'")
|
|
112
122
|
else
|
|
113
123
|
date_str
|
|
114
124
|
end
|
|
@@ -174,7 +184,6 @@ module Zena
|
|
|
174
184
|
# Open a list context with a query comming from the url params. Default param name is
|
|
175
185
|
# "qb"
|
|
176
186
|
def r_query
|
|
177
|
-
return parser_error("Cannot be used in list context (#{node.class_name})") if node.list_context?
|
|
178
187
|
return parser_error("Missing 'default' query") unless default_psql = @params[:default]
|
|
179
188
|
|
|
180
189
|
count = get_count(default_psql, {:find => @params[:find]})
|
|
@@ -184,9 +193,21 @@ module Zena
|
|
|
184
193
|
rescue ::QueryBuilder::Error => err
|
|
185
194
|
return parser_error(err.message)
|
|
186
195
|
end
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
196
|
+
|
|
197
|
+
if count == :all
|
|
198
|
+
klass = [default_query.main_class]
|
|
199
|
+
type = :find
|
|
200
|
+
res_nil = true
|
|
201
|
+
elsif count == :first
|
|
202
|
+
klass = default_query.main_class
|
|
203
|
+
type = :find
|
|
204
|
+
res_nil = true
|
|
205
|
+
else
|
|
206
|
+
klass = Number
|
|
207
|
+
type = :count
|
|
208
|
+
res_nil = false
|
|
209
|
+
end
|
|
210
|
+
|
|
190
211
|
can_be_nil = true
|
|
191
212
|
if sql = @params[:eval]
|
|
192
213
|
sql = RubyLess.translate(self, sql)
|
|
@@ -205,8 +226,12 @@ module Zena
|
|
|
205
226
|
sql = "#{sql} || #{default_psql.inspect}"
|
|
206
227
|
end
|
|
207
228
|
|
|
208
|
-
query = DynamicQuery.new(default_query,
|
|
209
|
-
|
|
229
|
+
query = DynamicQuery.new(default_query, single_node, sql, count)
|
|
230
|
+
if @blocks.empty? && type == :count
|
|
231
|
+
out "<%= #{query.to_s} %>"
|
|
232
|
+
else
|
|
233
|
+
expand_with_finder(:method => query.to_s, :class => klass, :nil => res_nil, :query => query)
|
|
234
|
+
end
|
|
210
235
|
end
|
|
211
236
|
|
|
212
237
|
# Pre-processing of the 'find("...")' method.
|
|
@@ -292,7 +317,7 @@ module Zena
|
|
|
292
317
|
private
|
|
293
318
|
def single_node
|
|
294
319
|
node = self.node
|
|
295
|
-
while node.list_context?
|
|
320
|
+
while node.list_context? || node.klass <= String || node.klass <= Number
|
|
296
321
|
node = node.up
|
|
297
322
|
if !node
|
|
298
323
|
raise ::QueryBuilder::Error.new("Could not access node context query builder from list #{self.node.class_name}")
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
require 'querybuilder'
|
|
2
|
+
|
|
3
|
+
module Zena
|
|
4
|
+
module Use
|
|
5
|
+
class QueryLink
|
|
6
|
+
|
|
7
|
+
module ModelMethods
|
|
8
|
+
def self.included(base)
|
|
9
|
+
base.send(:include, ::QueryBuilder)
|
|
10
|
+
base.extend ClassMethods
|
|
11
|
+
base.query_compiler = Zena::Use::QueryLink::Compiler
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
module ClassMethods
|
|
16
|
+
# Find a node and propagate visitor
|
|
17
|
+
def do_find(count, query)
|
|
18
|
+
case count
|
|
19
|
+
when :all
|
|
20
|
+
res = find_by_sql(query)
|
|
21
|
+
res.empty? ? nil : res
|
|
22
|
+
when :first
|
|
23
|
+
find_by_sql(query).first
|
|
24
|
+
when :count
|
|
25
|
+
count_by_sql(query)
|
|
26
|
+
else
|
|
27
|
+
nil
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class Compiler < ::QueryBuilder::Processor
|
|
34
|
+
attr_reader :node_name
|
|
35
|
+
set_main_table 'links'
|
|
36
|
+
set_main_class 'Link'
|
|
37
|
+
set_default :order, 'comment ASC'
|
|
38
|
+
|
|
39
|
+
# Overwrite this and take car to check for valid fields.
|
|
40
|
+
def process_field(field_name)
|
|
41
|
+
if %w{comment status date name}.include?(field_name)
|
|
42
|
+
field_name = 'comment' if field_name == 'name'
|
|
43
|
+
"#{table}.#{field_name}"
|
|
44
|
+
else
|
|
45
|
+
super # raise an error
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def map_attr(fld)
|
|
50
|
+
# error
|
|
51
|
+
nil
|
|
52
|
+
end
|
|
53
|
+
end # Compiler
|
|
54
|
+
|
|
55
|
+
end # QueryLink
|
|
56
|
+
end # Use
|
|
57
|
+
end # Zena
|