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/query_node.rb
CHANGED
|
@@ -177,14 +177,14 @@ module Zena
|
|
|
177
177
|
|
|
178
178
|
def get_scope_index_field(field_name)
|
|
179
179
|
return nil if @query.main_class.real_class.column_names.include?(field_name)
|
|
180
|
-
# scope index
|
|
180
|
+
# 1. Try scope index
|
|
181
181
|
klass = @query.main_class
|
|
182
182
|
if index_model = klass.kind_of?(VirtualClass) ? klass.idx_class : nil
|
|
183
183
|
index_model = Zena.resolve_const(index_model) rescue NilClass
|
|
184
184
|
if index_model < Zena::Use::ScopeIndex::IndexMethods && index_model.column_names.include?(field_name)
|
|
185
185
|
table_to_use = add_key_value_table('scope_index', index_model.table_name) do |tbl_name|
|
|
186
|
-
# This block is only executed once
|
|
187
|
-
|
|
186
|
+
# This block is only executed once (ON clause)
|
|
187
|
+
"#{table('nodes')}.id = #{tbl_name}.node_id"
|
|
188
188
|
end
|
|
189
189
|
"#{table_to_use}.#{field_name}"
|
|
190
190
|
else
|
|
@@ -192,7 +192,6 @@ module Zena
|
|
|
192
192
|
nil
|
|
193
193
|
end
|
|
194
194
|
else
|
|
195
|
-
# no index model: ignore
|
|
196
195
|
nil
|
|
197
196
|
end
|
|
198
197
|
end
|
|
@@ -220,7 +219,7 @@ module Zena
|
|
|
220
219
|
use_name, source, target, filter = table_def
|
|
221
220
|
table_to_use = add_key_value_table(use_name, target, map_def[:key]) do |tbl_name|
|
|
222
221
|
# This block is only executed once
|
|
223
|
-
|
|
222
|
+
filter.gsub(
|
|
224
223
|
'TABLE1', table(source)
|
|
225
224
|
).gsub(
|
|
226
225
|
'TABLE2', tbl_name
|
|
@@ -241,20 +240,6 @@ module Zena
|
|
|
241
240
|
elsif field_name == 'random'
|
|
242
241
|
Zena::Db.sql_function(field_name, nil)
|
|
243
242
|
else
|
|
244
|
-
if processing_filter? && field_name =~ /^(.*)_ids?$/
|
|
245
|
-
# tag_id = 33 ===> join links as lk, nodes as tt .......
|
|
246
|
-
rel = $1
|
|
247
|
-
|
|
248
|
-
# Fake field_or_attr so it does not use 'zip' on nodes
|
|
249
|
-
context[:processing] = :relation
|
|
250
|
-
if join_relation($1, 'jnode')
|
|
251
|
-
res = "#{table('jnode')}.zip"
|
|
252
|
-
end
|
|
253
|
-
context[:processing] = :filter
|
|
254
|
-
|
|
255
|
-
return res
|
|
256
|
-
end
|
|
257
|
-
|
|
258
243
|
# property or real column
|
|
259
244
|
|
|
260
245
|
# FIXME !!!! Why does this happen ?
|
|
@@ -279,12 +264,14 @@ module Zena
|
|
|
279
264
|
|
|
280
265
|
tbl = add_key_value_table(group_name, index_table, field_name) do |tbl_name|
|
|
281
266
|
# This block is only executed once
|
|
282
|
-
|
|
283
|
-
add_filter "#{tbl_name}.key = #{quote(field_name)}"
|
|
267
|
+
on_clause = "#{tbl_name}.node_id = #{table}.id AND #{tbl_name}.key = #{quote(field_name)}"
|
|
284
268
|
if group_name.to_s =~ /^ml_/
|
|
285
|
-
|
|
269
|
+
on_clause << " AND #{tbl_name}.lang = #{quote(visitor.lang)}"
|
|
286
270
|
end
|
|
287
271
|
# no need for distinct, the new table makes a 1-1 relation
|
|
272
|
+
# ON CLAUSE
|
|
273
|
+
on_clause
|
|
274
|
+
|
|
288
275
|
end
|
|
289
276
|
|
|
290
277
|
"#{tbl}.value"
|
|
@@ -364,8 +351,44 @@ module Zena
|
|
|
364
351
|
if fld = get_scope_index_field(scope_idx_field)
|
|
365
352
|
return [[:idx_field, fld], function]
|
|
366
353
|
else
|
|
367
|
-
#
|
|
368
|
-
|
|
354
|
+
# 2. Try to use relation as scope filter 'hot.title = "xxx"', 'hot.title = "xxx"'
|
|
355
|
+
# Multiple links with hot.id = 334 and hot2.id = 323...
|
|
356
|
+
rel = class_name.sub(/\d$/,'')
|
|
357
|
+
|
|
358
|
+
source_kpath = @query.main_class.kpath
|
|
359
|
+
|
|
360
|
+
if rel = RelationProxy.find_by_role(rel.singularize, source_kpath)
|
|
361
|
+
table_to_use = add_key_value_table('jnode', 'nodes', class_name) do |tbl_name|
|
|
362
|
+
# This block is only executed once per relation name (once for 'hot', once for 'hot2')
|
|
363
|
+
# TODO: Can we remove this ?
|
|
364
|
+
distinct!
|
|
365
|
+
lnk = add_key_value_table('links', 'links', class_name) do |lt|
|
|
366
|
+
"#{lt}.#{rel.link_side} = #{table(main_table)}.id AND #{lt}.relation_id = #{rel.id}"
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
%Q{#{tbl_name}.id = #{lnk}.#{rel.other_side}}
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
# Temporarily move to the remote class
|
|
373
|
+
tbl_alias_bak = context[:table_alias]
|
|
374
|
+
context[:table_alias] = table_to_use
|
|
375
|
+
main_class_bak = @query.main_class
|
|
376
|
+
|
|
377
|
+
@query.main_class = rel.other_vclass
|
|
378
|
+
fld = process_field(field_name)
|
|
379
|
+
|
|
380
|
+
# Move back
|
|
381
|
+
@query.main_class = main_class_bak
|
|
382
|
+
context[:table_alias] = tbl_alias_bak
|
|
383
|
+
if fld
|
|
384
|
+
[[:idx_field, fld], function]
|
|
385
|
+
else
|
|
386
|
+
nil
|
|
387
|
+
end
|
|
388
|
+
else
|
|
389
|
+
# not a scope index field
|
|
390
|
+
return [arg1, arg2]
|
|
391
|
+
end
|
|
369
392
|
end
|
|
370
393
|
end
|
|
371
394
|
|
|
@@ -465,6 +488,24 @@ module Zena
|
|
|
465
488
|
add_filter "#{table('comments')}.discussion_id = #{table('discussions')}.id"
|
|
466
489
|
# after_parse
|
|
467
490
|
end
|
|
491
|
+
when 'tag_cloud'
|
|
492
|
+
# tag cloud
|
|
493
|
+
if last?
|
|
494
|
+
change_processor Link.query_compiler, :rubyless_helper => @rubyless_helper
|
|
495
|
+
# no need to load discussions, versions and all the mess
|
|
496
|
+
add_table('links')
|
|
497
|
+
lnk = table('links')
|
|
498
|
+
add_filter "(#{lnk}.source_id = #{process_attr('id')} OR #{lnk}.target_id = #{process_attr('id')}) AND #{lnk}.relation_id IS NULL"
|
|
499
|
+
else
|
|
500
|
+
after_process # Make sure we secure the current part
|
|
501
|
+
change_processor Link.query_compiler, :rubyless_helper => @rubyless_helper
|
|
502
|
+
|
|
503
|
+
add_table('links')
|
|
504
|
+
lnk = table('links')
|
|
505
|
+
add_filter "(#{lnk}.source_id = #{table('nodes')}.id OR #{lnk}.target_id = #{table('nodes')}.id) AND #{lnk}.relation_id IS NULL"
|
|
506
|
+
end
|
|
507
|
+
@query.group = " GROUP BY #{lnk}.comment"
|
|
508
|
+
add_select("COUNT(#{table('nodes')}.id)", 'link_count')
|
|
468
509
|
else
|
|
469
510
|
return nil
|
|
470
511
|
end
|
|
@@ -603,14 +644,9 @@ module Zena
|
|
|
603
644
|
end
|
|
604
645
|
|
|
605
646
|
if rel = RelationProxy.find_by_role(relation.singularize, source_kpath)
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
add_table(use_name, main_table)
|
|
610
|
-
else
|
|
611
|
-
add_table(main_table)
|
|
612
|
-
set_main_class(rel.other_vclass)
|
|
613
|
-
end
|
|
647
|
+
|
|
648
|
+
add_table(main_table)
|
|
649
|
+
set_main_class(rel.other_vclass)
|
|
614
650
|
|
|
615
651
|
add_table('links')
|
|
616
652
|
|
data/lib/zena/use/relations.rb
CHANGED
|
@@ -130,7 +130,7 @@ module Zena
|
|
|
130
130
|
def l_status
|
|
131
131
|
return @l_status if defined? @l_status
|
|
132
132
|
val = @link ? @link[:status] : self['l_status']
|
|
133
|
-
val ? val.
|
|
133
|
+
val ? val.to_f : nil
|
|
134
134
|
end
|
|
135
135
|
|
|
136
136
|
# TODO: could we use LINK_ATTRIBUTES and 'define_method' here ?
|
|
@@ -151,19 +151,6 @@ module Zena
|
|
|
151
151
|
@link ? @link[:id] : (self[:link_id] == -1 ? nil : self[:link_id]) # -1 == dummy link
|
|
152
152
|
end
|
|
153
153
|
|
|
154
|
-
def link_id=(v)
|
|
155
|
-
if @link && @link[:id].to_i != v.to_i
|
|
156
|
-
@link = nil
|
|
157
|
-
end
|
|
158
|
-
self[:link_id] = v.to_i
|
|
159
|
-
if @link_attributes_to_update
|
|
160
|
-
if rel = relation_proxy_from_link
|
|
161
|
-
@link_attributes_to_update.each do |k,v|
|
|
162
|
-
rel.send("other_#{k}=",v)
|
|
163
|
-
end
|
|
164
|
-
end
|
|
165
|
-
end
|
|
166
|
-
end
|
|
167
154
|
|
|
168
155
|
# FIXME: this method does an 'update' not only 'add'
|
|
169
156
|
def add_link(role, hash)
|
|
@@ -228,13 +215,19 @@ module Zena
|
|
|
228
215
|
@l_comment = v.blank? ? nil : v
|
|
229
216
|
if rel = relation_proxy_from_link
|
|
230
217
|
rel.other_comment = @l_comment
|
|
218
|
+
else
|
|
219
|
+
l = @link_attributes_to_update ||= {}
|
|
220
|
+
l[:comment] = @l_comment
|
|
231
221
|
end
|
|
232
222
|
end
|
|
233
223
|
|
|
234
224
|
def l_status=(v)
|
|
235
|
-
@l_status = v.blank? ? nil : v
|
|
225
|
+
@l_status = v.blank? ? nil : v
|
|
236
226
|
if rel = relation_proxy_from_link
|
|
237
227
|
rel.other_status = @l_status
|
|
228
|
+
else
|
|
229
|
+
l = @link_attributes_to_update ||= {}
|
|
230
|
+
l[:status] = @l_status
|
|
238
231
|
end
|
|
239
232
|
end
|
|
240
233
|
|
|
@@ -242,6 +235,23 @@ module Zena
|
|
|
242
235
|
@l_date = v.blank? ? nil : v
|
|
243
236
|
if rel = relation_proxy_from_link
|
|
244
237
|
rel.other_date = @l_date
|
|
238
|
+
else
|
|
239
|
+
l = @link_attributes_to_update ||= {}
|
|
240
|
+
l[:date] = @l_date
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def link_id=(v)
|
|
245
|
+
if @link && @link[:id].to_i != v.to_i
|
|
246
|
+
@link = nil
|
|
247
|
+
end
|
|
248
|
+
self[:link_id] = v.to_i
|
|
249
|
+
if @link_attributes_to_update
|
|
250
|
+
if rel = relation_proxy_from_link
|
|
251
|
+
@link_attributes_to_update.each do |k,v|
|
|
252
|
+
rel.send("other_#{k}=",v)
|
|
253
|
+
end
|
|
254
|
+
end
|
|
245
255
|
end
|
|
246
256
|
end
|
|
247
257
|
|
data/lib/zena/use/rendering.rb
CHANGED
|
@@ -35,6 +35,7 @@ module Zena
|
|
|
35
35
|
module ControllerMethods
|
|
36
36
|
def self.included(base)
|
|
37
37
|
base.send(:helper_attr, :js_data, :zafu_headers)
|
|
38
|
+
base.send(:helper_method, :set_caching)
|
|
38
39
|
base.send(:layout, false)
|
|
39
40
|
end
|
|
40
41
|
|
|
@@ -45,6 +46,12 @@ module Zena
|
|
|
45
46
|
def zafu_headers
|
|
46
47
|
@zafu_headers ||= {}
|
|
47
48
|
end
|
|
49
|
+
|
|
50
|
+
def set_caching(opts)
|
|
51
|
+
if request.query_string =~ opts[:allow_query]
|
|
52
|
+
@cache_query = request.query_string
|
|
53
|
+
end
|
|
54
|
+
end
|
|
48
55
|
|
|
49
56
|
# TODO: test
|
|
50
57
|
# Our own handling of exceptions
|
|
@@ -147,10 +154,18 @@ module Zena
|
|
|
147
154
|
}
|
|
148
155
|
end
|
|
149
156
|
|
|
150
|
-
if result[:
|
|
157
|
+
if error = result[:error]
|
|
151
158
|
# error reporting from rendering engine
|
|
152
159
|
opts[:cache] = false
|
|
153
|
-
|
|
160
|
+
@render_error = error
|
|
161
|
+
render :file => 'nodes/render_error'
|
|
162
|
+
|
|
163
|
+
elsif result[:type] == 'text/html'
|
|
164
|
+
# debugging mode from rendering engine
|
|
165
|
+
opts[:cache] = false
|
|
166
|
+
|
|
167
|
+
render :inline => result[:data]
|
|
168
|
+
|
|
154
169
|
else
|
|
155
170
|
if zafu_headers
|
|
156
171
|
if disposition = zafu_headers.delete('Content-Disposition')
|
|
@@ -182,9 +197,13 @@ module Zena
|
|
|
182
197
|
cache_page(:content_data => result[:data], :content_path => result[:file]) if opts[:cache]
|
|
183
198
|
else
|
|
184
199
|
# html
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
200
|
+
if opts.delete(:as_string)
|
|
201
|
+
render_to_string :file => template_url(opts), :layout => false
|
|
202
|
+
else
|
|
203
|
+
render :file => template_url(opts), :layout => false, :status => opts[:status]
|
|
204
|
+
headers.merge!(zafu_headers)
|
|
205
|
+
cache_page(:url => opts[:cache_url]) if opts[:cache]
|
|
206
|
+
end
|
|
188
207
|
end
|
|
189
208
|
# This does not work, Rendering::Redirect is wrapped in TemplateError
|
|
190
209
|
# rescue Zena::Use::Rendering::Redirect
|
|
@@ -204,14 +223,15 @@ module Zena
|
|
|
204
223
|
def cache_page(opts={})
|
|
205
224
|
if cachestamp_format?(params['format'])
|
|
206
225
|
headers['Expires'] = (Time.now + 365*24*3600).strftime("%a, %d %b %Y %H:%M:%S GMT")
|
|
207
|
-
headers['Cache-Control'] = (!current_site.authentication? && @node.
|
|
226
|
+
headers['Cache-Control'] = (!current_site.authentication? && @node.v_public?) ? 'public' : 'private'
|
|
208
227
|
end
|
|
209
228
|
|
|
210
229
|
if perform_caching && caching_allowed(:authenticated => opts.delete(:authenticated))
|
|
211
230
|
|
|
212
231
|
url = page_cache_file(opts.delete(:url))
|
|
232
|
+
|
|
213
233
|
opts = {:expire_after => nil,
|
|
214
|
-
:path => (current_site.
|
|
234
|
+
:path => (current_site.cache_path + url),
|
|
215
235
|
:content_data => response.body,
|
|
216
236
|
:node_id => @node[:id]
|
|
217
237
|
}.merge(opts)
|
|
@@ -221,7 +241,7 @@ module Zena
|
|
|
221
241
|
|
|
222
242
|
# Return true if we can cache the current page
|
|
223
243
|
def caching_allowed(opts = {})
|
|
224
|
-
return false if current_site.authentication? || query_params != {}
|
|
244
|
+
return false if current_site.authentication? || (query_params != {} && !@cache_query)
|
|
225
245
|
# Cache even if authenticated (public content).
|
|
226
246
|
# Content viewed by anonymous user should be cached anyway.
|
|
227
247
|
opts[:authenticated] || visitor.is_anon?
|
|
@@ -229,16 +249,23 @@ module Zena
|
|
|
229
249
|
|
|
230
250
|
# Cache file path that reflects the called url
|
|
231
251
|
def page_cache_file(url = nil)
|
|
232
|
-
path = url || url_for(:only_path => true, :skip_relative_url_root => true
|
|
252
|
+
path = url || url_for(:only_path => true, :skip_relative_url_root => true)
|
|
233
253
|
path = ((path.empty? || path == "/") ? "/index" : URI.unescape(path))
|
|
234
254
|
ext = params[:format].blank? ? 'html' : params[:format]
|
|
235
|
-
|
|
236
|
-
#
|
|
255
|
+
|
|
237
256
|
# FULL QUERY_STRING in cached page ?
|
|
257
|
+
if @cache_query
|
|
258
|
+
# This builds blog29.htmlp=2.html and it is OK (helps make rewrite rules simple)
|
|
259
|
+
path << @cache_query << ".#{ext}"
|
|
260
|
+
else
|
|
261
|
+
path << ".#{ext}" unless path =~ /\.#{ext}(\?\d+|)$/
|
|
262
|
+
end
|
|
263
|
+
|
|
238
264
|
if cachestamp_format?(params['format'])
|
|
239
|
-
#
|
|
240
|
-
|
|
265
|
+
# Set expire
|
|
266
|
+
response.headers['Expires'] = 1.year.from_now.httpdate
|
|
241
267
|
end
|
|
268
|
+
|
|
242
269
|
path
|
|
243
270
|
end
|
|
244
271
|
|
|
@@ -272,14 +299,15 @@ module Zena
|
|
|
272
299
|
# urls to localhost (the rendering engine is external to Zena and will need to
|
|
273
300
|
# make calls to get assets).
|
|
274
301
|
def baseurl
|
|
275
|
-
if Zena::ASSET_PORT
|
|
302
|
+
if Zena::ASSET_PORT > 0
|
|
276
303
|
if Zena::ASSET_PORT == request.port
|
|
277
304
|
raise Exception.new("Custom rendering not allowed on this process (port == asset_port).")
|
|
278
305
|
else
|
|
279
306
|
"http://127.0.0.1:#{Zena::ASSET_PORT}"
|
|
280
307
|
end
|
|
281
308
|
else
|
|
282
|
-
|
|
309
|
+
# This can break if using mongrel and round-robin (deadlock)
|
|
310
|
+
"#{ssl_request? ? 'https' : 'http'}://#{current_site.host}"
|
|
283
311
|
end
|
|
284
312
|
end
|
|
285
313
|
|
|
@@ -304,6 +332,29 @@ module Zena
|
|
|
304
332
|
out "<% set_headers(#{headers.join(', ')}) %>"
|
|
305
333
|
end
|
|
306
334
|
end
|
|
335
|
+
|
|
336
|
+
# <r:cache rebuild='true' allow_query='p=1?[0-9]'/>
|
|
337
|
+
# <r:cache rebuild='true' allow_query='p=1?[0-9]'/>
|
|
338
|
+
def r_cache
|
|
339
|
+
params_list = []
|
|
340
|
+
if re = @params[:allow_query]
|
|
341
|
+
reg_test = %r{^#{re}$}
|
|
342
|
+
params_list << ":allow_query => #{reg_test.inspect}"
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
if rebuild = @params[:rebuild]
|
|
346
|
+
# TODO: implement "replace if changed (diff)" instead of cache removal if there is the rebuild
|
|
347
|
+
# setting so that the cached timestamp does not change.
|
|
348
|
+
params_list << ":rebuild => #{@params[:rebuild].inspect}"
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
if at = @params[:expire_at]
|
|
352
|
+
params_list << ":rebuild => #{@params[:rebuild].inspect}"
|
|
353
|
+
end
|
|
354
|
+
out "<% set_caching(:allow_query => #{reg_test.inspect}, :rebuild => #{@params[:rebuild].inspect}) %>"
|
|
355
|
+
rescue => err
|
|
356
|
+
parser_error("Invalid regular expression (#{err.message})")
|
|
357
|
+
end
|
|
307
358
|
|
|
308
359
|
def r_style
|
|
309
360
|
@markup.tag = 'style'
|
data/lib/zena/use/upload.rb
CHANGED
|
@@ -5,6 +5,8 @@ require 'uuidtools'
|
|
|
5
5
|
module Zena
|
|
6
6
|
module Use
|
|
7
7
|
module Upload
|
|
8
|
+
UPLOAD_KEY = defined?(Mongrel) ? 'upload_id' : "X-Progress-ID"
|
|
9
|
+
|
|
8
10
|
def self.has_network?
|
|
9
11
|
response = nil
|
|
10
12
|
Net::HTTP.new('example.com', '80').start do |http|
|
|
@@ -41,6 +43,7 @@ module Zena
|
|
|
41
43
|
yield(att, error) if block_given?
|
|
42
44
|
[att, error]
|
|
43
45
|
end
|
|
46
|
+
|
|
44
47
|
|
|
45
48
|
private
|
|
46
49
|
def fetch_uri(uri_str, max_file_size = 10)
|
|
@@ -141,13 +144,37 @@ module Zena
|
|
|
141
144
|
end
|
|
142
145
|
end
|
|
143
146
|
end
|
|
147
|
+
|
|
148
|
+
def render_upload
|
|
149
|
+
responds_to_parent do # execute the redirect in the iframe's parent window
|
|
150
|
+
render :update do |page|
|
|
151
|
+
if @node.new_record?
|
|
152
|
+
page.replace_html 'form_errors', error_messages_for(:node, :object => @node)
|
|
153
|
+
page.call 'UploadProgress.setAsError'
|
|
154
|
+
else
|
|
155
|
+
page.call 'UploadProgress.setAsFinished'
|
|
156
|
+
page.delay(1) do # allow the progress bar fade to complete
|
|
157
|
+
if js = params[:js]
|
|
158
|
+
page << js.gsub('NODE_ID', @node.zip.to_s)
|
|
159
|
+
end
|
|
160
|
+
if params[:reload]
|
|
161
|
+
page << "Zena.t().Zena.reload(#{params[:reload].inspect})"
|
|
162
|
+
end
|
|
163
|
+
if params[:redir]
|
|
164
|
+
page << "Zena.reload_and_close(#{params[:redir].inspect})"
|
|
165
|
+
else
|
|
166
|
+
page.redirect_to document_url(@node[:zip], :reload => params[:reload], :js => params[:js])
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
144
173
|
end # ControllerMethods
|
|
145
174
|
|
|
146
175
|
module ViewMethods
|
|
147
176
|
include RubyLess
|
|
148
|
-
safe_method [:upload_field, {:type => String}] => String
|
|
149
177
|
|
|
150
|
-
UPLOAD_KEY = defined?(Mongrel) ? 'upload_id' : "X-Progress-ID"
|
|
151
178
|
def upload_form_tag(url_opts, html_opts = {})
|
|
152
179
|
@uuid = UUIDTools::UUID.random_create.to_s.gsub('-','')
|
|
153
180
|
html_opts.reverse_merge!(:multipart => true, :id => "UploadForm#{@uuid}")
|
|
@@ -165,6 +192,8 @@ module Zena
|
|
|
165
192
|
end
|
|
166
193
|
|
|
167
194
|
def upload_field(opts = {})
|
|
195
|
+
uuid = opts[:uuid] || @uuid
|
|
196
|
+
dom = opts[:dom] || 'node'
|
|
168
197
|
case opts[:type].to_s
|
|
169
198
|
when 'onclick'
|
|
170
199
|
link = link_to_remote(_("change"), :update=>'upload_field', :url => get_uf_documents_path(:uuid => @uuid), :method => :get, :complete=>"['file', 'upload_field'].each(Element.toggle);")
|
|
@@ -174,11 +203,11 @@ module Zena
|
|
|
174
203
|
<div id="upload_field" class='toggle_div' style='display:none;'></div>
|
|
175
204
|
TXT
|
|
176
205
|
else
|
|
177
|
-
attach_file_id, attach_url_id = "af#{
|
|
178
|
-
onchange = %Q{onchange="Zena.get_filename(this,'
|
|
206
|
+
attach_file_id, attach_url_id = "af#{uuid}", "au#{uuid}"
|
|
207
|
+
onchange = %Q{onchange="Zena.get_filename(this,'#{dom}_title'); $('#{dom}_title').focus(); $('#{dom}_title').select();"}
|
|
179
208
|
<<-TXT
|
|
180
209
|
<div id='#{attach_file_id}' class='attach'><label for='attachment' onclick=\"['#{attach_file_id}', '#{attach_url_id}'].each(Element.toggle);\">#{_('file')} / <span class='off'>#{_('url')}</span></label>
|
|
181
|
-
<input style='line-height:1.5em;' id="attachment#{
|
|
210
|
+
<input style='line-height:1.5em;' id="attachment#{uuid}" name="attachment" #{onchange} class='file' type='file'/></div>
|
|
182
211
|
|
|
183
212
|
<div id='#{attach_url_id}' class='attach' style='display:none;'><label for='url' onclick=\"['#{attach_file_id}', '#{attach_url_id}'].each(Element.toggle);\"><span class='off'>#{_('file')}</span> / #{_('url')}</label>
|
|
184
213
|
<input style='line-height:1.5em;' size='30' id='attachment_url' type='text' #{onchange} name='attachment_url'/><br/></div>
|
data/lib/zena/use/urls.rb
CHANGED
|
@@ -18,10 +18,12 @@ module Zena
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
ALLOWED_REGEXP = /\A(([a-zA-Z]+)([0-9]+)|([#{String::ALLOWED_CHARS_IN_URL}\-%]+))(_[a-zA-Z]+|)(\..+|)\Z/
|
|
21
|
+
ALLOWED_REGEXP = /\A(([a-zA-Z]+)([0-9]+)|([#{String::ALLOWED_CHARS_IN_URL}\-%]+))(_[a-zA-Z]+|)(=[a-z0-9]+|)(\..+|)\Z/
|
|
22
22
|
|
|
23
23
|
module Common
|
|
24
|
-
|
|
24
|
+
# This is directly related to the FileMatch clause in httpd.rhtml (mod_expires for apaches)
|
|
25
|
+
CACHESTAMP_FORMATS = %w{ico flv jpg jpeg png gif js css swf}
|
|
26
|
+
|
|
25
27
|
def prefix
|
|
26
28
|
if visitor.is_anon?
|
|
27
29
|
visitor.lang
|
|
@@ -99,7 +101,7 @@ module Zena
|
|
|
99
101
|
end
|
|
100
102
|
|
|
101
103
|
if node.kind_of?(Document) && format == node.ext
|
|
102
|
-
if node.
|
|
104
|
+
if node.v_public? && !visitor.site.authentication?
|
|
103
105
|
# force the use of a cacheable path for the data, even when navigating in '/oo'
|
|
104
106
|
pre = node.version.lang
|
|
105
107
|
end
|
|
@@ -108,12 +110,9 @@ module Zena
|
|
|
108
110
|
if asset = opts.delete(:asset)
|
|
109
111
|
mode = nil
|
|
110
112
|
end
|
|
111
|
-
|
|
112
|
-
|
|
113
|
+
|
|
113
114
|
if should_cachestamp?(node, format, asset)
|
|
114
|
-
|
|
115
|
-
else
|
|
116
|
-
opts.delete(:cachestamp) # cachestamp
|
|
115
|
+
stamp = make_cachestamp(node, mode)
|
|
117
116
|
end
|
|
118
117
|
|
|
119
118
|
path = if !asset && node[:id] == visitor.site[:root_id] && mode.nil? && format == 'html'
|
|
@@ -122,7 +121,8 @@ module Zena
|
|
|
122
121
|
"#{abs_url_prefix}/#{pre}/" +
|
|
123
122
|
basepath_as_url(node.basepath) +
|
|
124
123
|
(mode ? "_#{mode}" : '') +
|
|
125
|
-
(asset ? "
|
|
124
|
+
(asset ? "=#{asset}" : '') +
|
|
125
|
+
(stamp ? ".#{stamp}" : '') +
|
|
126
126
|
(format == 'html' ? '' : ".#{format}")
|
|
127
127
|
else
|
|
128
128
|
"#{abs_url_prefix}/#{pre}/" +
|
|
@@ -130,7 +130,8 @@ module Zena
|
|
|
130
130
|
(node.klass.downcase ) +
|
|
131
131
|
(node[:zip].to_s ) +
|
|
132
132
|
(mode ? "_#{mode}" : '') +
|
|
133
|
-
(asset ? "
|
|
133
|
+
(asset ? "=#{asset}" : '') +
|
|
134
|
+
(stamp ? ".#{stamp}" : '') +
|
|
134
135
|
".#{format}"
|
|
135
136
|
end
|
|
136
137
|
append_query_params(path, opts)
|
|
@@ -150,7 +151,6 @@ module Zena
|
|
|
150
151
|
if opts == {}
|
|
151
152
|
path
|
|
152
153
|
else
|
|
153
|
-
cachestamp = opts.delete(:cachestamp)
|
|
154
154
|
tz = opts.delete(:tz)
|
|
155
155
|
list = opts.keys.map do |k|
|
|
156
156
|
# FIXME: DOC
|
|
@@ -181,14 +181,10 @@ module Zena
|
|
|
181
181
|
nil
|
|
182
182
|
end
|
|
183
183
|
end.flatten.compact
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
# TODO: replace '&' by '&' ? Or escape later ? Use h before zen_path in templates ? What about css/xls/other stuff ?
|
|
189
|
-
# Best solution: use 'h' in template when set in default
|
|
190
|
-
path + (list.empty? ? '' : "?#{list.sort.join('&')}")
|
|
191
|
-
end
|
|
184
|
+
|
|
185
|
+
# TODO: replace '&' by '&' ? Or escape later ? Use h before zen_path in templates ? What about css/xls/other stuff ?
|
|
186
|
+
# Best solution: use 'h' in template when set in default
|
|
187
|
+
path + (list.empty? ? '' : "?#{list.sort.join('&')}")
|
|
192
188
|
end
|
|
193
189
|
end
|
|
194
190
|
|
|
@@ -218,7 +214,7 @@ module Zena
|
|
|
218
214
|
end
|
|
219
215
|
|
|
220
216
|
def make_cachestamp(node, mode)
|
|
221
|
-
if mode
|
|
217
|
+
str = if mode
|
|
222
218
|
if node.kind_of?(Image)
|
|
223
219
|
if iformat = Iformat[mode]
|
|
224
220
|
"#{node.updated_at.to_i + iformat[:hash_id]}"
|
|
@@ -234,6 +230,8 @@ module Zena
|
|
|
234
230
|
else
|
|
235
231
|
node.updated_at.to_i.to_s
|
|
236
232
|
end
|
|
233
|
+
|
|
234
|
+
Digest::SHA1.hexdigest(str)[0..4]
|
|
237
235
|
end
|
|
238
236
|
|
|
239
237
|
# Url parameters (without format/mode/prefix...)
|
|
@@ -695,7 +693,7 @@ module Zena
|
|
|
695
693
|
|
|
696
694
|
def insert_ajax_args(target, hash_params, action)
|
|
697
695
|
hash_params << ":s => start_id"
|
|
698
|
-
hash_params << ":link_id => this.link_id" if @context[:has_link_id] && node.will_be?(Node)
|
|
696
|
+
hash_params << ":link_id => this.link_id" if @context[:has_link_id] && node.will_be?(Node) && !node.list_context?
|
|
699
697
|
|
|
700
698
|
# FIXME: when we have proper markup.dyn_params[:id] support,
|
|
701
699
|
# we should not need this crap anymore.
|
|
@@ -816,6 +814,7 @@ module Zena
|
|
|
816
814
|
end
|
|
817
815
|
|
|
818
816
|
def text_for_link(default = nil)
|
|
817
|
+
|
|
819
818
|
if dynamic_blocks?
|
|
820
819
|
expand_with
|
|
821
820
|
else
|
|
@@ -826,15 +825,19 @@ module Zena
|
|
|
826
825
|
end
|
|
827
826
|
|
|
828
827
|
if method
|
|
829
|
-
|
|
828
|
+
if method.opts[:html_safe]
|
|
829
|
+
method.literal || "<%= #{method} %>"
|
|
830
|
+
else
|
|
831
|
+
method.literal ? ::ERB::Util.html_escape(method.literal) : "<%=h #{method} %>"
|
|
832
|
+
end
|
|
830
833
|
elsif default
|
|
831
834
|
default
|
|
832
835
|
elsif node.will_be?(Node)
|
|
833
|
-
"<%= #{node(Node)}.prop['title'] %>"
|
|
836
|
+
"<%=h #{node(Node)}.prop['title'] %>"
|
|
834
837
|
elsif node.will_be?(Version)
|
|
835
|
-
"<%= #{node(Version)}.node.prop['title'] %>"
|
|
838
|
+
"<%=h #{node(Version)}.node.prop['title'] %>"
|
|
836
839
|
elsif node.will_be?(Link)
|
|
837
|
-
"<%= #{node(Link)}.name %>"
|
|
840
|
+
"<%=h #{node(Link)}.name %>"
|
|
838
841
|
else
|
|
839
842
|
_('edit')
|
|
840
843
|
end
|
|
@@ -59,11 +59,23 @@ module Zena
|
|
|
59
59
|
end
|
|
60
60
|
end
|
|
61
61
|
|
|
62
|
-
def version_id(lang = nil)
|
|
62
|
+
def version_id(lang = nil, ugps = visitor.group_ids)
|
|
63
63
|
lang ||= visitor.lang
|
|
64
|
-
access = can_see_redactions? ? vhash['w'] : vhash['r']
|
|
64
|
+
access = can_see_redactions?(ugps) ? vhash['w'] : vhash['r']
|
|
65
65
|
access[lang] || access[self[:ref_lang]] || access.values.first
|
|
66
66
|
end
|
|
67
|
+
|
|
68
|
+
# Return true if the current version can be seen by the public.
|
|
69
|
+
def v_public?
|
|
70
|
+
visitor.is_anon? ||
|
|
71
|
+
begin
|
|
72
|
+
anon = visitor.site.anon
|
|
73
|
+
# visible by anonymous
|
|
74
|
+
can_read?(anon, anon.group_ids) &&
|
|
75
|
+
# anonymous would see this exact version
|
|
76
|
+
version.id == version_id(visitor.lang, visitor.site.anon.group_ids)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
67
79
|
|
|
68
80
|
# Return the list of versions that are stored in the vhash and could be loaded depending
|
|
69
81
|
# on the visitor.
|