zena 0.15.2 → 0.16.0

Sign up to get free protection for your applications and to get access to all the features.
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