class FileManagerSetting include Mongoid::Document include Mongoid::Timestamps field :only_editable_for_uploader, type: Boolean, default: false field :root_path, type: String, default: "" field :modules_saved_info, type: Hash, default: {} field :modules_keys, type: Array, default: [] belongs_to :file_manager_root has_many :file_manager_uploads has_many :file_manager_trashes @@mutex = Mutex.new @@resource = ConditionVariable.new def self.get_models_uploaders if !self.class_variable_defined?(:@@get_models_uploaders) @@get_models_uploaders = false end if @@get_models_uploaders @@mutex.synchronize { @@resource.wait(@@mutex) } end @@get_models_uploaders = true if self.class_variable_defined?(:@@modules_info) @@get_models_uploaders = false return @@modules_info end setting = self.first if setting.nil? setting = self.create end modules_info = {} file_only_models = [] user_id_fields = ['user_id', 'create_user_id', 'update_user_id'] user_id_field_info = {} Rails::Engine.descendants.each do |engine| unless engine.abstract_railtie? || engine.initializers.blank? module_name = engine.initializers[0].name if ModuleApp.where(:key=> module_name).count > 0 models_path = Dir.glob("#{engine.root}/app/models/*") uploaders = {} models_path.each do |path| begin require File.basename(path) m = File.basename(path).sub(/\..+/, '').camelize.constantize if m.uploaders.count > 0 user_id_field = nil user_id_fields.each do |f| if m.fields.include?(f) user_id_field = f break end end if user_id_field.nil? user_id_field = m.fields.select{|f| f.include?('user_id')}.first end user_id_field_info[m] = user_id_field uploaders_info = {} obj = m.new(:id=>nil) m.uploaders.each do |field, uploader_klass| uploaders_info[field] = { uploader_klass => "public/" + obj.send(field).store_dir } end self.set_record_callback(setting, module_name, m, user_id_field) uploaders[m] = uploaders_info m_str = m.to_s if m_str.match(/(File|Image)$/) file_only_models << m_str else belongs_to_fields = m.relations.select{|k,v| v.macro == :belongs_to}.keys if belongs_to_fields.count > 0 && (m.relations.count - belongs_to_fields.count) == 0 fields = m.fields.keys - belongs_to_fields.map{|s| "#{s}_id"} fields = fields - ["_id", "created_at", "updated_at", "description", "title", "title_translations", "rss2_id", "order", "choose_lang", "privacy_type", "should_destroy", "file_title", "download_count", "sort_number"] if (fields - m.uploaders.keys.map(&:to_s)).count == 0 file_only_models << m_str end end end end rescue LoadError end end if uploaders.count > 0 modules_info[module_name] = uploaders end end end end begin require 'asset' module_name = 'asset' m = Asset uploaders = {} if m.uploaders.count > 0 uploaders_info = {} obj = m.new(:id=>nil) m.uploaders.each do |field, uploader_klass| uploaders_info[field] = { uploader_klass => "public/" + obj.send(field).store_dir } end uploaders[m] = uploaders_info user_id_field = nil user_id_fields.each do |f| if m.fields.include?(f) user_id_field = f break end end if user_id_field.nil? user_id_field = m.fields.select{|f| f.include?('user_id')}.first end user_id_field_info[m] = user_id_field self.set_record_callback(setting, module_name, m, user_id_field) user_id_field end modules_info[module_name] = uploaders file_only_models << m.to_s rescue LoadError end @@file_only_models = file_only_models @@user_id_field_info = user_id_field_info @@modules_info = modules_info @@mutex.synchronize { @@get_models_uploaders = false @@resource.signal } modules_info end def self.set_record_callback(setting, module_name, m, user_id_field) uploader_fields = m.uploaders.keys m_str = m.to_s m.before_save do |record| uploader_fields.each{|f| record.instance_variable_set("@#{f}_changed", record.send("#{f}_changed?"))} true end m.after_save do |record| uploader_fields.each do |f| f_changed = "@#{f}_changed" if record.instance_variable_get(f_changed) store_path = "public#{URI.decode(record.send(f).url)}" if user_id_field user_id = record.send(user_id_field) else user_id = nil end basic_info = {:module=> module_name, :model=>m_str, :related_field=> f, :related_id => record.id} other_info = {:path=> store_path, :user_id=> user_id, :is_default=>true, :created_at => record.created_at, :updated_at => record.updated_at} full_info = other_info.merge(basic_info) old_record = setting.file_manager_uploads.where(basic_info).first if old_record.nil? setting.file_manager_uploads.create(full_info) else old_record.update_attributes(other_info) end end record.remove_instance_variable(f_changed) unless record.instance_variable_get(f_changed).nil? end true end m.after_destroy do |record| unless record.instance_variable_get(:@skip_remove_callback) setting.file_manager_uploads.where(:model=>m_str, :related_id => record.id).destroy end true end end def self.file_only_models unless self.class_variable_defined?(:@@file_only_models) self.get_models_uploaders end return @@file_only_models end def self.get_module_info(key) if key == 'all' title = I18n.t("file_manager.all_files") link = nil icon_class = 'icons-disk' sidebar = nil elsif key == 'asset' title = I18n.t('filemanager') link = Rails.application.routes.url_helpers.admin_assets_path icon_class = 'icons-folder' sidebar = nil else module_app = ModuleApp.where(:key=>key).first return if module_app.nil? t = module_app.get_registration return if t.nil? sidebar = t.get_side_bar if sidebar t = sidebar icon_class = t.get_icon_class module_label = t.instance_variable_get(:@head_label) link = t.instance_variable_get(:@head_link) if link link = Rails.application.routes.url_helpers.send(link) end else icon_class = module_app.icon_class_no_sidebar module_label = t.instance_variable_get(:@module_label) plugin_t = OrbitApp::Plugin::Registration.find_by_module_app_name(module_app.title) link = plugin_t.admin_partial_path if plugin_t end title = I18n.t(module_label) end { :title => title, :link => link, :icon_class => icon_class, :sidebar => sidebar } end def create_records modules_info = self.class.get_models_uploaders models_dict = self.modules_saved_info modules_info.each do |module_key, uploaders| uploaders.each do |m, uploaders_info| m_str = m.to_s if models_dict[m_str].nil? models_dict[m_str] = nil end end end self.modules_saved_info = models_dict self.modules_keys = modules_info.keys self.save if self.class.all.count > 1 self.class.where(:id.ne=> self.id).destroy end modules_info.each do |module_key, uploaders| # module_app = ModuleApp.where(:key=> module_key).first # I18n.t("module_name.#{module_key}") uploaders.each do |m, uploaders_info| user_id_field = @@user_id_field_info[m] uploader_fields = uploaders_info.keys records = m.any_of(uploader_fields.map{|f| {f => {"$ne" => nil}}}) m_str = m.to_s if self.modules_saved_info[m_str] records = records.where(:created_at.gte=> (self.modules_saved_info[m_str] - 1)) end records = records.order_by(:created_at=> :asc).to_a records_last_idx = records.length - 1 records.each_with_index do |r, i| uploader_fields.each do |f| f_value = r.send(f) if f_value.present? store_path = "public#{URI.decode(f_value.url)}" unless File.exist?(store_path) next end if user_id_field user_id = r.send(user_id_field) else user_id = nil end basic_info = {:module=> module_key, :model=> m.to_s, :related_field=> f, :related_id => r.id, :is_default=> true} other_info = {:path=> store_path, :user_id=> user_id, :created_at => r.created_at, :updated_at => r.updated_at} full_info = other_info.merge(basic_info) old_record = self.file_manager_uploads.where(basic_info).first if old_record.nil? self.file_manager_uploads.create(full_info) else old_record.update_attributes(other_info) end end end if i % 10 || i == records_last_idx puts "#{m} updated at #{r.created_at}" self.class.where(:id=>self.id).update_all("modules_saved_info.#{m}" => r.created_at.to_i) end end end end end def get_modules_keys _modules_keys = self.modules_keys.sort _modules_keys = ["all"] + ["asset"] + (_modules_keys - ["asset"]) end end