simple-piwik 0.5.0
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.
- 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
|
+
|