Commit 961148fb74e53842f028b9485cfb210ec5d4562f
Exists in
master
and in
28 other branches
Merge branch 'stable'
Conflicts: po/pt_BR/noosfero.po
Showing
34 changed files
with
266 additions
and
107 deletions
Show diff stats
app/controllers/my_profile/profile_editor_controller.rb
@@ -64,7 +64,7 @@ class ProfileEditorController < MyProfileController | @@ -64,7 +64,7 @@ class ProfileEditorController < MyProfileController | ||
64 | def header_footer | 64 | def header_footer |
65 | @no_design_blocks = true | 65 | @no_design_blocks = true |
66 | if request.post? | 66 | if request.post? |
67 | - @profile.update_attributes!(:custom_footer => params[:custom_footer], :custom_header => params[:custom_header]) | 67 | + @profile.update_header_and_footer(params[:custom_header], params[:custom_footer]) |
68 | redirect_to :action => 'index' | 68 | redirect_to :action => 'index' |
69 | else | 69 | else |
70 | @header = boxes_holder.custom_header | 70 | @header = boxes_holder.custom_header |
app/controllers/my_profile/themes_controller.rb
@@ -4,7 +4,7 @@ class ThemesController < MyProfileController | @@ -4,7 +4,7 @@ class ThemesController < MyProfileController | ||
4 | no_design_blocks | 4 | no_design_blocks |
5 | 5 | ||
6 | def set | 6 | def set |
7 | - profile.update_attributes!(:theme => params[:id]) | 7 | + profile.update_theme(params[:id]) |
8 | redirect_to :action => 'index' | 8 | redirect_to :action => 'index' |
9 | end | 9 | end |
10 | 10 | ||
@@ -79,8 +79,7 @@ class ThemesController < MyProfileController | @@ -79,8 +79,7 @@ class ThemesController < MyProfileController | ||
79 | end | 79 | end |
80 | 80 | ||
81 | def set_layout_template | 81 | def set_layout_template |
82 | - profile.layout_template = params[:id] | ||
83 | - profile.save! | 82 | + profile.update_layout_template(params[:id]) |
84 | redirect_to :action => 'index' | 83 | redirect_to :action => 'index' |
85 | end | 84 | end |
86 | 85 |
app/helpers/application_helper.rb
@@ -311,22 +311,35 @@ module ApplicationHelper | @@ -311,22 +311,35 @@ module ApplicationHelper | ||
311 | end | 311 | end |
312 | 312 | ||
313 | def current_theme | 313 | def current_theme |
314 | - return session[:theme] if (session[:theme]) | ||
315 | - | ||
316 | - # utility for developers: set the theme to 'random' in development mode and | ||
317 | - # you will get a different theme every request. This is interesting for | ||
318 | - # testing | ||
319 | - if ENV['RAILS_ENV'] == 'development' && @environment.theme == 'random' | ||
320 | - @theme ||= Dir.glob('public/designs/themes/*').map { |f| File.basename(f) }.rand | ||
321 | - return @theme | ||
322 | - end | ||
323 | - | ||
324 | - p = profile | ||
325 | - if p | ||
326 | - p.theme | ||
327 | - else | ||
328 | - @environment.theme | ||
329 | - end | 314 | + @current_theme ||= |
315 | + begin | ||
316 | + if (session[:theme]) | ||
317 | + session[:theme] | ||
318 | + else | ||
319 | + # utility for developers: set the theme to 'random' in development mode and | ||
320 | + # you will get a different theme every request. This is interesting for | ||
321 | + # testing | ||
322 | + if ENV['RAILS_ENV'] == 'development' && environment.theme == 'random' | ||
323 | + @random_theme ||= Dir.glob('public/designs/themes/*').map { |f| File.basename(f) }.rand | ||
324 | + @random_theme | ||
325 | + else | ||
326 | + if profile | ||
327 | + profile.theme | ||
328 | + elsif environment | ||
329 | + environment.theme | ||
330 | + else | ||
331 | + if logger | ||
332 | + logger.warn("No environment found. This is weird.") | ||
333 | + logger.warn("Request environment: %s" % request.env.inspect) | ||
334 | + logger.warn("Request parameters: %s" % params.inspect) | ||
335 | + end | ||
336 | + | ||
337 | + # could not determine the theme, so return the default one | ||
338 | + 'default' | ||
339 | + end | ||
340 | + end | ||
341 | + end | ||
342 | + end | ||
330 | end | 343 | end |
331 | 344 | ||
332 | def theme_include(template) | 345 | def theme_include(template) |
app/helpers/sweeper_helper.rb
@@ -43,4 +43,7 @@ module SweeperHelper | @@ -43,4 +43,7 @@ module SweeperHelper | ||
43 | blocks.map(&:cache_keys).each{|ck|expire_timeout_fragment(ck)} | 43 | blocks.map(&:cache_keys).each{|ck|expire_timeout_fragment(ck)} |
44 | end | 44 | end |
45 | 45 | ||
46 | + def expire_profile_index(profile) | ||
47 | + expire_timeout_fragment(profile.relationships_cache_key) | ||
48 | + end | ||
46 | end | 49 | end |
app/models/article.rb
@@ -214,6 +214,13 @@ class Article < ActiveRecord::Base | @@ -214,6 +214,13 @@ class Article < ActiveRecord::Base | ||
214 | end | 214 | end |
215 | end | 215 | end |
216 | 216 | ||
217 | + def allow_post_content?(logged_person = nil) | ||
218 | + if logged_person && logged_person.has_permission?('post_content', profile) | ||
219 | + return true | ||
220 | + end | ||
221 | + false | ||
222 | + end | ||
223 | + | ||
217 | def comments_updated | 224 | def comments_updated |
218 | ferret_update | 225 | ferret_update |
219 | end | 226 | end |
@@ -266,8 +273,10 @@ class Article < ActiveRecord::Base | @@ -266,8 +273,10 @@ class Article < ActiveRecord::Base | ||
266 | profile | 273 | profile |
267 | end | 274 | end |
268 | 275 | ||
269 | - def cache_key(params = {}) | ||
270 | - "article-id-#{id}" + | 276 | + alias :active_record_cache_key :cache_key |
277 | + def cache_key(params = {}, the_profile = nil) | ||
278 | + active_record_cache_key + | ||
279 | + (allow_post_content?(the_profile) ? "-owner" : '') + | ||
271 | (params[:npage] ? "-npage-#{params[:npage]}" : '') + | 280 | (params[:npage] ? "-npage-#{params[:npage]}" : '') + |
272 | (params[:year] ? "-year-#{params[:year]}" : '') + | 281 | (params[:year] ? "-year-#{params[:year]}" : '') + |
273 | (params[:month] ? "-month-#{params[:month]}" : '') | 282 | (params[:month] ? "-month-#{params[:month]}" : '') |
app/models/feed_reader_block.rb
@@ -28,7 +28,7 @@ class FeedReaderBlock < Block | @@ -28,7 +28,7 @@ class FeedReaderBlock < Block | ||
28 | 28 | ||
29 | def formatted_feed_content | 29 | def formatted_feed_content |
30 | return "<ul>\n" + | 30 | return "<ul>\n" + |
31 | - self.feed_items.map{ |item| "<li><a href='#{item[:link]}'>#{item[:title]}</a></li>" }.join("\n") + | 31 | + self.feed_items[0..(limit-1)].map{ |item| "<li><a href='#{item[:link]}'>#{item[:title]}</a></li>" }.join("\n") + |
32 | "</ul>" | 32 | "</ul>" |
33 | end | 33 | end |
34 | 34 |
app/models/person.rb
@@ -279,4 +279,8 @@ class Person < Profile | @@ -279,4 +279,8 @@ class Person < Profile | ||
279 | page = params[:npage] || '1' | 279 | page = params[:npage] || '1' |
280 | identifier + '-manage-friends-page-' + page | 280 | identifier + '-manage-friends-page-' + page |
281 | end | 281 | end |
282 | + | ||
283 | + def relationships_cache_key | ||
284 | + identifier + '-profile-relationships' | ||
285 | + end | ||
282 | end | 286 | end |
app/models/profile.rb
@@ -643,4 +643,18 @@ class Profile < ActiveRecord::Base | @@ -643,4 +643,18 @@ class Profile < ActiveRecord::Base | ||
643 | ProfileSweeper.new().after_create(profile) | 643 | ProfileSweeper.new().after_create(profile) |
644 | end | 644 | end |
645 | 645 | ||
646 | + def update_header_and_footer(header, footer) | ||
647 | + self.custom_header = header | ||
648 | + self.custom_footer = footer | ||
649 | + self.save(false) | ||
650 | + end | ||
651 | + | ||
652 | + def update_theme(theme) | ||
653 | + self.update_attribute(:theme, theme) | ||
654 | + end | ||
655 | + | ||
656 | + def update_layout_template(template) | ||
657 | + self.update_attribute(:layout_template, template) | ||
658 | + end | ||
659 | + | ||
646 | end | 660 | end |
app/sweepers/article_sweeper.rb
@@ -13,7 +13,11 @@ class ArticleSweeper < ActiveRecord::Observer | @@ -13,7 +13,11 @@ class ArticleSweeper < ActiveRecord::Observer | ||
13 | protected | 13 | protected |
14 | 14 | ||
15 | def expire_caches(article) | 15 | def expire_caches(article) |
16 | - article.hierarchy.each {|a| expire_fragment(a.cache_key) } | 16 | + article.hierarchy.each do |a| |
17 | + if a != article | ||
18 | + a.touch | ||
19 | + end | ||
20 | + end | ||
17 | blocks = (article.profile.blocks + article.profile.environment.blocks).select{|b|[RecentDocumentsBlock, BlogArchivesBlock].any?{|c| b.kind_of?(c)}} | 21 | blocks = (article.profile.blocks + article.profile.environment.blocks).select{|b|[RecentDocumentsBlock, BlogArchivesBlock].any?{|c| b.kind_of?(c)}} |
18 | blocks.map(&:cache_keys).each{|ck|expire_timeout_fragment(ck)} | 22 | blocks.map(&:cache_keys).each{|ck|expire_timeout_fragment(ck)} |
19 | env = article.profile.environment | 23 | env = article.profile.environment |
app/sweepers/profile_sweeper.rb
@@ -17,8 +17,11 @@ protected | @@ -17,8 +17,11 @@ protected | ||
17 | profile.members.each do |member| | 17 | profile.members.each do |member| |
18 | expire_communities(member) if profile.community? | 18 | expire_communities(member) if profile.community? |
19 | expire_enterprises(member) if profile.enterprise? | 19 | expire_enterprises(member) if profile.enterprise? |
20 | + expire_profile_index(member) if profile.enterprise? | ||
20 | end | 21 | end |
21 | 22 | ||
23 | + expire_profile_index(profile) if profile.person? | ||
24 | + | ||
22 | profile.blocks.each do |block| | 25 | profile.blocks.each do |block| |
23 | expire_timeout_fragment(block.cache_keys) | 26 | expire_timeout_fragment(block.cache_keys) |
24 | end | 27 | end |
app/views/blocks/my_network/person.rhtml
@@ -3,8 +3,8 @@ | @@ -3,8 +3,8 @@ | ||
3 | content_tag('b', owner.articles.count), owner.public_profile_url.merge(:action => 'sitemap') ) %></li> | 3 | content_tag('b', owner.articles.count), owner.public_profile_url.merge(:action => 'sitemap') ) %></li> |
4 | <li><%= link_to(n__('One friend', '%s friends', owner.friends.count) % | 4 | <li><%= link_to(n__('One friend', '%s friends', owner.friends.count) % |
5 | content_tag('b', owner.friends.count), owner.public_profile_url.merge(:action => 'friends')) %></li> | 5 | content_tag('b', owner.friends.count), owner.public_profile_url.merge(:action => 'friends')) %></li> |
6 | - <li><%= link_to(n__('One community', '%s communities', owner.communities.size) % | ||
7 | - content_tag('b', owner.communities.size), owner.public_profile_url.merge(:action => 'communities')) %></li> | 6 | + <li><%= link_to(n__('One community', '%{num} communities', owner.communities.size) % |
7 | + {:num => content_tag('b', owner.communities.size)}, owner.public_profile_url.merge(:action => 'communities')) %></li> | ||
8 | <li><%= link_to(n_('One tag', '%s tags', owner.article_tags.size) % | 8 | <li><%= link_to(n_('One tag', '%s tags', owner.article_tags.size) % |
9 | content_tag('b', owner.article_tags.size), owner.public_profile_url.merge(:action => 'tags')) %></li> | 9 | content_tag('b', owner.article_tags.size), owner.public_profile_url.merge(:action => 'tags')) %></li> |
10 | </ul> | 10 | </ul> |
app/views/content_viewer/view_page.rhtml
@@ -23,7 +23,7 @@ | @@ -23,7 +23,7 @@ | ||
23 | 23 | ||
24 | <div> | 24 | <div> |
25 | <%= article_title(@page, :no_link => true) %> | 25 | <%= article_title(@page, :no_link => true) %> |
26 | - <% if logged_in? && current_user.person.has_permission?('post_content', profile) %> | 26 | + <% if @page.allow_post_content?(user) %> |
27 | <div id="article-actions"> | 27 | <div id="article-actions"> |
28 | <% unless @page.blog? %> | 28 | <% unless @page.blog? %> |
29 | <%= link_to content_tag( 'span', label_for_edit_article(@page) ), | 29 | <%= link_to content_tag( 'span', label_for_edit_article(@page) ), |
@@ -80,7 +80,7 @@ | @@ -80,7 +80,7 @@ | ||
80 | </div> | 80 | </div> |
81 | <% end %> | 81 | <% end %> |
82 | 82 | ||
83 | -<% cache(@page.cache_key(params)) do %> | 83 | +<% cache(@page.cache_key(params, user)) do %> |
84 | <div class="<%="article-body article-body-" + @page.css_class_name %>"> | 84 | <div class="<%="article-body article-body-" + @page.css_class_name %>"> |
85 | <%= article_to_html(@page) %> | 85 | <%= article_to_html(@page) %> |
86 | <br style="clear:both" /> | 86 | <br style="clear:both" /> |
app/views/layouts/application-ng.rhtml
@@ -5,6 +5,7 @@ | @@ -5,6 +5,7 @@ | ||
5 | <%= meta_tags_for_article(@page) %> | 5 | <%= meta_tags_for_article(@page) %> |
6 | <!--<meta http-equiv="refresh" content="1"/>--> | 6 | <!--<meta http-equiv="refresh" content="1"/>--> |
7 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> | 7 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> |
8 | + <meta name="description" content="<%= @environment.name %>" /> | ||
8 | <link rel="shortcut icon" href="<%= '/designs/themes/' + current_theme + '/imgs/favicon.ico' %>" type="image/x-icon" /> | 9 | <link rel="shortcut icon" href="<%= '/designs/themes/' + current_theme + '/imgs/favicon.ico' %>" type="image/x-icon" /> |
9 | <%= noosfero_javascript %> | 10 | <%= noosfero_javascript %> |
10 | <%= import_blocks_stylesheets %> | 11 | <%= import_blocks_stylesheets %> |
app/views/layouts/application.rhtml
@@ -3,7 +3,7 @@ | @@ -3,7 +3,7 @@ | ||
3 | <head> | 3 | <head> |
4 | <title><%= page_title %></title> | 4 | <title><%= page_title %></title> |
5 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> | 5 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> |
6 | - <meta name="description" content="FIXME: Descriptions of Noosfero" /> | 6 | + <meta name="description" content="<%= @environment.name %>" /> |
7 | <meta name="keywords" content="Noosfero, Community, Open Source" /> | 7 | <meta name="keywords" content="Noosfero, Community, Open Source" /> |
8 | <link rel="shortcut icon" href="<%= '/designs/themes/' + current_theme + '/images/favicon.ico' %>" type="image/x-icon" /> | 8 | <link rel="shortcut icon" href="<%= '/designs/themes/' + current_theme + '/images/favicon.ico' %>" type="image/x-icon" /> |
9 | <!-- ok --><%= meta_tags_for_article(@page) %> | 9 | <!-- ok --><%= meta_tags_for_article(@page) %> |
app/views/profile/_person.rhtml
@@ -16,7 +16,7 @@ | @@ -16,7 +16,7 @@ | ||
16 | <%= display_field(_('e-Mail:'), profile, :email, true) { |email| link_to_email(email) } %> | 16 | <%= display_field(_('e-Mail:'), profile, :email, true) { |email| link_to_email(email) } %> |
17 | <% end %> | 17 | <% end %> |
18 | 18 | ||
19 | -<% cache_timeout(profile.identifier + '-profile-relationships', 4.hours.from_now) do %> | 19 | +<% cache_timeout(profile.relationships_cache_key, 4.hours.from_now) do %> |
20 | <% if !(profile.organization.blank? && profile.organization_website.blank?) && (profile.active_fields.include?('organization') || profile.active_fields.include?('organization_website')) %> | 20 | <% if !(profile.organization.blank? && profile.organization_website.blank?) && (profile.active_fields.include?('organization') || profile.active_fields.include?('organization_website')) %> |
21 | <tr> | 21 | <tr> |
22 | <th colspan='2'><%= _('Work')%></th> | 22 | <th colspan='2'><%= _('Work')%></th> |
app/views/profile_editor/_organization.rhtml
@@ -63,23 +63,24 @@ | @@ -63,23 +63,24 @@ | ||
63 | <%= labelled_check_box(_('Enable "contact us"'), 'profile_data[enable_contact_us]', "1", @profile.enable_contact_us) if @profile.enterprise? %> | 63 | <%= labelled_check_box(_('Enable "contact us"'), 'profile_data[enable_contact_us]', "1", @profile.enable_contact_us) if @profile.enterprise? %> |
64 | 64 | ||
65 | <h1><%= _('Moderation options') %></h1> | 65 | <h1><%= _('Moderation options') %></h1> |
66 | - <div style='margin-bottom: 1em'> | ||
67 | - <%= _('New members must be approved:')%> | ||
68 | - </div> | ||
69 | - <div style='margin-bottom: 0.5em'> | ||
70 | - <%= radio_button 'profile_data', 'closed', 'true', :style => 'float: left' %> | ||
71 | - <div style='margin-left: 30px'> | ||
72 | - <%= _('<strong>Before</strong> joining this group (a moderator has to accept the member in pending request before member can access the intranet and/or the website).') %> | 66 | + <% if profile.community? %> |
67 | + <div style='margin-bottom: 1em'> | ||
68 | + <%= _('New members must be approved:')%> | ||
73 | </div> | 69 | </div> |
74 | - </div> | ||
75 | - <div> | ||
76 | - <%= radio_button 'profile_data', 'closed', 'false', :style => 'float: left' %> | ||
77 | - <div style='margin-left: 30px'> | ||
78 | - <%= _('<strong>After</strong> joining this group (a moderator can always desactivate access for users later).') %> | 70 | + <div style='margin-bottom: 0.5em'> |
71 | + <%= radio_button 'profile_data', 'closed', 'true', :style => 'float: left' %> | ||
72 | + <div style='margin-left: 30px'> | ||
73 | + <%= _('<strong>Before</strong> joining this group (a moderator has to accept the member in pending request before member can access the intranet and/or the website).') %> | ||
74 | + </div> | ||
79 | </div> | 75 | </div> |
80 | - </div> | ||
81 | - | ||
82 | - <br> | 76 | + <div> |
77 | + <%= radio_button 'profile_data', 'closed', 'false', :style => 'float: left' %> | ||
78 | + <div style='margin-left: 30px'> | ||
79 | + <%= _('<strong>After</strong> joining this group (a moderator can always desactivate access for users later).') %> | ||
80 | + </div> | ||
81 | + </div> | ||
82 | + <br> | ||
83 | + <% end %> | ||
83 | <div style='margin-bottom: 1em'> | 84 | <div style='margin-bottom: 1em'> |
84 | <%= _('New articles posted by members of this group must be approved:')%> | 85 | <%= _('New articles posted by members of this group must be approved:')%> |
85 | 86 |
app/views/profile_editor/_person_form.rhtml
@@ -15,7 +15,7 @@ | @@ -15,7 +15,7 @@ | ||
15 | <%= optional_field(@person, 'cell_phone', f.text_field(:cell_phone)) %> | 15 | <%= optional_field(@person, 'cell_phone', f.text_field(:cell_phone)) %> |
16 | <%= optional_field(@person, 'comercial_phone', f.text_field(:comercial_phone)) %> | 16 | <%= optional_field(@person, 'comercial_phone', f.text_field(:comercial_phone)) %> |
17 | <%= optional_field(@person, 'sex', f.radio_group(:profile_data, :sex, [ ['male',_('Male')], ['female',_('Female')] ])) %> | 17 | <%= optional_field(@person, 'sex', f.radio_group(:profile_data, :sex, [ ['male',_('Male')], ['female',_('Female')] ])) %> |
18 | -<%= optional_field(@person, 'birth_date', labelled_form_field(_('Birth date'), '<div class="select-birth-date">' + pick_date(:profile_data, :birth_date, {:start_year => (Date.today.year - 100), :end_year => (Date.today.year - 10)}) + '</div>')) %> | 18 | +<%= optional_field(@person, 'birth_date', labelled_form_field(_('Birth date'), '<div class="select-birth-date">' + pick_date(:profile_data, :birth_date, {:start_year => (Date.today.year - 100), :end_year => (Date.today.year - 5)}) + '</div>')) %> |
19 | <%= optional_field(@person, 'nationality', f.text_field(:nationality)) %> | 19 | <%= optional_field(@person, 'nationality', f.text_field(:nationality)) %> |
20 | <%= optional_field(@person, 'country', select_country(_('Country'), 'profile_data', 'country', {:class => 'type-select'})) %> | 20 | <%= optional_field(@person, 'country', select_country(_('Country'), 'profile_data', 'country', {:class => 'type-select'})) %> |
21 | <%= optional_field(@person, 'state', f.text_field(:state)) %> | 21 | <%= optional_field(@person, 'state', f.text_field(:state)) %> |
app/views/profile_editor/edit.rhtml
@@ -9,7 +9,7 @@ | @@ -9,7 +9,7 @@ | ||
9 | <div id="profile_change_picture"> | 9 | <div id="profile_change_picture"> |
10 | <h2><%= _('Change picture') %></h2> | 10 | <h2><%= _('Change picture') %></h2> |
11 | <% f.fields_for :image_builder, @profile.image do |i| %> | 11 | <% f.fields_for :image_builder, @profile.image do |i| %> |
12 | - <%= file_field_or_thumbnail(_('Image:'), @profile.image, i) %><%= _("(max size %s)")% Image.max_size.to_humanreadable %> | 12 | + <%= file_field_or_thumbnail(_('Image:'), @profile.image, i) %><%= _("Max size: %s (.jpg, .gif, .png)")% Image.max_size.to_humanreadable %> |
13 | <% end %> | 13 | <% end %> |
14 | </div> | 14 | </div> |
15 | 15 |
app/views/shared/tiny_mce.rhtml
@@ -24,7 +24,7 @@ tinyMCE.init({ | @@ -24,7 +24,7 @@ tinyMCE.init({ | ||
24 | apply_source_formatting : true, | 24 | apply_source_formatting : true, |
25 | content_css: '/stylesheets/tinymce.css', | 25 | content_css: '/stylesheets/tinymce.css', |
26 | language: <%= tinymce_language.inspect %>, | 26 | language: <%= tinymce_language.inspect %>, |
27 | - cleanup_callback : "customCleanup" | 27 | + entity_encoding: 'raw' |
28 | }); | 28 | }); |
29 | 29 | ||
30 | function convertWord(type, content) { | 30 | function convertWord(type, content) { |
@@ -43,16 +43,4 @@ function convertWord(type, content) { | @@ -43,16 +43,4 @@ function convertWord(type, content) { | ||
43 | return content; | 43 | return content; |
44 | } | 44 | } |
45 | 45 | ||
46 | -function customCleanup(type, value) { | ||
47 | - switch (type) { | ||
48 | - case "get_from_editor": | ||
49 | - value = value.replace(/&amp;/g,"&"); | ||
50 | - break; | ||
51 | - case "insert_to_editor": | ||
52 | - value = value.replace(/&amp;/g,"&"); | ||
53 | - break; | ||
54 | - } | ||
55 | - return value; | ||
56 | -} | ||
57 | - | ||
58 | </script> | 46 | </script> |
@@ -0,0 +1,10 @@ | @@ -0,0 +1,10 @@ | ||
1 | +class AddUpdatedAtToProfiles < ActiveRecord::Migration | ||
2 | + def self.up | ||
3 | + add_column :profiles, :updated_at, :datetime | ||
4 | + execute 'update profiles set updated_at = created_at' | ||
5 | + end | ||
6 | + | ||
7 | + def self.down | ||
8 | + remove_column :profiles, :updated_at | ||
9 | + end | ||
10 | +end |
db/schema.rb
@@ -89,8 +89,8 @@ ActiveRecord::Schema.define(:version => 69) do | @@ -89,8 +89,8 @@ ActiveRecord::Schema.define(:version => 69) do | ||
89 | t.boolean "virtual", :default => false | 89 | t.boolean "virtual", :default => false |
90 | end | 90 | end |
91 | 91 | ||
92 | - add_index "articles_categories", ["article_id"], :name => "index_articles_categories_on_article_id" | ||
93 | add_index "articles_categories", ["category_id"], :name => "index_articles_categories_on_category_id" | 92 | add_index "articles_categories", ["category_id"], :name => "index_articles_categories_on_category_id" |
93 | + add_index "articles_categories", ["article_id"], :name => "index_articles_categories_on_article_id" | ||
94 | 94 | ||
95 | create_table "blocks", :force => true do |t| | 95 | create_table "blocks", :force => true do |t| |
96 | t.string "title" | 96 | t.string "title" |
@@ -131,8 +131,8 @@ ActiveRecord::Schema.define(:version => 69) do | @@ -131,8 +131,8 @@ ActiveRecord::Schema.define(:version => 69) do | ||
131 | t.boolean "virtual", :default => false | 131 | t.boolean "virtual", :default => false |
132 | end | 132 | end |
133 | 133 | ||
134 | - add_index "categories_profiles", ["profile_id"], :name => "index_categories_profiles_on_profile_id" | ||
135 | add_index "categories_profiles", ["category_id"], :name => "index_categories_profiles_on_category_id" | 134 | add_index "categories_profiles", ["category_id"], :name => "index_categories_profiles_on_category_id" |
135 | + add_index "categories_profiles", ["profile_id"], :name => "index_categories_profiles_on_profile_id" | ||
136 | 136 | ||
137 | create_table "comments", :force => true do |t| | 137 | create_table "comments", :force => true do |t| |
138 | t.string "title" | 138 | t.string "title" |
@@ -211,8 +211,8 @@ ActiveRecord::Schema.define(:version => 69) do | @@ -211,8 +211,8 @@ ActiveRecord::Schema.define(:version => 69) do | ||
211 | t.datetime "updated_at" | 211 | t.datetime "updated_at" |
212 | end | 212 | end |
213 | 213 | ||
214 | - add_index "product_categorizations", ["product_id"], :name => "index_product_categorizations_on_product_id" | ||
215 | add_index "product_categorizations", ["category_id"], :name => "index_product_categorizations_on_category_id" | 214 | add_index "product_categorizations", ["category_id"], :name => "index_product_categorizations_on_category_id" |
215 | + add_index "product_categorizations", ["product_id"], :name => "index_product_categorizations_on_product_id" | ||
216 | 216 | ||
217 | create_table "products", :force => true do |t| | 217 | create_table "products", :force => true do |t| |
218 | t.integer "enterprise_id" | 218 | t.integer "enterprise_id" |
@@ -284,10 +284,6 @@ ActiveRecord::Schema.define(:version => 69) do | @@ -284,10 +284,6 @@ ActiveRecord::Schema.define(:version => 69) do | ||
284 | t.integer "environment_id" | 284 | t.integer "environment_id" |
285 | end | 285 | end |
286 | 286 | ||
287 | - create_table "schema_info", :id => false, :force => true do |t| | ||
288 | - t.integer "version" | ||
289 | - end | ||
290 | - | ||
291 | create_table "taggings", :force => true do |t| | 287 | create_table "taggings", :force => true do |t| |
292 | t.integer "tag_id" | 288 | t.integer "tag_id" |
293 | t.integer "taggable_id" | 289 | t.integer "taggable_id" |
@@ -295,8 +291,8 @@ ActiveRecord::Schema.define(:version => 69) do | @@ -295,8 +291,8 @@ ActiveRecord::Schema.define(:version => 69) do | ||
295 | t.datetime "created_at" | 291 | t.datetime "created_at" |
296 | end | 292 | end |
297 | 293 | ||
298 | - add_index "taggings", ["tag_id"], :name => "index_taggings_on_tag_id" | ||
299 | add_index "taggings", ["taggable_id", "taggable_type"], :name => "index_taggings_on_taggable_id_and_taggable_type" | 294 | add_index "taggings", ["taggable_id", "taggable_type"], :name => "index_taggings_on_taggable_id_and_taggable_type" |
295 | + add_index "taggings", ["tag_id"], :name => "index_taggings_on_tag_id" | ||
300 | 296 | ||
301 | create_table "tags", :force => true do |t| | 297 | create_table "tags", :force => true do |t| |
302 | t.string "name" | 298 | t.string "name" |
lib/noosfero.rb
1 | module Noosfero | 1 | module Noosfero |
2 | PROJECT = 'noosfero' | 2 | PROJECT = 'noosfero' |
3 | - VERSION = '0.19.2' | 3 | + VERSION = '0.19.3' |
4 | SVN_ROOT = 'https://svn.colivre.coop.br/svn/noosfero' | 4 | SVN_ROOT = 'https://svn.colivre.coop.br/svn/noosfero' |
5 | 5 | ||
6 | def self.pattern_for_controllers_in_directory(dir) | 6 | def self.pattern_for_controllers_in_directory(dir) |
po/pt_BR/noosfero.po
@@ -13,7 +13,7 @@ msgid "" | @@ -13,7 +13,7 @@ msgid "" | ||
13 | msgstr "" | 13 | msgstr "" |
14 | "Project-Id-Version: noosfero 0.19.0\n" | 14 | "Project-Id-Version: noosfero 0.19.0\n" |
15 | "POT-Creation-Date: 2009-08-04 14:28-0300\n" | 15 | "POT-Creation-Date: 2009-08-04 14:28-0300\n" |
16 | -"PO-Revision-Date: 2009-08-13 09:20-0300\n" | 16 | +"PO-Revision-Date: 2009-08-21 20:42-0300\n" |
17 | "Last-Translator: Joenio Costa <joenio@colivre.coop.br>\n" | 17 | "Last-Translator: Joenio Costa <joenio@colivre.coop.br>\n" |
18 | "Language-Team: LANGUAGE <LL@li.org>\n" | 18 | "Language-Team: LANGUAGE <LL@li.org>\n" |
19 | "MIME-Version: 1.0\n" | 19 | "MIME-Version: 1.0\n" |
@@ -6671,3 +6671,6 @@ msgstr "" | @@ -6671,3 +6671,6 @@ msgstr "" | ||
6671 | 6671 | ||
6672 | msgid "You must type at least 3 characters" | 6672 | msgid "You must type at least 3 characters" |
6673 | msgstr "Você precisa digitar pelo menos 3 caracteres" | 6673 | msgstr "Você precisa digitar pelo menos 3 caracteres" |
6674 | + | ||
6675 | +msgid "Max size: %s (.jpg, .gif, .png)" | ||
6676 | +msgstr "Tamanho máximo: %s (.jpg, .gif, .png)" |
test/functional/application_controller_test.rb
@@ -427,4 +427,9 @@ class ApplicationControllerTest < Test::Unit::TestCase | @@ -427,4 +427,9 @@ class ApplicationControllerTest < Test::Unit::TestCase | ||
427 | assert_equal false, @controller.avoid_ssl | 427 | assert_equal false, @controller.avoid_ssl |
428 | end | 428 | end |
429 | 429 | ||
430 | + should 'diplay name of environment in description' do | ||
431 | + get :index | ||
432 | + assert_tag :tag => 'meta', :attributes => { :name => 'description', :content => assigns(:environment).name } | ||
433 | + end | ||
434 | + | ||
430 | end | 435 | end |
test/functional/profile_editor_controller_test.rb
@@ -302,31 +302,23 @@ class ProfileEditorControllerTest < Test::Unit::TestCase | @@ -302,31 +302,23 @@ class ProfileEditorControllerTest < Test::Unit::TestCase | ||
302 | assert_not_nil assigns(:profile).image | 302 | assert_not_nil assigns(:profile).image |
303 | end | 303 | end |
304 | 304 | ||
305 | - should 'display closed attribute for enterprise when it is set' do | ||
306 | - org = Enterprise.create!(:name => 'test org', :identifier => 'testorg', :contact_person => 'my contact', :closed => true, :environment => Environment.default) | 305 | + should 'display closed attribute for communities when it is set' do |
306 | + org = Community.create!(:name => 'test org', :identifier => 'testorg', :contact_person => 'my contact', :closed => true, :environment => Environment.default) | ||
307 | get :edit, :profile => 'testorg' | 307 | get :edit, :profile => 'testorg' |
308 | 308 | ||
309 | assert_tag :tag => 'input', :attributes => { :type => 'radio', :name => 'profile_data[closed]', :value => 'true', :checked => 'checked' } | 309 | assert_tag :tag => 'input', :attributes => { :type => 'radio', :name => 'profile_data[closed]', :value => 'true', :checked => 'checked' } |
310 | assert_no_tag :tag => 'input', :attributes => { :type => 'radio', :name => 'profile_data[closed]', :value => 'false', :checked => 'checked' } | 310 | assert_no_tag :tag => 'input', :attributes => { :type => 'radio', :name => 'profile_data[closed]', :value => 'false', :checked => 'checked' } |
311 | end | 311 | end |
312 | 312 | ||
313 | - should 'display closed attribute for organizations when it is set' do | ||
314 | - org = Organization.create!(:name => 'test org', :identifier => 'testorg', :contact_person => 'my contact', :closed => true, :environment => Environment.default) | ||
315 | - get :edit, :profile => 'testorg' | ||
316 | - | ||
317 | - assert_tag :tag => 'input', :attributes => { :type => 'radio', :name => 'profile_data[closed]', :value => 'true', :checked => 'checked' } | ||
318 | - assert_no_tag :tag => 'input', :attributes => { :type => 'radio', :name => 'profile_data[closed]', :value => 'false', :checked => 'checked' } | ||
319 | - end | ||
320 | - | ||
321 | - should 'display closed attribute for organizations when it is set to false' do | ||
322 | - org = Organization.create!(:name => 'test org', :identifier => 'testorg', :contact_person => 'my contact', :closed => false) | 313 | + should 'display closed attribute for communities when it is set to false' do |
314 | + org = Community.create!(:name => 'test org', :identifier => 'testorg', :contact_person => 'my contact', :closed => false) | ||
323 | get :edit, :profile => 'testorg' | 315 | get :edit, :profile => 'testorg' |
324 | assert_no_tag :tag => 'input', :attributes => { :type => 'radio', :name => 'profile_data[closed]', :value => 'true', :checked => 'checked' } | 316 | assert_no_tag :tag => 'input', :attributes => { :type => 'radio', :name => 'profile_data[closed]', :value => 'true', :checked => 'checked' } |
325 | assert_tag :tag => 'input', :attributes => { :type => 'radio', :name => 'profile_data[closed]', :value => 'false', :checked => 'checked' } | 317 | assert_tag :tag => 'input', :attributes => { :type => 'radio', :name => 'profile_data[closed]', :value => 'false', :checked => 'checked' } |
326 | end | 318 | end |
327 | 319 | ||
328 | - should 'display closed attribute for organizations when it is set to nothing at all' do | ||
329 | - org = Organization.create!(:name => 'test org', :identifier => 'testorg', :contact_person => 'my contact', :closed => nil) | 320 | + should 'display closed attribute for communities when it is set to nothing at all' do |
321 | + org = Community.create!(:name => 'test org', :identifier => 'testorg', :contact_person => 'my contact', :closed => nil) | ||
330 | get :edit, :profile => 'testorg' | 322 | get :edit, :profile => 'testorg' |
331 | assert_no_tag :tag => 'input', :attributes => { :type => 'radio', :name => 'profile_data[closed]', :value => 'true', :checked => 'checked' } | 323 | assert_no_tag :tag => 'input', :attributes => { :type => 'radio', :name => 'profile_data[closed]', :value => 'true', :checked => 'checked' } |
332 | assert_tag :tag => 'input', :attributes => { :type => 'radio', :name => 'profile_data[closed]', :value => 'false', :checked => 'checked' } | 324 | assert_tag :tag => 'input', :attributes => { :type => 'radio', :name => 'profile_data[closed]', :value => 'false', :checked => 'checked' } |
@@ -348,6 +340,22 @@ class ProfileEditorControllerTest < Test::Unit::TestCase | @@ -348,6 +340,22 @@ class ProfileEditorControllerTest < Test::Unit::TestCase | ||
348 | assert !org.closed | 340 | assert !org.closed |
349 | end | 341 | end |
350 | 342 | ||
343 | + should 'not display option to close when it is enterprise' do | ||
344 | + org = Enterprise.create!(:name => 'test org', :identifier => 'testorg', :contact_person => 'my contact', :environment => Environment.default) | ||
345 | + get :edit, :profile => 'testorg' | ||
346 | + | ||
347 | + assert_no_tag :tag => 'input', :attributes => { :type => 'radio', :name => 'profile_data[closed]', :value => 'true' } | ||
348 | + assert_no_tag :tag => 'input', :attributes => { :type => 'radio', :name => 'profile_data[closed]', :value => 'false' } | ||
349 | + end | ||
350 | + | ||
351 | + should 'display option to close when it is community' do | ||
352 | + org = Community.create!(:name => 'test org', :identifier => 'testorg', :contact_person => 'my contact', :environment => Environment.default) | ||
353 | + get :edit, :profile => 'testorg' | ||
354 | + | ||
355 | + assert_tag :tag => 'input', :attributes => { :type => 'radio', :name => 'profile_data[closed]', :value => 'true' } | ||
356 | + assert_tag :tag => 'input', :attributes => { :type => 'radio', :name => 'profile_data[closed]', :value => 'false' } | ||
357 | + end | ||
358 | + | ||
351 | should 'display manage members options if has permission' do | 359 | should 'display manage members options if has permission' do |
352 | profile = Profile['ze'] | 360 | profile = Profile['ze'] |
353 | community = Community.create!(:name => 'test org', :identifier => 'testorg', :contact_person => 'my contact', :environment => Environment.default) | 361 | community = Community.create!(:name => 'test org', :identifier => 'testorg', :contact_person => 'my contact', :environment => Environment.default) |
@@ -526,6 +534,17 @@ class ProfileEditorControllerTest < Test::Unit::TestCase | @@ -526,6 +534,17 @@ class ProfileEditorControllerTest < Test::Unit::TestCase | ||
526 | assert_equal 'new footer', person.custom_footer | 534 | assert_equal 'new footer', person.custom_footer |
527 | end | 535 | end |
528 | 536 | ||
537 | + should 'save header and footer even if model is invalid' do | ||
538 | + person = create_user('designtestuser').person | ||
539 | + person.sex = nil; person.save! | ||
540 | + person.environment.custom_person_fields = {'sex' => {'required' => 'true', 'active' => 'true'} }; person.environment.save! | ||
541 | + | ||
542 | + post :header_footer, :profile => 'designtestuser', :custom_header => 'new header', :custom_footer => 'new footer' | ||
543 | + person = Person.find(person.id) | ||
544 | + assert_equal 'new header', person.custom_header | ||
545 | + assert_equal 'new footer', person.custom_footer | ||
546 | + end | ||
547 | + | ||
529 | should 'go back to editor after saving header/footer' do | 548 | should 'go back to editor after saving header/footer' do |
530 | person = create_user('designtestuser').person | 549 | person = create_user('designtestuser').person |
531 | post :header_footer, :profile => 'designtestuser', :custom_header => 'new header', :custom_footer => 'new footer' | 550 | post :header_footer, :profile => 'designtestuser', :custom_header => 'new header', :custom_footer => 'new footer' |
test/functional/themes_controller_test.rb
@@ -78,6 +78,16 @@ class ThemesControllerTest < Test::Unit::TestCase | @@ -78,6 +78,16 @@ class ThemesControllerTest < Test::Unit::TestCase | ||
78 | assert_equal 'onetheme', profile.theme | 78 | assert_equal 'onetheme', profile.theme |
79 | end | 79 | end |
80 | 80 | ||
81 | + should 'save selection of theme even if model is invalid' do | ||
82 | + @profile.sex = nil | ||
83 | + @profile.save! | ||
84 | + @profile.environment.custom_person_fields = { 'sex' => {'required' => 'true', 'active' => 'true'} }; @profile.environment.save! | ||
85 | + | ||
86 | + get :set, :profile => 'testinguser', :id => 'onetheme' | ||
87 | + profile = Profile.find(@profile.id) | ||
88 | + assert_equal 'onetheme', profile.theme | ||
89 | + end | ||
90 | + | ||
81 | should 'point back to control panel' do | 91 | should 'point back to control panel' do |
82 | get :index, :profile => 'testinguser' | 92 | get :index, :profile => 'testinguser' |
83 | assert_tag :tag => 'a', :attributes => { :href => '/myprofile/testinguser' }, :content => 'Back' | 93 | assert_tag :tag => 'a', :attributes => { :href => '/myprofile/testinguser' }, :content => 'Back' |
@@ -258,6 +268,17 @@ class ThemesControllerTest < Test::Unit::TestCase | @@ -258,6 +268,17 @@ class ThemesControllerTest < Test::Unit::TestCase | ||
258 | assert_redirected_to :action => 'index' | 268 | assert_redirected_to :action => 'index' |
259 | end | 269 | end |
260 | 270 | ||
271 | + should 'set template even if the model is invalid' do | ||
272 | + @profile.sex = nil | ||
273 | + @profile.save! | ||
274 | + @profile.environment.custom_person_fields = { 'sex' => {'required' => 'true', 'active' => 'true'} }; @profile.environment.save! | ||
275 | + | ||
276 | + post :set_layout_template, :profile => 'testinguser', :id => 'leftbar' | ||
277 | + profile = Profile.find(@profile.id) | ||
278 | + assert_equal 'leftbar', profile.layout_template | ||
279 | + assert_redirected_to :action => 'index' | ||
280 | + end | ||
281 | + | ||
261 | should 'not display "new theme" button when user themes are disabled' do | 282 | should 'not display "new theme" button when user themes are disabled' do |
262 | env.disable('user_themes') | 283 | env.disable('user_themes') |
263 | env.save! | 284 | env.save! |
test/unit/article_test.rb
@@ -705,15 +705,13 @@ class ArticleTest < Test::Unit::TestCase | @@ -705,15 +705,13 @@ class ArticleTest < Test::Unit::TestCase | ||
705 | end | 705 | end |
706 | 706 | ||
707 | should 'use npage to compose cache key' do | 707 | should 'use npage to compose cache key' do |
708 | - a = Article.new | ||
709 | - a.expects(:id).returns(34) | ||
710 | - assert_equal 'article-id-34-npage-2', a.cache_key(:npage => 2) | 708 | + a = Article.create!(:name => 'Published at', :profile => profile) |
709 | + assert_match(/-npage-2/,a.cache_key(:npage => 2)) | ||
711 | end | 710 | end |
712 | 711 | ||
713 | should 'use year and month to compose cache key' do | 712 | should 'use year and month to compose cache key' do |
714 | - a = Article.new | ||
715 | - a.expects(:id).returns(34) | ||
716 | - assert_equal 'article-id-34-year-2009-month-04', a.cache_key(:year => '2009', :month => '04') | 713 | + a = Article.create!(:name => 'Published at', :profile => profile) |
714 | + assert_match(/-year-2009-month-04/, a.cache_key(:year => '2009', :month => '04')) | ||
717 | end | 715 | end |
718 | 716 | ||
719 | should 'not be highlighted by default' do | 717 | should 'not be highlighted by default' do |
@@ -749,4 +747,20 @@ class ArticleTest < Test::Unit::TestCase | @@ -749,4 +747,20 @@ class ArticleTest < Test::Unit::TestCase | ||
749 | assert_equal [c], a.categories | 747 | assert_equal [c], a.categories |
750 | end | 748 | end |
751 | 749 | ||
750 | + should 'add owner on cache_key when has profile' do | ||
751 | + a = profile.articles.create!(:name => 'a test article') | ||
752 | + assert_match(/-owner/, a.cache_key({}, profile)) | ||
753 | + end | ||
754 | + | ||
755 | + should 'not add owner on cache_key when has no profile' do | ||
756 | + a = profile.articles.create!(:name => 'a test article') | ||
757 | + assert_no_match(/-owner/, a.cache_key({})) | ||
758 | + end | ||
759 | + | ||
760 | + should 'add owner on cache_key when profile is community' do | ||
761 | + c = Community.create!(:name => 'new_comm') | ||
762 | + a = c.articles.create!(:name => 'a test article') | ||
763 | + assert_match(/-owner/, a.cache_key({}, c)) | ||
764 | + end | ||
765 | + | ||
752 | end | 766 | end |
test/unit/blog_test.rb
@@ -130,16 +130,6 @@ class BlogTest < ActiveSupport::TestCase | @@ -130,16 +130,6 @@ class BlogTest < ActiveSupport::TestCase | ||
130 | assert ! blog.valid? | 130 | assert ! blog.valid? |
131 | end | 131 | end |
132 | 132 | ||
133 | - should 'expires cache when update post' do | ||
134 | - p = create_user('testuser').person | ||
135 | - blog = Blog.create!(:name => 'Blog test', :profile => p) | ||
136 | - post = Article.create!(:name => 'First post', :profile => p, :parent => blog) | ||
137 | - ArticleSweeper.any_instance.expects(:expire_fragment).with(blog.cache_key) | ||
138 | - ArticleSweeper.any_instance.expects(:expire_fragment).with(post.cache_key) | ||
139 | - post.name = 'Edited First post' | ||
140 | - assert post.save! | ||
141 | - end | ||
142 | - | ||
143 | should 'remove external feed when removing blog' do | 133 | should 'remove external feed when removing blog' do |
144 | p = create_user('testuser').person | 134 | p = create_user('testuser').person |
145 | blog = Blog.create!(:name => 'Blog test', :profile => p, :external_feed_builder => {:enabled => true, :address => "http://bli.org/feed"}) | 135 | blog = Blog.create!(:name => 'Blog test', :profile => p, :external_feed_builder => {:enabled => true, :address => "http://bli.org/feed"}) |
test/unit/feed_reader_block_test.rb
@@ -81,4 +81,16 @@ class FeedReaderBlockTest < ActiveSupport::TestCase | @@ -81,4 +81,16 @@ class FeedReaderBlockTest < ActiveSupport::TestCase | ||
81 | assert_equal %w[ last-post second-post first-post ], feed.feed_items.map{|i|i[:title]} | 81 | assert_equal %w[ last-post second-post first-post ], feed.feed_items.map{|i|i[:title]} |
82 | end | 82 | end |
83 | 83 | ||
84 | + should 'display only limit posts' do | ||
85 | + feed.limit = 1; feed.save! | ||
86 | + %w[ first-post second-post ].each do |i| | ||
87 | + feed.add_item(i, "http://localhost/#{i}", Date.today, "some contet for #{i}") | ||
88 | + end | ||
89 | + | ||
90 | + assert_tag_in_string feed.formatted_feed_content, :tag => 'a', :attributes => { :href => 'http://localhost/second-post' }, :content => 'second-post' | ||
91 | + assert_no_tag_in_string feed.formatted_feed_content, :tag => 'a', :attributes => { :href => 'http://localhost/first-post' }, :content => 'first-post' | ||
92 | + end | ||
93 | + | ||
94 | + | ||
95 | + | ||
84 | end | 96 | end |
test/unit/tiny_mce_article_test.rb
@@ -4,7 +4,9 @@ class TinyMceArticleTest < Test::Unit::TestCase | @@ -4,7 +4,9 @@ class TinyMceArticleTest < Test::Unit::TestCase | ||
4 | 4 | ||
5 | def setup | 5 | def setup |
6 | Article.rebuild_index | 6 | Article.rebuild_index |
7 | + @profile = create_user('zezinho').person | ||
7 | end | 8 | end |
9 | + attr_reader :profile | ||
8 | 10 | ||
9 | # this test can be removed when we get real tests for TinyMceArticle | 11 | # this test can be removed when we get real tests for TinyMceArticle |
10 | should 'be an article' do | 12 | should 'be an article' do |
@@ -20,16 +22,21 @@ class TinyMceArticleTest < Test::Unit::TestCase | @@ -20,16 +22,21 @@ class TinyMceArticleTest < Test::Unit::TestCase | ||
20 | end | 22 | end |
21 | 23 | ||
22 | should 'be found when searching for articles by query' do | 24 | should 'be found when searching for articles by query' do |
23 | - ze = create_user('zezinho').person | ||
24 | - tma = TinyMceArticle.create!(:name => 'test tinymce article', :body => '---', :profile => ze) | 25 | + tma = TinyMceArticle.create!(:name => 'test tinymce article', :body => '---', :profile => profile) |
25 | assert_includes TinyMceArticle.find_by_contents('article'), tma | 26 | assert_includes TinyMceArticle.find_by_contents('article'), tma |
26 | assert_includes Article.find_by_contents('article'), tma | 27 | assert_includes Article.find_by_contents('article'), tma |
27 | end | 28 | end |
28 | 29 | ||
29 | should 'not sanitize target attribute' do | 30 | should 'not sanitize target attribute' do |
30 | - ze = create_user('zezinho').person | ||
31 | - article = TinyMceArticle.create!(:name => 'open link in new window', :body => "open <a href='www.invalid.com' target='_blank'>link</a> in new window", :profile => ze) | 31 | + article = TinyMceArticle.create!(:name => 'open link in new window', :body => "open <a href='www.invalid.com' target='_blank'>link</a> in new window", :profile => profile) |
32 | assert_tag_in_string article.body, :tag => 'a', :attributes => {:target => '_blank'} | 32 | assert_tag_in_string article.body, :tag => 'a', :attributes => {:target => '_blank'} |
33 | end | 33 | end |
34 | 34 | ||
35 | + should 'not translate & to amp; over times' do | ||
36 | + article = TinyMceArticle.create!(:name => 'link', :body => "<a href='www.invalid.com?param1=value¶m2=value'>link</a>", :profile => profile) | ||
37 | + assert article.save | ||
38 | + assert_no_match /&amp;/, article.body | ||
39 | + assert_match /&/, article.body | ||
40 | + end | ||
41 | + | ||
35 | end | 42 | end |
vendor/plugins/timed_cached_fragment/lib/timed_cache_fragment.rb
@@ -3,14 +3,13 @@ module ActionController | @@ -3,14 +3,13 @@ module ActionController | ||
3 | module Cache | 3 | module Cache |
4 | module TimedCache | 4 | module TimedCache |
5 | #handles standard ERB fragments used in RHTML | 5 | #handles standard ERB fragments used in RHTML |
6 | - def cache_timeout(name={}, expire = 10.minutes.from_now, &block) | 6 | + def cache_timeout(key={}, expire = 10.minutes.from_now, &block) |
7 | unless perform_caching then block.call; return end | 7 | unless perform_caching then block.call; return end |
8 | - key = fragment_cache_key(name) | ||
9 | if is_cache_expired?(key,true) | 8 | if is_cache_expired?(key,true) |
10 | expire_timeout_fragment(key) | 9 | expire_timeout_fragment(key) |
11 | set_timeout(key, expire) | 10 | set_timeout(key, expire) |
12 | end | 11 | end |
13 | - cache_erb_fragment(block,name) | 12 | + cache_erb_fragment(block,key) |
14 | end | 13 | end |
15 | #handles the expiration of timeout fragment | 14 | #handles the expiration of timeout fragment |
16 | def expire_timeout_fragment(key) | 15 | def expire_timeout_fragment(key) |
@@ -0,0 +1,13 @@ | @@ -0,0 +1,13 @@ | ||
1 | +if ActiveRecord::Base.instance_methods.include?("touch") && Class.const_defined?('TOUCH_LOADED') | ||
2 | + puts "W: ActiveRecord already provides a touch method, which means you must be using rails 2.3.3 or later." | ||
3 | + puts "W: In this case the touch plugin could probably be removed" | ||
4 | +end | ||
5 | +TOUCH_LOADED = true | ||
6 | + | ||
7 | +module Touch | ||
8 | + def touch | ||
9 | + update_attribute(:updated_at, Time.now) | ||
10 | + end | ||
11 | +end | ||
12 | + | ||
13 | +ActiveRecord::Base.send(:include, Touch) |
vendor/plugins/white_list_sanitizer_unescape_before_reescape/init.rb
0 → 100644
@@ -0,0 +1,22 @@ | @@ -0,0 +1,22 @@ | ||
1 | +# monkey patch to fix WhiteListSanitizer bug | ||
2 | +# http://apidock.com/rails/HTML/WhiteListSanitizer/process_attributes_for | ||
3 | +# | ||
4 | +# this was solved in rails 2.2.1, then remove this patch when upgrade to it | ||
5 | + | ||
6 | +HTML::WhiteListSanitizer.module_eval do | ||
7 | + # unescape before reescape to avoid: | ||
8 | + # & -> & -> &amp; -> &amp;amp; -> &amp;amp;amp; -> etc | ||
9 | + protected | ||
10 | + def process_attributes_for(node, options) | ||
11 | + return unless node.attributes | ||
12 | + node.attributes.keys.each do |attr_name| | ||
13 | + value = node.attributes[attr_name].to_s | ||
14 | + | ||
15 | + if !options[:attributes].include?(attr_name) || contains_bad_protocols?(attr_name, value) | ||
16 | + node.attributes.delete(attr_name) | ||
17 | + else | ||
18 | + node.attributes[attr_name] = attr_name == 'style' ? sanitize_css(value) : CGI::escapeHTML(CGI::unescapeHTML(value)) | ||
19 | + end | ||
20 | + end | ||
21 | + end | ||
22 | +end |