File Storage Directory does not change #522

This commit is contained in:
Karel Picman 2016-04-12 12:07:16 +02:00
parent 68c68cdf79
commit 3a4d3e8b2b
4 changed files with 132 additions and 123 deletions

12
Gemfile
View File

@ -1,5 +1,5 @@
# encoding: utf-8 # encoding: utf-8
# #
# Redmine plugin for Document Management System "Features" # Redmine plugin for Document Management System "Features"
# #
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com> # Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
@ -22,12 +22,12 @@
source 'https://rubygems.org' source 'https://rubygems.org'
gem 'rubyzip', '>= 1.0.0' gem 'rubyzip'
gem 'zip-zip' # Just to avoid 'cannot load such file -- zip/zip' error gem 'zip-zip'
gem 'simple_enum' gem 'simple_enum'
gem 'uuidtools', '~> 2.1.1' gem 'uuidtools'
gem 'dav4rack', '~> 0.3.0' gem 'dav4rack'
group :xapian do group :xapian do
gem 'xapian-full-alaveteli', :require => false gem 'xapian-full-alaveteli', :require => false
end end

View File

@ -1,5 +1,5 @@
# encoding: utf-8 # encoding: utf-8
# #
# Redmine plugin for Document Management System "Features" # Redmine plugin for Document Management System "Features"
# #
# Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com> # Copyright (C) 2011 Vít Jonáš <vit.jonas@gmail.com>
@ -21,16 +21,16 @@
class DmsfUploadController < ApplicationController class DmsfUploadController < ApplicationController
unloadable unloadable
menu_item :dmsf menu_item :dmsf
before_filter :find_project before_filter :find_project
before_filter :authorize before_filter :authorize
before_filter :find_folder, :except => [:upload_file, :upload, :commit] before_filter :find_folder, :except => [:upload_file, :upload, :commit]
helper :all helper :all
helper :dmsf_workflows helper :dmsf_workflows
accept_api_auth :upload, :commit accept_api_auth :upload, :commit
def upload_files def upload_files
@ -38,7 +38,7 @@ class DmsfUploadController < ApplicationController
@uploads = [] @uploads = []
if uploaded_files && uploaded_files.is_a?(Hash) if uploaded_files && uploaded_files.is_a?(Hash)
# standard file input uploads # standard file input uploads
uploaded_files.each_value do |uploaded_file| uploaded_files.each_value do |uploaded_file|
upload = DmsfUpload.create_from_uploaded_attachment(@project, @folder, uploaded_file) upload = DmsfUpload.create_from_uploaded_attachment(@project, @folder, uploaded_file)
@uploads.push(upload) if upload @uploads.push(upload) if upload
end end
@ -53,9 +53,9 @@ class DmsfUploadController < ApplicationController
end end
end end
# async single file upload handling # async single file upload handling
def upload_file def upload_file
@tempfile = params[:file] @tempfile = params[:file]
unless @tempfile.original_filename unless @tempfile.original_filename
render_404 render_404
return return
@ -72,21 +72,21 @@ class DmsfUploadController < ApplicationController
rescue Exception => e rescue Exception => e
Rails.logger.error e.message Rails.logger.error e.message
end end
render :layout => nil, :json => { :jsonrpc => '2.0', render :layout => nil, :json => { :jsonrpc => '2.0',
:error => { :error => {
:code => 103, :code => 103,
:message => l(:header_minimum_filesize), :message => l(:header_minimum_filesize),
:details => l(:error_minimum_filesize, :details => l(:error_minimum_filesize,
:file => @tempfile.original_filename.to_s) :file => @tempfile.original_filename.to_s)
} }
} }
else else
render :layout => false render :layout => false
end end
end end
# REST API document upload # REST API document upload
def upload def upload
unless request.content_type == 'application/octet-stream' unless request.content_type == 'application/octet-stream'
render :nothing => true, :status => 406 render :nothing => true, :status => 406
return return
@ -109,69 +109,69 @@ class DmsfUploadController < ApplicationController
} }
end end
end end
def commit_files def commit_files
commit_files_internal params[:commited_files] commit_files_internal params[:commited_files]
end end
# REST API file commit # REST API file commit
def commit def commit
attachments = params[:attachments] attachments = params[:attachments]
if attachments && attachments.is_a?(Hash) if attachments && attachments.is_a?(Hash)
@folder = DmsfFolder.visible.find_by_id attachments[:folder_id].to_i if attachments[:folder_id].present? @folder = DmsfFolder.visible.find_by_id attachments[:folder_id].to_i if attachments[:folder_id].present?
# standard file input uploads # standard file input uploads
uploaded_files = attachments.select { |key, value| key == 'uploaded_file'} uploaded_files = attachments.select { |key, value| key == 'uploaded_file'}
uploaded_files.each_value do |uploaded_file| uploaded_files.each_value do |uploaded_file|
upload = DmsfUpload.create_from_uploaded_attachment(@project, @folder, uploaded_file) upload = DmsfUpload.create_from_uploaded_attachment(@project, @folder, uploaded_file)
uploaded_file[:disk_filename] = upload.disk_filename uploaded_file[:disk_filename] = upload.disk_filename
end end
end end
commit_files_internal uploaded_files commit_files_internal uploaded_files
end end
private private
def commit_files_internal(commited_files) def commit_files_internal(commited_files)
if commited_files && commited_files.is_a?(Hash) if commited_files && commited_files.is_a?(Hash)
@files = [] @files = []
failed_uploads = [] failed_uploads = []
commited_files.each_value do |commited_file| commited_files.each_value do |commited_file|
name = commited_file[:name] name = commited_file[:name]
new_revision = DmsfFileRevision.new new_revision = DmsfFileRevision.new
file = DmsfFile.visible.find_file_by_name(@project, @folder, name) file = DmsfFile.visible.find_file_by_name(@project, @folder, name)
unless file unless file
link = DmsfLink.find_link_by_file_name(@project, @folder, name) link = DmsfLink.find_link_by_file_name(@project, @folder, name)
file = link.target_file if link file = link.target_file if link
end end
unless file unless file
file = DmsfFile.new file = DmsfFile.new
file.project = @project file.project = @project
file.name = name file.name = name
file.folder = @folder file.folder = @folder
file.notification = Setting.plugin_redmine_dmsf[:dmsf_default_notifications].present? file.notification = Setting.plugin_redmine_dmsf[:dmsf_default_notifications].present?
new_revision.minor_version = 0 new_revision.minor_version = 0
new_revision.major_version = 0 new_revision.major_version = 0
else else
if file.last_revision if file.last_revision
last_revision = file.last_revision last_revision = file.last_revision
new_revision.source_revision = last_revision new_revision.source_revision = last_revision
new_revision.major_version = last_revision.major_version new_revision.major_version = last_revision.major_version
new_revision.minor_version = last_revision.minor_version new_revision.minor_version = last_revision.minor_version
else else
new_revision.minor_version = 0 new_revision.minor_version = 0
new_revision.major_version = 0 new_revision.major_version = 0
end end
end end
if file.locked_for_user? if file.locked_for_user?
failed_uploads.push(commited_file) failed_uploads.push(commited_file)
next next
end end
commited_disk_filepath = "#{DmsfHelper.temp_dir}/#{commited_file[:disk_filename].gsub(/[\/\\]/,'')}" commited_disk_filepath = "#{DmsfHelper.temp_dir}/#{commited_file[:disk_filename].gsub(/[\/\\]/,'')}"
new_revision.file = file new_revision.file = file
new_revision.user = User.current new_revision.user = User.current
new_revision.name = name new_revision.name = name
@ -183,43 +183,49 @@ class DmsfUploadController < ApplicationController
new_revision.major_version = commited_file[:custom_version_major].to_i new_revision.major_version = commited_file[:custom_version_major].to_i
new_revision.minor_version = commited_file[:custom_version_minor].to_i new_revision.minor_version = commited_file[:custom_version_minor].to_i
else else
new_revision.increase_version(version, true) new_revision.increase_version(version, true)
end end
new_revision.mime_type = Redmine::MimeType.of(new_revision.name) new_revision.mime_type = Redmine::MimeType.of(new_revision.name)
new_revision.size = File.size(commited_disk_filepath) new_revision.size = File.size(commited_disk_filepath)
# Need to save file first to generate id for it in case of creation. # Need to save file first to generate id for it in case of creation.
# File id is needed to properly generate revision disk filename # File id is needed to properly generate revision disk filename
if commited_file[:dmsf_file_revision].present? if commited_file[:dmsf_file_revision].present?
commited_file[:dmsf_file_revision][:custom_field_values].each_with_index do |v, i| commited_file[:dmsf_file_revision][:custom_field_values].each_with_index do |v, i|
new_revision.custom_field_values[i].value = v[1] new_revision.custom_field_values[i].value = v[1]
end end
end end
if new_revision.valid? && file.save if new_revision.valid? && file.save
new_revision.disk_filename = new_revision.new_storage_filename new_revision.disk_filename = new_revision.new_storage_filename
else else
failed_uploads.push(commited_file) failed_uploads.push(commited_file)
next next
end end
if new_revision.save if new_revision.save
new_revision.assign_workflow(commited_file[:dmsf_workflow_id]) new_revision.assign_workflow(commited_file[:dmsf_workflow_id])
FileUtils.mv(commited_disk_filepath, new_revision.disk_file) begin
file.set_last_revision new_revision FileUtils.mv(commited_disk_filepath, new_revision.disk_file)
@files.push(file) file.set_last_revision new_revision
@files.push(file)
rescue Exception => e
Rails.logger.error e.message
flash[:error] = e.message
failed_uploads.push(file)
end
else else
failed_uploads.push(commited_file) failed_uploads.push(commited_file)
end end
end end
unless @files.empty? unless @files.empty?
@files.each { |file| log_activity(file, 'uploaded') if file } @files.each { |file| log_activity(file, 'uploaded') if file }
if (@folder && @folder.notification?) || (!@folder && @project.dmsf_notification?) if (@folder && @folder.notification?) || (!@folder && @project.dmsf_notification?)
begin begin
recipients = DmsfMailer.get_notify_users(@project, @files) recipients = DmsfMailer.get_notify_users(@project, @files)
recipients.each do |u| recipients.each do |u|
DmsfMailer.files_updated(u, @project, @files).deliver DmsfMailer.files_updated(u, @project, @files).deliver
end end
if Setting.plugin_redmine_dmsf[:dmsf_display_notified_recipients] == '1' if Setting.plugin_redmine_dmsf[:dmsf_display_notified_recipients] == '1'
unless recipients.empty? unless recipients.empty?
to = recipients.collect{ |r| r.name }.first(DMSF_MAX_NOTIFICATION_RECEIVERS_INFO).join(', ') to = recipients.collect{ |r| r.name }.first(DMSF_MAX_NOTIFICATION_RECEIVERS_INFO).join(', ')
@ -238,22 +244,22 @@ class DmsfUploadController < ApplicationController
end end
respond_to do |format| respond_to do |format|
format.js format.js
format.api { format.api {
render_validation_errors(failed_uploads) unless failed_uploads.empty? render_validation_errors(failed_uploads) unless failed_uploads.empty?
} }
format.html { redirect_to dmsf_folder_path(:id => @project, :folder_id => @folder) } format.html { redirect_to dmsf_folder_path(:id => @project, :folder_id => @folder) }
end end
end end
def log_activity(file, action) def log_activity(file, action)
Rails.logger.info "#{Time.now.strftime('%Y-%m-%d %H:%M:%S')} #{User.current.login}@#{request.remote_ip}/#{request.env['HTTP_X_FORWARDED_FOR']}: #{action} dmsf://#{file.project.identifier}/#{file.id}/#{file.last_revision.id}" Rails.logger.info "#{Time.now.strftime('%Y-%m-%d %H:%M:%S')} #{User.current.login}@#{request.remote_ip}/#{request.env['HTTP_X_FORWARDED_FOR']}: #{action} dmsf://#{file.project.identifier}/#{file.id}/#{file.last_revision.id}"
end end
def find_folder def find_folder
@folder = DmsfFolder.visible.find(params[:folder_id]) if params.keys.include?('folder_id') @folder = DmsfFolder.visible.find(params[:folder_id]) if params.keys.include?('folder_id')
rescue DmsfAccessError rescue DmsfAccessError
render_403 render_403
end end
end end

View File

@ -29,13 +29,13 @@ end
class DmsfFile < ActiveRecord::Base class DmsfFile < ActiveRecord::Base
unloadable unloadable
include RedmineDmsf::Lockable include RedmineDmsf::Lockable
belongs_to :project belongs_to :project
belongs_to :folder, :class_name => 'DmsfFolder', :foreign_key => 'dmsf_folder_id' belongs_to :folder, :class_name => 'DmsfFolder', :foreign_key => 'dmsf_folder_id'
belongs_to :deleted_by_user, :class_name => 'User', :foreign_key => 'deleted_by_user_id' belongs_to :deleted_by_user, :class_name => 'User', :foreign_key => 'deleted_by_user_id'
has_many :revisions, -> { order("#{DmsfFileRevision.table_name}.major_version DESC, #{DmsfFileRevision.table_name}.minor_version DESC, #{DmsfFileRevision.table_name}.updated_at DESC") }, has_many :revisions, -> { order("#{DmsfFileRevision.table_name}.major_version DESC, #{DmsfFileRevision.table_name}.minor_version DESC, #{DmsfFileRevision.table_name}.updated_at DESC") },
:class_name => 'DmsfFileRevision', :foreign_key => 'dmsf_file_id', :class_name => 'DmsfFileRevision', :foreign_key => 'dmsf_file_id',
:dependent => :destroy :dependent => :destroy
@ -44,10 +44,10 @@ class DmsfFile < ActiveRecord::Base
has_many :referenced_links, -> { where target_type: DmsfFile.model_name.to_s}, has_many :referenced_links, -> { where target_type: DmsfFile.model_name.to_s},
:class_name => 'DmsfLink', :foreign_key => 'target_id', :dependent => :destroy :class_name => 'DmsfLink', :foreign_key => 'target_id', :dependent => :destroy
accepts_nested_attributes_for :revisions, :locks, :referenced_links, :project accepts_nested_attributes_for :revisions, :locks, :referenced_links, :project
STATUS_DELETED = 1 STATUS_DELETED = 1
STATUS_ACTIVE = 0 STATUS_ACTIVE = 0
scope :visible, -> { where(:deleted => STATUS_ACTIVE) } scope :visible, -> { where(:deleted => STATUS_ACTIVE) }
scope :deleted, -> { where(:deleted => STATUS_DELETED) } scope :deleted, -> { where(:deleted => STATUS_DELETED) }
@ -61,27 +61,27 @@ class DmsfFile < ActiveRecord::Base
existing_file = DmsfFile.visible.find_file_by_name(self.project, self.folder, self.name) existing_file = DmsfFile.visible.find_file_by_name(self.project, self.folder, self.name)
errors.add(:name, l('activerecord.errors.messages.taken')) unless errors.add(:name, l('activerecord.errors.messages.taken')) unless
existing_file.nil? || existing_file.id == self.id existing_file.nil? || existing_file.id == self.id
end end
acts_as_event :title => Proc.new { |o| o.name }, acts_as_event :title => Proc.new { |o| o.name },
:description => Proc.new { |o| :description => Proc.new { |o|
desc = Redmine::Search.cache_store.fetch("DmsfFile-#{o.id}") desc = Redmine::Search.cache_store.fetch("DmsfFile-#{o.id}")
if desc if desc
Redmine::Search.cache_store.delete("DmsfFile-#{o.id}") Redmine::Search.cache_store.delete("DmsfFile-#{o.id}")
else else
desc = o.description desc = o.description
desc += ' / ' if o.description.present? && o.last_revision.comment.present? desc += ' / ' if o.description.present? && o.last_revision.comment.present?
desc += o.last_revision.comment if o.last_revision.comment.present? desc += o.last_revision.comment if o.last_revision.comment.present?
end end
desc desc
}, },
:url => Proc.new { |o| {:controller => 'dmsf_files', :action => 'show', :id => o} }, :url => Proc.new { |o| {:controller => 'dmsf_files', :action => 'show', :id => o} },
:datetime => Proc.new { |o| o.updated_at }, :datetime => Proc.new { |o| o.updated_at },
:author => Proc.new { |o| o.last_revision.user } :author => Proc.new { |o| o.last_revision.user }
acts_as_searchable :columns => ["#{table_name}.name", "#{DmsfFileRevision.table_name}.title", "#{DmsfFileRevision.table_name}.description", "#{DmsfFileRevision.table_name}.comment"], acts_as_searchable :columns => ["#{table_name}.name", "#{DmsfFileRevision.table_name}.title", "#{DmsfFileRevision.table_name}.description", "#{DmsfFileRevision.table_name}.comment"],
:project_key => 'project_id', :project_key => 'project_id',
:date_column => "#{table_name}.updated_at" :date_column => "#{table_name}.updated_at"
before_create :default_values before_create :default_values
def default_values def default_values
@ -96,19 +96,22 @@ class DmsfFile < ActiveRecord::Base
@@storage_path = nil @@storage_path = nil
def self.storage_path def self.storage_path
unless @@storage_path.present? path = Setting.plugin_redmine_dmsf['dmsf_storage_directory'].strip if Setting.plugin_redmine_dmsf['dmsf_storage_directory'].present?
@@storage_path = Setting.plugin_redmine_dmsf['dmsf_storage_directory'].strip if Setting.plugin_redmine_dmsf['dmsf_storage_directory'].present? path = Pathname(Redmine::Configuration['attachments_storage_path']).join('dmsf') if path.blank? && Redmine::Configuration['attachments_storage_path'].present?
@@storage_path = Pathname(Redmine::Configuration['attachments_storage_path']).join('dmsf') if @@storage_path.blank? && Redmine::Configuration['attachments_storage_path'].present? path = Rails.root.join('files/dmsf').to_s if path.blank?
@@storage_path = Rails.root.join('files/dmsf').to_s if @@storage_path.blank? DmsfFile.storage_path = path if path != @@storage_path
Dir.mkdir(@@storage_path) unless File.exists?(@@storage_path)
end
@@storage_path @@storage_path
end end
# Lets introduce a write for storage path, that way we can also # Lets introduce a write for storage path, that way we can also
# better interact from test-cases etc # better interact from test-cases etc
def self.storage_path=(obj) def self.storage_path=(path)
@@storage_path = obj begin
FileUtils.mkdir_p(path) unless File.exists?(path)
rescue Exception => e
Rails.logger.error e.message
end
@@storage_path = path
end end
def self.find_file_by_name(project, folder, name) def self.find_file_by_name(project, folder, name)
@ -128,7 +131,7 @@ class DmsfFile < ActiveRecord::Base
def set_last_revision(new_revision) def set_last_revision(new_revision)
@last_revision = new_revision @last_revision = new_revision
end end
def deleted? def deleted?
self.deleted == STATUS_DELETED self.deleted == STATUS_DELETED
end end
@ -141,7 +144,7 @@ class DmsfFile < ActiveRecord::Base
end end
begin begin
# Revisions and links of a deleted file SHOULD be deleted too # Revisions and links of a deleted file SHOULD be deleted too
self.revisions.each { |r| r.delete(commit, true) } self.revisions.each { |r| r.delete(commit, true) }
if commit if commit
self.destroy self.destroy
else else
@ -161,7 +164,7 @@ class DmsfFile < ActiveRecord::Base
errors[:base] << l(:error_parent_folder) errors[:base] << l(:error_parent_folder)
return false return false
end end
self.revisions.each { |r| r.restore } self.revisions.each { |r| r.restore }
self.deleted = STATUS_ACTIVE self.deleted = STATUS_ACTIVE
self.deleted_by_user = nil self.deleted_by_user = nil
save save
@ -172,8 +175,8 @@ class DmsfFile < ActiveRecord::Base
end end
def description def description
self.last_revision ? self.last_revision.description : '' self.last_revision ? self.last_revision.description : ''
end end
def version def version
self.last_revision ? self.last_revision.version : '0' self.last_revision ? self.last_revision.version : '0'
@ -291,33 +294,33 @@ class DmsfFile < ActiveRecord::Base
def self.search(tokens, projects = nil, options = {}, user = User.current) def self.search(tokens, projects = nil, options = {}, user = User.current)
tokens = [] << tokens unless tokens.is_a?(Array) tokens = [] << tokens unless tokens.is_a?(Array)
projects = [] << projects if projects.is_a?(Project) projects = [] << projects if projects.is_a?(Project)
project_ids = projects.collect(&:id) if projects project_ids = projects.collect(&:id) if projects
if options[:offset] if options[:offset]
limit_options = ["dmsf_files.updated_at #{options[:before] ? '<' : '>'} ?", options[:offset]] limit_options = ["dmsf_files.updated_at #{options[:before] ? '<' : '>'} ?", options[:offset]]
end end
if options[:titles_only] if options[:titles_only]
columns = [searchable_options[:columns][1]] columns = [searchable_options[:columns][1]]
else else
columns = searchable_options[:columns] columns = searchable_options[:columns]
end end
token_clauses = columns.collect{ |column| "(LOWER(#{column}) LIKE ?)" } token_clauses = columns.collect{ |column| "(LOWER(#{column}) LIKE ?)" }
sql = (['(' + token_clauses.join(' OR ') + ')'] * tokens.size).join(options[:all_words] ? ' AND ' : ' OR ') sql = (['(' + token_clauses.join(' OR ') + ')'] * tokens.size).join(options[:all_words] ? ' AND ' : ' OR ')
find_options = [sql, * (tokens.collect {|w| "%#{w.downcase}%"} * token_clauses.size).sort] find_options = [sql, * (tokens.collect {|w| "%#{w.downcase}%"} * token_clauses.size).sort]
project_conditions = [] project_conditions = []
project_conditions << Project.allowed_to_condition(user, :view_dmsf_files) project_conditions << Project.allowed_to_condition(user, :view_dmsf_files)
project_conditions << "#{DmsfFile.table_name}.project_id IN (#{project_ids.join(',')})" if project_ids.present? project_conditions << "#{DmsfFile.table_name}.project_id IN (#{project_ids.join(',')})" if project_ids.present?
results = [] results = []
scope = self.visible.joins(:project, :revisions) scope = self.visible.joins(:project, :revisions)
scope = scope.limit(options[:limit]) unless options[:limit].blank? scope = scope.limit(options[:limit]) unless options[:limit].blank?
scope = scope.where(limit_options) unless limit_options.blank? scope = scope.where(limit_options) unless limit_options.blank?
scope = scope.where(project_conditions.join(' AND ')) scope = scope.where(project_conditions.join(' AND '))
results = scope.where(find_options).uniq.to_a results = scope.where(find_options).uniq.to_a
if !options[:titles_only] && $xapian_bindings_available if !options[:titles_only] && $xapian_bindings_available
@ -361,7 +364,7 @@ class DmsfFile < ActiveRecord::Base
enquire.query = query enquire.query = query
matchset = enquire.mset(0, 1000) matchset = enquire.mset(0, 1000)
if matchset if matchset
matchset.matches.each { |m| matchset.matches.each { |m|
docdata = m.document.data{url} docdata = m.document.data{url}
dochash = Hash[*docdata.scan(/(url|sample|modtime|author|type|size)=\/?([^\n\]]+)/).flatten] dochash = Hash[*docdata.scan(/(url|sample|modtime|author|type|size)=\/?([^\n\]]+)/).flatten]
@ -372,14 +375,14 @@ class DmsfFile < ActiveRecord::Base
id_attribute = dmsf_attrs[0][1] if dmsf_attrs.length > 0 id_attribute = dmsf_attrs[0][1] if dmsf_attrs.length > 0
next if dmsf_attrs.length == 0 || id_attribute == 0 next if dmsf_attrs.length == 0 || id_attribute == 0
next unless results.select{|f| f.id.to_s == id_attribute}.empty? next unless results.select{|f| f.id.to_s == id_attribute}.empty?
dmsf_file = DmsfFile.visible.where(limit_options).where(:id => id_attribute).first dmsf_file = DmsfFile.visible.where(limit_options).where(:id => id_attribute).first
if dmsf_file if dmsf_file
if user.allowed_to?(:view_dmsf_files, dmsf_file.project) && if user.allowed_to?(:view_dmsf_files, dmsf_file.project) &&
(project_ids.blank? || (project_ids.include?(dmsf_file.project.id))) (project_ids.blank? || (project_ids.include?(dmsf_file.project.id)))
Redmine::Search.cache_store.write("DmsfFile-#{dmsf_file.id}", Redmine::Search.cache_store.write("DmsfFile-#{dmsf_file.id}",
dochash['sample'].force_encoding('UTF-8')) if dochash['sample'] dochash['sample'].force_encoding('UTF-8')) if dochash['sample']
break if(!options[:limit].blank? && results.count >= options[:limit]) break if(!options[:limit].blank? && results.count >= options[:limit])
results << dmsf_file results << dmsf_file
end end
@ -389,14 +392,14 @@ class DmsfFile < ActiveRecord::Base
end end
end end
end end
[results, results.count] [results, results.count]
end end
def self.search_result_ranks_and_ids(tokens, user = User.current, projects = nil, options = {}) def self.search_result_ranks_and_ids(tokens, user = User.current, projects = nil, options = {})
r = self.search(tokens, projects, options, user)[0] r = self.search(tokens, projects, options, user)[0]
r.map{ |f| [f.updated_at.to_i, f.id]} r.map{ |f| [f.updated_at.to_i, f.id]}
end end
def display_name def display_name
if self.name.length > 50 if self.name.length > 50
@ -404,33 +407,33 @@ class DmsfFile < ActiveRecord::Base
end end
self.name self.name
end end
def image? def image?
self.last_revision && !!(self.last_revision.disk_filename =~ /\.(bmp|gif|jpg|jpe|jpeg|png|svg)$/i) self.last_revision && !!(self.last_revision.disk_filename =~ /\.(bmp|gif|jpg|jpe|jpeg|png|svg)$/i)
end end
def preview(limit) def preview(limit)
result = 'No preview available' result = 'No preview available'
if (self.last_revision.disk_filename =~ /\.(txt|ini|diff|c|cpp|php|csv|rb|h|erb|html|css|py)$/i) if (self.last_revision.disk_filename =~ /\.(txt|ini|diff|c|cpp|php|csv|rb|h|erb|html|css|py)$/i)
begin begin
f = File.new(self.last_revision.disk_file) f = File.new(self.last_revision.disk_file)
f.each_line do |line| f.each_line do |line|
case f.lineno case f.lineno
when 1 when 1
result = line result = line
when limit.to_i + 1 when limit.to_i + 1
break break
else else
result << line result << line
end end
end end
rescue Exception => e rescue Exception => e
result = e.message result = e.message
end end
end end
result result
end end
def formatted_name(format) def formatted_name(format)
if self.last_revision if self.last_revision
self.last_revision.formatted_name(format) self.last_revision.formatted_name(format)
@ -438,5 +441,5 @@ class DmsfFile < ActiveRecord::Base
self.name self.name
end end
end end
end end

View File

@ -27,12 +27,12 @@ class DmsfFileRevision < ActiveRecord::Base
belongs_to :folder, :class_name => 'DmsfFolder', :foreign_key => 'dmsf_folder_id' belongs_to :folder, :class_name => 'DmsfFolder', :foreign_key => 'dmsf_folder_id'
belongs_to :deleted_by_user, :class_name => 'User', :foreign_key => 'deleted_by_user_id' belongs_to :deleted_by_user, :class_name => 'User', :foreign_key => 'deleted_by_user_id'
has_many :access, :class_name => 'DmsfFileRevisionAccess', :foreign_key => 'dmsf_file_revision_id', :dependent => :destroy has_many :access, :class_name => 'DmsfFileRevisionAccess', :foreign_key => 'dmsf_file_revision_id', :dependent => :destroy
has_many :dmsf_workflow_step_assignment, :dependent => :destroy has_many :dmsf_workflow_step_assignment, :dependent => :destroy
accepts_nested_attributes_for :access, :dmsf_workflow_step_assignment, :file, :user accepts_nested_attributes_for :access, :dmsf_workflow_step_assignment, :file, :user
STATUS_DELETED = 1 STATUS_DELETED = 1
STATUS_ACTIVE = 0 STATUS_ACTIVE = 0
scope :visible, -> { where(:deleted => STATUS_ACTIVE) } scope :visible, -> { where(:deleted => STATUS_ACTIVE) }
scope :deleted, -> { where(:deleted => STATUS_DELETED) } scope :deleted, -> { where(:deleted => STATUS_DELETED) }
@ -42,7 +42,7 @@ class DmsfFileRevision < ActiveRecord::Base
:datetime => Proc.new {|o| o.updated_at }, :datetime => Proc.new {|o| o.updated_at },
:description => Proc.new {|o| o.comment }, :description => Proc.new {|o| o.comment },
:author => Proc.new {|o| o.user } :author => Proc.new {|o| o.user }
acts_as_activity_provider :type => 'dmsf_file_revisions', acts_as_activity_provider :type => 'dmsf_file_revisions',
:timestamp => "#{DmsfFileRevision.table_name}.updated_at", :timestamp => "#{DmsfFileRevision.table_name}.updated_at",
:author_key => "#{DmsfFileRevision.table_name}.user_id", :author_key => "#{DmsfFileRevision.table_name}.user_id",
@ -51,11 +51,11 @@ class DmsfFileRevision < ActiveRecord::Base
joins( joins(
"INNER JOIN #{DmsfFile.table_name} ON #{DmsfFileRevision.table_name}.dmsf_file_id = #{DmsfFile.table_name}.id " + "INNER JOIN #{DmsfFile.table_name} ON #{DmsfFileRevision.table_name}.dmsf_file_id = #{DmsfFile.table_name}.id " +
"INNER JOIN #{Project.table_name} ON #{DmsfFile.table_name}.project_id = #{Project.table_name}.id"). "INNER JOIN #{Project.table_name} ON #{DmsfFile.table_name}.project_id = #{Project.table_name}.id").
where("#{DmsfFile.table_name}.deleted = ?", STATUS_ACTIVE) where("#{DmsfFile.table_name}.deleted = ?", STATUS_ACTIVE)
validates :title, :presence => true validates :title, :presence => true
validates_format_of :name, :with => DmsfFolder.invalid_characters, validates_format_of :name, :with => DmsfFolder.invalid_characters,
:message => l(:error_contains_invalid_character) :message => l(:error_contains_invalid_character)
def project def project
self.file.project if self.file self.file.project if self.file
@ -136,7 +136,7 @@ class DmsfFileRevision < ActiveRecord::Base
project_base = project.identifier.gsub(/[^\w\.\-]/,'_') project_base = project.identifier.gsub(/[^\w\.\-]/,'_')
storage_base << "/p_#{project_base}" storage_base << "/p_#{project_base}"
end end
Dir.mkdir(storage_base) unless File.exists?(storage_base) FileUtils.mkdir_p(storage_base) unless File.exists?(storage_base)
"#{storage_base}/#{self.disk_filename}" "#{storage_base}/#{self.disk_filename}"
end end
@ -249,7 +249,7 @@ class DmsfFileRevision < ActiveRecord::Base
parts = self.version.split '.' parts = self.version.split '.'
parts.size == 2 ? parts[0].to_i * 1000 + parts[1].to_i : 0 parts.size == 2 ? parts[0].to_i * 1000 + parts[1].to_i : 0
end end
def formatted_name(format) def formatted_name(format)
return self.name if format.blank? return self.name if format.blank?
if self.name =~ /(.*)(\..*)$/ if self.name =~ /(.*)(\..*)$/
@ -257,7 +257,7 @@ class DmsfFileRevision < ActiveRecord::Base
ext = $2 ext = $2
else else
filename = self.name filename = self.name
end end
format.sub!('%t', self.title) format.sub!('%t', self.title)
format.sub!('%f', filename) format.sub!('%f', filename)
format.sub!('%d', self.updated_at.strftime('%Y%m%d%H%M%S')) format.sub!('%d', self.updated_at.strftime('%Y%m%d%H%M%S'))