zena 1.2.1 → 1.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (202) hide show
  1. data/History.txt +38 -1
  2. data/app/controllers/documents_controller.rb +7 -5
  3. data/app/controllers/nodes_controller.rb +47 -6
  4. data/app/controllers/user_sessions_controller.rb +12 -3
  5. data/app/controllers/virtual_classes_controller.rb +8 -2
  6. data/app/models/acl.rb +5 -2
  7. data/app/models/cached_page.rb +5 -5
  8. data/app/models/column.rb +27 -4
  9. data/app/models/group.rb +1 -1
  10. data/app/models/node.rb +106 -24
  11. data/app/models/note.rb +2 -1
  12. data/app/models/relation.rb +9 -4
  13. data/app/models/relation_proxy.rb +2 -2
  14. data/app/models/role.rb +12 -5
  15. data/app/models/site.rb +10 -9
  16. data/app/models/skin.rb +8 -0
  17. data/app/models/string_hash.rb +65 -0
  18. data/app/models/text_document.rb +1 -1
  19. data/app/models/user.rb +2 -0
  20. data/app/models/virtual_class.rb +43 -10
  21. data/app/views/comments/create.rjs +1 -32
  22. data/app/views/comments/edit.rjs +1 -1
  23. data/app/views/comments/update.rjs +1 -1
  24. data/app/views/documents/show.rhtml +1 -1
  25. data/app/views/groups/_form.rhtml +7 -0
  26. data/app/views/groups/_li.rhtml +1 -1
  27. data/app/views/nodes/500.html +2 -1
  28. data/app/views/nodes/destroy.rjs +2 -0
  29. data/app/views/sites/jobs.erb +2 -3
  30. data/app/views/templates/document_create_tabs/_file.rhtml +1 -1
  31. data/app/views/templates/document_create_tabs/_import.rhtml +4 -1
  32. data/app/views/templates/document_create_tabs/_template.rhtml +3 -0
  33. data/app/views/templates/document_create_tabs/_text_document.rhtml +3 -0
  34. data/app/views/versions/custom_tab.rhtml +1 -1
  35. data/app/views/versions/edit.rhtml +1 -1
  36. data/bricks/acls/lib/bricks/acls.rb +3 -3
  37. data/bricks/acls/zena/test/unit/acl_test.rb +15 -0
  38. data/bricks/fs_skin/lib/bricks/fs_skin.rb +190 -0
  39. data/bricks/fs_skin/zena/init.rb +1 -0
  40. data/bricks/fs_skin/zena/migrate/20110702010330_add_fs_skin_to_idx_templates.rb +12 -0
  41. data/bricks/{static → fs_skin}/zena/skins/blog/Image-edit.zafu +0 -0
  42. data/bricks/{static → fs_skin}/zena/skins/blog/Image.zafu +0 -0
  43. data/bricks/{static → fs_skin}/zena/skins/blog/Node-+index.zafu +0 -0
  44. data/bricks/{static → fs_skin}/zena/skins/blog/Node-+notFound.zafu +0 -0
  45. data/bricks/{static → fs_skin}/zena/skins/blog/Node-+search.zafu +0 -0
  46. data/bricks/{static → fs_skin}/zena/skins/blog/Node.zafu +1 -1
  47. data/bricks/{static → fs_skin}/zena/skins/blog/Post.zafu +0 -0
  48. data/bricks/{static → fs_skin}/zena/skins/blog/Project--kml.zafu +0 -0
  49. data/bricks/{static → fs_skin}/zena/skins/blog/Project.zafu +0 -0
  50. data/bricks/{static → fs_skin}/zena/skins/blog/comments.zafu +0 -0
  51. data/bricks/{static → fs_skin}/zena/skins/blog/dict.yml +0 -0
  52. data/bricks/{static → fs_skin}/zena/skins/blog/img/dateBg.jpg +0 -0
  53. data/bricks/{static → fs_skin}/zena/skins/blog/img/header.png +0 -0
  54. data/bricks/{static → fs_skin}/zena/skins/blog/img/mapPin.png +0 -0
  55. data/bricks/{static → fs_skin}/zena/skins/blog/img/menu.gif +0 -0
  56. data/bricks/{static → fs_skin}/zena/skins/blog/img/menuover.gif +0 -0
  57. data/bricks/{static → fs_skin}/zena/skins/blog/img/style.css +0 -0
  58. data/bricks/fs_skin/zena/tasks.rb +26 -0
  59. data/bricks/{static/zena/test/integration/static_integration_test.rb → fs_skin/zena/test/integration/fs_skin_integration_test.rb} +6 -6
  60. data/bricks/fs_skin/zena/test/unit/fs_skin_test.rb +33 -0
  61. data/bricks/grid/lib/bricks/grid.rb +4 -3
  62. data/bricks/tags/lib/bricks/tags.rb +1 -7
  63. data/bricks/zena/zena/migrate/20120605091558_add_ssl_login_to_site.rb +7 -0
  64. data/bricks/zena/zena/migrate/20120630123551_add_auto_publish_to_group.rb +9 -0
  65. data/config/bricks.yml +3 -3
  66. data/config/gems.yml +2 -3
  67. data/lib/tasks/zena.rake +7 -3
  68. data/lib/zafu.rb +7 -0
  69. data/lib/zafu/all.rb +21 -0
  70. data/lib/zafu/compiler.rb +7 -0
  71. data/lib/zafu/controller_methods.rb +58 -0
  72. data/lib/zafu/handler.rb +57 -0
  73. data/lib/zafu/info.rb +4 -0
  74. data/lib/zafu/markup.rb +309 -0
  75. data/lib/zafu/mock_helper.rb +42 -0
  76. data/lib/zafu/node_context.rb +203 -0
  77. data/lib/zafu/ordered_hash.rb +53 -0
  78. data/lib/zafu/parser.rb +676 -0
  79. data/lib/zafu/parsing_rules.rb +382 -0
  80. data/lib/zafu/process/ajax.rb +530 -0
  81. data/lib/zafu/process/conditional.rb +92 -0
  82. data/lib/zafu/process/context.rb +186 -0
  83. data/lib/zafu/process/forms.rb +143 -0
  84. data/lib/zafu/process/html.rb +186 -0
  85. data/lib/zafu/process/ruby_less_processing.rb +321 -0
  86. data/lib/zafu/security.rb +15 -0
  87. data/lib/zafu/template.rb +25 -0
  88. data/lib/zafu/test_helper.rb +19 -0
  89. data/lib/zafu/view_methods.rb +6 -0
  90. data/lib/zena.rb +1 -1
  91. data/lib/zena/acts/enrollable.rb +1 -1
  92. data/lib/zena/app.rb +4 -17
  93. data/lib/zena/console.rb +18 -1
  94. data/lib/zena/core_ext/file_utils.rb +13 -1
  95. data/lib/zena/core_ext/fixnum.rb +4 -0
  96. data/lib/zena/core_ext/float.rb +7 -0
  97. data/lib/zena/deploy.rb +4 -2
  98. data/lib/zena/deploy/app_init.rhtml +2 -1
  99. data/lib/zena/deploy/database.rhtml +1 -1
  100. data/lib/zena/info.rb +1 -1
  101. data/lib/zena/parser/zazen_rules.rb +4 -4
  102. data/lib/zena/routes.rb +1 -1
  103. data/lib/zena/test_controller.rb +1 -1
  104. data/lib/zena/use.rb +14 -1
  105. data/lib/zena/use/action.rb +4 -2
  106. data/lib/zena/use/ajax.rb +86 -38
  107. data/lib/zena/use/authlogic.rb +16 -1
  108. data/lib/zena/use/calendar.rb +37 -17
  109. data/lib/zena/use/conditional.rb +2 -2
  110. data/lib/zena/use/context.rb +30 -9
  111. data/lib/zena/use/dates.rb +39 -3
  112. data/lib/zena/use/display.rb +6 -19
  113. data/lib/zena/use/forms.rb +100 -79
  114. data/lib/zena/use/i18n.rb +40 -16
  115. data/lib/zena/use/query_builder.rb +0 -6
  116. data/lib/zena/use/query_node.rb +17 -4
  117. data/lib/zena/use/relations.rb +1 -3
  118. data/lib/zena/use/rendering.rb +10 -8
  119. data/lib/zena/use/scope_index.rb +5 -1
  120. data/lib/zena/use/search.rb +2 -1
  121. data/lib/zena/use/urls.rb +82 -77
  122. data/lib/zena/use/workflow.rb +12 -4
  123. data/lib/zena/use/zafu_safe_definitions.rb +37 -9
  124. data/lib/zena/use/zafu_templates.rb +49 -20
  125. data/lib/zena/use/zazen.rb +6 -2
  126. data/locale/it/LC_MESSAGES/zena.mo +0 -0
  127. data/locale/it/zena.mo +0 -0
  128. data/locale/it/zena.po +1982 -0
  129. data/public/images/arrow_back.png +0 -0
  130. data/public/images/remove_tag.png +0 -0
  131. data/public/javascripts/grid.js +800 -199
  132. data/public/javascripts/window.js +1 -1
  133. data/public/javascripts/zena.js +130 -21
  134. data/public/stylesheets/grid.css +11 -2
  135. data/public/stylesheets/zena.css +2 -1
  136. data/test/custom_queries/complex.host.yml +5 -0
  137. data/test/fixtures/files/TestNode.zafu +36 -0
  138. data/test/functional/nodes_controller_test.rb +18 -1
  139. data/test/integration/zafu_compiler/action.yml +2 -2
  140. data/test/integration/zafu_compiler/ajax.yml +44 -26
  141. data/test/integration/zafu_compiler/asset.yml +12 -2
  142. data/test/integration/zafu_compiler/basic.yml +0 -16
  143. data/test/integration/zafu_compiler/calendar.yml +6 -6
  144. data/test/integration/zafu_compiler/complex_ok.yml +23 -1
  145. data/test/integration/zafu_compiler/conditional.yml +5 -5
  146. data/test/integration/zafu_compiler/context.yml +6 -5
  147. data/test/integration/zafu_compiler/dates.yml +23 -2
  148. data/test/integration/zafu_compiler/display.yml +46 -2
  149. data/test/integration/zafu_compiler/errors.yml +2 -2
  150. data/test/integration/zafu_compiler/eval.yml +35 -7
  151. data/test/integration/zafu_compiler/forms.yml +47 -13
  152. data/test/integration/zafu_compiler/i18n.yml +2 -2
  153. data/test/integration/zafu_compiler/meta.yml +35 -1
  154. data/test/integration/zafu_compiler/query.yml +23 -4
  155. data/test/integration/zafu_compiler/relations.yml +10 -6
  156. data/test/integration/zafu_compiler/roles.yml +4 -4
  157. data/test/integration/zafu_compiler/rubyless.yml +11 -1
  158. data/test/integration/zafu_compiler/safe_definitions.yml +23 -5
  159. data/test/integration/zafu_compiler/security.yml +10 -6
  160. data/test/integration/zafu_compiler/urls.yml +23 -6
  161. data/test/integration/zafu_compiler/zafu_attributes.yml +1 -1
  162. data/test/integration/zafu_compiler/zazen.yml +14 -0
  163. data/test/selenium/Add/add3.rsel +8 -8
  164. data/test/selenium/Destroy/0setup.rsel +12 -0
  165. data/test/selenium/Destroy/destroy1.rsel +16 -0
  166. data/test/selenium/Edit/edit2.rsel +9 -9
  167. data/test/selenium/Edit/edit5.rsel +9 -9
  168. data/test/selenium/Edit/edit6.rsel +9 -9
  169. data/test/selenium/Form/form4.rsel +17 -0
  170. data/test/selenium/Toggle/toggle1.rsel +2 -0
  171. data/test/selenium/Toggle/toggle2.rsel +18 -0
  172. data/test/sites/zena/columns.yml +3 -0
  173. data/test/sites/zena/versions.yml +7 -0
  174. data/test/unit/cached_page_test.rb +13 -13
  175. data/test/unit/column_test.rb +26 -0
  176. data/test/unit/node_test.rb +16 -1
  177. data/test/unit/project_test.rb +6 -1
  178. data/test/unit/relation_test.rb +1 -1
  179. data/test/unit/role_test.rb +1 -1
  180. data/test/unit/string_hash_test.rb +30 -0
  181. data/test/unit/virtual_class_test.rb +31 -17
  182. data/test/unit/zafu_markup_test.rb +414 -0
  183. data/test/unit/zafu_node_context_test.rb +375 -0
  184. data/test/unit/zafu_ordered_hash_test.rb +69 -0
  185. data/test/unit/zena/acts/enrollable_test.rb +1 -1
  186. data/test/unit/zena/parser/zafu_asset.yml +0 -10
  187. data/test/unit/zena/parser/zazen.yml +1 -1
  188. data/test/unit/zena/parser_test.rb +1 -72
  189. data/test/unit/zena/use/dates_test.rb +1 -1
  190. data/test/unit/zena/use/rendering_test.rb +24 -7
  191. data/test/unit/zena/use/scope_index_test.rb +17 -0
  192. data/test/unit/zena/use/zazen_test.rb +2 -1
  193. data/zena.gemspec +71 -37
  194. metadata +104 -83
  195. data/app/views/nodes/destroy.erb +0 -0
  196. data/bricks/static/lib/bricks/static.rb +0 -151
  197. data/bricks/static/zena/init.rb +0 -1
  198. data/bricks/static/zena/migrate/20110702010330_add_static_to_idx_templates.rb +0 -12
  199. data/bricks/static/zena/test/unit/static_test.rb +0 -33
  200. data/lib/zena/parser/zafu_rules.rb +0 -244
  201. data/lib/zena/parser/zafu_tags.rb +0 -198
  202. 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('<','&lt;').gsub('>','&gt;') %></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 = {'<%' => '&lt;%', '%>' => '%&gt;', '<' => '&lt;'}
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("'", "&apos;")
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
@@ -0,0 +1,6 @@
1
+ require 'zafu/controller_methods'
2
+ module Zafu
3
+ module ViewMethods
4
+ include Zafu::ControllerMethods::Common
5
+ end
6
+ end
@@ -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 2011"
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)
@@ -101,7 +101,7 @@ module Zena
101
101
  next unless role.class == Role && role.id
102
102
  role_ids << role.id if role.column_names & keys != []
103
103
  end
104
-
104
+
105
105
  prop['cached_role_ids'] = role_ids
106
106
  end
107
107
 
@@ -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
- ::Skin.class_eval do
72
- Zena::Use.each_module_for('Skin') do |mod|
73
- include mod
74
- end
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
@@ -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
- for curr_page in (1..page_count)
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