Module: CmsApplicationHelper

Defined in:
app/helpers/cms_application_helper.rb

Instance Method Summary collapse

Instance Method Details

#all_times_array(interval = 5) ⇒ Object

Get an array of all times, useful in select’s (5 minute interval by default)



606
607
608
609
610
611
612
613
614
615
616
617
# File 'app/helpers/cms_application_helper.rb', line 606

def all_times_array(interval = 5)
  a = []
  (0..23).each do |h|
    (0..59).each do |m|
      next unless m % interval == 0
      t = Time.utc(2000, 1, 1, h, m)
      a << t.strftime("%I").to_i.to_s + t.strftime(":%M%p").downcase
    end
  end
  
  a
end


584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
# File 'app/helpers/cms_application_helper.rb', line 584

def breadcrumbs(options = {})
  # only works on CCS pages
  if @pg
    separator = options.delete(:separator) || ' &raquo; '
    link_class = options.delete(:link_class)
    
    pg = @pg
    ret = pg.title
    
    while pg = pg.parent
      if pg.published_version >= 0
        ret = "<a href=\"/#{pg.path}\" class=\"#{link_class}\">#{pg.title}</a>" + separator + ret
      end
    end
    
    return ret
  else
    return ''
  end
end

#convert_content_pathObject



40
41
42
# File 'app/helpers/cms_application_helper.rb', line 40

def convert_content_path
  params[:content_path] = params[:content_path].to_s.split('/') rescue []
end

#convert_invalid_chars!(s) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'app/helpers/cms_application_helper.rb', line 76

def convert_invalid_chars!(s)
  # leave commented out until we're sure these are still needed
  
  # s.gsub!(/\xe2\x80\x98/, '&lsquo;')  # ‘
  # s.gsub!(/\xe2\x80\x99/, '&rsquo;')  # ’
  # s.gsub!(/\xe2\x80\x9c/, '&ldquo;')  # “
  # s.gsub!(/\xe2\x80\x9d/, '&rdquo;')  # ”
  # s.gsub!(/\xe2\x80\x93/, '&ndash;')  # –
  # s.gsub!(/\xe2\x80\x94/, '&mdash;')  # —
  # s.gsub!(/\xe2\x80\xa2/, '&bull;')   # •
  # s.gsub!(/\xe2\x80\xa6/, '&hellip;') # …
  # s.gsub!(/\xe2\x80\xa8/, '&nbsp;')   # (space)
  # s.gsub!(/\xe2\x84\xa2/, '&trade;')  # ™
  # 
  # s.gsub!(/\xc2\xae/, '&reg;')    # ®
  # s.gsub!(/\xc2\xab/, '&laquo;')  # «
  # s.gsub!(/\xc2\xbb/, '&raquo;')  # »
  # s.gsub!(/\xc2\xbd/, '&frac12;') # ½
  # s.gsub!(/\xc2\xbc/, '&frac14;') # ¼
  # 
  # s.gsub!(/\xc4\x80/, '&#x100;')  # Ā
  # s.gsub!(/\xc4\x81/, '&#x101;')  # ā
  # s.gsub!(/\xc4\x92/, '&#x112;')  # Ē
  # s.gsub!(/\xc4\x93/, '&#x113;')  # ē
  # s.gsub!(/\xc4\xaa/, '&#x12A;')  # Ī
  # s.gsub!(/\xc4\xab/, '&#x12B;')  # ī
  # s.gsub!(/\xc5\x8c/, '&#x14C;')  # Ō
  # s.gsub!(/\xc5\x8d/, '&#x14D;')  # ō
  # s.gsub!(/\xc5\xaa/, '&#x16A;')  # Ū
  # s.gsub!(/\xc5\xab/, '&#x16B;')  # ū
  # 
  # s.gsub!(/\xc3\x84/, '&Auml;') # Ä
  # s.gsub!(/\xc3\x8b/, '&Euml;') # Ë
  # s.gsub!(/\xc3\x8f/, '&Iuml;') # Ï
  # s.gsub!(/\xc3\x96/, '&Ouml;') # Ö
  # s.gsub!(/\xc3\x9c/, '&Uuml;') # Ü
  # s.gsub!(/\xc3\xa4/, '&auml;') # ä
  # s.gsub!(/\xc3\xab/, '&euml;') # ë
  # s.gsub!(/\xc3\xaf/, '&iuml;') # ï
  # s.gsub!(/\xc3\xb6/, '&ouml;') # ö
  # s.gsub!(/\xc3\xbc/, '&uuml;') # ü
  # 
  # s.gsub!(/\xc3\x81/, '&Aacute;') # Á
  # s.gsub!(/\xc3\x89/, '&Eacute;') # É
  # s.gsub!(/\xc3\x8d/, '&Iacute;') # Í
  # s.gsub!(/\xc3\x93/, '&Oacute;') # Ó
  # s.gsub!(/\xc3\x9a/, '&Uacute;') # Ú
  # s.gsub!(/\xc3\xa1/, '&aacute;') # á
  # s.gsub!(/\xc3\xa9/, '&eacute;') # é
  # s.gsub!(/\xc3\xad/, '&iacute;') # í
  # s.gsub!(/\xc3\xb3/, '&oacute;') # ó
  # s.gsub!(/\xc3\xba/, '&uacute;') # ú
  # 
  # s.gsub!(/\xc5\x98/, '&#x158;') # Ř
  # s.gsub!(/\xc5\x99/, '&#x159;') # ř
  # 
  # s.gsub!(/\x85/, '&hellip;') # …
  # s.gsub!(/\x8b/, '&lt;')     # <
  # s.gsub!(/\x9b/, '&gt;')     # >
  # s.gsub!(/\x91/, '&lsquo;')  # ‘
  # s.gsub!(/\x92/, '&rsquo;')  # ’
  # s.gsub!(/\x93/, '&ldquo;')  # “
  # s.gsub!(/\x94/, '&rdquo;')  # ”
  # s.gsub!(/\x97/, '&mdash;')  # —
  # s.gsub!(/\x99/, '&trade;')  # ™
  # s.gsub!(/\x95/, '*')
  # s.gsub!(/\x96/, '-')
  # s.gsub!(/\x98/, '~')
  # s.gsub!(/\x88/, '^')
  # s.gsub!(/\x82/, ',')
  # s.gsub!(/\x84/, ',,')
  # s.gsub!(/\x89/, 'o/oo')
  # s.gsub!(/\x8c/, 'OE')
  # s.gsub!(/\x9c/, 'oe')
end

#convert_invalid_chars_in_paramsObject



62
63
64
# File 'app/helpers/cms_application_helper.rb', line 62

def convert_invalid_chars_in_params
  dig_deep(params) { |s| convert_invalid_chars!(s) }
end


1089
1090
1091
1092
1093
# File 'app/helpers/cms_application_helper.rb', line 1089

def copyright_year(year)
  year_str, this_year = year.to_s, Time.now.year.to_s
  year_str << "&ndash;#{this_year}" if ((year_str.to_i.to_s == year_str) and (year_str.to_i != this_year.to_i))
  year_str.html_safe
end

#cropper_image_tag(options) ⇒ Object



1056
1057
1058
1059
# File 'app/helpers/cms_application_helper.rb', line 1056

def cropper_image_tag(options)
  ret = "<img id=\"testImage\" src=\"/assets/#{options[:url]}\" />".html_safe
  ret += javascript_tag("cropper = new Cropper.Img('testImage', { minWidth: 0, minHeight: 0, captureKeys: false, onEndCrop: onEndCrop });")
end

#date_picker(object, method_prefix, options = {}) ⇒ Object

Display a date picker with an ajax calendar.

Options:

  • :default_value => Time.now

  • :start_date => ‘06/01/2006’, :end_date => ‘05/31/2007’

  • :exclude_days => [ :monday, :saturday, :sunday ]

  • :blackout_ranges => [ [‘06/04/2006’, ‘06/18/2006’], [‘08/16/2006’, ‘09/01/2006’] ] (not implemented)

TODOC: There are a number of somewhat complex prerequisites…



777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
# File 'app/helpers/cms_application_helper.rb', line 777

def date_picker(object, method_prefix, options = {})
  object = object.to_s
  method_prefix = method_prefix.to_s
  
  # set some arbitrary but sensible limits for now...
  start_date = options[:start_date] || 5.years.ago
  start_date = Time.parse(start_date) if start_date.kind_of? String
  end_date   = options[:end_date] || 10.years.from_now
  end_date = Time.parse(end_date) if end_date.kind_of? String
  
  onchange = options[:onchange] || ''
  exclude_days = options[:exclude_days] || []
  min_year = start_date.year
  max_year = end_date.year
  
  
  exclude_days.map! do |d|
    case (d)
      when :sunday then 0
      when :monday then 1
      when :tuesday then 2
      when :wednesday then 3
      when :thursday then 4
      when :friday then 5
      when :saturday then 6
      else nil
    end
  end
  
  i = 0
  while exclude_days.include?(start_date.wday) && i < 7
    start_date += 1.day
    i += 1
  end
  
  default_value = options[:default_value] || (instance_variable_get("@#{object}").send(method_prefix) rescue nil)
  default_value = Time.parse(default_value) if default_value.is_a?(String)
  default_value ||= start_date
  
  draw_calendar = <<-EOT
    window.addEventListener('DOMContentLoaded', (event) => {
      new Ajax.Updater('date_picker_#{object}_#{method_prefix}_days',
                         '#{date_picker_url}?month=' + $('#{object}_#{method_prefix}_month_sel').value +
                         '&year=' + $('#{object}_#{method_prefix}_year_sel').value +
                         '&min_time=' + #{start_date.to_i} +
                         '&max_time=' + #{end_date.to_i} +
                         '&exclude_days=#{exclude_days.join(',')}' +
                         '&onchange=#{escape_javascript(options[:onchange])}' +
                         '&object=#{object}' +
                         '&method_prefix=#{method_prefix}', {method:'get', asynchronous:true, evalScripts:true})
      });
    EOT

  ret = <<-EOT
<span><a href="#" onclick="showDatePicker('#{object}', '#{method_prefix}'); return false;"><span id="date_picker_#{object}_#{method_prefix}_value" style="font-weight: normal;">#{default_value.strftime('%a %m/%d/%y')}</span></a></span>
<span id="date_picker_#{object}_#{method_prefix}icon"><a href="#" onclick="showDatePicker('#{object}', '#{method_prefix}'); return false;"><img src="/assets/management/icon_time.gif" style="float: none" alt="date picker" /></a></span>
<div id="date_picker_#{object}_#{method_prefix}main" style="display: none; background-color: white; border: 1px solid gray; padding: 3px; z-index: 101;" class="date-picker-main">
  <table width="190">
    <tr>
      <td><a href="#" onclick="dpPrevMonth('#{object}', '#{method_prefix}', #{min_year}); #{h(draw_calendar)}; return false;"><img src="/assets/interface/arrow_previous.gif" border="0" alt="Previous" style="float: left; padding: 2px 0 0 6px; margin: 0;" /></a></td>
      <td colspan="5" align="center">
        <nobr>
        #{ select_tag object + '_' + method_prefix + '_month_sel', options_for_select(months_hash, default_value.month.to_s), :class => 'form', :style => 'border: 1px solid gray; font-size: 11px; padding: 0; margin: 0;', :onchange => h(draw_calendar) }
        #{ select_tag object + '_' + method_prefix + '_year_sel', options_for_select((min_year..max_year).to_a, default_value.year), :class => 'form', :style => 'border: 1px solid gray; font-size: 11px; padding: 0; margin: 0;', :onchange => h(draw_calendar) }
        </nobr>
      </td>
      <td><a href="#" onclick="dpNextMonth('#{object}', '#{method_prefix}', '#{max_year}'); #{h(draw_calendar)}; return false;"><img src="/assets/interface/arrow_next.gif" border="0" alt="Next" style="float: right; padding: 2px 6px 0 0; margin: 0;" /></a></td>
    </tr>
  </table>
  <div id="date_picker_#{object}_#{method_prefix}_days" class="date-picker-days"></div>
  #{ text_field object, method_prefix + '_year', :value => default_value.year, :style => 'display: none;' }
  #{ text_field object, method_prefix + '_month', :value => default_value.month, :style => 'display: none;' }
  #{ text_field object, method_prefix + '_day', :value => default_value.day, :style => 'display: none;' }
  <div style="width: 100%;" align="center" class="date-picker-close">
      <a href="#" onclick="hideDatePicker('#{object}', '#{method_prefix}'); return false;">Close</a>
  </div>
</div>
EOT
  ret += javascript_tag(draw_calendar)
  ret.html_safe
end

#date_to_str(t, convert = true) ⇒ Object

Convert times to a standard format (e.g. 1:35pm)



186
187
188
189
190
191
192
193
# File 'app/helpers/cms_application_helper.rb', line 186

def date_to_str(t, convert = true)
  return '' if t == nil
  if convert
    gm_to_local(t).strftime("%m").to_i.to_s + '/' + gm_to_local(t).strftime("%d").to_i.to_s + gm_to_local(t).strftime("/%Y")
  else
    t.strftime("%m").to_i.to_s + '/' + t.strftime("%d").to_i.to_s + t.strftime("/%Y")
  end
end

#dig_deep(hash, &block) ⇒ Object



66
67
68
69
70
71
72
73
74
# File 'app/helpers/cms_application_helper.rb', line 66

def dig_deep(hash, &block)
  if hash.instance_of? String
    yield(hash)
  elsif hash.kind_of? Hash
    hash.each_key { |h| dig_deep(hash[h]) { |s| block.call(s) } }
  else
    nil
  end
end

#encoded_mail_to(email, link_text = nil) ⇒ Object

Creates a mailto: link that is encoded to prevent most harvesting attempts.



754
755
756
757
758
759
760
761
762
763
764
765
766
# File 'app/helpers/cms_application_helper.rb', line 754

def encoded_mail_to(email, link_text = nil)
  email = h(email)
  url = ''
  text = ''
  
  # this only works with ascii, but email addresses are supposed to be ascii
  email.bytes.to_a.each_with_index do |b, i|
    url << (i % 2 == 0 ? sprintf("%%%x", b) : b)
    text << (i % 4 == 0 ? '<span>' << b << '</span>' : b)
  end
  
  "<a href=\"mailto:#{url}\">#{link_text || text}</a>".html_safe
end

#error_messages_for(object_name, options = {}) ⇒ Object

:nodoc:



663
664
665
666
667
668
669
670
671
672
673
674
675
# File 'app/helpers/cms_application_helper.rb', line 663

def error_messages_for(object_name, options = {}) # :nodoc:
  options = options.symbolize_keys
  object = instance_variable_get("@#{object_name.to_s}")
  return '' unless object
  
  unless object.errors.empty?
    ("div",
      ("h3", "There were problems with the following fields:") +
      ("ul", object.errors.full_messages.collect { |msg| ("li", msg) }),
      "id" => options[:id] || "errorExplanation", "class" => options[:class] || "errorExplanation"
    )
  end
end

#event_calendar(options = {}) ⇒ Object

Display a clickable ajax event calendar.

Options:

  • :start_date => ‘06/01/2006’, :end_date => ‘05/31/2007’

  • :show_selects => true (default :false)

  • :calendar_id => 1

  • :css_prefix => ‘calendar_’

TODOC: There are a number of somewhat complex prerequisites…



868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
# File 'app/helpers/cms_application_helper.rb', line 868

def event_calendar(options = {})
  start_date = options[:start_date] || Time.now
  end_date   = options[:end_date] || 1.year.from_now
  start_date = Time.parse(start_date) if start_date.is_a? String
  end_date = Time.parse(end_date) if end_date.is_a? String
  
  onchange = options[:onchange] || ''
  min_year = start_date.year
  max_year = min_year + 5
  
  calendar_id = options[:calendar_id] || Calendar.find_first.id
  
  css_prefix = options[:css_prefix] || 'calendar_'
  popout_direction = options[:popout_direction] || :right
  
  draw_calendar = "var ta = $('event_calendar_events_' + " +
                  "$('event_calendar_month_sel').value + '_' + $('event_calendar_year_sel').value); " +
                  "new Ajax.Request(" +
                  "'#{url_for :controller => "/util", :action => "calendar" }?" +
                  "month=' + $('event_calendar_month_sel').value + " +
                  "'&year=' + $('event_calendar_year_sel').value + " +
                  "'&min_time=#{start_date.to_i}&max_time=#{end_date.to_i}" +
                  "&calendar_id=#{calendar_id}&css_prefix=#{css_prefix}" +
                  "&popout_direction=#{popout_direction.to_s}', {method:'get', asynchronous:true, evalScripts:true})"
  
  # keep all this junk in sync with what's in UtilController
  @month = Time.now.month
  @year = Time.now.year
  @min_time = start_date.to_i
  @max_time = end_date.to_i
  @calendar = Calendar.find(calendar_id)
  @css_prefix = css_prefix
  @popout_direction = popout_direction
  
  first_of_month = Time.utc(@year, @month, 1)
  last_of_month = first_of_month.end_of_month
  events = @calendar.events.where('start_date >= ? and start_date <= ?', first_of_month, last_of_month)
    
  @event_days = {}
  events.each do |e|
    @event_days[e.start_date.mday] = e
  end
  
  ret = <<EOF
<table id="event_calendar" class="#{css_prefix}container" cellspacing="0" cellpadding="0" border="0">
  <tr class="#{css_prefix}container">
    <td class="#{css_prefix}container">
      <table class="#{css_prefix}head" cellspacing="0" cellpadding="0" border="0">
        <tr class="#{css_prefix}head">
          <td class="#{css_prefix}head #{css_prefix}head_prev_month"><a href="#" onclick="dpPrevMonth('event', 'calendar', #{min_year}); #{draw_calendar}; return false;"><img src="/assets/interface/arrow_previous.gif" border="0" alt="Previous" style="float: left; padding-left: 2px;" /></a></td>
          <td class="#{css_prefix}head #{css_prefix}head_month_select">
            <div#{options[:show_selects] ? '' : ' style="display: none"'}>
              #{ select 'event_calendar', 'month_sel', months_hash, { :selected => Time.now.month.to_s }, :class => 'form', :style => 'font-size: 11px;', :onchange => draw_calendar }
              #{ select 'event_calendar', 'year_sel', (min_year..max_year).to_a, { :selected => Time.now.year }, :class => 'form', :style => 'font-size: 11px;', :onchange => draw_calendar }
            </div>
            <div id="event_calendar_month_year"#{options[:show_selects] ? ' style="display: none"' : ''}>
              #{render '/util/_calendar_month_year'}
            </div>
          </td>
          <td class="#{css_prefix}head #{css_prefix}head_next_month"><a href="#" onclick="dpNextMonth('event', 'calendar', '#{max_year}'); #{draw_calendar}; return false;"><img src="/assets/interface/arrow_next.gif" border="0" alt="Next" style="float: right; padding-right: 2px;" /></a></td>
        </tr>
      </table>
    </td>
  </tr>
  <tr class="#{css_prefix}container">
    <td class="#{css_prefix}container">
      <div id="event_calendar_days" class="#{css_prefix}container #{css_prefix}container_days">
        #{render '/util/_calendar_days'}
      </div>
    </td>
  </tr>
</table>
EOF
  ret += javascript_tag(draw_calendar)
end

#first_non_empty(*args) ⇒ Object

Returns the first non-blank string in its arg list.



51
52
53
54
55
56
57
58
59
60
# File 'app/helpers/cms_application_helper.rb', line 51

def first_non_empty(*args)
  while !args.empty?
    ret = args.shift
    # TODO: This is what I want to do, but it caused a subtle change in behavior that was
    #       unacceptable for existing sites. Implement in next major version (post-3.0).
    # return ret unless ret.to_s.blank?
    return ret unless ret.to_s == ''
  end
  return ''
end

#flash_messageObject

Display any available flash messages (:error, :notice),

NOTE: @error and @notice are deprecated, use flash.now and flash.now instead.



680
681
682
683
684
685
686
687
688
# File 'app/helpers/cms_application_helper.rb', line 680

def flash_message
  link = ''.html_safe
  link << ' '.html_safe + link_to(flash[:link][0], flash[:link][1]) if flash[:link].present? && flash[:link].is_a?(Array)
  
  output = ''.html_safe
  output << ('div', h(flash[:error]) + link, class: 'alert alert-error error') if flash[:error].present?
  output << ('div', h(flash[:notice]) + link, class: 'alert alert-info notice') if flash[:notice].present?
  output
end

#form_icons(object_name, method_name, options = {}) ⇒ Object

Takes object_name and method_name as arguments (like other form helpers, such as text_field) and returns html containing form_error.gif and form_loading.gif. If there are no errors for the given field, form_error.gif is hidden using style=“display: none”. If there are errors, form_error.gif is shown, and its hover text lists the errors.



624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
# File 'app/helpers/cms_application_helper.rb', line 624

def form_icons(object_name, method_name, options = {})
  object_name = object_name.to_s
  method_name = method_name.to_s
  
  ret = ''
  errors = []
  
  instance_variable_get("@#{object_name}").errors.each do |attr, msg|
    errors << msg if attr == method_name
  end
  
  options[:style] ||= ''
  
  if errors.size == 0
    options[:style] << 'display: none;'
  end
  
  ret << "<div id=\"#{object_name}_#{method_name}_error\" class=\"form-error\""
  ret << " style=\"#{options[:style]}\"" unless options[:style].blank?
  if errors.size > 0
    ret << " title=\"#{h errors.join('; ')}\""
  end
  ret << '><img src="/assets/interface/form_error.gif" width="17" height="17" border="0" />'
  ret << '</div>'
  
  ret << "<div id=\"#{object_name}_#{method_name}_loading\" class=\"form-loading\" style=\"display: none;\">"
  ret << image_tag("interface/form_loading.gif", size: '16x16', border: 0, style: "margin: 0 1px 1px 0;")
  ret << "</div>"
  
  if errors.size > 0 && options[:display_messages]
    options[:message_separator] ||= '<br/>'
    ret << "<div id=\"#{object_name}_#{method_name}_error_messages\" class=\"form-error-messages\">"
    ret << errors.join(options[:message_separator])
    ret << "</div>"
  end
  
  ret
end

#gm_to_local(time) ⇒ Object

Convert from GMT/UTC to local time (based on time zone setting in session)



153
154
155
# File 'app/helpers/cms_application_helper.rb', line 153

def gm_to_local(time)
  ActiveSupport::TimeZone.new(session[:time_zone] || 'UTC').utc_to_local(time)
end

#image_button_to(source, options = {}, html_options = {}) ⇒ Object

Similar to button_to, but takes a url for a button image as its first argument.



691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
# File 'app/helpers/cms_application_helper.rb', line 691

def image_button_to(source, options = {}, html_options = {})
  # html_options.stringify_keys!
  # html_options[:type] = 'image'
  # html_options[:src] = image_path(source)
  # 
  # convert_boolean_attributes!(html_options, %w( disabled ))
  # 
  # if confirm = html_options.delete("confirm")
  #   html_options["onclick"] = "return #{confirm_javascript_function(confirm)};"
  # end
  # 
  # url = options.is_a?(String) ? options : url_for(options)
  # name ||= url
  # 
  # "<form method=\"post\" action=\"#{h url}\" class=\"image-button-to\"><div>" +
  #   tag("input", html_options) + "</div></form>"
  html_options = html_options.stringify_keys
  
  convert_boolean_attributes!(html_options, %w( disabled ))

  method_tag = ''
  if (method = html_options.delete('method')) && %w{put delete}.include?(method.to_s)
    method_tag = tag('input', :type => 'hidden', :name => '_method', :value => method.to_s)
  end

  form_method = method.to_s == 'get' ? 'get' : 'post'
  form_options = html_options.delete('form') || {}
  form_options[:class] ||= html_options.delete('form_class') || 'button_to'

  remote = html_options.delete('remote')

  request_token_tag = ''
  if form_method == 'post' && protect_against_forgery?
    request_token_tag = tag(:input, :type => "hidden", :name => request_forgery_protection_token.to_s, :value => form_authenticity_token)
  end

  url = options.is_a?(String) ? options : self.url_for(options)
  name ||= url

  html_options = convert_options_to_data_attributes(options, html_options)

  html_options.merge!("type" => "image", "value" => name, "src" => image_path(source))

  form_options.merge!(:method => form_method, :action => url, :class => "image-button-to")
  form_options.merge!("data-remote" => "true") if remote

  "#{tag(:form, form_options, true)}<div>#{method_tag}#{tag("input", html_options)}#{request_token_tag}</div></form>".html_safe
end

#image_submit_to_remote(source, options = {}) ⇒ Object

Similar to submit_to_remote, but takes a url for a button image as its first argument.



742
743
744
745
746
747
748
749
750
751
# File 'app/helpers/cms_application_helper.rb', line 742

def image_submit_to_remote(source, options = {})
  options[:with] ||= 'Form.serialize(this.form)'
  
  options[:html] ||= {}
  options[:html][:type] = 'image'
  options[:html][:onclick] = "#{remote_function(options)}; return false;"
  options[:html][:src] = image_path(source)
  
  tag("input", options[:html], false)
end

#is_editing_page?Boolean

Returns true if the user is editing the current page.

Returns:

  • (Boolean)


14
15
16
# File 'app/helpers/cms_application_helper.rb', line 14

def is_editing_page?
  params[:controller] == 'manage/cms_pages' && params[:action] == 'edit_page_content'
end

#is_logged_in?Boolean

Returns true if a Member is logged in.

Returns:

  • (Boolean)


4
5
6
# File 'app/helpers/cms_application_helper.rb', line 4

def is_logged_in?
  session[:authenticated]
end

#is_logged_in_user?Boolean

Returns true if a User is logged in.

Returns:

  • (Boolean)


9
10
11
# File 'app/helpers/cms_application_helper.rb', line 9

def is_logged_in_user?
  session[:user_authenticated]
end

#load_page_objects(obj_type = nil, name = nil) ⇒ Object



197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'app/helpers/cms_application_helper.rb', line 197

def load_page_objects(obj_type = nil, name = nil)
  if params[:version].to_i > 0 && params[:version].to_i != @pg.published_version && !(@pg.published_version == 0 && params[:version].to_i == @pg.version)
    if is_logged_in_user?
      if user_has_permission?(:manage_cms)
        @pg.revert_to(params[:version].to_i)
      end
    else
      authenticate_user
      return false
    end
  elsif @pg.version != @pg.published_version
    @pg.revert_to(@pg.published_version)
  end
  
  @page_objects = OpenStruct.new
  query = @pg.objects.where(:cms_page_version => @pg.version)
  query = query.where(:obj_type => obj_type) if obj_type
  query = query.where(:name => name) if name
  query.each { |obj| @page_objects["obj-#{obj.obj_type.to_s}-#{obj.name}"] = obj.content }
  
  @page_objects
end

#local_to_gm(time) ⇒ Object

Convert from local time to GMT/UTC (based on time zone setting in session)



158
159
160
# File 'app/helpers/cms_application_helper.rb', line 158

def local_to_gm(time)
  ActiveSupport::TimeZone.new(session[:time_zone] || 'UTC').local_to_utc(time)
end

#months_hashObject

Returns a hash containing the months of the year. Intended for use with the select form helper.



1040
1041
1042
1043
1044
1045
# File 'app/helpers/cms_application_helper.rb', line 1040

def months_hash
  { 'January' => '1', 'February' => '2', 'March' => '3', 'April' => '4',
    'May' => '5', 'June' => '6', 'July' => '7', 'August' => '8',
    'September' => '9', 'October' => '10', 'November' => '11',
    'December' => '12' }.sort{ |a, b| a.last.to_i <=> b.last.to_i }
end

#ordered_hash(input) ⇒ Object

Note that this currently won’t work for > 100 options



983
984
985
986
987
988
989
990
991
# File 'app/helpers/cms_application_helper.rb', line 983

def ordered_hash(input) # :nodoc:
  ret = Hash.new
  i = 0
  for k in input
    ret[k[0]] = (i < 10 ? '0' + i.to_s : i.to_s) + k[1]
    i += 1
  end
  ret.sort { |a,b| a[1] <=> b[1] }.map { |a| a[1].slice!(0...2) ; a }
end

#page_file_path(page, filename) ⇒ Object

filename should include version number in query string



1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
# File 'app/helpers/cms_application_helper.rb', line 1062

def page_file_path(page, filename)
  if ImagineCmsConfig['amazon_s3'] && ImagineCmsConfig['amazon_s3']['enabled']
    prefix = ImagineCmsConfig['amazon_s3']['file_prefix']
    hostname = ImagineCmsConfig['amazon_s3'][Rails.env]['file_hostname']
    filename, timestamp = File.basename(filename).split('?')
    "//#{hostname}/#{prefix}/#{page.path.blank? ? 'index' : page.path}/#{ERB::Util.url_encode filename}?#{timestamp}"
  else
    "/#{File.join('assets', 'content', page.path, File.basename(filename))}"
  end
end

#page_image_path(page, filename) ⇒ Object

filename should include version number in query string



1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
# File 'app/helpers/cms_application_helper.rb', line 1074

def page_image_path(page, filename)
  if ImagineCmsConfig['amazon_s3'] && ImagineCmsConfig['amazon_s3']['enabled']
    prefix = ImagineCmsConfig['amazon_s3']['image_prefix']
    hostname = ImagineCmsConfig['amazon_s3'][Rails.env]['image_hostname']
    filename, timestamp = File.basename(filename).split('?')
    "//#{hostname}/#{prefix}/#{page.path.blank? ? 'index' : page.path}/#{ERB::Util.url_encode filename}?#{timestamp}"
  else
    "/#{File.join('assets', 'content', page.path, File.basename(filename))}"
  end
end

#page_image_tag(page, filename) ⇒ Object



1085
1086
1087
# File 'app/helpers/cms_application_helper.rb', line 1085

def page_image_tag(page, filename)
  "<img src=\"#{page_image_path(page, filename)}\" alt=\"#{File.basename(filename, '.*').sub(/-[[:xdigit:]]{32}\z/, '').capitalize}\" />".html_safe
end

#page_list_items(pg, key, options = {}) ⇒ Object



220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
# File 'app/helpers/cms_application_helper.rb', line 220

def page_list_items(pg, key, options = {})
  pages = []
  single_pages = []
  instance_tags_include = []
  instance_tags_exclude = []
  instance_tags_require = []
  
  conditions = [ 'cms_pages.published_version >= 0', 'cms_pages.published_date is not null', 'cms_pages.published_date < NOW()' ]
  cond_vars = []
  
  if options[:start_date]
    options[:start_date] = Time.parse(options[:start_date]) if options[:start_date].is_a? String
    conditions << 'cms_pages.article_date >= ?'
    cond_vars << options[:start_date]
  end
  if options[:end_date]
    options[:end_date] = Time.parse(options[:end_date]) if options[:end_date].is_a? String
    conditions << 'cms_pages.article_date < ?'
    cond_vars << (options[:end_date] + 1.day)
  end
  
  @page_objects["#{key}-sources-tag-count"] = @page_objects["#{key}-sources-tag-count"].to_i
  
  for i in 0...@page_objects["#{key}-sources-tag-count"]
    case @page_objects["#{key}-sources-tag#{i}-behavior"]
    when 'include'
      instance_tags_include << @page_objects["#{key}-sources-tag#{i}"]
    when 'exclude'
      instance_tags_exclude << @page_objects["#{key}-sources-tag#{i}"]
    when 'require'
      instance_tags_require << @page_objects["#{key}-sources-tag#{i}"]
    end
  end
  include_tags = instance_tags_include.map { |t| t.strip }.reject { |t| t.blank? }
  exclude_tags = instance_tags_exclude.map { |t| t.strip }.reject { |t| t.blank? }
  require_tags = instance_tags_require.map { |t| t.strip }.reject { |t| t.blank? }
  
  if include_tags.empty?
    include_tags = substitute_placeholders(options[:include_tags] || '', pg).split(',').map { |t| t.strip }.reject { |t| t.blank? }
    include_tags.each do |t|
      i = @page_objects["#{key}-sources-tag-count"]
      @page_objects["#{key}-sources-tag#{i}"] = t
      @page_objects["#{key}-sources-tag#{i}-behavior"] = 'include'
      @page_objects["#{key}-sources-tag-count"] += 1
    end
  end
  if exclude_tags.empty?
    exclude_tags = substitute_placeholders(options[:exclude_tags] || '', pg).split(',').map { |t| t.strip }.reject { |t| t.blank? }
    exclude_tags.each do |t|
      i = @page_objects["#{key}-sources-tag-count"]
      @page_objects["#{key}-sources-tag#{i}"] = t
      @page_objects["#{key}-sources-tag#{i}-behavior"] = 'exclude'
      @page_objects["#{key}-sources-tag-count"] += 1
    end
  end
  if require_tags.empty?
    require_tags = substitute_placeholders(options[:require_tags] || '', pg).split(',').map { |t| t.strip }.reject { |t| t.blank? }
    require_tags.each do |t|
      i = @page_objects["#{key}-sources-tag-count"]
      @page_objects["#{key}-sources-tag#{i}"] = t
      @page_objects["#{key}-sources-tag#{i}-behavior"] = 'require'
      @page_objects["#{key}-sources-tag-count"] += 1
    end
  end
  
  # pull all folder content
  folders = []
  for i in 0...@page_objects["#{key}-sources-folder-count"].to_i
    folders << OpenStruct.new(src: @page_objects["#{key}-sources-folder#{i}"].strip,
                              expand_folders: @page_objects["#{key}-sources-folder#{i}-expand-folders"])
  end
  folders = folders.reject { |f| f.src.blank? }
  
  if folders.empty?
    folders = substitute_placeholders(options[:folders] || '', pg).split(',').map do |f|
      bits = f.strip.split(':')
      
      obj = OpenStruct.new
      obj.src = bits[0]
      obj.expand_folders = 'true'
      
      while bit = bits.shift
        case bit
        when 'expand-folders'
          ;
        when 'no-expand-folders'
          obj.expand_folders = 'false'
        end
      end
      
      obj
    end
    folders += substitute_placeholders(options[:pages] || '', pg).split(',').map do |f|
      bits = f.strip.split(':')
      
      obj = OpenStruct.new
      obj.src = bits[0]
      obj.expand_folders = 'false'
      
      obj
    end
    folders = folders.reject { |f| f.src.blank? }
    
    @page_objects["#{key}-sources-folder-count"] = folders.size
    folders.each_with_index do |f, i|
      @page_objects["#{key}-sources-folder#{i}"] = f.src
      @page_objects["#{key}-sources-folder#{i}-expand-folders"] = f.expand_folders
    end
  end
  
  # exclude expired items if specified
  if @page_objects["#{key}-include-expired"]
    if @page_objects["#{key}-include-expired"] == 'false'
      conditions << '(cms_pages.expires = ? OR (cms_pages.expires = ? AND cms_pages.expiration_date >= ?))'
      cond_vars << false
      cond_vars << true
      cond_vars << Time.now
    end
  end
  
  folders.each do |f|
    logger.debug "Expanding folder #{f.src} (expand_folders: #{f.expand_folders})"
    begin
      if f.expand_folders && f.expand_folders == 'true'  # expand folders (i.e. specified path is prefix)
        if f.src == '/'
          pages.concat CmsPage.includes(:tags).where([ conditions.join(' and ') ].concat(cond_vars))
        else
          f.src = f.src.slice(1...f.src.length) if f.src.slice(0,1) == '/'
          fconditions = conditions.dup
          fconditions << 'path like ?'
          fcond_vars = cond_vars.dup
          fcond_vars << f.src+'/%'
          pages.concat CmsPage.includes(:tags).where([ fconditions.join(' and ') ].concat(fcond_vars))
        end
      else
        f.src = f.src.slice(1...f.src.length) if f.src.slice(0,1) == '/'
        parent_page = CmsPage.find_by_path(f.src)
        if parent_page.children.size > 0
          logger.debug " > Adding children of #{f.src}"
          pages.concat parent_page.children.includes(:tags).where([ conditions.join(' and ') ].concat(cond_vars)).to_a
        else
          logger.debug " > Adding single page #{f.src}"
          single_pages << parent_page  # user specified a single page, not a folder
        end
      end
    rescue StandardError => e
      logger.debug e
    end
  end
  
  # pull all include tag content
  include_tags.each do |tag|
    pages.concat CmsPageTag.where(:name => tag).includes(:page).references(:page).where([ conditions.join(' and ') ].concat(cond_vars)).map { |cpt| cpt.page }
  end
  
  # dump anything that has an excluded tag
  exclude_tags.each do |tag|
    pages.reject! { |page| page.tags.reject { |t| t.name != tag } != [] }
  end
  
  # dump anything that does not have a required tag
  require_tags.each do |tag|
    pages.reject! { |page| page.tags.reject { |t| t.name != tag } == [] }
  end
  
  # set some reasonable defaults in case the sort keys are nil
  pages.each { |pg| pg. ||= Time.now; pg.position ||= 0; pg.title ||= '' }
  pri_sort_key = first_non_empty(@page_objects["#{key}-sort-first-field"], options[:primary_sort_key], 'article_date')
  pri_sort_dir = first_non_empty(@page_objects["#{key}-sort-first-direction"], options[:primary_sort_direction], 'asc')
  sec_sort_key = first_non_empty(@page_objects["#{key}-sort-second-field"], options[:secondary_sort_key], 'position')
  sec_sort_dir = first_non_empty(@page_objects["#{key}-sort-second-direction"], options[:secondary_sort_direction], 'asc')
  @page_objects["#{key}-sort-first-field"] ||= pri_sort_key
  @page_objects["#{key}-sort-first-direction"] ||= pri_sort_dir
  @page_objects["#{key}-sort-second-field"] ||= sec_sort_key
  @page_objects["#{key}-sort-second-direction"] ||= sec_sort_dir
  
  keys_with_dir = [ [ pri_sort_key, pri_sort_dir ], [ sec_sort_key, sec_sort_dir ] ]
  pages.sort! do |a,b|
    index = 0
    result = 0
    while result == 0 && index < keys_with_dir.size
      sort_key = keys_with_dir[index][0]
      aval = a.send(sort_key)
      bval = b.send(sort_key)
      
      if !aval
        result = 1
      elsif !bval
        result = -1
      else
        result = aval <=> bval
      end
      
      result *= -1 if keys_with_dir[index][1] && keys_with_dir[index][1].downcase == 'desc'
      index += 1
    end
    
    result
  end
  
  offset = first_non_empty(@page_objects["#{key}-item-offset"], options[:item_offset], 0).to_i
  @page_objects["#{key}-item-offset"] = offset
  
  # exclude current page if box is checked (even for single_pages)
  if pg && (options[:exclude_current] === true || @page_objects["#{key}-exclude-current"] == 'true')
    pages.reject! { |page| page == pg }
    single_pages.reject! { |page| page == pg }
  end
  
  logger.debug "Page List Offset: #{offset} / #{pages.size} #{pages.map(&:id)}"
  pages = pages[offset, pages.size] || []
  
  # since the user selected these pages individually, they expect them to be included (and prioritized!), no matter what
  # (but make sure they are unique)
  pages = (single_pages + pages).uniq unless single_pages.empty?
  
  # randomize if requested
  randomize = first_non_empty(@page_objects["#{key}-use-randomization"], options[:use_randomization], 'false').to_s == 'true'
  random_pool_size = first_non_empty(@page_objects["#{key}-random-pool-size"], options[:random_pool_size], '').to_i
  @page_objects["#{key}-use-randomization"] = randomize
  @page_objects["#{key}-random-pool-size"] = random_pool_size
  
  if randomize
    if random_pool_size > 0
      pages = pages.first(random_pool_size)
    end
    
    n = pages.length
    for i in 0...n
      r = rand(n-1).floor
      pages[r], pages[i] = pages[i], pages[r]
    end
  end
  
  # make options specified in templates/snippets accessible to page list segments and rss feeds
  @page_objects["#{key}-max-item-count"] = first_non_empty(@page_objects["#{key}-max-item-count"], options[:item_count], pages.size).to_i
  @page_objects["#{key}-template"] = options[:template] if @page_objects["#{key}-template"].blank?
  @page_objects["#{key}-use-pagination"] = options[:use_pagination] unless options[:use_pagination].blank?
  
  # also make return value accessible to page list segments and rss feeds (so we don't have to do this all again)
  @page_list_pages ||= {}
  @page_list_pages[key] = pages
  
  pages
end

#product_browser(object, method, options = {}) ⇒ Object

:nodoc:



944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
# File 'app/helpers/cms_application_helper.rb', line 944

def product_browser(object, method, options = {}) # :nodoc:
  # allowed options, with defaults:
  #  - :can_select_department => false
  #  - :can_select category => false
  #  - :allow_multiple => false    # not implemented
  #  - :offset_x => 0, :offset_y => 0
  #
  # Note that allowing dept and category will cause this helper to create multiple
  # input fields, called object_method_department_id and object_method_category_id.
  # It is your job to figure out which one is not blank and use that return value.
  # Similarly, with allow multiple, you will need to parse the comma-separated list
  # of ids yourself.
  
  object = object.to_s
  method = method.to_s
  
  object_name = self.instance_variable_get('@' + object).send(method + '_object_name')
  object_name = 'Select' if (object_name || '') == ''
  
  ret = <<EOF
<a href="#" onclick="if (cbBrowserVisible) { cbHideBrowser(); } else { cbShowBrowser('#{object}', '#{method}', #{options[:offset_x] || 0}, #{options[:offset_y] || 0}); #{remote_function(:update => 'columnBrowserLevel0', :url => { :controller => '/management/bcom/products', :action => 'list_departments', :mode => 'select' })}; } return false;"><span id="#{object}_#{method}_link">#{object_name}</span></a>
<div id="#{object}_#{method}_container" style="display: none"></div>
<div style="display: none">
  #{text_field object, method + '_object_name'}
  #{text_field object, method + '_department_id'}
  #{text_field object, method + '_category_id'}
  #{text_field object, method + '_product_id'}
  #{text_field object, method + '_product_option_id'}
  #{text_field object, method + '_object_name_temp'}
  #{text_field object, method + '_department_id_temp'}
  #{text_field object, method + '_category_id_temp'}
  #{text_field object, method + '_product_id_temp'}
  #{text_field object, method + '_product_option_id_temp'}
</div>
EOF
  return ret
end

#short_months_hashObject

Returns a hash containing the 3-character abbreviations of the months of the year. Intended for use with the select form helper.



1049
1050
1051
1052
1053
# File 'app/helpers/cms_application_helper.rb', line 1049

def short_months_hash
  { 'Jan' => '1', 'Feb' => '2', 'Mar' => '3', 'Apr' => '4', 'May' => '5',
    'Jun' => '6', 'Jul' => '7', 'Aug' => '8', 'Sep' => '9', 'Oct' => '10',
    'Nov' => '11', 'Dec' => '12' }.sort{ |a, b| a.last.to_i <=> b.last.to_i }
end

#substitute_placeholder(html, page, key, value) ⇒ Object



466
467
468
469
470
471
472
473
474
475
476
477
478
479
# File 'app/helpers/cms_application_helper.rb', line 466

def substitute_placeholder(html, page, key, value)
  val = value
  
  html.gsub(/<#\s*#{key}(\..*?)*\s*#>/) do |match|
    $1.to_s.scan(/\.([\w]+)(\(.*?\))?/).each do |func, args|
      case func
      when 'gsub', 'downcase', 'upcase'
        val = eval(%["#{val}".#{func}#{args}])
      end
    end
    
    val
  end
end

#substitute_placeholders(html, page, extra_attributes = {}) ⇒ Object



481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
# File 'app/helpers/cms_application_helper.rb', line 481

def substitute_placeholders(html, page, extra_attributes = {})
  return html unless page
  
  temp = html.dup
  
  # mangle anything inside of an insert_object so that it won't be caught (yet)
  temp.gsub!(/((?:insert_object|text_editor|texteditor|page_list|pagelist|snippet)\()((?:\(.*?\)|[^()]*?)*)(\))/) do |match|
    one, two, three = $1, $2, $3
    one + two.gsub(/<#/, '<!#') + three
  end
  
  # first, extras passed in args
  extra_attributes.each { |k,v| temp = substitute_placeholder(temp, page, k, v) }
  
  # next, page object attributes and template options (from page properties)
  page.objects.where(obj_type: 'attribute').each { |obj| temp = substitute_placeholder(temp, page, obj.name, obj.content) }
  page.objects.where(obj_type: 'option').each { |obj| temp = substitute_placeholder(temp, page, "option_#{obj.name.gsub(/[^\w\d]/, '_')}", obj.content) }
  
  # path is kind of a special case, we like to see it with a leading /
  temp = substitute_placeholder(temp, page, 'path', "/#{page.path}")
  
  # substitute tags in a helpful way
  temp = substitute_placeholder(temp, page, 'tags', page.tags.map { |t| t.name }.join(', '))
  temp = substitute_placeholder(temp, page, 'tags_as_css_classes', page.tags_as_css_classes)
  
  # use full date/time format for created_on and updated_on
  temp = substitute_placeholder(temp, page, 'created_on', "#{page.created_on.strftime('%a')} #{date_to_str(page.created_on)} #{time_to_str(page.created_on)}") if page.created_on
  temp = substitute_placeholder(temp, page, 'updated_on', "#{page.updated_on.strftime('%a')} #{date_to_str(page.updated_on)} #{time_to_str(page.updated_on)}") if page.updated_on
  
  # handle any custom substitutions
  temp = substitute_placeholders_custom(temp, page)
  
  # finally, toss in the rest of the generic class attributes
  (page.attributes.map { |c| c.first } +
  [ 'article_date_month', 'article_date_mon', 'article_date_day', 'article_date_year', 'article_date_yr' ]).each do |attr|
    begin
      val = page.send(attr.downcase.underscore)
      case val.class.to_s
      when 'ActiveSupport::TimeWithZone'
        val = val.utc
        val = val.strftime("(%a) ") + val.strftime("%B ") + val.day.to_s + val.strftime(", %Y")
      when 'Time'
        val = val.strftime("(%a) ") + val.strftime("%B ") + val.day.to_s + val.strftime(", %Y")
      when 'NilClass'
        val = ''
      else
        # logger.error "#{attr} (#{val.class}): #{val}"
      end
    rescue
      # val = '<!-- attribute not found -->'
      val = ''
    end
    temp = substitute_placeholder(temp, page, attr, val)
  end
  
  # unknown attributes will be simply deleted (unless we enable some kind of substitution debugging in the future)
  # if SomeKindOfDebuggingEnabled
  #   temp.gsub!(/<#\s*(.*?)\s*#>/, "<!-- attribute not found -->")
  # else
  temp.gsub!(/<#\s*(.*?)\s*#>/, '')
  # end
  
  # unmangle mangled stuff
  temp.gsub!(/((?:insert_object|text_editor|texteditor|page_list|pagelist|snippet)\()((?:\(.*?\)|[^()]*?)*)(\))/) do |match|
    one, two, three = $1, $2, $3
    one + two.gsub(/<!#/, '<#') + three
  end
  
  temp.html_safe
end

#substitute_placeholders_custom(temp, page) ⇒ Object

override this method to do your own custom subtitutions



553
554
555
556
557
558
559
560
561
562
# File 'app/helpers/cms_application_helper.rb', line 553

def substitute_placeholders_custom(temp, page)
  # an example:
  # begin
  #   temp.gsub!(/<#\s*upcoming_event_date\s*#>/, page.article_date.strftime("<span class=\"month\">%b</span><span class=\"day\">%d</span>"))
  # rescue
  # end
  
  # remember to return your modified copy of temp
  temp
end

#template_option(name, type = :string) ⇒ Object



565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
# File 'app/helpers/cms_application_helper.rb', line 565

def template_option(name, type = :string)
  return nil unless @pg
  
  @template_options ||= OpenStruct.new
  @template_options[name] = type
  
  key = name.gsub(/[^\w\d]/, '_')
  obj = @pg.objects.where(:name => "#{type}-#{key}", :obj_type => 'option').first
  return nil unless obj
  
  case type
  when :checkbox
    obj.content == "1"
  else
    obj.content
  end
end

#time_to_str(t, convert = true) ⇒ Object

Convert times to a standard format (e.g. 1:35pm)



176
177
178
179
180
181
182
183
# File 'app/helpers/cms_application_helper.rb', line 176

def time_to_str(t, convert = true)
  return '' if t == nil
  if convert
    gm_to_local(t).strftime("%I").to_i.to_s + gm_to_local(t).strftime(":%M%p").downcase
  else
    t.strftime("%I").to_i.to_s + t.strftime(":%M%p").downcase
  end
end

#ts_to_str(ts) ⇒ Object

Convert a time object into a formatted date/time string



163
164
165
166
167
# File 'app/helpers/cms_application_helper.rb', line 163

def ts_to_str(ts)
  return '' if ts == nil
  gm_to_local(ts).strftime('%a %b %d, %Y') + ' at ' +
    gm_to_local(ts).strftime('%I:%M%p').downcase + ' ' + (session[:time_zone_abbr] || '')
end

#ts_to_time_str(ts) ⇒ Object

Convert a time object into a formatted time string (no date)



170
171
172
173
# File 'app/helpers/cms_application_helper.rb', line 170

def ts_to_time_str(ts)
  return '' if ts == nil
  gm_to_local(ts).strftime('%I:%M:%S%p').downcase
end

#url_for_currentObject

COMPAT - url_for_current



45
46
47
48
# File 'app/helpers/cms_application_helper.rb', line 45

def url_for_current
  # logger.debug("DEPRECATION WARNING (Imagine CMS) WARNING: url_for_current called")
  request.fullpath
end

#us_states_hash(include_territories = false) ⇒ Object

Returns an array of arrays (no, it is not named particularly well) containing the 50 US states and their abbreviations. Pass true as first arg to enable territories, etc. Intended for use with the select form helper.



996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
# File 'app/helpers/cms_application_helper.rb', line 996

def us_states_hash(include_territories = false)
  states_plus_dc = {
    "Alabama" => 'AL', "Alaska" => 'AK', "Arizona" => 'AZ', "Arkansas" => 'AR',
    "California" => 'CA', "Colorado" => 'CO', "Connecticut" => 'CT',
    "Delaware" => 'DE', "District Of Columbia" => 'DC',
    "Florida" => 'FL',
    "Georgia" => 'GA',
    "Hawaii" => 'HI',
    "Idaho" => 'ID', "Illinois" => 'IL', "Indiana" => 'IN', "Iowa" => 'IA',
    "Kansas" => 'KS', "Kentucky" => 'KY',
    "Louisiana" => 'LA',
    "Maine" => 'ME', "Maryland" => 'MD', "Massachusetts" => 'MA', "Michigan" => 'MI',
    "Minnesota" => 'MN', "Mississippi" => 'MS', "Missouri" => 'MO', "Montana" => 'MT',
    "Nebraska" => 'NE', "Nevada" => 'NV', "New Hampshire" => 'NH', "New Jersey" => 'NJ',
    "New Mexico" => 'NM', "New York" => 'NY', "North Carolina" => 'NC', "North Dakota" => 'ND',
    "Ohio" => 'OH', "Oklahoma" => 'OK', "Oregon" => 'OR',
    "Pennsylvania" => 'PA',  
    "Rhode Island" => 'RI',
    "South Carolina" => 'SC', "South Dakota" => 'SD',
    "Tennessee" => 'TN', "Texas" => 'TX',
    "Utah" => 'UT',
    "Vermont" => 'VT', "Virginia"=>'VA',
    "Washington" => 'WA', "West Virginia" => 'WV', "Wisconsin" => 'WI', "Wyoming" => 'WY'
  }
  
  territories_etc = {
    "Armed Forces Americas" => 'AA',
    "Armed Forces Europe, Middle East, Africa and Canada" => 'AE',
    "Armed Forces Pacific" => 'AP',
    "American Samoa" => 'AS',
    "Federated States of Micronesia" => 'FM',
    "Guam" => 'GU',
    "Marshall Islands" => 'MH',
    "Northern Mariana Islands" => 'MP',
    "Palau" => 'PW',
    "Puerto Rico" => 'PR',
    "Virgin Islands" => 'VI'
  }
  
  (include_territories ? states_plus_dc.merge(territories_etc) : states_plus_dc).to_a.sort { |a,b| a.last <=> b.last }
end

#valid_email_address?(addr, perform_mx_lookup = false) ⇒ Boolean

Determines whether the input string is a valid email address per RFC specification

Returns:

  • (Boolean)


19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'app/helpers/cms_application_helper.rb', line 19

def valid_email_address?(addr, perform_mx_lookup = false)
  valid = true
  
  # simplified regex for speed... the original can basically lock up the system on longish addresses
  # valid = valid && addr.to_s =~ /\A([\w\d]+(?:[\w\d\!\#\$\%\&\*\+\-\/\=\?\^\`\{\|\}\~\.]*[\w\d]+)*)@((?:[\w\d]+(?:[-]*[\w\d]+)*\.)+[\w]{2,})\z/
  valid = valid && addr.to_s =~ /\A([\w\d\!\#\$\%\&\*\+\-\/\=\?\^\`\{\|\}\~\.]+)@((?:[\w\d]+(?:[-]*[\w\d]+)*\.)+[\w]{2,})\z/
  user, host = $1, $2
  
  if perform_mx_lookup
    begin
      # require 'net/dns'
      res = Net::DNS::Resolver.new
      valid = valid && res.mx(host).size > 0
    rescue StandardError => e
      logger.error(e)
    end
  end
  
  valid
end