simple-piwik 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/LICENSE +20 -0
- data/README.rdoc +18 -0
- data/Rakefile +33 -0
- data/VERSION +1 -0
- data/lib/piwik/base.rb +94 -0
- data/lib/piwik/site.rb +216 -0
- data/lib/piwik/trackable.rb +79 -0
- data/lib/piwik/user.rb +132 -0
- data/lib/simple-piwik.rb +6 -0
- data/script/console +10 -0
- data/simple-piwik.gemspec +59 -0
- data/test/files/config/example_piwik.yml +4 -0
- data/test/simple-piwik_test.rb +69 -0
- data/test/test_helper.rb +16 -0
- metadata +101 -0
data/.document
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 mihael
|
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.
|
data/README.rdoc
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
= simple-piwik
|
2
|
+
|
3
|
+
Description goes here.
|
4
|
+
|
5
|
+
== Note on Patches/Pull Requests
|
6
|
+
|
7
|
+
* Fork the project.
|
8
|
+
* Make your feature addition or bug fix.
|
9
|
+
* Add tests for it. This is important so I don't break it in a
|
10
|
+
future version unintentionally.
|
11
|
+
* Commit, do not mess with rakefile, version, or history.
|
12
|
+
(if you want to have your own version, that is fine but
|
13
|
+
bump version in a commit by itself I can ignore when I pull)
|
14
|
+
* Send me a pull request. Bonus points for topic branches.
|
15
|
+
|
16
|
+
== Copyright
|
17
|
+
|
18
|
+
Copyright (c) 2011 mihael. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "simple-piwik"
|
8
|
+
gem.summary = %Q{A ruby client for the Piwik API.}
|
9
|
+
gem.description = %Q{Provides simple access to the Piwik API.}
|
10
|
+
gem.email = "mihael.ploh@gmail.com"
|
11
|
+
gem.homepage = "http://github.com/mihael/simple-piwik"
|
12
|
+
gem.authors = ["mihael"]
|
13
|
+
gem.add_dependency "activesupport", ">= 3.0.9"
|
14
|
+
gem.add_dependency "rest-client", ">= 1.6.1"
|
15
|
+
gem.add_dependency "json", ">= 1.4.6"
|
16
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
17
|
+
end
|
18
|
+
rescue LoadError
|
19
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
20
|
+
end
|
21
|
+
|
22
|
+
require 'rake/testtask'
|
23
|
+
Rake::TestTask.new(:test) do |test|
|
24
|
+
test.libs << 'lib' << 'test'
|
25
|
+
test.pattern = 'test/**/*_test.rb'
|
26
|
+
test.verbose = true
|
27
|
+
end
|
28
|
+
|
29
|
+
task :test => :check_dependencies
|
30
|
+
|
31
|
+
task :default => :test
|
32
|
+
|
33
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.5.0
|
data/lib/piwik/base.rb
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
#require 'rubygems'
|
2
|
+
#require 'cgi'
|
3
|
+
require 'active_support/all'
|
4
|
+
require 'json/ext'
|
5
|
+
require 'rest_client'
|
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
|
+
def self.on_rails?
|
27
|
+
(defined?(::Rails) && ::Rails.respond_to?(:root)) || (defined?(RAILS_ROOT) && RAILS_ROOT!=nil)
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.config_file
|
31
|
+
if defined?(::Rails) && ::Rails.respond_to?(:root)
|
32
|
+
File.join(::Rails.root, 'config', 'piwik.yml')
|
33
|
+
elsif defined?(RAILS_ROOT) && RAILS_ROOT!=nil
|
34
|
+
File.join(RAILS_ROOT, 'config', 'piwik.yml')
|
35
|
+
else
|
36
|
+
File.join( ENV['HOME'] || ENV['USERPROFILE'] || ENV['HOMEPATH'] || ".", '.piwik' )
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.parse_json json
|
41
|
+
JSON.parse json
|
42
|
+
end
|
43
|
+
|
44
|
+
def parse_json json
|
45
|
+
self.class.parse_json json
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
# Calls the supplied Piwik API method, with the supplied parameters.
|
50
|
+
#
|
51
|
+
# Returns a string containing the XML reply from Piwik, or raises a
|
52
|
+
# <tt>Piwik::ApiError</tt> exception with the error message returned by Piwik
|
53
|
+
# in case it receives an error.
|
54
|
+
def call(method, params={})
|
55
|
+
self.class.call(method, params, config[:piwik_url], config[:auth_token])
|
56
|
+
end
|
57
|
+
|
58
|
+
# Calls the supplied Piwik API method, with the supplied parameters.
|
59
|
+
#
|
60
|
+
# Returns the object parsed from JSON reply from Piwik, or raises a
|
61
|
+
# <tt>Piwik::ApiError</tt> exception with the error message returned by Piwik
|
62
|
+
# in case it receives an error.
|
63
|
+
def self.call(method, params={}, piwik_url=nil, auth_token=nil)
|
64
|
+
raise MissingConfiguration, "Please edit ~/.piwik to include your piwik url and auth_key" if piwik_url.nil? || auth_token.nil?
|
65
|
+
url = "#{piwik_url}/?module=API&format=json&method=#{method}"
|
66
|
+
url << "&token_auth=#{auth_token}" unless auth_token.nil?
|
67
|
+
params.each { |k, v| url << "&#{k}=#{CGI.escape(v.to_s)}" }
|
68
|
+
verbose_obj_save = $VERBOSE
|
69
|
+
$VERBOSE = nil # Suppress "warning: peer certificate won't be verified in this SSL session"
|
70
|
+
json = RestClient.get(url)
|
71
|
+
$VERBOSE = verbose_obj_save
|
72
|
+
result = self.parse_json json
|
73
|
+
if json =~ /error message=/
|
74
|
+
raise ApiError, result['error']['message'] if result['error']
|
75
|
+
end
|
76
|
+
result
|
77
|
+
end
|
78
|
+
|
79
|
+
# Checks for the config, creates it if not found
|
80
|
+
def self.load_config_from_file
|
81
|
+
config = {}
|
82
|
+
config_file = self.config_file
|
83
|
+
temp_config = if File.exists?(config_file)
|
84
|
+
YAML::load(open(config_file))
|
85
|
+
else
|
86
|
+
open(config_file,'w') { |f| f.puts @@template }
|
87
|
+
YAML::load(@@template)
|
88
|
+
end
|
89
|
+
temp_config.each { |k,v| config[k.to_sym] = v } if temp_config
|
90
|
+
raise MissingConfiguration, "Please edit #{config_file} to include piwik url and auth_key" if config[:piwik_url] == nil || config[:auth_token] == nil
|
91
|
+
config
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
data/lib/piwik/site.rb
ADDED
@@ -0,0 +1,216 @@
|
|
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> or <tt>RAILS_ROOT/config/piwik.yml</tt>
|
11
|
+
# (and create the file with an empty template if it 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
|
+
result = call('SitesManager.addSite', :siteName => name, :urls => main_url)
|
66
|
+
@id = result['value'].to_i
|
67
|
+
@created_at = Time.current
|
68
|
+
id && id > 0 ? true : false
|
69
|
+
end
|
70
|
+
|
71
|
+
# Saves the current site in Piwik, updating it's data.
|
72
|
+
#
|
73
|
+
# Equivalent Piwik API call: SitesManager.updateSite (idSite, siteName, urls)
|
74
|
+
def update
|
75
|
+
raise UnknownSite, "Site not existent in Piwik yet, call 'save' first" if new?
|
76
|
+
raise ArgumentError, "Name can not be blank" if name.blank?
|
77
|
+
raise ArgumentError, "Main URL can not be blank" if main_url.blank?
|
78
|
+
result = call('SitesManager.updateSite', :idSite => id, :siteName => name, :urls => main_url)
|
79
|
+
result['result'] == 'success' ? true : false
|
80
|
+
end
|
81
|
+
|
82
|
+
def reload
|
83
|
+
#TODO
|
84
|
+
end
|
85
|
+
|
86
|
+
# Deletes the current site from Piwik.
|
87
|
+
#
|
88
|
+
# Equivalent Piwik API call: SitesManager.deleteSite (idSite)
|
89
|
+
def destroy
|
90
|
+
raise UnknownSite, "Site not existent in Piwik yet, call 'save' first" if new?
|
91
|
+
result = call('SitesManager.deleteSite', :idSite => id)
|
92
|
+
#puts "\n destroy #{result} \n"
|
93
|
+
freeze
|
94
|
+
result['result'] == 'success' ? true : false
|
95
|
+
end
|
96
|
+
|
97
|
+
# Gives read access (<tt>'view'</tt>) to the supplied user login for the current
|
98
|
+
# site.
|
99
|
+
def give_view_access_to(login)
|
100
|
+
give_access_to(:view, login)
|
101
|
+
end
|
102
|
+
|
103
|
+
# Gives read and write access (<tt>'admin'</tt>) for the supplied user login for the
|
104
|
+
# current site.
|
105
|
+
def give_admin_access_to(login)
|
106
|
+
give_access_to(:admin, login)
|
107
|
+
end
|
108
|
+
|
109
|
+
# Removes all access (gives an <tt>'noaccess'</tt>) for the supplied user login for
|
110
|
+
# the current site.
|
111
|
+
def give_no_access_to(login)
|
112
|
+
give_access_to(:noaccess, login)
|
113
|
+
end
|
114
|
+
alias_method :remove_access_from, :give_no_access_to
|
115
|
+
|
116
|
+
# Returns a hash with a summary of access information for the current site
|
117
|
+
# (visits, unique visitors, actions / pageviews, maximum actions per visit,
|
118
|
+
# bounces and total time spent in all visits in seconds), filtered by the
|
119
|
+
# supplied period and date.
|
120
|
+
#
|
121
|
+
# * <tt>period</tt> should be one of <tt>:day</tt>, <tt>:week</tt>, <tt>:month</tt> or <tt>:year</tt> (default: <tt>:day</tt>)
|
122
|
+
# * <tt>date</tt> should be a <tt>Date</tt> object (default: <tt>Date.today</tt>)
|
123
|
+
#
|
124
|
+
# Equivalent Piwik API call: VisitsSummary.get (idSite, period, date)
|
125
|
+
def summary(period=:day, date=Date.today)
|
126
|
+
raise UnknownSite, "Site not existent in Piwik yet, call 'save' first" if new?
|
127
|
+
result = call('VisitsSummary.get', :idSite => id, :period => period, :date => date)
|
128
|
+
{
|
129
|
+
:visits => result['nb_visits'].to_i,
|
130
|
+
:unique_visitors => result['nb_uniq_visitors'].to_i,
|
131
|
+
:actions => result['nb_actions'].to_i,
|
132
|
+
:max_actions_per_visit => result['max_actions'].to_i,
|
133
|
+
:bounces => result['bounce_count'].to_i,
|
134
|
+
:total_time_spent => result['sum_visit_length'].to_i, # in seconds
|
135
|
+
}
|
136
|
+
end
|
137
|
+
|
138
|
+
# Returns the amount of visits for the current site, filtered by the
|
139
|
+
# supplied period and date.
|
140
|
+
#
|
141
|
+
# * <tt>period</tt> should be one of <tt>:day</tt>, <tt>:week</tt>, <tt>:month</tt> or <tt>:year</tt> (default: <tt>:day</tt>)
|
142
|
+
# * <tt>date</tt> should be a <tt>Date</tt> object (default: <tt>Date.today</tt>)
|
143
|
+
#
|
144
|
+
# Equivalent Piwik API call: VisitsSummary.getVisits (idSite, period, date)
|
145
|
+
def visits(period=:day, date=Date.today)
|
146
|
+
raise UnknownSite, "Site not existent in Piwik yet, call 'save' first" if new?
|
147
|
+
result = call('VisitsSummary.getVisits', :idSite => id, :period => period, :date => date)
|
148
|
+
result.to_i
|
149
|
+
end
|
150
|
+
|
151
|
+
# Returns the amount of unique visitors for the current site, filtered by
|
152
|
+
# the supplied period and date.
|
153
|
+
#
|
154
|
+
# * <tt>period</tt> should be one of <tt>:day</tt>, <tt>:week</tt>, <tt>:month</tt> or <tt>:year</tt> (default: <tt>:day</tt>)
|
155
|
+
# * <tt>date</tt> should be a <tt>Date</tt> object (default: <tt>Date.today</tt>)
|
156
|
+
#
|
157
|
+
# Equivalent Piwik API call: VisitsSummary.getUniqueVisitors (idSite, period, date)
|
158
|
+
def unique_visitors(period=:day, date=Date.today)
|
159
|
+
raise UnknownSite, "Site not existent in Piwik yet, call 'save' first" if new?
|
160
|
+
result = call('VisitsSummary.getUniqueVisitors', :idSite => id, :period => period, :date => date)
|
161
|
+
result.to_i
|
162
|
+
end
|
163
|
+
|
164
|
+
# Returns the amount of actions (pageviews) for the current site, filtered
|
165
|
+
# by the supplied period and date.
|
166
|
+
#
|
167
|
+
# * <tt>period</tt> should be one of <tt>:day</tt>, <tt>:week</tt>, <tt>:month</tt> or <tt>:year</tt> (default: <tt>:day</tt>)
|
168
|
+
# * <tt>date</tt> should be a <tt>Date</tt> object (default: <tt>Date.today</tt>)
|
169
|
+
#
|
170
|
+
# Equivalent Piwik API call: VisitsSummary.getActions (idSite, period, date)
|
171
|
+
def actions(period=:day, date=Date.today)
|
172
|
+
raise UnknownSite, "Site not existent in Piwik yet, call 'save' first" if new?
|
173
|
+
result = call('VisitsSummary.getActions', :idSite => id, :period => period, :date => date)
|
174
|
+
result.to_i
|
175
|
+
end
|
176
|
+
alias_method :pageviews, :actions
|
177
|
+
|
178
|
+
private
|
179
|
+
# Loads the attributes in the instance variables.
|
180
|
+
def load_attributes(attributes)
|
181
|
+
@id = attributes[:id]
|
182
|
+
@name = attributes[:name]
|
183
|
+
@main_url = attributes[:main_url] ? attributes[:main_url].gsub(/\/$/, '') : nil
|
184
|
+
@created_at = attributes[:created_at]
|
185
|
+
end
|
186
|
+
|
187
|
+
# Gives the supplied access for the supplied user, for the current site.
|
188
|
+
#
|
189
|
+
# * <tt>access</tt> can be one of <tt>:view</tt>, <tt>:admin</tt> or <tt>:noaccess</tt>
|
190
|
+
# * <tt>login</tt> is the user login on Piwik
|
191
|
+
#
|
192
|
+
# Equivalent Piwik API call: UsersManager.setUserAccess (userLogin, access, idSites)
|
193
|
+
def give_access_to(access, login)
|
194
|
+
raise UnknownSite, "Site not existent in Piwik yet, call 'save' first" if new?
|
195
|
+
result = call('UsersManager.setUserAccess', :idSites => id, :access => access.to_s, :userLogin => login.to_s)
|
196
|
+
#result['success'] ? true : false
|
197
|
+
result['result'] == 'success' ? true : false
|
198
|
+
end
|
199
|
+
|
200
|
+
# Returns a hash with the attributes of the supplied site, identified
|
201
|
+
# by it's Id in <tt>site_id</tt>.
|
202
|
+
#
|
203
|
+
# Equivalent Piwik API call: SitesManager.getSiteFromId (idSite)
|
204
|
+
def self.get_site_attributes_by_id(site_id, piwik_url, auth_token)
|
205
|
+
result = call('SitesManager.getSiteFromId', {:idSite => site_id}, piwik_url, auth_token)
|
206
|
+
#puts "get_site_attributes_by_id #{result.to_s}"
|
207
|
+
attributes = {
|
208
|
+
:id => result[0]['idsite'].to_i,
|
209
|
+
:name => result[0]['name'],
|
210
|
+
:main_url => result[0]['main_url'],
|
211
|
+
:created_at => Time.parse(result[0]['ts_created'])
|
212
|
+
}
|
213
|
+
attributes
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module Piwik
|
2
|
+
module Trackable
|
3
|
+
def piwik_tracking_js
|
4
|
+
if Config.use_async
|
5
|
+
<<-code
|
6
|
+
<!-- Piwik -->
|
7
|
+
<script type="text/javascript">
|
8
|
+
var _paq = _paq || [];
|
9
|
+
(function(){
|
10
|
+
var u=(("https:" == document.location.protocol) ? "#{Config.url.sub("http:","https:")}/" : "#{Config.url}/");
|
11
|
+
_paq.push(['setSiteId', #{@site.piwik_id}]);
|
12
|
+
_paq.push(['setTrackerUrl', u+'piwik.php']);
|
13
|
+
_paq.push(['trackPageView']);
|
14
|
+
var d=document,
|
15
|
+
g=d.createElement('script'),
|
16
|
+
s=d.getElementsByTagName('script')[0];
|
17
|
+
g.type='text/javascript';
|
18
|
+
g.defer=true;
|
19
|
+
g.async=true;
|
20
|
+
g.src=u+'piwik.js';
|
21
|
+
s.parentNode.insertBefore(g,s);
|
22
|
+
})();
|
23
|
+
</script>
|
24
|
+
<!-- End Piwik Tag -->
|
25
|
+
code
|
26
|
+
else
|
27
|
+
<<-code
|
28
|
+
<!-- Piwik -->
|
29
|
+
<script type="text/javascript">
|
30
|
+
var pkBaseURL = (("https:" == document.location.protocol) ? "#{Config.url.sub("http:","https:")}/" : "#{Config.url}/");
|
31
|
+
document.write(unescape("%3Cscript src='" + pkBaseURL + "piwik.js' type='text/javascript'%3E%3C/script%3E"));
|
32
|
+
</script><script type="text/javascript">
|
33
|
+
try {
|
34
|
+
var piwikTracker = Piwik.getTracker(pkBaseURL + "piwik.php", #{@site.piwik_id});
|
35
|
+
piwikTracker.trackPageView();
|
36
|
+
piwikTracker.enableLinkTracking();
|
37
|
+
} catch( err ) {}
|
38
|
+
</script>
|
39
|
+
<!-- End Piwik Tag -->
|
40
|
+
code
|
41
|
+
end
|
42
|
+
rescue NoMethodError
|
43
|
+
# ignore
|
44
|
+
end
|
45
|
+
|
46
|
+
def add_piwik_analytics_tracking
|
47
|
+
if Config.use_async
|
48
|
+
self.response.body = response.body.sub!(/<\/[hH][eE][aA][dD]>/, "#{piwik_tracking_js}</head>") if response.body.respond_to?(:sub!)
|
49
|
+
else
|
50
|
+
self.response.body = response.body.sub!(/<\/[bB][oO][dD][yY]>/, "#{piwik_tracking_js}</body>") if response.body.respond_to?(:sub!)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class Config
|
56
|
+
|
57
|
+
@@use_async = false
|
58
|
+
cattr_accessor :use_async
|
59
|
+
|
60
|
+
@@url = Piwik::Base.load_config_from_file[:piwik_url]
|
61
|
+
cattr_accessor :url
|
62
|
+
|
63
|
+
@@environments = ["production","development"]
|
64
|
+
cattr_accessor :environments
|
65
|
+
|
66
|
+
@@formats = [:html, :all]
|
67
|
+
cattr_accessor :formats
|
68
|
+
|
69
|
+
=begin rdoc
|
70
|
+
Checks whether the model can be tracked using piwik by checking for a piwik_id and domain fields.
|
71
|
+
This is a pretty specific use case, a more generic application tracking solution is available here:
|
72
|
+
https://github.com/Achillefs/piwik_analytics/ (this file is actually swiped from that plugin)
|
73
|
+
=end
|
74
|
+
def self.enabled?(format)
|
75
|
+
raise Piwik::MissingConfiguration if url.blank?
|
76
|
+
environments.include?(Rails.env) && formats.include?(format.to_sym)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
data/lib/piwik/user.rb
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
module Piwik
|
2
|
+
class User < Piwik::Base
|
3
|
+
attr_accessor :login, :password, :email, :user_alias
|
4
|
+
attr_reader :created_at, :config
|
5
|
+
|
6
|
+
# Initializes a new <tt>Piwik::User</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> or <tt>RAILS_ROOT/config/piwik.yml</tt>
|
11
|
+
# (and create the file with an empty template if it doesn't exists).
|
12
|
+
#
|
13
|
+
# Valid (and required) attributes are:
|
14
|
+
# * <tt>:login</tt> - the user login
|
15
|
+
# * <tt>:password</tt> - the user password
|
16
|
+
# * <tt>:email</tt> - the user email
|
17
|
+
# * <tt>:alias</tt> - the user alias
|
18
|
+
def initialize(attributes={}, piwik_url=nil, auth_token=nil)
|
19
|
+
raise ArgumentError, "expected an attributes Hash, got #{attributes.inspect}" unless attributes.is_a?(Hash)
|
20
|
+
@config = if piwik_url.nil? || auth_token.nil?
|
21
|
+
self.class.load_config_from_file
|
22
|
+
else
|
23
|
+
{:piwik_url => piwik_url, :auth_token => auth_token}
|
24
|
+
end
|
25
|
+
load_attributes(attributes)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns <tt>true</tt> if the current site does not exists in the Piwik yet.
|
29
|
+
def new?
|
30
|
+
created_at.nil? or created_at.blank?
|
31
|
+
end
|
32
|
+
|
33
|
+
# Saves the current user in Piwik.
|
34
|
+
#
|
35
|
+
# Calls <tt>create</tt> it it's a new user, <tt>update</tt> otherwise.
|
36
|
+
def save
|
37
|
+
new? ? create : update
|
38
|
+
end
|
39
|
+
|
40
|
+
# Saves the current new user in Piwik.
|
41
|
+
#
|
42
|
+
# Equivalent Piwik API call: UsersManager.addUser (userLogin, password, email, alias)
|
43
|
+
def create
|
44
|
+
raise ArgumentError, "User already exists in Piwik, call 'update' instead" unless new?
|
45
|
+
raise ArgumentError, "Login can not be blank" if login.blank?
|
46
|
+
raise ArgumentError, "Password can not be blank" if password.blank?
|
47
|
+
raise ArgumentError, "Email can not be blank" if email.blank?
|
48
|
+
user_alias = login if user_alias.blank?
|
49
|
+
|
50
|
+
result = call('UsersManager.addUser', :userLogin => login, :password => password, :email => email, :alias => user_alias)
|
51
|
+
@created_at = Time.current
|
52
|
+
#puts "\n create #{result} \n"
|
53
|
+
|
54
|
+
if result["result"]
|
55
|
+
result['message'] == 'ok' ? true : false
|
56
|
+
else
|
57
|
+
false
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Saves the current user in Piwik, updating it's data.
|
62
|
+
#
|
63
|
+
# Equivalent Piwik API call: UsersManager.updateUser (userLogin, password, email, alias)
|
64
|
+
def update
|
65
|
+
raise UnknownUser, "User not existent in Piwik yet, call 'save' first" if new?
|
66
|
+
raise ArgumentError, "Login can not be blank" if login.blank?
|
67
|
+
raise ArgumentError, "Password can not be blank" if password.blank?
|
68
|
+
raise ArgumentError, "Email can not be blank" if email.blank?
|
69
|
+
user_alias = login if user_alias.blank?
|
70
|
+
|
71
|
+
result = call('UsersManager.updateUser', :userLogin => login, :password => password, :email => email, :alias => user_alias)
|
72
|
+
result['result'] == 'success' ? true : false
|
73
|
+
end
|
74
|
+
|
75
|
+
# Deletes the current user from Piwik.
|
76
|
+
#
|
77
|
+
# Equivalent Piwik API call: UsersManager.deleteUser (userLogin)
|
78
|
+
def destroy
|
79
|
+
raise UnknownUser, "User not existent in Piwik yet, call 'save' first" if new?
|
80
|
+
result = call('UsersManager.deleteUser', :userLogin => login)
|
81
|
+
freeze
|
82
|
+
result['result'] == 'success' ? true : false
|
83
|
+
end
|
84
|
+
|
85
|
+
# Returns an instance of <tt>Piwik::User</tt> representing the user identified by
|
86
|
+
# the supplied <tt>userLogin</tt>. Raises a <tt>Piwik::ApiError</tt> if the user doesn't
|
87
|
+
# exists or if the user associated with the supplied auth_token does not
|
88
|
+
# have 'admin' access.
|
89
|
+
#
|
90
|
+
# You can pass the URL for your Piwik install and an authorization token as
|
91
|
+
# the second and third parameters. If you don't, than it will try to find
|
92
|
+
# them in a <tt>'~/.piwik'</tt> or <tt>RAILS_ROOT/config/piwik.yml</tt>
|
93
|
+
# (and create the file with an empty template if it doesn't exists).
|
94
|
+
def self.load(user_login, piwik_url=nil, auth_token=nil)
|
95
|
+
raise ArgumentError, "expected a user Login" if user_login.nil?
|
96
|
+
@config = if piwik_url.nil? || auth_token.nil?
|
97
|
+
load_config_from_file
|
98
|
+
else
|
99
|
+
{:piwik_url => piwik_url, :auth_token => auth_token}
|
100
|
+
end
|
101
|
+
attributes = get_user_attributes_by_login(user_login, @config[:piwik_url], @config[:auth_token])
|
102
|
+
new(attributes, @config[:piwik_url], @config[:auth_token])
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
# Loads the attributes in the instance variables.
|
107
|
+
def load_attributes(attributes)
|
108
|
+
@login = attributes[:login]
|
109
|
+
@password = attributes[:password]
|
110
|
+
@email = attributes[:email]
|
111
|
+
@user_alias = attributes[:user_alias]
|
112
|
+
@created_at = attributes[:created_at]
|
113
|
+
end
|
114
|
+
|
115
|
+
# Returns a hash with the attributes of the supplied user, identified
|
116
|
+
# by it's Login in <tt>user_login</tt>.
|
117
|
+
#
|
118
|
+
# Equivalent Piwik API call: UsersManager.getUser (userLogin)
|
119
|
+
def self.get_user_attributes_by_login(user_login, piwik_url, auth_token)
|
120
|
+
result = call('UsersManager.getUser', {:userLogin => user_login}, piwik_url, auth_token)
|
121
|
+
#puts "\n get_user_attributes_by_login #{result} \n"
|
122
|
+
attributes = {
|
123
|
+
:login => result[0]['login'],
|
124
|
+
:user_alias => result[0]['alias'],
|
125
|
+
:email => result[0]['email'],
|
126
|
+
:password => result[0]['password'],
|
127
|
+
:created_at => Time.parse(result[0]['date_registered'])
|
128
|
+
}
|
129
|
+
attributes
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
data/lib/simple-piwik.rb
ADDED
data/script/console
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# File: script/console
|
3
|
+
irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
|
4
|
+
|
5
|
+
libs = " -r irb/completion"
|
6
|
+
# Perhaps use a console_lib to store any extra methods I may want available in the cosole
|
7
|
+
# libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
|
8
|
+
libs << " -r #{File.dirname(__FILE__) + '/../lib/piwik.rb'}"
|
9
|
+
puts "Loading piwik gem"
|
10
|
+
exec "#{irb} #{libs} --simple-prompt"
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{simple-piwik}
|
8
|
+
s.version = "0.5.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = [%q{mihael}]
|
12
|
+
s.date = %q{2011-08-03}
|
13
|
+
s.description = %q{Provides simple access to the Piwik API.}
|
14
|
+
s.email = %q{mihael.ploh@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
"LICENSE",
|
22
|
+
"README.rdoc",
|
23
|
+
"Rakefile",
|
24
|
+
"VERSION",
|
25
|
+
"lib/piwik/base.rb",
|
26
|
+
"lib/piwik/site.rb",
|
27
|
+
"lib/piwik/trackable.rb",
|
28
|
+
"lib/piwik/user.rb",
|
29
|
+
"lib/simple-piwik.rb",
|
30
|
+
"script/console",
|
31
|
+
"simple-piwik.gemspec",
|
32
|
+
"test/files/config/example_piwik.yml",
|
33
|
+
"test/simple-piwik_test.rb",
|
34
|
+
"test/test_helper.rb"
|
35
|
+
]
|
36
|
+
s.homepage = %q{http://github.com/mihael/simple-piwik}
|
37
|
+
s.require_paths = [%q{lib}]
|
38
|
+
s.rubygems_version = %q{1.8.6}
|
39
|
+
s.summary = %q{A ruby client for the Piwik API.}
|
40
|
+
|
41
|
+
if s.respond_to? :specification_version then
|
42
|
+
s.specification_version = 3
|
43
|
+
|
44
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
45
|
+
s.add_runtime_dependency(%q<activesupport>, [">= 3.0.9"])
|
46
|
+
s.add_runtime_dependency(%q<rest-client>, [">= 1.6.1"])
|
47
|
+
s.add_runtime_dependency(%q<json>, [">= 1.4.6"])
|
48
|
+
else
|
49
|
+
s.add_dependency(%q<activesupport>, [">= 3.0.9"])
|
50
|
+
s.add_dependency(%q<rest-client>, [">= 1.6.1"])
|
51
|
+
s.add_dependency(%q<json>, [">= 1.4.6"])
|
52
|
+
end
|
53
|
+
else
|
54
|
+
s.add_dependency(%q<activesupport>, [">= 3.0.9"])
|
55
|
+
s.add_dependency(%q<rest-client>, [">= 1.6.1"])
|
56
|
+
s.add_dependency(%q<json>, [">= 1.4.6"])
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
@@ -0,0 +1,69 @@
|
|
1
|
+
#require File.join(File.expand_path(File.dirname(__FILE__)),"test_helper")
|
2
|
+
require 'test_helper'
|
3
|
+
|
4
|
+
class PiwikTest < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
@domain = "http://test.local"
|
7
|
+
@name = "Test Site"
|
8
|
+
@site = Piwik::Site.new(:name => @name, :main_url => @domain)
|
9
|
+
@login = "test_user"
|
10
|
+
@password = "changeme"
|
11
|
+
@email = "test@pwave.com"
|
12
|
+
@user_alias = "Test User"
|
13
|
+
@user = Piwik::User.new(:login => @login, :password => @password, :email => @email, :user_alias => @user_alias)
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_can_instantiate_site
|
17
|
+
assert_equal @name, @site.name
|
18
|
+
assert_equal @domain, @site.main_url
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_can_save_load_update_and_destroy_site
|
22
|
+
assert_equal nil, @site.id
|
23
|
+
@site.save
|
24
|
+
assert_not_equal 0, @site.id
|
25
|
+
assert_not_equal nil, @site.id
|
26
|
+
reloaded = Piwik::Site.load(@site.id)
|
27
|
+
assert_equal reloaded.id, @site.id
|
28
|
+
reloaded.name = "Changed Name"
|
29
|
+
reloaded.update
|
30
|
+
reloaded = Piwik::Site.load(@site.id)
|
31
|
+
assert_equal "Changed Name", reloaded.name
|
32
|
+
assert_equal true, reloaded.destroy
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_can_instantiate_user
|
36
|
+
assert_equal @login, @user.login
|
37
|
+
assert_equal @password, @user.password
|
38
|
+
assert_equal @email, @user.email
|
39
|
+
assert_equal @user_alias, @user.user_alias
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_can_save_load_update_and_destroy_user
|
43
|
+
@user.save
|
44
|
+
reloaded = Piwik::User.load(@user.login)
|
45
|
+
assert_equal reloaded.login, @user.login
|
46
|
+
reloaded.email = "changed@mail.com"
|
47
|
+
reloaded.password = "changeme"
|
48
|
+
reloaded.update
|
49
|
+
reloaded = Piwik::User.load(@user.login)
|
50
|
+
assert_equal"changed@mail.com", reloaded.email
|
51
|
+
assert_equal true, @user.destroy
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_can_read_standalone_config
|
55
|
+
File.open(File.join(ENV["HOME"],".piwik"), "w") { p.puts(File.read("./files/config/piwik/yml")) } unless File.join(ENV["HOME"],".piwik")
|
56
|
+
assert_nothing_raised do
|
57
|
+
Piwik::Base.load_config_from_file
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
def test_can_read_rails_config
|
63
|
+
stub_rails_env do
|
64
|
+
assert_nothing_raised do
|
65
|
+
Piwik::Base.load_config_from_file
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
#require 'stringio'
|
4
|
+
#require 'open-uri'
|
5
|
+
#require 'shoulda'
|
6
|
+
|
7
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
8
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
9
|
+
require 'simple-piwik'
|
10
|
+
|
11
|
+
class Test::Unit::TestCase
|
12
|
+
def stub_rails_env &block
|
13
|
+
Object.const_set("RAILS_ROOT", File.join(File.dirname(__FILE__),"files"))
|
14
|
+
yield
|
15
|
+
end
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: simple-piwik
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.5.0
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- mihael
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-08-03 00:00:00 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: activesupport
|
17
|
+
prerelease: false
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 3.0.9
|
24
|
+
type: :runtime
|
25
|
+
version_requirements: *id001
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: rest-client
|
28
|
+
prerelease: false
|
29
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 1.6.1
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id002
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: json
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 1.4.6
|
46
|
+
type: :runtime
|
47
|
+
version_requirements: *id003
|
48
|
+
description: Provides simple access to the Piwik API.
|
49
|
+
email: mihael.ploh@gmail.com
|
50
|
+
executables: []
|
51
|
+
|
52
|
+
extensions: []
|
53
|
+
|
54
|
+
extra_rdoc_files:
|
55
|
+
- LICENSE
|
56
|
+
- README.rdoc
|
57
|
+
files:
|
58
|
+
- .document
|
59
|
+
- LICENSE
|
60
|
+
- README.rdoc
|
61
|
+
- Rakefile
|
62
|
+
- VERSION
|
63
|
+
- lib/piwik/base.rb
|
64
|
+
- lib/piwik/site.rb
|
65
|
+
- lib/piwik/trackable.rb
|
66
|
+
- lib/piwik/user.rb
|
67
|
+
- lib/simple-piwik.rb
|
68
|
+
- script/console
|
69
|
+
- simple-piwik.gemspec
|
70
|
+
- test/files/config/example_piwik.yml
|
71
|
+
- test/simple-piwik_test.rb
|
72
|
+
- test/test_helper.rb
|
73
|
+
homepage: http://github.com/mihael/simple-piwik
|
74
|
+
licenses: []
|
75
|
+
|
76
|
+
post_install_message:
|
77
|
+
rdoc_options: []
|
78
|
+
|
79
|
+
require_paths:
|
80
|
+
- lib
|
81
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
82
|
+
none: false
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: "0"
|
87
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
|
+
none: false
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: "0"
|
93
|
+
requirements: []
|
94
|
+
|
95
|
+
rubyforge_project:
|
96
|
+
rubygems_version: 1.8.6
|
97
|
+
signing_key:
|
98
|
+
specification_version: 3
|
99
|
+
summary: A ruby client for the Piwik API.
|
100
|
+
test_files: []
|
101
|
+
|