KayakoClient 0.0.1b

Sign up to get free protection for your applications and to get access to all the features.
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