Class: FogBugz

Inherits:
Object
  • Object
show all
Defined in:
lib/fogbugz-api.rb

Overview

FogBugz class

Constant Summary collapse

API_VERSION =

Version of the FogBuz API this was written for. If the minversion returned by FogBugz is greater than this value this library will not function. TODO

  1. If API mismatch… destroy Object?

5
CASE_COLUMNS =

This is an array of all possible values that can be returned on a case. For methods that ask for cols wanted for a case this array will be used if their is nothing else specified.

%w(ixBug fOpen sTitle sLatestTextSummary ixBugEventLatestText
ixProject sProject ixArea sArea ixGroup ixPersonAssignedTo sPersonAssignedTo
sEmailAssignedTo ixPersonOpenedBy ixPersonResolvedBy ixPersonClosedBy
ixPersonLastEditedBy ixStatus sStatus ixPriority sPriority ixFixFor sFixFor
dtFixFor sVersion sComputer hrsOrigEst hrsCurrEst hrsElapsed c sCustomerEmail
ixMailbox ixCategory sCategory dtOpened dtResolved dtClosed ixBugEventLatest
dtLastUpdated fReplied fForwarded sTicket ixDiscussTopic dtDue sReleaseNotes
ixBugEventLastView dtLastView ixRelatedBugs sScoutDescription sScoutMessage
fScoutStopReporting fSubscribed events)

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(url, use_ssl = false, token = nil) ⇒ FogBugz

Creates an instance of the FogBugz class.

  • url: URL to your FogBugz installation. URL only as in my.fogbugz.com without the http or https.

  • use_ssl: Does this server use SSL? true/false

  • token: Already have a token for the server? You can provide that here.

Connects to the specified FogBugz installation and grabs the api.xml file to get other information such as API version, API minimum version, and the API endpoint. Also sets http/https connection to the server and sets the token if provided. FogBugzError will be raise if the minimum API version returned by FogBugz is greater than API_VERSION of this class.

Example Usage:

fb = FogBugz.new(“my.fogbugz.com”,true)

Raises:



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/fogbugz-api.rb', line 50

def initialize(url,use_ssl=false,token=nil)
  @url = url
  @use_ssl = use_ssl
  connect

  # Attempt to grap api.xml file from the server specified by url.  Will let
  # us know API is functional and verion matches this class
  result = Hpricot.XML(@connection.get("/api.xml").body)

  @api_version = (result/"version").inner_html.to_i
  @api_minversion = (result/"minversion").inner_html.to_i
  @api_url = "/" + (result/"url").inner_html

  # Make sure this class will work w/ API version
  raise FogBugzError, "API version mismatch" if (API_VERSION < @api_minversion)

  @token = token ? token : ""
end

Instance Attribute Details

#api_minversionObject (readonly)

Returns the value of attribute api_minversion.



31
32
33
# File 'lib/fogbugz-api.rb', line 31

def api_minversion
  @api_minversion
end

#api_urlObject (readonly)

Returns the value of attribute api_url.



31
32
33
# File 'lib/fogbugz-api.rb', line 31

def api_url
  @api_url
end

#api_versionObject (readonly)

Returns the value of attribute api_version.



31
32
33
# File 'lib/fogbugz-api.rb', line 31

def api_version
  @api_version
end

#tokenObject (readonly)

Returns the value of attribute token.



31
32
33
# File 'lib/fogbugz-api.rb', line 31

def token
  @token
end

#urlObject (readonly)

Returns the value of attribute url.



31
32
33
# File 'lib/fogbugz-api.rb', line 31

def url
  @url
end

#use_sslObject (readonly)

Returns the value of attribute use_ssl.



31
32
33
# File 'lib/fogbugz-api.rb', line 31

def use_ssl
  @use_ssl
end

Instance Method Details

#area(area = nil, ixProject = nil) ⇒ Object

Returns details about a specific area

  • area: Either the id of an area (ixArea) or the name of an area (sArea). If passing name, then the ID of the project the area belongs to needs to be passed.

  • ixProject: ID of a project which contains specific area. Needed if wanting details for area by name.

Value returned is a Hash of containing all properties of the located area. nil is returned for unsuccessful search.



188
189
190
191
192
193
194
195
196
197
# File 'lib/fogbugz-api.rb', line 188

def area(area=nil,ixProject=nil)
  return nil if not area
  cmd = {"cmd" => "viewArea", "token" => @token}
  cmd = {"ixArea" => area.to_s}.merge(cmd) if area.class == Fixnum
  cmd = {"sArea" => area}.merge(cmd) if area.class == String
  cmd = {"ixProject" => ixProject.to_s}.merge(cmd) if ixProject
  result = Hpricot.XML(@connection.post(@api_url,to_params(cmd)).body)
  return_value = list_process(result,"area","sArea")
  return_value[return_value.keys[0]]
end

#areas(fWrite = false, ixProject = nil, ixArea = nil) ⇒ Object



161
162
163
164
165
166
167
168
169
# File 'lib/fogbugz-api.rb', line 161

def areas(fWrite=false, ixProject=nil, ixArea=nil)
  return_value = Hash.new
  cmd = {"cmd" => "listAreas", "token" => @token}
  cmd = {"fWrite"=>"1"}.merge(cmd) if fWrite
  cmd = {"ixProject"=>ixProject}.merge(cmd) if ixProject
  cmd = {"ixArea" => ixArea}.merge(cmd) if ixArea
  result = Hpricot.XML(@connection.post(@api_url,to_params(cmd)).body)
  return list_process(result,"area","sArea")
end

#categoriesObject



239
240
241
242
243
# File 'lib/fogbugz-api.rb', line 239

def categories
  cmd = {"cmd" => "listCategories", "token" => @token}
  result = Hpricot.XML(@connection.post(@api_url,to_params(cmd)).body)
  return list_process(result,"category","sCategory")
end

#category(ixCategory) ⇒ Object

Returns details about a specific Category

  • ixCategory: The id of the Category to view.

Value returned is a Hash containing all properties of the located Category. nil is returned for unsucessful search.



250
251
252
253
254
255
# File 'lib/fogbugz-api.rb', line 250

def category(ixCategory)
  cmd = {"cmd" => "viewCategory", "token" => @token, "ixCategory" => ixCategory.to_s}
  result = Hpricot.XML(@connection.post(@api_url,to_params(cmd)).body)
  return_value = list_process(result,"category","sCategory")
  return_value[return_value.keys[0]]    
end

#filtersObject



104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/fogbugz-api.rb', line 104

def filters
  cmd = {"cmd" => "listFilters", "token" => @token}
  result = Hpricot.XML(@connection.post(@api_url, to_params(cmd)).body)
  return_value = Hash.new
  (result/"filter").each do |filter|
    # create hash for each new project
    filter_name = filter.inner_html
    return_value[filter_name] = Hash.new
    return_value[filter_name]["name"] = filter_name
    return_value[filter_name] = filter.attributes.merge(return_value[filter_name])
  end
  return_value
end

#fix_for(fix_for, ixProject = nil) ⇒ Object

Returns details about a specific Fix For (releases)

  • fix_for: Either the id of a Fix For (ixFixFor) or the name of a Fix For (sFixFor). If passing name, then the ID of the project the area belongs to needs to be passed.

  • ixProject: ID of a project which contains specific Fix For. Needed if wanting details for Fix For by name.

Value returned is a Hash containing all properties of the located Fix For. nil is returned for unsuccessful search.



214
215
216
217
218
219
220
221
222
223
# File 'lib/fogbugz-api.rb', line 214

def fix_for(fix_for,ixProject=nil)
  return nil if not fix_for
  cmd = {"cmd" => "viewFixFor", "token" => @token}
  cmd = {"ixFixFor" => fix_for.to_s}.merge(cmd) if fix_for.class == Fixnum
  cmd = {"sFixFor" => fix_for}.merge(cmd) if fix_for.class == String
  cmd = {"ixProject" => ixProject.to_s}.merge(cmd) if ixProject
  result = Hpricot.XML(@connection.post(@api_url,to_params(cmd)).body)
  return_value = list_process(result,"fixfor","sFixFor")
  return_value[return_value.keys[0]]
end

#fix_fors(ixProject = nil, ixFixFor = nil) ⇒ Object



199
200
201
202
203
204
205
206
# File 'lib/fogbugz-api.rb', line 199

def fix_fors(ixProject=nil,ixFixFor=nil)
  return_value = Hash.new
  cmd = {"cmd" => "listFixFors", "token" => @token}
  {"ixProject"=>ixProject}.merge(cmd) if ixProject
  {"ixFixFor" => ixFixFor}.merge(cmd) if ixFixFor
  result = Hpricot.XML(@connection.post(@api_url,to_params(cmd)).body)
  return list_process(result,"fixfor","sFixFor")
end

#logoffObject



98
99
100
101
102
# File 'lib/fogbugz-api.rb', line 98

def logoff
  cmd = {"cmd" => "logoff", "token" => @token}
  result = Hpricot.XML(@connection.post(@api_url, to_params(cmd)).body)
  @token = ""
end

#logon(email, password) ⇒ Object

Validates a user with FogBugz. Saves the returned token for use with other commands.

If a token was already specified with new it will be overwritten with the token picked up by a successful authentication.



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/fogbugz-api.rb', line 74

def logon(email,password)
  cmd = {"cmd" => "logon", "email" => email, "password" => password}

  result = Hpricot.XML(@connection.post(@api_url, to_params(cmd)).body)

  if (result/"error").length >= 1
    # error code 1 = bad login
    # error code 2 = ambiguous name
    case (result/"error").first["code"]
      when "1"
        raise FogBugzError, (result/"error").inner_html
      when "2"
        ambiguous_users = []
        (result/"person").each do |person|
          ambiguous_users << CDATA_REGEXP.match(person.inner_html)[1]
        end
        raise FogBugzError, (result/"error").inner_html + " " + ambiguous_users.join(", ")
    end  # case
  elsif (result/"token").length == 1
    # successful login
    @token = CDATA_REGEXP.match((result/"token").inner_html)[1]
  end
end

#mailbox(ixMailbox) ⇒ Object

Returns details about a specific mailbox

  • ixMailbox: The id of the Mailbox to view

Value returned is a Hash containing all properties of the located Mailbox. nil is returned for unsuccessful search.



367
368
369
370
371
372
# File 'lib/fogbugz-api.rb', line 367

def mailbox(ixMailbox)
  cmd = {"cmd" => "viewMailbox", "token" => @token, "ixMailbox" => ixMailbox.to_s}
  result = Hpricot.XML(@connection.post(@api_url,to_params(cmd)).body)
  return_value = list_process(result,"mailbox","ixMailbox")
  return_value[return_value.keys[0]]    
end

#mailboxesObject

Returns a list of mailboxes that you have access to.



351
352
353
354
355
356
357
358
359
360
# File 'lib/fogbugz-api.rb', line 351

def mailboxes
  cmd = {
    "cmd" => "listMailboxes",
    "token" => @token
  }
  result = Hpricot.XML(@connection.post(@api_url,to_params(cmd)).body)
  # usually lists were keyed w/ a name field.  Mailboxes just
  # weren't working for me so I'm going with ixMailbox value
  return list_process(result,"mailbox","ixMailbox")
end

#new_area(ixProject, sArea, ixPersonPrimaryContact = -1)) ⇒ Object

Creates a new area within a specific project

  • ixProject: ID of the project to contain the new area.

  • sArea: Title of the new area.

  • ixPersonPrimaryContact: ID of the person who will be the primary contact for this area. -1 will set to the Project’s primary contact, which is the default if not specified.



176
177
178
179
180
# File 'lib/fogbugz-api.rb', line 176

def new_area(ixProject,sArea,ixPersonPrimaryContact=-1)
  cmd = {"cmd" => "newArea", "token" => @token, "ixProject" => ixProject.to_s, "sArea" => sArea.to_s, "ixPersonPrimaryContact" => ixPersonPrimaryContact.to_s}
  result = Hpricot.XML(@connection.post(@api_url,to_params(cmd)).body)
  return (result/"ixArea").inner_html.to_i    
end

#new_case(params, cols = CASE_COLUMNS) ⇒ Object

Creates a FogBugz case.

  • params: must be a hash keyed with values from the FogBugz API docs. sTitle, ixProject (or sProject), etc…

  • cols: columns to be returned about the case which gets created. Ff not passed will use constant list (all) provided with Class



409
410
411
# File 'lib/fogbugz-api.rb', line 409

def new_case(params, cols=CASE_COLUMNS)
  case_process("new",params,cols)
end

#new_fix_for(sFixFor, fAssignable = true, ixProject = -1,, dtRelease = nil) ⇒ Object

Creates a new FixFor within FogBugz.

  • sFixFor: Title for the new FixFor

  • fAssignable: Can cases be assigned to this FixFor? true/false Default is true.

  • ixProject: ID of the project this FixFor belongs to. If -1 (which is default when not specified) this will be a global FixFor.

  • dtRelease: Release date for the new FixFor. If not passed, no release date will be set. Expecting DateTime class if value is passed.



231
232
233
234
235
236
237
# File 'lib/fogbugz-api.rb', line 231

def new_fix_for(sFixFor,fAssignable=true,ixProject=-1,dtRelease=nil)
  return nil if dtRelease and dtRelease.class != DateTime
  cmd = {"cmd" => "newFixFor","token"=>@token,"sFixFor"=>sFixFor,"fAssignable"=>(fAssignable) ? "1" : "0","ixProject"=>ixProject.to_s}
  cmd = {"dtRelease"=>dtRelease}.merge(cmd) if dtRelease
  result = Hpricot.XML(@connection.post(@api_url,to_params(cmd)).body)
  return (result/"ixFixFor").inner_html.to_i        
end

#new_person(sEmail, sFullname, nType, fActive = true) ⇒ Object

Creates a new Person within FogBugz.

  • sEmail: Email address of the new Person.

  • sFullname: Fullname of the new Person.

  • nType: Type for the new user. 0 = Normal User, 1 = Administrator, 2 = Community User, 3 = Virtual User

  • fActive: Is the new Person active? true/false



317
318
319
320
321
# File 'lib/fogbugz-api.rb', line 317

def new_person(sEmail,sFullname,nType,fActive=true)
  cmd = {"cmd" => "newPerson", "token" => @token, "sEmail" => sEmail.to_s, "sFullname" => sFullname.to_s, "nType" => nType.to_s, "fActive" => (fActive) ? "1" : "0"}
  result = Hpricot.XML(@connection.post(@api_url,to_params(cmd)).body)
  return (result/"ixPerson").inner_html.to_i        
end

#new_project(sProject, ixPersonPrimaryContact, fAllowPublicSubmit, ixGroup, fInbox) ⇒ Object

Returns an integer, which is ixProject for the project created TODO - change to accept Has of parameters?



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/fogbugz-api.rb', line 129

def new_project(sProject, ixPersonPrimaryContact, fAllowPublicSubmit, ixGroup, fInbox)

  # I would have thought that the fAllowPublicSubmit would have been
  # true/false... instead seems to need to be 0 or 1.
  cmd = {
    "cmd" => "newProject",
    "token" => @token,
    "sProject" => sProject,
    "ixPersonPrimaryContact" => ixPersonPrimaryContact.to_s,
    "fAllowPublicSubmit" => fAllowPublicSubmit.to_s,
    "ixGroup" => ixGroup.to_s,
    "fInbox" => fInbox.to_s
  }
  result = Hpricot.XML(@connection.post(@api_url,to_params(cmd)).body)
  return (result/"ixProject").inner_html.to_i
end

#people(fIncludeNormal = "1", fIncludeCommunity = nil, fIncludeVirtual = nil) ⇒ Object

Returns list of people in corresponding categories.

  • fIncludeNormal: Only include Normal users. If no options specified, fIncludeNormal=1 is assumed.

  • fIncludeCommunity: true/false Will include Community users in return.

  • fIncludeVirtual: true/false Will include Virtual users in return.



281
282
283
284
285
286
287
288
289
290
291
# File 'lib/fogbugz-api.rb', line 281

def people(fIncludeNormal="1", fIncludeCommunity=nil, fIncludeVirtual=nil)
  cmd = {
    "cmd" => "listPeople",
    "token" => @token,
    "fIncludeNormal" => fIncludeNormal
  }
  cmd = {"fIncludeCommunity" => "1"}.merge(cmd) if fIncludeCommunity
  cmd = {"fIncludeVirtual" => "1"}.merge(cmd) if fIncludeVirtual
  result = Hpricot.XML(@connection.post(@api_url, to_params(cmd)).body)
  return list_process(result,"person","sFullName")
end

#person(ixPerson = nil, sEmail = nil) ⇒ Object

Returns details for a specific FogBugz user. Can search by person’s ID or their email address.

  • ixPerson: ID for the person to display

  • sEmail: Email address for the person to display.

Note: If you specify both, Email search seems to take precedence.

Value returned is a Hash of containing all properties of the located person. nil is returned for unsuccessful search.



301
302
303
304
305
306
307
308
309
# File 'lib/fogbugz-api.rb', line 301

def person(ixPerson=nil,sEmail=nil)
  return nil if not ixPerson || sEmail
  cmd = {"cmd" => "viewPerson", "token" => @token}
  cmd = {"ixPerson" => ixPerson.to_s}.merge(cmd) if ixPerson
  cmd = {"sEmail" => sEmail}.merge(cmd) if sEmail
  result = Hpricot.XML(@connection.post(@api_url, to_params(cmd)).body)
  return_value = list_process(result,"person","sFullName")
  return_value[return_value.keys[0]]
end

#prioritiesObject



257
258
259
260
261
# File 'lib/fogbugz-api.rb', line 257

def priorities
  cmd = {"cmd" => "listPriorities", "token" => @token}
  result = Hpricot.XML(@connection.post(@api_url,to_params(cmd)).body)
  return list_process(result,"priority","sPriority")
end

#priority(ixPriority) ⇒ Object

Returns details about a specific priority

  • ixPriority: The id of the Priority to view

Value returned is a Hash containing all properties of the located Priority. nil is returned for unsuccessful search.



268
269
270
271
272
273
# File 'lib/fogbugz-api.rb', line 268

def priority(ixPriority)
  cmd = {"cmd" => "viewPriority", "token" => @token, "ixPriority" => ixPriority.to_s}
  result = Hpricot.XML(@connection.post(@api_url,to_params(cmd)).body)
  return_value = list_process(result,"priority","sPriority")
  return_value[return_value.keys[0]]        
end

#project(project = nil) ⇒ Object

Returns details about a specific project.

  • project: Either the id (ixProject) or the name (sProject).

Value returned is a Hash containing all properties of the located project. nil is returned for unsuccessful search.



151
152
153
154
155
156
157
158
159
# File 'lib/fogbugz-api.rb', line 151

def project(project=nil)
  return nil if not project
  cmd = {"cmd" => "viewProject", "token" => @token}
  cmd = {"ixProject" => project.to_s}.merge(cmd) if project.class == Fixnum
  cmd = {"sProject" => project}.merge(cmd) if project.class == String
  result = Hpricot.XML(@connection.post(@api_url,to_params(cmd)).body)
  return_value =  list_process(result,"project","sProject")
  return_value[return_value.keys[0]]
end

#projects(fWrite = false, ixProject = nil) ⇒ Object



118
119
120
121
122
123
124
125
# File 'lib/fogbugz-api.rb', line 118

def projects(fWrite=false, ixProject=nil)
  return_value = Hash.new
  cmd = {"cmd" => "listProjects", "token" => @token}
  cmd = {"fWrite"=>"1"}.merge(cmd) if fWrite
  cmd = {"ixProject"=>ixProject}.merge(cmd) if ixProject
  result = Hpricot.XML(@connection.post(@api_url,to_params(cmd)).body)
  return list_process(result,"project","sProject")
end

#search(q, cols = CASE_COLUMNS, max = nil) ⇒ Object

Searches for FogBugz cases

  • q: Query for searching. Should hopefully work just like the Search box within the FogBugz application.

  • cols: Columns of information to be returned for each case found. Consult FogBugz API documentation for a list. If this is not specified the CASE_COLUMNS will be used. This will request every possible datapoint (as of API version 5) for each case.

  • max: Maximum number of cases to be returned for your search. Will return all if not specified.



384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
# File 'lib/fogbugz-api.rb', line 384

def search(q, cols=CASE_COLUMNS, max=nil)
  # TODO - shoudl I worry about the "operations" returned
  # in the <case>?
  
  cmd = {"cmd" => "search","token" => @token,"q" => q, "cols" => cols.join(",")}
  # ixBug is the key for the hash returned so I'm adding it to the cols array just in case
  cmd = {"cols" => (cols + ["ixBug"])}.merge(cmd) if not cols.include?("ixBug")
  cmd = {"max" => max}.merge(cmd) if max
  result = Hpricot.XML(@connection.post(@api_url,to_params(cmd)).body)
  return_value = list_process(result,"case","ixBug")
  # if one of the returned cols = events, then process 
  # this list and replace its spot in the Hash
  # with this instead of a string of XML
  return_value.each do |key,value|
    return_value[key]["events"] = list_process(Hpricot.XML(return_value[key]["events"]),"event","ixBugEvent") if return_value[key].has_key?("events")
  end
  return_value
end

#status(ixStatus) ⇒ Object

Returns details about a specific status

  • ixStatus: The id of the Status to view

Value returned is a Hash containing all properties of the located Status. nil is returned for unsuccessful search.



343
344
345
346
347
348
# File 'lib/fogbugz-api.rb', line 343

def status(ixStatus)
  cmd = {"cmd" => "viewStatus", "token" => @token, "ixStatus" => ixStatus.to_s}
  result = Hpricot.XML(@connection.post(@api_url,to_params(cmd)).body)
  return_value = list_process(result,"status","sStatus")
  return_value[return_value.keys[0]]            
end

#statuses(ixCategory = nil, fResolved = nil) ⇒ Object

Returns a list of statuses for a particular category.

  • ixCategory => category to return statuses for. If not specified, then all are returned.

  • fResolved => If = 1 then only resolved statuses are returned.



327
328
329
330
331
332
333
334
335
336
# File 'lib/fogbugz-api.rb', line 327

def statuses(ixCategory=nil,fResolved=nil)
  cmd = {
    "cmd" => "listStatuses",
    "token" => @token
  }
  cmd = {"ixCategory"=>ixCategory}.merge(cmd) if ixCategory
  cmd = {"fResolved"=>fResolved}.merge(cmd) if fResolved
  result = Hpricot.XML(@connection.post(@api_url,to_params(cmd)).body)
  return list_process(result,"status","sStatus")
end