# =XMPP4R - XMPP Library for Ruby # License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option. # Website::http://home.gna.org/xmpp4r/ require 'xmpp4r/x' require 'xmpp4r/jid' module Jabber module Dataforms ## # Data Forms (JEP-0004) implementation class XData < X name_xmlns 'x', 'jabber:x:data' def initialize(type=nil) super() self.type = type end ## # Search a field by it's var-name # var:: [String] # result:: [XDataField] or [nil] def field(var) each_element { |xe| return xe if xe.kind_of?(XDataField) and xe.var == var } nil end def fields(including_hidden=false) fields = [] each_element do |xe| if xe.kind_of?(XDataField) and (including_hidden or (xe.type != :hidden and xe.type != :fixed)) fields << xe end end fields end ## # The field names and their values in a hash # return:: [Array] of hashes containing fields names, their types and their values. def fields_and_values f_and_v = [] REXML::XPath.match(fields, '//field').each do |f| unless f.attributes['type'] =~ /multi/ f_and_v << {:var => f.attributes['var'], :type => f.type, :value => f.elements['value'].text} else values = REXML::XPath.match(f, 'value').map {|v| v.text} f_and_v << {:var => f.attributes['var'], :type => f.type, :value => values} end end f_and_v end ## # Populate a dataform using a hash of fields and values. Values can be either strings in the # case of :text_single types or arrays in the case of :text_multi types. # fields_and_values:: [Hash] def fill_form(fields_and_values) count = 0 fields_and_values.each do |item| self << ::Jabber::Dataforms::XDataField.new(item[:var].to_sym, item[:type].to_sym) self.children[count].values = (item[:value]) count += 1 end end ## # Type of this Data Form # result:: * :cancel # * :form # * :result # * :submit # * nil def type case attributes['type'] when 'cancel' then :cancel when 'form' then :form when 'result' then :result when 'submit' then :submit else nil end end ## # Set the type (see type) def type=(t) case t when :cancel then attributes['type'] = 'cancel' when :form then attributes['type'] = 'form' when :result then attributes['type'] = 'result' when :submit then attributes['type'] = 'submit' else attributes['type'] = nil end end ## # Get the Data Form title # return:: [XDataTitle] or nil def title first_element('title') end ## # Set the Data Form title # title:: [String] def title=(title) delete_elements('title') add_element(XDataTitle.new(title)) end ## # Get the Data Form instructions # return:: [Array] of [XDataInstructions] or nil def instructions fields = [] each_element('instructions') do |xe| fields << xe end fields end ## # Add Data Form instructions # i:: [String] def instructions=(i) add(XDataInstructions.new(i)) end end ## # Child of XData, contains the title of this Data Form class XDataTitle < XMPPElement name_xmlns 'title', 'jabber:x:data' def initialize(title=nil) super() add_text(title) end def to_s text.to_s end def title text end end ## # Child of XData, contains the instructions of this Data Form class XDataInstructions < XMPPElement name_xmlns 'instructions', 'jabber:x:data' def initialize(instructions=nil) super() add_text(instructions) end def to_s text.to_s end def instructions text end end ## # Child of XData, contains configurable/configured options of this Data Form class XDataField < XMPPElement name_xmlns 'field', 'jabber:x:data' def initialize(var=nil, type=nil) super() self.var = var self.type = type end def label attributes['label'] end def label=(s) attributes['label'] = s end def var attributes['var'] end def var=(s) attributes['var'] = s end ## # Type of this field # result:: # * :boolean # * :fixed # * :hidden # * :jid_multi # * :jid_single # * :list_multi # * :list_single # * :text_multi # * :text_private # * :text_single # * nil def type case attributes['type'] when 'boolean' then :boolean when 'fixed' then :fixed when 'hidden' then :hidden when 'jid-multi' then :jid_multi when 'jid-single' then :jid_single when 'list-multi' then :list_multi when 'list-single' then :list_single when 'text-multi' then :text_multi when 'text-private' then :text_private when 'text-single' then :text_single else nil end end ## # Set the type of this field (see type) def type=(t) case t when :boolean then attributes['type'] = 'boolean' when :fixed then attributes['type'] = 'fixed' when :hidden then attributes['type'] = 'hidden' when :jid_multi then attributes['type'] = 'jid-multi' when :jid_single then attributes['type'] = 'jid-single' when :list_multi then attributes['type'] = 'list-multi' when :list_single then attributes['type'] = 'list-single' when :text_multi then attributes['type'] = 'text-multi' when :text_private then attributes['type'] = 'text-private' when :text_single then attributes['type'] = 'text-single' else attributes['type'] = nil end end ## # Is this field required (has the child)? def required? res = false each_element('required') { res = true } res end ## # Set if this field is required # r:: [true] or [false] def required=(r) delete_elements('required') if r add REXML::Element.new('required') end end ## # Get the values (in a Data Form with type='submit') def values res = [] each_element('value') { |e| res << e.text } res end ## # Set the values def values=(ary) delete_elements('value') ary.each { |v| add(REXML::Element.new('value')).text = v } end ## # Get the first value def value values.first end ## # Remove all and set one value def value=(val) self.values = [val] end ## # Get the options (in a Data Form with type='form') def options res = {} each_element('option') { |e| value = nil e.each_element('value') { |ve| value = ve.text } res[value] = e.attributes['label'] } res end ## # Set the options def options=(hsh) delete_elements('option') hsh.each { |value,label| o = add(REXML::Element.new('option')) o.attributes['label'] = label o.add(REXML::Element.new('value')).text = value } end end ## # The element, can contain XDataField elements class XDataReported < XMPPElement name_xmlns 'reported', 'jabber:x:data' end end end