Commit 6c4f6400dbf5daea661eb9eef5d5369573f77f56

Authored by Larissa Reis
1 parent f078e729

Makes ExternalProfile respond to all Profile methods to avoid breakage

app/models/concerns/profile_entity.rb
... ... @@ -12,6 +12,8 @@ module ProfileEntity
12 12  
13 13 before_create :set_default_environment
14 14  
  15 + scope :recent, -> limit=nil { order('id DESC').limit(limit) }
  16 +
15 17 end
16 18  
17 19 def disable
... ... @@ -65,4 +67,77 @@ module ProfileEntity
65 67 end
66 68 end
67 69  
  70 + def to_liquid
  71 + HashWithIndifferentAccess.new :name => name, :identifier => identifier
  72 + end
  73 +
  74 + # Tells whether a specified profile has members or nor.
  75 + #
  76 + # On this class, returns <tt>false</tt> by default.
  77 + def has_members?
  78 + false
  79 + end
  80 +
  81 + def apply_type_specific_template(template)
  82 + end
  83 +
  84 + # Override this method in subclasses of Profile to create a default article
  85 + # set upon creation. Note that this method will be called *only* if there is
  86 + # no template for the type of profile (i.e. if the template was removed or in
  87 + # the creation of the template itself).
  88 + #
  89 + # This method must return an array of pre-populated articles, which will be
  90 + # associated to the profile before being saved. Example:
  91 + #
  92 + # def default_set_of_articles
  93 + # [Blog.new(:name => 'Blog'), Gallery.new(:name => 'Gallery')]
  94 + # end
  95 + #
  96 + # By default, this method returns an empty array.
  97 + def default_set_of_articles
  98 + []
  99 + end
  100 +
  101 + def blocks_to_expire_cache
  102 + []
  103 + end
  104 +
  105 + def cache_keys(params = {})
  106 + []
  107 + end
  108 +
  109 + def members_cache_key(params = {})
  110 + page = params[:npage] || '1'
  111 + sort = (params[:sort] == 'desc') ? params[:sort] : 'asc'
  112 + cache_key + '-members-page-' + page + '-' + sort
  113 + end
  114 +
  115 + def more_recent_label
  116 + _("Since: ")
  117 + end
  118 +
  119 + def control_panel_settings_button
  120 + {:title => _('Edit Profile'), :icon => 'edit-profile'}
  121 + end
  122 +
  123 + def control_panel_settings_button
  124 + {:title => _('Profile Info and settings'), :icon => 'edit-profile'}
  125 + end
  126 +
  127 + def exclude_verbs_on_activities
  128 + %w[]
  129 + end
  130 +
  131 + def allow_invitation_from(person)
  132 + false
  133 + end
  134 +
  135 + module ClassMethods
  136 +
  137 + def identification
  138 + name
  139 + end
  140 +
  141 + end
  142 +
68 143 end
... ...
app/models/external_person.rb
... ... @@ -23,87 +23,92 @@ class ExternalPerson &lt; ActiveRecord::Base
23 23 user
24 24 end
25 25  
26   - def url
27   - "http://#{self.source}/#{self.identifier}"
  26 + def privacy_setting
  27 + _('Public profile')
28 28 end
29 29  
30   - alias :public_profile_url :url
31   -
32 30 def avatar
33 31 "http://#{self.source}/profile/#{self.identifier}/icon/"
34 32 end
35 33  
  34 + def url
  35 + "http://#{self.source}/#{self.identifier}"
  36 + end
  37 +
  38 + alias :public_profile_url :url
  39 +
36 40 def admin_url
37 41 "http://#{self.source}/myprofile/#{self.identifier}"
38 42 end
39 43  
40   - def profile_custom_icon(gravatar_default=nil)
41   - self.avatar
  44 + def tasks_url
  45 + self.url
42 46 end
43   -
44   - def preferred_login_redirection
45   - environment.redirection_after_login
  47 + def leave_url(reload = false)
  48 + self.url
46 49 end
47   -
48   - def person?
49   - true
  50 + def join_url
  51 + self.url
50 52 end
51   -
52   - def is_admin?(environment = nil)
53   - false
  53 + def join_not_logged_url
  54 + self.url
54 55 end
55   -
56   - def lat
57   - nil
  56 + def check_membership_url
  57 + self.url
58 58 end
59   - def lng
60   - nil
  59 + def add_url
  60 + self.url
61 61 end
62   -
63   - def role_assignments
64   - RoleAssignment.none
  62 + def check_friendship_url
  63 + self.url
65 64 end
66   -
67   - def favorite_enterprises
68   - Enterprise.none
  65 + def people_suggestions_url
  66 + self.url
69 67 end
70   -
71   - def memberships
72   - Profile.none
  68 + def communities_suggestions_url
  69 + self.url
  70 + end
  71 + def top_url(scheme = 'http')
  72 + "#{scheme}://#{self.source}"
73 73 end
74 74  
75   - def friendships
76   - Profile.none
  75 + def profile_custom_icon(gravatar_default=nil)
  76 + self.avatar
77 77 end
78 78  
79   - def tasks
80   - Task.none
  79 + def preferred_login_redirection
  80 + environment.redirection_after_login
81 81 end
82 82  
83   - def suggested_profiles
84   - ProfileSuggestion.none
  83 + def location
  84 + self.source
85 85 end
86   - def suggested_people
87   - ProfileSuggestion.none
  86 +
  87 + def default_hostname
  88 + environment.default_hostname
88 89 end
89   - def suggested_communities
90   - ProfileSuggestion.none
  90 +
  91 + def possible_domains
  92 + environment.domains
91 93 end
92 94  
93   - def add_friend(friend, group = nil)
94   - false
  95 + def person?
  96 + true
95 97 end
96 98  
97   - def follows?(profile)
98   - false
  99 + def contact_email(*args)
  100 + self.email
99 101 end
100 102  
101   - def is_a_friend?(person)
102   - false
  103 + def notification_emails
  104 + [self.contact_email]
103 105 end
104 106  
105   - def already_request_friendship?(person)
106   - false
  107 + def jid(options = {})
  108 + "#{self.identifier}@#{self.source}"
  109 + end
  110 + def full_jid(options = {})
  111 + "#{jid(options)}/#{self.name}"
107 112 end
108 113  
109 114 class ExternalPerson::Image
... ... @@ -126,18 +131,6 @@ class ExternalPerson &lt; ActiveRecord::Base
126 131 ExternalPerson::Image.new(avatar)
127 132 end
128 133  
129   - def is_template?
130   - false
131   - end
132   -
133   - def enterprises
134   - []
135   - end
136   -
137   - def friends
138   - []
139   - end
140   -
141 134 def data_hash(gravatar_default = nil)
142 135 friends_list = {}
143 136 {
... ... @@ -155,4 +148,86 @@ class ExternalPerson &lt; ActiveRecord::Base
155 148 'chat_enabled' => false
156 149 }
157 150 end
  151 +
  152 + # External Person should respond to all methods in Person and Profile
  153 + def person_instance_methods
  154 + {}
  155 + end
  156 +
  157 + def profile_instance_methods
  158 + methods_and_responses = {
  159 + role_assignments: RoleAssignment.none, favorite_enterprises:
  160 + Enterprise.none, enterprises: Enterprise.none, memberships: Profile.none,
  161 + friendships: Profile.none, friends: Profile.none, tasks: Task.none,
  162 + suggested_profiles: ProfileSuggestion.none, suggested_people:
  163 + ProfileSuggestion.none, suggested_communities: ProfileSuggestion.none,
  164 + public_profile: true, nickname: nil, custom_footer: '', custom_header: '',
  165 + address: '', zip_code: '', contact_phone: '', image_builder: nil,
  166 + description: '', closed: false, template_id: nil, lat: nil, lng: nil,
  167 + is_template: false, fields_privacy: {}, preferred_domain_id: nil,
  168 + category_ids: [], country: '', city: '', state: '', national_region_code:
  169 + '', redirect_l10n: false, notification_time: 0, custom_url_redirection:
  170 + nil, email_suggestions: false, allow_members_to_invite: false,
  171 + invite_friends_only: false, secret: false, profile_admin_mail_notification:
  172 + false, redirection_after_login: nil, profile_activities:
  173 + ProfileActivity.none, action_tracker_notifications:
  174 + ActionTrackerNotification.none, tracked_notifications:
  175 + ActionTracker::Record.none, scraps_received: Scrap.none, template:
  176 + Profile.none, comments_received: Comment.none, email_templates:
  177 + EmailTemplate.none, members: Profile.none, members_like: Profile.none,
  178 + members_by: Profile.none, members_by_role: Profile.none, scraps:
  179 + Scrap.none, welcome_page_content: nil, settings: {}, find_in_all_tasks:
  180 + nil, top_level_categorization: {}, interests: Category.none, geolocation:
  181 + '', country_name: '', pending_categorizations: [], add_category: false,
  182 + create_pending_categorizations: false, top_level_articles: Article.none,
  183 + valid_identifier: true, valid_template: false, create_default_set_of_boxes:
  184 + true, copy_blocks_from: nil, default_template: nil,
  185 + template_without_default: nil, template_with_default: nil, apply_template:
  186 + false, iframe_whitelist: [], recent_documents: Article.none, last_articles:
  187 + Article.none, is_validation_entity?: false, hostname: nil, own_hostname:
  188 + nil, article_tags: {}, tagged_with: Article.none,
  189 + insert_default_article_set: false, copy_articles_from: true,
  190 + copy_article_tree: nil, copy_article?: false, add_member: false,
  191 + remove_member: false, add_admin: false, remove_admin: false, add_moderator:
  192 + false, display_info_to?: true, update_category_from_region: nil,
  193 + accept_category?: false, custom_header_expanded: '',
  194 + custom_footer_expanded: '', public?: true, themes: [], find_theme: nil,
  195 + blogs: Blog.none, blog: nil, has_blog?: false, forums: Forum.none, forum:
  196 + nil, has_forum?: false, admins: [], settings_field: {}, setting_changed:
  197 + false, public_content: true, enable_contact?: false, folder_types: [],
  198 + folders: Article.none, image_galleries: Article.none, image_valid: true,
  199 + update_header_and_footer: nil, update_theme: nil, update_layout_template:
  200 + nil, recent_actions: ActionTracker::Record.none, recent_notifications:
  201 + ActionTracker::Record.none, more_active_label: _('no activity'),
  202 + more_popular_label: _('no members'), profile_custom_image: nil,
  203 + is_on_homepage?: false, activities: ProfileActivity.none,
  204 + may_display_field_to?: true, may_display_location_to?: true, public_fields:
  205 + {}, followed_by?: false, display_private_info_to?: true, can_view_field?:
  206 + true, remove_from_suggestion_list: nil, layout_template: 'default',
  207 + is_admin?: false, add_friend: false, follows?: false, is_a_friend?: false,
  208 + already_request_friendship?: false
  209 + }
  210 +
  211 + derivated_methods = {}
  212 + methods_and_responses.keys.each do |method|
  213 + derivated_methods[method.to_s.insert(-1, '?').to_sym] = false
  214 + derivated_methods[method.to_s.insert(-1, '=').to_sym] = nil
  215 + end
  216 + derivated_methods.merge(methods_and_responses)
  217 + end
  218 +
  219 + def method_missing(method, *args, &block)
  220 + if person_instance_methods.keys.include?(method)
  221 + return person_instance_methods[method]
  222 + end
  223 + if profile_instance_methods.keys.include? method
  224 + return profile_instance_methods[method]
  225 + end
  226 + end
  227 +
  228 + def respond_to_missing?(method_name, include_private = false)
  229 + person_instance_methods.keys.include?(method_name) ||
  230 + profile_instance_methods.keys.include?(method_name) ||
  231 + super
  232 + end
158 233 end
... ...
app/models/profile.rb
... ... @@ -116,8 +116,6 @@ class Profile &lt; ApplicationRecord
116 116 }
117 117 scope :no_templates, -> { where is_template: false }
118 118  
119   - scope :recent, -> limit=nil { order('id DESC').limit(limit) }
120   -
121 119  
122 120 # Returns a scoped object to select profiles in a given location or in a radius
123 121 # distance from the given location center.
... ... @@ -483,9 +481,6 @@ class Profile &lt; ApplicationRecord
483 481 self.save(:validate => false)
484 482 end
485 483  
486   - def apply_type_specific_template(template)
487   - end
488   -
489 484 xss_terminate :only => [ :name, :nickname, :address, :contact_phone, :description ], :on => 'validation'
490 485 xss_terminate :only => [ :custom_footer, :custom_header ], :with => 'white_list'
491 486  
... ... @@ -526,10 +521,6 @@ class Profile &lt; ApplicationRecord
526 521 ).order('articles.published_at desc, articles.id desc')
527 522 end
528 523  
529   - def to_liquid
530   - HashWithIndifferentAccess.new :name => name, :identifier => identifier
531   - end
532   -
533 524 class << self
534 525  
535 526 # finds a profile by its identifier. This method is a shortcut to
... ... @@ -653,13 +644,6 @@ private :generate_url, :url_options
653 644 self.articles.tagged_with(tag)
654 645 end
655 646  
656   - # Tells whether a specified profile has members or nor.
657   - #
658   - # On this class, returns <tt>false</tt> by default.
659   - def has_members?
660   - false
661   - end
662   -
663 647 after_create :insert_default_article_set
664 648 def insert_default_article_set
665 649 if template
... ... @@ -674,23 +658,6 @@ private :generate_url, :url_options
674 658 end
675 659 end
676 660  
677   - # Override this method in subclasses of Profile to create a default article
678   - # set upon creation. Note that this method will be called *only* if there is
679   - # no template for the type of profile (i.e. if the template was removed or in
680   - # the creation of the template itself).
681   - #
682   - # This method must return an array of pre-populated articles, which will be
683   - # associated to the profile before being saved. Example:
684   - #
685   - # def default_set_of_articles
686   - # [Blog.new(:name => 'Blog'), Gallery.new(:name => 'Gallery')]
687   - # end
688   - #
689   - # By default, this method returns an empty array.
690   - def default_set_of_articles
691   - []
692   - end
693   -
694 661 def copy_articles_from other
695 662 return false if other.top_level_articles.empty?
696 663 other.top_level_articles.each do |a|
... ... @@ -891,14 +858,6 @@ private :generate_url, :url_options
891 858 articles.galleries
892 859 end
893 860  
894   - def blocks_to_expire_cache
895   - []
896   - end
897   -
898   - def cache_keys(params = {})
899   - []
900   - end
901   -
902 861 validate :image_valid
903 862  
904 863 def image_valid
... ... @@ -935,16 +894,6 @@ private :generate_url, :url_options
935 894 self.update_attribute(:layout_template, template)
936 895 end
937 896  
938   - def members_cache_key(params = {})
939   - page = params[:npage] || '1'
940   - sort = (params[:sort] == 'desc') ? params[:sort] : 'asc'
941   - cache_key + '-members-page-' + page + '-' + sort
942   - end
943   -
944   - def more_recent_label
945   - _("Since: ")
946   - end
947   -
948 897 def recent_actions
949 898 tracked_actions.recent
950 899 end
... ... @@ -999,18 +948,6 @@ private :generate_url, :url_options
999 948 end
1000 949 end
1001 950  
1002   - def control_panel_settings_button
1003   - {:title => _('Edit Profile'), :icon => 'edit-profile'}
1004   - end
1005   -
1006   - def self.identification
1007   - name
1008   - end
1009   -
1010   - def exclude_verbs_on_activities
1011   - %w[]
1012   - end
1013   -
1014 951 # Customize in subclasses
1015 952 def activities
1016 953 self.profile_activities.includes(:activity).order('updated_at DESC')
... ... @@ -1045,10 +982,6 @@ private :generate_url, :url_options
1045 982 self.active_fields
1046 983 end
1047 984  
1048   - def control_panel_settings_button
1049   - {:title => _('Profile Info and settings'), :icon => 'edit-profile'}
1050   - end
1051   -
1052 985 def followed_by?(person)
1053 986 person.is_member_of?(self)
1054 987 end
... ... @@ -1076,8 +1009,4 @@ private :generate_url, :url_options
1076 1009 suggestion.disable if suggestion
1077 1010 end
1078 1011  
1079   - def allow_invitation_from(person)
1080   - false
1081   - end
1082   -
1083 1012 end
... ...
test/unit/external_person_test.rb
1 1 # encoding: UTF-8
2 2 require_relative "../test_helper"
3 3  
4   -class PersonTest < ActiveSupport::TestCase
  4 +class ExternalPersonTest < ActiveSupport::TestCase
5 5 fixtures :environments
6 6  
7 7 def setup
... ... @@ -101,4 +101,15 @@ class PersonTest &lt; ActiveSupport::TestCase
101 101  
102 102 should 'profile image has public filename and mimetype' do
103 103 end
  104 +
  105 + should 'respond to all instance methods in Profile' do
  106 + methods = Profile.public_instance_methods(false)
  107 + methods.each do |method|
  108 + # We test if ExternalPerson responds to same methods as Profile, but we
  109 + # skip methods generated by plugins, libs and validations, which are
  110 + # usually only used internally
  111 + assert_respond_to ExternalPerson.new, method.to_sym unless method =~ /type_name|^autosave_.*|^after_.*|^before_.*|validate_.*|^attribute_.*|.*_?tags?_?.*|^custom_value.*|^custom_context.*|^xss.*|bar/
  112 + end
  113 + end
  114 +
104 115 end
... ...