zena 0.15.2 → 0.16.0

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 (284) hide show
  1. data/.gitignore +20 -0
  2. data/CREDITS +27 -0
  3. data/Capfile +3 -0
  4. data/DEVELOPERS +46 -0
  5. data/History.txt +15 -0
  6. data/MIT-LICENSE +19 -0
  7. data/Rakefile +44 -0
  8. data/TODO +24 -0
  9. data/TODO_ZENA_1_0 +23 -0
  10. data/app/controllers/application_controller.rb +3 -0
  11. data/app/controllers/documents_controller.rb +22 -56
  12. data/app/controllers/nodes_controller.rb +42 -27
  13. data/app/controllers/pings_controller.rb +19 -0
  14. data/app/controllers/relations_controller.rb +5 -1
  15. data/app/controllers/sites_controller.rb +1 -46
  16. data/app/controllers/user_sessions_controller.rb +47 -0
  17. data/app/controllers/users_controller.rb +1 -0
  18. data/app/controllers/versions_controller.rb +25 -7
  19. data/app/controllers/virtual_classes_controller.rb +1 -1
  20. data/app/helpers/application_helper.rb +1 -1
  21. data/app/models/comment.rb +2 -1
  22. data/app/models/contact_content.rb +2 -2
  23. data/app/models/data_entry.rb +5 -6
  24. data/app/models/document.rb +14 -10
  25. data/app/models/document_content.rb +4 -6
  26. data/app/models/iformat.rb +2 -2
  27. data/app/models/image_content.rb +6 -9
  28. data/app/models/node.rb +106 -164
  29. data/app/models/page.rb +0 -20
  30. data/app/models/site.rb +42 -12
  31. data/app/models/template.rb +3 -8
  32. data/app/models/template_content.rb +2 -0
  33. data/app/models/text_document.rb +13 -8
  34. data/app/models/user.rb +47 -100
  35. data/app/models/user_session.rb +4 -0
  36. data/app/models/version.rb +1 -1
  37. data/app/views/comments/create.rjs +3 -3
  38. data/app/views/comments/edit.rjs +1 -1
  39. data/app/views/comments/update.rjs +1 -1
  40. data/app/views/nodes/_import_results.rhtml +1 -1
  41. data/app/views/nodes/create.rjs +3 -3
  42. data/app/views/templates/document_create_tabs/_file.rhtml +1 -2
  43. data/app/views/templates/document_create_tabs/_import.rhtml +7 -2
  44. data/app/views/templates/edit_tabs/_document.rhtml +1 -3
  45. data/app/views/templates/edit_tabs/_image.rhtml +1 -3
  46. data/app/views/versions/_tr.rhtml +1 -1
  47. data/app/views/versions/edit.rhtml +2 -26
  48. data/bin/zena +6 -1
  49. data/bricks/delayed_job/README +18 -0
  50. data/bricks/delayed_job/migrate/20091104191643_create_delayed_jobs_table.rb +19 -0
  51. data/bricks/delayed_job/misc/init.rb +8 -0
  52. data/bricks/delayed_job/misc/tasks.rb +2 -0
  53. data/bricks/math/patch/application_helper.rb +1 -1
  54. data/bricks/sphinx/MIT-LICENSE +19 -0
  55. data/bricks/sphinx/README +19 -0
  56. data/bricks/sphinx/lib/use_sphinx.rb +78 -0
  57. data/bricks/sphinx/migrate/20091102171258_add_delta_for_sphinx.rb +9 -0
  58. data/bricks/sphinx/misc/deploy.rb +20 -0
  59. data/bricks/sphinx/misc/sphinx.yml +12 -0
  60. data/bricks/sphinx/misc/tasks.rb +21 -0
  61. data/bricks/sphinx/patch/node.rb +8 -0
  62. data/bricks/tags/lib/has_tags.rb +5 -3
  63. data/bricks/tags/test/zafu/tags.yml +13 -1
  64. data/config/bricks.yml +35 -0
  65. data/config/deploy.rb +8 -1
  66. data/config/environment.rb +1 -1
  67. data/config/environments/production.rb +1 -1
  68. data/config/gems.yml +28 -5
  69. data/config/sphinx.yml +12 -0
  70. data/db/init/base/skins/default/Node-+popupLayout.zafu +1 -16
  71. data/db/migrate/20091026161708_add_persistence_token.rb +13 -0
  72. data/db/migrate/20091101184952_add_session_table.rb +16 -0
  73. data/db/migrate/20091123175137_add_single_access_token.rb +9 -0
  74. data/db/migrate/20091124161608_rebuild_fullpath.rb +11 -0
  75. data/db/schema.rb +21 -8
  76. data/doc/README_FOR_APP +24 -0
  77. data/doc/fixtures.graffle +19568 -0
  78. data/doc/fixtures.pdf +0 -0
  79. data/doc/template/LICENSE +184 -0
  80. data/doc/template/README +37 -0
  81. data/doc/template/allison.css +283 -0
  82. data/doc/template/allison.js +307 -0
  83. data/doc/template/allison.rb +260 -0
  84. data/doc/template/cache/BODY +588 -0
  85. data/doc/template/cache/CLASS_INDEX +4 -0
  86. data/doc/template/cache/CLASS_PAGE +1 -0
  87. data/doc/template/cache/FILE_INDEX +4 -0
  88. data/doc/template/cache/FILE_PAGE +1 -0
  89. data/doc/template/cache/FONTS +1 -0
  90. data/doc/template/cache/FR_INDEX_BODY +1 -0
  91. data/doc/template/cache/IMGPATH +1 -0
  92. data/doc/template/cache/INDEX +1 -0
  93. data/doc/template/cache/JAVASCRIPT +307 -0
  94. data/doc/template/cache/METHOD_INDEX +4 -0
  95. data/doc/template/cache/METHOD_LIST +1 -0
  96. data/doc/template/cache/SRC_PAGE +1 -0
  97. data/doc/template/cache/STYLE +283 -0
  98. data/doc/template/cache/URL +1 -0
  99. data/doc/zafu_changes.yml +29 -0
  100. data/lib/base_additions.rb +1 -1
  101. data/lib/bricks.rb +9 -0
  102. data/lib/bricks/loader.rb +86 -0
  103. data/lib/bricks/requirements_validation.rb +71 -0
  104. data/lib/tasks/zena.rake +42 -4
  105. data/lib/zafu/action.rb +285 -0
  106. data/lib/zafu/ajax.rb +93 -0
  107. data/lib/zafu/attributes.rb +117 -0
  108. data/lib/zafu/calendar.rb +159 -0
  109. data/lib/zafu/context.rb +330 -0
  110. data/lib/zafu/core/html.rb +102 -0
  111. data/lib/zafu/core/move_to_parser.rb +167 -0
  112. data/lib/zafu/dates.rb +58 -0
  113. data/lib/zafu/display.rb +502 -0
  114. data/lib/zafu/eval.rb +66 -0
  115. data/lib/zafu/experimental.rb +66 -0
  116. data/lib/zafu/i18n.rb +64 -0
  117. data/lib/zafu/meta.rb +25 -0
  118. data/lib/zafu/refactor.rb +73 -0
  119. data/lib/zafu/support/context.rb +265 -0
  120. data/lib/zafu/support/dom.rb +145 -0
  121. data/lib/zafu/support/erb.rb +62 -0
  122. data/lib/zafu/support/flow.rb +401 -0
  123. data/lib/zafu/support/forms.rb +461 -0
  124. data/lib/zafu/support/links.rb +306 -0
  125. data/lib/zafu_parser.rb +26 -2
  126. data/lib/zena.rb +34 -15
  127. data/lib/zena/acts/multiversion.rb +2 -2
  128. data/lib/zena/acts/secure.rb +41 -30
  129. data/lib/zena/app.rb +7 -10
  130. data/lib/zena/controller/test_case.rb +12 -7
  131. data/lib/zena/crypto_provider/initial.rb +15 -0
  132. data/lib/zena/db.rb +6 -1
  133. data/lib/zena/deploy.rb +34 -6
  134. data/lib/zena/deploy/logrotate_app.rhtml +9 -0
  135. data/lib/zena/deploy/logrotate_host.rhtml +34 -0
  136. data/lib/zena/deploy/template.rb +1 -9
  137. data/lib/zena/foxy_parser.rb +1 -1
  138. data/lib/zena/info.rb +3 -1
  139. data/lib/zena/migrator.rb +1 -1
  140. data/lib/zena/parser.rb +12 -4
  141. data/lib/zena/parser/zazen_rules.rb +6 -6
  142. data/lib/zena/parser/zena_rules.rb +1 -7
  143. data/lib/zena/routes.rb +5 -5
  144. data/lib/zena/test_controller.rb +7 -2
  145. data/lib/zena/unit/test_case.rb +6 -8
  146. data/lib/zena/use/ajax.rb +10 -10
  147. data/lib/zena/use/authlogic.rb +93 -0
  148. data/lib/zena/use/dyn_attributes.rb +5 -0
  149. data/lib/zena/use/html_tags.rb +16 -34
  150. data/lib/zena/use/i18n.rb +4 -1
  151. data/lib/zena/use/node_query_finders.rb +8 -4
  152. data/lib/zena/use/refactor.rb +8 -20
  153. data/lib/zena/use/relations.rb +1 -0
  154. data/lib/zena/use/rendering.rb +4 -2
  155. data/lib/zena/use/search.rb +52 -0
  156. data/lib/zena/use/test_helper.rb +27 -28
  157. data/lib/zena/use/upload.rb +188 -0
  158. data/lib/zena/use/urls.rb +16 -14
  159. data/lib/zena/use/zafu.rb +16 -63
  160. data/lib/zena/use/zazen.rb +8 -8
  161. data/lib/zena/view/test_case.rb +8 -4
  162. data/locale/en/LC_MESSAGES/zena.mo +0 -0
  163. data/locale/en/zena.po +3 -3
  164. data/public/.htaccess +40 -0
  165. data/public/javascripts/upload-progress.js +17 -8
  166. data/public/javascripts/zena.js +8 -2
  167. data/public/stylesheets/popup.css +1 -0
  168. data/script/about +3 -0
  169. data/script/apache_logging +25 -0
  170. data/script/breakpointer +3 -0
  171. data/script/console +3 -0
  172. data/script/dbconsole +3 -0
  173. data/script/destroy +3 -0
  174. data/script/generate +3 -0
  175. data/script/performance/benchmarker +3 -0
  176. data/script/performance/profiler +3 -0
  177. data/script/plugin +3 -0
  178. data/script/process/inspector +3 -0
  179. data/script/process/reaper +3 -0
  180. data/script/process/spawner +3 -0
  181. data/script/runner +3 -0
  182. data/script/server +3 -0
  183. data/script/set_revision +29 -0
  184. data/spec/controllers/versions_controller_spec.rb +11 -0
  185. data/test/fixtures/files/Node-test.zafu +1 -1
  186. data/test/functional/nodes_controller_test.rb +25 -0
  187. data/test/functional/pings_controller_test.rb +8 -0
  188. data/test/functional/user_sessions_controller_test.rb +59 -0
  189. data/test/functional/users_controller_test.rb +81 -19
  190. data/test/helpers/node_query/filters.yml +5 -0
  191. data/test/helpers/node_query_test.rb +3 -3
  192. data/test/integration/multiple_hosts_test.rb +1 -1
  193. data/test/integration/navigation_test.rb +1 -1
  194. data/test/sites/complex/users.yml +1 -1
  195. data/test/sites/ocean/users.yml +3 -3
  196. data/test/sites/zena/users.yml +5 -4
  197. data/test/test_zena.rb +38 -38
  198. data/test/unit/cached_page_test.rb +2 -2
  199. data/test/unit/comment_test.rb +0 -1
  200. data/test/unit/document_test.rb +23 -11
  201. data/test/unit/helpers/ping_helper_test.rb +4 -0
  202. data/test/unit/multiversion_test.rb +24 -16
  203. data/test/unit/node_test.rb +32 -93
  204. data/test/unit/note_test.rb +9 -0
  205. data/test/unit/page_test.rb +2 -2
  206. data/test/unit/secure_test.rb +2 -12
  207. data/test/unit/site_test.rb +43 -24
  208. data/test/unit/template_test.rb +45 -3
  209. data/test/unit/text_document_test.rb +4 -3
  210. data/test/unit/user_test.rb +13 -33
  211. data/test/unit/zena/db_test.rb +8 -0
  212. data/test/unit/zena/parser/zazen.yml +4 -4
  213. data/test/unit/zena/use/dates_view_methods_test.rb +2 -1
  214. data/test/unit/zena/use/html_tags_test.rb +12 -4
  215. data/test/unit/zena/use/refactor_test.rb +4 -3
  216. data/test/unit/zena/use/rendering_test.rb +1 -0
  217. data/test/unit/zena/use/upload_test.rb +76 -0
  218. data/test/unit/zena/use/urls_test.rb +4 -0
  219. data/test/unit/zena/use/zafu_test.rb +8 -0
  220. data/test/unit/zena/workflow/status_version_test.rb +6 -0
  221. data/test/unit/zena/zena_tags/ajax.yml +4 -4
  222. data/test/unit/zena/zena_tags/basic.yml +21 -10
  223. data/test/unit/zena/zena_tags/relations.yml +0 -6
  224. data/test/unit/zena/zena_tags/rubyless.yml +35 -0
  225. data/test/unit/zena/zena_tags/zazen.yml +4 -4
  226. data/test/unit/zena/zena_tags_test.rb +36 -4
  227. data/vendor/TextMate/Zena.tmbundle/Commands/Run all yaml tests.tmCommand +1 -1
  228. data/vendor/TextMate/Zena.tmbundle/Commands/Run focused yaml test.tmCommand +2 -3
  229. data/vendor/TextMate/Zena.tmbundle/Support/RubyMate/catch_exception.rb +39 -0
  230. data/vendor/TextMate/Zena.tmbundle/Support/RubyMate/run_script.rb +102 -58
  231. data/vendor/TextMate/Zena.tmbundle/Support/RubyMate/stdin_dialog.rb +14 -0
  232. data/vendor/TextMate/Zena.tmbundle/info.plist +2 -0
  233. data/zena.gemspec +2085 -0
  234. metadata +265 -90
  235. data/app/controllers/sessions_controller.rb +0 -41
  236. data/app/views/sites/zena_up.html.erb +0 -11
  237. data/config/database.yml +0 -40
  238. data/db/production.sqlite3 +0 -0
  239. data/lib/bricks/patcher.rb +0 -68
  240. data/lib/zena/parser/zena_tags.rb +0 -3562
  241. data/lib/zena/use/authentification.rb +0 -120
  242. data/public/images/ext/contact_pv.png +0 -0
  243. data/public/images/ext/other_pv.png +0 -0
  244. data/public/images/ext/page_pv.png +0 -0
  245. data/public/images/ext/page_tiny.png +0 -0
  246. data/public/images/ext/pdf_pv.png +0 -0
  247. data/public/images/ext/post_pv.png +0 -0
  248. data/public/images/ext/post_tiny.png +0 -0
  249. data/public/images/ext/project_pv.png +0 -0
  250. data/public/images/ext/project_tiny.png +0 -0
  251. data/public/images/ext/tag_pv.png +0 -0
  252. data/public/images/ext/zip_pv.png +0 -0
  253. data/tasks/ann.rake +0 -80
  254. data/tasks/bones.rake +0 -20
  255. data/tasks/gem.rake +0 -201
  256. data/tasks/git.rake +0 -40
  257. data/tasks/notes.rake +0 -27
  258. data/tasks/post_load.rake +0 -34
  259. data/tasks/rdoc.rake +0 -51
  260. data/tasks/rubyforge.rake +0 -55
  261. data/tasks/setup.rb +0 -292
  262. data/tasks/spec.rake +0 -54
  263. data/tasks/svn.rake +0 -47
  264. data/tasks/test.rake +0 -40
  265. data/tasks/zentest.rake +0 -36
  266. data/test/fixtures/comments.yml +0 -126
  267. data/test/fixtures/contact_contents.yml +0 -132
  268. data/test/fixtures/data_entries.yml +0 -65
  269. data/test/fixtures/discussions.yml +0 -48
  270. data/test/fixtures/document_contents.yml +0 -108
  271. data/test/fixtures/dyn_attributes.yml +0 -66
  272. data/test/fixtures/groups.yml +0 -86
  273. data/test/fixtures/groups_users.yml +0 -81
  274. data/test/fixtures/iformats.yml +0 -29
  275. data/test/fixtures/links.yml +0 -313
  276. data/test/fixtures/nodes.yml +0 -2592
  277. data/test/fixtures/relations.yml +0 -126
  278. data/test/fixtures/sites.yml +0 -58
  279. data/test/fixtures/template_contents.yml +0 -172
  280. data/test/fixtures/users.yml +0 -167
  281. data/test/fixtures/versions.yml +0 -1911
  282. data/test/fixtures/virtual_classes.yml +0 -87
  283. data/test/fixtures/zips.yml +0 -15
  284. data/test/functional/sessions_controller_test.rb +0 -73
@@ -136,7 +136,10 @@ module Zena
136
136
  include Common
137
137
 
138
138
  def self.included(base)
139
- base.before_filter { FastGettext.text_domain = 'zena' }
139
+ FastGettext.add_text_domain 'zena', :path => "#{Zena::ROOT}/locale"
140
+ base.prepend_before_filter { FastGettext.text_domain = 'zena' }
141
+ base.before_filter :set_lang, :check_lang
142
+ base.after_filter :set_encoding
140
143
  end
141
144
 
142
145
  # Choose best language to display content.
@@ -193,7 +193,7 @@ class NodeQuery < QueryBuilder
193
193
  end
194
194
 
195
195
  def map_literal(value, env = :sql)
196
- if value =~ /(.*?)\[(visitor|param):(\w+)\](.*)/
196
+ if value =~ /(.*?)\[(visitor|param|node):(\w+)\](.*)/
197
197
  val_start = $1 == '' ? '' : "#{$1.inspect} +"
198
198
  val_end = $4 == '' ? '' : "+ #{$4.inspect}"
199
199
  case $2
@@ -201,6 +201,9 @@ class NodeQuery < QueryBuilder
201
201
  value = env == :sql ? insert_bind("#{val_start}Node.zafu_attribute(visitor.contact, #{$3.inspect})#{val_end}") : nil
202
202
  when 'param'
203
203
  value = env == :sql ? insert_bind("#{val_start}params[:#{$3}].to_s#{val_end}") : "params[:#{$3}]"
204
+ when 'node'
205
+ @uses_node_name = true
206
+ value = env == :sql ? insert_bind("#{val_start}#{@node_name}.safe_read(#{$3.inspect}).to_s#{val_end}") : "#{@node_name}.safe_read(#{$3.inspect})"
204
207
  end
205
208
  else
206
209
  value = env == :sql ? quote(value) : nil
@@ -470,11 +473,12 @@ module Zena
470
473
 
471
474
  # Find related nodes.
472
475
  # See Node#build_find for details on the options available.
473
- def find(count, rel)
476
+ # TODO: replace with rubyless translate ? Is this thing really used anyway ?
477
+ def find(count, rel, opts = {})
474
478
  rel = [rel] if rel.kind_of?(String)
475
479
 
476
- if rel.size == 1 && self.class.zafu_known_contexts[rel.first]
477
- self.send(rel.first)
480
+ if !opts[:skip_rubyless] && rel.size == 1 && type = RubyLess::SafeClass.safe_method_type_for(self.class, [rel.first])
481
+ self.send(type[:method])
478
482
  else
479
483
  query = Node.build_find(count, rel, :node_name => 'self')
480
484
  if query.valid?
@@ -1,30 +1,17 @@
1
1
  module Zena
2
2
  module Use
3
3
  module Refactor
4
- module Common
5
4
 
5
+ module Common
6
6
  # TODO: test
7
7
  def lang
8
- visitor.lang
8
+ @lang ||= visitor.lang
9
9
  end
10
10
  end # Common
11
11
 
12
12
  module ControllerMethods
13
13
  include Common
14
14
 
15
- # TODO: test
16
- def visitor
17
- @visitor ||= returning(User.make_visitor(:host => request.host, :id => session[:user])) do |user|
18
- if session[:user] != user[:id]
19
- # changed user (login/logout)
20
- session[:user] = user[:id]
21
- end
22
- if user.is_anon?
23
- user.ip = request.headers['REMOTE_ADDR']
24
- end
25
- end
26
- end
27
-
28
15
  # Read the parameters and add errors to the object if it is considered spam. Save it otherwize.
29
16
  def save_if_not_spam(obj, params)
30
17
  # do nothing (overwritten by plugins like zena_captcha)
@@ -34,9 +21,8 @@ module Zena
34
21
  end # ControllerMethods
35
22
 
36
23
  module ViewMethods
37
- include Common
38
24
 
39
- # TODO: use Rails native helper.
25
+ include Common
40
26
 
41
27
  # Quote for html values (input tag, alt attribute, etc)
42
28
  def fquote(text)
@@ -175,7 +161,7 @@ ENDTXT
175
161
  obj = opts[:node] || @node
176
162
  trad_list = []
177
163
  (obj.traductions || []).each do |ed|
178
- trad_list << "<span#{ ed.lang == lang ? " class='current'" : ''}>" + link_to( _(ed[:lang]), zen_path(obj,:lang=>ed[:lang])) + "</span>"
164
+ trad_list << "<span#{ ed.lang == visitor.lang ? " class='current'" : ''}>" + link_to( _(ed[:lang]), zen_path(obj,:lang=>ed[:lang])) + "</span>"
179
165
  end
180
166
  trad_list
181
167
  end
@@ -190,11 +176,13 @@ ENDTXT
190
176
 
191
177
  # This lets helpers render partials
192
178
  # TODO: make sure this is the best way to handle this problem.
179
+
193
180
  def render_to_string(*args)
194
- @controller ||= begin
181
+ controller ||= begin
195
182
  # ==> this means render_to_string uses a view with everything ApplicationController has...
196
183
  ApplicationController.new.instance_eval do
197
184
  class << self
185
+ public :render, :render_to_string
198
186
  attr_accessor :request, :response, :params
199
187
  end
200
188
 
@@ -209,7 +197,7 @@ ENDTXT
209
197
  end
210
198
  end
211
199
 
212
- @controller.send(:render_to_string, *args)
200
+ controller.render(*args)
213
201
  end
214
202
 
215
203
  end # ViewMethods
@@ -80,6 +80,7 @@ module Zena
80
80
 
81
81
  # Return an array of accessor methods for the matched relation alias.
82
82
  def relation_alias(match)
83
+ return nil if match[0] == 'parent_id'
83
84
  role = match[1]
84
85
  field = match[2]
85
86
 
@@ -13,6 +13,7 @@ module Zena
13
13
  module ControllerMethods
14
14
  def self.included(base)
15
15
  base.send(:helper_attr, :js_data)
16
+ base.send(:layout, false)
16
17
  end
17
18
 
18
19
  def js_data
@@ -94,11 +95,11 @@ module Zena
94
95
  params.delete(:mode)
95
96
 
96
97
  if opts[:format] != 'html'
97
- content_type = (EXT_TO_TYPE[opts[:format]] || ['application/octet-stream'])[0]
98
+ content_type = (Zena::EXT_TO_TYPE[opts[:format]] || ['application/octet-stream'])[0]
98
99
  template_path = template_url(opts)
99
100
  data = render_to_string(:file => template_path, :layout=>false)
100
101
  # TODO: use plugins...
101
- if opts[:format] == 'pdf' && ((ENABLE_LATEX && data =~ /\A% (latex)\n/) || (ENABLE_FOP && data =~ /\A<\?(xml)/))
102
+ if opts[:format] == 'pdf' && ((Zena::ENABLE_LATEX && data =~ /\A% (latex)\n/) || (Zena::ENABLE_FOP && data =~ /\A<\?(xml)/))
102
103
  rendering_egine = $1 == 'xml' ? 'fop' : $1
103
104
  # 1. find cached PDF. If found, send data.
104
105
  if @node[:user_id] == visitor[:id]
@@ -252,6 +253,7 @@ module Zena
252
253
 
253
254
  # TODO: test
254
255
  def popup_layout
256
+ js_data << "var is_editor = true;"
255
257
  template_url(:mode=>'+popupLayout')
256
258
  end
257
259
 
@@ -0,0 +1,52 @@
1
+ module Zena
2
+ module Use
3
+ module Search
4
+ module NodeClassMethods
5
+ # Return a hash to do a fulltext query.
6
+ def match_query(query, opts={})
7
+ node = opts.delete(:node)
8
+ if query == '.' && node
9
+ return opts.merge(
10
+ :conditions => ["parent_id = ?",node[:id]],
11
+ :order => 'name ASC' )
12
+ elsif !query.blank?
13
+ if Zena::Db.adapter == 'mysql' && RAILS_ENV != 'test'
14
+ match = sanitize_sql(["MATCH (vs.title,vs.text,vs.summary) AGAINST (?) OR nodes.name LIKE ?", query, "#{opts[:name_query] || query.url_name}%"])
15
+ select = sanitize_sql(["nodes.*, MATCH (vs.title,vs.text,vs.summary) AGAINST (?) + (5 * (nodes.name LIKE ?)) AS score", query, "#{query}%"])
16
+ else
17
+ match = sanitize_sql(["nodes.name LIKE ?", "#{query}%"])
18
+ select = "nodes.*, #{match} AS score"
19
+ end
20
+
21
+ return opts.merge(
22
+ :select => select,
23
+ :joins => "INNER JOIN versions AS vs ON vs.node_id = nodes.id AND vs.status >= #{Zena::Status[:pub]}",
24
+ :conditions => match,
25
+ :group => "nodes.id",
26
+ :order => "score DESC, zip ASC")
27
+ else
28
+ # error
29
+ return opts.merge(:conditions => '0')
30
+ end
31
+ end
32
+
33
+ def search_records(query, opts={})
34
+ with = opts[:with] || {}
35
+ with[:site_id] = current_site.id
36
+ if offset = opts[:offset]
37
+ limit = opts[:limit] || 20
38
+ Node.find(:all, match_query(query).merge(:offset => offset, :limit => limit))
39
+ else
40
+ if per_page = opts[:per_page]
41
+ page = opts[:page].to_i
42
+ page = 1 if page < 1
43
+ search_records(query, :offset => (page - 1) * per_page, :limit => per_page)
44
+ else
45
+ Node.find(:all, match_query(query, opts))
46
+ end
47
+ end
48
+ end
49
+ end # NodeClassMethods
50
+ end # Search
51
+ end # Use
52
+ end # Zena
@@ -1,26 +1,30 @@
1
+ require "authlogic/test_case"
1
2
  require 'hpricot'
3
+
2
4
  module Zena
3
5
  module Use
4
6
  module TestHelper
5
- # Set the current site used for testing (mostly to generate ids)
6
- def test_site(site_name)
7
- $_test_site = site_name
8
- end
7
+ include Zena::Use::Upload::UploadedFile
9
8
 
10
9
  # Set visitor for unit testing
11
- def login(name='anon', site_name = nil)
12
- if site_name
13
- @visitor = User.make_visitor(:user => name.to_s, :pass => name.to_s, :host => sites_host(site_name))
14
- else
15
- # find first matching site
16
- site = Site.find(:first, :select=>"sites.*, sites.name = '#{site_name}' AS site_ok", :from => "sites, users",
17
- :conditions=>["users.site_id = sites.id AND users.id = ?", users_id(name)], :order => "site_ok DESC")
18
- @visitor = User.make_visitor(:site => site, :id => users_id(name))
10
+ def login(fixture)
11
+ user = users(fixture)
12
+ Thread.current[:visitor] = user = users(fixture)
13
+ user.ip = '10.0.0.44'
14
+ $_test_site = user.site.name
15
+ ::I18n.locale = user.lang
16
+ end
17
+
18
+ # Show object's errors
19
+ def err(obj)
20
+ obj.errors.each_error do |er,msg|
21
+ puts "[#{er}] #{msg}"
19
22
  end
23
+ end
20
24
 
21
- $_test_site = visitor.site.name
22
- @visitor.ip = '10.0.0.127'
23
- ::I18n.locale = @visitor.lang
25
+ # Set the current site used for testing (mostly to generate ids)
26
+ def test_site(site_name)
27
+ $_test_site = site_name
24
28
  end
25
29
 
26
30
  def set_date(node_syms, opts = {})
@@ -83,7 +87,7 @@ module Zena
83
87
  end
84
88
 
85
89
  # taken from http://manuals.rubyonrails.com/read/chapter/28#page237 with some modifications
86
- def uploaded_file(fname, content_type="application/octet-stream", filename=nil)
90
+ def uploaded_fixture(fname, content_type="application/octet-stream", filename=nil)
87
91
  path = File.join(FILE_FIXTURES_PATH, fname)
88
92
  filename ||= File.basename(path)
89
93
  # simulate small files with StringIO
@@ -94,42 +98,37 @@ module Zena
94
98
  t = Tempfile.new(fname)
95
99
  FileUtils.copy_file(path, t.path)
96
100
  end
97
- (class << t; self; end;).class_eval do
98
- alias local_path path if defined?(:path)
99
- define_method(:original_filename) { filename }
100
- define_method(:content_type) { content_type }
101
- end
102
- return t
101
+ uploaded_file(t, filename, content_type)
103
102
  end
104
103
 
105
104
  # JPEG helper
106
105
  def uploaded_jpg(fname, filename=nil)
107
- uploaded_file(fname, 'image/jpeg', filename)
106
+ uploaded_fixture(fname, 'image/jpeg', filename)
108
107
  end
109
108
 
110
109
  # PDF helper
111
110
  def uploaded_pdf(fname, filename=nil)
112
- uploaded_file(fname, 'application/pdf', filename)
111
+ uploaded_fixture(fname, 'application/pdf', filename)
113
112
  end
114
113
 
115
114
  # TEXT helper
116
115
  def uploaded_text(fname, filename=nil)
117
- uploaded_file(fname, 'text/plain', filename)
116
+ uploaded_fixture(fname, 'text/plain', filename)
118
117
  end
119
118
 
120
119
  # PNG helper
121
120
  def uploaded_png(fname, filename=nil)
122
- uploaded_file(fname, 'image/png', filename)
121
+ uploaded_fixture(fname, 'image/png', filename)
123
122
  end
124
123
 
125
124
  # TGZ helper
126
125
  def uploaded_archive(fname, filename=nil)
127
- uploaded_file(fname, 'application/x-gzip', filename)
126
+ uploaded_fixture(fname, 'application/x-gzip', filename)
128
127
  end
129
128
 
130
129
  # ZIP helper
131
130
  def uploaded_zip(fname, filename=nil)
132
- uploaded_file(fname, 'application/zip', filename)
131
+ uploaded_fixture(fname, 'application/zip', filename)
133
132
  end
134
133
 
135
134
  def file_path(filename, mode = 'full', content_id = nil)
@@ -0,0 +1,188 @@
1
+ require 'uri'
2
+ require 'net/http'
3
+ require 'uuidtools'
4
+
5
+ module Zena
6
+ module Use
7
+ module Upload
8
+ def self.has_network?
9
+ response = nil
10
+ Net::HTTP.new('example.com', '80').start do |http|
11
+ response = http.head('/')
12
+ end
13
+ response.kind_of? Net::HTTPSuccess
14
+ rescue
15
+ false
16
+ end
17
+
18
+ module UploadedFile
19
+ protected
20
+ def uploaded_file(file, filename = nil, content_type = nil)
21
+ (class << file; self; end;).class_eval do
22
+ alias local_path path if respond_to?(:path) # FIXME: do we need this ?
23
+ define_method(:original_filename) { filename }
24
+ define_method(:content_type) { content_type }
25
+ end
26
+ file
27
+ end
28
+ end # UploadedFile
29
+
30
+ module ControllerMethods
31
+ include UploadedFile
32
+ protected
33
+ include ActionView::Helpers::NumberHelper # number_to_human_size
34
+ def get_attachment
35
+ att, error = nil, nil
36
+ if !params['attachment_url'].blank?
37
+ att, error = fetch_uri(params['attachment_url'])
38
+ else
39
+ att = params['attachment']
40
+ end
41
+ yield(att, error) if block_given?
42
+ [att, error]
43
+ end
44
+
45
+ private
46
+ def fetch_uri(uri_str, max_file_size = 10)
47
+ max_file_size = max_file_size * 1024 * 1024 # Mo
48
+
49
+ # first check head
50
+ response, error = fetch_response(uri_str, :head)
51
+ return [nil, error] unless response
52
+ if response['Content-Length'].nil?
53
+ return [nil, 'unknown size: cannot fetch url']
54
+ elsif response['Content-Length'].to_i > max_file_size
55
+ return [nil, 'size (%s) too big to fetch url' % number_to_human_size(response['Content-Length'].to_i)]
56
+ end
57
+
58
+ # Size is ok, get content
59
+ response, error = fetch_response(uri_str, :body)
60
+ return [nil, error] unless response
61
+
62
+ tmpf = Tempfile.new('fetch_uri')
63
+ File.open(tmpf.path, 'wb') do |file|
64
+ file.write(response.body)
65
+ end
66
+ if content_disposition = response['Content-Disposition']
67
+ original_filename = content_disposition[/filename\s*=\s*('|")(.+)\1/,2]
68
+ else
69
+ original_filename = uri_str.split('/').last
70
+ end
71
+
72
+ [uploaded_file(tmpf, original_filename, response['Content-Type'])]
73
+ end
74
+
75
+ def fetch_response(uri_str, type = :body, limit = 10)
76
+ return [nil, 'too many redirects'] if limit == 0
77
+ response = nil
78
+ uri = URI.parse(URI.escape(uri_str))
79
+ return [nil, 'invalid url'] unless uri.kind_of?(URI::HTTP)
80
+ Net::HTTP.new(uri.host, uri.port).start do |http|
81
+ if type == :body
82
+ response = http.request_get(uri.request_uri)
83
+ else
84
+ response = http.head(uri.request_uri)
85
+ end
86
+ end
87
+
88
+ case response
89
+ when Net::HTTPSuccess
90
+ response
91
+ when Net::HTTPRedirection
92
+ redirect = response['location']
93
+ port = (uri.scheme == 'http' && uri.port == 80) ? '' : ":#{uri.port}"
94
+ redirect = "#{uri.scheme}://#{uri.host}#{port}/#{redirect}" unless redirect =~ /\A\w+:\/\//
95
+ fetch_response(redirect, type, limit - 1)
96
+ else
97
+ [nil, 'not found']
98
+ end
99
+ rescue URI::InvalidURIError
100
+ [nil, 'invalid url']
101
+ end
102
+
103
+ def render_get_uf
104
+ @uuid = params[:uuid]
105
+ render :inline => "<%= link_to_function(_('cancel'), \"['file', 'upload_field'].each(Element.toggle);$('upload_field').innerHTML = '';\")%><%= upload_field %>"
106
+ end
107
+
108
+ def render_upload_progress
109
+ # When using the mod_upload_progress module, this is never hit:
110
+ # <Location /upload_progress>
111
+ # ReportUploads On
112
+ # </Location>
113
+ #
114
+ # When using Mongrel: mimic apache2 mod_upload_progress
115
+ #
116
+ # if (!found) {
117
+ # response = apr_psprintf(r->pool, "new Object({ 'state' : 'starting' })");
118
+ # } else if (err_status >= HTTP_BAD_REQUEST ) {
119
+ # response = apr_psprintf(r->pool, "new Object({ 'state' : 'error', 'status' : %d })", err_status);
120
+ # } else if (done) {
121
+ # response = apr_psprintf(r->pool, "new Object({ 'state' : 'done' })");
122
+ # } else if ( length == 0 && received == 0 ) {
123
+ # response = apr_psprintf(r->pool, "new Object({ 'state' : 'starting' })");
124
+ # } else {
125
+ # response = apr_psprintf(r->pool, "new Object({ 'state' : 'uploading', 'received' : %d, 'size' : %d, 'speed' : %d })", received, length, speed);
126
+ # }
127
+ render :update do |page|
128
+ begin
129
+ @status = Mongrel::Uploads.check(params[:"X-Progress-ID"])
130
+ if @status
131
+ if @status[:received] != @status[:size]
132
+ page << "new Object({ 'state' : 'uploading', 'received' : #{@status[:received]}, 'size' : #{@status[:size]} })"
133
+ else
134
+ page << "new Object({ 'state' : 'done' })"
135
+ end
136
+ else
137
+ #page << "new Object({ 'state' : 'done' })"
138
+ end
139
+ rescue NameError
140
+ page << "new Object({ 'state' : 'upload in progress..' })"
141
+ end
142
+ end
143
+ end
144
+ end # ControllerMethods
145
+
146
+ module ViewMethods
147
+ UPLOAD_KEY = defined?(Mongrel) ? 'upload_id' : "X-Progress-ID"
148
+ def upload_form_tag(url_opts, html_opts = {})
149
+ @uuid = UUIDTools::UUID.random_create.to_s.gsub('-','')
150
+ html_opts.reverse_merge!(:multipart => true, :id => "UploadForm#{@uuid}")
151
+ if html_opts[:multipart]
152
+ html_opts[:onsubmit] = "submitUploadForm('#{html_opts[:id]}', '#{@uuid}');"
153
+ url_opts[UPLOAD_KEY] = @uuid
154
+ end
155
+ if block_given?
156
+ form_tag( url_opts, html_opts ) do |f|
157
+ yield(f)
158
+ end
159
+ else
160
+ form_tag( url_opts, html_opts )
161
+ end
162
+ end
163
+
164
+ def upload_field(opts = {})
165
+ case opts[:type]
166
+ when :onclick
167
+ link = link_to_remote(_("change"), :update=>'upload_field', :url => get_uf_documents_path(:uuid => @uuid), :method => :get, :complete=>"['file', 'upload_field'].each(Element.toggle);")
168
+ <<-TXT
169
+ <label for='attachment'>#{_('file')}</label>
170
+ <div id="file" class='toggle_div'>#{link}</div>
171
+ <div id="upload_field" class='toggle_div' style='display:none;'></div>
172
+ TXT
173
+ else
174
+ attach_file_id, attach_url_id = "af#{@uuid}", "au#{@uuid}"
175
+ onchange = %Q{onchange="Zena.get_filename(this,'node_v_title'); $('node_v_title').focus(); $('node_v_title').select();"}
176
+ <<-TXT
177
+ <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>
178
+ <input style='line-height:1.5em;' id="attachment#{@uuid}" name="attachment" #{onchange} class='file' type="file" /></div>
179
+
180
+ <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>
181
+ <input style='line-height:1.5em;' size='30' id='attachment_url' type='text' #{onchange} name='attachment_url'/><br/></div>
182
+ TXT
183
+ end
184
+ end
185
+ end # ViewMethods
186
+ end # Upload
187
+ end # Use
188
+ end # Zena