class Tilia::VObject::Component::VCard
The VCard
component.
This component represents the BEGIN:VCARD and END:VCARD found in every vcard.
Constants
- DEFAULT_VERSION
VCards with version 2.1, 3.0 and 4.0 are found.
If the VCARD doesn't know its version, 2.1 is assumed.
Public Class Methods
sets instance variables
# File lib/tilia/v_object/component/v_card.rb, line 423 def initialize(*args) super @version = nil end
Public Instance Methods
Returns the default class for a property name.
@param [String] property_name
@return [String]
# File lib/tilia/v_object/component/v_card.rb, line 411 def class_name_for_property_name(property_name) class_name = super(property_name) # In vCard 4, BINARY no longer exists, and we need URI instead. if class_name == Property::Binary && document_type == VCARD40 return Property::Uri end class_name end
Converts the document to a different vcard version.
Use one of the VCARD constants for the target. This method will return a copy of the vcard in the new version.
At the moment the only supported conversion is from 3.0 to 4.0.
If input and output version are identical, a clone is returned.
@param [Fixnum] target
@return [VCard]
# File lib/tilia/v_object/component/v_card.rb, line 150 def convert(target) converter = VCardConverter.new converter.convert(self, target) end
Returns the current document type.
@return [Fixnum]
# File lib/tilia/v_object/component/v_card.rb, line 117 def document_type unless @version version = self['VERSION'].to_s case version when '2.1' @version = VCARD21 when '3.0' @version = VCARD30 when '4.0' @version = VCARD40 else # We don't want to cache the version if it's unknown, # because we might get a version property in a bit. return UNKNOWN end end @version end
This method returns an array, with the representation as it should be encoded in json. This is used to create jCard or jCal documents.
@return [Array]
# File lib/tilia/v_object/component/v_card.rb, line 351 def json_serialize # A vcard does not have sub-components, so we're overriding this # method to remove that array element. properties = [] children.each do |child| properties << child.json_serialize end [@name.downcase, properties] end
Returns a preferred field.
VCards can indicate wether a field such as ADR, TEL or EMAIL is preferred by specifying TYPE=PREF (vcard 2.1, 3) or PREF=x (vcard 4, x being a number between 1 and 100).
If neither of those parameters are specified, the first is returned, if a field with that name does not exist, null is returned.
@param [String] field_name
@return [Property, nil]
# File lib/tilia/v_object/component/v_card.rb, line 311 def preferred(property_name) preferred = nil last_pref = 101 select(property_name).each do |field| pref = 101 if field.key?('TYPE') && field['TYPE'].has('PREF') pref = 1 elsif field.key?('PREF') pref = field['PREF'].value.to_i end if pref < last_pref || preferred.nil? preferred = field last_pref = pref end end preferred end
(see Component#validate
)
# File lib/tilia/v_object/component/v_card.rb, line 161 def validate(options = 0) warnings = [] version_map = { VCARD21 => '2.1', VCARD30 => '3.0', VCARD40 => '4.0' } version = select('VERSION') if version.size == 1 version = self['VERSION'].to_s unless ['2.1', '3.0', '4.0'].include?(version) warnings << { 'level' => 3, 'message' => 'Only vcard version 4.0 (RFC6350), version 3.0 (RFC2426) or version 2.1 (icm-vcard-2.1) are supported.', 'node' => self } if options & REPAIR > 0 self['VERSION'] = version_map[DEFAULT_VERSION] end end if version == '2.1' && options & PROFILE_CARDDAV > 0 warnings << { 'level' => 3, 'message' => 'CardDAV servers are not allowed to accept vCard 2.1.', 'node' => self } end end uid = select('UID') if uid.size == 0 if options & PROFILE_CARDDAV > 0 # Required for CardDAV warning_level = 3 message = 'vCards on CardDAV servers MUST have a UID property.' else # Not required for regular vcards warning_level = 2 message = 'Adding a UID to a vCard property is recommended.' end if options & REPAIR > 0 self['UID'] = UuidUtil.uuid warning_level = 1 end warnings << { 'level' => warning_level, 'message' => message, 'node' => self } end fn = select('FN') if fn.size != 1 repaired = false if options & REPAIR > 0 && fn.size == 0 # We're going to try to see if we can use the contents of the # N property. if key?('N') value = self['N'].to_s.split(';') if value[1] self['FN'] = value[1] + ' ' + value[0] else self['FN'] = value[0] end repaired = true # Otherwise, the ORG property may work elsif key?('ORG') self['FN'] = self['ORG'].to_s repaired = true end end warnings << { 'level' => repaired ? 1 : 3, 'message' => 'The FN property must appear in the VCARD component exactly 1 time', 'node' => self } end w = super(options) w.concat warnings w end
(see Component#validation_rules
)
# File lib/tilia/v_object/component/v_card.rb, line 255 def validation_rules { 'ADR' => '*', 'ANNIVERSARY' => '?', 'BDAY' => '?', 'CALADRURI' => '*', 'CALURI' => '*', 'CATEGORIES' => '*', 'CLIENTPIDMAP' => '*', 'EMAIL' => '*', 'FBURL' => '*', 'IMPP' => '*', 'GENDER' => '?', 'GEO' => '*', 'KEY' => '*', 'KIND' => '?', 'LANG' => '*', 'LOGO' => '*', 'MEMBER' => '*', 'N' => '?', 'NICKNAME' => '*', 'NOTE' => '*', 'ORG' => '*', 'PHOTO' => '*', 'PRODID' => '?', 'RELATED' => '*', 'REV' => '?', 'ROLE' => '*', 'SOUND' => '*', 'SOURCE' => '*', 'TEL' => '*', 'TITLE' => '*', 'TZ' => '*', 'URL' => '*', 'VERSION' => '1', 'XML' => '*', # FN is commented out, because it's already handled by the # validate function, which may also try to repair it. # 'FN' => '+', 'UID' => '?' } end
This method serializes the data into XML. This is used to create xCard or xCal documents.
@param [Tilia::Xml::Writer] writer XML writer.
@return [void]
# File lib/tilia/v_object/component/v_card.rb, line 369 def xml_serialize(writer) properties_by_group = {} children.each do |property| group = property.group properties_by_group[group] = [] unless properties_by_group[group] properties_by_group[group] << property end writer.start_element(@name.downcase) properties_by_group.each do |group, properties| unless group.blank? writer.start_element('group') writer.write_attribute('name', group.downcase) end properties.each do |property| case property.name when 'VERSION' next when 'XML' value = property.parts fragment = Tilia::Xml::Element::XmlFragment.new(value[0]) writer.write(fragment) else property.xml_serialize(writer) end end writer.end_element unless group.blank? end writer.end_element end
Protected Instance Methods
This method should return a list of default property values.
@return [Hash]
# File lib/tilia/v_object/component/v_card.rb, line 337 def defaults { 'VERSION' => '4.0', 'PRODID' => "-//Tilia//Tilia VObject #{Version::VERSION}//EN", 'UID' => "tilia-vobject-#{UuidUtil.uuid}" } end