Commit 961148fb74e53842f028b9485cfb210ec5d4562f

Authored by Antonio Terceiro
2 parents e835f4f0 c35f9d57

Merge branch 'stable'

Conflicts:
	po/pt_BR/noosfero.po
app/controllers/my_profile/profile_editor_controller.rb
... ... @@ -64,7 +64,7 @@ class ProfileEditorController < MyProfileController
64 64 def header_footer
65 65 @no_design_blocks = true
66 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 68 redirect_to :action => 'index'
69 69 else
70 70 @header = boxes_holder.custom_header
... ...
app/controllers/my_profile/themes_controller.rb
... ... @@ -4,7 +4,7 @@ class ThemesController < MyProfileController
4 4 no_design_blocks
5 5  
6 6 def set
7   - profile.update_attributes!(:theme => params[:id])
  7 + profile.update_theme(params[:id])
8 8 redirect_to :action => 'index'
9 9 end
10 10  
... ... @@ -79,8 +79,7 @@ class ThemesController < MyProfileController
79 79 end
80 80  
81 81 def set_layout_template
82   - profile.layout_template = params[:id]
83   - profile.save!
  82 + profile.update_layout_template(params[:id])
84 83 redirect_to :action => 'index'
85 84 end
86 85  
... ...
app/helpers/application_helper.rb
... ... @@ -311,22 +311,35 @@ module ApplicationHelper
311 311 end
312 312  
313 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 343 end
331 344  
332 345 def theme_include(template)
... ...
app/helpers/sweeper_helper.rb
... ... @@ -43,4 +43,7 @@ module SweeperHelper
43 43 blocks.map(&:cache_keys).each{|ck|expire_timeout_fragment(ck)}
44 44 end
45 45  
  46 + def expire_profile_index(profile)
  47 + expire_timeout_fragment(profile.relationships_cache_key)
  48 + end
46 49 end
... ...
app/models/article.rb
... ... @@ -214,6 +214,13 @@ class Article < ActiveRecord::Base
214 214 end
215 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 224 def comments_updated
218 225 ferret_update
219 226 end
... ... @@ -266,8 +273,10 @@ class Article < ActiveRecord::Base
266 273 profile
267 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 280 (params[:npage] ? "-npage-#{params[:npage]}" : '') +
272 281 (params[:year] ? "-year-#{params[:year]}" : '') +
273 282 (params[:month] ? "-month-#{params[:month]}" : '')
... ...
app/models/feed_reader_block.rb
... ... @@ -28,7 +28,7 @@ class FeedReaderBlock < Block
28 28  
29 29 def formatted_feed_content
30 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 32 "</ul>"
33 33 end
34 34  
... ...
app/models/person.rb
... ... @@ -279,4 +279,8 @@ class Person &lt; Profile
279 279 page = params[:npage] || '1'
280 280 identifier + '-manage-friends-page-' + page
281 281 end
  282 +
  283 + def relationships_cache_key
  284 + identifier + '-profile-relationships'
  285 + end
282 286 end
... ...
app/models/profile.rb
... ... @@ -643,4 +643,18 @@ class Profile &lt; ActiveRecord::Base
643 643 ProfileSweeper.new().after_create(profile)
644 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 660 end
... ...
app/sweepers/article_sweeper.rb
... ... @@ -13,7 +13,11 @@ class ArticleSweeper &lt; ActiveRecord::Observer
13 13 protected
14 14  
15 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 21 blocks = (article.profile.blocks + article.profile.environment.blocks).select{|b|[RecentDocumentsBlock, BlogArchivesBlock].any?{|c| b.kind_of?(c)}}
18 22 blocks.map(&:cache_keys).each{|ck|expire_timeout_fragment(ck)}
19 23 env = article.profile.environment
... ...
app/sweepers/profile_sweeper.rb
... ... @@ -17,8 +17,11 @@ protected
17 17 profile.members.each do |member|
18 18 expire_communities(member) if profile.community?
19 19 expire_enterprises(member) if profile.enterprise?
  20 + expire_profile_index(member) if profile.enterprise?
20 21 end
21 22  
  23 + expire_profile_index(profile) if profile.person?
  24 +
22 25 profile.blocks.each do |block|
23 26 expire_timeout_fragment(block.cache_keys)
24 27 end
... ...
app/views/blocks/my_network/person.rhtml
... ... @@ -3,8 +3,8 @@
3 3 content_tag('b', owner.articles.count), owner.public_profile_url.merge(:action => 'sitemap') ) %></li>
4 4 <li><%= link_to(n__('One friend', '%s friends', owner.friends.count) %
5 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 8 <li><%= link_to(n_('One tag', '%s tags', owner.article_tags.size) %
9 9 content_tag('b', owner.article_tags.size), owner.public_profile_url.merge(:action => 'tags')) %></li>
10 10 </ul>
... ...
app/views/content_viewer/view_page.rhtml
... ... @@ -23,7 +23,7 @@
23 23  
24 24 <div>
25 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 27 <div id="article-actions">
28 28 <% unless @page.blog? %>
29 29 <%= link_to content_tag( 'span', label_for_edit_article(@page) ),
... ... @@ -80,7 +80,7 @@
80 80 </div>
81 81 <% end %>
82 82  
83   -<% cache(@page.cache_key(params)) do %>
  83 +<% cache(@page.cache_key(params, user)) do %>
84 84 <div class="<%="article-body article-body-" + @page.css_class_name %>">
85 85 <%= article_to_html(@page) %>
86 86 <br style="clear:both" />
... ...
app/views/layouts/application-ng.rhtml
... ... @@ -5,6 +5,7 @@
5 5 <%= meta_tags_for_article(@page) %>
6 6 <!--<meta http-equiv="refresh" content="1"/>-->
7 7 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  8 + <meta name="description" content="<%= @environment.name %>" />
8 9 <link rel="shortcut icon" href="<%= '/designs/themes/' + current_theme + '/imgs/favicon.ico' %>" type="image/x-icon" />
9 10 <%= noosfero_javascript %>
10 11 <%= import_blocks_stylesheets %>
... ...
app/views/layouts/application.rhtml
... ... @@ -3,7 +3,7 @@
3 3 <head>
4 4 <title><%= page_title %></title>
5 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 7 <meta name="keywords" content="Noosfero, Community, Open Source" />
8 8 <link rel="shortcut icon" href="<%= '/designs/themes/' + current_theme + '/images/favicon.ico' %>" type="image/x-icon" />
9 9 <!-- ok --><%= meta_tags_for_article(@page) %>
... ...
app/views/profile/_person.rhtml
... ... @@ -16,7 +16,7 @@
16 16 <%= display_field(_('e-Mail:'), profile, :email, true) { |email| link_to_email(email) } %>
17 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 20 <% if !(profile.organization.blank? && profile.organization_website.blank?) && (profile.active_fields.include?('organization') || profile.active_fields.include?('organization_website')) %>
21 21 <tr>
22 22 <th colspan='2'><%= _('Work')%></th>
... ...
app/views/profile_editor/_organization.rhtml
... ... @@ -63,23 +63,24 @@
63 63 <%= labelled_check_box(_('Enable "contact us"'), 'profile_data[enable_contact_us]', "1", @profile.enable_contact_us) if @profile.enterprise? %>
64 64  
65 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 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 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 84 <div style='margin-bottom: 1em'>
84 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 15 <%= optional_field(@person, 'cell_phone', f.text_field(:cell_phone)) %>
16 16 <%= optional_field(@person, 'comercial_phone', f.text_field(:comercial_phone)) %>
17 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 19 <%= optional_field(@person, 'nationality', f.text_field(:nationality)) %>
20 20 <%= optional_field(@person, 'country', select_country(_('Country'), 'profile_data', 'country', {:class => 'type-select'})) %>
21 21 <%= optional_field(@person, 'state', f.text_field(:state)) %>
... ...
app/views/profile_editor/edit.rhtml
... ... @@ -9,7 +9,7 @@
9 9 <div id="profile_change_picture">
10 10 <h2><%= _('Change picture') %></h2>
11 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 13 <% end %>
14 14 </div>
15 15  
... ...
app/views/shared/tiny_mce.rhtml
... ... @@ -24,7 +24,7 @@ tinyMCE.init({
24 24 apply_source_formatting : true,
25 25 content_css: '/stylesheets/tinymce.css',
26 26 language: <%= tinymce_language.inspect %>,
27   - cleanup_callback : "customCleanup"
  27 + entity_encoding: 'raw'
28 28 });
29 29  
30 30 function convertWord(type, content) {
... ... @@ -43,16 +43,4 @@ function convertWord(type, content) {
43 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;amp;/g,"&amp;");
50   - break;
51   - case "insert_to_editor":
52   - value = value.replace(/&amp;amp;/g,"&amp;");
53   - break;
54   - }
55   - return value;
56   -}
57   -
58 46 </script>
... ...
db/migrate/070_add_updated_at_to_profiles.rb 0 → 100644
... ... @@ -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/migrate/071_remove_lock_version.rb 0 → 100644
... ... @@ -0,0 +1,9 @@
  1 +class RemoveLockVersion < ActiveRecord::Migration
  2 + def self.up
  3 + remove_column :articles, :lock_version
  4 + end
  5 +
  6 + def self.down
  7 + add_column :articles, :lock_version, :integer, :default => 0
  8 + end
  9 +end
... ...
db/schema.rb
... ... @@ -89,8 +89,8 @@ ActiveRecord::Schema.define(:version =&gt; 69) do
89 89 t.boolean "virtual", :default => false
90 90 end
91 91  
92   - add_index "articles_categories", ["article_id"], :name => "index_articles_categories_on_article_id"
93 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 95 create_table "blocks", :force => true do |t|
96 96 t.string "title"
... ... @@ -131,8 +131,8 @@ ActiveRecord::Schema.define(:version =&gt; 69) do
131 131 t.boolean "virtual", :default => false
132 132 end
133 133  
134   - add_index "categories_profiles", ["profile_id"], :name => "index_categories_profiles_on_profile_id"
135 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 137 create_table "comments", :force => true do |t|
138 138 t.string "title"
... ... @@ -211,8 +211,8 @@ ActiveRecord::Schema.define(:version =&gt; 69) do
211 211 t.datetime "updated_at"
212 212 end
213 213  
214   - add_index "product_categorizations", ["product_id"], :name => "index_product_categorizations_on_product_id"
215 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 217 create_table "products", :force => true do |t|
218 218 t.integer "enterprise_id"
... ... @@ -284,10 +284,6 @@ ActiveRecord::Schema.define(:version =&gt; 69) do
284 284 t.integer "environment_id"
285 285 end
286 286  
287   - create_table "schema_info", :id => false, :force => true do |t|
288   - t.integer "version"
289   - end
290   -
291 287 create_table "taggings", :force => true do |t|
292 288 t.integer "tag_id"
293 289 t.integer "taggable_id"
... ... @@ -295,8 +291,8 @@ ActiveRecord::Schema.define(:version =&gt; 69) do
295 291 t.datetime "created_at"
296 292 end
297 293  
298   - add_index "taggings", ["tag_id"], :name => "index_taggings_on_tag_id"
299 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 297 create_table "tags", :force => true do |t|
302 298 t.string "name"
... ...
lib/noosfero.rb
1 1 module Noosfero
2 2 PROJECT = 'noosfero'
3   - VERSION = '0.19.2'
  3 + VERSION = '0.19.3'
4 4 SVN_ROOT = 'https://svn.colivre.coop.br/svn/noosfero'
5 5  
6 6 def self.pattern_for_controllers_in_directory(dir)
... ...
po/pt_BR/noosfero.po
... ... @@ -13,7 +13,7 @@ msgid &quot;&quot;
13 13 msgstr ""
14 14 "Project-Id-Version: noosfero 0.19.0\n"
15 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 17 "Last-Translator: Joenio Costa <joenio@colivre.coop.br>\n"
18 18 "Language-Team: LANGUAGE <LL@li.org>\n"
19 19 "MIME-Version: 1.0\n"
... ... @@ -6671,3 +6671,6 @@ msgstr &quot;&quot;
6671 6671  
6672 6672 msgid "You must type at least 3 characters"
6673 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 &lt; Test::Unit::TestCase
427 427 assert_equal false, @controller.avoid_ssl
428 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 435 end
... ...
test/functional/profile_editor_controller_test.rb
... ... @@ -302,31 +302,23 @@ class ProfileEditorControllerTest &lt; Test::Unit::TestCase
302 302 assert_not_nil assigns(:profile).image
303 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 307 get :edit, :profile => 'testorg'
308 308  
309 309 assert_tag :tag => 'input', :attributes => { :type => 'radio', :name => 'profile_data[closed]', :value => 'true', :checked => 'checked' }
310 310 assert_no_tag :tag => 'input', :attributes => { :type => 'radio', :name => 'profile_data[closed]', :value => 'false', :checked => 'checked' }
311 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 315 get :edit, :profile => 'testorg'
324 316 assert_no_tag :tag => 'input', :attributes => { :type => 'radio', :name => 'profile_data[closed]', :value => 'true', :checked => 'checked' }
325 317 assert_tag :tag => 'input', :attributes => { :type => 'radio', :name => 'profile_data[closed]', :value => 'false', :checked => 'checked' }
326 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 322 get :edit, :profile => 'testorg'
331 323 assert_no_tag :tag => 'input', :attributes => { :type => 'radio', :name => 'profile_data[closed]', :value => 'true', :checked => 'checked' }
332 324 assert_tag :tag => 'input', :attributes => { :type => 'radio', :name => 'profile_data[closed]', :value => 'false', :checked => 'checked' }
... ... @@ -348,6 +340,22 @@ class ProfileEditorControllerTest &lt; Test::Unit::TestCase
348 340 assert !org.closed
349 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 359 should 'display manage members options if has permission' do
352 360 profile = Profile['ze']
353 361 community = Community.create!(:name => 'test org', :identifier => 'testorg', :contact_person => 'my contact', :environment => Environment.default)
... ... @@ -526,6 +534,17 @@ class ProfileEditorControllerTest &lt; Test::Unit::TestCase
526 534 assert_equal 'new footer', person.custom_footer
527 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 548 should 'go back to editor after saving header/footer' do
530 549 person = create_user('designtestuser').person
531 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 &lt; Test::Unit::TestCase
78 78 assert_equal 'onetheme', profile.theme
79 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 91 should 'point back to control panel' do
82 92 get :index, :profile => 'testinguser'
83 93 assert_tag :tag => 'a', :attributes => { :href => '/myprofile/testinguser' }, :content => 'Back'
... ... @@ -258,6 +268,17 @@ class ThemesControllerTest &lt; Test::Unit::TestCase
258 268 assert_redirected_to :action => 'index'
259 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 282 should 'not display "new theme" button when user themes are disabled' do
262 283 env.disable('user_themes')
263 284 env.save!
... ...
test/unit/article_test.rb
... ... @@ -705,15 +705,13 @@ class ArticleTest &lt; Test::Unit::TestCase
705 705 end
706 706  
707 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 710 end
712 711  
713 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 715 end
718 716  
719 717 should 'not be highlighted by default' do
... ... @@ -749,4 +747,20 @@ class ArticleTest &lt; Test::Unit::TestCase
749 747 assert_equal [c], a.categories
750 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 766 end
... ...
test/unit/blog_test.rb
... ... @@ -130,16 +130,6 @@ class BlogTest &lt; ActiveSupport::TestCase
130 130 assert ! blog.valid?
131 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 133 should 'remove external feed when removing blog' do
144 134 p = create_user('testuser').person
145 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 &lt; ActiveSupport::TestCase
81 81 assert_equal %w[ last-post second-post first-post ], feed.feed_items.map{|i|i[:title]}
82 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 96 end
... ...
test/unit/tiny_mce_article_test.rb
... ... @@ -4,7 +4,9 @@ class TinyMceArticleTest &lt; Test::Unit::TestCase
4 4  
5 5 def setup
6 6 Article.rebuild_index
  7 + @profile = create_user('zezinho').person
7 8 end
  9 + attr_reader :profile
8 10  
9 11 # this test can be removed when we get real tests for TinyMceArticle
10 12 should 'be an article' do
... ... @@ -20,16 +22,21 @@ class TinyMceArticleTest &lt; Test::Unit::TestCase
20 22 end
21 23  
22 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 26 assert_includes TinyMceArticle.find_by_contents('article'), tma
26 27 assert_includes Article.find_by_contents('article'), tma
27 28 end
28 29  
29 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 32 assert_tag_in_string article.body, :tag => 'a', :attributes => {:target => '_blank'}
33 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&param2=value'>link</a>", :profile => profile)
  37 + assert article.save
  38 + assert_no_match /&amp;amp;/, article.body
  39 + assert_match /&amp;/, article.body
  40 + end
  41 +
35 42 end
... ...
vendor/plugins/timed_cached_fragment/lib/timed_cache_fragment.rb
... ... @@ -3,14 +3,13 @@ module ActionController
3 3 module Cache
4 4 module TimedCache
5 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 7 unless perform_caching then block.call; return end
8   - key = fragment_cache_key(name)
9 8 if is_cache_expired?(key,true)
10 9 expire_timeout_fragment(key)
11 10 set_timeout(key, expire)
12 11 end
13   - cache_erb_fragment(block,name)
  12 + cache_erb_fragment(block,key)
14 13 end
15 14 #handles the expiration of timeout fragment
16 15 def expire_timeout_fragment(key)
... ...
vendor/plugins/touch/init.rb 0 → 100644
... ... @@ -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 @@
  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; -> &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
... ...