mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-24 20:36:49 +00:00
Bring base files from spree_core
This commit is contained in:
196
app/helpers/spree/base_helper.rb
Normal file
196
app/helpers/spree/base_helper.rb
Normal file
@@ -0,0 +1,196 @@
|
||||
module Spree
|
||||
module BaseHelper
|
||||
|
||||
# Defined because Rails' current_page? helper is not working when Spree is mounted at root.
|
||||
def current_spree_page?(url)
|
||||
path = request.fullpath.gsub(/^\/\//, '/')
|
||||
if url.is_a?(String)
|
||||
return path == url
|
||||
elsif url.is_a?(Hash)
|
||||
return path == spree.url_for(url)
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def link_to_cart(text = nil)
|
||||
return "" if current_spree_page?(spree.cart_path)
|
||||
|
||||
text = text ? h(text) : Spree.t('cart')
|
||||
css_class = nil
|
||||
|
||||
if current_order.nil? or current_order.item_count.zero?
|
||||
text = "#{text}: (#{Spree.t('empty')})"
|
||||
css_class = 'empty'
|
||||
else
|
||||
text = "#{text}: (#{current_order.item_count}) <span class='amount'>#{current_order.display_total.to_html}</span>".html_safe
|
||||
css_class = 'full'
|
||||
end
|
||||
|
||||
link_to text, spree.cart_path, :class => "cart-info #{css_class}"
|
||||
end
|
||||
|
||||
# human readable list of variant options
|
||||
def variant_options(v, options={})
|
||||
v.options_text
|
||||
end
|
||||
|
||||
def meta_data_tags
|
||||
object = instance_variable_get('@'+controller_name.singularize)
|
||||
meta = {}
|
||||
|
||||
if object.kind_of? ActiveRecord::Base
|
||||
meta[:keywords] = object.meta_keywords if object[:meta_keywords].present?
|
||||
meta[:description] = object.meta_description if object[:meta_description].present?
|
||||
end
|
||||
|
||||
if meta[:description].blank? && object.kind_of?(Spree::Product)
|
||||
meta[:description] = strip_tags(truncate(object.description, length: 160, separator: ' '))
|
||||
end
|
||||
|
||||
meta.reverse_merge!({
|
||||
keywords: Spree::Config[:default_meta_keywords],
|
||||
description: Spree::Config[:default_meta_description]
|
||||
})
|
||||
|
||||
meta.map do |name, content|
|
||||
tag('meta', name: name, content: content)
|
||||
end.join("\n")
|
||||
end
|
||||
|
||||
def body_class
|
||||
@body_class ||= content_for?(:sidebar) ? 'two-col' : 'one-col'
|
||||
@body_class
|
||||
end
|
||||
|
||||
def logo(image_path=Spree::Config[:logo])
|
||||
link_to image_tag(image_path), spree.root_path
|
||||
end
|
||||
|
||||
def flash_messages(opts = {})
|
||||
opts[:ignore_types] = [:commerce_tracking].concat(Array(opts[:ignore_types]) || [])
|
||||
|
||||
flash.each do |msg_type, text|
|
||||
unless opts[:ignore_types].include?(msg_type)
|
||||
concat(content_tag :div, text, class: "flash #{msg_type}")
|
||||
end
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
def breadcrumbs(taxon, separator=" » ")
|
||||
return "" if current_page?("/") || taxon.nil?
|
||||
separator = raw(separator)
|
||||
crumbs = [content_tag(:li, link_to(Spree.t(:home), spree.root_path) + separator)]
|
||||
if taxon
|
||||
crumbs << content_tag(:li, link_to(Spree.t(:products), products_path) + separator)
|
||||
crumbs << taxon.ancestors.collect { |ancestor| content_tag(:li, link_to(ancestor.name , seo_url(ancestor)) + separator) } unless taxon.ancestors.empty?
|
||||
crumbs << content_tag(:li, content_tag(:span, link_to(taxon.name , seo_url(taxon))))
|
||||
else
|
||||
crumbs << content_tag(:li, content_tag(:span, Spree.t(:products)))
|
||||
end
|
||||
crumb_list = content_tag(:ul, raw(crumbs.flatten.map{|li| li.mb_chars}.join), class: 'inline')
|
||||
content_tag(:nav, crumb_list, id: 'breadcrumbs', class: 'sixteen columns')
|
||||
end
|
||||
|
||||
def taxons_tree(root_taxon, current_taxon, max_level = 1)
|
||||
return '' if max_level < 1 || root_taxon.children.empty?
|
||||
content_tag :ul, class: 'taxons-list' do
|
||||
root_taxon.children.map do |taxon|
|
||||
css_class = (current_taxon && current_taxon.self_and_ancestors.include?(taxon)) ? 'current' : nil
|
||||
content_tag :li, class: css_class do
|
||||
link_to(taxon.name, seo_url(taxon)) +
|
||||
taxons_tree(taxon, current_taxon, max_level - 1)
|
||||
end
|
||||
end.join("\n").html_safe
|
||||
end
|
||||
end
|
||||
|
||||
def available_countries
|
||||
checkout_zone = Zone.find_by(name: Spree::Config[:checkout_zone])
|
||||
|
||||
if checkout_zone && checkout_zone.kind == 'country'
|
||||
countries = checkout_zone.country_list
|
||||
else
|
||||
countries = Country.all
|
||||
end
|
||||
|
||||
countries.collect do |country|
|
||||
country.name = Spree.t(country.iso, scope: 'country_names', default: country.name)
|
||||
country
|
||||
end.sort { |a, b| a.name <=> b.name }
|
||||
end
|
||||
|
||||
def seo_url(taxon)
|
||||
return spree.nested_taxons_path(taxon.permalink)
|
||||
end
|
||||
|
||||
def gem_available?(name)
|
||||
Gem::Specification.find_by_name(name)
|
||||
rescue Gem::LoadError
|
||||
false
|
||||
rescue
|
||||
Gem.available?(name)
|
||||
end
|
||||
|
||||
def display_price(product_or_variant)
|
||||
product_or_variant.price_in(current_currency).display_price.to_html
|
||||
end
|
||||
|
||||
def pretty_time(time)
|
||||
[I18n.l(time.to_date, format: :long),
|
||||
time.strftime("%l:%M %p")].join(" ")
|
||||
end
|
||||
|
||||
def method_missing(method_name, *args, &block)
|
||||
if image_style = image_style_from_method_name(method_name)
|
||||
define_image_method(image_style)
|
||||
self.send(method_name, *args)
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
def link_to_tracking(shipment, options = {})
|
||||
return unless shipment.tracking
|
||||
|
||||
if shipment.tracking_url
|
||||
link_to(shipment.tracking, shipment.tracking_url, options)
|
||||
else
|
||||
content_tag(:span, shipment.tracking)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
# Returns style of image or nil
|
||||
def image_style_from_method_name(method_name)
|
||||
if style = method_name.to_s.sub(/_image$/, '')
|
||||
possible_styles = Spree::Image.attachment_definitions[:attachment][:styles]
|
||||
style if style.in? possible_styles.with_indifferent_access
|
||||
end
|
||||
end
|
||||
|
||||
def create_product_image_tag(image, product, options, style)
|
||||
options.reverse_merge! alt: image.alt.blank? ? product.name : image.alt
|
||||
image_tag image.attachment.url(style), options
|
||||
end
|
||||
|
||||
def define_image_method(style)
|
||||
self.class.send :define_method, "#{style}_image" do |product, *options|
|
||||
options = options.first || {}
|
||||
if product.images.empty?
|
||||
if !product.is_a?(Spree::Variant) && !product.variant_images.empty?
|
||||
create_product_image_tag(product.variant_images.first, product, options, style)
|
||||
else
|
||||
if product.is_a?(Variant) && !product.product.variant_images.empty?
|
||||
create_product_image_tag(product.product.variant_images.first, product, options, style)
|
||||
else
|
||||
image_tag "noimage/#{style}.png", options
|
||||
end
|
||||
end
|
||||
else
|
||||
create_product_image_tag(product.images.first, product, options, style)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
16
app/models/spree/log_entry.rb
Normal file
16
app/models/spree/log_entry.rb
Normal file
@@ -0,0 +1,16 @@
|
||||
module Spree
|
||||
class LogEntry < ActiveRecord::Base
|
||||
belongs_to :source, polymorphic: true
|
||||
|
||||
# Fix for #1767
|
||||
# If a payment fails, we want to make sure we keep the record of it failing
|
||||
after_rollback :save_anyway
|
||||
|
||||
def save_anyway
|
||||
log = Spree::LogEntry.new
|
||||
log.source = source
|
||||
log.details = details
|
||||
log.save!
|
||||
end
|
||||
end
|
||||
end
|
||||
143
spec/helpers/spree/base_helper_spec.rb
Normal file
143
spec/helpers/spree/base_helper_spec.rb
Normal file
@@ -0,0 +1,143 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Spree::BaseHelper do
|
||||
include Spree::BaseHelper
|
||||
|
||||
context "available_countries" do
|
||||
let(:country) { create(:country) }
|
||||
|
||||
before do
|
||||
3.times { create(:country) }
|
||||
end
|
||||
|
||||
context "with no checkout zone defined" do
|
||||
before do
|
||||
Spree::Config[:checkout_zone] = nil
|
||||
end
|
||||
|
||||
it "return complete list of countries" do
|
||||
available_countries.count.should == Spree::Country.count
|
||||
end
|
||||
end
|
||||
|
||||
context "with a checkout zone defined" do
|
||||
context "checkout zone is of type country" do
|
||||
before do
|
||||
@country_zone = create(:zone, :name => "CountryZone")
|
||||
@country_zone.members.create(:zoneable => country)
|
||||
Spree::Config[:checkout_zone] = @country_zone.name
|
||||
end
|
||||
|
||||
it "return only the countries defined by the checkout zone" do
|
||||
available_countries.should == [country]
|
||||
end
|
||||
end
|
||||
|
||||
context "checkout zone is of type state" do
|
||||
before do
|
||||
state_zone = create(:zone, :name => "StateZone")
|
||||
state = create(:state, :country => country)
|
||||
state_zone.members.create(:zoneable => state)
|
||||
Spree::Config[:checkout_zone] = state_zone.name
|
||||
end
|
||||
|
||||
it "return complete list of countries" do
|
||||
available_countries.count.should == Spree::Country.count
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Regression test for #1436
|
||||
context "defining custom image helpers" do
|
||||
let(:product) { mock_model(Spree::Product, :images => [], :variant_images => []) }
|
||||
before do
|
||||
Spree::Image.class_eval do
|
||||
attachment_definitions[:attachment][:styles].merge!({:very_strange => '1x1'})
|
||||
end
|
||||
end
|
||||
|
||||
it "should not raise errors when style exists" do
|
||||
expect { very_strange_image(product) }.not_to raise_error
|
||||
end
|
||||
|
||||
it "should raise NoMethodError when style is not exists" do
|
||||
expect { another_strange_image(product) }.to raise_error(NoMethodError)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# Regression test for #2034
|
||||
context "flash_message" do
|
||||
let(:flash) { {:notice => "ok", :foo => "foo", :bar => "bar"} }
|
||||
|
||||
it "should output all flash content" do
|
||||
flash_messages
|
||||
html = Nokogiri::HTML(helper.output_buffer)
|
||||
html.css(".notice").text.should == "ok"
|
||||
html.css(".foo").text.should == "foo"
|
||||
html.css(".bar").text.should == "bar"
|
||||
end
|
||||
|
||||
it "should output flash content except one key" do
|
||||
flash_messages(:ignore_types => :bar)
|
||||
html = Nokogiri::HTML(helper.output_buffer)
|
||||
html.css(".notice").text.should == "ok"
|
||||
html.css(".foo").text.should == "foo"
|
||||
html.css(".bar").text.should be_empty
|
||||
end
|
||||
|
||||
it "should output flash content except some keys" do
|
||||
flash_messages(:ignore_types => [:foo, :bar])
|
||||
html = Nokogiri::HTML(helper.output_buffer)
|
||||
html.css(".notice").text.should == "ok"
|
||||
html.css(".foo").text.should be_empty
|
||||
html.css(".bar").text.should be_empty
|
||||
helper.output_buffer.should == "<div class=\"flash notice\">ok</div>"
|
||||
end
|
||||
end
|
||||
|
||||
context "link_to_tracking" do
|
||||
it "returns tracking link if available" do
|
||||
a = link_to_tracking_html(:tracking => '123', :tracking_url => 'http://g.c/?t=123').css('a')
|
||||
|
||||
a.text.should == '123'
|
||||
a.attr('href').value.should == 'http://g.c/?t=123'
|
||||
end
|
||||
|
||||
it "returns tracking without link if link unavailable" do
|
||||
html = link_to_tracking_html(:tracking => '123', :tracking_url => nil)
|
||||
html.css('span').text.should == '123'
|
||||
end
|
||||
|
||||
it "returns nothing when no tracking" do
|
||||
html = link_to_tracking_html(:tracking => nil)
|
||||
html.css('span').text.should == ''
|
||||
end
|
||||
|
||||
def link_to_tracking_html(options = {})
|
||||
node = link_to_tracking(double(:shipment, options))
|
||||
Nokogiri::HTML(node.to_s)
|
||||
end
|
||||
end
|
||||
|
||||
# Regression test for #2396
|
||||
context "meta_data_tags" do
|
||||
it "truncates a product description to 160 characters" do
|
||||
# Because the controller_name method returns "test"
|
||||
# controller_name is used by this method to infer what it is supposed
|
||||
# to be generating meta_data_tags for
|
||||
text = Faker::Lorem.paragraphs(2).join(" ")
|
||||
@test = Spree::Product.new(:description => text)
|
||||
tags = Nokogiri::HTML.parse(meta_data_tags)
|
||||
content = tags.css("meta[name=description]").first["content"]
|
||||
assert content.length <= 160, "content length is not truncated to 160 characters"
|
||||
end
|
||||
end
|
||||
|
||||
context "pretty_time" do
|
||||
it "prints in a format" do
|
||||
expect(pretty_time(DateTime.new(2012, 5, 6, 13, 33))).to eq "May 06, 2012 1:33 PM"
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user