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.
- data/.gitignore +20 -0
- data/CREDITS +27 -0
- data/Capfile +3 -0
- data/DEVELOPERS +46 -0
- data/History.txt +15 -0
- data/MIT-LICENSE +19 -0
- data/Rakefile +44 -0
- data/TODO +24 -0
- data/TODO_ZENA_1_0 +23 -0
- data/app/controllers/application_controller.rb +3 -0
- data/app/controllers/documents_controller.rb +22 -56
- data/app/controllers/nodes_controller.rb +42 -27
- data/app/controllers/pings_controller.rb +19 -0
- data/app/controllers/relations_controller.rb +5 -1
- data/app/controllers/sites_controller.rb +1 -46
- data/app/controllers/user_sessions_controller.rb +47 -0
- data/app/controllers/users_controller.rb +1 -0
- data/app/controllers/versions_controller.rb +25 -7
- data/app/controllers/virtual_classes_controller.rb +1 -1
- data/app/helpers/application_helper.rb +1 -1
- data/app/models/comment.rb +2 -1
- data/app/models/contact_content.rb +2 -2
- data/app/models/data_entry.rb +5 -6
- data/app/models/document.rb +14 -10
- data/app/models/document_content.rb +4 -6
- data/app/models/iformat.rb +2 -2
- data/app/models/image_content.rb +6 -9
- data/app/models/node.rb +106 -164
- data/app/models/page.rb +0 -20
- data/app/models/site.rb +42 -12
- data/app/models/template.rb +3 -8
- data/app/models/template_content.rb +2 -0
- data/app/models/text_document.rb +13 -8
- data/app/models/user.rb +47 -100
- data/app/models/user_session.rb +4 -0
- data/app/models/version.rb +1 -1
- data/app/views/comments/create.rjs +3 -3
- data/app/views/comments/edit.rjs +1 -1
- data/app/views/comments/update.rjs +1 -1
- data/app/views/nodes/_import_results.rhtml +1 -1
- data/app/views/nodes/create.rjs +3 -3
- data/app/views/templates/document_create_tabs/_file.rhtml +1 -2
- data/app/views/templates/document_create_tabs/_import.rhtml +7 -2
- data/app/views/templates/edit_tabs/_document.rhtml +1 -3
- data/app/views/templates/edit_tabs/_image.rhtml +1 -3
- data/app/views/versions/_tr.rhtml +1 -1
- data/app/views/versions/edit.rhtml +2 -26
- data/bin/zena +6 -1
- data/bricks/delayed_job/README +18 -0
- data/bricks/delayed_job/migrate/20091104191643_create_delayed_jobs_table.rb +19 -0
- data/bricks/delayed_job/misc/init.rb +8 -0
- data/bricks/delayed_job/misc/tasks.rb +2 -0
- data/bricks/math/patch/application_helper.rb +1 -1
- data/bricks/sphinx/MIT-LICENSE +19 -0
- data/bricks/sphinx/README +19 -0
- data/bricks/sphinx/lib/use_sphinx.rb +78 -0
- data/bricks/sphinx/migrate/20091102171258_add_delta_for_sphinx.rb +9 -0
- data/bricks/sphinx/misc/deploy.rb +20 -0
- data/bricks/sphinx/misc/sphinx.yml +12 -0
- data/bricks/sphinx/misc/tasks.rb +21 -0
- data/bricks/sphinx/patch/node.rb +8 -0
- data/bricks/tags/lib/has_tags.rb +5 -3
- data/bricks/tags/test/zafu/tags.yml +13 -1
- data/config/bricks.yml +35 -0
- data/config/deploy.rb +8 -1
- data/config/environment.rb +1 -1
- data/config/environments/production.rb +1 -1
- data/config/gems.yml +28 -5
- data/config/sphinx.yml +12 -0
- data/db/init/base/skins/default/Node-+popupLayout.zafu +1 -16
- data/db/migrate/20091026161708_add_persistence_token.rb +13 -0
- data/db/migrate/20091101184952_add_session_table.rb +16 -0
- data/db/migrate/20091123175137_add_single_access_token.rb +9 -0
- data/db/migrate/20091124161608_rebuild_fullpath.rb +11 -0
- data/db/schema.rb +21 -8
- data/doc/README_FOR_APP +24 -0
- data/doc/fixtures.graffle +19568 -0
- data/doc/fixtures.pdf +0 -0
- data/doc/template/LICENSE +184 -0
- data/doc/template/README +37 -0
- data/doc/template/allison.css +283 -0
- data/doc/template/allison.js +307 -0
- data/doc/template/allison.rb +260 -0
- data/doc/template/cache/BODY +588 -0
- data/doc/template/cache/CLASS_INDEX +4 -0
- data/doc/template/cache/CLASS_PAGE +1 -0
- data/doc/template/cache/FILE_INDEX +4 -0
- data/doc/template/cache/FILE_PAGE +1 -0
- data/doc/template/cache/FONTS +1 -0
- data/doc/template/cache/FR_INDEX_BODY +1 -0
- data/doc/template/cache/IMGPATH +1 -0
- data/doc/template/cache/INDEX +1 -0
- data/doc/template/cache/JAVASCRIPT +307 -0
- data/doc/template/cache/METHOD_INDEX +4 -0
- data/doc/template/cache/METHOD_LIST +1 -0
- data/doc/template/cache/SRC_PAGE +1 -0
- data/doc/template/cache/STYLE +283 -0
- data/doc/template/cache/URL +1 -0
- data/doc/zafu_changes.yml +29 -0
- data/lib/base_additions.rb +1 -1
- data/lib/bricks.rb +9 -0
- data/lib/bricks/loader.rb +86 -0
- data/lib/bricks/requirements_validation.rb +71 -0
- data/lib/tasks/zena.rake +42 -4
- data/lib/zafu/action.rb +285 -0
- data/lib/zafu/ajax.rb +93 -0
- data/lib/zafu/attributes.rb +117 -0
- data/lib/zafu/calendar.rb +159 -0
- data/lib/zafu/context.rb +330 -0
- data/lib/zafu/core/html.rb +102 -0
- data/lib/zafu/core/move_to_parser.rb +167 -0
- data/lib/zafu/dates.rb +58 -0
- data/lib/zafu/display.rb +502 -0
- data/lib/zafu/eval.rb +66 -0
- data/lib/zafu/experimental.rb +66 -0
- data/lib/zafu/i18n.rb +64 -0
- data/lib/zafu/meta.rb +25 -0
- data/lib/zafu/refactor.rb +73 -0
- data/lib/zafu/support/context.rb +265 -0
- data/lib/zafu/support/dom.rb +145 -0
- data/lib/zafu/support/erb.rb +62 -0
- data/lib/zafu/support/flow.rb +401 -0
- data/lib/zafu/support/forms.rb +461 -0
- data/lib/zafu/support/links.rb +306 -0
- data/lib/zafu_parser.rb +26 -2
- data/lib/zena.rb +34 -15
- data/lib/zena/acts/multiversion.rb +2 -2
- data/lib/zena/acts/secure.rb +41 -30
- data/lib/zena/app.rb +7 -10
- data/lib/zena/controller/test_case.rb +12 -7
- data/lib/zena/crypto_provider/initial.rb +15 -0
- data/lib/zena/db.rb +6 -1
- data/lib/zena/deploy.rb +34 -6
- data/lib/zena/deploy/logrotate_app.rhtml +9 -0
- data/lib/zena/deploy/logrotate_host.rhtml +34 -0
- data/lib/zena/deploy/template.rb +1 -9
- data/lib/zena/foxy_parser.rb +1 -1
- data/lib/zena/info.rb +3 -1
- data/lib/zena/migrator.rb +1 -1
- data/lib/zena/parser.rb +12 -4
- data/lib/zena/parser/zazen_rules.rb +6 -6
- data/lib/zena/parser/zena_rules.rb +1 -7
- data/lib/zena/routes.rb +5 -5
- data/lib/zena/test_controller.rb +7 -2
- data/lib/zena/unit/test_case.rb +6 -8
- data/lib/zena/use/ajax.rb +10 -10
- data/lib/zena/use/authlogic.rb +93 -0
- data/lib/zena/use/dyn_attributes.rb +5 -0
- data/lib/zena/use/html_tags.rb +16 -34
- data/lib/zena/use/i18n.rb +4 -1
- data/lib/zena/use/node_query_finders.rb +8 -4
- data/lib/zena/use/refactor.rb +8 -20
- data/lib/zena/use/relations.rb +1 -0
- data/lib/zena/use/rendering.rb +4 -2
- data/lib/zena/use/search.rb +52 -0
- data/lib/zena/use/test_helper.rb +27 -28
- data/lib/zena/use/upload.rb +188 -0
- data/lib/zena/use/urls.rb +16 -14
- data/lib/zena/use/zafu.rb +16 -63
- data/lib/zena/use/zazen.rb +8 -8
- data/lib/zena/view/test_case.rb +8 -4
- data/locale/en/LC_MESSAGES/zena.mo +0 -0
- data/locale/en/zena.po +3 -3
- data/public/.htaccess +40 -0
- data/public/javascripts/upload-progress.js +17 -8
- data/public/javascripts/zena.js +8 -2
- data/public/stylesheets/popup.css +1 -0
- data/script/about +3 -0
- data/script/apache_logging +25 -0
- data/script/breakpointer +3 -0
- data/script/console +3 -0
- data/script/dbconsole +3 -0
- data/script/destroy +3 -0
- data/script/generate +3 -0
- data/script/performance/benchmarker +3 -0
- data/script/performance/profiler +3 -0
- data/script/plugin +3 -0
- data/script/process/inspector +3 -0
- data/script/process/reaper +3 -0
- data/script/process/spawner +3 -0
- data/script/runner +3 -0
- data/script/server +3 -0
- data/script/set_revision +29 -0
- data/spec/controllers/versions_controller_spec.rb +11 -0
- data/test/fixtures/files/Node-test.zafu +1 -1
- data/test/functional/nodes_controller_test.rb +25 -0
- data/test/functional/pings_controller_test.rb +8 -0
- data/test/functional/user_sessions_controller_test.rb +59 -0
- data/test/functional/users_controller_test.rb +81 -19
- data/test/helpers/node_query/filters.yml +5 -0
- data/test/helpers/node_query_test.rb +3 -3
- data/test/integration/multiple_hosts_test.rb +1 -1
- data/test/integration/navigation_test.rb +1 -1
- data/test/sites/complex/users.yml +1 -1
- data/test/sites/ocean/users.yml +3 -3
- data/test/sites/zena/users.yml +5 -4
- data/test/test_zena.rb +38 -38
- data/test/unit/cached_page_test.rb +2 -2
- data/test/unit/comment_test.rb +0 -1
- data/test/unit/document_test.rb +23 -11
- data/test/unit/helpers/ping_helper_test.rb +4 -0
- data/test/unit/multiversion_test.rb +24 -16
- data/test/unit/node_test.rb +32 -93
- data/test/unit/note_test.rb +9 -0
- data/test/unit/page_test.rb +2 -2
- data/test/unit/secure_test.rb +2 -12
- data/test/unit/site_test.rb +43 -24
- data/test/unit/template_test.rb +45 -3
- data/test/unit/text_document_test.rb +4 -3
- data/test/unit/user_test.rb +13 -33
- data/test/unit/zena/db_test.rb +8 -0
- data/test/unit/zena/parser/zazen.yml +4 -4
- data/test/unit/zena/use/dates_view_methods_test.rb +2 -1
- data/test/unit/zena/use/html_tags_test.rb +12 -4
- data/test/unit/zena/use/refactor_test.rb +4 -3
- data/test/unit/zena/use/rendering_test.rb +1 -0
- data/test/unit/zena/use/upload_test.rb +76 -0
- data/test/unit/zena/use/urls_test.rb +4 -0
- data/test/unit/zena/use/zafu_test.rb +8 -0
- data/test/unit/zena/workflow/status_version_test.rb +6 -0
- data/test/unit/zena/zena_tags/ajax.yml +4 -4
- data/test/unit/zena/zena_tags/basic.yml +21 -10
- data/test/unit/zena/zena_tags/relations.yml +0 -6
- data/test/unit/zena/zena_tags/rubyless.yml +35 -0
- data/test/unit/zena/zena_tags/zazen.yml +4 -4
- data/test/unit/zena/zena_tags_test.rb +36 -4
- data/vendor/TextMate/Zena.tmbundle/Commands/Run all yaml tests.tmCommand +1 -1
- data/vendor/TextMate/Zena.tmbundle/Commands/Run focused yaml test.tmCommand +2 -3
- data/vendor/TextMate/Zena.tmbundle/Support/RubyMate/catch_exception.rb +39 -0
- data/vendor/TextMate/Zena.tmbundle/Support/RubyMate/run_script.rb +102 -58
- data/vendor/TextMate/Zena.tmbundle/Support/RubyMate/stdin_dialog.rb +14 -0
- data/vendor/TextMate/Zena.tmbundle/info.plist +2 -0
- data/zena.gemspec +2085 -0
- metadata +265 -90
- data/app/controllers/sessions_controller.rb +0 -41
- data/app/views/sites/zena_up.html.erb +0 -11
- data/config/database.yml +0 -40
- data/db/production.sqlite3 +0 -0
- data/lib/bricks/patcher.rb +0 -68
- data/lib/zena/parser/zena_tags.rb +0 -3562
- data/lib/zena/use/authentification.rb +0 -120
- data/public/images/ext/contact_pv.png +0 -0
- data/public/images/ext/other_pv.png +0 -0
- data/public/images/ext/page_pv.png +0 -0
- data/public/images/ext/page_tiny.png +0 -0
- data/public/images/ext/pdf_pv.png +0 -0
- data/public/images/ext/post_pv.png +0 -0
- data/public/images/ext/post_tiny.png +0 -0
- data/public/images/ext/project_pv.png +0 -0
- data/public/images/ext/project_tiny.png +0 -0
- data/public/images/ext/tag_pv.png +0 -0
- data/public/images/ext/zip_pv.png +0 -0
- data/tasks/ann.rake +0 -80
- data/tasks/bones.rake +0 -20
- data/tasks/gem.rake +0 -201
- data/tasks/git.rake +0 -40
- data/tasks/notes.rake +0 -27
- data/tasks/post_load.rake +0 -34
- data/tasks/rdoc.rake +0 -51
- data/tasks/rubyforge.rake +0 -55
- data/tasks/setup.rb +0 -292
- data/tasks/spec.rake +0 -54
- data/tasks/svn.rake +0 -47
- data/tasks/test.rake +0 -40
- data/tasks/zentest.rake +0 -36
- data/test/fixtures/comments.yml +0 -126
- data/test/fixtures/contact_contents.yml +0 -132
- data/test/fixtures/data_entries.yml +0 -65
- data/test/fixtures/discussions.yml +0 -48
- data/test/fixtures/document_contents.yml +0 -108
- data/test/fixtures/dyn_attributes.yml +0 -66
- data/test/fixtures/groups.yml +0 -86
- data/test/fixtures/groups_users.yml +0 -81
- data/test/fixtures/iformats.yml +0 -29
- data/test/fixtures/links.yml +0 -313
- data/test/fixtures/nodes.yml +0 -2592
- data/test/fixtures/relations.yml +0 -126
- data/test/fixtures/sites.yml +0 -58
- data/test/fixtures/template_contents.yml +0 -172
- data/test/fixtures/users.yml +0 -167
- data/test/fixtures/versions.yml +0 -1911
- data/test/fixtures/virtual_classes.yml +0 -87
- data/test/fixtures/zips.yml +0 -15
- data/test/functional/sessions_controller_test.rb +0 -73
data/lib/zena/use/i18n.rb
CHANGED
|
@@ -136,7 +136,10 @@ module Zena
|
|
|
136
136
|
include Common
|
|
137
137
|
|
|
138
138
|
def self.included(base)
|
|
139
|
-
|
|
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
|
-
|
|
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
|
|
477
|
-
self.send(
|
|
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?
|
data/lib/zena/use/refactor.rb
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
200
|
+
controller.render(*args)
|
|
213
201
|
end
|
|
214
202
|
|
|
215
203
|
end # ViewMethods
|
data/lib/zena/use/relations.rb
CHANGED
data/lib/zena/use/rendering.rb
CHANGED
|
@@ -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
|
data/lib/zena/use/test_helper.rb
CHANGED
|
@@ -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
|
-
|
|
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(
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
|
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
|
-
(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|