require 'uri' require 'rack' require 'json' require 'date' require 'liquid' module Redmineup module Liquid module Filters module Base include Redmineup::MoneyHelper def textilize(input) RedCloth3.new(input).to_html end def default(input, value) input.blank? ? value : input end def underscore(input) input.to_s.gsub(' ', '_').gsub('/', '_').underscore end def dasherize(input) input.to_s.gsub(' ', '-').gsub('/', '-').dasherize end def shuffle(array) array.to_a.shuffle end def random(input) rand(input.to_i) end def md5(input) Digest::MD5.hexdigest(input) unless input.blank? end # example: # {{ "http:://www.example.com?key=hello world" | encode }} # # => http%3A%3A%2F%2Fwww.example.com%3Fkey%3Dhello+world def encode(input) ::Rack::Utils.escape(input) end # example: # {{ today | plus_days: 2 }} def plus_days(input, distanse) return '' if input.nil? days = distanse.to_i input.to_date + days.days rescue 'Invalid date' end # example: # {{ today | date_range: '2015-12-12' }} def date_range(input, distanse) return '' if input.nil? (input.to_date - distanse.to_date).to_i rescue 'Invalid date' end # example: # {{ now | utc }} def utc(input) return '' if input.nil? input.to_time.utc rescue 'Invalid date' end def modulo(input, operand) apply_operation(input, operand, :%) end def round(input, n = 0) result = to_number(input).round(to_number(n)) result = result.to_f if result.is_a?(BigDecimal) result = result.to_i if n == 0 result end def ceil(input) to_number(input).ceil.to_i end def floor(input) to_number(input).floor.to_i end def currency(input, currency_code = nil) price_to_currency(input, currency_code || container_currency, :converted => false) end def call_method(input, method_name) if input.respond_to?(method_name) input.method(method_name).call end end def custom_field(input, field_name) if input.respond_to?(:custom_field_values) custom_value = input.custom_field_values.detect { |cfv| cfv.custom_field.name == field_name } custom_value.custom_field.format.formatted_custom_value(nil, custom_value) if custom_value end end def custom_fields(input) if input.respond_to?(:custom_field_values) input.custom_field_values.map { |cfv| cfv.custom_field.name } end end def attachment(input, file_name) if input.respond_to?(:attachments) if input.attachments.is_a?(Hash) attachment = input.attachments[file_name] else attachment = input.attachments.detect{|a| a.file_name == file_name} end AttachmentDrop.new attachment if attachment end end def multi_line(input) input.to_s.gsub("\n", '
').html_safe end def concat(input, *args) result = input.to_s args.flatten.each { |a| result << a.to_s } result end # right justify and padd a string def rjust(input, integer, padstr = '') input.to_s.rjust(integer, padstr) end # left justify and padd a string def ljust(input, integer, padstr = '') input.to_s.ljust(integer, padstr) end def textile(input) ::RedCloth3.new(input).to_html end protected # Convert an array of properties ('key:value') into a hash # Ex: ['width:50', 'height:100'] => { :width => '50', :height => '100' } def args_to_options(*args) options = {} args.flatten.each do |a| if (a =~ /^(.*):(.*)$/) options[$1.to_sym] = $2 end end options end # Write options (Hash) into a string according to the following pattern: # ="", =" orange_property end end end def time(input) case input when Time input.clone when Date input.to_time when String Time.parse(input) rescue Time.at(input.to_i) when Numeric Time.at(input) else raise Errors::InvalidDateError, "Invalid Date: '#{input.inspect}' is not a valid datetime." end.localtime end def groupable?(element) element.respond_to?(:group_by) end def item_property(item, property) if item.respond_to?(:to_liquid) property.to_s.split(".").reduce(item.to_liquid) do |subvalue, attribute| subvalue[attribute] end elsif item.respond_to?(:data) item.data[property.to_s] else item[property.to_s] end end def as_liquid(item) case item when Hash pairs = item.map { |k, v| as_liquid([k, v]) } Hash[pairs] when Array item.map { |i| as_liquid(i) } else if item.respond_to?(:to_liquid) liquidated = item.to_liquid # prevent infinite recursion for simple types (which return `self`) if liquidated == item item else as_liquid(liquidated) end else item end end end def container @container ||= @context.registers[:container] end def container_currency container.currency if container.respond_to?(:currency) end end ::Liquid::Template.register_filter(Redmineup::Liquid::Filters::Base) end end end