# =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