zena 1.2.1 → 1.2.2
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 +38 -1
- data/app/controllers/documents_controller.rb +7 -5
- data/app/controllers/nodes_controller.rb +47 -6
- data/app/controllers/user_sessions_controller.rb +12 -3
- data/app/controllers/virtual_classes_controller.rb +8 -2
- data/app/models/acl.rb +5 -2
- data/app/models/cached_page.rb +5 -5
- data/app/models/column.rb +27 -4
- data/app/models/group.rb +1 -1
- data/app/models/node.rb +106 -24
- data/app/models/note.rb +2 -1
- data/app/models/relation.rb +9 -4
- data/app/models/relation_proxy.rb +2 -2
- data/app/models/role.rb +12 -5
- data/app/models/site.rb +10 -9
- data/app/models/skin.rb +8 -0
- data/app/models/string_hash.rb +65 -0
- data/app/models/text_document.rb +1 -1
- data/app/models/user.rb +2 -0
- data/app/models/virtual_class.rb +43 -10
- data/app/views/comments/create.rjs +1 -32
- data/app/views/comments/edit.rjs +1 -1
- data/app/views/comments/update.rjs +1 -1
- data/app/views/documents/show.rhtml +1 -1
- data/app/views/groups/_form.rhtml +7 -0
- data/app/views/groups/_li.rhtml +1 -1
- data/app/views/nodes/500.html +2 -1
- data/app/views/nodes/destroy.rjs +2 -0
- data/app/views/sites/jobs.erb +2 -3
- data/app/views/templates/document_create_tabs/_file.rhtml +1 -1
- data/app/views/templates/document_create_tabs/_import.rhtml +4 -1
- data/app/views/templates/document_create_tabs/_template.rhtml +3 -0
- data/app/views/templates/document_create_tabs/_text_document.rhtml +3 -0
- data/app/views/versions/custom_tab.rhtml +1 -1
- data/app/views/versions/edit.rhtml +1 -1
- data/bricks/acls/lib/bricks/acls.rb +3 -3
- data/bricks/acls/zena/test/unit/acl_test.rb +15 -0
- data/bricks/fs_skin/lib/bricks/fs_skin.rb +190 -0
- data/bricks/fs_skin/zena/init.rb +1 -0
- data/bricks/fs_skin/zena/migrate/20110702010330_add_fs_skin_to_idx_templates.rb +12 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/Image-edit.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/Image.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/Node-+index.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/Node-+notFound.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/Node-+search.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/Node.zafu +1 -1
- data/bricks/{static → fs_skin}/zena/skins/blog/Post.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/Project--kml.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/Project.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/comments.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/dict.yml +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/img/dateBg.jpg +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/img/header.png +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/img/mapPin.png +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/img/menu.gif +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/img/menuover.gif +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/img/style.css +0 -0
- data/bricks/fs_skin/zena/tasks.rb +26 -0
- data/bricks/{static/zena/test/integration/static_integration_test.rb → fs_skin/zena/test/integration/fs_skin_integration_test.rb} +6 -6
- data/bricks/fs_skin/zena/test/unit/fs_skin_test.rb +33 -0
- data/bricks/grid/lib/bricks/grid.rb +4 -3
- data/bricks/tags/lib/bricks/tags.rb +1 -7
- data/bricks/zena/zena/migrate/20120605091558_add_ssl_login_to_site.rb +7 -0
- data/bricks/zena/zena/migrate/20120630123551_add_auto_publish_to_group.rb +9 -0
- data/config/bricks.yml +3 -3
- data/config/gems.yml +2 -3
- data/lib/tasks/zena.rake +7 -3
- data/lib/zafu.rb +7 -0
- data/lib/zafu/all.rb +21 -0
- data/lib/zafu/compiler.rb +7 -0
- data/lib/zafu/controller_methods.rb +58 -0
- data/lib/zafu/handler.rb +57 -0
- data/lib/zafu/info.rb +4 -0
- data/lib/zafu/markup.rb +309 -0
- data/lib/zafu/mock_helper.rb +42 -0
- data/lib/zafu/node_context.rb +203 -0
- data/lib/zafu/ordered_hash.rb +53 -0
- data/lib/zafu/parser.rb +676 -0
- data/lib/zafu/parsing_rules.rb +382 -0
- data/lib/zafu/process/ajax.rb +530 -0
- data/lib/zafu/process/conditional.rb +92 -0
- data/lib/zafu/process/context.rb +186 -0
- data/lib/zafu/process/forms.rb +143 -0
- data/lib/zafu/process/html.rb +186 -0
- data/lib/zafu/process/ruby_less_processing.rb +321 -0
- data/lib/zafu/security.rb +15 -0
- data/lib/zafu/template.rb +25 -0
- data/lib/zafu/test_helper.rb +19 -0
- data/lib/zafu/view_methods.rb +6 -0
- data/lib/zena.rb +1 -1
- data/lib/zena/acts/enrollable.rb +1 -1
- data/lib/zena/app.rb +4 -17
- data/lib/zena/console.rb +18 -1
- data/lib/zena/core_ext/file_utils.rb +13 -1
- data/lib/zena/core_ext/fixnum.rb +4 -0
- data/lib/zena/core_ext/float.rb +7 -0
- data/lib/zena/deploy.rb +4 -2
- data/lib/zena/deploy/app_init.rhtml +2 -1
- data/lib/zena/deploy/database.rhtml +1 -1
- data/lib/zena/info.rb +1 -1
- data/lib/zena/parser/zazen_rules.rb +4 -4
- data/lib/zena/routes.rb +1 -1
- data/lib/zena/test_controller.rb +1 -1
- data/lib/zena/use.rb +14 -1
- data/lib/zena/use/action.rb +4 -2
- data/lib/zena/use/ajax.rb +86 -38
- data/lib/zena/use/authlogic.rb +16 -1
- data/lib/zena/use/calendar.rb +37 -17
- data/lib/zena/use/conditional.rb +2 -2
- data/lib/zena/use/context.rb +30 -9
- data/lib/zena/use/dates.rb +39 -3
- data/lib/zena/use/display.rb +6 -19
- data/lib/zena/use/forms.rb +100 -79
- data/lib/zena/use/i18n.rb +40 -16
- data/lib/zena/use/query_builder.rb +0 -6
- data/lib/zena/use/query_node.rb +17 -4
- data/lib/zena/use/relations.rb +1 -3
- data/lib/zena/use/rendering.rb +10 -8
- data/lib/zena/use/scope_index.rb +5 -1
- data/lib/zena/use/search.rb +2 -1
- data/lib/zena/use/urls.rb +82 -77
- data/lib/zena/use/workflow.rb +12 -4
- data/lib/zena/use/zafu_safe_definitions.rb +37 -9
- data/lib/zena/use/zafu_templates.rb +49 -20
- data/lib/zena/use/zazen.rb +6 -2
- data/locale/it/LC_MESSAGES/zena.mo +0 -0
- data/locale/it/zena.mo +0 -0
- data/locale/it/zena.po +1982 -0
- data/public/images/arrow_back.png +0 -0
- data/public/images/remove_tag.png +0 -0
- data/public/javascripts/grid.js +800 -199
- data/public/javascripts/window.js +1 -1
- data/public/javascripts/zena.js +130 -21
- data/public/stylesheets/grid.css +11 -2
- data/public/stylesheets/zena.css +2 -1
- data/test/custom_queries/complex.host.yml +5 -0
- data/test/fixtures/files/TestNode.zafu +36 -0
- data/test/functional/nodes_controller_test.rb +18 -1
- data/test/integration/zafu_compiler/action.yml +2 -2
- data/test/integration/zafu_compiler/ajax.yml +44 -26
- data/test/integration/zafu_compiler/asset.yml +12 -2
- data/test/integration/zafu_compiler/basic.yml +0 -16
- data/test/integration/zafu_compiler/calendar.yml +6 -6
- data/test/integration/zafu_compiler/complex_ok.yml +23 -1
- data/test/integration/zafu_compiler/conditional.yml +5 -5
- data/test/integration/zafu_compiler/context.yml +6 -5
- data/test/integration/zafu_compiler/dates.yml +23 -2
- data/test/integration/zafu_compiler/display.yml +46 -2
- data/test/integration/zafu_compiler/errors.yml +2 -2
- data/test/integration/zafu_compiler/eval.yml +35 -7
- data/test/integration/zafu_compiler/forms.yml +47 -13
- data/test/integration/zafu_compiler/i18n.yml +2 -2
- data/test/integration/zafu_compiler/meta.yml +35 -1
- data/test/integration/zafu_compiler/query.yml +23 -4
- data/test/integration/zafu_compiler/relations.yml +10 -6
- data/test/integration/zafu_compiler/roles.yml +4 -4
- data/test/integration/zafu_compiler/rubyless.yml +11 -1
- data/test/integration/zafu_compiler/safe_definitions.yml +23 -5
- data/test/integration/zafu_compiler/security.yml +10 -6
- data/test/integration/zafu_compiler/urls.yml +23 -6
- data/test/integration/zafu_compiler/zafu_attributes.yml +1 -1
- data/test/integration/zafu_compiler/zazen.yml +14 -0
- data/test/selenium/Add/add3.rsel +8 -8
- data/test/selenium/Destroy/0setup.rsel +12 -0
- data/test/selenium/Destroy/destroy1.rsel +16 -0
- data/test/selenium/Edit/edit2.rsel +9 -9
- data/test/selenium/Edit/edit5.rsel +9 -9
- data/test/selenium/Edit/edit6.rsel +9 -9
- data/test/selenium/Form/form4.rsel +17 -0
- data/test/selenium/Toggle/toggle1.rsel +2 -0
- data/test/selenium/Toggle/toggle2.rsel +18 -0
- data/test/sites/zena/columns.yml +3 -0
- data/test/sites/zena/versions.yml +7 -0
- data/test/unit/cached_page_test.rb +13 -13
- data/test/unit/column_test.rb +26 -0
- data/test/unit/node_test.rb +16 -1
- data/test/unit/project_test.rb +6 -1
- data/test/unit/relation_test.rb +1 -1
- data/test/unit/role_test.rb +1 -1
- data/test/unit/string_hash_test.rb +30 -0
- data/test/unit/virtual_class_test.rb +31 -17
- data/test/unit/zafu_markup_test.rb +414 -0
- data/test/unit/zafu_node_context_test.rb +375 -0
- data/test/unit/zafu_ordered_hash_test.rb +69 -0
- data/test/unit/zena/acts/enrollable_test.rb +1 -1
- data/test/unit/zena/parser/zafu_asset.yml +0 -10
- data/test/unit/zena/parser/zazen.yml +1 -1
- data/test/unit/zena/parser_test.rb +1 -72
- data/test/unit/zena/use/dates_test.rb +1 -1
- data/test/unit/zena/use/rendering_test.rb +24 -7
- data/test/unit/zena/use/scope_index_test.rb +17 -0
- data/test/unit/zena/use/zazen_test.rb +2 -1
- data/zena.gemspec +71 -37
- metadata +104 -83
- data/app/views/nodes/destroy.erb +0 -0
- data/bricks/static/lib/bricks/static.rb +0 -151
- data/bricks/static/zena/init.rb +0 -1
- data/bricks/static/zena/migrate/20110702010330_add_static_to_idx_templates.rb +0 -12
- data/bricks/static/zena/test/unit/static_test.rb +0 -33
- data/lib/zena/parser/zafu_rules.rb +0 -244
- data/lib/zena/parser/zafu_tags.rb +0 -198
- data/lib/zena/parser/zena_rules.rb +0 -23
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
require 'rubyless'
|
|
2
|
+
|
|
3
|
+
module Zafu
|
|
4
|
+
module Process
|
|
5
|
+
module RubyLessProcessing
|
|
6
|
+
include RubyLess
|
|
7
|
+
|
|
8
|
+
def self.included(base)
|
|
9
|
+
base.process_unknown :rubyless_eval
|
|
10
|
+
|
|
11
|
+
base.class_eval do
|
|
12
|
+
def do_method(sym)
|
|
13
|
+
super
|
|
14
|
+
rescue RubyLess::Error => err
|
|
15
|
+
parser_error(err.message)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Actual method resolution. The lookup first starts in the current helper. If nothing is found there, it
|
|
21
|
+
# searches inside a 'helpers' module and finally looks into the current node_context.
|
|
22
|
+
# If nothing is found at this stage, we prepend the method with the current node and start over again.
|
|
23
|
+
def safe_method_type(signature, receiver = nil)
|
|
24
|
+
super || get_method_type(signature, false)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Resolve unknown methods by using RubyLess in the current compilation context (the
|
|
28
|
+
# translate method in RubyLess will call 'safe_method_type' in this module).
|
|
29
|
+
def rubyless_eval(params = @params)
|
|
30
|
+
if @method =~ /^([A-Z]\w+?)\?$/
|
|
31
|
+
return rubyless_class_scope($1)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
rubyless_render(@method, params)
|
|
35
|
+
rescue RubyLess::NoMethodError => err
|
|
36
|
+
parser_continue("#{err.error_message} <span class='type'>#{err.method_with_arguments}</span> (#{node.klass} context)")
|
|
37
|
+
rescue RubyLess::Error => err
|
|
38
|
+
parser_continue(err.message)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Print documentation on the current node type.
|
|
42
|
+
def r_m
|
|
43
|
+
if @params[:helper] == 'true'
|
|
44
|
+
klass = helper.class
|
|
45
|
+
else
|
|
46
|
+
klass = node.klass
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
out "<div class='rubyless-m'><h3>Documentation for <b>#{klass}</b></h3>"
|
|
50
|
+
out "<ul>"
|
|
51
|
+
RubyLess::SafeClass.safe_methods_for(klass).each do |signature, opts|
|
|
52
|
+
opts = opts.dup
|
|
53
|
+
opts.delete(:method)
|
|
54
|
+
if opts.keys == [:class]
|
|
55
|
+
opts = opts[:class]
|
|
56
|
+
end
|
|
57
|
+
out "<li>#{signature.inspect} => #{opts.inspect}</li>"
|
|
58
|
+
end
|
|
59
|
+
out "</ul></div>"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# TEMPORARY METHOD DURING HACKING...
|
|
63
|
+
# def r_erb
|
|
64
|
+
# "<pre><%= @erb.gsub('<','<').gsub('>','>') %></pre>"
|
|
65
|
+
# end
|
|
66
|
+
|
|
67
|
+
def rubyless_render(method, params)
|
|
68
|
+
# We need to set this here because we cannot pass options to RubyLess or get them back
|
|
69
|
+
# when we evaluate the method to see if we can use blocks as arguments.
|
|
70
|
+
@rendering_block_owner = true
|
|
71
|
+
code = method_with_arguments(method, params)
|
|
72
|
+
# It is strange that we need to freeze code... But if we don't, we
|
|
73
|
+
# get double ##{} on some systems (Linux).
|
|
74
|
+
rubyless_expand RubyLess.translate(self, code.freeze)
|
|
75
|
+
ensure
|
|
76
|
+
@rendering_block_owner = false
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def set_markup_attr(markup, key, value)
|
|
80
|
+
value = value.kind_of?(RubyLess::TypedString) ? value : RubyLess.translate_string(self, value)
|
|
81
|
+
if value.literal
|
|
82
|
+
markup.set_param(key, form_quote(value.literal))
|
|
83
|
+
else
|
|
84
|
+
markup.set_dyn_param(key, "<%= #{value} %>")
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def append_markup_attr(markup, key, value)
|
|
89
|
+
value = RubyLess.translate_string(self, value)
|
|
90
|
+
if value.literal
|
|
91
|
+
markup.append_param(key, form_quote(value.literal))
|
|
92
|
+
else
|
|
93
|
+
markup.append_dyn_param(key, "<%= #{value} %>")
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def get_attribute_or_eval(use_string_block = true)
|
|
98
|
+
if @params[:date] && method != 'link'
|
|
99
|
+
return parser_continue("'date' parameter is deprecated. Please use 'attr' or 'eval'.")
|
|
100
|
+
elsif attribute = @params[:attr]
|
|
101
|
+
code = "this.#{attribute}"
|
|
102
|
+
elsif code = @params[:eval] || @params[:test]
|
|
103
|
+
elsif code = @params[:param]
|
|
104
|
+
code = "params[:#{code}]"
|
|
105
|
+
elsif text = @params[:text]
|
|
106
|
+
code = "%Q{#{text}}"
|
|
107
|
+
elsif text = @params[:t]
|
|
108
|
+
code = "t(%Q{#{text}})"
|
|
109
|
+
# elsif var = @params[:var]
|
|
110
|
+
# if code = get_context_var('set_var', var)
|
|
111
|
+
# return code
|
|
112
|
+
# else
|
|
113
|
+
# return parser_continue("Var #{var.inspect} not declared.")
|
|
114
|
+
# end
|
|
115
|
+
elsif use_string_block && @blocks.size == 1 && @blocks.first.kind_of?(String)
|
|
116
|
+
return RubyLess::TypedString.new(@blocks.first.inspect, :class => String, :literal => @blocks.first)
|
|
117
|
+
else
|
|
118
|
+
return parser_continue("Missing attribute/eval parameter")
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
RubyLess.translate(self, code)
|
|
122
|
+
rescue RubyLess::Error => err
|
|
123
|
+
return parser_continue(err.message, code)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Pass default values as parameters in @context as :param_XXXX
|
|
127
|
+
def r_default
|
|
128
|
+
cont = {}
|
|
129
|
+
@params.each do |k, v|
|
|
130
|
+
cont[:"params_#{k}"] = v
|
|
131
|
+
end
|
|
132
|
+
expand_with cont
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
private
|
|
136
|
+
# Extract arguments from params (evaluates params as RubyLess strings).
|
|
137
|
+
def extract_from_params(*keys)
|
|
138
|
+
res = []
|
|
139
|
+
|
|
140
|
+
keys.each do |key|
|
|
141
|
+
next unless value = param(key.to_sym)
|
|
142
|
+
res << ":#{key} => #{RubyLess.translate_string(self, value)}"
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
res.empty? ? nil : res
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def param(key, default = nil)
|
|
149
|
+
@params[key] || @context[:"params_#{key}"] || default
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# Method resolution. The first matching method is returned. Order of evaluation is
|
|
153
|
+
# 1. find node_context (@page, @image, self)
|
|
154
|
+
# 2. set var (set_xxx = '...')
|
|
155
|
+
# 3. template helper methods
|
|
156
|
+
# 4. contextual node methods (var1.xxx)
|
|
157
|
+
# 5. contextual first node of list method ([...].first.xxx)
|
|
158
|
+
# 6. append block as argument (restart 1-5 with xxx(block_string))
|
|
159
|
+
def get_method_type(signature, added_options = false)
|
|
160
|
+
node = self.node
|
|
161
|
+
|
|
162
|
+
if type = node_context_from_signature(signature)
|
|
163
|
+
# Resolve this, @page, @node
|
|
164
|
+
type
|
|
165
|
+
elsif type = get_var_from_signature(signature)
|
|
166
|
+
# Resolved stored set_xxx='something' in context.
|
|
167
|
+
type
|
|
168
|
+
elsif type = safe_method_from(helper, signature)
|
|
169
|
+
# Resolve template helper methods
|
|
170
|
+
type
|
|
171
|
+
elsif helper.respond_to?(:helpers) && type = safe_method_from(helper.helpers, signature)
|
|
172
|
+
# Resolve by looking at the included helpers
|
|
173
|
+
type
|
|
174
|
+
elsif node && !node.list_context? && type = safe_method_from(node.klass, signature, node)
|
|
175
|
+
# not a list_contex
|
|
176
|
+
# Resolve node context methods: xxx.foo, xxx.bar
|
|
177
|
+
# All direct methods from nodes should be html escaped:
|
|
178
|
+
type = type[:class].call(self, node.klass, signature) if type[:class].kind_of?(Proc)
|
|
179
|
+
type.merge(:receiver => RubyLess::TypedString.new(node.name, :class => node.klass, :h => true))
|
|
180
|
+
elsif node && node.list_context? && type = safe_method_from(Array, signature, node)
|
|
181
|
+
# FIXME: why do we need this here ? Remove with related code in zafu_safe_definitions ?
|
|
182
|
+
type = type[:class].call(self, node.klass, signature) if type[:class].kind_of?(Proc)
|
|
183
|
+
type.merge(:receiver => RubyLess::TypedString.new(node.name, :class => Array, :elem => node.klass.first))
|
|
184
|
+
elsif node && node.list_context? && type = safe_method_from(node.klass.first, signature, node)
|
|
185
|
+
type = type[:class].call(self, node.klass, signature) if type[:class].kind_of?(Proc)
|
|
186
|
+
type.merge(:receiver => RubyLess::TypedString.new("#{node.name}.first", :class => node.klass.first, :h => true))
|
|
187
|
+
elsif @rendering_block_owner && @blocks.first.kind_of?(String) && !added_options
|
|
188
|
+
# Insert the block content into the method: <r:trans>blah</r:trans> becomes trans("blah")
|
|
189
|
+
signature_with_block = signature.dup
|
|
190
|
+
signature_with_block << String
|
|
191
|
+
if type = get_method_type(signature_with_block, true)
|
|
192
|
+
type.merge(:prepend_args => RubyLess::TypedString.new(@blocks.first.inspect, :class => String, :literal => @blocks.first))
|
|
193
|
+
else
|
|
194
|
+
nil
|
|
195
|
+
end
|
|
196
|
+
elsif node && !added_options
|
|
197
|
+
# Try prepending current node before arguments: link("foo") becomes link(var1, "foo")
|
|
198
|
+
signature_with_node = signature.dup
|
|
199
|
+
signature_with_node.insert(1, node.real_class) # node.klass ?
|
|
200
|
+
if type = get_method_type(signature_with_node, true)
|
|
201
|
+
type.merge(:prepend_args => RubyLess::TypedString.new(node.name, :class => node.klass))
|
|
202
|
+
else
|
|
203
|
+
nil
|
|
204
|
+
end
|
|
205
|
+
else
|
|
206
|
+
nil
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def method_with_arguments(method, params)
|
|
211
|
+
hash_arguments = []
|
|
212
|
+
arguments = []
|
|
213
|
+
params.keys.sort {|a,b| a.to_s <=> b.to_s}.each do |k|
|
|
214
|
+
if k =~ /\A_/
|
|
215
|
+
arguments << "%Q{#{params[k]}}"
|
|
216
|
+
else
|
|
217
|
+
hash_arguments << ":#{k} => %Q{#{params[k]}}"
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
if hash_arguments != []
|
|
222
|
+
arguments << hash_arguments.join(', ')
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
if arguments != []
|
|
226
|
+
if method =~ /^(.*)\((.*)\)$/
|
|
227
|
+
if $2 == ''
|
|
228
|
+
"#{$1}(#{arguments.join(', ')})"
|
|
229
|
+
else
|
|
230
|
+
"#{$1}(#{$2}, #{arguments.join(', ')})"
|
|
231
|
+
end
|
|
232
|
+
else
|
|
233
|
+
"#{method}(#{arguments.join(', ')})"
|
|
234
|
+
end
|
|
235
|
+
else
|
|
236
|
+
method
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def rubyless_expand(res)
|
|
241
|
+
if res.klass == String && !@blocks.detect {|b| !b.kind_of?(String)}
|
|
242
|
+
if lit = res.literal
|
|
243
|
+
out erb_escape(lit)
|
|
244
|
+
# TODO: Enable this when we have time to ensure tests/functionality work correctly.
|
|
245
|
+
#elsif res.opts[:h]
|
|
246
|
+
# show_string(res)
|
|
247
|
+
else
|
|
248
|
+
out "<%= #{res} %>"
|
|
249
|
+
end
|
|
250
|
+
elsif res.klass == Boolean
|
|
251
|
+
expand_if(res)
|
|
252
|
+
elsif @blocks.empty?
|
|
253
|
+
out "<%= #{res} %>"
|
|
254
|
+
else
|
|
255
|
+
expand_with_finder(:method => res, :class => res.klass, :query => res.opts[:query], :nil => res.could_be_nil?)
|
|
256
|
+
end
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
def rubyless_class_scope(class_name)
|
|
260
|
+
return parser_error("Cannot scope class in list (use each before filtering).") if node.list_context?
|
|
261
|
+
|
|
262
|
+
# capital letter ==> class conditional
|
|
263
|
+
klass = Module.const_get(class_name)
|
|
264
|
+
if klass.ancestors.include?(node.klass)
|
|
265
|
+
expand_if("#{node}.kind_of?(#{klass})")
|
|
266
|
+
else
|
|
267
|
+
# render nothing: incompatible classes
|
|
268
|
+
''
|
|
269
|
+
end
|
|
270
|
+
rescue
|
|
271
|
+
parser_error("Invalid class name '#{class_name}'")
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
# Find a class or behavior based on a name. The returned class should implement
|
|
275
|
+
# 'safe_method_type'.
|
|
276
|
+
def get_class(class_name)
|
|
277
|
+
Module.const_get(class_name)
|
|
278
|
+
rescue
|
|
279
|
+
nil
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
# This is used to resolve 'this' (current NodeContext), '@node' as NodeContext with class Node,
|
|
283
|
+
# '@page' as first NodeContext of type Page, etc.
|
|
284
|
+
def node_context_from_signature(signature)
|
|
285
|
+
return nil unless signature.size == 1
|
|
286
|
+
ivar = signature.first
|
|
287
|
+
if ivar == 'this'
|
|
288
|
+
node.opts.merge(:class => node.klass, :method => node.name)
|
|
289
|
+
elsif ivar[0..0] == '@' && klass = get_class(ivar[1..-1].capitalize)
|
|
290
|
+
if node = self.node(klass)
|
|
291
|
+
node.opts.merge(:class => node.klass, :method => node.name)
|
|
292
|
+
else
|
|
293
|
+
nil
|
|
294
|
+
end
|
|
295
|
+
else
|
|
296
|
+
nil
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
# Find stored variables back. Stored elements are set with set_xxx='something to eval'.
|
|
301
|
+
def get_var_from_signature(signature)
|
|
302
|
+
return nil unless signature.size == 1
|
|
303
|
+
if var = get_context_var('set_var', signature.first)
|
|
304
|
+
{:method => var, :class => var.klass, :nil => var.could_be_nil?, :query => var.opts[:query]}
|
|
305
|
+
else
|
|
306
|
+
nil
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
def safe_method_from(solver, signature, receiver = nil)
|
|
311
|
+
|
|
312
|
+
if solver.respond_to?(:safe_method_type)
|
|
313
|
+
solver.safe_method_type(signature, receiver)
|
|
314
|
+
else
|
|
315
|
+
RubyLess::SafeClass.safe_method_type_for(solver, signature)
|
|
316
|
+
end
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
end # RubyLessProcessing
|
|
320
|
+
end # Process
|
|
321
|
+
end # Zafu
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module Zafu
|
|
2
|
+
module Security
|
|
3
|
+
SECURE_REGEXP = %r{<%|%>|<\Z}
|
|
4
|
+
SAFE_CODE = {'<%' => '<%', '%>' => '%>', '<' => '<'}
|
|
5
|
+
# Make sure translations and other literal values cannot be used to build erb.
|
|
6
|
+
def erb_escape(text)
|
|
7
|
+
# Do not only replace '<%' ! or <r:t>min</r:t>% ==> <% ...
|
|
8
|
+
text.gsub(SECURE_REGEXP) {|code| SAFE_CODE[code]}
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def form_quote(text)
|
|
12
|
+
erb_escape(text).gsub("'", "'")
|
|
13
|
+
end
|
|
14
|
+
end # Security
|
|
15
|
+
end # Zafu
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require 'zafu/compiler'
|
|
2
|
+
|
|
3
|
+
module Zafu
|
|
4
|
+
class Template
|
|
5
|
+
def initialize(template, src_helper = nil, compiler = Zafu::Compiler)
|
|
6
|
+
if template.kind_of?(String)
|
|
7
|
+
@ast = compiler.new(template)
|
|
8
|
+
else
|
|
9
|
+
@ast = compiler.new_with_url(template.path, :helper => src_helper)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def to_erb(context = {})
|
|
14
|
+
@ast.to_erb(context)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def to_ruby(context = {})
|
|
18
|
+
src = ::ERB.new("<% __in_erb_template=true %>#{to_erb(context)}", nil, '-').src
|
|
19
|
+
|
|
20
|
+
# Ruby 1.9 prepends an encoding to the source. However this is
|
|
21
|
+
# useless because you can only set an encoding on the first line
|
|
22
|
+
RUBY_VERSION >= '1.9' ? src.sub(/\A#coding:.*\n/, '') : src
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require 'zafu/template'
|
|
2
|
+
|
|
3
|
+
module Zafu
|
|
4
|
+
module TestHelper
|
|
5
|
+
include RubyLess::SafeClass
|
|
6
|
+
|
|
7
|
+
def zafu_erb(source, src_helper = self, compiler = Zafu::Compiler)
|
|
8
|
+
Zafu::Template.new(source, src_helper, compiler).to_erb(compilation_context)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def zafu_render(source, src_helper = self, compiler = Zafu::Compiler)
|
|
12
|
+
eval Zafu::Template.new(source, src_helper, compiler).to_ruby(compilation_context)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def compilation_context
|
|
16
|
+
{:node => @node_context, :helper => self}
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
data/lib/zena.rb
CHANGED
|
@@ -222,7 +222,7 @@ module Zena
|
|
|
222
222
|
def init
|
|
223
223
|
config = Rails.configuration
|
|
224
224
|
enable_tools
|
|
225
|
-
puts "** zena #{Zena::VERSION} starting (c) Gaspard Bucher
|
|
225
|
+
puts "** zena #{Zena::VERSION} starting (c) Gaspard Bucher 2012"
|
|
226
226
|
puts "** Bricks: #{Bricks::CONFIG.map{|k,v| k}.sort.join(', ')}"
|
|
227
227
|
|
|
228
228
|
add_load_paths(config)
|
data/lib/zena/acts/enrollable.rb
CHANGED
data/lib/zena/app.rb
CHANGED
|
@@ -55,24 +55,11 @@ module Zena
|
|
|
55
55
|
end
|
|
56
56
|
Bricks.apply_patches('application_controller.rb')
|
|
57
57
|
Bricks.apply_patches('application_helper.rb')
|
|
58
|
-
|
|
59
|
-
::User.class_eval do
|
|
60
|
-
Zena::Use.each_module_for('User') do |mod|
|
|
61
|
-
include mod
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
::Site.class_eval do
|
|
66
|
-
Zena::Use.each_module_for('Site') do |mod|
|
|
67
|
-
include mod
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
58
|
|
|
71
|
-
::
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
end
|
|
59
|
+
Zena::Use.upgrade_class('User')
|
|
60
|
+
Zena::Use.upgrade_class('Site')
|
|
61
|
+
Zena::Use.upgrade_class('Skin')
|
|
62
|
+
|
|
76
63
|
end
|
|
77
64
|
end
|
|
78
65
|
end
|
data/lib/zena/console.rb
CHANGED
|
@@ -195,7 +195,9 @@ module Zena
|
|
|
195
195
|
page_count = (count.to_f / limit).ceil
|
|
196
196
|
puts "#{count} nodes, #{page_count} chunk(s) (100 items)"
|
|
197
197
|
curr_page = 1
|
|
198
|
-
|
|
198
|
+
# We walk pages in reverse order in case objects are deleted
|
|
199
|
+
|
|
200
|
+
for curr_page in (1..page_count).to_a.reverse
|
|
199
201
|
query.offset = " OFFSET #{limit * (curr_page - 1)}"
|
|
200
202
|
if list = Node.do_find(:all, eval(query.to_s(:find)))
|
|
201
203
|
puts "Page #{curr_page}/#{page_count}"
|
|
@@ -206,5 +208,20 @@ module Zena
|
|
|
206
208
|
end
|
|
207
209
|
nil
|
|
208
210
|
end
|
|
211
|
+
|
|
212
|
+
def profile(node_id)
|
|
213
|
+
require 'ruby-prof'
|
|
214
|
+
ctrl = NodesController.new
|
|
215
|
+
ctrl.request = Struct.new(:format).new(Mime::HTML)
|
|
216
|
+
ctrl.instance_variable_set(:@node, nodes(node_id))
|
|
217
|
+
start = Time.now
|
|
218
|
+
result = RubyProf.profile do
|
|
219
|
+
yield(ctrl)
|
|
220
|
+
end
|
|
221
|
+
puts(Time.now - start)
|
|
222
|
+
File.open('grind.log', 'wb') do |f|
|
|
223
|
+
RubyProf::CallTreePrinter.new(result).print(f)
|
|
224
|
+
end
|
|
225
|
+
end
|
|
209
226
|
end # Console
|
|
210
227
|
end # Zena
|