zena 1.1.1 → 1.1.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.
Files changed (55) hide show
  1. data/History.txt +15 -0
  2. data/app/controllers/nodes_controller.rb +13 -8
  3. data/app/models/acl.rb +19 -5
  4. data/app/models/column.rb +2 -0
  5. data/app/models/node.rb +3 -2
  6. data/app/models/site.rb +3 -0
  7. data/app/models/user.rb +1 -1
  8. data/app/views/columns/_add.html.erb +2 -2
  9. data/app/views/columns/_form.html.erb +8 -2
  10. data/app/views/columns/_li.html.erb +4 -1
  11. data/app/views/columns/index.html.erb +2 -2
  12. data/app/views/zafu/default/Node-+adminLayout.zafu +9 -1
  13. data/app/views/zafu/default/Node-admin.zafu +6 -3
  14. data/bricks/acls/lib/bricks/acls.rb +7 -7
  15. data/bricks/acls/zena/test/unit/acl_test.rb +33 -11
  16. data/bricks/math/lib/bricks/math.rb +11 -8
  17. data/bricks/worker/zena/worker +1 -0
  18. data/bricks/zena/zena/migrate/20111101103900_add_comment_to_columns.rb +9 -0
  19. data/config/gems.yml +7 -4
  20. data/lib/bricks.rb +2 -0
  21. data/lib/bricks/helper.rb +18 -0
  22. data/lib/zena.rb +1 -1
  23. data/lib/zena/console.rb +24 -0
  24. data/lib/zena/db_helper/abstract_db.rb +5 -2
  25. data/lib/zena/db_helper/mysql.rb +6 -3
  26. data/lib/zena/info.rb +1 -1
  27. data/lib/zena/init.rb +22 -0
  28. data/lib/zena/use/ajax.rb +1 -1
  29. data/lib/zena/use/forms.rb +6 -2
  30. data/lib/zena/use/i18n.rb +13 -65
  31. data/lib/zena/use/ml_index.rb +15 -0
  32. data/lib/zena/use/query_node.rb +10 -7
  33. data/lib/zena/use/rendering.rb +5 -0
  34. data/lib/zena/use/upload.rb +5 -2
  35. data/lib/zena/use/version_hash.rb +2 -0
  36. data/public/stylesheets/backend.css +6 -3
  37. data/public/stylesheets/zena.css +2 -2
  38. data/test/integration/navigation_test.rb +25 -1
  39. data/test/integration/query_node/basic.yml +6 -1
  40. data/test/integration/query_node/filters.yml +6 -1
  41. data/test/integration/query_node/idx_scope.yml +10 -0
  42. data/test/integration/zafu_compiler/ajax.yml +19 -0
  43. data/test/integration/zafu_compiler/display.yml +4 -0
  44. data/test/integration/zafu_compiler/meta.yml +8 -0
  45. data/test/selenium/Drop/drop1.rsel +6 -10
  46. data/test/selenium/Drop/drop2.rsel +6 -3
  47. data/test/selenium/Drop/drop3.rsel +19 -34
  48. data/test/selenium/Drop/drop4.rsel +25 -33
  49. data/test/sites/zena/columns.yml +4 -3
  50. data/test/unit/bricks_test.rb +24 -0
  51. data/test/unit/column_test.rb +5 -0
  52. data/test/unit/zena/use/ml_index_test.rb +26 -0
  53. data/test/unit/zena/use/version_hash_test.rb +0 -1
  54. data/zena.gemspec +28 -122
  55. metadata +85 -145
@@ -1,6 +1,7 @@
1
1
  require 'digest/sha1'
2
2
  module Bricks
3
3
  module Math
4
+
4
5
  module ViewMethods
5
6
  def math_asset(opts)
6
7
  content = opts[:content]
@@ -66,15 +67,17 @@ module Bricks
66
67
  f.syswrite("\n\\end{document}\n")
67
68
  end
68
69
 
69
- system("cd #{File.dirname(tempf.path)}; latex -interaction=batchmode #{"#{base}.tex".inspect} &> '#{base}.err'")
70
- if !File.exists?("#{base}.dvi")
71
- Node.logger.error(File.read("#{base}.err"))
72
- system("cp '#{Zena::ROOT}/public/world.png' #{filepath.inspect}")
73
- else
74
- system("dvips #{tempf.path}.dvi -E -o #{base}.ps &> '#{base}.err'") #|| Node.logger.error(File.read("#{base}.err"))
75
- system("convert -units PixelsPerInch -density 150 -matte -fuzz '10%' -transparent '#ffffff' #{base}.ps #{filepath.inspect} &> '#{base}.err'") #|| Node.logger.error(File.read("#{base}.err"))
70
+ ok, msg, err = Bricks::run(File.dirname(tempf.path), 'latex', '-interaction=batchmode', "#{base}.tex")
71
+ if ok
72
+ ok, msg, err = Bricks::run(nil, 'dvips', "#{tempf.path}.dvi", '-E', '-o', "#{base}.ps")
73
+ end
74
+ if ok
75
+ ok, msg, err = Bricks::run(nil, 'convert', '-units', 'PixelsPerInch', '-density', '150', '-matte', '-fuzz', '10%', '-transparent', '#ffffff', "#{base}.ps", filepath)
76
+ end
77
+ if !ok
78
+ Node.logger.error(err)
79
+ Bricks::run(nil, 'cp', "#{Zena::ROOT}/public/world.png", filepath.inspect)
76
80
  end
77
-
78
81
  ensure
79
82
  system("rm -rf #{tempf.path.inspect} #{(tempf.path + '.*').inspect}")
80
83
  end
@@ -39,6 +39,7 @@ Daemons.run_proc('worker', daemon_options) do
39
39
 
40
40
  require 'delayed/worker'
41
41
  begin
42
+ require 'thinking_sphinx'
42
43
  require 'thinking_sphinx/deltas/delayed_delta'
43
44
  rescue LoadError
44
45
  # Ignore
@@ -0,0 +1,9 @@
1
+ class AddCommentToColumns < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :columns, :comment, :text
4
+ end
5
+
6
+ def self.down
7
+ remove_column :columns, :comment
8
+ end
9
+ end
@@ -2,7 +2,7 @@ hpricot:
2
2
  gettext: '= 2.1.0'
3
3
  ruby-recaptcha: '= 1.0.3'
4
4
  syntax: '= 1.0.0'
5
- tzinfo: '= 0.3.26'
5
+ tzinfo:
6
6
  uuidtools: '= 2.0.0'
7
7
  rails: '= 2.3.11'
8
8
  json: '= 1.5.1'
@@ -12,13 +12,16 @@ will_paginate: '~> 2.3.12'
12
12
  differ: '= 0.1.2'
13
13
  shoulda: '= 2.10.3'
14
14
  httparty: '= 0.7.8'
15
+ open4:
16
+ daemons: # upload progress
17
+ gem_plugin: # upload progress
15
18
 
16
- querybuilder: '= 1.0.1'
19
+ querybuilder: '= 1.1.0'
17
20
  yamltest: '= 0.7.0'
18
- rubyless: '= 0.8.5'
21
+ rubyless: '= 0.8.6'
19
22
  property: '= 2.2.0'
20
23
  versions: '= 0.3.1'
21
- zafu: '= 0.8.3'
24
+ zafu: '= 0.8.4'
22
25
 
23
26
  jeweler:
24
27
 
@@ -1,9 +1,11 @@
1
1
  require 'bricks/requirements_validation'
2
2
  require 'bricks/loader'
3
+ require 'bricks/helper'
3
4
 
4
5
  module Bricks
5
6
  extend Bricks::RequirementsValidation
6
7
  extend Bricks::Loader
8
+ extend Bricks::Helper
7
9
  CONFIG = self.config_for_active_bricks
8
10
  end
9
11
 
@@ -0,0 +1,18 @@
1
+ require 'open4'
2
+ module Bricks
3
+ module Helper
4
+ def run(cd, *args)
5
+ status = 0
6
+ msg = nil
7
+ err = nil
8
+ cd ||= '.'
9
+ Dir.chdir(cd) do
10
+ status = Open4::popen4(*args) do |pid, stdin, stdout, stderr|
11
+ msg = stdout.read
12
+ err = stderr.read
13
+ end
14
+ end
15
+ return status == 0, msg, err
16
+ end
17
+ end
18
+ end
@@ -19,7 +19,7 @@ module Zena
19
19
  end
20
20
  end
21
21
 
22
- ASSET_PORT = Bricks.raw_config['asset_port']
22
+ ASSET_PORT = Bricks.raw_config['asset_port'].to_i
23
23
 
24
24
  ENABLE_LATEX = true && has_executable('pdflatex') # enable LateX post-rendering
25
25
  ENABLE_FOP = true && has_executable('fop', 'xsltproc') # enable xsl-fo post-rendering
@@ -70,6 +70,30 @@ module Zena
70
70
  end
71
71
  end
72
72
 
73
+ # Transform every value of a given property by using a block with |node, old_value| and
74
+ # returning the new value.
75
+ def change_prop(pseudo_sql, key)
76
+ unless block_given?
77
+ puts "You need to provide a block |node, old_value| and return the new value"
78
+ return
79
+ end
80
+ foreach(pseudo_sql) do |node|
81
+ node.versions.each do |v|
82
+ prop = v.prop
83
+ val = prop[key]
84
+ new_val = yield(node, val)
85
+ unless new_val == val
86
+ if new_val
87
+ prop[key] = new_val
88
+ else
89
+ prop.delete(key)
90
+ end
91
+ Zena::Db.execute "UPDATE #{v.class.table_name} SET properties=#{Zena::Db.quote(v.class.encode_properties(prop))} WHERE id=#{v[:id]}"
92
+ end
93
+ end
94
+ end
95
+ end
96
+
73
97
  def login(name, host = nil)
74
98
  finder = {}
75
99
  finder[:conditions] = cond = [[]]
@@ -118,8 +118,9 @@ module Zena
118
118
  end
119
119
 
120
120
  # Return a string matching the SQLiss function.
121
- def sql_function(function, arg)
122
- return arg unless function
121
+ def sql_function(function, *args)
122
+ return args.first unless function
123
+ arg = args.first
123
124
  case function
124
125
  when 'count'
125
126
  "COUNT(#{arg})"
@@ -129,6 +130,8 @@ module Zena
129
130
  "MAX(#{arg})"
130
131
  when 'sum'
131
132
  "SUM(#{arg})"
133
+ when 'coalesce'
134
+ "COALESCE(#{args.join(',')})"
132
135
  else
133
136
  super
134
137
  end
@@ -37,7 +37,7 @@ module Zena
37
37
  end
38
38
 
39
39
  def table_options
40
- 'type=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci'
40
+ 'ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci'
41
41
  end
42
42
 
43
43
  def update_value(name, opts)
@@ -78,8 +78,9 @@ module Zena
78
78
  end
79
79
 
80
80
  # Return a string matching the SQLiss function.
81
- def sql_function(function, arg)
82
- return arg unless function
81
+ def sql_function(function, *args)
82
+ return args.first unless function
83
+ arg = args.first
83
84
  case function
84
85
  when 'year'
85
86
  "year(#{arg})"
@@ -91,6 +92,8 @@ module Zena
91
92
  "DATE(#{arg})"
92
93
  when 'random'
93
94
  'RAND()'
95
+ when 'coalesce'
96
+ "COALESCE(#{args.join(',')})"
94
97
  else
95
98
  super
96
99
  end
@@ -1,4 +1,4 @@
1
1
  module Zena
2
- VERSION = '1.1.1'
2
+ VERSION = '1.1.2'
3
3
  ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
4
4
  end
@@ -0,0 +1,22 @@
1
+ # This is a dummy file to make mongrel happy when
2
+ # gem_plugin starts to do stupid things.
3
+ # The other solution would be for the gem_plugin to get fixed.
4
+ # See http://rubyforge.org/tracker/index.php?func=detail&aid=16145&group_id=1306&atid=5145
5
+ #
6
+ =begin
7
+ ----[ diff -u /usr/lib/ruby/gems/1.8/gems/gem_plugin-0.2.3/lib/gem_plugin.rb{~,} ]----
8
+ --- /usr/lib/ruby/gems/1.8/gems/gem_plugin-0.2.3/lib/gem_plugin.rb~ 2007-12-06 17:34:58.000000000 +0100
9
+ +++ /usr/lib/ruby/gems/1.8/gems/gem_plugin-0.2.3/lib/gem_plugin.rb 2007-12-06 17:35:09.000000000 +0100
10
+ @@ -130,8 +130,9 @@
11
+ # Previously was set wrong, we already have the correct gem path!
12
+ #gem_dir = File.join(Gem.dir, "gems", "#{gem.name}-#{gem.version}")
13
+ gem_dir = File.join(Gem.dir, "gems", path)
14
+ -
15
+ - require File.join(gem_dir, "lib", gem.name, "init.rb")
16
+ + init_rb = File.join(gem_dir, "lib", gem.name, "init.rb")
17
+ +
18
+ + require init_rb if File.readable?(init_rb)
19
+ @gems[gem.name] = gem_dir
20
+ end
21
+ end
22
+ =end
@@ -223,7 +223,7 @@ module Zena
223
223
 
224
224
  markup.tag ||= 'div'
225
225
 
226
- if @name.blank?
226
+ if node.instance_variable_get(:@dom_prefix).blank?
227
227
  # make sure we have a scope
228
228
  node.dom_prefix = dom_name
229
229
  end
@@ -491,8 +491,12 @@ module Zena
491
491
  r_select
492
492
  when 'date_box', 'date'
493
493
  return parser_error("date_box without name") unless attribute
494
- code = ::RubyLess.translate(self, "this.#{attribute}")
495
- value = @context[:in_add] ? "''" : code
494
+ if value = @params[:value]
495
+ code = ::RubyLess.translate(self, value)
496
+ else
497
+ code = ::RubyLess.translate(self, "this.#{attribute}")
498
+ end
499
+ value = code # @context[:in_add] ? "''" : code
496
500
  html_params = [':size => 15']
497
501
  [:style, :class, :onclick, :size, :time].each do |key|
498
502
  html_params << ":#{key} => #{@params[key].inspect}" if @params[key]
@@ -114,13 +114,17 @@ module Zena
114
114
 
115
115
  # Choose best language to display content.
116
116
  # 1. 'test.host/oo?lang=en' use 'lang', redirect without lang
117
+ # 2. 'test.host/nodes/12?node[v_lang]=es
117
118
  # 3. 'test.host/oo' use visitor[:lang]
118
- # 4. 'test.host/' use session[:lang]
119
- # 5. 'test.host/oo' use visitor lang
120
- # 6. 'test.host/' use HTTP_ACCEPT_LANGUAGE
121
- # 7. 'test.host/' use default language
119
+ # 4. 'test.host/es' use prefix ONLY ENABLED FOR html format (see below)
120
+ # 5. 'test.host/' use session[:lang]
121
+ # 6. 'test.host/oo' use visitor lang
122
+ # 7. 'test.host/' use HTTP_ACCEPT_LANGUAGE
123
+ # 8. 'test.host/' use default language
122
124
  #
123
- # 8. 'test.host/fr' the redirect for this rule is called once we are sure the request is not for document data (lang in this case can be different from what the visitor is visiting due to caching optimization)
125
+ # 4. 'test.host/es' the redirect for this rule is called once we are sure the request is
126
+ # not for document data (lang in this case can be different from what the visitor is
127
+ # visiting due to caching optimization).
124
128
  def set_lang
125
129
  if params[:prefix] =~ /^\d+$/
126
130
  # this has nothing to do with set_lang...
@@ -132,7 +136,11 @@ module Zena
132
136
  chosen_lang = nil
133
137
  [
134
138
  params[:lang],
139
+ # FIXME: This is good to protect templates and other documents but is *NOT* nice when translating a website !!
140
+ # What should we do ?
135
141
  params[:node] ? params[:node][:v_lang] : nil,
142
+ # Avoid redirects for static assets (cached documents).
143
+ request.format == Mime::HTML ? params[:prefix] : nil,
136
144
  visitor.is_anon? ? session[:lang] : visitor.lang,
137
145
  (request.headers['HTTP_ACCEPT_LANGUAGE'] || '').split(',').sort {|a,b| (b.split(';q=')[1] || 1.0).to_f <=> (a.split(';q=')[1] || 1.0).to_f }.map {|l| l.split(';')[0].split('-')[0] },
138
146
  (visitor.is_anon? ? visitor.lang : nil), # anonymous user's lang comes last
@@ -142,7 +150,6 @@ module Zena
142
150
  break
143
151
  end
144
152
  end
145
-
146
153
  set_visitor_lang(chosen_lang || current_site[:default_lang])
147
154
  true
148
155
  end
@@ -374,66 +381,7 @@ module Zena
374
381
  end
375
382
 
376
383
  alias r_t r_trans
377
- #def r_trans
378
- # static = true
379
- # if @params[:text]
380
- # text = @params[:text]
381
- # elsif @params[:attr]
382
- # text = "#{node_attribute(@params[:attr])}"
383
- # static = false
384
- # else
385
- # res = []
386
- # text = ""
387
- # @blocks.each do |b|
388
- # if b.kind_of?(String)
389
- # res << b.inspect
390
- # text << b
391
- # elsif ['show', 'current_date'].include?(b.method)
392
- # res << expand_block(b, :trans=>true)
393
- # static = false
394
- # else
395
- # # ignore
396
- # end
397
- # end
398
- # unless static
399
- # text = res.join(' + ')
400
- # end
401
- # end
402
- # if static
403
- # _(text)
404
- # else
405
- # "<%= _(#{text}) %>"
406
- # end
407
- #end
408
-
409
384
 
410
- # show language selector
411
- #def r_lang_links
412
- # if wrap_tag = @params[:wrap]
413
- # wrap_tag = Zafu::Markup.new(wrap_tag)
414
- # tag_in = "<#{opts[:wrap]}>"
415
- # tag_out = "</#{opts[:wrap]}>"
416
- # else
417
- # tag_in = tag_out = ''
418
- # end
419
- # res = []
420
- # visitor.site.lang_list.each do |l|
421
- # if l == visitor.lang
422
- # if opts[:wrap]
423
- # res << "<#{opts[:wrap]} class='on'>#{l}" + tag_out
424
- # else
425
- # res << "<em>#{l}</em>"
426
- # end
427
- # else
428
- # if visitor.is_anon? && params[:prefix]
429
- # res << tag_in + link_to(l, params.merge(:prefix => l)) + tag_out
430
- # else
431
- # res << tag_in + link_to(l, params.merge(:lang => l)) + tag_out
432
- # end
433
- # end
434
- # end
435
- # res.join(opts[:join] || '')
436
- #end
437
385
  protected
438
386
 
439
387
  # Overwriten from Zafu to insert dictionary in partial if there is one
@@ -53,6 +53,21 @@ module Zena
53
53
  end
54
54
  end
55
55
  end # ModelMethods
56
+
57
+ module SiteMethods
58
+ def self.included(base)
59
+ base.before_save :rebuild_index_on_lang_list_change
60
+ end
61
+
62
+ protected
63
+ def rebuild_index_on_lang_list_change
64
+ if languages_changed? && !new_record?
65
+ # delete all ml entries for this site and rebuild
66
+ Zena::Db.execute "DELETE idx FROM idx_nodes_ml_strings idx INNER JOIN nodes ON idx.node_id = nodes.id WHERE nodes.site_id = #{self[:id]}"
67
+ rebuild_index
68
+ end
69
+ end
70
+ end # SiteMethods
56
71
  end # MLIndex
57
72
  end # Use
58
73
  end # Zena
@@ -197,13 +197,15 @@ module Zena
197
197
  end
198
198
  end
199
199
 
200
+ def process_idx_field(scope_field)
201
+ scope_field
202
+ end
203
+
200
204
  # Overwrite this and take care to check for valid fields.
201
205
  def process_field(field_name)
202
206
  if fld = @query.attributes_alias[field_name]
203
207
  # use custom query alias value defined in select clause: 'custom_a AS validation'
204
208
  return processing_filter? ? "(#{fld})" : fld
205
- elsif processing_filter? && scope_field = get_scope_index_field(field_name)
206
- scope_field
207
209
  elsif processing_filter? && map_def = self.class.filter_fields[field_name]
208
210
  # Special filter fields such as 'role', 'tag' or 'class'
209
211
  if map_def.kind_of?(String)
@@ -291,7 +293,7 @@ module Zena
291
293
  "params[#{pagination_key.to_sym.inspect}]"
292
294
  end
293
295
 
294
- # Handle special case for 'class = ' and 'role = '
296
+ # Handle special case for 'class = ' and 'role = ' and 'foo.date ='
295
297
  def process_equal(left, right)
296
298
  if (left == [:field, 'class'] || left == [:field, 'klass']) &&
297
299
  (right[0] == :field || right[0] == :string)
@@ -353,20 +355,21 @@ module Zena
353
355
  end
354
356
 
355
357
  scope_idx_field = "#{class_name}_#{field_name}"
356
- if get_scope_index_field(scope_idx_field)
357
- return [[:field, scope_idx_field], function]
358
+ if fld = get_scope_index_field(scope_idx_field)
359
+ return [[:idx_field, fld], function]
358
360
  else
359
361
  # not a scope index field
360
362
  return [arg1, arg2]
361
363
  end
362
364
  end
363
365
 
364
- def process_function(arg, method)
366
+ def process_function(arg, method, *args)
365
367
  # Resolve scope index fields
366
368
  arg, method = resolve_scope_idx_fields(arg, method)
367
369
  if method
368
370
  arg, method = process(arg), process(method)
369
- Zena::Db.sql_function(method, arg)
371
+ args = [arg] + args.map{|a| process(a)}
372
+ Zena::Db.sql_function(method, *args)
370
373
  else
371
374
  process(arg)
372
375
  end