File Storage Directory does not change #522
This commit is contained in:
parent
68c68cdf79
commit
3a4d3e8b2b
12
Gemfile
12
Gemfile
@ -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
|
||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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'))
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user