Commit ddb644699b03fa44d64db803cf72abf8c0759883

Authored by Rodrigo Souto
2 parents 18ea9ebe 8f4b2c3d

Merge branch 'stable'

Showing 43 changed files with 799 additions and 592 deletions   Show diff stats
@@ -6,6 +6,7 @@ noosfero, that's not a problem). @@ -6,6 +6,7 @@ noosfero, that's not a problem).
6 Developers 6 Developers
7 ========== 7 ==========
8 8
  9 +Alan Freihof Tygel <alantygel@gmail.com>
9 Alessandro Palmeira <alessandro.palmeira@gmail.com> 10 Alessandro Palmeira <alessandro.palmeira@gmail.com>
10 Alessandro Palmeira + Caio C. Salgado <alessandro.palmeira@gmail.com> 11 Alessandro Palmeira + Caio C. Salgado <alessandro.palmeira@gmail.com>
11 Alessandro Palmeira + Caio Salgado <alessandro.palmeira@gmail.com> 12 Alessandro Palmeira + Caio Salgado <alessandro.palmeira@gmail.com>
app/models/approve_article.rb
@@ -48,7 +48,7 @@ class ApproveArticle &lt; Task @@ -48,7 +48,7 @@ class ApproveArticle &lt; Task
48 end 48 end
49 49
50 def perform 50 def perform
51 - article.copy!(:name => name, :abstract => abstract, :body => body, :profile => target, :reference_article => article, :parent => article_parent, :highlighted => highlighted, :source => article.source, :last_changed_by_id => article.author.id) 51 + article.copy!(:name => name, :abstract => abstract, :body => body, :profile => target, :reference_article => article, :parent => article_parent, :highlighted => highlighted, :source => article.source, :last_changed_by_id => article.author_id)
52 end 52 end
53 53
54 def title 54 def title
app/models/article.rb
@@ -562,6 +562,10 @@ class Article &lt; ActiveRecord::Base @@ -562,6 +562,10 @@ class Article &lt; ActiveRecord::Base
562 author ? author.url : nil 562 author ? author.url : nil
563 end 563 end
564 564
  565 + def author_id
  566 + author ? author.id : nil
  567 + end
  568 +
565 alias :active_record_cache_key :cache_key 569 alias :active_record_cache_key :cache_key
566 def cache_key(params = {}, the_profile = nil, language = 'en') 570 def cache_key(params = {}, the_profile = nil, language = 'en')
567 active_record_cache_key+'-'+language + 571 active_record_cache_key+'-'+language +
app/models/comment.rb
@@ -74,6 +74,10 @@ class Comment &lt; ActiveRecord::Base @@ -74,6 +74,10 @@ class Comment &lt; ActiveRecord::Base
74 self.find(:all, :order => 'created_at desc, id desc', :limit => limit) 74 self.find(:all, :order => 'created_at desc, id desc', :limit => limit)
75 end 75 end
76 76
  77 + def notification_emails
  78 + self.article.profile.notification_emails - [self.author_email || self.email]
  79 + end
  80 +
77 after_save :notify_article 81 after_save :notify_article
78 after_destroy :notify_article 82 after_destroy :notify_article
79 def notify_article 83 def notify_article
@@ -114,7 +118,7 @@ class Comment &lt; ActiveRecord::Base @@ -114,7 +118,7 @@ class Comment &lt; ActiveRecord::Base
114 118
115 def notify_by_mail 119 def notify_by_mail
116 if source.kind_of?(Article) && article.notify_comments? 120 if source.kind_of?(Article) && article.notify_comments?
117 - if !article.profile.notification_emails.empty? 121 + if !notification_emails.empty?
118 Comment::Notifier.deliver_mail(self) 122 Comment::Notifier.deliver_mail(self)
119 end 123 end
120 emails = article.followers - [author_email] 124 emails = article.followers - [author_email]
@@ -174,7 +178,7 @@ class Comment &lt; ActiveRecord::Base @@ -174,7 +178,7 @@ class Comment &lt; ActiveRecord::Base
174 class Notifier < ActionMailer::Base 178 class Notifier < ActionMailer::Base
175 def mail(comment) 179 def mail(comment)
176 profile = comment.article.profile 180 profile = comment.article.profile
177 - recipients profile.notification_emails 181 + recipients comment.notification_emails
178 from "#{profile.environment.name} <#{profile.environment.contact_email}>" 182 from "#{profile.environment.name} <#{profile.environment.contact_email}>"
179 subject _("[%s] you got a new comment!") % [profile.environment.name] 183 subject _("[%s] you got a new comment!") % [profile.environment.name]
180 body :recipient => profile.nickname || profile.name, 184 body :recipient => profile.nickname || profile.name,
app/models/environment.rb
@@ -234,7 +234,8 @@ class Environment &lt; ActiveRecord::Base @@ -234,7 +234,8 @@ class Environment &lt; ActiveRecord::Base
234 end 234 end
235 235
236 settings_items :activation_blocked_text, :type => String 236 settings_items :activation_blocked_text, :type => String
237 - settings_items :message_for_disabled_enterprise, :type => String 237 + settings_items :message_for_disabled_enterprise, :type => String,
  238 + :default => _('This enterprise needs to be enabled.')
238 settings_items :location, :type => String 239 settings_items :location, :type => String
239 settings_items :layout_template, :type => String, :default => 'default' 240 settings_items :layout_template, :type => String, :default => 'default'
240 settings_items :homepage, :type => String 241 settings_items :homepage, :type => String
app/models/profile.rb
@@ -463,6 +463,10 @@ class Profile &lt; ActiveRecord::Base @@ -463,6 +463,10 @@ class Profile &lt; ActiveRecord::Base
463 { :profile => identifier, :controller => 'profile_editor', :action => 'index' } 463 { :profile => identifier, :controller => 'profile_editor', :action => 'index' }
464 end 464 end
465 465
  466 + def tasks_url
  467 + { :profile => identifier, :controller => 'tasks', :action => 'index', :host => default_hostname }
  468 + end
  469 +
466 def leave_url(reload = false) 470 def leave_url(reload = false)
467 { :profile => identifier, :controller => 'profile', :action => 'leave', :reload => reload } 471 { :profile => identifier, :controller => 'profile', :action => 'leave', :reload => reload }
468 end 472 end
app/models/task_mailer.rb
@@ -14,7 +14,7 @@ class TaskMailer &lt; ActionMailer::Base @@ -14,7 +14,7 @@ class TaskMailer &lt; ActionMailer::Base
14 14
15 recipients task.target.notification_emails 15 recipients task.target.notification_emails
16 16
17 - url_for_tasks_list = task.target.kind_of?(Environment) ? '' : url_for(task.target.url.merge(:controller => 'tasks', :action => 'index')) 17 + url_for_tasks_list = task.target.kind_of?(Environment) ? '' : url_for(task.target.tasks_url)
18 18
19 from self.class.generate_from(task) 19 from self.class.generate_from(task)
20 subject '[%s] %s' % [task.environment.name, task.target_notification_description] 20 subject '[%s] %s' % [task.environment.name, task.target_notification_description]
app/models/user.rb
@@ -31,7 +31,7 @@ class User &lt; ActiveRecord::Base @@ -31,7 +31,7 @@ class User &lt; ActiveRecord::Base
31 after_create do |user| 31 after_create do |user|
32 user.person ||= Person.new 32 user.person ||= Person.new
33 user.person.attributes = user.person_data.merge(:identifier => user.login, :user => user, :environment_id => user.environment_id) 33 user.person.attributes = user.person_data.merge(:identifier => user.login, :user => user, :environment_id => user.environment_id)
34 - user.person.name ||= user.login 34 + user.person.name ||= user.name
35 user.person.visible = false unless user.activated? 35 user.person.visible = false unless user.activated?
36 user.person.save! 36 user.person.save!
37 if user.environment.enabled?('skip_new_user_email_confirmation') 37 if user.environment.enabled?('skip_new_user_email_confirmation')
db/migrate/20130111232201_aggressive_indexing_strategy3.rb 0 → 100644
@@ -0,0 +1,39 @@ @@ -0,0 +1,39 @@
  1 +class AggressiveIndexingStrategy3 < ActiveRecord::Migration
  2 + def self.up
  3 + add_index :articles, :slug
  4 + add_index :articles, :parent_id
  5 + add_index :articles, :profile_id
  6 + add_index :articles, :name
  7 +
  8 + add_index :article_versions, :article_id
  9 +
  10 + add_index :comments, [:source_id, :spam]
  11 +
  12 + add_index :profiles, :identifier
  13 +
  14 + add_index :friendships, :person_id
  15 + add_index :friendships, :friend_id
  16 + add_index :friendships, [:person_id, :friend_id], :uniq => true
  17 +
  18 + add_index :external_feeds, :blog_id
  19 + end
  20 +
  21 + def self.down
  22 + remove_index :articles, :slug
  23 + remove_index :articles, :parent_id
  24 + remove_index :articles, :profile_id
  25 + remove_index :articles, :name
  26 +
  27 + remove_index :article_versions, :article_id
  28 +
  29 + remove_index :comments, [:source_id, :spam]
  30 +
  31 + remove_index :profiles, :identifier
  32 +
  33 + remove_index :friendships, :person_id
  34 + remove_index :friendships, :friend_id
  35 + remove_index :friendships, [:person_id, :friend_id]
  36 +
  37 + remove_index :external_feeds, :blog_id
  38 + end
  39 +end
@@ -9,7 +9,7 @@ @@ -9,7 +9,7 @@
9 # 9 #
10 # It's strongly recommended to check this file into your version control system. 10 # It's strongly recommended to check this file into your version control system.
11 11
12 -ActiveRecord::Schema.define(:version => 20121008185303) do 12 +ActiveRecord::Schema.define(:version => 20130111232201) do
13 13
14 create_table "abuse_reports", :force => true do |t| 14 create_table "abuse_reports", :force => true do |t|
15 t.integer "reporter_id" 15 t.integer "reporter_id"
@@ -88,6 +88,8 @@ ActiveRecord::Schema.define(:version =&gt; 20121008185303) do @@ -88,6 +88,8 @@ ActiveRecord::Schema.define(:version =&gt; 20121008185303) do
88 t.integer "license_id" 88 t.integer "license_id"
89 end 89 end
90 90
  91 + add_index "article_versions", ["article_id"], :name => "index_article_versions_on_article_id"
  92 +
91 create_table "articles", :force => true do |t| 93 create_table "articles", :force => true do |t|
92 t.string "name" 94 t.string "name"
93 t.string "slug" 95 t.string "slug"
@@ -129,6 +131,10 @@ ActiveRecord::Schema.define(:version =&gt; 20121008185303) do @@ -129,6 +131,10 @@ ActiveRecord::Schema.define(:version =&gt; 20121008185303) do
129 t.integer "license_id" 131 t.integer "license_id"
130 end 132 end
131 133
  134 + add_index "articles", ["name"], :name => "index_articles_on_name"
  135 + add_index "articles", ["parent_id"], :name => "index_articles_on_parent_id"
  136 + add_index "articles", ["profile_id"], :name => "index_articles_on_profile_id"
  137 + add_index "articles", ["slug"], :name => "index_articles_on_slug"
132 add_index "articles", ["translation_of_id"], :name => "index_articles_on_translation_of_id" 138 add_index "articles", ["translation_of_id"], :name => "index_articles_on_translation_of_id"
133 139
134 create_table "articles_categories", :id => false, :force => true do |t| 140 create_table "articles_categories", :id => false, :force => true do |t|
@@ -217,6 +223,8 @@ ActiveRecord::Schema.define(:version =&gt; 20121008185303) do @@ -217,6 +223,8 @@ ActiveRecord::Schema.define(:version =&gt; 20121008185303) do
217 t.string "referrer" 223 t.string "referrer"
218 end 224 end
219 225
  226 + add_index "comments", ["source_id", "spam"], :name => "index_comments_on_source_id_and_spam"
  227 +
220 create_table "contact_lists", :force => true do |t| 228 create_table "contact_lists", :force => true do |t|
221 t.text "list" 229 t.text "list"
222 t.string "error_fetching" 230 t.string "error_fetching"
@@ -280,6 +288,7 @@ ActiveRecord::Schema.define(:version =&gt; 20121008185303) do @@ -280,6 +288,7 @@ ActiveRecord::Schema.define(:version =&gt; 20121008185303) do
280 t.integer "update_errors", :default => 0 288 t.integer "update_errors", :default => 0
281 end 289 end
282 290
  291 + add_index "external_feeds", ["blog_id"], :name => "index_external_feeds_on_blog_id"
283 add_index "external_feeds", ["enabled"], :name => "index_external_feeds_on_enabled" 292 add_index "external_feeds", ["enabled"], :name => "index_external_feeds_on_enabled"
284 add_index "external_feeds", ["fetched_at"], :name => "index_external_feeds_on_fetched_at" 293 add_index "external_feeds", ["fetched_at"], :name => "index_external_feeds_on_fetched_at"
285 294
@@ -295,6 +304,10 @@ ActiveRecord::Schema.define(:version =&gt; 20121008185303) do @@ -295,6 +304,10 @@ ActiveRecord::Schema.define(:version =&gt; 20121008185303) do
295 t.string "group" 304 t.string "group"
296 end 305 end
297 306
  307 + add_index "friendships", ["friend_id"], :name => "index_friendships_on_friend_id"
  308 + add_index "friendships", ["person_id", "friend_id"], :name => "index_friendships_on_person_id_and_friend_id"
  309 + add_index "friendships", ["person_id"], :name => "index_friendships_on_person_id"
  310 +
298 create_table "images", :force => true do |t| 311 create_table "images", :force => true do |t|
299 t.integer "parent_id" 312 t.integer "parent_id"
300 t.string "content_type" 313 t.string "content_type"
@@ -446,6 +459,7 @@ ActiveRecord::Schema.define(:version =&gt; 20121008185303) do @@ -446,6 +459,7 @@ ActiveRecord::Schema.define(:version =&gt; 20121008185303) do
446 end 459 end
447 460
448 add_index "profiles", ["environment_id"], :name => "index_profiles_on_environment_id" 461 add_index "profiles", ["environment_id"], :name => "index_profiles_on_environment_id"
  462 + add_index "profiles", ["identifier"], :name => "index_profiles_on_identifier"
449 add_index "profiles", ["region_id"], :name => "index_profiles_on_region_id" 463 add_index "profiles", ["region_id"], :name => "index_profiles_on_region_id"
450 464
451 create_table "qualifier_certifiers", :force => true do |t| 465 create_table "qualifier_certifiers", :force => true do |t|
debian/changelog
  1 +noosfero (0.39.2) unstable; urgency=low
  2 +
  3 + * Bugfixes release
  4 +
  5 + -- Rodrigo Souto <rodrigo@colivre.coop.br> Sat, 12 Jan 2013 10:13:46 +0000
  6 +
1 noosfero (0.39.1) unstable; urgency=low 7 noosfero (0.39.1) unstable; urgency=low
2 8
3 * Bugfixes release 9 * Bugfixes release
etc/noosfero/varnish-noosfero.vcl
1 sub vcl_recv { 1 sub vcl_recv {
2 if (req.request == "GET" || req.request == "HEAD") { 2 if (req.request == "GET" || req.request == "HEAD") {
3 if (req.http.Cookie) { 3 if (req.http.Cookie) {
4 - # We only care about the "_noosfero_session.*" cookie, used for  
5 - # authentication.  
6 - if (req.http.Cookie !~ "_noosfero_session.*" ) { 4 + # We only care about the "_noosfero_.*" cookies, used by Noosfero
  5 + if (req.http.Cookie !~ "_noosfero_.*" ) {
7 # strip all cookies 6 # strip all cookies
8 unset req.http.Cookie; 7 unset req.http.Cookie;
9 } 8 }
gitignore.example
@@ -21,8 +21,8 @@ public/user_themes @@ -21,8 +21,8 @@ public/user_themes
21 public/designs/themes/default 21 public/designs/themes/default
22 public/designs/themes/* 22 public/designs/themes/*
23 public/designs/icons/default 23 public/designs/icons/default
24 -public/javascripts/cache*.js  
25 -public/stylesheets/cache*.css 24 +public/javascripts/cache*
  25 +public/stylesheets/cache*
26 public/plugins 26 public/plugins
27 db/development.db 27 db/development.db
28 db/production.db 28 db/production.db
lib/noosfero.rb
@@ -2,7 +2,7 @@ require &#39;fast_gettext&#39; @@ -2,7 +2,7 @@ require &#39;fast_gettext&#39;
2 2
3 module Noosfero 3 module Noosfero
4 PROJECT = 'noosfero' 4 PROJECT = 'noosfero'
5 - VERSION = '0.39.1' 5 + VERSION = '0.39.2'
6 6
7 def self.pattern_for_controllers_in_directory(dir) 7 def self.pattern_for_controllers_in_directory(dir)
8 disjunction = controllers_in_directory(dir).join('|') 8 disjunction = controllers_in_directory(dir).join('|')
plugins/shopping_cart/controllers/shopping_cart_plugin_controller.rb 0 → 100644
@@ -0,0 +1,296 @@ @@ -0,0 +1,296 @@
  1 +require 'base64'
  2 +
  3 +class ShoppingCartPluginController < PublicController
  4 +
  5 + include ShoppingCartPlugin::CartHelper
  6 + helper ShoppingCartPlugin::CartHelper
  7 +
  8 + append_view_path File.join(File.dirname(__FILE__) + '/../views')
  9 + before_filter :login_required, :only => []
  10 +
  11 + before_filter :login_required, :only => []
  12 +
  13 + def get
  14 + config =
  15 + if cart.nil?
  16 + { 'enterprise_id' => nil, 'hasProducts' => false }
  17 + else
  18 + { 'enterprise_id' => cart[:enterprise_id], 'hasProducts' => (cart[:items].keys.size > 0) }
  19 + end
  20 + render :text => config.to_json
  21 + end
  22 +
  23 + def add
  24 + product = find_product(params[:id])
  25 + if product && enterprise = validate_same_enterprise(product)
  26 + self.cart = { :enterprise_id => enterprise.id, :items => {} } if self.cart.nil?
  27 + self.cart[:items][product.id] = 0 if self.cart[:items][product.id].nil?
  28 + self.cart[:items][product.id] += 1
  29 + render :text => {
  30 + :ok => true,
  31 + :error => {:code => 0},
  32 + :products => [{
  33 + :id => product.id,
  34 + :name => product.name,
  35 + :price => get_price(product, enterprise.environment),
  36 + :description => product.description,
  37 + :picture => product.default_image(:minor),
  38 + :quantity => self.cart[:items][product.id]
  39 + }]
  40 + }.to_json
  41 + end
  42 + end
  43 +
  44 + def remove
  45 + id = params[:id].to_i
  46 + if validate_cart_presence && validate_cart_has_product(id)
  47 + self.cart[:items].delete(id)
  48 + self.cart = nil if self.cart[:items].empty?
  49 + render :text => {
  50 + :ok => true,
  51 + :error => {:code => 0},
  52 + :product_id => id
  53 + }.to_json
  54 + end
  55 + end
  56 +
  57 + def list
  58 + if validate_cart_presence
  59 + products = self.cart[:items].collect do |id, quantity|
  60 + product = Product.find(id)
  61 + { :id => product.id,
  62 + :name => product.name,
  63 + :price => get_price(product, product.enterprise.environment),
  64 + :description => product.description,
  65 + :picture => product.default_image(:minor),
  66 + :quantity => quantity
  67 + }
  68 + end
  69 + render :text => {
  70 + :ok => true,
  71 + :error => {:code => 0},
  72 + :products => products
  73 + }.to_json
  74 + end
  75 + end
  76 +
  77 + def update_quantity
  78 + quantity = params[:quantity].to_i
  79 + id = params[:id].to_i
  80 + if validate_cart_presence && validate_cart_has_product(id) && validate_item_quantity(quantity)
  81 + product = Product.find(id)
  82 + self.cart[:items][product.id] = quantity
  83 + render :text => {
  84 + :ok => true,
  85 + :error => {:code => 0},
  86 + :product_id => id,
  87 + :quantity => quantity
  88 + }.to_json
  89 + end
  90 + end
  91 +
  92 + def clean
  93 + self.cart = nil
  94 + render :text => {
  95 + :ok => true,
  96 + :error => {:code => 0}
  97 + }.to_json
  98 + end
  99 +
  100 + def buy
  101 + @cart = cart
  102 + @enterprise = environment.enterprises.find(cart[:enterprise_id])
  103 + render :layout => false
  104 + end
  105 +
  106 + def send_request
  107 + register_order(params[:customer], self.cart[:items])
  108 + begin
  109 + enterprise = Enterprise.find(cart[:enterprise_id])
  110 + ShoppingCartPlugin::Mailer.deliver_customer_notification(params[:customer], enterprise, self.cart[:items])
  111 + ShoppingCartPlugin::Mailer.deliver_supplier_notification(params[:customer], enterprise, self.cart[:items])
  112 + self.cart = nil
  113 + render :text => {
  114 + :ok => true,
  115 + :message => _('Request sent successfully. Check your email.'),
  116 + :error => {:code => 0}
  117 + }.to_json
  118 + rescue ActiveRecord::ActiveRecordError
  119 + render :text => {
  120 + :ok => false,
  121 + :error => {
  122 + :code => 6,
  123 + :message => exception.message
  124 + }
  125 + }.to_json
  126 + end
  127 + end
  128 +
  129 + def visibility
  130 + render :text => self.cart.has_key?(:visibility) ? self.cart[:visibility].to_json : true.to_json
  131 + end
  132 +
  133 + def show
  134 + begin
  135 + self.cart[:visibility] = true
  136 + render :text => {
  137 + :ok => true,
  138 + :message => _('Basket displayed.'),
  139 + :error => {:code => 0}
  140 + }.to_json
  141 + rescue Exception => exception
  142 + render :text => {
  143 + :ok => false,
  144 + :error => {
  145 + :code => 7,
  146 + :message => exception.message
  147 + }
  148 + }.to_json
  149 + end
  150 + end
  151 +
  152 + def hide
  153 + begin
  154 + self.cart[:visibility] = false
  155 + render :text => {
  156 + :ok => true,
  157 + :message => _('Basket hidden.'),
  158 + :error => {:code => 0}
  159 + }.to_json
  160 + rescue Exception => exception
  161 + render :text => {
  162 + :ok => false,
  163 + :error => {
  164 + :code => 8,
  165 + :message => exception.message
  166 + }
  167 + }.to_json
  168 + end
  169 + end
  170 +
  171 + private
  172 +
  173 + def validate_same_enterprise(product)
  174 + if self.cart && self.cart[:enterprise_id] && product.enterprise_id != self.cart[:enterprise_id]
  175 + render :text => {
  176 + :ok => false,
  177 + :error => {
  178 + :code => 1,
  179 + :message => _("Can't join items from different enterprises.")
  180 + }
  181 + }.to_json
  182 + return nil
  183 + end
  184 + product.enterprise
  185 + end
  186 +
  187 + def validate_cart_presence
  188 + if self.cart.nil?
  189 + render :text => {
  190 + :ok => false,
  191 + :error => {
  192 + :code => 2,
  193 + :message => _("There is no basket.")
  194 + }
  195 + }.to_json
  196 + return false
  197 + end
  198 + true
  199 + end
  200 +
  201 + def find_product(id)
  202 + begin
  203 + product = Product.find(id)
  204 + rescue ActiveRecord::RecordNotFound
  205 + render :text => {
  206 + :ok => false,
  207 + :error => {
  208 + :code => 3,
  209 + :message => _("This enterprise doesn't have this product.")
  210 + }
  211 + }.to_json
  212 + return nil
  213 + end
  214 + product
  215 + end
  216 +
  217 + def validate_cart_has_product(id)
  218 + if !self.cart[:items].has_key?(id)
  219 + render :text => {
  220 + :ok => false,
  221 + :error => {
  222 + :code => 4,
  223 + :message => _("The basket doesn't have this product.")
  224 + }
  225 + }.to_json
  226 + return false
  227 + end
  228 + true
  229 + end
  230 +
  231 + def validate_item_quantity(quantity)
  232 + if quantity.to_i < 1
  233 + render :text => {
  234 + :ok => false,
  235 + :error => {
  236 + :code => 5,
  237 + :message => _("Invalid quantity.")
  238 + }
  239 + }.to_json
  240 + return false
  241 + end
  242 + true
  243 + end
  244 +
  245 + def register_order(custumer, items)
  246 + new_items = {}
  247 + items.each do |id, quantity|
  248 + product = Product.find(id)
  249 + price = product.price || 0
  250 + new_items[id] = {:quantity => quantity, :price => price, :name => product.name}
  251 + end
  252 + ShoppingCartPlugin::PurchaseOrder.create!(
  253 + :seller => Enterprise.find(cart[:enterprise_id]),
  254 + :customer => user,
  255 + :status => ShoppingCartPlugin::PurchaseOrder::Status::OPENED,
  256 + :products_list => new_items,
  257 + :customer_name => params[:customer][:name],
  258 + :customer_email => params[:customer][:email],
  259 + :customer_contact_phone => params[:customer][:contact_phone],
  260 + :customer_address => params[:customer][:address],
  261 + :customer_city => params[:customer][:city],
  262 + :customer_zip_code => params[:customer][:zip_code]
  263 + )
  264 + end
  265 +
  266 + protected
  267 +
  268 + def cart
  269 + @cart ||=
  270 + begin
  271 + cookies[cookie_key] && YAML.load(Base64.decode64(cookies[cookie_key])) || nil
  272 + end
  273 + @cart
  274 + end
  275 +
  276 + def cart=(data)
  277 + @cart = data
  278 + end
  279 +
  280 + after_filter :save_cookie
  281 + def save_cookie
  282 + if @cart.nil?
  283 + cookies.delete(cookie_key, :path => '/plugin/shopping_cart')
  284 + else
  285 + cookies[cookie_key] = {
  286 + :value => Base64.encode64(@cart.to_yaml),
  287 + :path => "/plugin/shopping_cart"
  288 + }
  289 + end
  290 + end
  291 +
  292 + def cookie_key
  293 + :_noosfero_plugin_shopping_cart
  294 + end
  295 +
  296 +end
plugins/shopping_cart/controllers/shopping_cart_plugin_profile_controller.rb
@@ -1,248 +0,0 @@ @@ -1,248 +0,0 @@
1 -include ShoppingCartPlugin::CartHelper  
2 -  
3 -class ShoppingCartPluginProfileController < ProfileController  
4 - append_view_path File.join(File.dirname(__FILE__) + '/../views')  
5 - before_filter :login_required, :only => []  
6 -  
7 - before_filter :login_required, :only => []  
8 -  
9 - def add  
10 - session[:cart] = { :enterprise_id => profile.id, :items => {} } if session[:cart].nil?  
11 - if validate_same_enterprise && product = validate_enterprise_has_product(params[:id])  
12 - session[:cart][:items][product.id] = 0 if session[:cart][:items][product.id].nil?  
13 - session[:cart][:items][product.id] += 1  
14 - render :text => {  
15 - :ok => true,  
16 - :error => {:code => 0},  
17 - :products => [{  
18 - :id => product.id,  
19 - :name => product.name,  
20 - :price => get_price(product, profile.environment),  
21 - :description => product.description,  
22 - :picture => product.default_image(:minor),  
23 - :quantity => session[:cart][:items][product.id]  
24 - }]  
25 - }.to_json  
26 - end  
27 - end  
28 -  
29 - def remove  
30 - id = params[:id].to_i  
31 - if validate_cart_presence && validate_cart_has_product(id)  
32 - session[:cart][:items].delete(id)  
33 - session[:cart] = nil if session[:cart][:items].empty?  
34 - render :text => {  
35 - :ok => true,  
36 - :error => {:code => 0},  
37 - :product_id => id  
38 - }.to_json  
39 - end  
40 - end  
41 -  
42 - def list  
43 - if validate_cart_presence  
44 - products = session[:cart][:items].collect do |id, quantity|  
45 - product = Product.find(id)  
46 - { :id => product.id,  
47 - :name => product.name,  
48 - :price => get_price(product, profile.environment),  
49 - :description => product.description,  
50 - :picture => product.default_image(:minor),  
51 - :quantity => quantity  
52 - }  
53 - end  
54 - render :text => {  
55 - :ok => true,  
56 - :error => {:code => 0},  
57 - :enterprise => Enterprise.find(session[:cart][:enterprise_id]).identifier,  
58 - :products => products  
59 - }.to_json  
60 - end  
61 - end  
62 -  
63 - def update_quantity  
64 - quantity = params[:quantity].to_i  
65 - id = params[:id].to_i  
66 - if validate_cart_presence && validate_cart_has_product(id) && validate_item_quantity(quantity)  
67 - product = Product.find(id)  
68 - session[:cart][:items][product.id] = quantity  
69 - render :text => {  
70 - :ok => true,  
71 - :error => {:code => 0},  
72 - :product_id => id,  
73 - :quantity => quantity  
74 - }.to_json  
75 - end  
76 - end  
77 -  
78 - def clean  
79 - session[:cart] = nil  
80 - render :text => {  
81 - :ok => true,  
82 - :error => {:code => 0}  
83 - }.to_json  
84 - end  
85 -  
86 - def buy  
87 - @environment = profile.environment  
88 - render :layout => false  
89 - end  
90 -  
91 - def send_request  
92 - register_order(params[:customer], session[:cart][:items])  
93 - begin  
94 - ShoppingCartPlugin::Mailer.deliver_customer_notification(params[:customer], profile, session[:cart][:items])  
95 - ShoppingCartPlugin::Mailer.deliver_supplier_notification(params[:customer], profile, session[:cart][:items])  
96 - render :text => {  
97 - :ok => true,  
98 - :message => _('Request sent successfully. Check your email.'),  
99 - :error => {:code => 0}  
100 - }.to_json  
101 - rescue Exception => exception  
102 - render :text => {  
103 - :ok => false,  
104 - :error => {  
105 - :code => 6,  
106 - :message => exception.message  
107 - }  
108 - }.to_json  
109 - end  
110 - end  
111 -  
112 - def visibility  
113 - render :text => session[:cart].has_key?(:visibility) ? session[:cart][:visibility].to_json : true.to_json  
114 - end  
115 -  
116 - def show  
117 - begin  
118 - session[:cart][:visibility] = true  
119 - render :text => {  
120 - :ok => true,  
121 - :message => _('Basket displayed.'),  
122 - :error => {:code => 0}  
123 - }.to_json  
124 - rescue Exception => exception  
125 - render :text => {  
126 - :ok => false,  
127 - :error => {  
128 - :code => 7,  
129 - :message => exception.message  
130 - }  
131 - }.to_json  
132 - end  
133 - end  
134 -  
135 - def hide  
136 - begin  
137 - session[:cart][:visibility] = false  
138 - render :text => {  
139 - :ok => true,  
140 - :message => _('Basket hidden.'),  
141 - :error => {:code => 0}  
142 - }.to_json  
143 - rescue Exception => exception  
144 - render :text => {  
145 - :ok => false,  
146 - :error => {  
147 - :code => 8,  
148 - :message => exception.message  
149 - }  
150 - }.to_json  
151 - end  
152 - end  
153 -  
154 - private  
155 -  
156 - def validate_same_enterprise  
157 - if profile.id != session[:cart][:enterprise_id]  
158 - render :text => {  
159 - :ok => false,  
160 - :error => {  
161 - :code => 1,  
162 - :message => _("Can't join items from different enterprises.")  
163 - }  
164 - }.to_json  
165 - return false  
166 - end  
167 - true  
168 - end  
169 -  
170 - def validate_cart_presence  
171 - if session[:cart].nil?  
172 - render :text => {  
173 - :ok => false,  
174 - :error => {  
175 - :code => 2,  
176 - :message => _("There is no basket.")  
177 - }  
178 - }.to_json  
179 - return false  
180 - end  
181 - true  
182 - end  
183 -  
184 - def validate_enterprise_has_product(id)  
185 - begin  
186 - product = profile.products.find(id)  
187 - rescue  
188 - render :text => {  
189 - :ok => false,  
190 - :error => {  
191 - :code => 3,  
192 - :message => _("This enterprise doesn't have this product.")  
193 - }  
194 - }.to_json  
195 - return nil  
196 - end  
197 - product  
198 - end  
199 -  
200 - def validate_cart_has_product(id)  
201 - if !session[:cart][:items].has_key?(id)  
202 - render :text => {  
203 - :ok => false,  
204 - :error => {  
205 - :code => 4,  
206 - :message => _("The basket doesn't have this product.")  
207 - }  
208 - }.to_json  
209 - return false  
210 - end  
211 - true  
212 - end  
213 -  
214 - def validate_item_quantity(quantity)  
215 - if quantity.to_i < 1  
216 - render :text => {  
217 - :ok => false,  
218 - :error => {  
219 - :code => 5,  
220 - :message => _("Invalid quantity.")  
221 - }  
222 - }.to_json  
223 - return false  
224 - end  
225 - true  
226 - end  
227 -  
228 - def register_order(custumer, items)  
229 - new_items = {}  
230 - items.each do |id, quantity|  
231 - product = Product.find(id)  
232 - price = product.price || 0  
233 - new_items[id] = {:quantity => quantity, :price => price, :name => product.name}  
234 - end  
235 - ShoppingCartPlugin::PurchaseOrder.create!(  
236 - :seller => profile,  
237 - :customer => user,  
238 - :status => ShoppingCartPlugin::PurchaseOrder::Status::OPENED,  
239 - :products_list => new_items,  
240 - :customer_name => params[:customer][:name],  
241 - :customer_email => params[:customer][:email],  
242 - :customer_contact_phone => params[:customer][:contact_phone],  
243 - :customer_address => params[:customer][:address],  
244 - :customer_city => params[:customer][:city],  
245 - :customer_zip_code => params[:customer][:zip_code]  
246 - )  
247 - end  
248 -end  
plugins/shopping_cart/lib/shopping_cart_plugin.rb
@@ -11,12 +11,13 @@ class ShoppingCartPlugin &lt; Noosfero::Plugin @@ -11,12 +11,13 @@ class ShoppingCartPlugin &lt; Noosfero::Plugin
11 _("A shopping basket feature for enterprises") 11 _("A shopping basket feature for enterprises")
12 end 12 end
13 13
14 - def add_to_cart_button(item, enterprise = context.profile) 14 + def add_to_cart_button(item)
  15 + enterprise = item.enterprise
15 if enterprise.shopping_cart && item.available 16 if enterprise.shopping_cart && item.available
16 lambda { 17 lambda {
17 link_to(_('Add to basket'), "add:#{item.name}", 18 link_to(_('Add to basket'), "add:#{item.name}",
18 :class => 'cart-add-item', 19 :class => 'cart-add-item',
19 - :onclick => "Cart.addItem('#{enterprise.identifier}', #{item.id}, this); return false" 20 + :onclick => "Cart.addItem(#{item.id}, this); return false"
20 ) 21 )
21 } 22 }
22 end 23 end
@@ -35,7 +36,7 @@ class ShoppingCartPlugin &lt; Noosfero::Plugin @@ -35,7 +36,7 @@ class ShoppingCartPlugin &lt; Noosfero::Plugin
35 end 36 end
36 37
37 def body_beginning 38 def body_beginning
38 - expanded_template('cart.html.erb',{:cart => context.session[:cart]}) 39 + expanded_template('cart.html.erb')
39 end 40 end
40 41
41 def control_panel_buttons 42 def control_panel_buttons
plugins/shopping_cart/lib/shopping_cart_plugin/cart_helper.rb
1 module ShoppingCartPlugin::CartHelper 1 module ShoppingCartPlugin::CartHelper
2 2
3 include ActionView::Helpers::NumberHelper 3 include ActionView::Helpers::NumberHelper
  4 + include ActionView::Helpers::TagHelper
4 5
5 def sell_price(product) 6 def sell_price(product)
6 return 0 if product.price.nil? 7 return 0 if product.price.nil?
plugins/shopping_cart/lib/shopping_cart_plugin/mailer.rb
1 class ShoppingCartPlugin::Mailer < Noosfero::Plugin::MailerBase 1 class ShoppingCartPlugin::Mailer < Noosfero::Plugin::MailerBase
2 2
  3 + include ShoppingCartPlugin::CartHelper
  4 +
3 def customer_notification(customer, supplier, items) 5 def customer_notification(customer, supplier, items)
4 domain = supplier.hostname || supplier.environment.default_hostname 6 domain = supplier.hostname || supplier.environment.default_hostname
5 recipients customer[:email] 7 recipients customer[:email]
@@ -10,7 +12,8 @@ class ShoppingCartPlugin::Mailer &lt; Noosfero::Plugin::MailerBase @@ -10,7 +12,8 @@ class ShoppingCartPlugin::Mailer &lt; Noosfero::Plugin::MailerBase
10 body :customer => customer, 12 body :customer => customer,
11 :supplier => supplier, 13 :supplier => supplier,
12 :items => items, 14 :items => items,
13 - :environment => supplier.environment 15 + :environment => supplier.environment,
  16 + :helper => self
14 end 17 end
15 18
16 def supplier_notification(customer, supplier, items) 19 def supplier_notification(customer, supplier, items)
@@ -23,6 +26,8 @@ class ShoppingCartPlugin::Mailer &lt; Noosfero::Plugin::MailerBase @@ -23,6 +26,8 @@ class ShoppingCartPlugin::Mailer &lt; Noosfero::Plugin::MailerBase
23 body :customer => customer, 26 body :customer => customer,
24 :supplier => supplier, 27 :supplier => supplier,
25 :items => items, 28 :items => items,
26 - :environment => supplier.environment 29 + :environment => supplier.environment,
  30 + :helper => self
  31 +
27 end 32 end
28 end 33 end
plugins/shopping_cart/public/cart.js
@@ -11,10 +11,9 @@ function Cart(config) { @@ -11,10 +11,9 @@ function Cart(config) {
11 $(".cart-buy", this.cartElem).button({ icons: { primary: 'ui-icon-cart'} }); 11 $(".cart-buy", this.cartElem).button({ icons: { primary: 'ui-icon-cart'} });
12 if (!this.empty) { 12 if (!this.empty) {
13 $(this.cartElem).show(); 13 $(this.cartElem).show();
14 - this.enterprise = config.enterprise;  
15 me = this; 14 me = this;
16 $.ajax({ 15 $.ajax({
17 - url: '/profile/'+ this.enterprise +'/plugin/shopping_cart/visibility', 16 + url: '/plugin/shopping_cart/visibility',
18 dataType: 'json', 17 dataType: 'json',
19 success: function(data, status, ajax){ 18 success: function(data, status, ajax){
20 me.visible = /^true$/i.test(data); 19 me.visible = /^true$/i.test(data);
@@ -25,7 +24,7 @@ function Cart(config) { @@ -25,7 +24,7 @@ function Cart(config) {
25 alert('Visibility - HTTP '+status+': '+errorThrown); 24 alert('Visibility - HTTP '+status+': '+errorThrown);
26 } 25 }
27 }); 26 });
28 - $(".cart-buy", this.cartElem).colorbox({href: '/profile/' + this.enterprise + '/plugin/shopping_cart/buy'}); 27 + $(".cart-buy", this.cartElem).colorbox({ href: '/plugin/shopping_cart/buy' });
29 } 28 }
30 } 29 }
31 30
@@ -34,7 +33,7 @@ function Cart(config) { @@ -34,7 +33,7 @@ function Cart(config) {
34 Cart.prototype.listProducts = function() { 33 Cart.prototype.listProducts = function() {
35 var me = this; 34 var me = this;
36 $.ajax({ 35 $.ajax({
37 - url: '/profile/'+ this.enterprise +'/plugin/shopping_cart/list', 36 + url: '/plugin/shopping_cart/list',
38 dataType: 'json', 37 dataType: 'json',
39 success: function(data, ststus, ajax){ 38 success: function(data, ststus, ajax){
40 if ( !data.ok ) alert(data.error.message); 39 if ( !data.ok ) alert(data.error.message);
@@ -61,7 +60,7 @@ function Cart(config) { @@ -61,7 +60,7 @@ function Cart(config) {
61 '<span class="item-name">'+ item.name +'</span>' + 60 '<span class="item-name">'+ item.name +'</span>' +
62 '<div class="item-price">' + 61 '<div class="item-price">' +
63 '<input size="1" value="'+item.quantity+'" />'+ (item.price ? '&times; '+ item.price : '') +'</div>' + 62 '<input size="1" value="'+item.quantity+'" />'+ (item.price ? '&times; '+ item.price : '') +'</div>' +
64 - ' <a href="remove:'+item.name+'" onclick="Cart.removeItem(\''+this.enterprise+'\', '+item.id+'); return false"' + 63 + ' <a href="remove:'+item.name+'" onclick="Cart.removeItem('+item.id+'); return false"' +
65 ' class="button icon-remove"><span>remove</span></a>' 64 ' class="button icon-remove"><span>remove</span></a>'
66 ).appendTo(li); 65 ).appendTo(li);
67 var input = $("input", li)[0]; 66 var input = $("input", li)[0];
@@ -100,7 +99,7 @@ function Cart(config) { @@ -100,7 +99,7 @@ function Cart(config) {
100 var me = this; 99 var me = this;
101 if( quantity == NaN ) return input.value = input.lastValue; 100 if( quantity == NaN ) return input.value = input.lastValue;
102 $.ajax({ 101 $.ajax({
103 - url: '/profile/'+ this.enterprise +'/plugin/shopping_cart/update_quantity/'+ itemId +'?quantity='+ quantity, 102 + url: '/plugin/shopping_cart/update_quantity/'+ itemId +'?quantity='+ quantity,
104 dataType: 'json', 103 dataType: 'json',
105 success: function(data, status, ajax){ 104 success: function(data, status, ajax){
106 if ( !data.ok ) { 105 if ( !data.ok ) {
@@ -132,8 +131,7 @@ function Cart(config) { @@ -132,8 +131,7 @@ function Cart(config) {
132 this.updateTotal(); 131 this.updateTotal();
133 } 132 }
134 133
135 - Cart.addItem = function(enterprise, itemId, link) {  
136 - // on the future, the instance may be found by the enterprise identifier. 134 + Cart.addItem = function(itemId, link) {
137 link.intervalId = setInterval(function() { 135 link.intervalId = setInterval(function() {
138 steps = ['w', 'n', 'e', 's']; 136 steps = ['w', 'n', 'e', 's'];
139 if( !link.step || link.step==3 ) link.step = 0; 137 if( !link.step || link.step==3 ) link.step = 0;
@@ -144,18 +142,13 @@ function Cart(config) { @@ -144,18 +142,13 @@ function Cart(config) {
144 clearInterval(link.intervalId); 142 clearInterval(link.intervalId);
145 $(link).button({ icons: { primary: 'ui-icon-cart'}, disable: false }); 143 $(link).button({ icons: { primary: 'ui-icon-cart'}, disable: false });
146 }; 144 };
147 - this.instance.addItem(enterprise, itemId, stopBtLoading); 145 + this.instance.addItem(itemId, stopBtLoading);
148 } 146 }
149 147
150 - Cart.prototype.addItem = function(enterprise, itemId, callback) {  
151 - if(!this.enterprise) {  
152 - this.enterprise = enterprise;  
153 - $(".cart-buy", this.cartElem).colorbox({href: '/profile/' + this.enterprise + '/plugin/shopping_cart/buy'});  
154 -// $(this.cartElem).show();  
155 - } 148 + Cart.prototype.addItem = function(itemId, callback) {
156 var me = this; 149 var me = this;
157 $.ajax({ 150 $.ajax({
158 - url: '/profile/'+ enterprise +'/plugin/shopping_cart/add/'+ itemId, 151 + url: '/plugin/shopping_cart/add/'+ itemId,
159 dataType: 'json', 152 dataType: 'json',
160 success: function(data, status, ajax){ 153 success: function(data, status, ajax){
161 if ( !data.ok ) alert(data.error.message); 154 if ( !data.ok ) alert(data.error.message);
@@ -169,16 +162,16 @@ function Cart(config) { @@ -169,16 +162,16 @@ function Cart(config) {
169 }); 162 });
170 } 163 }
171 164
172 - Cart.removeItem = function(enterprise, itemId) { 165 + Cart.removeItem = function(itemId) {
173 var message = this.instance.cartElem.getAttribute('data-l10nRemoveItem'); 166 var message = this.instance.cartElem.getAttribute('data-l10nRemoveItem');
174 - if( confirm(message) ) this.instance.removeItem(enterprise, itemId); 167 + if( confirm(message) ) this.instance.removeItem(itemId);
175 } 168 }
176 169
177 - Cart.prototype.removeItem = function(enterprise, itemId) { 170 + Cart.prototype.removeItem = function(itemId) {
178 if ($("li", this.itemsBox).size() < 2) return this.clean(); 171 if ($("li", this.itemsBox).size() < 2) return this.clean();
179 var me = this; 172 var me = this;
180 $.ajax({ 173 $.ajax({
181 - url: '/profile/'+ enterprise +'/plugin/shopping_cart/remove/'+ itemId, 174 + url: '/plugin/shopping_cart/remove/'+ itemId,
182 dataType: 'json', 175 dataType: 'json',
183 success: function(data, status, ajax){ 176 success: function(data, status, ajax){
184 if ( !data.ok ) alert(data.error.message); 177 if ( !data.ok ) alert(data.error.message);
@@ -200,7 +193,7 @@ function Cart(config) { @@ -200,7 +193,7 @@ function Cart(config) {
200 193
201 Cart.prototype.show = function() { 194 Cart.prototype.show = function() {
202 $.ajax({ 195 $.ajax({
203 - url: '/profile/'+ this.enterprise +'/plugin/shopping_cart/show', 196 + url: '/plugin/shopping_cart/show',
204 dataType: 'json', 197 dataType: 'json',
205 cache: false, 198 cache: false,
206 error: function(ajax, status, errorThrown) { 199 error: function(ajax, status, errorThrown) {
@@ -215,7 +208,7 @@ function Cart(config) { @@ -215,7 +208,7 @@ function Cart(config) {
215 } 208 }
216 Cart.prototype.hide = function() { 209 Cart.prototype.hide = function() {
217 $.ajax({ 210 $.ajax({
218 - url: '/profile/'+ this.enterprise +'/plugin/shopping_cart/hide', 211 + url: '/plugin/shopping_cart/hide',
219 dataType: 'json', 212 dataType: 'json',
220 cache: false, 213 cache: false,
221 error: function(ajax, status, errorThrown) { 214 error: function(ajax, status, errorThrown) {
@@ -252,7 +245,7 @@ function Cart(config) { @@ -252,7 +245,7 @@ function Cart(config) {
252 Cart.prototype.clean = function() { 245 Cart.prototype.clean = function() {
253 var me = this; 246 var me = this;
254 $.ajax({ 247 $.ajax({
255 - url: '/profile/'+ me.enterprise +'/plugin/shopping_cart/clean', 248 + url: '/plugin/shopping_cart/clean',
256 dataType: 'json', 249 dataType: 'json',
257 success: function(data, status, ajax){ 250 success: function(data, status, ajax){
258 if ( !data.ok ) alert(data.error.message); 251 if ( !data.ok ) alert(data.error.message);
@@ -261,7 +254,6 @@ function Cart(config) { @@ -261,7 +254,6 @@ function Cart(config) {
261 $(me.cartElem).slideUp(500, function() { 254 $(me.cartElem).slideUp(500, function() {
262 $(me.itemsBox).empty(); 255 $(me.itemsBox).empty();
263 me.hide(); 256 me.hide();
264 - me.enterprise = null;  
265 me.updateTotal(); 257 me.updateTotal();
266 me.empty = true; 258 me.empty = true;
267 }); 259 });
@@ -284,7 +276,7 @@ function Cart(config) { @@ -284,7 +276,7 @@ function Cart(config) {
284 var me = this; 276 var me = this;
285 $.ajax({ 277 $.ajax({
286 type: 'POST', 278 type: 'POST',
287 - url: '/profile/'+ me.enterprise +'/plugin/shopping_cart/send_request', 279 + url: '/plugin/shopping_cart/send_request',
288 data: params, 280 data: params,
289 dataType: 'json', 281 dataType: 'json',
290 success: function(data, status, ajax){ 282 success: function(data, status, ajax){
@@ -309,7 +301,19 @@ function Cart(config) { @@ -309,7 +301,19 @@ function Cart(config) {
309 } 301 }
310 302
311 $(function(){ 303 $(function(){
312 - $('.cart-add-item').button({ icons: { primary: 'ui-icon-cart'} }) 304 +
  305 + $.ajax({
  306 + url: "/plugin/shopping_cart/get",
  307 + dataType: 'json',
  308 + success: function(data) {
  309 + new Cart(data);
  310 + $('.cart-add-item').button({ icons: { primary: 'ui-icon-cart'} })
  311 + },
  312 + cache: false,
  313 + error: function(ajax, status, errorThrown) {
  314 + alert('Error getting shopping cart - HTTP '+status+': '+errorThrown);
  315 + }
  316 + });
313 }); 317 });
314 318
315 })(jQuery); 319 })(jQuery);
plugins/shopping_cart/public/style.css
1 -@import url(colorbox/colorbox.css);  
2 -  
3 .cart-add-item .ui-icon-cart { 1 .cart-add-item .ui-icon-cart {
4 background: url("/plugins/shopping_cart/images/button-icon.png") no-repeat scroll left center transparent; 2 background: url("/plugins/shopping_cart/images/button-icon.png") no-repeat scroll left center transparent;
5 width: 22px; 3 width: 22px;
plugins/shopping_cart/test/functional/shopping_cart_plugin_controller_test.rb 0 → 100644
@@ -0,0 +1,225 @@ @@ -0,0 +1,225 @@
  1 +require File.dirname(__FILE__) + '/../../../../test/test_helper'
  2 +require File.dirname(__FILE__) + '/../../controllers/shopping_cart_plugin_controller'
  3 +
  4 +# Re-raise errors caught by the controller.
  5 +class ShoppingCartPluginController; def rescue_action(e) raise e end; end
  6 +
  7 +class ShoppingCartPluginControllerTest < ActionController::TestCase
  8 +
  9 + def setup
  10 + @controller = ShoppingCartPluginController.new
  11 + @request = ActionController::TestRequest.new
  12 + @response = ActionController::TestResponse.new
  13 + @enterprise = fast_create(Enterprise)
  14 + @product = fast_create(Product, :enterprise_id => @enterprise.id)
  15 + end
  16 + attr_reader :enterprise
  17 + attr_reader :product
  18 +
  19 + should 'force cookie expiration with explicit path for an empty cart' do
  20 + get :get
  21 + assert @response.headers['Set-Cookie'].any? { |c| c =~ /_noosfero_plugin_shopping_cart=; path=\/plugin\/shopping_cart; expires=.*-1970/}
  22 + end
  23 +
  24 + should 'add a new product to cart' do
  25 + get :add, :id => product.id
  26 +
  27 + assert product_in_cart?(product)
  28 + assert_equal 1, product_quantity(product)
  29 + end
  30 +
  31 + should 'grow quantity through add' do
  32 + get :add, :id => product.id
  33 + assert_equal 1, product_quantity(product)
  34 +
  35 + get :add, :id => product.id
  36 + assert_equal 2, product_quantity(product)
  37 + end
  38 +
  39 + should 'not add product to cart if it does not exists' do
  40 + assert_nothing_raised { get :add, :id => 9999 }
  41 +
  42 + assert !product_in_cart?(product)
  43 + assert !response_ok?
  44 + assert 3, reponse_error_code
  45 + end
  46 +
  47 + should 'remove cart if the product being removed is the last one' do
  48 + get :add, :id => product.id
  49 + assert cart?
  50 +
  51 + get :remove, :id => product.id
  52 + assert !cart?
  53 + end
  54 +
  55 + should 'not try to remove a product if there is no cart' do
  56 + instantiate_cart
  57 + assert !cart?
  58 +
  59 + assert_nothing_raised { get :remove, :id => 9999 }
  60 + assert !response_ok?
  61 + assert_equal 2, reponse_error_code
  62 + end
  63 +
  64 + should 'just remove product if there are other products on cart' do
  65 + another_product = fast_create(Product, :enterprise_id => enterprise.id)
  66 + get :add, :id => product.id
  67 + get :add, :id => another_product.id
  68 +
  69 + get :remove, :id => product.id
  70 + assert cart?
  71 + assert !product_in_cart?(product)
  72 + end
  73 +
  74 + should 'not try to remove a product that is not in the cart' do
  75 + get :add, :id => product.id
  76 + assert cart?
  77 + assert_nothing_raised { get :remove, :id => 9999 }
  78 +
  79 + assert !response_ok?
  80 + assert_equal 4, reponse_error_code
  81 + end
  82 +
  83 + should 'not try to list the cart if there is no cart' do
  84 + instantiate_cart
  85 + assert !cart?
  86 +
  87 + assert_nothing_raised { get :list }
  88 + assert !response_ok?
  89 + assert_equal 2, reponse_error_code
  90 + end
  91 +
  92 + should 'list products without errors' do
  93 + get :add, :id => product.id
  94 +
  95 + assert_nothing_raised { get :list }
  96 + assert response_ok?
  97 + end
  98 +
  99 + should 'update the quantity of a product' do
  100 + get :add, :id => product.id
  101 + assert 1, product_quantity(product)
  102 +
  103 + get :update_quantity, :id => product.id, :quantity => 3
  104 + assert 3, product_quantity(product)
  105 + end
  106 +
  107 + should 'not try to update quantity the quantity of a product if there is no cart' do
  108 + instantiate_cart
  109 + assert !cart?
  110 +
  111 + assert_nothing_raised { get :update_quantity, :id => 9999, :quantity => 3 }
  112 + assert !response_ok?
  113 + assert_equal 2, reponse_error_code
  114 + end
  115 +
  116 + should 'not try to update the quantity of a product that is not in the cart' do
  117 + get :add, :id => product.id
  118 + assert cart?
  119 + assert_nothing_raised { get :update_quantity, :id => 9999, :quantity => 3 }
  120 +
  121 + assert !response_ok?
  122 + assert_equal 4, reponse_error_code
  123 + end
  124 +
  125 + should 'not update the quantity of a product with a invalid value' do
  126 + get :add, :id => product.id
  127 +
  128 + assert_nothing_raised { get :update_quantity, :id => product.id, :quantity => -1}
  129 + assert !response_ok?
  130 + assert_equal 5, reponse_error_code
  131 +
  132 + assert_nothing_raised { get :update_quantity, :id => product.id, :quantity => 'asdf'}
  133 + assert !response_ok?
  134 + assert_equal 5, reponse_error_code
  135 + end
  136 +
  137 + should 'clean the cart' do
  138 + another_product = fast_create(Product, :enterprise_id => enterprise.id)
  139 + get :add, :id => product.id
  140 + get :add, :id => another_product.id
  141 +
  142 + assert_nothing_raised { get :clean }
  143 + assert !cart?
  144 + end
  145 +
  146 + should 'not crash if there is no cart' do
  147 + instantiate_cart
  148 + assert !cart?
  149 + assert_nothing_raised { get :clean }
  150 + end
  151 +
  152 + should 'register order on send request' do
  153 + product1 = fast_create(Product, :enterprise_id => enterprise.id, :price => 1.99)
  154 + product2 = fast_create(Product, :enterprise_id => enterprise.id, :price => 2.23)
  155 + @controller.stubs(:cart).returns({ :enterprise_id => enterprise.id, :items => {product1.id => 1, product2.id => 2}})
  156 + assert_difference ShoppingCartPlugin::PurchaseOrder, :count, 1 do
  157 + post :send_request,
  158 + :customer => {:name => "Manuel", :email => "manuel@ceu.com"}
  159 + end
  160 +
  161 + order = ShoppingCartPlugin::PurchaseOrder.last
  162 +
  163 + assert_equal 1.99, order.products_list[product1.id][:price]
  164 + assert_equal 1, order.products_list[product1.id][:quantity]
  165 + assert_equal 2.23, order.products_list[product2.id][:price]
  166 + assert_equal 2, order.products_list[product2.id][:quantity]
  167 + assert_equal ShoppingCartPlugin::PurchaseOrder::Status::OPENED, order.status
  168 + end
  169 +
  170 + should 'register order on send request and not crash if product is not defined' do
  171 + product1 = fast_create(Product, :enterprise_id => enterprise.id)
  172 + @controller.stubs(:cart).returns({ :enterprise_id => enterprise.id, :items => {product1.id => 1}})
  173 + assert_difference ShoppingCartPlugin::PurchaseOrder, :count, 1 do
  174 + post :send_request,
  175 + :customer => {:name => "Manuel", :email => "manuel@ceu.com"}
  176 + end
  177 +
  178 + order = ShoppingCartPlugin::PurchaseOrder.last
  179 +
  180 + assert_equal 0, order.products_list[product1.id][:price]
  181 + end
  182 +
  183 + should 'clean the cart after placing the order' do
  184 + product1 = fast_create(Product, :enterprise_id => enterprise.id)
  185 + post :add, :id => product1.id
  186 + post :send_request, :customer => { :name => "Manuel", :email => "manuel@ceu.com" }
  187 + assert !cart?, "cart expected to be empty!"
  188 + end
  189 +
  190 + private
  191 +
  192 + def json_response
  193 + ActiveSupport::JSON.decode @response.body
  194 + end
  195 +
  196 + def cart?
  197 + !@controller.send(:cart).nil?
  198 + end
  199 +
  200 + def product_in_cart?(product)
  201 + @controller.send(:cart) &&
  202 + @controller.send(:cart)[:items] &&
  203 + @controller.send(:cart)[:items].has_key?(product.id)
  204 + end
  205 +
  206 + def product_quantity(product)
  207 + @controller.send(:cart)[:items][product.id]
  208 + end
  209 +
  210 + def response_ok?
  211 + json_response['ok']
  212 + end
  213 +
  214 + def reponse_error_code
  215 + json_response['error']['code']
  216 + end
  217 +
  218 + # temporary hack...if I don't do this the session stays as an Array instead
  219 + # of a TestSession
  220 + def instantiate_cart
  221 + get :add, :id => product.id
  222 + get :remove, :id => product.id
  223 + end
  224 +
  225 +end
plugins/shopping_cart/test/functional/shopping_cart_plugin_profile_controller_test.rb
@@ -1,213 +0,0 @@ @@ -1,213 +0,0 @@
1 -require File.dirname(__FILE__) + '/../../../../test/test_helper'  
2 -require File.dirname(__FILE__) + '/../../controllers/shopping_cart_plugin_profile_controller'  
3 -  
4 -# Re-raise errors caught by the controller.  
5 -class ShoppingCartPluginProfileController; def rescue_action(e) raise e end; end  
6 -  
7 -class ShoppingCartPluginProfileControllerTest < ActionController::TestCase  
8 -  
9 - def setup  
10 - @controller = ShoppingCartPluginProfileController.new  
11 - @request = ActionController::TestRequest.new  
12 - @response = ActionController::TestResponse.new  
13 - @enterprise = fast_create(Enterprise)  
14 - @product = fast_create(Product, :enterprise_id => @enterprise.id)  
15 - end  
16 - attr_reader :enterprise  
17 - attr_reader :product  
18 -  
19 - should 'add a new product to cart' do  
20 - get :add, :profile => enterprise.identifier, :id => product.id  
21 -  
22 - assert product_in_cart?(product)  
23 - assert_equal 1, product_quantity(product)  
24 - end  
25 -  
26 - should 'grow quantity through add' do  
27 - get :add, :profile => enterprise.identifier, :id => product.id  
28 - assert_equal 1, product_quantity(product)  
29 -  
30 - get :add, :profile => enterprise.identifier, :id => product.id  
31 - assert_equal 2, product_quantity(product)  
32 - end  
33 -  
34 - should 'not add product to cart if it does not exists' do  
35 - assert_nothing_raised { get :add, :profile => enterprise.identifier, :id => 9999 }  
36 -  
37 - assert !product_in_cart?(product)  
38 - assert !response_ok?  
39 - assert 3, reponse_error_code  
40 - end  
41 -  
42 - should 'remove cart if the product being removed is the last one' do  
43 - get :add, :profile => enterprise.identifier, :id => product.id  
44 - assert cart?  
45 -  
46 - get :remove, :profile => enterprise.identifier, :id => product.id  
47 - assert !cart?  
48 - end  
49 -  
50 - should 'not try to remove a product if there is no cart' do  
51 - instantiate_session  
52 - assert !cart?  
53 -  
54 - assert_nothing_raised { get :remove, :profile => enterprise.identifier, :id => 9999 }  
55 - assert !response_ok?  
56 - assert_equal 2, reponse_error_code  
57 - end  
58 -  
59 - should 'just remove product if there are other products on cart' do  
60 - another_product = fast_create(Product, :enterprise_id => enterprise.id)  
61 - get :add, :profile => enterprise.identifier, :id => product.id  
62 - get :add, :profile => enterprise.identifier, :id => another_product.id  
63 -  
64 - get :remove, :profile => enterprise.identifier, :id => product.id  
65 - assert cart?  
66 - assert !product_in_cart?(product)  
67 - end  
68 -  
69 - should 'not try to remove a product that is not in the cart' do  
70 - get :add, :profile => enterprise.identifier, :id => product.id  
71 - assert cart?  
72 - assert_nothing_raised { get :remove, :profile => enterprise.identifier, :id => 9999 }  
73 -  
74 - assert !response_ok?  
75 - assert_equal 4, reponse_error_code  
76 - end  
77 -  
78 - should 'not try to list the cart if there is no cart' do  
79 - instantiate_session  
80 - assert !cart?  
81 -  
82 - assert_nothing_raised { get :list, :profile => enterprise.identifier }  
83 - assert !response_ok?  
84 - assert_equal 2, reponse_error_code  
85 - end  
86 -  
87 - should 'list products without errors' do  
88 - get :add, :profile => enterprise.identifier, :id => product.id  
89 -  
90 - assert_nothing_raised { get :list, :profile => enterprise.identifier }  
91 - assert response_ok?  
92 - end  
93 -  
94 - should 'update the quantity of a product' do  
95 - get :add, :profile => enterprise.identifier, :id => product.id  
96 - assert 1, product_quantity(product)  
97 -  
98 - get :update_quantity, :profile => enterprise.identifier, :id => product.id, :quantity => 3  
99 - assert 3, product_quantity(product)  
100 - end  
101 -  
102 - should 'not try to update quantity the quantity of a product if there is no cart' do  
103 - instantiate_session  
104 - assert !cart?  
105 -  
106 - assert_nothing_raised { get :update_quantity, :profile => enterprise.identifier, :id => 9999, :quantity => 3 }  
107 - assert !response_ok?  
108 - assert_equal 2, reponse_error_code  
109 - end  
110 -  
111 - should 'not try to update the quantity of a product that is not in the cart' do  
112 - get :add, :profile => enterprise.identifier, :id => product.id  
113 - assert cart?  
114 - assert_nothing_raised { get :update_quantity, :profile => enterprise.identifier, :id => 9999, :quantity => 3 }  
115 -  
116 - assert !response_ok?  
117 - assert_equal 4, reponse_error_code  
118 - end  
119 -  
120 - should 'not update the quantity of a product with a invalid value' do  
121 - get :add, :profile => enterprise.identifier, :id => product.id  
122 -  
123 - assert_nothing_raised { get :update_quantity, :profile => enterprise.identifier, :id => product.id, :quantity => -1}  
124 - assert !response_ok?  
125 - assert_equal 5, reponse_error_code  
126 -  
127 - assert_nothing_raised { get :update_quantity, :profile => enterprise.identifier, :id => product.id, :quantity => 'asdf'}  
128 - assert !response_ok?  
129 - assert_equal 5, reponse_error_code  
130 - end  
131 -  
132 - should 'clean the cart' do  
133 - another_product = fast_create(Product, :enterprise_id => enterprise.id)  
134 - get :add, :profile => enterprise.identifier, :id => product.id  
135 - get :add, :profile => enterprise.identifier, :id => another_product.id  
136 -  
137 - assert_nothing_raised { get :clean, :profile => enterprise.identifier }  
138 - assert !cart?  
139 - end  
140 -  
141 - should 'not crash if there is no cart' do  
142 - instantiate_session  
143 - assert !cart?  
144 - assert_nothing_raised { get :clean, :profile => enterprise.identifier }  
145 - end  
146 -  
147 - should 'register order on send request' do  
148 - product1 = fast_create(Product, :enterprise_id => enterprise.id, :price => 1.99)  
149 - product2 = fast_create(Product, :enterprise_id => enterprise.id, :price => 2.23)  
150 - @controller.stubs(:session).returns({:cart => {:items => {product1.id => 1, product2.id => 2}}})  
151 - assert_difference ShoppingCartPlugin::PurchaseOrder, :count, 1 do  
152 - post :send_request,  
153 - :customer => {:name => "Manuel", :email => "manuel@ceu.com"},  
154 - :profile => enterprise.identifier  
155 - end  
156 -  
157 - order = ShoppingCartPlugin::PurchaseOrder.last  
158 -  
159 - assert_equal 1.99, order.products_list[product1.id][:price]  
160 - assert_equal 1, order.products_list[product1.id][:quantity]  
161 - assert_equal 2.23, order.products_list[product2.id][:price]  
162 - assert_equal 2, order.products_list[product2.id][:quantity]  
163 - assert_equal ShoppingCartPlugin::PurchaseOrder::Status::OPENED, order.status  
164 - end  
165 -  
166 - should 'register order on send request and not crash if product is not defined' do  
167 - product1 = fast_create(Product, :enterprise_id => enterprise.id)  
168 - @controller.stubs(:session).returns({:cart => {:items => {product1.id => 1}}})  
169 - assert_difference ShoppingCartPlugin::PurchaseOrder, :count, 1 do  
170 - post :send_request,  
171 - :customer => {:name => "Manuel", :email => "manuel@ceu.com"},  
172 - :profile => enterprise.identifier  
173 - end  
174 -  
175 - order = ShoppingCartPlugin::PurchaseOrder.last  
176 -  
177 - assert_equal 0, order.products_list[product1.id][:price]  
178 - end  
179 -  
180 - private  
181 -  
182 - def json_response  
183 - ActiveSupport::JSON.decode @response.body  
184 - end  
185 -  
186 - def cart?  
187 - !session[:cart].nil?  
188 - end  
189 -  
190 - def product_in_cart?(product)  
191 - session[:cart][:items].has_key?(product.id)  
192 - end  
193 -  
194 - def product_quantity(product)  
195 - session[:cart][:items][product.id]  
196 - end  
197 -  
198 - def response_ok?  
199 - json_response['ok']  
200 - end  
201 -  
202 - def reponse_error_code  
203 - json_response['error']['code']  
204 - end  
205 -  
206 - # temporary hack...if I don't do this the session stays as an Array instead  
207 - # of a TestSession  
208 - def instantiate_session  
209 - get :add, :profile => enterprise.identifier, :id => product.id  
210 - get :remove, :profile => enterprise.identifier, :id => product.id  
211 - end  
212 -  
213 -end  
plugins/shopping_cart/test/unit/shopping_cart_plugin_test.rb
@@ -7,7 +7,6 @@ class ShoppingCartPluginTest &lt; ActiveSupport::TestCase @@ -7,7 +7,6 @@ class ShoppingCartPluginTest &lt; ActiveSupport::TestCase
7 @context = mock() 7 @context = mock()
8 @profile = mock() 8 @profile = mock()
9 @profile.stubs(:identifier).returns('random-user') 9 @profile.stubs(:identifier).returns('random-user')
10 - @context.stubs(:profile).returns(@profile)  
11 @shopping_cart.context = @context 10 @shopping_cart.context = @context
12 @shopping_cart.stubs(:profile).returns(@profile) 11 @shopping_cart.stubs(:profile).returns(@profile)
13 end 12 end
@@ -23,7 +22,8 @@ class ShoppingCartPluginTest &lt; ActiveSupport::TestCase @@ -23,7 +22,8 @@ class ShoppingCartPluginTest &lt; ActiveSupport::TestCase
23 product = fast_create(Product, :available => false) 22 product = fast_create(Product, :available => false)
24 enterprise = mock() 23 enterprise = mock()
25 enterprise.stubs(:shopping_cart).returns(true) 24 enterprise.stubs(:shopping_cart).returns(true)
  25 + product.stubs(:enterprise).returns(enterprise)
26 26
27 - assert_nil shopping_cart.add_to_cart_button(product, enterprise) 27 + assert_nil shopping_cart.add_to_cart_button(product)
28 end 28 end
29 end 29 end
plugins/shopping_cart/views/cart.html.erb
@@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
7 <a href="cart:clean" onclick="Cart.clean(this); return false" class="cart-clean"><%=_('Clean basket')%></a> 7 <a href="cart:clean" onclick="Cart.clean(this); return false" class="cart-clean"><%=_('Clean basket')%></a>
8 <ul class="cart-items"></ul> 8 <ul class="cart-items"></ul>
9 <div class="cart-total"><%=_('Total:')%> <b></b></div> 9 <div class="cart-total"><%=_('Total:')%> <b></b></div>
10 - <a href="cart:buy" class="cart-buy"><%=_('Shopping checkout')%></a> 10 + <a href="/plugin/shopping_cart/buy" class="cart-buy"><%=_('Shopping checkout')%></a>
11 </div> 11 </div>
12 <a href="#" onclick="Cart.toggle(this); return false" class="cart-toggle"> 12 <a href="#" onclick="Cart.toggle(this); return false" class="cart-toggle">
13 <span class="str-show"><%=_('Show basket')%></span> 13 <span class="str-show"><%=_('Show basket')%></span>
@@ -15,9 +15,3 @@ @@ -15,9 +15,3 @@
15 </a> 15 </a>
16 </div> 16 </div>
17 </div> 17 </div>
18 -  
19 -<script type="text/javascript">  
20 -//<![CDATA[  
21 - new Cart({hasProducts:<%= !locals[:cart].nil? ? "true, enterprise:'#{Enterprise.find(locals[:cart][:enterprise_id]).identifier}'" : "false" %>});  
22 -//]]>  
23 -</script>  
plugins/shopping_cart/views/shopping_cart_plugin/buy.html.erb 0 → 100644
@@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
  1 +<% person = user.nil? ? Person.new : user %>
  2 +<div id='cart-request-box'>
  3 + <% form_for(:customer, person, :url => {:action => 'send_request'},
  4 + :html => {:onsubmit => "return Cart.send_request(this)", :id => 'cart-request-form' }) do |f| %>
  5 + <div id="cart-form-main">
  6 + <%= labelled_form_field('* ' + _("Name"), f.text_field(:name, :class => 'required') ) %>
  7 + <%= labelled_form_field('* ' + _("Email"), f.text_field(:email, :class => 'required email') ) %>
  8 + <%= labelled_form_field('* ' + _("Contact phone"), f.text_field(:contact_phone, :class => 'required') ) %>
  9 + </div>
  10 + <fieldset><legend><%=_('Delivery Address')%></legend>
  11 + <%= labelled_form_field(_('Address (street and number)'), f.text_field(:address)) %>
  12 + <%= labelled_form_field( _("City"), f.text_field(:city)) %>
  13 + <%= labelled_form_field(_('ZIP code'), f.text_field(:zip_code)) %>
  14 + </fieldset>
  15 + <div id="cart-form-actions">
  16 + <%= submit_button(:send, _('Send buy request')) %>
  17 + </div>
  18 + <% end %>
  19 + <%= items_table(@cart[:items], @enterprise) %>
  20 + <%= link_to '', '#', :onclick => "Cart.colorbox_close(this);", :class => 'cart-box-close icon-cancel' %>
  21 +</div>
  22 +
  23 +<script type="text/javascript">
  24 +//<![CDATA[
  25 + jQuery(document).ready(function(){
  26 + jQuery("#cart-request-form").validate({
  27 + submitHandler: function(form) {
  28 + jQuery(form).find('input.submit').attr('disabled', true);
  29 + jQuery('#cboxLoadingOverlay').show().addClass('loading');
  30 + jQuery('#cboxLoadingGraphic').show().addClass('loading');
  31 + }
  32 + });
  33 + });
  34 +//]]>
  35 +</script>
plugins/shopping_cart/views/shopping_cart_plugin/mailer/customer_notification.html.erb
@@ -35,7 +35,7 @@ @@ -35,7 +35,7 @@
35 </ul> 35 </ul>
36 36
37 <p><%=_('Here are the products you bought:')%></p> 37 <p><%=_('Here are the products you bought:')%></p>
38 - <%= items_table(@items, @supplier, true) %> 38 + <%= @helper.items_table(@items, @supplier, true) %>
39 39
40 <p> 40 <p>
41 --<br/> 41 --<br/>
plugins/shopping_cart/views/shopping_cart_plugin/mailer/supplier_notification.html.erb
@@ -33,7 +33,7 @@ @@ -33,7 +33,7 @@
33 </ul> 33 </ul>
34 34
35 <p><%=_('And here are the items bought by this customer:')%></p> 35 <p><%=_('And here are the items bought by this customer:')%></p>
36 - <%= items_table(@items, @supplier, true) %> 36 + <%= @helper.items_table(@items, @supplier, true) %>
37 37
38 <p> 38 <p>
39 --<br/> 39 --<br/>
plugins/shopping_cart/views/shopping_cart_plugin/send_request.html.erb 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +<%= _("Request sent successfully check your email.")%>
plugins/shopping_cart/views/shopping_cart_plugin_profile/buy.html.erb
@@ -1,35 +0,0 @@ @@ -1,35 +0,0 @@
1 -<% person = user.nil? ? Person.new : user %>  
2 -<div id='cart-request-box'>  
3 - <% form_for(:customer, person, :url => {:action => 'send_request'},  
4 - :html => {:onsubmit => "return Cart.send_request(this)", :id => 'cart-request-form' }) do |f| %>  
5 - <div id="cart-form-main">  
6 - <%= labelled_form_field('* ' + _("Name"), f.text_field(:name, :class => 'required') ) %>  
7 - <%= labelled_form_field('* ' + _("Email"), f.text_field(:email, :class => 'required email') ) %>  
8 - <%= labelled_form_field('* ' + _("Contact phone"), f.text_field(:contact_phone, :class => 'required') ) %>  
9 - </div>  
10 - <fieldset><legend><%=_('Delivery Address')%></legend>  
11 - <%= labelled_form_field(_('Address (street and number)'), f.text_field(:address)) %>  
12 - <%= labelled_form_field( _("City"), f.text_field(:city)) %>  
13 - <%= labelled_form_field(_('ZIP code'), f.text_field(:zip_code)) %>  
14 - </fieldset>  
15 - <div id="cart-form-actions">  
16 - <%= submit_button(:send, _('Send buy request')) %>  
17 - </div>  
18 - <% end %>  
19 - <%= items_table(session[:cart][:items], profile) %>  
20 - <%= link_to '', '#', :onclick => "Cart.colorbox_close(this);", :class => 'cart-box-close icon-cancel' %>  
21 -</div>  
22 -  
23 -<script type="text/javascript">  
24 -//<![CDATA[  
25 - jQuery(document).ready(function(){  
26 - jQuery("#cart-request-form").validate({  
27 - submitHandler: function(form) {  
28 - jQuery(form).find('input.submit').attr('disabled', true);  
29 - jQuery('#cboxLoadingOverlay').show().addClass('loading');  
30 - jQuery('#cboxLoadingGraphic').show().addClass('loading');  
31 - }  
32 - });  
33 - });  
34 -//]]>  
35 -</script>  
plugins/shopping_cart/views/shopping_cart_plugin_profile/send_request.html.erb
@@ -1 +0,0 @@ @@ -1 +0,0 @@
1 -<%= _("Request sent successfully check your email.")%>  
plugins/spaminator/controllers/spaminator_plugin_admin_controller.rb
@@ -34,7 +34,7 @@ class SpaminatorPluginAdminController &lt; AdminController @@ -34,7 +34,7 @@ class SpaminatorPluginAdminController &lt; AdminController
34 settings.scanning = true 34 settings.scanning = true
35 settings.save! 35 settings.save!
36 remove_scheduled_scan 36 remove_scheduled_scan
37 - Delayed::Job.enqueue(SpaminatorPlugin::ScanJob.new(environment)) 37 + Delayed::Job.enqueue(SpaminatorPlugin::ScanJob.new(environment.id))
38 end 38 end
39 redirect_to :action => 'index' 39 redirect_to :action => 'index'
40 end 40 end
plugins/spaminator/lib/spaminator_plugin/scan_job.rb
@@ -6,7 +6,11 @@ class SpaminatorPlugin::ScanJob &lt; Struct.new(:environment_id) @@ -6,7 +6,11 @@ class SpaminatorPlugin::ScanJob &lt; Struct.new(:environment_id)
6 settings.scanning = true 6 settings.scanning = true
7 settings.save! 7 settings.save!
8 8
9 - SpaminatorPlugin::Spaminator.run(environment) 9 + begin
  10 + SpaminatorPlugin::Spaminator.run(environment)
  11 + rescue Exception => exception
  12 + SpaminatorPlugin::Spaminator.log("Spaminator failed with the following error: \n ==> #{exception}\n#{exception.backtrace.join("\n")}")
  13 + end
10 14
11 settings.scanning = false 15 settings.scanning = false
12 SpaminatorPlugin.schedule_scan(environment) if settings.deployed 16 SpaminatorPlugin.schedule_scan(environment) if settings.deployed
plugins/spaminator/lib/spaminator_plugin/spaminator.rb
@@ -11,6 +11,14 @@ class SpaminatorPlugin::Spaminator @@ -11,6 +11,14 @@ class SpaminatorPlugin::Spaminator
11 def benchmark(environment) 11 def benchmark(environment)
12 puts Benchmark.measure { run(environment) } 12 puts Benchmark.measure { run(environment) }
13 end 13 end
  14 +
  15 + def initialize_logger(logpath)
  16 + @logger = Logger.new(logpath)
  17 + end
  18 +
  19 + def log(message)
  20 + @logger << "[#{Time.now.strftime("%F %T %z")}] #{message}\n"
  21 + end
14 end 22 end
15 23
16 24
@@ -20,9 +28,12 @@ class SpaminatorPlugin::Spaminator @@ -20,9 +28,12 @@ class SpaminatorPlugin::Spaminator
20 @report = SpaminatorPlugin::Report.new(:environment => environment, 28 @report = SpaminatorPlugin::Report.new(:environment => environment,
21 :total_people => Person.count, 29 :total_people => Person.count,
22 :total_comments => Comment.count) 30 :total_comments => Comment.count)
  31 + logpath = File.join(SpaminatorPlugin.root_path, 'log', "#{environment.name.to_slug}_#{ENV['RAILS_ENV']}_#{Time.now.strftime("%F_%T")}.log")
  32 + self.class.initialize_logger(logpath)
23 end 33 end
24 34
25 def run 35 def run
  36 + self.class.log("Starting Spaminator scan")
26 start_time = Time.now 37 start_time = Time.now
27 38
28 process_all_comments 39 process_all_comments
@@ -37,6 +48,7 @@ class SpaminatorPlugin::Spaminator @@ -37,6 +48,7 @@ class SpaminatorPlugin::Spaminator
37 finish_report 48 finish_report
38 @settings.last_run = start_time 49 @settings.last_run = start_time
39 @settings.save! 50 @settings.save!
  51 + self.class.log("Finishing Spaminator scan successfully")
40 end 52 end
41 53
42 # TODO considering run everything always 54 # TODO considering run everything always
@@ -53,6 +65,7 @@ class SpaminatorPlugin::Spaminator @@ -53,6 +65,7 @@ class SpaminatorPlugin::Spaminator
53 end 65 end
54 66
55 def process_all_comments 67 def process_all_comments
  68 + self.class.log("Starting to process all comments")
56 comments = comments_to_process 69 comments = comments_to_process
57 total = comments.count 70 total = comments.count
58 pbar = ProgressBar.new("☢ Comments", total) 71 pbar = ProgressBar.new("☢ Comments", total)
@@ -66,9 +79,11 @@ class SpaminatorPlugin::Spaminator @@ -66,9 +79,11 @@ class SpaminatorPlugin::Spaminator
66 end 79 end
67 @report.processed_comments = total 80 @report.processed_comments = total
68 pbar.finish 81 pbar.finish
  82 + self.class.log("All comments processed")
69 end 83 end
70 84
71 def process_all_people 85 def process_all_people
  86 + self.class.log("Starting to process all people")
72 people = people_to_process 87 people = people_to_process
73 total = people.count 88 total = people.count
74 pbar = ProgressBar.new("☢ People", total) 89 pbar = ProgressBar.new("☢ People", total)
@@ -79,9 +94,11 @@ class SpaminatorPlugin::Spaminator @@ -79,9 +94,11 @@ class SpaminatorPlugin::Spaminator
79 end 94 end
80 @report.processed_people = total 95 @report.processed_people = total
81 pbar.finish 96 pbar.finish
  97 + self.class.log("All people processed")
82 end 98 end
83 99
84 def process_comment(comment) 100 def process_comment(comment)
  101 + self.class.log("Processing Comment[#{comment.id.to_s}]")
85 comment = Comment.find(comment.id) 102 comment = Comment.find(comment.id)
86 comment.check_for_spam 103 comment.check_for_spam
87 @report.spams_by_content += 1 if comment.spam 104 @report.spams_by_content += 1 if comment.spam
@@ -97,6 +114,7 @@ class SpaminatorPlugin::Spaminator @@ -97,6 +114,7 @@ class SpaminatorPlugin::Spaminator
97 # person is author of more than 2 comments marked as spam 114 # person is author of more than 2 comments marked as spam
98 # → mark as spammer 115 # → mark as spammer
99 # 116 #
  117 + self.class.log("Processing Person[#{person.id.to_s}] by comments")
100 begin 118 begin
101 number_of_spam_comments = Comment.spam.where(:author_id => person.id).count 119 number_of_spam_comments = Comment.spam.where(:author_id => person.id).count
102 if number_of_spam_comments > 2 120 if number_of_spam_comments > 2
@@ -115,6 +133,7 @@ class SpaminatorPlugin::Spaminator @@ -115,6 +133,7 @@ class SpaminatorPlugin::Spaminator
115 # → disable the profile 133 # → disable the profile
116 # ? mark their comments as spam 134 # ? mark their comments as spam
117 # 135 #
  136 + self.class.log("Processing Person[#{person.id.to_s}] by network")
118 if person.created_at < (Time.now - 1.month) && 137 if person.created_at < (Time.now - 1.month) &&
119 person.friends.count == 0 && 138 person.friends.count == 0 &&
120 person.communities.count <= 1 139 person.communities.count <= 1
@@ -151,6 +170,7 @@ class SpaminatorPlugin::Spaminator @@ -151,6 +170,7 @@ class SpaminatorPlugin::Spaminator
151 end 170 end
152 171
153 def register_fail(kind, failed) 172 def register_fail(kind, failed)
  173 + self.class.log("Failed #{kind.to_s.camelize}[#{failed.id.to_s}]")
154 @report[:failed][kind.to_sym] << failed.id 174 @report[:failed][kind.to_sym] << failed.id
155 end 175 end
156 end 176 end
test/functional/profile_controller_test.rb
@@ -234,7 +234,7 @@ class ProfileControllerTest &lt; ActionController::TestCase @@ -234,7 +234,7 @@ class ProfileControllerTest &lt; ActionController::TestCase
234 login_as(@profile.identifier) 234 login_as(@profile.identifier)
235 ent = fast_create(Enterprise, :name => 'my test enterprise', :identifier => 'my-test-enterprise', :enabled => false) 235 ent = fast_create(Enterprise, :name => 'my test enterprise', :identifier => 'my-test-enterprise', :enabled => false)
236 get :index, :profile => ent.identifier 236 get :index, :profile => ent.identifier
237 - assert_tag :tag => 'div', :attributes => { :id => 'profile-disabled' }, :content => Environment.default.message_for_disabled_enterprise 237 + assert_tag :tag => 'div', :attributes => { :id => 'profile-disabled' }, :content => /#{Environment.default.message_for_disabled_enterprise}/
238 end 238 end
239 239
240 should 'not show message for disabled enterprise to non-enterprises' do 240 should 'not show message for disabled enterprise to non-enterprises' do
test/unit/approve_article_test.rb
@@ -414,4 +414,20 @@ class ApproveArticleTest &lt; ActiveSupport::TestCase @@ -414,4 +414,20 @@ class ApproveArticleTest &lt; ActiveSupport::TestCase
414 assert_match /My Article/, task.task_cancelled_message 414 assert_match /My Article/, task.task_cancelled_message
415 end 415 end
416 416
  417 + should 'not save 4 on the new article\'s last_changed_by_ud after approval if author is nil' do
  418 + article = fast_create(Article)
  419 + task = ApproveArticle.create!(:article => article, :target => community, :requestor => profile)
  420 + task.finish
  421 + new_article = Article.last
  422 + assert_nil new_article.last_changed_by_id
  423 + end
  424 +
  425 + should 'not crash if target has its own domain' do
  426 + article = fast_create(Article)
  427 + profile.domains << Domain.create(:name => 'example.org')
  428 + assert_nothing_raised do
  429 + ApproveArticle.create!(:article => article, :target => profile, :requestor => community)
  430 + end
  431 + end
  432 +
417 end 433 end
test/unit/article_test.rb
@@ -1822,4 +1822,15 @@ class ArticleTest &lt; ActiveSupport::TestCase @@ -1822,4 +1822,15 @@ class ArticleTest &lt; ActiveSupport::TestCase
1822 assert_equal author_name, article.author_name 1822 assert_equal author_name, article.author_name
1823 end 1823 end
1824 1824
  1825 + should "author_id return the author id of the article's author" do
  1826 + author = fast_create(Person)
  1827 + article = Article.create!(:name => 'Test', :profile => profile, :last_changed_by => author)
  1828 + assert_equal author.id, article.author_id
  1829 + end
  1830 +
  1831 + should "author_id return nil if there is no article's author" do
  1832 + article = Article.create!(:name => 'Test', :profile => profile, :last_changed_by => nil)
  1833 + assert_nil article.author_id
  1834 + end
  1835 +
1825 end 1836 end
test/unit/comment_notifier_test.rb
@@ -8,26 +8,27 @@ class CommentNotifierTest &lt; ActiveSupport::TestCase @@ -8,26 +8,27 @@ class CommentNotifierTest &lt; ActiveSupport::TestCase
8 ActionMailer::Base.delivery_method = :test 8 ActionMailer::Base.delivery_method = :test
9 ActionMailer::Base.perform_deliveries = true 9 ActionMailer::Base.perform_deliveries = true
10 ActionMailer::Base.deliveries = [] 10 ActionMailer::Base.deliveries = []
11 - @profile = create_user('user_comment_test').person 11 + @profile = create_user('content_owner').person
  12 + @author = create_user('author').person
12 @article = fast_create(Article, :name => 'Article test', :profile_id => @profile.id, :notify_comments => true) 13 @article = fast_create(Article, :name => 'Article test', :profile_id => @profile.id, :notify_comments => true)
13 end 14 end
14 15
15 should 'deliver mail after make an article comment' do 16 should 'deliver mail after make an article comment' do
16 assert_difference ActionMailer::Base.deliveries, :size do 17 assert_difference ActionMailer::Base.deliveries, :size do
17 - create_comment_and_notify(:author => @profile, :title => 'test comment', :body => 'you suck!', :source => @article ) 18 + create_comment_and_notify(:author => @author, :title => 'test comment', :body => 'you suck!', :source => @article )
18 end 19 end
19 end 20 end
20 21
21 should 'deliver mail to owner of article' do 22 should 'deliver mail to owner of article' do
22 - create_comment_and_notify(:author => @profile, :title => 'test comment', :body => 'you suck!', :source => @article ) 23 + create_comment_and_notify(:author => @author, :title => 'test comment', :body => 'you suck!', :source => @article )
23 sent = ActionMailer::Base.deliveries.first 24 sent = ActionMailer::Base.deliveries.first
24 assert_equal [@profile.email], sent.to 25 assert_equal [@profile.email], sent.to
25 end 26 end
26 27
27 should 'display author name in delivered mail' do 28 should 'display author name in delivered mail' do
28 - create_comment_and_notify(:author => @profile, :title => 'test comment', :body => 'you suck!', :source => @article) 29 + create_comment_and_notify(:author => @author, :title => 'test comment', :body => 'you suck!', :source => @article)
29 sent = ActionMailer::Base.deliveries.first 30 sent = ActionMailer::Base.deliveries.first
30 - assert_match /user_comment_test/, sent.body 31 + assert_match /#{@author.name}/, sent.body
31 end 32 end
32 33
33 should 'display unauthenticated author name and email in delivered mail' do 34 should 'display unauthenticated author name and email in delivered mail' do
@@ -40,18 +41,18 @@ class CommentNotifierTest &lt; ActiveSupport::TestCase @@ -40,18 +41,18 @@ class CommentNotifierTest &lt; ActiveSupport::TestCase
40 should 'not deliver mail if notify comments is false' do 41 should 'not deliver mail if notify comments is false' do
41 @article.update_attribute(:notify_comments, false) 42 @article.update_attribute(:notify_comments, false)
42 assert_no_difference ActionMailer::Base.deliveries, :size do 43 assert_no_difference ActionMailer::Base.deliveries, :size do
43 - create_comment_and_notify(:author => @profile, :title => 'test comment', :body => 'you suck!', :source => @article) 44 + create_comment_and_notify(:author => @author, :title => 'test comment', :body => 'you suck!', :source => @article)
44 end 45 end
45 end 46 end
46 47
47 should 'include comment title in the e-mail' do 48 should 'include comment title in the e-mail' do
48 - create_comment_and_notify(:author => @profile, :title => 'comment title', :body => 'comment body', :source => @article) 49 + create_comment_and_notify(:author => @author, :title => 'comment title', :body => 'comment body', :source => @article)
49 sent = ActionMailer::Base.deliveries.first 50 sent = ActionMailer::Base.deliveries.first
50 assert_match /comment title/, sent.body 51 assert_match /comment title/, sent.body
51 end 52 end
52 53
53 should 'include comment text in the e-mail' do 54 should 'include comment text in the e-mail' do
54 - create_comment_and_notify(:author => @profile, :title => 'comment title', :body => 'comment body', :source => @article) 55 + create_comment_and_notify(:author => @author, :title => 'comment title', :body => 'comment body', :source => @article)
55 sent = ActionMailer::Base.deliveries.first 56 sent = ActionMailer::Base.deliveries.first
56 assert_match /comment body/, sent.body 57 assert_match /comment body/, sent.body
57 end 58 end
@@ -61,7 +62,7 @@ class CommentNotifierTest &lt; ActiveSupport::TestCase @@ -61,7 +62,7 @@ class CommentNotifierTest &lt; ActiveSupport::TestCase
61 assert_equal [], community.notification_emails 62 assert_equal [], community.notification_emails
62 article = fast_create(Article, :name => 'Article test', :profile_id => community.id, :notify_comments => true) 63 article = fast_create(Article, :name => 'Article test', :profile_id => community.id, :notify_comments => true)
63 assert_no_difference ActionMailer::Base.deliveries, :size do 64 assert_no_difference ActionMailer::Base.deliveries, :size do
64 - create_comment_and_notify(:author => @profile, :title => 'test comment', :body => 'there is no addresses to send notification', :source => article) 65 + create_comment_and_notify(:author => @author, :title => 'test comment', :body => 'there is no addresses to send notification', :source => article)
65 end 66 end
66 end 67 end
67 68
@@ -80,6 +81,17 @@ class CommentNotifierTest &lt; ActiveSupport::TestCase @@ -80,6 +81,17 @@ class CommentNotifierTest &lt; ActiveSupport::TestCase
80 assert_not_includes ActionMailer::Base.deliveries.map(&:bcc).flatten, follower.email 81 assert_not_includes ActionMailer::Base.deliveries.map(&:bcc).flatten, follower.email
81 end 82 end
82 83
  84 + should 'not deliver mail to comments author' do
  85 + community = fast_create(Community)
  86 + community.add_admin @profile
  87 + community.add_admin @author
  88 +
  89 + article = fast_create(Article, :name => 'Article test', :profile_id => community.id, :notify_comments => true)
  90 + create_comment_and_notify(:source => @article, :author => @author, :title => 'comment title', :body => 'comment body')
  91 + sent = ActionMailer::Base.deliveries.first
  92 + assert_not_includes sent.to, @author.email
  93 + end
  94 +
83 private 95 private
84 96
85 def create_comment_and_notify(args) 97 def create_comment_and_notify(args)
test/unit/disabled_enterprise_message_block_test.rb
@@ -18,17 +18,6 @@ class DisabledEnterpriseMessageBlockTest &lt; ActiveSupport::TestCase @@ -18,17 +18,6 @@ class DisabledEnterpriseMessageBlockTest &lt; ActiveSupport::TestCase
18 instance_eval(&block.content) 18 instance_eval(&block.content)
19 end 19 end
20 20
21 - should 'display nothing if environment has no message' do  
22 - e = fast_create(Environment)  
23 - block = DisabledEnterpriseMessageBlock.new  
24 - p = Profile.new  
25 - block.expects(:owner).returns(p)  
26 - p.expects(:environment).returns(e)  
27 -  
28 - expects(:render).with(:file => 'blocks/disabled_enterprise_message', :locals => { :message => ''})  
29 - instance_eval(&block.content)  
30 - end  
31 -  
32 should 'not be editable' do 21 should 'not be editable' do
33 assert !DisabledEnterpriseMessageBlock.new.editable? 22 assert !DisabledEnterpriseMessageBlock.new.editable?
34 end 23 end
test/unit/profile_test.rb
@@ -246,6 +246,13 @@ class ProfileTest &lt; ActiveSupport::TestCase @@ -246,6 +246,13 @@ class ProfileTest &lt; ActiveSupport::TestCase
246 assert_equal({ :profile => 'testprofile', :controller => 'profile_editor', :action => 'index'}, profile.admin_url) 246 assert_equal({ :profile => 'testprofile', :controller => 'profile_editor', :action => 'index'}, profile.admin_url)
247 end 247 end
248 248
  249 + should 'provide URL to tasks area' do
  250 + environment = create_environment('mycolivre.net')
  251 + profile = build(Profile, :identifier => 'testprofile', :environment_id => create_environment('mycolivre.net').id)
  252 +
  253 + assert_equal({ :host => profile.default_hostname, :profile => 'testprofile', :controller => 'tasks', :action => 'index'}, profile.tasks_url)
  254 + end
  255 +
249 should 'provide URL to public profile' do 256 should 'provide URL to public profile' do
250 environment = create_environment('mycolivre.net') 257 environment = create_environment('mycolivre.net')
251 profile = build(Profile, :identifier => 'testprofile', :environment_id => environment.id) 258 profile = build(Profile, :identifier => 'testprofile', :environment_id => environment.id)
test/unit/task_mailer_test.rb
@@ -84,22 +84,9 @@ class TaskMailerTest &lt; ActiveSupport::TestCase @@ -84,22 +84,9 @@ class TaskMailerTest &lt; ActiveSupport::TestCase
84 end 84 end
85 85
86 should 'be able to send a "target notification" message' do 86 should 'be able to send a "target notification" message' do
87 - task = Task.new 87 + task = Task.new(:target => fast_create(Person))
88 task.expects(:target_notification_description).returns('the task') 88 task.expects(:target_notification_description).returns('the task')
89 89
90 - target = mock()  
91 - target.expects(:notification_emails).returns(['target@example.com'])  
92 - target.expects(:name).returns('Target')  
93 - target.expects(:url).returns({:host => 'my.domain.com', :profile => 'testprofile'})  
94 -  
95 - environment = mock()  
96 - environment.expects(:contact_email).returns('sender@example.com')  
97 - environment.expects(:default_hostname).returns('example.com')  
98 - environment.expects(:name).returns('example').at_least_once  
99 -  
100 - task.expects(:target).returns(target).at_least_once  
101 - task.expects(:environment).returns(environment).at_least_once  
102 -  
103 TaskMailer.deliver_target_notification(task, 'the message') 90 TaskMailer.deliver_target_notification(task, 'the message')
104 assert !ActionMailer::Base.deliveries.empty? 91 assert !ActionMailer::Base.deliveries.empty?
105 end 92 end
test/unit/user_test.rb
@@ -617,6 +617,19 @@ class UserTest &lt; ActiveSupport::TestCase @@ -617,6 +617,19 @@ class UserTest &lt; ActiveSupport::TestCase
617 end 617 end
618 end 618 end
619 619
  620 + should 'create person with name equal to user name if a user name is defined' do
  621 + user = User.new( :login => 'quire', :email => 'quire@example.com', :password => 'quire', :password_confirmation => 'quire' )
  622 + user.name = "Some name"
  623 + user.save
  624 + assert_equal 'Some name', user.person.name
  625 + end
  626 +
  627 + should 'create person with name equal to user login if no user name is defined' do
  628 + user = User.new( :login => 'quire', :email => 'quire@example.com', :password => 'quire', :password_confirmation => 'quire' )
  629 + user.save
  630 + assert_equal 'quire', user.person.name
  631 + end
  632 +
620 protected 633 protected
621 def new_user(options = {}) 634 def new_user(options = {})
622 user = User.new({ :login => 'quire', :email => 'quire@example.com', :password => 'quire', :password_confirmation => 'quire' }.merge(options)) 635 user = User.new({ :login => 'quire', :email => 'quire@example.com', :password => 'quire', :password_confirmation => 'quire' }.merge(options))
vendor/plugins/noosfero_caching/init.rb
@@ -38,11 +38,24 @@ module NoosferoHttpCaching @@ -38,11 +38,24 @@ module NoosferoHttpCaching
38 def call(env) 38 def call(env)
39 status, headers, body = @app.call(env) 39 status, headers, body = @app.call(env)
40 if headers['X-Noosfero-Auth'] == 'false' 40 if headers['X-Noosfero-Auth'] == 'false'
41 - headers.delete('Set-Cookie') 41 + headers['Set-Cookie'] = remove_unwanted_cookies(headers['Set-Cookie'])
  42 + headers.delete('Set-Cookie') if headers['Set-Cookie'].blank?
42 end 43 end
43 headers.delete('X-Noosfero-Auth') 44 headers.delete('X-Noosfero-Auth')
44 [status, headers, body] 45 [status, headers, body]
45 end 46 end
  47 +
  48 + protected
  49 +
  50 + # filter off all cookies except for plugin-provided ones that are
  51 + # path-specific (i.e path != "/").
  52 + def remove_unwanted_cookies(cookie_list)
  53 + return nil if cookie_list.nil?
  54 + cookie_list.select do |c|
  55 + c =~ /^_noosfero_plugin_\w+=/ && c =~ /path=\/\w+/
  56 + end
  57 + end
  58 +
46 end 59 end
47 60
48 end 61 end