summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean-Philippe Lang <jp_lang@yahoo.fr>2012-07-16 17:15:40 +0000
committerJean-Philippe Lang <jp_lang@yahoo.fr>2012-07-16 17:15:40 +0000
commit537be80be26c38d5384d588873d2682fd908ee62 (patch)
tree0f4a60940759a5ad8d86bebcd17b36649b02dfc8
parent5c2de4dfc95293a7965ff8cf980a310922fc4c05 (diff)
downloadredmine-537be80be26c38d5384d588873d2682fd908ee62.tar.gz
redmine-537be80be26c38d5384d588873d2682fd908ee62.zip
Adds a macro for inserting thumbnails in formatted text (#3510).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@10013 e93f8b46-1217-0410-a6f0-8f06a7374b81
-rw-r--r--app/controllers/attachments_controller.rb2
-rw-r--r--app/models/attachment.rb12
-rw-r--r--config/routes.rb2
-rw-r--r--lib/redmine/wiki_formatting/macros.rb18
-rw-r--r--test/functional/attachments_controller_test.rb47
-rw-r--r--test/integration/routing/attachments_test.rb4
-rw-r--r--test/unit/lib/redmine/wiki_formatting/macros_test.rb20
7 files changed, 78 insertions, 27 deletions
diff --git a/app/controllers/attachments_controller.rb b/app/controllers/attachments_controller.rb
index edae9b0cc..74a11a1c7 100644
--- a/app/controllers/attachments_controller.rb
+++ b/app/controllers/attachments_controller.rb
@@ -61,7 +61,7 @@ class AttachmentsController < ApplicationController
end
def thumbnail
- if @attachment.thumbnailable? && Setting.thumbnails_enabled? && thumbnail = @attachment.thumbnail
+ if @attachment.thumbnailable? && thumbnail = @attachment.thumbnail(:size => params[:size])
if stale?(:etag => thumbnail)
send_file thumbnail,
:filename => filename_for_content_disposition(@attachment.filename),
diff --git a/app/models/attachment.rb b/app/models/attachment.rb
index 9aeee07d0..a1c232d16 100644
--- a/app/models/attachment.rb
+++ b/app/models/attachment.rb
@@ -171,9 +171,17 @@ class Attachment < ActiveRecord::Base
# Returns the full path the attachment thumbnail, or nil
# if the thumbnail cannot be generated.
- def thumbnail
+ def thumbnail(options={})
if thumbnailable? && readable?
- size = Setting.thumbnails_size.to_i
+ size = options[:size].to_i
+ if size > 0
+ # Limit the number of thumbnails per image
+ size = (size / 50) * 50
+ # Maximum thumbnail size
+ size = 800 if size > 800
+ else
+ size = Setting.thumbnails_size.to_i
+ end
size = 100 unless size > 0
target = File.join(self.class.thumbnails_storage_path, "#{id}_#{digest}_#{size}.thumb")
diff --git a/config/routes.rb b/config/routes.rb
index 87e656475..d904c9b9e 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -264,7 +264,7 @@ RedmineApp::Application.routes.draw do
match 'attachments/:id/:filename', :controller => 'attachments', :action => 'show', :id => /\d+/, :filename => /.*/, :via => :get
match 'attachments/download/:id/:filename', :controller => 'attachments', :action => 'download', :id => /\d+/, :filename => /.*/, :via => :get
match 'attachments/download/:id', :controller => 'attachments', :action => 'download', :id => /\d+/, :via => :get
- match 'attachments/thumbnail/:id', :controller => 'attachments', :action => 'thumbnail', :id => /\d+/, :via => :get
+ match 'attachments/thumbnail/:id(/:size)', :controller => 'attachments', :action => 'thumbnail', :id => /\d+/, :via => :get, :size => /\d+/
resources :attachments, :only => [:show, :destroy]
resources :groups do
diff --git a/lib/redmine/wiki_formatting/macros.rb b/lib/redmine/wiki_formatting/macros.rb
index cd1d83596..81e5999f8 100644
--- a/lib/redmine/wiki_formatting/macros.rb
+++ b/lib/redmine/wiki_formatting/macros.rb
@@ -116,6 +116,24 @@ module Redmine
@included_wiki_pages.pop
out
end
+
+ desc "Displays a clickable thumbnail of an attached image. Examples:\n\n<pre>{{thumbnail(image.png)}}\n{{thumbnail(image.png, size=300, title=Thumbnail)}}</pre>"
+ macro :thumbnail do |obj, args|
+ args, options = extract_macro_options(args, :size, :title)
+ filename = args.first
+ raise 'Filename required' unless filename.present?
+ size = options[:size]
+ raise 'Invalid size parameter' unless size.nil? || size.match(/^\d+$/)
+ size = size.to_i
+ size = nil unless size > 0
+ if obj && obj.respond_to?(:attachments) && attachment = Attachment.latest_attach(obj.attachments, filename)
+ title = options[:title] || attachment.title
+ img = image_tag(url_for(:controller => 'attachments', :action => 'thumbnail', :id => attachment, :size => size), :alt => attachment.filename)
+ link_to(img, url_for(:controller => 'attachments', :action => 'show', :id => attachment), :class => 'thumbnail', :title => title)
+ else
+ raise "Attachment #{filename} not found"
+ end
+ end
end
end
end
diff --git a/test/functional/attachments_controller_test.rb b/test/functional/attachments_controller_test.rb
index 949ed3979..11c3faa95 100644
--- a/test/functional/attachments_controller_test.rb
+++ b/test/functional/attachments_controller_test.rb
@@ -262,43 +262,44 @@ class AttachmentsControllerTest < ActionController::TestCase
def test_thumbnail
Attachment.clear_thumbnails
@request.session[:user_id] = 2
- with_settings :thumbnails_enabled => '1' do
- get :thumbnail, :id => 16
- assert_response :success
- assert_equal 'image/png', response.content_type
- end
+
+ get :thumbnail, :id => 16
+ assert_response :success
+ assert_equal 'image/png', response.content_type
end
- def test_thumbnail_should_return_404_for_non_image_attachment
+ def test_thumbnail_should_not_exceed_maximum_size
+ Redmine::Thumbnail.expects(:generate).with {|source, target, size| size == 800}
+
@request.session[:user_id] = 2
- with_settings :thumbnails_enabled => '1' do
- get :thumbnail, :id => 15
- assert_response 404
- end
+ get :thumbnail, :id => 16, :size => 2000
end
- def test_thumbnail_should_return_404_if_thumbnails_not_enabled
+ def test_thumbnail_should_round_size
+ Redmine::Thumbnail.expects(:generate).with {|source, target, size| size == 250}
+
@request.session[:user_id] = 2
- with_settings :thumbnails_enabled => '0' do
- get :thumbnail, :id => 16
- assert_response 404
- end
+ get :thumbnail, :id => 16, :size => 260
+ end
+
+ def test_thumbnail_should_return_404_for_non_image_attachment
+ @request.session[:user_id] = 2
+
+ get :thumbnail, :id => 15
+ assert_response 404
end
def test_thumbnail_should_return_404_if_thumbnail_generation_failed
Attachment.any_instance.stubs(:thumbnail).returns(nil)
@request.session[:user_id] = 2
- with_settings :thumbnails_enabled => '1' do
- get :thumbnail, :id => 16
- assert_response 404
- end
+
+ get :thumbnail, :id => 16
+ assert_response 404
end
def test_thumbnail_should_be_denied_without_permission
- with_settings :thumbnails_enabled => '1' do
- get :thumbnail, :id => 16
- assert_redirected_to '/login?back_url=http%3A%2F%2Ftest.host%2Fattachments%2Fthumbnail%2F16'
- end
+ get :thumbnail, :id => 16
+ assert_redirected_to '/login?back_url=http%3A%2F%2Ftest.host%2Fattachments%2Fthumbnail%2F16'
end
else
puts '(ImageMagick convert not available)'
diff --git a/test/integration/routing/attachments_test.rb b/test/integration/routing/attachments_test.rb
index ba4bb2c36..fc54dea41 100644
--- a/test/integration/routing/attachments_test.rb
+++ b/test/integration/routing/attachments_test.rb
@@ -50,6 +50,10 @@ class RoutingAttachmentsTest < ActionController::IntegrationTest
{ :controller => 'attachments', :action => 'thumbnail', :id => '1' }
)
assert_routing(
+ { :method => 'get', :path => "/attachments/thumbnail/1/200" },
+ { :controller => 'attachments', :action => 'thumbnail', :id => '1', :size => '200' }
+ )
+ assert_routing(
{ :method => 'delete', :path => "/attachments/1" },
{ :controller => 'attachments', :action => 'destroy', :id => '1' }
)
diff --git a/test/unit/lib/redmine/wiki_formatting/macros_test.rb b/test/unit/lib/redmine/wiki_formatting/macros_test.rb
index abc880068..4bea9a57d 100644
--- a/test/unit/lib/redmine/wiki_formatting/macros_test.rb
+++ b/test/unit/lib/redmine/wiki_formatting/macros_test.rb
@@ -119,4 +119,24 @@ class Redmine::WikiFormatting::MacrosTest < ActionView::TestCase
def test_macro_child_pages_without_wiki_page_should_fail
assert_match /can be called from wiki pages only/, textilizable("{{child_pages}}")
end
+
+ def test_macro_thumbnail
+ assert_equal '<p><a href="/attachments/17" class="thumbnail" title="testfile.PNG"><img alt="testfile.PNG" src="/attachments/thumbnail/17" /></a></p>',
+ textilizable("{{thumbnail(testfile.png)}}", :object => Issue.find(14))
+ end
+
+ def test_macro_thumbnail_with_size
+ assert_equal '<p><a href="/attachments/17" class="thumbnail" title="testfile.PNG"><img alt="testfile.PNG" src="/attachments/thumbnail/17/200" /></a></p>',
+ textilizable("{{thumbnail(testfile.png, size=200)}}", :object => Issue.find(14))
+ end
+
+ def test_macro_thumbnail_with_title
+ assert_equal '<p><a href="/attachments/17" class="thumbnail" title="Cool image"><img alt="testfile.PNG" src="/attachments/thumbnail/17" /></a></p>',
+ textilizable("{{thumbnail(testfile.png, title=Cool image)}}", :object => Issue.find(14))
+ end
+
+ def test_macro_thumbnail_with_invalid_filename_should_fail
+ assert_include 'test.png not found',
+ textilizable("{{thumbnail(test.png)}}", :object => Issue.find(14))
+ end
end