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.
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,2 @@
1
+ @node = @parent
2
+ update_page_content(page, @node)
@@ -2,9 +2,8 @@
2
2
 
3
3
  <table id='tasks_list' class='admin jobs' cellspacing="0">
4
4
  <tr>
5
- <th do='t'>execution</th>
6
- <th do='t'>info</th>
7
- <th do='t'></th>
5
+ <th><%= _('execution') %></th>
6
+ <th><%= _('info') %></th>
8
7
  </tr>
9
8
  <%= render :partial=>'sites/job', :collection=>@jobs %>
10
9
  </table>
@@ -1,6 +1,6 @@
1
1
  <%= upload_form_tag(:action => 'upload') %>
2
2
  <%= hidden_field 'node', 'parent_id', :value=>@node.parent_zip %>
3
- <% [:redir, :js].each do |p|; next unless params[p] %>
3
+ <% [:redir, :js, :reload].each do |p|; next unless params[p] %>
4
4
  <input type='hidden' name='<%= p %>' value='<%= h params[p] %>'/>
5
5
  <% end %>
6
6
  <p class="btn_validate"><input type="submit" value='<%= _('validate') %>'/></p>
@@ -1,5 +1,8 @@
1
1
  <%= upload_form_tag( :controller => 'nodes', :action => 'import', :id => @node.parent_zip ) %>
2
2
  <p class="btn_validate"><input type="submit" value='<%= _('validate') %>'/></p>
3
+ <% [:redir, :js, :reload].each do |p|; next unless params[p] %>
4
+ <input type='hidden' name='<%= p %>' value='<%= h params[p] %>'/>
5
+ <% end %>
3
6
 
4
7
  <%= upload_field %>
5
8
 
@@ -7,7 +10,7 @@
7
10
  <label for='node_klass'><%= _('class of first element') %></label>
8
11
  <%= select('node', 'klass', Node.classes_for_form, :selected => 'Page' ) %><br/>
9
12
 
10
- <% if @node.can_publish? && !visitor.site.auto_publish? %>
13
+ <% if @node.can_publish? && !@node.auto_publish? %>
11
14
  <label for='node_v_status'><%= _('publish nodes') %></label>
12
15
  <small><input type='checkbox' name='node[v_status]' value='50'/> <%= _('pub') %></small><br/>
13
16
  <% end -%>
@@ -1,6 +1,9 @@
1
1
  <%= form_tag( documents_path ) %>
2
2
  <%= hidden_field 'node', 'parent_id', :value => @node.parent_zip %>
3
3
  <p class="btn_validate"><input type="submit" onclick="$('loader').style.visibility = 'visible';" value='<%= _('validate') %>'/></p>
4
+ <% [:redir, :js, :reload].each do |p|; next unless params[p] %>
5
+ <input type='hidden' name='<%= p %>' value='<%= h params[p] %>'/>
6
+ <% end %>
4
7
 
5
8
  <input type='hidden' name='node[klass]' value='Template'/>
6
9
 
@@ -1,6 +1,9 @@
1
1
  <%= form_tag( documents_path ) %>
2
2
  <%= hidden_field 'node', 'parent_id', :value=>@node.parent_zip %>
3
3
  <p class="btn_validate"><input type="submit" onclick="$('loader').style.visibility = 'visible';" value='<%= _('validate') %>'/></p>
4
+ <% [:redir, :js, :reload].each do |p|; next unless params[p] %>
5
+ <input type='hidden' name='<%= p %>' value='<%= h params[p] %>'/>
6
+ <% end %>
4
7
 
5
8
  <label for='node_content_type'><%= _('content type') %></label>
6
9
  <input id='node_content_type' type='text' name='node[content_type]'/><br/>
@@ -3,7 +3,7 @@
3
3
  <label for='<%= col.name %>'><%= _(col.name) %></label>
4
4
  <% case col.ptype
5
5
  when :datetime %>
6
- <%= date_box(@node, col.name, :size=>15, :value => @node.prop[col.name]) %>
6
+ <%= date_box(@node, "node[#{col.name}]", :size=>15, :value => @node.prop[col.name]) %>
7
7
  <% else %>
8
8
  <%= text_area 'node', col.name, :cols => nil, :rows => 1, :value => @node.prop[col.name], :class => 'full_width' %>
9
9
  <% end %>
@@ -29,7 +29,7 @@
29
29
  }) %>
30
30
  </div>
31
31
  <div><%= node_action_link('add_doc', @node.zip) %></div>
32
- <% if @node.full_drive? && !visitor.site.auto_publish? %><div><small><input type='checkbox' name='node[v_backup]' value='true'/> <%= _('bak') %></small> <small><input type='checkbox' name='node[v_status]' value='50'<%= params[:pub] ? " checked='checked'" : '' %>/> <%= _('pub') %></small></div><% end -%>
32
+ <% if @node.full_drive? && !@node.auto_publish? %><div><small><input type='checkbox' name='node[v_backup]' value='true'/> <%= _('bak') %></small> <small><input type='checkbox' name='node[v_status]' value='50'<%= params[:pub] ? " checked='checked'" : '' %>/> <%= _('pub') %></small></div><% end -%>
33
33
  </div>
34
34
  <% partial.each_index do |i| %><div id='<%= partial[i] %>_tab' <%= i == 0 ? "" : "style='display:none;'" %> class='tab_content'>
35
35
  <%= render :partial=>"templates/edit_tabs/#{partial[i]}" %>
@@ -6,10 +6,10 @@ module Bricks
6
6
  end
7
7
  # If we have an exec skin, we check that t_url points in this skin's
8
8
  # directory to avoid letting the user render with any zafu template.
9
- def template_path_from_template_url_with_acls(template_url=params[:t_url])
9
+ def template_path_from_template_url_with_acls(suffix='', template_url=params[:t_url], build=true)
10
10
  if visitor.exec_acl && skin = visitor.exec_acl.exec_skin
11
11
  # Make sure t_url is using templates in the allowed Skin
12
- skin_name = skin.title.to_filename
12
+ skin_name = skin.skin_name
13
13
  unless template_url[0..skin_name.size] == skin_name + '/'
14
14
  # Wrong Skin !
15
15
  Node.logger.warn "Bad t_url used in ACL context (#{template_url}). Visitor = #{visitor.id} // #{visitor.login}"
@@ -17,7 +17,7 @@ module Bricks
17
17
  raise ActiveRecord::RecordNotFound
18
18
  end
19
19
  end
20
- template_path_from_template_url_without_acls(template_url)
20
+ template_path_from_template_url_without_acls(suffix, template_url, build)
21
21
  end
22
22
  end
23
23
 
@@ -65,6 +65,21 @@ class AclTest < Zena::Unit::TestCase
65
65
  end
66
66
  end # saving an acl with asset_host in query
67
67
 
68
+ context 'saving an acl with an error in rubyless syntax' do
69
+ subject do
70
+ acls(:rap)
71
+ end
72
+
73
+ should 'return an error' do
74
+ erebus_id = groups_id(:erebus)
75
+ visitor.instance_eval do
76
+ @group_ids = self.group_ids + [erebus_id]
77
+ end
78
+ assert !subject.update_attributes(:query => "nodes in site")
79
+ assert_equal 'parse error on value ["in", 1] (kIN)', subject.errors[:query]
80
+ end
81
+ end # saving an acl with asset_host in query
82
+
68
83
 
69
84
  context 'a visitor' do
70
85
  context 'with normal access' do
@@ -0,0 +1,190 @@
1
+ module Bricks
2
+ module Fs_skin
3
+ ELEM = "([a-zA-Z_]+)"
4
+ ELEM_REGEXP = %r{^#{ELEM}$}
5
+ SECURE_PATH_REGEXP = %r{^[a-zA-Z_/\-\+]+$}
6
+ STATIC_SKIN_REGEXP = %r{^#{ELEM}-#{ELEM}$}
7
+ ZAFU_URL_REGEXP = %r{^\$#{ELEM}-#{ELEM}/(.+)$}
8
+ BRICK_NAME_REGEXP = %r{^#{RAILS_ROOT}/bricks/#{ELEM}/zena/skins$}
9
+
10
+ module ControllerMethods
11
+ def self.included(base)
12
+ base.alias_method_chain :get_template_text, :fs_skin
13
+ base.alias_method_chain :template_url_for_asset, :fs_skin
14
+ base.alias_method_chain :get_best_template, :fs_skin
15
+ end
16
+
17
+ def get_template_text_with_fs_skin(path, section_id = nil, opts = {})
18
+ if path =~ ZAFU_URL_REGEXP
19
+ brick_name, skin_name, path = $1, $2, $3
20
+ Skin.text_from_fs_skin(brick_name, skin_name, path, opts)
21
+ elsif !(path =~ %r{^(/|\$)}) && section_id.nil? && @fs_skin_brick_name && @fs_skin_skin_name
22
+ Skin.text_from_fs_skin(@fs_skin_brick_name, @fs_skin_skin_name, path, opts)
23
+ else
24
+ return *get_template_text_without_fs_skin(path, section_id, opts)
25
+ end
26
+ end
27
+
28
+ def template_url_for_asset_with_fs_skin(opts)
29
+ # TODO
30
+ template_url_for_asset_without_fs_skin(opts)
31
+ end
32
+
33
+ def get_best_template_with_fs_skin(kpaths, format, mode, skin)
34
+ return get_best_template_without_fs_skin(kpaths, format, mode, skin) unless fs_skin = skin.z_fs_skin
35
+ if idx_template = IdxTemplate.first(
36
+ :conditions => ["tkpath IN (?) AND format = ? AND mode #{mode ? '=' : 'IS'} ? AND (skin_id = ? OR fs_skin = ?) AND site_id = ?",
37
+ kpaths, format, mode, skin.id, fs_skin, skin.site_id],
38
+ :order => "length(tkpath) DESC, skin_id DESC"
39
+ )
40
+ if idx_template.path.nil?
41
+ template = secure(Template) { Template.find(idx_template.node_id) }
42
+ get_best_template_without_fs_skin(kpaths, format, mode, skin, template)
43
+ elsif fs_skin =~ STATIC_SKIN_REGEXP
44
+ @fs_skin_brick_name, @fs_skin_skin_name = $1, $2
45
+ if idx_template.path =~ SECURE_PATH_REGEXP
46
+ zafu_url = "$#{@fs_skin_brick_name}-#{@fs_skin_skin_name}/#{idx_template.path}"
47
+ template = Template.new
48
+ template.tkpath = idx_template.tkpath
49
+ [zafu_url, template]
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ # TODO
56
+ # Asset resolution: route = /fs_skin/fs_skin-blog/img/style.css
57
+ # ===> fs_skin brick ==> brick path
58
+ # ===> blog/img/style.css ==> brick path/zena/skins/ blog/img/style.css
59
+ # Cache in public directory
60
+ # FIXME: clear_cache should erase /home/fs_skin
61
+ end # ControllerMethods
62
+
63
+ module SkinMethods
64
+ def self.included(base)
65
+
66
+ base.class_eval do
67
+ property do |p|
68
+ p.string 'z_fs_skin'
69
+ end
70
+
71
+ safe_property 'z_fs_skin'
72
+ validate :validate_z_fs_skin
73
+ alias_method_chain :skin_name, :fs_skin
74
+ end
75
+
76
+ # We move this method here so that we do not need to reference
77
+ # Bricks::Fs_skin in I18n when fs_skin brick is disabled.
78
+ def base.text_from_fs_skin(brick_name, skin_name, path, opts)
79
+ if path =~ SECURE_PATH_REGEXP
80
+ fullpath = "$#{brick_name}-#{skin_name}/#{path}"
81
+ section_id = nil
82
+ template = nil
83
+
84
+ abs_path = File.join(RAILS_ROOT, 'bricks', brick_name, 'zena', 'skins', skin_name, path)
85
+ if opts[:ext]
86
+ abs_path_l = abs_path + ".#{visitor.lang}.#{opts[:ext]}"
87
+ abs_path = abs_path + ".#{opts[:ext]}"
88
+ else
89
+ abs_path_l ||= abs_path + ".zafu"
90
+ end
91
+ if abs_path_l
92
+ if text = File.exist?(abs_path_l) ? File.read(abs_path_l) : nil
93
+ return text, fullpath, section_id, template
94
+ end
95
+ end
96
+ if text = File.exist?(abs_path) ? File.read(abs_path) : nil
97
+ return text, fullpath, section_id, template
98
+ end
99
+ end
100
+ end
101
+ end
102
+
103
+ def skin_name_with_fs_skin
104
+ z_fs_skin ? ('$' + z_fs_skin) : skin_name_without_fs_skin
105
+ end
106
+
107
+ private
108
+ def validate_z_fs_skin
109
+ if !(z_fs_skin.nil? || z_fs_skin =~ STATIC_SKIN_REGEXP)
110
+ errors.add(:z_fs_skin, _('invalid'))
111
+ end
112
+ true
113
+ end
114
+ end # SkinMethods
115
+
116
+ module SiteMethods
117
+ def self.included(base)
118
+ base.alias_method_chain :rebuild_index, :fs_skin
119
+ end
120
+
121
+ def rebuild_index_with_fs_skin(nodes = nil, page = nil, page_count = nil)
122
+ if !page
123
+ Zena::SiteWorker.perform(self, :rebuild_fs_skin_index, nil)
124
+ end
125
+ rebuild_index_without_fs_skin(nodes, page, page_count)
126
+ end
127
+
128
+ def rebuild_fs_skin_index
129
+ Zena::Db.execute "DELETE FROM idx_templates WHERE node_id IS NULL AND site_id = #{id}"
130
+ Bricks.paths_for('zena/skins').each do |p|
131
+ if p =~ BRICK_NAME_REGEXP
132
+ brick_name = $1
133
+ list = []
134
+ Dir.foreach(p) do |skin_name|
135
+ if skin_name =~ ELEM_REGEXP
136
+ build_fs_skin_index(brick_name, skin_name, "#{p}/#{skin_name}")
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end
142
+
143
+ private
144
+ def add_fs_skin_symlink(brick_name, skin_name, skin_path)
145
+ source_path = File.join(skin_path, 'static')
146
+ target_dir = File.join(RAILS_ROOT, 'public', 'static')
147
+ target_path = File.join(target_dir, "#{brick_name}-#{skin_name}")
148
+ if File.exist?(source_path) && !File.exist?(target_path)
149
+ if !File.exist?(target_dir)
150
+ Dir.mkdir(target_dir)
151
+ end
152
+ FileUtils.symlink_or_copy(source_path, target_path)
153
+ end
154
+ end
155
+
156
+ def build_fs_skin_index(brick_name, skin_name, path)
157
+ add_fs_skin_symlink(brick_name, skin_name, path)
158
+ # path = absolute path
159
+ # 1. Find all templates
160
+ Dir.foreach(path) do |elem|
161
+ next if elem =~ /^\./
162
+ elem_path = File.join(path, elem)
163
+ if File.directory?(elem_path)
164
+ build_fs_skin_index(brick_name, skin_name, elem_path)
165
+ elsif elem =~ Template::MODE_FORMAT_FROM_TITLE
166
+ # 2. Get klass, mode, format
167
+ klass = $1
168
+ mode = $4.blank? ? nil : $4
169
+ format = $6 || 'html'
170
+ idx_path = elem_path[%r{^#{RAILS_ROOT}/bricks/#{brick_name}/zena/skins/#{skin_name}/(.+)\.zafu$}, 1]
171
+ # 3. Get kpath
172
+ if idx_path && vclass = VirtualClass[klass]
173
+ tkpath = vclass.kpath
174
+
175
+ # 4. insert idx_template entry (kpath, site_id, mode, format, path relative to bricks/brick/zena/skins/skin_name)
176
+ IdxTemplate.create(
177
+ :tkpath => tkpath,
178
+ :mode => mode,
179
+ :format => format,
180
+ :site_id => id,
181
+ :fs_skin => "#{brick_name}-#{skin_name}",
182
+ :path => idx_path
183
+ )
184
+ end
185
+ end
186
+ end
187
+ end
188
+ end # SiteMethods
189
+ end # Fs_skin
190
+ end # Bricks
@@ -0,0 +1 @@
1
+ Zena.use Bricks::Fs_skin
@@ -0,0 +1,12 @@
1
+ class AddFsSkinToIdxTemplates < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :idx_templates, :fs_skin, :string, :limit => 30
4
+ add_column :idx_templates, :path, :string, :limit => 300
5
+ add_index :idx_templates, [:fs_skin], :name => "index_idx_templates_on_fs_skin"
6
+ end
7
+
8
+ def self.down
9
+ remove_index :idx_templates, :name => "index_idx_templates_on_fs_skin"
10
+ remove_column :idx_templates, :fs_skin
11
+ end
12
+ end
@@ -59,7 +59,7 @@
59
59
  <div style="clear: both;"> </div>
60
60
 
61
61
  <div id="footer">
62
- &copy; Copyright <a href="#">Static blog</a> | <r:zena type='made'/> | <r:login_link/>
62
+ &copy; Copyright <a href="#">Fs_skin blog</a> | <r:zena type='made'/> | <r:login_link/>
63
63
  </div>
64
64
  </div>
65
65
  </body>
@@ -0,0 +1,26 @@
1
+
2
+ namespace :fs_skin do
3
+ desc 'rebuild fs_skin index'
4
+ task :index => :environment do
5
+ # Make sure all bricks are loaded before executing the index rebuild
6
+ Zena::Use.upgrade_class('Site')
7
+
8
+ include Zena::Acts::Secure
9
+ if ENV['HOST']
10
+ sites = [Site.find_by_host(ENV['HOST'])]
11
+ else
12
+ sites = Site.all
13
+ end
14
+
15
+ sites.each do |site|
16
+ Thread.current[:visitor] = site.any_admin
17
+ if ENV['WORKER'] == 'false' || RAILS_ENV == 'test'
18
+ # We avoid SiteWorker.
19
+ site.rebuild_fs_skin_index
20
+ else
21
+ # We try to use the site worker.
22
+ Zena::SiteWorker.perform(site, :rebuild_fs_skin_index, nil)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,8 +1,8 @@
1
1
  require File.dirname(__FILE__) + '/../../../../../test/test_helper'
2
2
 
3
- class StaticIntegrationTest < Zena::Integration::TestCase
3
+ class Fs_skinIntegrationTest < Zena::Integration::TestCase
4
4
 
5
- context 'A page using a static Skin' do
5
+ context 'A page using a fs_skin Skin' do
6
6
  subject do
7
7
  secure(Node) { nodes(:wiki) }
8
8
  end
@@ -10,7 +10,7 @@ class StaticIntegrationTest < Zena::Integration::TestCase
10
10
  setup do
11
11
  $_test_site = 'zena'
12
12
  login(:lion)
13
- skin = secure(Skin) { Skin.create(:title => 'foo', :z_static => 'static-blog', :parent_id => nodes_id(:skins), :v_status => Zena::Status::Pub)}
13
+ skin = secure(Skin) { Skin.create(:title => 'foo', :z_fs_skin => 'fs_skin-blog', :parent_id => nodes_id(:skins), :v_status => Zena::Status::Pub)}
14
14
  subject.skin_id = skin.id
15
15
  assert subject.save
16
16
  end
@@ -20,11 +20,11 @@ class StaticIntegrationTest < Zena::Integration::TestCase
20
20
  FileUtils.rmtree("#{SITES_ROOT}/test.host/zafu")
21
21
  end
22
22
 
23
- should 'use static template' do
23
+ should 'use fs_skin template' do
24
24
  get "http://test.host/en/blog#{subject.zip}.html"
25
25
  assert_response :success
26
- assert_match %r{Copyright <a href="#">Static blog</a>}, response.body
26
+ assert_match %r{Copyright <a href="#">Fs_skin blog</a>}, response.body
27
27
  end
28
28
  end # with normal access
29
- end # A page using a static Skin
29
+ end # A page using a fs_skin Skin
30
30
  end
@@ -0,0 +1,33 @@
1
+ require File.dirname(__FILE__) + '/../../../../../test/test_helper'
2
+
3
+ class Fs_skinTest < Zena::Unit::TestCase
4
+
5
+ context 'A Skin' do
6
+ setup do
7
+ login(:lion)
8
+ end
9
+
10
+ subject do
11
+ secure(Node) { nodes(:wikiSkin) }
12
+ end
13
+
14
+ should 'have z_fs_skin prop' do
15
+ subject.z_fs_skin = 'foo'
16
+ assert_equal 'foo', subject.prop['z_fs_skin']
17
+ end
18
+
19
+ should 'allow brick-skin values' do
20
+ assert subject.update_attributes(:z_fs_skin => 'fs_skin-blog')
21
+ end
22
+
23
+ should 'allow nil values' do
24
+ assert subject.update_attributes(:z_fs_skin => 'fs_skin-blog')
25
+ assert subject.update_attributes(:z_fs_skin => nil)
26
+ end
27
+
28
+ should 'not allow any value' do
29
+ assert !subject.update_attributes(:z_fs_skin => '../foo-/bar/..')
30
+ assert_equal 'invalid', subject.errors[:z_fs_skin]
31
+ end
32
+ end # A Skin
33
+ end