Commit 2fd621c3d7332efcdb65b6e7045269ada32ad58c

Authored by Fabio Teixeira
Committed by Tallys Martins
1 parent d841eedf

Add software statistic block

Signed-off-by: brenddongontijo <brenddongontijo@msn.com>
Signed-off-by: Fabio Teixeira <fabio1079@gmail.com>
Signed-off-by: Pedro de Lyra <pedrodelyra@gmail.com>
Signed-off-by: Luciano Prestes Cavalcanti <lucianopcbr@gmail.com>
Signed-off-by: Simiao Carvalho <simiaosimis@gmail.com>
Signed-off-by: Victor Matias Navarro <victor.matias.navarro@gmail.com>
controllers/software_communities_plugin_profile_controller.rb 0 → 100644
... ... @@ -0,0 +1,49 @@
  1 +class SoftwareCommunitiesPluginProfileController < ProfileController
  2 + append_view_path File.join(File.dirname(__FILE__) + '/../views')
  3 +
  4 + before_filter :validate_download_params, only: [:download_file]
  5 +
  6 + ERROR_MESSAGES = {
  7 + :not_found => _("Could not find the download file"),
  8 + :invalid_params => _("Invalid download params")
  9 + }
  10 +
  11 + def download_file
  12 + download_block = DownloadBlock.find_by_id params[:block]
  13 + index = params[:download_index].to_i
  14 +
  15 + if download_block and (index < download_block.downloads.size)
  16 + download = Download.new(download_block.downloads[index])
  17 +
  18 + download.total_downloads += 1
  19 + download_block.downloads[index] = download.to_hash
  20 + download_block.save
  21 +
  22 + redirect_to download.link
  23 + else
  24 + session[:notice] = ERROR_MESSAGES[:not_found]
  25 + render_not_found
  26 + end
  27 + end
  28 +
  29 + private
  30 +
  31 + def validate_download_params
  32 + valid_block = (!params[:block].nil?) and (params[:block].to_i > 0)
  33 + valid_index = params[:download_index].to_i >= 0
  34 +
  35 + if !valid_block or !valid_index
  36 + session[:notice] = ERROR_MESSAGES[:invalid_params]
  37 + safe_redirect_back
  38 + end
  39 + end
  40 +
  41 + def safe_redirect_back
  42 + begin
  43 + redirect_to :back
  44 + rescue ActionController::RedirectBackError
  45 + # There is no :back if it is a copied url
  46 + render_not_found
  47 + end
  48 + end
  49 +end
... ...
lib/download.rb 0 → 100644
... ... @@ -0,0 +1,51 @@
  1 +#FIX ME: Turn this into a proper model(next release)
  2 +class Download
  3 + def initialize data
  4 + @name = data[:name]
  5 + @link = data[:link]
  6 + @software_description = data[:software_description]
  7 + @minimum_requirements = data[:minimum_requirements]
  8 + @size = data[:size]
  9 +
  10 + @total_downloads = if data[:total_downloads]
  11 + data[:total_downloads]
  12 + else
  13 + 0
  14 + end
  15 + end
  16 +
  17 + def self.validate_download_list download_list
  18 + download_list.select! do |download|
  19 + not download[:name].blank?
  20 + end
  21 +
  22 + download_list.map do |download|
  23 + Download.new(download).to_hash
  24 + end
  25 + end
  26 +
  27 + def to_hash
  28 + {
  29 + :name => @name,
  30 + :link => @link,
  31 + :software_description => @software_description,
  32 + :minimum_requirements => @minimum_requirements,
  33 + :size => @size,
  34 + :total_downloads => @total_downloads
  35 + }
  36 + end
  37 +
  38 + def total_downloads= value
  39 + if value.is_a? Integer
  40 + @total_downloads = value
  41 + end
  42 + end
  43 +
  44 + def total_downloads
  45 + @total_downloads
  46 + end
  47 +
  48 + def link
  49 + @link
  50 + end
  51 +end
... ...
lib/download_block.rb
... ... @@ -8,11 +8,7 @@ class DownloadBlock &lt; Block
8 8 validate :download_values
9 9  
10 10 def download_values
11   - self.downloads.each do |download|
12   - if download[:name] == ""
13   - downloads.delete(download)
14   - end
15   - end
  11 + self.downloads = Download.validate_download_list(self.downloads)
16 12 end
17 13  
18 14 def self.description
... ...
lib/ext/community.rb
... ... @@ -12,6 +12,8 @@ class Community
12 12  
13 13 has_one :software_info, :dependent=>:destroy
14 14  
  15 + settings_items :hits, :type => :integer, :default => 0
  16 +
15 17 def self.create_after_moderation(requestor, attributes = {})
16 18 community = Community.new(attributes)
17 19  
... ... @@ -55,4 +57,10 @@ class Community
55 57 def remove_of_community_search_software?
56 58 return software?
57 59 end
  60 +
  61 + def hit
  62 + self.hits += 1
  63 + self.save!
  64 + end
  65 +
58 66 end
... ...
lib/ext/profile_controller.rb
... ... @@ -2,6 +2,8 @@ require_dependency &#39;profile_controller&#39;
2 2  
3 3 class ProfileController
4 4  
  5 + before_filter :hit_view_page
  6 +
5 7 def communities
6 8 type = []
7 9 params[:type].downcase! unless params[:type].nil?
... ... @@ -37,4 +39,33 @@ class ProfileController
37 39 end
38 40 end
39 41  
  42 + def user_is_a_bot?
  43 + user_agent= request.env["HTTP_USER_AGENT"]
  44 + user_agent.blank? ||
  45 + user_agent.match(/bot/) ||
  46 + user_agent.match(/spider/) ||
  47 + user_agent.match(/crawler/) ||
  48 + user_agent.match(/\(.*https?:\/\/.*\)/)
  49 + end
  50 +
  51 + def already_visited?(element)
  52 + user_id = if user.nil? then -1 else current_user.id end
  53 + user_id = "#{user_id}_#{element.id}_#{element.class}"
  54 +
  55 + if cookies.signed[:visited] == user_id
  56 + return true
  57 + else
  58 + cookies.permanent.signed[:visited] = user_id
  59 + return false
  60 + end
  61 + end
  62 +
  63 + def hit_view_page
  64 + if profile
  65 + community = profile
  66 + community.hit unless user_is_a_bot? ||
  67 + already_visited?(community) ||
  68 + community.class != Community
  69 + end
  70 + end
40 71 end
... ...
lib/software_communities_plugin.rb
... ... @@ -42,7 +42,8 @@ class SoftwareCommunitiesPlugin &lt; Noosfero::Plugin
42 42 SearchCatalogBlock => { :type => [Environment] },
43 43 SoftwareHighlightsBlock => { :type => [Environment] },
44 44 SoftwareTabDataBlock => {:type => [Community], :position => 1},
45   - WikiBlock => {:type => [Community]}
  45 + WikiBlock => {:type => [Community]},
  46 + StatisticBlock => { :type => [Community] }
46 47 }
47 48 end
48 49  
... ...
lib/statistic_block.rb 0 → 100644
... ... @@ -0,0 +1,52 @@
  1 +class StatisticBlock < Block
  2 +
  3 + settings_items :benefited_people, :type => :integer, :default => 0
  4 + settings_items :saved_resources, :type => :float, :default => 0.0
  5 +
  6 + attr_accessible :benefited_people, :saved_resources
  7 +
  8 + def self.description
  9 + _('Software Statistics')
  10 + end
  11 +
  12 + def help
  13 + _('This block displays software statistics.')
  14 + end
  15 +
  16 + def content(args={})
  17 + download_blocks = get_profile_download_blocks(self.owner)
  18 + downloads = download_blocks.map do |download_block|
  19 + get_downloads_from_block(download_block)
  20 + end
  21 +
  22 + block = self
  23 +
  24 + lambda do |object|
  25 + render(
  26 + :file => 'blocks/software_statistics',
  27 + :locals => {
  28 + :block => block,
  29 + :total_downloads => downloads.sum
  30 + }
  31 + )
  32 + end
  33 + end
  34 +
  35 + def cacheable?
  36 + false
  37 + end
  38 +
  39 + private
  40 +
  41 + def get_profile_download_blocks profile
  42 + DownloadBlock.joins(:box).where("boxes.owner_id = ?", profile.id)
  43 + end
  44 +
  45 + def get_downloads_from_block download_block
  46 + downloads = download_block.downloads.map do |download|
  47 + download[:total_downloads] unless download[:total_downloads].nil?
  48 + end
  49 + downloads.select! {|value| not value.nil? }
  50 + downloads.sum
  51 + end
  52 +end
... ...
test/functional/profile_controller_test.rb 0 → 100644
... ... @@ -0,0 +1,40 @@
  1 +require "test_helper"
  2 +require 'profile_controller'
  3 +
  4 +# Re-raise errors caught by the controller.
  5 +class ProfileController; def rescue_action(e) raise e end; end
  6 +
  7 +class ProfileControllerTest < ActionController::TestCase
  8 + def setup
  9 + Environment.default.enable('products_for_enterprises')
  10 + @profile = create_user('testuser').person
  11 + end
  12 + attr_reader :profile
  13 +
  14 + should 'not count a visit twice for the same user' do
  15 + profile = create_user('someone').person
  16 + login_as(@profile.identifier)
  17 + community = fast_create('Community')
  18 +
  19 + get :index, :profile => community.identifier
  20 + community.reload
  21 + assert_equal 1, community.hits
  22 +
  23 + get :index, :profile => community.identifier
  24 + community.reload
  25 + assert_equal 1, community.hits
  26 + end
  27 +
  28 + should 'not count a visit twice for unlogged users' do
  29 + profile = create_user('someone').person
  30 + community = fast_create('Community')
  31 + get :index, :profile => community.identifier
  32 + community.reload
  33 + assert_equal 1, community.hits
  34 +
  35 + get :index, :profile => community.identifier
  36 + community.reload
  37 + assert_equal 1, community.hits
  38 + end
  39 +end
  40 +
... ...
test/functional/software_communities_plugin_profile_controller_test.rb 0 → 100644
... ... @@ -0,0 +1,67 @@
  1 +require File.dirname(__FILE__) + '/../../../../test/test_helper'
  2 +require File.dirname(__FILE__) + '/../helpers/software_test_helper'
  3 +require File.dirname(__FILE__) + '/../../controllers/software_communities_plugin_profile_controller'
  4 +
  5 +class SoftwareCommunitiesPluginProfileController; def rescue_action(e) raise e end; end
  6 +
  7 +class SoftwareCommunitiesPluginProfileControllerTest < ActionController::TestCase
  8 + include SoftwareTestHelper
  9 +
  10 + def setup
  11 + @controller = SoftwareCommunitiesPluginProfileController.new
  12 + @request = ActionController::TestRequest.new
  13 + @response = ActionController::TestResponse.new
  14 +
  15 + @environment = Environment.default
  16 + @environment.enable_plugin('SoftwareCommunitiesPlugin')
  17 + @environment.save!
  18 +
  19 + LicenseInfo.create(
  20 + :version=>"CC-GPL-V2",
  21 + :link=>"http://creativecommons.org/licenses/GPL/2.0/legalcode.pt"
  22 + )
  23 + @download_data = {
  24 + :name=>"Google",
  25 + :link=>"http://google.com",
  26 + :software_description=>"all",
  27 + :minimum_requirements=>"none",
  28 + :size=>"?",
  29 + :total_downloads=>0
  30 + }
  31 +
  32 + @software = create_software(software_fields)
  33 + @software.save!
  34 +
  35 + download_block = DownloadBlock.new
  36 + download_block.downloads = Download.validate_download_list([@download_data])
  37 + download_block.save!
  38 +
  39 + @software.community.blocks << download_block
  40 + @software.community.save!
  41 + end
  42 +
  43 + should 'redirect to download link with correct params' do
  44 + download_block = DownloadBlock.last
  45 + get :download_file, :profile=>@software.community.identifier,
  46 + :block => download_block.id, :download_index => 0
  47 +
  48 + assert_equal nil, session[:notice]
  49 + assert_redirected_to download_block.downloads[0][:link]
  50 + end
  51 +
  52 + should "notice when the download was not found" do
  53 + download_block = DownloadBlock.last
  54 + get :download_file, :profile=>@software.community.identifier,
  55 + :block => 123, :download_index => 0
  56 +
  57 + assert_equal "Could not find the download file", session[:notice]
  58 + end
  59 +
  60 + should "notice when given invalid download params" do
  61 + download_block = DownloadBlock.last
  62 + get :download_file, :profile=>@software.community.identifier,
  63 + :block => download_block.id, :download_index => -5
  64 +
  65 + assert_equal "Invalid download params", session[:notice]
  66 + end
  67 +end
... ...
test/unit/download_test.rb 0 → 100644
... ... @@ -0,0 +1,53 @@
  1 +require File.dirname(__FILE__) + '/../../../../test/test_helper'
  2 +require File.dirname(__FILE__) + '/../helpers/plugin_test_helper'
  3 +
  4 +class DownloadTest < ActiveSupport::TestCase
  5 + include PluginTestHelper
  6 +
  7 + def setup
  8 + @downloads_sample_data = [
  9 + {
  10 + :name=>"Sample data A",
  11 + :link=>"http://some.url.com",
  12 + :software_description=>"all",
  13 + :minimum_requirements=>"none",
  14 + :size=>"10 mb",
  15 + :total_downloads=>0
  16 + },
  17 + {
  18 + :name=>"Sample data B",
  19 + :link=>"http://other.url",
  20 + :software_description=>"Linux",
  21 + :minimum_requirements=>"500 mb Ram",
  22 + :size=>"3 GB",
  23 + :total_downloads=>123
  24 + }
  25 + ]
  26 + end
  27 +
  28 + should "Set as 0(zero) total_downloads if it is not given" do
  29 + without_total_downloads = Download.new({})
  30 + with_total_downloads = Download.new(@downloads_sample_data.last)
  31 +
  32 + assert_equal 0, without_total_downloads.total_downloads
  33 + assert_equal @downloads_sample_data.last[:total_downloads], with_total_downloads.total_downloads
  34 + end
  35 +
  36 + should "Remove downloads without a name" do
  37 + @downloads_sample_data[1] = @downloads_sample_data[1].slice! :name
  38 + downloads = Download.validate_download_list @downloads_sample_data
  39 +
  40 + assert_equal 1, downloads.size
  41 + assert_equal @downloads_sample_data[0][:name], downloads[0][:name]
  42 + end
  43 +
  44 + should "Only set total_downloads if the value is integer" do
  45 + download = Download.new(@downloads_sample_data.last)
  46 +
  47 + download.total_downloads = "456"
  48 + assert_not_equal 456, download.total_downloads
  49 +
  50 + download.total_downloads = 456
  51 + assert_equal 456, download.total_downloads
  52 + end
  53 +end
... ...
views/blocks/download.html.erb
... ... @@ -4,12 +4,19 @@
4 4 <h3 class="block-title"> <%= _("Download #{block.owner.software_info.community.name}") %> </h3>
5 5 <ul class="download-list">
6 6 <% block.downloads.each_with_index do |download, index| %>
7   - <li id="download-item-<%=(index+1)%>">
8   - <div class="download-button">
9   - <%= link_to download[:link], title: _("Download the software") do %>
10   - <span class="download-image"></span>
11   - <span class="download-size"><%= download[:size] %></span>
12   - <% end %>
  7 + <div id="download-info-<%=(index+1)%>">
  8 + <div id="version01">
  9 + <%= link_to :controller => 'software_communities_plugin_profile', :action=> 'download_file', :block=>block.id, :download_index=> index , title: _("Download the software") do %>
  10 + <span id="image-download"></span>
  11 + <span id="size-download"><%= download[:size] %></span>
  12 + <% end %>
  13 + </div>
  14 +
  15 + <div id="info-software-download">
  16 + <span class="download-name"><%= _("#{download[:name]}") %></span>
  17 + <span class="download-system"><%= _("Platform:#{download[:software_description]}") %> </span>
  18 + <span class="req_min_spb"><%= link_to _("Minimum Requirements"), download[:minimum_requirements] %></span>
  19 + </div>
13 20 </div>
14 21 <div class="download-info">
15 22 <span class="download-name"><%= _("#{download[:name]}") %></span>
... ...
views/blocks/software_statistics.html.erb 0 → 100644
... ... @@ -0,0 +1,11 @@
  1 +<div class="software-metrics-block">
  2 + <ul class="metrics-list">
  3 + <li><span class="arrow-globe-icon"></span><a href="#"><%= pluralize(profile.hits, 'visita', 'visitas') %></a></li>
  4 + <li><span class="downloads-icon"></span><a href="#"><%= pluralize(total_downloads, 'download', 'downloads') %></a></li>
  5 + <li><span class="face-icon"></span><a href="#"><%= block.benefited_people.to_s + _(' benefited people*') %></a></li>
  6 + <li><span class="pig-safe-icon"></span><a href="#"><strong class="saved-money"><%= number_to_currency(block.saved_resources, unit: 'R$ ', separator: ',', delimiter: '.') %></strong> <%= _(' saved resources*') %></a></li>
  7 + </ul>
  8 +
  9 +
  10 + <div class="admin-estimation">* <%= _("Data estimated by the software administrator.") %></div>
  11 +</div>
... ...
views/box_organizer/_statistic_block.html.erb 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +<div id='edit-softwares-block'>
  2 + <%= labelled_form_field _('Benefited People'), text_field(:block, :benefited_people) %>
  3 + <%= labelled_form_field _('Saved Resources'), text_field(:block, :saved_resources) %>
  4 +</div>
  5 +
... ...