Commit 76e29aed97e98044fede7f4a280abc96b80d58a6

Authored by Braulio Bhavamitra
1 parent f678092a

concerns: move most lib files models concerns

Showing 55 changed files with 841 additions and 831 deletions   Show diff stats
app/mailers/mailing.rb
... ... @@ -2,7 +2,8 @@ require_dependency 'mailing_job'
2 2  
3 3 class Mailing < ApplicationRecord
4 4  
5   - acts_as_having_settings :field => :data
  5 + extend ActsAsHavingSettings::ClassMethods
  6 + acts_as_having_settings field: :data
6 7  
7 8 attr_accessible :subject, :body, :data
8 9  
... ...
app/models/article.rb
... ... @@ -13,7 +13,9 @@ class Article &lt; ApplicationRecord
13 13 :image_builder, :show_to_followers, :archived,
14 14 :author, :display_preview, :published_at, :person_followers
15 15  
  16 + extend ActsAsHavingImage::ClassMethods
16 17 acts_as_having_image
  18 +
17 19 include Noosfero::Plugin::HotSpot
18 20  
19 21 SEARCHABLE_FIELDS = {
... ... @@ -91,7 +93,8 @@ class Article &lt; ApplicationRecord
91 93 has_many :article_categorizations_including_virtual, :class_name => 'ArticleCategorization'
92 94 has_many :categories_including_virtual, :through => :article_categorizations_including_virtual, :source => :category
93 95  
94   - acts_as_having_settings :field => :setting
  96 + extend ActsAsHavingSettings::ClassMethods
  97 + acts_as_having_settings field: :setting
95 98  
96 99 settings_items :display_hits, :type => :boolean, :default => true
97 100 settings_items :author_name, :type => :string, :default => ""
... ... @@ -242,6 +245,7 @@ class Article &lt; ApplicationRecord
242 245 acts_as_taggable
243 246 N_('Tag list')
244 247  
  248 + extend ActsAsFilesystem::ActsMethods
245 249 acts_as_filesystem
246 250  
247 251 acts_as_versioned
... ...
app/models/block.rb
... ... @@ -17,6 +17,7 @@ class Block &lt; ApplicationRecord
17 17 belongs_to :mirror_block, :class_name => "Block"
18 18 has_many :observers, :class_name => "Block", :foreign_key => "mirror_block_id"
19 19  
  20 + extend ActsAsHavingSettings::ClassMethods
20 21 acts_as_having_settings
21 22  
22 23 scope :enabled, -> { where :enabled => true }
... ...
app/models/blog.rb
... ... @@ -2,7 +2,9 @@ class Blog &lt; Folder
2 2  
3 3 attr_accessible :visualization_format
4 4  
  5 + extend ActsAsHavingPosts::ClassMethods
5 6 acts_as_having_posts
  7 +
6 8 include PostsLimit
7 9  
8 10 #FIXME This should be used until there is a migration to fix all blogs that
... ...
app/models/category.rb
... ... @@ -21,6 +21,7 @@ class Category &lt; ApplicationRecord
21 21  
22 22 scope :on_level, -> parent { where :parent_id => parent }
23 23  
  24 + extend ActsAsFilesystem::ActsMethods
24 25 acts_as_filesystem
25 26  
26 27 has_many :article_categorizations
... ... @@ -35,6 +36,7 @@ class Category &lt; ApplicationRecord
35 36 has_many :people, :through => :profile_categorizations, :source => :profile, :class_name => 'Person'
36 37 has_many :communities, :through => :profile_categorizations, :source => :profile, :class_name => 'Community'
37 38  
  39 + extend ActsAsHavingImage::ClassMethods
38 40 acts_as_having_image
39 41  
40 42 before_save :normalize_display_color
... ...
app/models/comment.rb
... ... @@ -38,6 +38,7 @@ class Comment &lt; ApplicationRecord
38 38  
39 39 validate :article_archived?
40 40  
  41 + extend ActsAsHavingSettings::ClassMethods
41 42 acts_as_having_settings
42 43  
43 44 xss_terminate :only => [ :body, :title, :name ], :on => 'validation'
... ...
app/models/concerns/acts_as_filesystem.rb 0 → 100644
... ... @@ -0,0 +1,265 @@
  1 +module ActsAsFilesystem
  2 +
  3 + module ActsMethods
  4 +
  5 + # Declares the ActiveRecord model to acts like a filesystem: objects are
  6 + # arranged in a tree (liks acts_as_tree), and . The underlying table must
  7 + # have the following fields:
  8 + #
  9 + # * name (+:string+) - the title of the object
  10 + # * slug (+:string+)- the title turned in a URL-friendly string (downcased,
  11 + # non-ascii chars transliterated into ascii, all sequences of
  12 + # non-alphanumericd characters changed into dashed)
  13 + # * path (+:text+)- stores the full path of the object (the full path of
  14 + # the parent, a "/" and the slug of the object)
  15 + # * children_count - a cache of the number of children elements.
  16 + def acts_as_filesystem
  17 + # a filesystem is a tree
  18 + acts_as_tree :counter_cache => :children_count
  19 +
  20 + extend ClassMethods
  21 + include InstanceMethods
  22 + if self.has_path?
  23 + after_update :update_children_path
  24 + before_create :set_path
  25 + include InstanceMethods::PathMethods
  26 + end
  27 +
  28 + before_save :set_ancestry
  29 + end
  30 +
  31 + end
  32 +
  33 + module ClassMethods
  34 +
  35 + def build_ancestry(parent_id = nil, ancestry = '')
  36 + ActiveRecord::Base.transaction do
  37 + self.base_class.where(parent_id: parent_id).each do |node|
  38 + node.update_column :ancestry, ancestry
  39 +
  40 + build_ancestry node.id, (ancestry.empty? ? "#{node.formatted_ancestry_id}" :
  41 + "#{ancestry}#{node.ancestry_sep}#{node.formatted_ancestry_id}")
  42 + end
  43 + end
  44 +
  45 + #raise "Couldn't reach and set ancestry on every record" if self.base_class.where('ancestry is null').count != 0
  46 + end
  47 +
  48 + def has_path?
  49 + (['name', 'slug', 'path'] - self.column_names).blank?
  50 + end
  51 +
  52 + end
  53 +
  54 + module InstanceMethods
  55 +
  56 + def ancestry_column
  57 + 'ancestry'
  58 + end
  59 + def ancestry_sep
  60 + '.'
  61 + end
  62 + def has_ancestry?
  63 + self.class.column_names.include? self.ancestry_column
  64 + end
  65 +
  66 + def formatted_ancestry_id
  67 + "%010d" % self.id if self.id
  68 + end
  69 +
  70 + def ancestry
  71 + self[ancestry_column]
  72 + end
  73 + def ancestor_ids
  74 + return nil if !has_ancestry? or ancestry.nil?
  75 + @ancestor_ids ||= ancestry.split(ancestry_sep).map{ |id| id.to_i }
  76 + end
  77 +
  78 + def ancestry=(value)
  79 + self[ancestry_column] = value
  80 + end
  81 + def set_ancestry
  82 + return unless self.has_ancestry?
  83 + if self.ancestry.nil? or (new_record? or parent_id_changed?) or recalculate_path
  84 + self.ancestry = self.hierarchy(true)[0...-1].map{ |p| p.formatted_ancestry_id }.join(ancestry_sep)
  85 + end
  86 + end
  87 +
  88 + def descendents_options
  89 + ["#{self.ancestry_column} LIKE ?", "%#{self.formatted_ancestry_id}%"]
  90 + end
  91 + def descendents
  92 + self.class.where descendents_options
  93 + end
  94 +
  95 + # calculates the level of the record in the records hierarchy. Top-level
  96 + # records have level 0; the children of the top-level records have
  97 + # level 1; the children of records with level 1 have level 2, and so on.
  98 + #
  99 + # A level 0
  100 + # / \
  101 + # B C level 1
  102 + # / \ / \
  103 + # E F G H level 2
  104 + # ...
  105 + def level
  106 + self.hierarchy.size - 1
  107 + end
  108 +
  109 + # Is this record a top-level record?
  110 + def top_level?
  111 + self.parent.nil?
  112 + end
  113 +
  114 + # Is this record a leaf in the hierarchy tree of records?
  115 + #
  116 + # Being a leaf means that this record has no subrecord.
  117 + def leaf?
  118 + self.children.empty?
  119 + end
  120 +
  121 + def top_ancestor
  122 + if has_ancestry? and !ancestry.blank?
  123 + self.class.base_class.find_by id: self.top_ancestor_id
  124 + else
  125 + self.hierarchy.first
  126 + end
  127 + end
  128 + def top_ancestor_id
  129 + if has_ancestry? and !ancestry.nil?
  130 + self.ancestor_ids.first
  131 + else
  132 + self.hierarchy.first.id
  133 + end
  134 + end
  135 +
  136 + # returns the full hierarchy from the top-level item to this one. For
  137 + # example, if item1 has a children item2 and item2 has a children item3,
  138 + # then item3's hierarchy would be [item1, item2, item3].
  139 + #
  140 + # If +reload+ is passed as +true+, then the hierarchy is reload (usefull
  141 + # when the ActiveRecord object was modified in some way, or just after
  142 + # changing parent)
  143 + def hierarchy(reload = false)
  144 + @hierarchy = nil if reload or recalculate_path
  145 +
  146 + if @hierarchy.nil?
  147 + @hierarchy = []
  148 +
  149 + if !reload and !recalculate_path and ancestor_ids
  150 + objects = self.class.base_class.where(id: ancestor_ids)
  151 + ancestor_ids.each{ |id| @hierarchy << objects.find{ |t| t.id == id } }
  152 + @hierarchy << self
  153 + else
  154 + item = self
  155 + while item
  156 + @hierarchy.unshift(item)
  157 + item = item.parent
  158 + end
  159 + end
  160 + end
  161 +
  162 + @hierarchy
  163 + end
  164 +
  165 + def map_traversal(&block)
  166 + result = []
  167 + current_level = [self]
  168 +
  169 + while !current_level.empty?
  170 + result += current_level
  171 + ids = current_level.select {|item| item.children_count > 0}.map(&:id)
  172 + break if ids.empty?
  173 + current_level = self.class.base_class.where(parent_id: ids)
  174 + end
  175 + block ||= (lambda { |x| x })
  176 + result.map(&block)
  177 + end
  178 +
  179 + def all_children
  180 + res = map_traversal
  181 + res.shift
  182 + res
  183 + end
  184 +
  185 + #####
  186 + # Path methods
  187 + # These methods are used when _path_, _name_ and _slug_ attributes exist
  188 + # and should be calculated based on the tree
  189 + #####
  190 + module PathMethods
  191 + # used to know when to trigger batch renaming
  192 + attr_accessor :recalculate_path
  193 +
  194 + # calculates the full path to this record using parent's path.
  195 + def calculate_path
  196 + self.hierarchy.map{ |obj| obj.slug }.join('/')
  197 + end
  198 + def set_path
  199 + if self.path == self.slug && !self.top_level?
  200 + self.path = self.calculate_path
  201 + end
  202 + end
  203 + def explode_path
  204 + path.split(/\//)
  205 + end
  206 +
  207 + def update_children_path
  208 + if self.recalculate_path
  209 + self.children.each do |child|
  210 + child.path = child.calculate_path
  211 + child.recalculate_path = true
  212 + child.save!
  213 + end
  214 + end
  215 + self.recalculate_path = false
  216 + end
  217 +
  218 + # calculates the full name of a record by accessing the name of all its
  219 + # ancestors.
  220 + #
  221 + # If you have this record hierarchy:
  222 + # Record "A"
  223 + # Record "B"
  224 + # Record "C"
  225 + #
  226 + # Then Record "C" will have "A/B/C" as its full name.
  227 + def full_name(sep = '/')
  228 + self.hierarchy.map {|item| item.name || '?' }.join(sep)
  229 + end
  230 +
  231 + # gets the name without leading parents. Useful when dividing records
  232 + # in top-level groups and full names must not include the top-level
  233 + # record which is already a emphasized label
  234 + def full_name_without_leading(count, sep = '/')
  235 + parts = self.full_name(sep).split(sep)
  236 + count.times { parts.shift }
  237 + parts.join(sep)
  238 + end
  239 +
  240 + def set_name(value)
  241 + if self.name != value
  242 + self.recalculate_path = true
  243 + end
  244 + self[:name] = value
  245 + end
  246 +
  247 + # sets the name of the record. Also sets #slug accordingly.
  248 + def name=(value)
  249 + self.set_name(value)
  250 + unless self.name.blank?
  251 + self.slug = self.name.to_slug
  252 + end
  253 + end
  254 +
  255 + # sets the slug of the record. Also sets the path with the new slug value.
  256 + def slug=(value)
  257 + self[:slug] = value
  258 + unless self.slug.blank?
  259 + self.path = self.calculate_path
  260 + end
  261 + end
  262 + end
  263 + end
  264 +end
  265 +
... ...
app/models/concerns/acts_as_having_boxes.rb 0 → 100644
... ... @@ -0,0 +1,37 @@
  1 +module ActsAsHavingBoxes
  2 +
  3 + module ClassMethods
  4 + def acts_as_having_boxes
  5 + has_many :boxes, -> { order :position }, as: :owner, dependent: :destroy
  6 + self.send(:include, ActsAsHavingBoxes)
  7 + end
  8 + end
  9 +
  10 + module BlockArray
  11 + def find(id)
  12 + select { |item| item.id == id.to_i }.first
  13 + end
  14 + end
  15 +
  16 + def blocks(reload = false)
  17 + if (reload)
  18 + @blocks = nil
  19 + end
  20 + if @blocks.nil?
  21 + @blocks = boxes.includes(:blocks).inject([]) do |acc,obj|
  22 + acc.concat(obj.blocks)
  23 + end
  24 + @blocks.send(:extend, BlockArray)
  25 + end
  26 + @blocks
  27 + end
  28 +
  29 + # returns 3 unless the class table has a boxes_limit column. In that case
  30 + # return the value of the column.
  31 + def boxes_limit layout_template = nil
  32 + layout_template ||= self.layout_template
  33 + @boxes_limit ||= LayoutTemplate.find(layout_template).number_of_boxes || 3
  34 + end
  35 +
  36 +end
  37 +
... ...
app/models/concerns/acts_as_having_image.rb 0 → 100644
... ... @@ -0,0 +1,25 @@
  1 +module ActsAsHavingImage
  2 +
  3 + module ClassMethods
  4 + def acts_as_having_image
  5 + belongs_to :image, dependent: :destroy
  6 + scope :with_image, -> { where "#{table_name}.image_id IS NOT NULL" }
  7 + scope :without_image, -> { where "#{table_name}.image_id IS NULL" }
  8 + attr_accessible :image_builder
  9 + include ActsAsHavingImage
  10 + end
  11 + end
  12 +
  13 + def image_builder=(img)
  14 + if image && image.id == img[:id]
  15 + image.attributes = img
  16 + else
  17 + build_image(img)
  18 + end unless img[:uploaded_data].blank?
  19 + if img[:remove_image] == 'true'
  20 + self.image_id = nil
  21 + end
  22 + end
  23 +
  24 +end
  25 +
... ...
app/models/concerns/acts_as_having_posts.rb 0 → 100644
... ... @@ -0,0 +1,49 @@
  1 +module ActsAsHavingPosts
  2 +
  3 + module ClassMethods
  4 + def acts_as_having_posts(scope = nil)
  5 + has_many :posts, -> {
  6 + s = order('published_at DESC, id DESC').where('articles.type != ?', 'RssFeed')
  7 + s = s.instance_exec(&scope) if scope
  8 + s
  9 + }, class_name: 'Article', foreign_key: 'parent_id', source: :children
  10 +
  11 + attr_accessor :feed_attrs
  12 +
  13 + after_create do |blog|
  14 + blog.children << RssFeed.new(:name => 'feed', :profile => blog.profile)
  15 + blog.feed = blog.feed_attrs
  16 + end
  17 +
  18 + settings_items :posts_per_page, :type => :integer, :default => 5
  19 +
  20 + self.send(:include, ActsAsHavingPosts)
  21 + end
  22 + end
  23 +
  24 + def has_posts?
  25 + true
  26 + end
  27 +
  28 + def feed
  29 + children.where(:type => 'RssFeed').first
  30 + end
  31 +
  32 + def feed=(attrs)
  33 + if attrs
  34 + if self.feed
  35 + self.feed.update(attrs)
  36 + else
  37 + self.feed_attrs = attrs
  38 + end
  39 + end
  40 + self.feed
  41 + end
  42 +
  43 + def name=(value)
  44 + self.set_name(value)
  45 + self.slug = self.slug.blank? ? self.name.to_slug : self.slug.to_slug
  46 + end
  47 +
  48 +end
  49 +
... ...
app/models/concerns/acts_as_having_settings.rb 0 → 100644
... ... @@ -0,0 +1,89 @@
  1 +# declare missing types
  2 +module ActiveRecord
  3 + module Type
  4 + class Symbol < Value
  5 + def cast_value value
  6 + value.to_sym
  7 + end
  8 + end
  9 + class Array < Value
  10 + def cast_value value
  11 + ::Array.wrap(value)
  12 + end
  13 + end
  14 + class Hash < Value
  15 + def cast_value value
  16 + h = ::Hash[value]
  17 + h.symbolize_keys!
  18 + h
  19 + end
  20 + end
  21 + end
  22 +end
  23 +
  24 +module ActsAsHavingSettings
  25 +
  26 + def self.type_cast value, type
  27 + # do not cast nil
  28 + return value if value.nil?
  29 + type.send :cast_value, value
  30 + end
  31 +
  32 + module ClassMethods
  33 +
  34 + def acts_as_having_settings(*args)
  35 + options = args.last.is_a?(Hash) ? args.pop : {}
  36 + field = (options[:field] || :settings).to_sym
  37 +
  38 + serialize field, Hash
  39 + class_attribute :settings_field
  40 + self.settings_field = field
  41 +
  42 + class_eval do
  43 + def settings_field
  44 + self[self.class.settings_field] ||= Hash.new
  45 + end
  46 +
  47 + def setting_changed? setting_field
  48 + setting_field = setting_field.to_sym
  49 + changed_settings = self.changes[self.class.settings_field]
  50 + return false if changed_settings.nil?
  51 +
  52 + old_setting_value = changed_settings.first.nil? ? nil : changed_settings.first[setting_field]
  53 + new_setting_value = changed_settings.last[setting_field]
  54 + old_setting_value != new_setting_value
  55 + end
  56 + end
  57 +
  58 + settings_items *args
  59 + end
  60 +
  61 + def settings_items *names
  62 +
  63 + options = names.extract_options!
  64 + default = options[:default]
  65 + type = options[:type]
  66 + type = if type.present? then ActiveRecord::Type.const_get(type.to_s.camelize.to_sym).new else nil end
  67 +
  68 + names.each do |setting|
  69 + # symbolize key
  70 + setting = setting.to_sym
  71 +
  72 + define_method setting do
  73 + h = send self.class.settings_field
  74 + val = h[setting]
  75 + # translate default value if it is used
  76 + if not val.nil? then val elsif default.is_a? String then gettext default else default end
  77 + end
  78 +
  79 + define_method "#{setting}=" do |value|
  80 + h = send self.class.settings_field
  81 + h[setting] = if type then ActsAsHavingSettings.type_cast value, type else value end
  82 + end
  83 + end
  84 + end
  85 +
  86 + end
  87 +
  88 +end
  89 +
... ...
app/models/concerns/code_numbering.rb 0 → 100644
... ... @@ -0,0 +1,57 @@
  1 +module CodeNumbering
  2 + module ClassMethods
  3 + def code_numbering field, options = {}
  4 + class_attribute :code_numbering_field
  5 + class_attribute :code_numbering_options
  6 +
  7 + self.code_numbering_field = field
  8 + self.code_numbering_options = options
  9 +
  10 + before_create :create_code_numbering
  11 +
  12 + include CodeNumbering::InstanceMethods
  13 + end
  14 + end
  15 +
  16 + module InstanceMethods
  17 +
  18 + def code
  19 + self.attributes[self.code_numbering_field.to_s]
  20 + end
  21 +
  22 + def code_scope
  23 + scope = self.code_numbering_options[:scope]
  24 + case scope
  25 + when Symbol
  26 + self.send scope
  27 + when Proc
  28 + instance_exec &scope
  29 + else
  30 + self.class
  31 + end
  32 + end
  33 +
  34 + def code_maximum
  35 + self.code_scope.maximum(self.code_numbering_field) || 0
  36 + end
  37 +
  38 + def create_code_numbering
  39 + max = self.code_numbering_options[:start].to_i - 1 if self.code_numbering_options[:start]
  40 + max = self.code_maximum
  41 + self.send "#{self.code_numbering_field}=", max+1
  42 + end
  43 +
  44 + def reset_scope_code_numbering
  45 + max = self.code_numbering_options[:start].to_i - 1 if self.code_numbering_options[:start]
  46 + max ||= 1
  47 +
  48 + self.code_scope.order(:created_at).each do |record|
  49 + record.update_column self.code_numbering_field, max
  50 + max += 1
  51 + end
  52 + self.reload
  53 + end
  54 +
  55 + end
  56 +end
  57 +
... ...
app/models/concerns/customizable.rb 0 → 100644
... ... @@ -0,0 +1,124 @@
  1 +module Customizable
  2 +
  3 + def self.included(base)
  4 + base.attr_accessible :custom_values
  5 + base.extend ClassMethods
  6 + end
  7 +
  8 + module ClassMethods
  9 + def acts_as_customizable(options = {})
  10 + attr_accessor :custom_values
  11 + has_many :custom_field_values, :dependent => :delete_all, :as => :customized
  12 + send :include, Customizable::InstanceMethods
  13 + after_save :save_custom_values
  14 + validate :valid_custom_values?
  15 + end
  16 +
  17 + def active_custom_fields environment
  18 + environment.custom_fields.select{|cf| customized_ancestors_list.include?(cf.customized_type) && cf.active}
  19 + end
  20 +
  21 + def required_custom_fields environment
  22 + environment.custom_fields.select{|cf| customized_ancestors_list.include?(cf.customized_type) && cf.required}
  23 + end
  24 +
  25 + def signup_custom_fields environment
  26 + environment.custom_fields.select{|cf| customized_ancestors_list.include?(cf.customized_type) && cf.signup}
  27 + end
  28 +
  29 + def custom_fields environment
  30 + environment.custom_fields.select{|cf| customized_ancestors_list.include?(cf.customized_type)}
  31 + end
  32 +
  33 + def customized_ancestors_list
  34 + current=self
  35 + result=[]
  36 + while current.instance_methods.include? :custom_value do
  37 + result << current.name
  38 + current=current.superclass
  39 + end
  40 + result
  41 + end
  42 +
  43 + end
  44 +
  45 + module InstanceMethods
  46 +
  47 + def valid_custom_values?
  48 + is_valid = true
  49 + parse_custom_values.each do |cv|
  50 + unless cv.valid?
  51 + name = cv.custom_field.name
  52 + errors.add(name, cv.errors.messages[name.to_sym].first)
  53 + is_valid = false
  54 + end
  55 + end
  56 + is_valid
  57 + end
  58 +
  59 + def customized_class
  60 + current=self.class
  61 + while current.instance_methods.include? :custom_fields do
  62 + result=current
  63 + current=current.superclass
  64 + end
  65 + result.name
  66 + end
  67 +
  68 + def is_public(field_name)
  69 + cv = self.custom_field_values.detect{|cv| cv.custom_field.name==field_name}
  70 + cv.nil? ? false : cv.public
  71 + end
  72 +
  73 + def public_values
  74 + self.custom_field_values.select{|cv| cv.public}
  75 + end
  76 +
  77 + def custom_value(field_name)
  78 + cv = self.custom_field_values.detect{|cv| cv.custom_field.name==field_name}
  79 + cv.nil? ? default_value_for(field_name) : cv.value
  80 + end
  81 +
  82 + def default_value_for(field_name)
  83 + field=self.class.custom_fields(environment).detect {|c| c.name == field_name}
  84 + field.nil? ? nil : field.default_value
  85 + end
  86 +
  87 + def parse_custom_values
  88 + return_list = []
  89 + return return_list if custom_values.blank?
  90 + custom_values.each_pair do |key, value|
  91 + custom_field = environment.custom_fields.detect{|cf|cf.name==key}
  92 + next if custom_field.blank?
  93 + custom_field_value = self.custom_field_values(true).detect{|cv| cv.custom_field.name==key}
  94 +
  95 + if custom_field_value.nil?
  96 + custom_field_value = CustomFieldValue.new
  97 + custom_field_value.custom_field = custom_field
  98 + custom_field_value.customized = self
  99 + end
  100 +
  101 + if value.is_a?(Hash)
  102 + custom_field_value.value = value['value'].to_s
  103 + if value.has_key?('public')
  104 + is_public = value['public']=="true" || value['public']==true
  105 + custom_field_value.public = is_public
  106 + else
  107 + custom_field_value.public = false
  108 + end
  109 + else
  110 + custom_field_value.value = value.to_s
  111 + custom_field_value.public = false
  112 + end
  113 + return_list << custom_field_value
  114 + end
  115 + return_list
  116 + end
  117 +
  118 + def save_custom_values
  119 + parse_custom_values.each(&:save)
  120 + end
  121 +
  122 + end
  123 +end
  124 +
... ...
app/models/concerns/delayed_attachment_fu.rb 0 → 100644
... ... @@ -0,0 +1,55 @@
  1 +module DelayedAttachmentFu
  2 +
  3 + module ClassMethods
  4 + def delay_attachment_fu_thumbnails
  5 + include DelayedAttachmentFu::InstanceMethods
  6 + after_create do |file|
  7 + if file.thumbnailable?
  8 + Delayed::Job.enqueue CreateThumbnailsJob.new(file.class.name, file.id)
  9 + end
  10 + end
  11 + end
  12 + end
  13 +
  14 + module InstanceMethods
  15 + # skip processing with RMagick
  16 + def process_attachment
  17 + end
  18 +
  19 + def after_process_attachment
  20 + save_to_storage
  21 + @temp_paths.clear
  22 + @saved_attachment = nil
  23 + run_callbacks :after_attachment_saved
  24 + end
  25 +
  26 + def create_thumbnails
  27 + if thumbnailable?
  28 + self.class.with_image(full_filename) do |img|
  29 + self.width = img.columns
  30 + self.height = img.rows
  31 + self.save!
  32 + end
  33 + self.class.attachment_options[:thumbnails].each do |suffix, size|
  34 + self.create_or_update_thumbnail(self.full_filename, suffix, size)
  35 + end
  36 + self.thumbnails_processed = true
  37 + self.save!
  38 + end
  39 + end
  40 +
  41 + def public_filename(size=nil)
  42 + force, size = true, nil if size == :uploaded
  43 + if !self.thumbnailable? || self.thumbnails_processed || force
  44 + super size
  45 + else
  46 + size ||= :thumb
  47 + '/images/icons-app/image-loading-%s.png' % size
  48 + end
  49 + end
  50 +
  51 +
  52 + end
  53 +end
  54 +
  55 +
... ...
app/models/concerns/set_profile_region_from_city_state.rb 0 → 100644
... ... @@ -0,0 +1,44 @@
  1 +module SetProfileRegionFromCityState
  2 +
  3 + module ClassMethods
  4 + def set_profile_region_from_city_state
  5 + before_save :region_from_city_and_state
  6 +
  7 + include InstanceMethods
  8 + alias_method_chain :city=, :region
  9 + alias_method_chain :state=, :region
  10 + end
  11 + end
  12 +
  13 + module InstanceMethods
  14 + include Noosfero::Plugin::HotSpot
  15 +
  16 + def city_with_region=(value)
  17 + self.city_without_region = value
  18 + @change_region = true
  19 + end
  20 +
  21 + def state_with_region=(value)
  22 + self.state_without_region = value
  23 + @change_region = true
  24 + end
  25 +
  26 + def region_from_city_and_state
  27 + if @change_region
  28 + self.region = nil
  29 + state = search_region(State, self.state)
  30 + self.region = search_region(City.where(:parent_id => state.id), self.city) if state
  31 + end
  32 + end
  33 +
  34 + private
  35 +
  36 + def search_region(scope, query)
  37 + return nil if !query
  38 + query = query.downcase.strip
  39 + scope.where(['lower(name)=? OR lower(abbreviation)=? OR lower(acronym)=?', query, query, query]).first
  40 + end
  41 +
  42 + end
  43 +
  44 +end
... ...
app/models/concerns/translatable_content.rb 0 → 100644
... ... @@ -0,0 +1,8 @@
  1 +module TranslatableContent
  2 +
  3 + def translatable?
  4 + return false if self.profile && !self.profile.environment.languages.present?
  5 + parent.nil? || !parent.forum?
  6 + end
  7 +
  8 +end
... ...
app/models/concerns/white_list_filter.rb 0 → 100644
... ... @@ -0,0 +1,37 @@
  1 +module WhiteListFilter
  2 +
  3 + def check_iframe_on_content(content, trusted_sites)
  4 + if content.blank? || !content.include?('iframe')
  5 + return content
  6 + end
  7 + content.gsub!(/<iframe[^>]*>\s*<\/iframe>/i) do |iframe|
  8 + result = ''
  9 + unless iframe =~ /src=['"].*src=['"]/
  10 + trusted_sites.each do |trusted_site|
  11 + re_dom = trusted_site.gsub('.', '\.')
  12 + if iframe =~ /src=["'](https?:)?\/\/(www\.)?#{re_dom}\//
  13 + result = iframe
  14 + end
  15 + end
  16 + end
  17 + result
  18 + end
  19 + content
  20 + end
  21 +
  22 + module ClassMethods
  23 + def filter_iframes(*opts)
  24 + options = opts.last.is_a?(Hash) && opts.pop || {}
  25 + white_list_method = options[:whitelist] || :iframe_whitelist
  26 + opts.each do |field|
  27 + before_validation do |obj|
  28 + obj.check_iframe_on_content(obj.send(field), obj.send(white_list_method))
  29 + end
  30 + end
  31 + end
  32 + end
  33 +
  34 + def self.included(c)
  35 + c.send(:extend, WhiteListFilter::ClassMethods)
  36 + end
  37 +end
... ...
app/models/create_community.rb
... ... @@ -12,6 +12,7 @@ class CreateCommunity &lt; Task
12 12 attr_accessible :environment, :requestor, :target
13 13 attr_accessible :reject_explanation, :template_id
14 14  
  15 + extend ActsAsHavingImage::ClassMethods
15 16 acts_as_having_image
16 17  
17 18 DATA_FIELDS = Community.fields + ['name', 'closed', 'description']
... ...
app/models/environment.rb
... ... @@ -200,6 +200,7 @@ class Environment &lt; ApplicationRecord
200 200 # Relationships and applied behaviour
201 201 # #################################################
202 202  
  203 + extend ActsAsHavingBoxes::ClassMethods
203 204 acts_as_having_boxes
204 205  
205 206 after_create do |env|
... ... @@ -251,7 +252,8 @@ class Environment &lt; ApplicationRecord
251 252 # #################################################
252 253  
253 254 # store the Environment settings as YAML-serialized Hash.
254   - acts_as_having_settings :field => :settings
  255 + extend ActsAsHavingSettings::ClassMethods
  256 + acts_as_having_settings field: :settings
255 257  
256 258 # introduce and explain to users something about the signup
257 259 settings_items :signup_intro, :type => String
... ...
app/models/event.rb
1   -require 'noosfero/translatable_content'
2 1 require 'builder'
3 2  
4 3 class Event < Article
... ... @@ -138,7 +137,7 @@ class Event &lt; Article
138 137 false
139 138 end
140 139  
141   - include Noosfero::TranslatableContent
  140 + include TranslatableContent
142 141 include MaybeAddHttp
143 142  
144 143 end
... ...
app/models/folder.rb
... ... @@ -10,7 +10,8 @@ class Folder &lt; Article
10 10 errors.add(:parent, "A folder should not belong to a blog.") if parent && parent.blog?
11 11 end
12 12  
13   - acts_as_having_settings :field => :setting
  13 + extend ActsAsHavingSettings::ClassMethods
  14 + acts_as_having_settings field: :setting
14 15  
15 16 xss_terminate :only => [ :name, :body ], :with => 'white_list', :on => 'validation'
16 17  
... ...
app/models/forum.rb
1 1 class Forum < Folder
2 2  
  3 + extend ActsAsHavingPosts::ClassMethods
3 4 acts_as_having_posts -> { reorder 'updated_at DESC' }
  5 +
4 6 include PostsLimit
5 7  
6 8 attr_accessible :has_terms_of_use, :terms_of_use, :topic_creation
... ...
app/models/image.rb
... ... @@ -23,6 +23,7 @@ class Image &lt; ApplicationRecord
23 23  
24 24 validates_attachment :size => N_("{fn} of uploaded file was larger than the maximum size of 5.0 MB").fix_i18n
25 25  
  26 + extend DelayedAttachmentFu::ClassMethods
26 27 delay_attachment_fu_thumbnails
27 28  
28 29 postgresql_attachment_fu
... ...
app/models/profile.rb
... ... @@ -88,6 +88,8 @@ class Profile &lt; ApplicationRecord
88 88 }
89 89  
90 90 acts_as_accessible
  91 +
  92 + include Customizable
91 93 acts_as_customizable
92 94  
93 95 include Noosfero::Plugin::HotSpot
... ... @@ -185,6 +187,7 @@ class Profile &lt; ApplicationRecord
185 187 Person.members_of(self).by_role(roles)
186 188 end
187 189  
  190 + extend ActsAsHavingBoxes::ClassMethods
188 191 acts_as_having_boxes
189 192  
190 193 acts_as_taggable
... ... @@ -231,7 +234,8 @@ class Profile &lt; ApplicationRecord
231 234 scrap.nil? ? Scrap.all_scraps(self) : Scrap.all_scraps(self).find(scrap)
232 235 end
233 236  
234   - acts_as_having_settings :field => :data
  237 + extend ActsAsHavingSettings::ClassMethods
  238 + acts_as_having_settings field: :data
235 239  
236 240 def settings
237 241 data
... ... @@ -285,6 +289,7 @@ class Profile &lt; ApplicationRecord
285 289  
286 290 has_many :files, :class_name => 'UploadedFile'
287 291  
  292 + extend ActsAsHavingImage::ClassMethods
288 293 acts_as_having_image
289 294  
290 295 has_many :tasks, :dependent => :destroy, :as => 'target'
... ...
app/models/profile_suggestion.rb
... ... @@ -17,7 +17,8 @@ class ProfileSuggestion &lt; ApplicationRecord
17 17 self.class.generate_profile_suggestions(profile_suggestion.person)
18 18 end
19 19  
20   - acts_as_having_settings :field => :categories
  20 + extend ActsAsHavingSettings::ClassMethods
  21 + acts_as_having_settings field: :categories
21 22  
22 23 validate :must_be_a_valid_category, :on => :create
23 24 def must_be_a_valid_category
... ...
app/models/task.rb
... ... @@ -11,7 +11,8 @@
11 11 # will need to declare <ttserialize</tt> itself).
12 12 class Task < ApplicationRecord
13 13  
14   - acts_as_having_settings :field => :data
  14 + extend ActsAsHavingSettings::ClassMethods
  15 + acts_as_having_settings field: :data
15 16  
16 17 module Status
17 18 # the status of tasks just created
... ...
app/models/text_article.rb
1   -require 'noosfero/translatable_content'
2   -
3 1 # a base class for all text article types.
4 2 class TextArticle < Article
5 3  
... ... @@ -9,7 +7,7 @@ class TextArticle &lt; Article
9 7 _('Article')
10 8 end
11 9  
12   - include Noosfero::TranslatableContent
  10 + include TranslatableContent
13 11  
14 12 def self.icon_name(article = nil)
15 13 if article && !article.parent.nil? && article.parent.kind_of?(Blog)
... ...
app/models/tiny_mce_article.rb
1   -require 'white_list_filter'
2   -
3 1 class TinyMceArticle < TextArticle
4 2  
5 3 def self.short_description
... ...
app/models/uploaded_file.rb
... ... @@ -84,6 +84,7 @@ class UploadedFile &lt; Article
84 84  
85 85 validates_attachment :size => N_("{fn} of uploaded file was larger than the maximum size of %{size}").sub('%{size}', self.max_size.to_humanreadable).fix_i18n
86 86  
  87 + extend DelayedAttachmentFu::ClassMethods
87 88 delay_attachment_fu_thumbnails
88 89  
89 90 postgresql_attachment_fu
... ...
config/initializers/00_dependencies.rb
... ... @@ -16,14 +16,6 @@ end
16 16 require 'extensions'
17 17  
18 18 # locally-developed modules
19   -require 'acts_as_filesystem'
20   -require 'acts_as_having_settings'
21   -require 'acts_as_having_boxes'
22   -require 'acts_as_having_image'
23   -require 'acts_as_having_posts'
24   -require 'acts_as_customizable'
25 19 require 'route_if'
26 20 require 'maybe_add_http'
27   -require 'set_profile_region_from_city_state'
28   -require 'white_list_filter'
29 21  
... ...
config/initializers/delayed_attachment_fu.rb
... ... @@ -1 +0,0 @@
1   -require 'delayed_attachment_fu'
db/migrate/20160422163123_enable_products_plugin_on_environments.rb
... ... @@ -7,6 +7,7 @@ class Environment &lt; ApplicationRecord
7 7 has_many :profiles
8 8 has_many :products, through: :profiles
9 9  
  10 + extend ActsAsHavingSettings::ClassMethods
10 11 acts_as_having_settings field: :settings
11 12 settings_items :enabled_plugins, type: Array
12 13 end
... ...
lib/acts_as_customizable.rb
... ... @@ -1,125 +0,0 @@
1   -module Customizable
2   -
3   - def self.included(base)
4   - base.attr_accessible :custom_values
5   - base.extend ClassMethods
6   - end
7   -
8   - module ClassMethods
9   - def acts_as_customizable(options = {})
10   - attr_accessor :custom_values
11   - has_many :custom_field_values, :dependent => :delete_all, :as => :customized
12   - send :include, Customizable::InstanceMethods
13   - after_save :save_custom_values
14   - validate :valid_custom_values?
15   - end
16   -
17   - def active_custom_fields environment
18   - environment.custom_fields.select{|cf| customized_ancestors_list.include?(cf.customized_type) && cf.active}
19   - end
20   -
21   - def required_custom_fields environment
22   - environment.custom_fields.select{|cf| customized_ancestors_list.include?(cf.customized_type) && cf.required}
23   - end
24   -
25   - def signup_custom_fields environment
26   - environment.custom_fields.select{|cf| customized_ancestors_list.include?(cf.customized_type) && cf.signup}
27   - end
28   -
29   - def custom_fields environment
30   - environment.custom_fields.select{|cf| customized_ancestors_list.include?(cf.customized_type)}
31   - end
32   -
33   - def customized_ancestors_list
34   - current=self
35   - result=[]
36   - while current.instance_methods.include? :custom_value do
37   - result << current.name
38   - current=current.superclass
39   - end
40   - result
41   - end
42   -
43   - end
44   -
45   - module InstanceMethods
46   -
47   - def valid_custom_values?
48   - is_valid = true
49   - parse_custom_values.each do |cv|
50   - unless cv.valid?
51   - name = cv.custom_field.name
52   - errors.add(name, cv.errors.messages[name.to_sym].first)
53   - is_valid = false
54   - end
55   - end
56   - is_valid
57   - end
58   -
59   - def customized_class
60   - current=self.class
61   - while current.instance_methods.include? :custom_fields do
62   - result=current
63   - current=current.superclass
64   - end
65   - result.name
66   - end
67   -
68   - def is_public(field_name)
69   - cv = self.custom_field_values.detect{|cv| cv.custom_field.name==field_name}
70   - cv.nil? ? false : cv.public
71   - end
72   -
73   - def public_values
74   - self.custom_field_values.select{|cv| cv.public}
75   - end
76   -
77   - def custom_value(field_name)
78   - cv = self.custom_field_values.detect{|cv| cv.custom_field.name==field_name}
79   - cv.nil? ? default_value_for(field_name) : cv.value
80   - end
81   -
82   - def default_value_for(field_name)
83   - field=self.class.custom_fields(environment).detect {|c| c.name == field_name}
84   - field.nil? ? nil : field.default_value
85   - end
86   -
87   - def parse_custom_values
88   - return_list = []
89   - return return_list if custom_values.blank?
90   - custom_values.each_pair do |key, value|
91   - custom_field = environment.custom_fields.detect{|cf|cf.name==key}
92   - next if custom_field.blank?
93   - custom_field_value = self.custom_field_values(true).detect{|cv| cv.custom_field.name==key}
94   -
95   - if custom_field_value.nil?
96   - custom_field_value = CustomFieldValue.new
97   - custom_field_value.custom_field = custom_field
98   - custom_field_value.customized = self
99   - end
100   -
101   - if value.is_a?(Hash)
102   - custom_field_value.value = value['value'].to_s
103   - if value.has_key?('public')
104   - is_public = value['public']=="true" || value['public']==true
105   - custom_field_value.public = is_public
106   - else
107   - custom_field_value.public = false
108   - end
109   - else
110   - custom_field_value.value = value.to_s
111   - custom_field_value.public = false
112   - end
113   - return_list << custom_field_value
114   - end
115   - return_list
116   - end
117   -
118   - def save_custom_values
119   - parse_custom_values.each(&:save)
120   - end
121   -
122   - end
123   -end
124   -
125   -ActiveRecord::Base.include Customizable
lib/acts_as_filesystem.rb
... ... @@ -1,267 +0,0 @@
1   -module ActsAsFileSystem
2   -
3   - module ActsMethods
4   -
5   - # Declares the ActiveRecord model to acts like a filesystem: objects are
6   - # arranged in a tree (liks acts_as_tree), and . The underlying table must
7   - # have the following fields:
8   - #
9   - # * name (+:string+) - the title of the object
10   - # * slug (+:string+)- the title turned in a URL-friendly string (downcased,
11   - # non-ascii chars transliterated into ascii, all sequences of
12   - # non-alphanumericd characters changed into dashed)
13   - # * path (+:text+)- stores the full path of the object (the full path of
14   - # the parent, a "/" and the slug of the object)
15   - # * children_count - a cache of the number of children elements.
16   - def acts_as_filesystem
17   - # a filesystem is a tree
18   - acts_as_tree :counter_cache => :children_count
19   -
20   - extend ClassMethods
21   - include InstanceMethods
22   - if self.has_path?
23   - after_update :update_children_path
24   - before_create :set_path
25   - include InstanceMethods::PathMethods
26   - end
27   -
28   - before_save :set_ancestry
29   - end
30   -
31   - end
32   -
33   - module ClassMethods
34   -
35   - def build_ancestry(parent_id = nil, ancestry = '')
36   - ActiveRecord::Base.transaction do
37   - self.base_class.where(parent_id: parent_id).each do |node|
38   - node.update_column :ancestry, ancestry
39   -
40   - build_ancestry node.id, (ancestry.empty? ? "#{node.formatted_ancestry_id}" :
41   - "#{ancestry}#{node.ancestry_sep}#{node.formatted_ancestry_id}")
42   - end
43   - end
44   -
45   - #raise "Couldn't reach and set ancestry on every record" if self.base_class.where('ancestry is null').count != 0
46   - end
47   -
48   - def has_path?
49   - (['name', 'slug', 'path'] - self.column_names).blank?
50   - end
51   -
52   - end
53   -
54   - module InstanceMethods
55   -
56   - def ancestry_column
57   - 'ancestry'
58   - end
59   - def ancestry_sep
60   - '.'
61   - end
62   - def has_ancestry?
63   - self.class.column_names.include? self.ancestry_column
64   - end
65   -
66   - def formatted_ancestry_id
67   - "%010d" % self.id if self.id
68   - end
69   -
70   - def ancestry
71   - self[ancestry_column]
72   - end
73   - def ancestor_ids
74   - return nil if !has_ancestry? or ancestry.nil?
75   - @ancestor_ids ||= ancestry.split(ancestry_sep).map{ |id| id.to_i }
76   - end
77   -
78   - def ancestry=(value)
79   - self[ancestry_column] = value
80   - end
81   - def set_ancestry
82   - return unless self.has_ancestry?
83   - if self.ancestry.nil? or (new_record? or parent_id_changed?) or recalculate_path
84   - self.ancestry = self.hierarchy(true)[0...-1].map{ |p| p.formatted_ancestry_id }.join(ancestry_sep)
85   - end
86   - end
87   -
88   - def descendents_options
89   - ["#{self.ancestry_column} LIKE ?", "%#{self.formatted_ancestry_id}%"]
90   - end
91   - def descendents
92   - self.class.where descendents_options
93   - end
94   -
95   - # calculates the level of the record in the records hierarchy. Top-level
96   - # records have level 0; the children of the top-level records have
97   - # level 1; the children of records with level 1 have level 2, and so on.
98   - #
99   - # A level 0
100   - # / \
101   - # B C level 1
102   - # / \ / \
103   - # E F G H level 2
104   - # ...
105   - def level
106   - self.hierarchy.size - 1
107   - end
108   -
109   - # Is this record a top-level record?
110   - def top_level?
111   - self.parent.nil?
112   - end
113   -
114   - # Is this record a leaf in the hierarchy tree of records?
115   - #
116   - # Being a leaf means that this record has no subrecord.
117   - def leaf?
118   - self.children.empty?
119   - end
120   -
121   - def top_ancestor
122   - if has_ancestry? and !ancestry.blank?
123   - self.class.base_class.find_by id: self.top_ancestor_id
124   - else
125   - self.hierarchy.first
126   - end
127   - end
128   - def top_ancestor_id
129   - if has_ancestry? and !ancestry.nil?
130   - self.ancestor_ids.first
131   - else
132   - self.hierarchy.first.id
133   - end
134   - end
135   -
136   - # returns the full hierarchy from the top-level item to this one. For
137   - # example, if item1 has a children item2 and item2 has a children item3,
138   - # then item3's hierarchy would be [item1, item2, item3].
139   - #
140   - # If +reload+ is passed as +true+, then the hierarchy is reload (usefull
141   - # when the ActiveRecord object was modified in some way, or just after
142   - # changing parent)
143   - def hierarchy(reload = false)
144   - @hierarchy = nil if reload or recalculate_path
145   -
146   - if @hierarchy.nil?
147   - @hierarchy = []
148   -
149   - if !reload and !recalculate_path and ancestor_ids
150   - objects = self.class.base_class.where(id: ancestor_ids)
151   - ancestor_ids.each{ |id| @hierarchy << objects.find{ |t| t.id == id } }
152   - @hierarchy << self
153   - else
154   - item = self
155   - while item
156   - @hierarchy.unshift(item)
157   - item = item.parent
158   - end
159   - end
160   - end
161   -
162   - @hierarchy
163   - end
164   -
165   - def map_traversal(&block)
166   - result = []
167   - current_level = [self]
168   -
169   - while !current_level.empty?
170   - result += current_level
171   - ids = current_level.select {|item| item.children_count > 0}.map(&:id)
172   - break if ids.empty?
173   - current_level = self.class.base_class.where(parent_id: ids)
174   - end
175   - block ||= (lambda { |x| x })
176   - result.map(&block)
177   - end
178   -
179   - def all_children
180   - res = map_traversal
181   - res.shift
182   - res
183   - end
184   -
185   - #####
186   - # Path methods
187   - # These methods are used when _path_, _name_ and _slug_ attributes exist
188   - # and should be calculated based on the tree
189   - #####
190   - module PathMethods
191   - # used to know when to trigger batch renaming
192   - attr_accessor :recalculate_path
193   -
194   - # calculates the full path to this record using parent's path.
195   - def calculate_path
196   - self.hierarchy.map{ |obj| obj.slug }.join('/')
197   - end
198   - def set_path
199   - if self.path == self.slug && !self.top_level?
200   - self.path = self.calculate_path
201   - end
202   - end
203   - def explode_path
204   - path.split(/\//)
205   - end
206   -
207   - def update_children_path
208   - if self.recalculate_path
209   - self.children.each do |child|
210   - child.path = child.calculate_path
211   - child.recalculate_path = true
212   - child.save!
213   - end
214   - end
215   - self.recalculate_path = false
216   - end
217   -
218   - # calculates the full name of a record by accessing the name of all its
219   - # ancestors.
220   - #
221   - # If you have this record hierarchy:
222   - # Record "A"
223   - # Record "B"
224   - # Record "C"
225   - #
226   - # Then Record "C" will have "A/B/C" as its full name.
227   - def full_name(sep = '/')
228   - self.hierarchy.map {|item| item.name || '?' }.join(sep)
229   - end
230   -
231   - # gets the name without leading parents. Useful when dividing records
232   - # in top-level groups and full names must not include the top-level
233   - # record which is already a emphasized label
234   - def full_name_without_leading(count, sep = '/')
235   - parts = self.full_name(sep).split(sep)
236   - count.times { parts.shift }
237   - parts.join(sep)
238   - end
239   -
240   - def set_name(value)
241   - if self.name != value
242   - self.recalculate_path = true
243   - end
244   - self[:name] = value
245   - end
246   -
247   - # sets the name of the record. Also sets #slug accordingly.
248   - def name=(value)
249   - self.set_name(value)
250   - unless self.name.blank?
251   - self.slug = self.name.to_slug
252   - end
253   - end
254   -
255   - # sets the slug of the record. Also sets the path with the new slug value.
256   - def slug=(value)
257   - self[:slug] = value
258   - unless self.slug.blank?
259   - self.path = self.calculate_path
260   - end
261   - end
262   - end
263   - end
264   -end
265   -
266   -ActiveRecord::Base.extend ActsAsFileSystem::ActsMethods
267   -
lib/acts_as_having_boxes.rb
... ... @@ -1,38 +0,0 @@
1   -module ActsAsHavingBoxes
2   -
3   - module ClassMethods
4   - def acts_as_having_boxes
5   - has_many :boxes, -> { order :position }, as: :owner, dependent: :destroy
6   - self.send(:include, ActsAsHavingBoxes)
7   - end
8   - end
9   -
10   - module BlockArray
11   - def find(id)
12   - select { |item| item.id == id.to_i }.first
13   - end
14   - end
15   -
16   - def blocks(reload = false)
17   - if (reload)
18   - @blocks = nil
19   - end
20   - if @blocks.nil?
21   - @blocks = boxes.includes(:blocks).inject([]) do |acc,obj|
22   - acc.concat(obj.blocks)
23   - end
24   - @blocks.send(:extend, BlockArray)
25   - end
26   - @blocks
27   - end
28   -
29   - # returns 3 unless the class table has a boxes_limit column. In that case
30   - # return the value of the column.
31   - def boxes_limit layout_template = nil
32   - layout_template ||= self.layout_template
33   - @boxes_limit ||= LayoutTemplate.find(layout_template).number_of_boxes || 3
34   - end
35   -
36   -end
37   -
38   -ActiveRecord::Base.extend ActsAsHavingBoxes::ClassMethods
lib/acts_as_having_image.rb
... ... @@ -1,27 +0,0 @@
1   -module ActsAsHavingImage
2   -
3   - module ClassMethods
4   - def acts_as_having_image
5   - belongs_to :image, dependent: :destroy
6   - scope :with_image, -> { where "#{table_name}.image_id IS NOT NULL" }
7   - scope :without_image, -> { where "#{table_name}.image_id IS NULL" }
8   - attr_accessible :image_builder
9   - include ActsAsHavingImage
10   - end
11   - end
12   -
13   - def image_builder=(img)
14   - if image && image.id == img[:id]
15   - image.attributes = img
16   - else
17   - build_image(img)
18   - end unless img[:uploaded_data].blank?
19   - if img[:remove_image] == 'true'
20   - self.image_id = nil
21   - end
22   - end
23   -
24   -end
25   -
26   -ActiveRecord::Base.extend ActsAsHavingImage::ClassMethods
27   -
lib/acts_as_having_posts.rb
... ... @@ -1,51 +0,0 @@
1   -module ActsAsHavingPosts
2   -
3   - module ClassMethods
4   - def acts_as_having_posts(scope = nil)
5   - has_many :posts, -> {
6   - s = order('published_at DESC, id DESC').where('articles.type != ?', 'RssFeed')
7   - s = s.instance_exec(&scope) if scope
8   - s
9   - }, class_name: 'Article', foreign_key: 'parent_id', source: :children
10   -
11   - attr_accessor :feed_attrs
12   -
13   - after_create do |blog|
14   - blog.children << RssFeed.new(:name => 'feed', :profile => blog.profile)
15   - blog.feed = blog.feed_attrs
16   - end
17   -
18   - settings_items :posts_per_page, :type => :integer, :default => 5
19   -
20   - self.send(:include, ActsAsHavingPosts)
21   - end
22   - end
23   -
24   - def has_posts?
25   - true
26   - end
27   -
28   - def feed
29   - children.where(:type => 'RssFeed').first
30   - end
31   -
32   - def feed=(attrs)
33   - if attrs
34   - if self.feed
35   - self.feed.update(attrs)
36   - else
37   - self.feed_attrs = attrs
38   - end
39   - end
40   - self.feed
41   - end
42   -
43   - def name=(value)
44   - self.set_name(value)
45   - self.slug = self.slug.blank? ? self.name.to_slug : self.slug.to_slug
46   - end
47   -
48   -end
49   -
50   -ActiveRecord::Base.extend ActsAsHavingPosts::ClassMethods
51   -
lib/acts_as_having_settings.rb
... ... @@ -1,91 +0,0 @@
1   -# declare missing types
2   -module ActiveRecord
3   - module Type
4   - class Symbol < Value
5   - def cast_value value
6   - value.to_sym
7   - end
8   - end
9   - class Array < Value
10   - def cast_value value
11   - ::Array.wrap(value)
12   - end
13   - end
14   - class Hash < Value
15   - def cast_value value
16   - h = ::Hash[value]
17   - h.symbolize_keys!
18   - h
19   - end
20   - end
21   - end
22   -end
23   -
24   -module ActsAsHavingSettings
25   -
26   - def self.type_cast value, type
27   - # do not cast nil
28   - return value if value.nil?
29   - type.send :cast_value, value
30   - end
31   -
32   - module ClassMethods
33   -
34   - def acts_as_having_settings(*args)
35   - options = args.last.is_a?(Hash) ? args.pop : {}
36   - field = (options[:field] || :settings).to_sym
37   -
38   - serialize field, Hash
39   - class_attribute :settings_field
40   - self.settings_field = field
41   -
42   - class_eval do
43   - def settings_field
44   - self[self.class.settings_field] ||= Hash.new
45   - end
46   -
47   - def setting_changed? setting_field
48   - setting_field = setting_field.to_sym
49   - changed_settings = self.changes[self.class.settings_field]
50   - return false if changed_settings.nil?
51   -
52   - old_setting_value = changed_settings.first.nil? ? nil : changed_settings.first[setting_field]
53   - new_setting_value = changed_settings.last[setting_field]
54   - old_setting_value != new_setting_value
55   - end
56   - end
57   -
58   - settings_items *args
59   - end
60   -
61   - def settings_items *names
62   -
63   - options = names.extract_options!
64   - default = options[:default]
65   - type = options[:type]
66   - type = if type.present? then ActiveRecord::Type.const_get(type.to_s.camelize.to_sym).new else nil end
67   -
68   - names.each do |setting|
69   - # symbolize key
70   - setting = setting.to_sym
71   -
72   - define_method setting do
73   - h = send self.class.settings_field
74   - val = h[setting]
75   - # translate default value if it is used
76   - if not val.nil? then val elsif default.is_a? String then gettext default else default end
77   - end
78   -
79   - define_method "#{setting}=" do |value|
80   - h = send self.class.settings_field
81   - h[setting] = if type then ActsAsHavingSettings.type_cast value, type else value end
82   - end
83   - end
84   - end
85   -
86   - end
87   -
88   -end
89   -
90   -ActiveRecord::Base.extend ActsAsHavingSettings::ClassMethods
91   -
lib/code_numbering.rb
... ... @@ -1,58 +0,0 @@
1   -module CodeNumbering
2   - module ClassMethods
3   - def code_numbering field, options = {}
4   - class_attribute :code_numbering_field
5   - class_attribute :code_numbering_options
6   -
7   - self.code_numbering_field = field
8   - self.code_numbering_options = options
9   -
10   - before_create :create_code_numbering
11   -
12   - include CodeNumbering::InstanceMethods
13   - end
14   - end
15   -
16   - module InstanceMethods
17   -
18   - def code
19   - self.attributes[self.code_numbering_field.to_s]
20   - end
21   -
22   - def code_scope
23   - scope = self.code_numbering_options[:scope]
24   - case scope
25   - when Symbol
26   - self.send scope
27   - when Proc
28   - instance_exec &scope
29   - else
30   - self.class
31   - end
32   - end
33   -
34   - def code_maximum
35   - self.code_scope.maximum(self.code_numbering_field) || 0
36   - end
37   -
38   - def create_code_numbering
39   - max = self.code_numbering_options[:start].to_i - 1 if self.code_numbering_options[:start]
40   - max = self.code_maximum
41   - self.send "#{self.code_numbering_field}=", max+1
42   - end
43   -
44   - def reset_scope_code_numbering
45   - max = self.code_numbering_options[:start].to_i - 1 if self.code_numbering_options[:start]
46   - max ||= 1
47   -
48   - self.code_scope.order(:created_at).each do |record|
49   - record.update_column self.code_numbering_field, max
50   - max += 1
51   - end
52   - self.reload
53   - end
54   -
55   - end
56   -end
57   -
58   -ActiveRecord::Base.extend CodeNumbering::ClassMethods
lib/delayed_attachment_fu.rb
... ... @@ -1,56 +0,0 @@
1   -module DelayedAttachmentFu
2   -
3   - module ClassMethods
4   - def delay_attachment_fu_thumbnails
5   - include DelayedAttachmentFu::InstanceMethods
6   - after_create do |file|
7   - if file.thumbnailable?
8   - Delayed::Job.enqueue CreateThumbnailsJob.new(file.class.name, file.id)
9   - end
10   - end
11   - end
12   - end
13   -
14   - module InstanceMethods
15   - # skip processing with RMagick
16   - def process_attachment
17   - end
18   -
19   - def after_process_attachment
20   - save_to_storage
21   - @temp_paths.clear
22   - @saved_attachment = nil
23   - run_callbacks :after_attachment_saved
24   - end
25   -
26   - def create_thumbnails
27   - if thumbnailable?
28   - self.class.with_image(full_filename) do |img|
29   - self.width = img.columns
30   - self.height = img.rows
31   - self.save!
32   - end
33   - self.class.attachment_options[:thumbnails].each do |suffix, size|
34   - self.create_or_update_thumbnail(self.full_filename, suffix, size)
35   - end
36   - self.thumbnails_processed = true
37   - self.save!
38   - end
39   - end
40   -
41   - def public_filename(size=nil)
42   - force, size = true, nil if size == :uploaded
43   - if !self.thumbnailable? || self.thumbnails_processed || force
44   - super size
45   - else
46   - size ||= :thumb
47   - '/images/icons-app/image-loading-%s.png' % size
48   - end
49   - end
50   -
51   -
52   - end
53   -end
54   -
55   -ActiveRecord::Base.extend DelayedAttachmentFu::ClassMethods
56   -
lib/noosfero/translatable_content.rb
... ... @@ -1,7 +0,0 @@
1   -module Noosfero::TranslatableContent
2   -
3   - def translatable?
4   - return false if self.profile && !self.profile.environment.languages.present?
5   - parent.nil? || !parent.forum?
6   - end
7   -end
lib/set_profile_region_from_city_state.rb
... ... @@ -1,44 +0,0 @@
1   -module SetProfileRegionFromCityState
2   -
3   - module ClassMethods
4   - def set_profile_region_from_city_state
5   - before_save :region_from_city_and_state
6   -
7   - include InstanceMethods
8   - alias_method_chain :city=, :region
9   - alias_method_chain :state=, :region
10   - end
11   - end
12   -
13   - module InstanceMethods
14   - include Noosfero::Plugin::HotSpot
15   -
16   - def city_with_region=(value)
17   - self.city_without_region = value
18   - @change_region = true
19   - end
20   -
21   - def state_with_region=(value)
22   - self.state_without_region = value
23   - @change_region = true
24   - end
25   -
26   - def region_from_city_and_state
27   - if @change_region
28   - self.region = nil
29   - state = search_region(State, self.state)
30   - self.region = search_region(City.where(:parent_id => state.id), self.city) if state
31   - end
32   - end
33   -
34   - private
35   -
36   - def search_region(scope, query)
37   - return nil if !query
38   - query = query.downcase.strip
39   - scope.where(['lower(name)=? OR lower(abbreviation)=? OR lower(acronym)=?', query, query, query]).first
40   - end
41   -
42   - end
43   -
44   -end
lib/white_list_filter.rb
... ... @@ -1,37 +0,0 @@
1   -module WhiteListFilter
2   -
3   - def check_iframe_on_content(content, trusted_sites)
4   - if content.blank? || !content.include?('iframe')
5   - return content
6   - end
7   - content.gsub!(/<iframe[^>]*>\s*<\/iframe>/i) do |iframe|
8   - result = ''
9   - unless iframe =~ /src=['"].*src=['"]/
10   - trusted_sites.each do |trusted_site|
11   - re_dom = trusted_site.gsub('.', '\.')
12   - if iframe =~ /src=["'](https?:)?\/\/(www\.)?#{re_dom}\//
13   - result = iframe
14   - end
15   - end
16   - end
17   - result
18   - end
19   - content
20   - end
21   -
22   - module ClassMethods
23   - def filter_iframes(*opts)
24   - options = opts.last.is_a?(Hash) && opts.pop || {}
25   - white_list_method = options[:whitelist] || :iframe_whitelist
26   - opts.each do |field|
27   - before_validation do |obj|
28   - obj.check_iframe_on_content(obj.send(field), obj.send(white_list_method))
29   - end
30   - end
31   - end
32   - end
33   -
34   - def self.included(c)
35   - c.send(:extend, WhiteListFilter::ClassMethods)
36   - end
37   -end
plugins/analytics/models/analytics_plugin/page_view.rb
... ... @@ -8,6 +8,7 @@ class AnalyticsPlugin::PageView &lt; ApplicationRecord
8 8 attr_accessor :request
9 9 attr_accessible :request
10 10  
  11 + extend ActsAsHavingSettings::ClassMethods
11 12 acts_as_having_settings field: :options
12 13  
13 14 belongs_to :profile, validate: true
... ...
plugins/fb_app/models/fb_app_plugin/page_tab.rb
... ... @@ -9,6 +9,7 @@ class FbAppPlugin::PageTab &lt; ApplicationRecord
9 9  
10 10 belongs_to :owner_profile, foreign_key: :profile_id, class_name: 'Profile'
11 11  
  12 + extend ActsAsHavingSettings::ClassMethods
12 13 acts_as_having_settings field: :config
13 14  
14 15 ConfigTypes = [:profile, :profiles, :query]
... ...
plugins/newsletter/lib/newsletter_plugin/newsletter.rb
... ... @@ -167,6 +167,7 @@ class NewsletterPlugin::Newsletter &lt; ApplicationRecord
167 167 end
168 168 end
169 169  
  170 + extend ActsAsHavingImage::ClassMethods
170 171 acts_as_having_image
171 172  
172 173 def last_send_at
... ...
plugins/oauth_client/models/oauth_client_plugin/auth.rb
... ... @@ -10,6 +10,7 @@ class OauthClientPlugin::Auth &lt; ApplicationRecord
10 10 validates_presence_of :provider
11 11 validates_uniqueness_of :profile_id, scope: :provider_id
12 12  
  13 + extend ActsAsHavingSettings::ClassMethods
13 14 acts_as_having_settings field: :data
14 15  
15 16 def expires_in
... ...
plugins/oauth_client/models/oauth_client_plugin/provider.rb
... ... @@ -4,7 +4,10 @@ class OauthClientPlugin::Provider &lt; ApplicationRecord
4 4  
5 5 validates_presence_of :name, :strategy
6 6  
  7 + extend ActsAsHavingImage::ClassMethods
7 8 acts_as_having_image
  9 +
  10 + extend ActsAsHavingSettings::ClassMethods
8 11 acts_as_having_settings field: :options
9 12  
10 13 settings_items :site, type: String
... ... @@ -16,6 +19,4 @@ class OauthClientPlugin::Provider &lt; ApplicationRecord
16 19  
17 20 scope :enabled, -> { where enabled: true }
18 21  
19   - acts_as_having_image
20   -
21 22 end
... ...
plugins/products/models/products_plugin/product.rb
... ... @@ -45,6 +45,7 @@ class ProductsPlugin::Product &lt; ApplicationRecord
45 45 has_many :qualifiers, through: :product_qualifiers
46 46 has_many :certifiers, through: :product_qualifiers
47 47  
  48 + extend ActsAsHavingSettings::ClassMethods
48 49 acts_as_having_settings field: :data
49 50  
50 51 track_actions :create_product, :after_create, keep_params: [:name, :url ], if: Proc.new { |a| a.is_trackable? }, custom_user: :action_tracker_user
... ... @@ -129,6 +130,7 @@ class ProductsPlugin::Product &lt; ApplicationRecord
129 130 image ? image.public_filename(size) : '/images/icons-app/product-default-pic-%s.png' % size
130 131 end
131 132  
  133 + extend ActsAsHavingImage::ClassMethods
132 134 acts_as_having_image
133 135  
134 136 def save_image
... ...
plugins/shopping_cart/db/migrate/20131226125124_move_shopping_cart_purchase_order_to_orders_plugin_order.rb
... ... @@ -2,6 +2,7 @@ OrdersPlugin.send :remove_const, :Item if defined? OrdersPlugin::Item
2 2 OrdersPlugin.send :remove_const, :Order if defined? OrdersPlugin::Order
3 3  
4 4 class ShoppingCartPlugin::PurchaseOrder < ApplicationRecord
  5 + extend ActsAsHavingSettings::ClassMethods
5 6 acts_as_having_settings field: :data
6 7  
7 8 module Status
... ...
plugins/video/lib/video_plugin/video.rb
1   -require 'noosfero/translatable_content'
2 1 require 'application_helper'
3 2 require 'net/http'
4 3  
... ...
plugins/video/lib/video_plugin/video_gallery.rb
... ... @@ -14,7 +14,8 @@ class VideoPlugin::VideoGallery &lt; Folder
14 14 errors.add(:parent, "A video gallery should not belong to a blog.") if parent && parent.blog?
15 15 end
16 16  
17   - acts_as_having_settings :field => :setting
  17 + extend ActsAsHavingSettings::ClassMethods
  18 + acts_as_having_settings field: :setting
18 19  
19 20 xss_terminate :only => [ :body ], :with => 'white_list', :on => 'validation'
20 21  
... ...
test/unit/event_test.rb
... ... @@ -282,7 +282,7 @@ class EventTest &lt; ActiveSupport::TestCase
282 282 end
283 283  
284 284 should 'be translatable' do
285   - assert_kind_of Noosfero::TranslatableContent, Event.new
  285 + assert_kind_of TranslatableContent, Event.new
286 286 end
287 287  
288 288 should 'tiny mce editor is enabled' do
... ...
test/unit/text_article_test.rb
... ... @@ -15,7 +15,7 @@ class TextArticleTest &lt; ActiveSupport::TestCase
15 15 end
16 16  
17 17 should 'be translatable' do
18   - assert_kind_of Noosfero::TranslatableContent, TextArticle.new
  18 + assert_kind_of TranslatableContent, TextArticle.new
19 19 end
20 20  
21 21 should 'return article icon name' do
... ...
test/unit/translatable_content_test.rb
... ... @@ -4,7 +4,7 @@ class TranslatableContentTest &lt; ActiveSupport::TestCase
4 4  
5 5 class Content
6 6 attr_accessor :parent, :profile
7   - include Noosfero::TranslatableContent
  7 + include TranslatableContent
8 8 end
9 9  
10 10 def setup
... ...