KayakoClient 0.0.1b

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. data/lib/kayako_client.rb +36 -0
  2. data/lib/kayako_client/base.rb +98 -0
  3. data/lib/kayako_client/department.rb +31 -0
  4. data/lib/kayako_client/http/http.rb +217 -0
  5. data/lib/kayako_client/http/http_backend.rb +31 -0
  6. data/lib/kayako_client/http/http_client.rb +87 -0
  7. data/lib/kayako_client/http/http_response.rb +61 -0
  8. data/lib/kayako_client/http/net_http.rb +109 -0
  9. data/lib/kayako_client/mixins/api.rb +299 -0
  10. data/lib/kayako_client/mixins/attachment.rb +69 -0
  11. data/lib/kayako_client/mixins/authentication.rb +34 -0
  12. data/lib/kayako_client/mixins/client.rb +308 -0
  13. data/lib/kayako_client/mixins/logger.rb +29 -0
  14. data/lib/kayako_client/mixins/object.rb +456 -0
  15. data/lib/kayako_client/mixins/post_client.rb +42 -0
  16. data/lib/kayako_client/mixins/staff_visibility_api.rb +9 -0
  17. data/lib/kayako_client/mixins/ticket_api.rb +55 -0
  18. data/lib/kayako_client/mixins/ticket_client.rb +135 -0
  19. data/lib/kayako_client/mixins/user_visibility_api.rb +9 -0
  20. data/lib/kayako_client/staff.rb +25 -0
  21. data/lib/kayako_client/staff_group.rb +9 -0
  22. data/lib/kayako_client/ticket.rb +241 -0
  23. data/lib/kayako_client/ticket_attachment.rb +42 -0
  24. data/lib/kayako_client/ticket_count.rb +135 -0
  25. data/lib/kayako_client/ticket_custom_field.rb +110 -0
  26. data/lib/kayako_client/ticket_note.rb +105 -0
  27. data/lib/kayako_client/ticket_post.rb +61 -0
  28. data/lib/kayako_client/ticket_priority.rb +24 -0
  29. data/lib/kayako_client/ticket_status.rb +31 -0
  30. data/lib/kayako_client/ticket_time_track.rb +27 -0
  31. data/lib/kayako_client/ticket_type.rb +26 -0
  32. data/lib/kayako_client/user.rb +61 -0
  33. data/lib/kayako_client/user_group.rb +12 -0
  34. data/lib/kayako_client/user_organization.rb +23 -0
  35. data/lib/kayako_client/xml/lib_xml.rb +86 -0
  36. data/lib/kayako_client/xml/rexml_document.rb +77 -0
  37. data/lib/kayako_client/xml/xml.rb +63 -0
  38. data/lib/kayako_client/xml/xml_backend.rb +42 -0
  39. metadata +105 -0
@@ -0,0 +1,24 @@
1
+ require 'kayako_client/mixins/user_visibility_api'
2
+
3
+ module KayakoClient
4
+ class TicketPriority < KayakoClient::Tickets
5
+ include KayakoClient::UserVisibilityAPI
6
+
7
+ supports :all, :get
8
+
9
+ PRIORITY_TYPES = [ :public, :private ].freeze
10
+
11
+ property :id, :integer
12
+ property :title, :string
13
+ property :display_order, :integer
14
+ property :fr_color_code, :string
15
+ property :bg_color_code, :string
16
+ property :display_icon, :string
17
+ property :type, :symbol, :in => PRIORITY_TYPES
18
+ property :user_visibility_custom, :boolean
19
+ property :user_group_ids, [ :integer ], :get => :usergroupid, :condition => { :user_visibility_custom => true }
20
+
21
+ associate :user_groups, :user_group_ids, UserGroup
22
+
23
+ end
24
+ end
@@ -0,0 +1,31 @@
1
+ require 'kayako_client/department'
2
+
3
+ module KayakoClient
4
+ class TicketStatus < KayakoClient::Tickets
5
+ include KayakoClient::StaffVisibilityAPI
6
+
7
+ supports :all, :get
8
+
9
+ STATUS_TYPES = [ :public, :private ].freeze
10
+
11
+ property :id, :integer
12
+ property :title, :string
13
+ property :display_order, :integer
14
+ property :department_id, :integer
15
+ property :display_icon, :string
16
+ property :type, :symbol, :in => STATUS_TYPES
17
+ property :display_in_main_list, :boolean
18
+ property :mark_as_resolved, :boolean
19
+ property :display_count, :integer
20
+ property :status_color, :string
21
+ property :status_bg_color, :string
22
+ property :reset_due_time, :boolean
23
+ property :trigger_survey, :boolean
24
+ property :staff_visibility_custom, :boolean
25
+ property :staff_group_ids, [ :integer ], :get => :staffgroupid, :condition => { :staff_visibility_custom => true }
26
+
27
+ associate :department, :department_id, Department
28
+ associate :staff_groups, :staff_group_ids, StaffGroup
29
+
30
+ end
31
+ end
@@ -0,0 +1,27 @@
1
+ require 'kayako_client/mixins/ticket_api'
2
+
3
+ module KayakoClient
4
+ class TicketTimeTrack < KayakoClient::Tickets
5
+ include KayakoClient::TicketAPI
6
+
7
+ supports :all, :get, :post, :delete
8
+
9
+ property :id, :integer, :readonly => true
10
+ property :ticket_id, :integer, :required => :post
11
+ property :time_worked, :integer, :required => :post, :set => :timespent
12
+ property :time_billable, :integer, :required => :post
13
+ property :bill_date, :date, :required => :post, :set => :billtimeline
14
+ property :work_date, :date, :required => :post, :set => :worktimeline
15
+ property :worker_staff_id, :integer
16
+ property :worker_staff_name, :string, :readonly => true
17
+ property :creator_staff_id, :integer, :required => :post, :set => :staffid
18
+ property :creator_staff_name, :string, :readonly => true
19
+ property :note_color, :integer, :range => 1..5
20
+ property :contents, :string, :required => :post
21
+
22
+ associate :ticket, :ticket_id, Ticket
23
+ associate :worker_staff, :worker_staff_id, Staff
24
+ associate :creator_staff, :creator_staff_id, Staff
25
+
26
+ end
27
+ end
@@ -0,0 +1,26 @@
1
+ require 'kayako_client/mixins/user_visibility_api'
2
+
3
+ require 'kayako_client/department'
4
+
5
+ module KayakoClient
6
+ class TicketType < KayakoClient::Tickets
7
+ include KayakoClient::UserVisibilityAPI
8
+
9
+ supports :all, :get
10
+
11
+ TYPE_TYPES = [ :public, :private ].freeze
12
+
13
+ property :id, :integer
14
+ property :title, :string
15
+ property :display_order, :integer
16
+ property :department_id, :integer
17
+ property :display_icon, :string
18
+ property :type, :symbol, :in => TYPE_TYPES
19
+ property :user_visibility_custom, :boolean
20
+ property :user_group_ids, [ :integer ], :get => :usergroupid, :condition => { :user_visibility_custom => true }
21
+
22
+ associate :department, :department_id, Department
23
+ associate :user_groups, :user_group_ids, UserGroup
24
+
25
+ end
26
+ end
@@ -0,0 +1,61 @@
1
+ require 'kayako_client/user_group'
2
+ require 'kayako_client/user_organization'
3
+
4
+ module KayakoClient
5
+ class User < KayakoClient::Base
6
+
7
+ USER_ROLES = [ :user, :manager ].freeze
8
+ USER_SALUTATIONS = [ 'Mr.', 'Ms.', 'Mrs.', 'Dr.' ].freeze
9
+
10
+ # NOTE: if :user_group_id is set the group should be of :registered type
11
+
12
+ property :id, :integer, :readonly => true
13
+ property :user_group_id, :integer, :required => :post
14
+ property :user_role, :symbol, :in => USER_ROLES
15
+ property :user_organization_id, :integer
16
+ property :salutation, :string, :in => USER_SALUTATIONS
17
+ property :user_expiry, :date
18
+ property :full_name, :string, :required => [ :put, :post ]
19
+ property :emails, [ :string ], :required => :post, :get => :email, :set => :email
20
+ property :designation, :string
21
+ property :phone, :string
22
+ property :date_line, :date, :readonly => true
23
+ property :last_visit, :date, :readonly => true
24
+ property :is_enabled, :boolean
25
+ property :time_zone, :string
26
+ property :enable_dst, :boolean
27
+ property :sla_plan_id, :integer
28
+ property :sla_plan_expiry, :date
29
+ property :password, :string, :new => true, :required => :post
30
+ property :send_welcome_email, :boolean, :new => true
31
+
32
+ associate :user_group, :user_group_id, UserGroup
33
+ associate :user_organization, :user_organization_id, UserOrganization
34
+
35
+ def self.all(marker = nil, limit = nil, options = {})
36
+ unless marker.nil?
37
+ unless marker.to_i > 0
38
+ logger.error "invalid :marker - #{marker}" if logger
39
+ raise ArgumentError, "invalid marker"
40
+ end
41
+ unless limit.nil? || limit.to_i > 0
42
+ logger.error "invalid :limit (:maxitems) - #{limit}" if logger
43
+ raise ArgumentError, "invalid limit"
44
+ end
45
+ else
46
+ if limit && limit.to_i > 0
47
+ logger.error "invalid :marker" if logger
48
+ raise ArgumentError, "missing marker"
49
+ end
50
+ end
51
+
52
+ e = path + '/Filter'
53
+ if marker
54
+ e << "/#{marker.to_i}"
55
+ e << "/#{limit.to_i}" if limit
56
+ end
57
+ super(options.merge(:e => e))
58
+ end
59
+
60
+ end
61
+ end
@@ -0,0 +1,12 @@
1
+ module KayakoClient
2
+ class UserGroup < KayakoClient::Base
3
+
4
+ USER_GROUP_TYPES = [ :guest, :registered ].freeze
5
+
6
+ property :id, :integer, :readonly => true
7
+ property :title, :string, :required => [ :put, :post ]
8
+ property :group_type, :symbol, :required => :post, :new => true
9
+ property :is_master, :boolean, :readonly => true
10
+
11
+ end
12
+ end
@@ -0,0 +1,23 @@
1
+ module KayakoClient
2
+ class UserOrganization < KayakoClient::Base
3
+
4
+ USER_ORGANIZATION_TYPES = [ :restricted, :shared ].freeze
5
+
6
+ property :id, :integer, :readonly => true
7
+ property :name, :string, :required => [ :put, :post ]
8
+ property :organization_type, :symbol, :required => :post, :in => USER_ORGANIZATION_TYPES
9
+ property :address, :string
10
+ property :city, :string
11
+ property :state, :string
12
+ property :postal_code, :integer
13
+ property :country, :string
14
+ property :phone, :string
15
+ property :fax, :string
16
+ property :website, :string
17
+ property :date_line, :date, :readonly => true
18
+ property :last_update, :date, :readonly => true
19
+ property :sla_plan_id, :integer
20
+ property :sla_plan_expiry, :date
21
+
22
+ end
23
+ end
@@ -0,0 +1,86 @@
1
+ require 'libxml'
2
+
3
+ module KayakoClient
4
+
5
+ class LibXML
6
+ include KayakoClient::Logger
7
+ include KayakoClient::XMLBackend
8
+
9
+ def initialize(document, options = {})
10
+ logger = options[:logger] if options[:logger]
11
+ if (document.start_with?('<?xml '))
12
+ @xml = ::LibXML::XML::Parser.string(document).parse
13
+ else
14
+ start = document.index('<?xml version="1.0" encoding="UTF-8"?>')
15
+ if start && start > 0
16
+ @notice = document.slice(0..start-1).gsub(%r{</?[A-Z0-9]+(?: +[A-Z]+="[^">]*")?>}i, '')
17
+ @xml = ::LibXML::XML::Parser.string(document.slice(start..document.size)).parse
18
+ else
19
+ @error = document.gsub(%r{</?[A-Z0-9]+(?: +[A-Z]+="[^">]*")?>}i, '')
20
+ end
21
+ end
22
+ rescue ::LibXML::XML::Parser::ParseError => error
23
+ error.extend(::KayakoClient::XMLException)
24
+ raise
25
+ end
26
+
27
+ def count
28
+ if !error? && @xml.root
29
+ @xml.root.children.inject(0) do |count, node|
30
+ count += 1 if node.element?
31
+ count
32
+ end
33
+ else
34
+ 0
35
+ end
36
+ end
37
+
38
+ def each(&block)
39
+ @xml.root.each_element(&block) if !error? && @xml.root
40
+ end
41
+
42
+ def to_hash(root = nil)
43
+ hash = {}
44
+ if !error? && @xml.root
45
+ root ||= @xml.root
46
+ root.each_attr do |attribute|
47
+ hash[attribute.name.to_sym] = attribute.value
48
+ end
49
+ root.each_element do |property|
50
+ name = property.name.to_sym
51
+ elements = property.children.inject(0) do |count, node|
52
+ count += 1 if node.element?
53
+ count
54
+ end
55
+ if elements > 0 || property.attributes?
56
+ value = to_hash(property)
57
+ if property.children.size == 1 && (property.first.text? || property.first.cdata?)
58
+ text = property.content.strip
59
+ unless text.empty?
60
+ value ||= {}
61
+ value[:contents] = text
62
+ end
63
+ end
64
+ elsif property.children.size == 1 && (property.first.text? || property.first.cdata?)
65
+ value = property.content.strip
66
+ end
67
+ unless value.nil? || value.empty?
68
+ if hash.include?(name)
69
+ hash[name] = [ hash[name] ] unless hash[name].is_a?(Array)
70
+ hash[name].push(value)
71
+ else
72
+ hash[name] = value
73
+ end
74
+ end
75
+ end
76
+ if root.children.size == 1 && (root.first.text? || root.first.cdata?)
77
+ text = root.content.strip
78
+ hash[:contents] = text unless text.empty?
79
+ end
80
+ end
81
+ hash.empty? ? nil : hash
82
+ end
83
+
84
+ end
85
+
86
+ end
@@ -0,0 +1,77 @@
1
+ require 'rexml/document'
2
+
3
+ module KayakoClient
4
+ class REXMLDocument
5
+ include KayakoClient::Logger
6
+ include KayakoClient::XMLBackend
7
+
8
+ def initialize(document, options = {})
9
+ logger = options[:logger] if options[:logger]
10
+ if (document.start_with?('<?xml '))
11
+ @xml = REXML::Document.new(document)
12
+ else
13
+ start = document.index('<?xml version="1.0" encoding="UTF-8"?>')
14
+ if start && start > 0
15
+ @notice = document.slice(0..start-1).gsub(%r{</?[A-Z0-9]+(?: +[A-Z]+="[^">]*")?>}i, '')
16
+ @xml = REXML::Document.new(document.slice(start..document.size))
17
+ else
18
+ @error = document.gsub(%r{</?[A-Z0-9]+(?: +[A-Z]+="[^">]*")?>}i, '')
19
+ end
20
+ end
21
+ rescue REXML::ParseException => error
22
+ error.extend(::KayakoClient::XMLException)
23
+ raise
24
+ end
25
+
26
+ def count
27
+ if !error? && @xml.root
28
+ @xml.root.elements.count
29
+ else
30
+ 0
31
+ end
32
+ end
33
+
34
+ def each(&block)
35
+ @xml.root.elements.each(&block) if !error? && @xml.root
36
+ end
37
+
38
+ def to_hash(root = nil)
39
+ hash = {}
40
+ if !error? && @xml.root
41
+ root ||= @xml.root
42
+ root.attributes.each do |attribute, value|
43
+ hash[attribute.to_sym] = value
44
+ end
45
+ root.elements.each do |property|
46
+ name = property.name.to_sym
47
+ if property.has_elements? || property.has_attributes?
48
+ value = to_hash(property)
49
+ if property.has_text?
50
+ text = property.text.strip
51
+ unless text.empty?
52
+ value ||= {}
53
+ value[:contents] = text
54
+ end
55
+ end
56
+ elsif property.has_text?
57
+ value = property.text.strip
58
+ end
59
+ unless value.nil? || value.empty?
60
+ if hash.include?(name)
61
+ hash[name] = [ hash[name] ] unless hash[name].is_a?(Array)
62
+ hash[name].push(value)
63
+ else
64
+ hash[name] = value
65
+ end
66
+ end
67
+ end
68
+ if root.has_text?
69
+ text = root.text.strip
70
+ hash[:contents] = text unless text.empty?
71
+ end
72
+ end
73
+ hash.empty? ? nil : hash
74
+ end
75
+
76
+ end
77
+ end
@@ -0,0 +1,63 @@
1
+ module KayakoClient
2
+ module XML
3
+
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
7
+
8
+ def xml_backend=(backend)
9
+ if backend.is_a?(String)
10
+ raise ArgumentError, "invalid XML backend: #{backend}" unless backend =~ /^[A-Za-z_]+$/
11
+ file = backend.gsub(/([a-z])([A-Z])/, '\1_\2').gsub(/([A-Z])([A-Z][a-z])/, '\1_\2').downcase
12
+ require "kayako_client/xml/#{file}"
13
+ backend = KayakoClient.const_get(backend)
14
+ end
15
+ if backend.is_a?(Class)
16
+ if backend.included_modules.include?(KayakoClient::XMLBackend)
17
+ @xml_backend = backend
18
+ else
19
+ raise ArgumentError, "invalid XML backend: #{backend.name}"
20
+ end
21
+ else
22
+ raise ArgumentError, "unsupported XML backend"
23
+ end
24
+ end
25
+
26
+ def xml_backend
27
+ @xml_backend ||= self.class.xml_backend
28
+ end
29
+
30
+ module ClassMethods
31
+
32
+ def xml_backend=(backend)
33
+ if backend.is_a?(String)
34
+ raise ArgumentError, "invalid XML backend: #{backend}" unless backend =~ /^[A-Za-z_]+$/
35
+ file = backend.gsub(/([a-z])([A-Z])/, '\1_\2').gsub(/([A-Z])([A-Z][a-z])/, '\1_\2').downcase
36
+ require "kayako_client/xml/#{file}"
37
+ backend = KayakoClient.const_get(backend)
38
+ end
39
+ if backend.is_a?(Class)
40
+ if backend.included_modules.include?(KayakoClient::XMLBackend)
41
+ @@xml_backend = backend
42
+ else
43
+ raise ArgumentError, "invalid XML backend: #{backend.name}"
44
+ end
45
+ else
46
+ raise ArgumentError, "unsupported XML backend"
47
+ end
48
+ end
49
+
50
+ def xml_backend
51
+ begin
52
+ require 'kayako_client/xml/lib_xml'
53
+ @@xml_backend ||= KayakoClient::LibXML
54
+ rescue LoadError
55
+ require 'kayako_client/xml/rexml_document'
56
+ @@xml_backend ||= KayakoClient::REXMLDocument
57
+ end
58
+ end
59
+
60
+ end
61
+
62
+ end
63
+ end
@@ -0,0 +1,42 @@
1
+ module KayakoClient
2
+
3
+ module XMLBackend
4
+
5
+ def initialize(document)
6
+ raise NotImplementedError, "not implemented"
7
+ end
8
+
9
+ def count
10
+ raise NotImplementedError, "not implemented"
11
+ end
12
+
13
+ def each(&block)
14
+ raise NotImplementedError, "not implemented"
15
+ end
16
+
17
+ def to_hash(root = nil)
18
+ raise NotImplementedError, "not implemented"
19
+ end
20
+
21
+ def notice?
22
+ defined?(@notice)
23
+ end
24
+
25
+ def error?
26
+ defined?(@error)
27
+ end
28
+
29
+ def notice
30
+ @notice || nil
31
+ end
32
+
33
+ def error
34
+ @error || nil
35
+ end
36
+
37
+ end
38
+
39
+ module XMLException
40
+ end
41
+
42
+ end