Mercurial > hg > soundsoftware-site
diff app/models/attachment.rb @ 1298:4f746d8966dd redmine_2.3_integration
Merge from redmine-2.3 branch to create new branch redmine-2.3-integration
author | Chris Cannam |
---|---|
date | Fri, 14 Jun 2013 09:28:30 +0100 |
parents | 622f24f53b42 |
children |
line wrap: on
line diff
--- a/app/models/attachment.rb Fri Jun 14 09:07:32 2013 +0100 +++ b/app/models/attachment.rb Fri Jun 14 09:28:30 2013 +0100 @@ -1,5 +1,5 @@ # Redmine - project management software -# Copyright (C) 2006-2012 Jean-Philippe Lang +# Copyright (C) 2006-2013 Jean-Philippe Lang # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -16,6 +16,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. require "digest/md5" +require "fileutils" class Attachment < ActiveRecord::Base belongs_to :container, :polymorphic => true @@ -92,9 +93,6 @@ def filename=(arg) write_attribute :filename, sanitize_filename(arg.to_s) - if new_record? && disk_filename.blank? - self.disk_filename = Attachment.disk_filename(filename) - end filename end @@ -102,7 +100,13 @@ # and computes its MD5 hash def files_to_final_location if @temp_file && (@temp_file.size > 0) + self.disk_directory = target_directory + self.disk_filename = Attachment.disk_filename(filename, disk_directory) logger.info("Saving attachment '#{self.diskfile}' (#{@temp_file.size} bytes)") + path = File.dirname(diskfile) + unless File.directory?(path) + FileUtils.mkdir_p(path) + end md5 = Digest::MD5.new File.open(diskfile, "wb") do |f| if @temp_file.respond_to?(:read) @@ -134,7 +138,7 @@ # Returns file's location on disk def diskfile - File.join(self.class.storage_path, disk_filename.to_s) + File.join(self.class.storage_path, disk_directory.to_s, disk_filename.to_s) end def title @@ -154,11 +158,19 @@ end def visible?(user=User.current) - container && container.attachments_visible?(user) + if container_id + container && container.attachments_visible?(user) + else + author == user + end end def deletable?(user=User.current) - container && container.attachments_deletable?(user) + if container_id + container && container.attachments_deletable?(user) + else + author == user + end end def image? @@ -251,6 +263,26 @@ Attachment.where("created_on < ? AND (container_type IS NULL OR container_type = '')", Time.now - age).destroy_all end + # Moves an existing attachment to its target directory + def move_to_target_directory! + if !new_record? & readable? + src = diskfile + self.disk_directory = target_directory + dest = diskfile + if src != dest && FileUtils.mkdir_p(File.dirname(dest)) && FileUtils.mv(src, dest) + update_column :disk_directory, disk_directory + end + end + end + + # Moves existing attachments that are stored at the root of the files + # directory (ie. created before Redmine 2.3) to their target subdirectories + def self.move_from_root_to_target_directory + Attachment.where("disk_directory IS NULL OR disk_directory = ''").find_each do |attachment| + attachment.move_to_target_directory! + end + end + private # Physically deletes the file from the file system @@ -268,8 +300,15 @@ @filename = just_filename.gsub(/[\/\?\%\*\:\|\"\'<>]+/, '_') end - # Returns an ASCII or hashed filename - def self.disk_filename(filename) + # Returns the subdirectory in which the attachment will be saved + def target_directory + time = created_on || DateTime.now + time.strftime("%Y/%m") + end + + # Returns an ASCII or hashed filename that do not + # exists yet in the given subdirectory + def self.disk_filename(filename, directory=nil) timestamp = DateTime.now.strftime("%y%m%d%H%M%S") ascii = '' if filename =~ %r{^[a-zA-Z0-9_\.\-]*$} @@ -279,7 +318,7 @@ # keep the extension if any ascii << $1 if filename =~ %r{(\.[a-zA-Z0-9]+)$} end - while File.exist?(File.join(@@storage_path, "#{timestamp}_#{ascii}")) + while File.exist?(File.join(storage_path, directory.to_s, "#{timestamp}_#{ascii}")) timestamp.succ! end "#{timestamp}_#{ascii}"