piwik 0.0.2

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.
@@ -0,0 +1,9 @@
1
+ == 0.0.2 2008-07-22
2
+
3
+ * Added specs for existing API methods
4
+ * Created RubyForge project at http://rubyforge.org/projects/piwik/
5
+
6
+ == 0.0.1 2008-07-21
7
+
8
+ * 1 major enhancement:
9
+ * Initial release
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Riopro Informática Ltda
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,31 @@
1
+ History.txt
2
+ License.txt
3
+ Manifest.txt
4
+ PostInstall.txt
5
+ README.txt
6
+ Rakefile
7
+ Todo.txt
8
+ config/hoe.rb
9
+ config/requirements.rb
10
+ lib/piwik.rb
11
+ lib/piwik/base.rb
12
+ lib/piwik/site.rb
13
+ lib/piwik/user.rb
14
+ lib/piwik/version.rb
15
+ script/console
16
+ script/destroy
17
+ script/generate
18
+ script/txt2html
19
+ setup.rb
20
+ spec/piwik_spec.rb
21
+ spec/spec.opts
22
+ spec/spec_helper.rb
23
+ tasks/deployment.rake
24
+ tasks/environment.rake
25
+ tasks/rspec.rake
26
+ tasks/website.rake
27
+ website/index.html
28
+ website/index.txt
29
+ website/javascripts/rounded_corners_lite.inc.js
30
+ website/stylesheets/screen.css
31
+ website/template.html.erb
@@ -0,0 +1,4 @@
1
+
2
+ For more information on piwik, see http://piwik.rubyforge.org or
3
+ http://github.com/riopro/piwik/
4
+
@@ -0,0 +1,77 @@
1
+ = piwik
2
+
3
+ * http://piwik.rubyforge.org
4
+ * http://github.com/riopro/piwik/tree/master
5
+
6
+ == DESCRIPTION:
7
+
8
+ A simple Ruby client for the Piwik API.
9
+
10
+ == FEATURES/PROBLEMS:
11
+
12
+ * Object-oriented interface to the Piwik API;
13
+ * For now, only a small subset of the API is implemented (only basic actions)
14
+
15
+ == SYNOPSIS:
16
+
17
+ Piwik is an open source web analytics software, written in PHP. It provides an
18
+ extensive REST-like API, and this gem aims to be a simple Ruby wrapper to access
19
+ this API in a Ruby-friendly way. For example:
20
+
21
+ >> require 'rubygems'
22
+ => []
23
+ >> require 'piwik'
24
+ => []
25
+ >> site = Piwik::Site.load(1, 'http://your.piwi.install', 'some_auth_key')
26
+ => #<Piwik::Site:0xb74bf994 @name="Example.com", @config={:auth_token=>"some_auth_key", :piwik_url=>"http://your.piwi.install"}, @id=1, @main_url="http://www.example.com", @created_at=Tue Jul 15 18:55:40 -0300 2008>
27
+ >> site.pageviews(:month, Date.today)
28
+ => 88
29
+
30
+ See the Piwik::Site RDoc for full documentation.
31
+
32
+ For more information on Piwik and it's API, see the Piwik website (http://piwik.org)
33
+ and the Piwik API reference (http://dev.piwik.org/trac/wiki/API/Reference).
34
+
35
+ == REQUIREMENTS:
36
+
37
+ RubyGems and the following gems (installed automatically if necessary):
38
+
39
+ activesupport
40
+ xml-simple
41
+ rest-client
42
+
43
+ == INSTALL:
44
+
45
+ From RubyForge:
46
+
47
+ sudo gem install piwik
48
+
49
+ From Github (with RubyGems >= 1.2.0):
50
+
51
+ sudo gem sources -a http://gems.github.com # you only have to do this once
52
+ sudo gem install riopro-piwik
53
+
54
+ == LICENSE:
55
+
56
+ (The MIT License)
57
+
58
+ Copyright (c) 2008 Riopro Informatica Ltda
59
+
60
+ Permission is hereby granted, free of charge, to any person obtaining
61
+ a copy of this software and associated documentation files (the
62
+ 'Software'), to deal in the Software without restriction, including
63
+ without limitation the rights to use, copy, modify, merge, publish,
64
+ distribute, sublicense, and/or sell copies of the Software, and to
65
+ permit persons to whom the Software is furnished to do so, subject to
66
+ the following conditions:
67
+
68
+ The above copyright notice and this permission notice shall be
69
+ included in all copies or substantial portions of the Software.
70
+
71
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
72
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
73
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
74
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
75
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
76
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
77
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,4 @@
1
+ require 'config/requirements'
2
+ require 'config/hoe' # setup Hoe + all gem configuration
3
+
4
+ Dir['tasks/**/*.rake'].each { |rake| load rake }
@@ -0,0 +1,6 @@
1
+ TODO:
2
+ =====
3
+
4
+ * Implement the rest of the API for a site
5
+ * Model the User object, and implement it's API methods
6
+ * Improve and extend the test coverage
@@ -0,0 +1,76 @@
1
+ require 'piwik/version'
2
+
3
+ AUTHOR = 'Rodrigo Tassinari de Oliveira @ Riopro Informática Ltda' # can also be an array of Authors
4
+ EMAIL = "roliveira@riopro.com.br"
5
+ DESCRIPTION = "A simple Ruby client for the Piwik API"
6
+ GEM_NAME = 'piwik' # what ppl will type to install your gem
7
+ RUBYFORGE_PROJECT = 'piwik' # The unix name for your project
8
+ HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
9
+ DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
10
+ EXTRA_DEPENDENCIES = [
11
+ ['activesupport', '>= 1.4.4'],
12
+ ['rest-client', '>= 0.5.1'],
13
+ ['xml-simple', '>= 1.0.11']
14
+ ] # An array of rubygem dependencies [name, version]
15
+
16
+ @config_file = "~/.rubyforge/user-config.yml"
17
+ @config = nil
18
+ RUBYFORGE_USERNAME = "riopro"
19
+ def rubyforge_username
20
+ unless @config
21
+ begin
22
+ @config = YAML.load(File.read(File.expand_path(@config_file)))
23
+ rescue
24
+ puts <<-EOS
25
+ ERROR: No rubyforge config file found: #{@config_file}
26
+ Run 'rubyforge setup' to prepare your env for access to Rubyforge
27
+ - See http://newgem.rubyforge.org/rubyforge.html for more details
28
+ EOS
29
+ exit
30
+ end
31
+ end
32
+ RUBYFORGE_USERNAME.replace @config["username"]
33
+ end
34
+
35
+
36
+ REV = nil
37
+ # UNCOMMENT IF REQUIRED:
38
+ # REV = YAML.load(`svn info`)['Revision']
39
+ VERS = Piwik::VERSION::STRING + (REV ? ".#{REV}" : "")
40
+ RDOC_OPTS = ['--quiet', '--title', 'piwik documentation',
41
+ "--opname", "index.html",
42
+ "--line-numbers",
43
+ "--main", "README",
44
+ "--inline-source",
45
+ "-c utf8"]
46
+
47
+ class Hoe
48
+ def extra_deps
49
+ @extra_deps.reject! { |x| Array(x).first == 'hoe' }
50
+ @extra_deps
51
+ end
52
+ end
53
+
54
+ # Generate all the Rake tasks
55
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
56
+ $hoe = Hoe.new(GEM_NAME, VERS) do |p|
57
+ p.developer(AUTHOR, EMAIL)
58
+ p.description = DESCRIPTION
59
+ p.summary = DESCRIPTION
60
+ p.url = HOMEPATH
61
+ p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
62
+ p.test_globs = ["test/**/test_*.rb"]
63
+ p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store'] #An array of file patterns to delete on clean.
64
+
65
+ # == Optional
66
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
67
+ p.extra_deps = EXTRA_DEPENDENCIES
68
+
69
+ #p.spec_extras = {} # A hash of extra values to set in the gemspec.
70
+ end
71
+
72
+ CHANGES = $hoe.paragraphs_of('History.txt', 0..1).join("\\n\\n")
73
+ PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
74
+ $hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
75
+ $hoe.rsync_args = '-av --delete --ignore-errors'
76
+ $hoe.spec.post_install_message = File.open(File.dirname(__FILE__) + "/../PostInstall.txt").read rescue ""
@@ -0,0 +1,15 @@
1
+ require 'fileutils'
2
+ include FileUtils
3
+
4
+ require 'rubygems'
5
+ %w[rake hoe newgem rubigen].each do |req_gem|
6
+ begin
7
+ require req_gem
8
+ rescue LoadError
9
+ puts "This Rakefile requires the '#{req_gem}' RubyGem."
10
+ puts "Installation: gem install #{req_gem} -y"
11
+ exit
12
+ end
13
+ end
14
+
15
+ $:.unshift(File.join(File.dirname(__FILE__), %w[.. lib]))
@@ -0,0 +1,10 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ require 'piwik/base.rb'
5
+ require 'piwik/site.rb'
6
+ require 'piwik/user.rb'
7
+
8
+ module Piwik
9
+
10
+ end
@@ -0,0 +1,44 @@
1
+ require 'rubygems'
2
+ require 'cgi'
3
+ require 'activesupport'
4
+ require 'rest_client'
5
+ require 'xmlsimple'
6
+
7
+ module Piwik
8
+ class ApiError < StandardError; end
9
+ class MissingConfiguration < ArgumentError; end
10
+ class UnknownSite < ArgumentError; end
11
+ class UnknownUser < ArgumentError; end
12
+
13
+ class Base
14
+ @@template = <<-EOF
15
+ # .piwik
16
+ #
17
+ # Please fill in fields like this:
18
+ #
19
+ # piwik_url: http://your.piwik.site
20
+ # auth_token: secret
21
+ #
22
+ piwik_url:
23
+ auth_token:
24
+ EOF
25
+
26
+ private
27
+ # Checks for the config, creates it if not found
28
+ def self.load_config_from_file
29
+ config = {}
30
+ home = ENV['HOME'] || ENV['USERPROFILE'] || ENV['HOMEPATH']
31
+ if File.exists?(home + "/.piwik")
32
+ temp_config = YAML::load open(home + "/.piwik")
33
+ else
34
+ open(home + '/.piwik','w') { |f| f.puts @@template }
35
+ temp_config = YAML::load(@@template)
36
+ end
37
+ temp_config.each { |k,v| config[k.to_sym] = v } if temp_config
38
+ if config[:piwik_url] == nil || config[:auth_token] == nil
39
+ raise MissingConfiguration, "Please edit ~/.piwik to include your piwik url and auth_key"
40
+ end
41
+ config
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,252 @@
1
+ module Piwik
2
+ class Site < Piwik::Base
3
+ attr_accessor :name, :main_url
4
+ attr_reader :id, :created_at, :config
5
+
6
+ # Initializes a new <tt>Piwik::Site</tt> object, with the supplied attributes.
7
+ #
8
+ # You can pass the URL for your Piwik install and an authorization token as
9
+ # the second and third parameters. If you don't, than it will try to find
10
+ # them in a <tt>'~/.piwik'</tt> (and create the file with an empty template if it
11
+ # doesn't exists).
12
+ #
13
+ # Valid (and required) attributes are:
14
+ # * <tt>:name</tt> - the site's name
15
+ # * <tt>:main_url</tt> - the site's url
16
+ def initialize(attributes={}, piwik_url=nil, auth_token=nil)
17
+ raise ArgumentError, "expected an attributes Hash, got #{attributes.inspect}" unless attributes.is_a?(Hash)
18
+ @config = if piwik_url.nil? || auth_token.nil?
19
+ self.class.load_config_from_file
20
+ else
21
+ {:piwik_url => piwik_url, :auth_token => auth_token}
22
+ end
23
+ load_attributes(attributes)
24
+ end
25
+
26
+ # Returns an instance of <tt>Piwik::Site</tt> representing the site identified by
27
+ # the supplied <tt>site_id</tt>. Raises a <tt>Piwik::ApiError</tt> if the site doesn't
28
+ # exists or if the user associated with the supplied auth_token does not
29
+ # have at least 'view' access to the site.
30
+ #
31
+ # You can pass the URL for your Piwik install and an authorization token as
32
+ # the second and third parameters. If you don't, than it will try to find
33
+ # them in a <tt>'~/.piwik'</tt> (and create the file with an empty template if it
34
+ # doesn't exists).
35
+ def self.load(site_id, piwik_url=nil, auth_token=nil)
36
+ raise ArgumentError, "expected a site Id" if site_id.nil?
37
+ @config = if piwik_url.nil? || auth_token.nil?
38
+ load_config_from_file
39
+ else
40
+ {:piwik_url => piwik_url, :auth_token => auth_token}
41
+ end
42
+ attributes = get_site_attributes_by_id(site_id, @config[:piwik_url], @config[:auth_token])
43
+ new(attributes, @config[:piwik_url], @config[:auth_token])
44
+ end
45
+
46
+ # Returns <tt>true</tt> if the current site does not exists in the Piwik yet.
47
+ def new?
48
+ id.nil? && created_at.nil?
49
+ end
50
+
51
+ # Saves the current site in Piwik.
52
+ #
53
+ # Calls <tt>create</tt> it it's a new site, <tt>update</tt> otherwise.
54
+ def save
55
+ new? ? create : update
56
+ end
57
+
58
+ # Saves the current new site in Piwik.
59
+ #
60
+ # Equivalent Piwik API call: SitesManager.addSite (siteName, urls)
61
+ def create
62
+ raise ArgumentError, "Site already exists in Piwik, call 'update' instead" unless new?
63
+ raise ArgumentError, "Name can not be blank" if name.blank?
64
+ raise ArgumentError, "Main URL can not be blank" if main_url.blank?
65
+ xml = call('SitesManager.addSite', :siteName => name, :urls => main_url)
66
+ result = XmlSimple.xml_in(xml, {'ForceArray' => false})
67
+ @id = result.to_i
68
+ @created_at = Time.current
69
+ id && id > 0 ? true : false
70
+ end
71
+
72
+ # Saves the current site in Piwik, updating it's data.
73
+ #
74
+ # Equivalent Piwik API call: SitesManager.updateSite (idSite, siteName, urls)
75
+ def update
76
+ raise UnknownSite, "Site not existent in Piwik yet, call 'save' first" if new?
77
+ raise ArgumentError, "Name can not be blank" if name.blank?
78
+ raise ArgumentError, "Main URL can not be blank" if main_url.blank?
79
+ xml = call('SitesManager.updateSite', :idSite => id, :siteName => name, :urls => main_url)
80
+ result = XmlSimple.xml_in(xml, {'ForceArray' => false})
81
+ result['success'] ? true : false
82
+ end
83
+
84
+ def reload
85
+ #TODO
86
+ end
87
+
88
+ # Deletes the current site from Piwik.
89
+ #
90
+ # Equivalent Piwik API call: SitesManager.deleteSite (idSite)
91
+ def destroy
92
+ raise UnknownSite, "Site not existent in Piwik yet, call 'save' first" if new?
93
+ xml = call('SitesManager.deleteSite', :idSite => id)
94
+ result = XmlSimple.xml_in(xml, {'ForceArray' => false})
95
+ freeze
96
+ result['success'] ? true : false
97
+ end
98
+
99
+ # Gives read access (<tt>'view'</tt>) to the supplied user login for the current
100
+ # site.
101
+ def give_view_access_to(login)
102
+ give_access_to(:view, login)
103
+ end
104
+
105
+ # Gives read and write access (<tt>'admin'</tt>) for the supplied user login for the
106
+ # current site.
107
+ def give_admin_access_to(login)
108
+ give_access_to(:admin, login)
109
+ end
110
+
111
+ # Removes all access (gives an <tt>'noaccess'</tt>) for the supplied user login for
112
+ # the current site.
113
+ def give_no_access_to(login)
114
+ give_access_to(:noaccess, login)
115
+ end
116
+ alias_method :remove_access_from, :give_no_access_to
117
+
118
+ # Returns a hash with a summary of access information for the current site
119
+ # (visits, unique visitors, actions / pageviews, maximum actions per visit,
120
+ # bounces and total time spent in all visits in seconds), filtered by the
121
+ # supplied period and date.
122
+ #
123
+ # * <tt>period</tt> should be one of <tt>:day</tt>, <tt>:week</tt>, <tt>:month</tt> or <tt>:year</tt> (default: <tt>:day</tt>)
124
+ # * <tt>date</tt> should be a <tt>Date</tt> object (default: <tt>Date.today</tt>)
125
+ #
126
+ # Equivalent Piwik API call: VisitsSummary.get (idSite, period, date)
127
+ def summary(period=:day, date=Date.today)
128
+ raise UnknownSite, "Site not existent in Piwik yet, call 'save' first" if new?
129
+ xml = call('VisitsSummary.get', :idSite => id, :period => period, :date => date)
130
+ result = XmlSimple.xml_in(xml, {'ForceArray' => false})
131
+ {
132
+ :visits => result['nb_visits'].to_i,
133
+ :unique_visitors => result['nb_uniq_visitors'].to_i,
134
+ :actions => result['nb_actions'].to_i,
135
+ :max_actions_per_visit => result['max_actions'].to_i,
136
+ :bounces => result['bounce_count'].to_i,
137
+ :total_time_spent => result['sum_visit_length'].to_i, # in seconds
138
+ }
139
+ end
140
+
141
+ # Returns the amount of visits for the current site, filtered by the
142
+ # supplied period and date.
143
+ #
144
+ # * <tt>period</tt> should be one of <tt>:day</tt>, <tt>:week</tt>, <tt>:month</tt> or <tt>:year</tt> (default: <tt>:day</tt>)
145
+ # * <tt>date</tt> should be a <tt>Date</tt> object (default: <tt>Date.today</tt>)
146
+ #
147
+ # Equivalent Piwik API call: VisitsSummary.getVisits (idSite, period, date)
148
+ def visits(period=:day, date=Date.today)
149
+ raise UnknownSite, "Site not existent in Piwik yet, call 'save' first" if new?
150
+ xml = call('VisitsSummary.getVisits', :idSite => id, :period => period, :date => date)
151
+ result = XmlSimple.xml_in(xml, {'ForceArray' => false})
152
+ result.to_i
153
+ end
154
+
155
+ # Returns the amount of unique visitors for the current site, filtered by
156
+ # the supplied period and date.
157
+ #
158
+ # * <tt>period</tt> should be one of <tt>:day</tt>, <tt>:week</tt>, <tt>:month</tt> or <tt>:year</tt> (default: <tt>:day</tt>)
159
+ # * <tt>date</tt> should be a <tt>Date</tt> object (default: <tt>Date.today</tt>)
160
+ #
161
+ # Equivalent Piwik API call: VisitsSummary.getUniqueVisitors (idSite, period, date)
162
+ def unique_visitors(period=:day, date=Date.today)
163
+ raise UnknownSite, "Site not existent in Piwik yet, call 'save' first" if new?
164
+ xml = call('VisitsSummary.getUniqueVisitors', :idSite => id, :period => period, :date => date)
165
+ result = XmlSimple.xml_in(xml, {'ForceArray' => false})
166
+ result.to_i
167
+ end
168
+
169
+ # Returns the amount of actions (pageviews) for the current site, filtered
170
+ # by the supplied period and date.
171
+ #
172
+ # * <tt>period</tt> should be one of <tt>:day</tt>, <tt>:week</tt>, <tt>:month</tt> or <tt>:year</tt> (default: <tt>:day</tt>)
173
+ # * <tt>date</tt> should be a <tt>Date</tt> object (default: <tt>Date.today</tt>)
174
+ #
175
+ # Equivalent Piwik API call: VisitsSummary.getActions (idSite, period, date)
176
+ def actions(period=:day, date=Date.today)
177
+ raise UnknownSite, "Site not existent in Piwik yet, call 'save' first" if new?
178
+ xml = call('VisitsSummary.getActions', :idSite => id, :period => period, :date => date)
179
+ result = XmlSimple.xml_in(xml, {'ForceArray' => false})
180
+ result.to_i
181
+ end
182
+ alias_method :pageviews, :actions
183
+
184
+ private
185
+ # Calls the supplied Piwik API method, with the supplied parameters.
186
+ #
187
+ # Returns a string containing the XML reply from Piwik, or raises a
188
+ # <tt>Piwik::ApiError</tt> exception with the error message returned by Piwik
189
+ # in case it receives an error.
190
+ def call(method, params={})
191
+ self.class.call(method, params, config[:piwik_url], config[:auth_token])
192
+ end
193
+
194
+ # Loads the attributes in the instance variables.
195
+ def load_attributes(attributes)
196
+ @id = attributes[:id]
197
+ @name = attributes[:name]
198
+ @main_url = attributes[:main_url] ? attributes[:main_url].gsub(/\/$/, '') : nil
199
+ @created_at = attributes[:created_at]
200
+ end
201
+
202
+ # Gives the supplied access for the supplied user, for the current site.
203
+ #
204
+ # * <tt>access</tt> can be one of <tt>:view</tt>, <tt>:admin</tt> or <tt>:noaccess</tt>
205
+ # * <tt>login</tt> is the user login on Piwik
206
+ #
207
+ # Equivalent Piwik API call: UsersManager.setUserAccess (userLogin, access, idSites)
208
+ def give_access_to(access, login)
209
+ raise UnknownSite, "Site not existent in Piwik yet, call 'save' first" if new?
210
+ xml = call('UsersManager.setUserAccess', :idSites => id, :access => access.to_s, :userLogin => login.to_s)
211
+ result = XmlSimple.xml_in(xml, {'ForceArray' => false})
212
+ result['success'] ? true : false
213
+ end
214
+
215
+ # Calls the supplied Piwik API method, with the supplied parameters.
216
+ #
217
+ # Returns a string containing the XML reply from Piwik, or raises a
218
+ # <tt>Piwik::ApiError</tt> exception with the error message returned by Piwik
219
+ # in case it receives an error.
220
+ def self.call(method, params={}, piwik_url=nil, auth_token=nil)
221
+ raise MissingConfiguration, "Please edit ~/.piwik to include your piwik url and auth_key" if piwik_url.nil? || auth_token.nil?
222
+ url = "#{piwik_url}/?module=API&format=xml&method=#{method}"
223
+ url << "&token_auth=#{auth_token}" unless auth_token.nil?
224
+ params.each { |k, v| url << "&#{k}=#{CGI.escape(v.to_s)}" }
225
+ verbose_obj_save = $VERBOSE
226
+ $VERBOSE = nil # Suppress "warning: peer certificate won't be verified in this SSL session"
227
+ xml = RestClient.get(url)
228
+ $VERBOSE = verbose_obj_save
229
+ if xml =~ /error message=/
230
+ result = XmlSimple.xml_in(xml, {'ForceArray' => false})
231
+ raise ApiError, result['error']['message'] if result['error']
232
+ end
233
+ xml
234
+ end
235
+
236
+ # Returns a hash with the attributes of the supplied site, identified
237
+ # by it's Id in <tt>site_id</tt>.
238
+ #
239
+ # Equivalent Piwik API call: SitesManager.getSiteFromId (idSite)
240
+ def self.get_site_attributes_by_id(site_id, piwik_url, auth_token)
241
+ xml = call('SitesManager.getSiteFromId', {:idSite => site_id}, piwik_url, auth_token)
242
+ result = XmlSimple.xml_in(xml, {'ForceArray' => false})
243
+ attributes = {
244
+ :id => result['row']['idsite'].to_i,
245
+ :name => result['row']['name'],
246
+ :main_url => result['row']['main_url'],
247
+ :created_at => Time.parse(result['row']['ts_created']),
248
+ }
249
+ attributes
250
+ end
251
+ end
252
+ end