renderer.rb 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. class NotificationFactory::Renderer
  2. =begin
  3. examples how to use
  4. message_subject = NotificationFactory::Renderer.new(
  5. {
  6. ticket: Ticket.first,
  7. },
  8. 'de-de',
  9. 'some template <b>#{ticket.title}</b> {config.fqdn}',
  10. false
  11. ).render
  12. message_body = NotificationFactory::Renderer.new(
  13. {
  14. ticket: Ticket.first,
  15. },
  16. 'de-de',
  17. 'some template <b>#{ticket.title}</b> #{config.fqdn}',
  18. ).render
  19. =end
  20. def initialize(objects, locale, template, escape = true)
  21. @objects = objects
  22. @locale = locale || Setting.get('locale_default') || 'en-us'
  23. @template = NotificationFactory::Template.new(template, escape)
  24. @escape = escape
  25. end
  26. def render
  27. ERB.new(@template.to_s).result(binding)
  28. end
  29. # d - data of object
  30. # d('user.firstname', htmlEscape)
  31. def d(key, escape = nil)
  32. # do validaton, ignore some methodes
  33. return "\#{#{key} / not allowed}" if !data_key_valid?(key)
  34. # aliases
  35. map = {
  36. 'article.body' => 'article.body_as_text_with_quote.text2html',
  37. }
  38. if map[key]
  39. key = map[key]
  40. end
  41. # escape in html mode
  42. if escape
  43. no_escape = {
  44. 'article.body_as_html' => true,
  45. 'article.body_as_text_with_quote.text2html' => true,
  46. }
  47. if no_escape[key]
  48. escape = false
  49. end
  50. end
  51. value = nil
  52. object_methods = key.split('.')
  53. object_name = object_methods.shift
  54. # if no object is given, just return
  55. return '#{no such object}' if object_name.blank? # rubocop:disable Lint/InterpolationCheck
  56. object_refs = @objects[object_name] || @objects[object_name.to_sym]
  57. # if object is not in avalable objects, just return
  58. return "\#{#{object_name} / no such object}" if !object_refs
  59. # if content of method is a complex datatype, just return
  60. if object_methods.blank? && object_refs.class != String && object_refs.class != Float && object_refs.class != Integer
  61. return "\#{#{key} / no such method}"
  62. end
  63. previous_object_refs = ''
  64. object_methods_s = ''
  65. object_methods.each do |method_raw|
  66. method = method_raw.strip
  67. if method == 'value'
  68. temp = object_refs
  69. object_refs = display_value(previous_object_refs, method, object_methods_s, object_refs)
  70. previous_object_refs = temp
  71. end
  72. if object_methods_s != ''
  73. object_methods_s += '.'
  74. end
  75. object_methods_s += method
  76. next if method == 'value'
  77. if object_methods_s == ''
  78. value = "\#{#{object_name}.#{object_methods_s} / no such method}"
  79. break
  80. end
  81. arguments = nil
  82. if /\A(?<method_id>[^\(]+)\((?<parameter>[^\)]+)\)\z/ =~ method
  83. if parameter != parameter.to_i.to_s
  84. value = "\#{#{object_name}.#{object_methods_s} / invalid parameter: #{parameter}}"
  85. break
  86. end
  87. begin
  88. arguments = Array(parameter.to_i)
  89. method = method_id
  90. rescue
  91. value = "\#{#{object_name}.#{object_methods_s} / #{e.message}}"
  92. break
  93. end
  94. end
  95. # if method exists
  96. if !object_refs.respond_to?(method.to_sym)
  97. value = "\#{#{object_name}.#{object_methods_s} / no such method}"
  98. break
  99. end
  100. begin
  101. previous_object_refs = object_refs
  102. object_refs = object_refs.send(method.to_sym, *arguments)
  103. rescue => e
  104. value = "\#{#{object_name}.#{object_methods_s} / #{e.message}}"
  105. break
  106. end
  107. end
  108. placeholder = if !value
  109. object_refs
  110. else
  111. value
  112. end
  113. escaping(placeholder, escape)
  114. end
  115. # c - config
  116. # c('fqdn', htmlEscape)
  117. def c(key, escape = nil)
  118. config = Setting.get(key)
  119. escaping(config, escape)
  120. end
  121. # t - translation
  122. # t('yes', htmlEscape)
  123. def t(key, escape = nil)
  124. translation = Translation.translate(@locale, key)
  125. escaping(translation, escape)
  126. end
  127. # h - htmlEscape
  128. # h('fqdn', htmlEscape)
  129. def h(key)
  130. return key if !key
  131. CGI.escapeHTML(key.to_s)
  132. end
  133. private
  134. def escaping(key, escape)
  135. return key if escape == false
  136. return key if escape.nil? && !@escape
  137. h key
  138. end
  139. def data_key_valid?(key)
  140. return false if key =~ /`|\.(|\s*)(save|destroy|delete|remove|drop|update|create|new|all|where|find|raise|dump|rollback|freeze)/i && key !~ /(update|create)d_(at|by)/i
  141. true
  142. end
  143. def display_value(object, method_name, previous_method_names, key)
  144. return key if method_name != 'value' ||
  145. !key.instance_of?(String)
  146. attributes = ObjectManager::Attribute
  147. .where(object_lookup_id: ObjectLookup.by_name(object.class.to_s))
  148. .where(name: previous_method_names.split('.').last)
  149. return key if attributes.count.zero? || attributes.first.data_type != 'select'
  150. attributes.first.data_option['options'][key] || key
  151. end
  152. end