Bug 11926: URI-encode data sent to statistics server
[koha.git] / C4 / UsageStats.pm
1 package UsageStats;
2
3 # Copyright 2000-2003 Katipo Communications
4 # Copyright 2010 BibLibre
5 # Parts Copyright 2010 Catalyst IT
6 #
7 # This file is part of Koha.
8 #
9 # Koha is free software; you can redistribute it and/or modify it under the
10 # terms of the GNU General Public License as published by the Free Software
11 # Foundation; either version 2 of the License, or (at your option) any later
12 # version.
13 #
14 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
15 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
17 #
18 # You should have received a copy of the GNU General Public License along
19 # with Koha; if not, write to the Free Software Foundation, Inc.,
20 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
22 use strict;
23 use C4::Context;
24 use POSIX qw(strftime);
25 use LWP::UserAgent;
26 use JSON;
27 use URI::Encode qw(uri_encode);
28
29 =head1 NAME C4::UsageStats
30
31 =head1 DESCRIPTION
32
33 This package contains what is needed to report Koha statistics to hea
34 hea.koha-community.org is the server that centralize Koha setups informations
35 Koha libraries are encouraged to provide informations about their collections,
36 their structure,...
37
38 This package is normally only called by a cronjob, like
39 0 3 1 * * export KOHA_CONF=/home/koha/etc/koha-conf.xml; export PERL5LIB=/home/koha/src; perl /home/koha/src/C4/UsageStats.pm
40
41 IMPORTANT : please do NOT run the cron on the 1st, but on another day. The idea is to avoid all
42 Koha libraries sending their data at the same time ! So choose any day between 1 and 28 !
43
44
45 =head2 NeedUpdate
46
47   $needUpdateYN = C4::UsageStats::NeedUpdate;
48
49 Returns Y (1) if the last update is more than 1 month old
50 This way, even if the cronjob is run every minute, the webservice will be called
51 only once a month !
52
53 =cut
54
55 sub NeedUpdate {
56     my $lastupdated = C4::Context->preference('UsageStatsLastUpdateTime') || 0;
57     my $now = strftime("%s", localtime);
58
59     # Need to launch cron.
60     return 1 if $now - $lastupdated >= 2592000;
61
62     # Cron no need to be launched.
63     return 0;
64 }
65
66 =head2 LaunchCron
67
68   LaunchCron();
69
70 Compute results and send them to the centralized server
71
72 =cut
73
74 sub LaunchCron {
75     if (!C4::Context->preference('UsageStatsShare')) {
76       die ("UsageStats is not configured");
77     }
78     if (NeedUpdate) {
79         C4::Context->set_preference('UsageStatsLastUpdateTime', strftime("%s", localtime));
80         my $data = BuildReport();
81         ReportToCommunity($data);
82     }
83 }
84
85 =head2 Builreport
86
87   BuildReport();
88
89 retrieve some database volumety and systempreferences that will be sent to hea server
90
91 =cut
92
93 sub BuildReport {
94     my $report = {
95         'library' => {
96             'name' => C4::Context->preference('UsageStatsLibraryName'),
97             'id' => C4::Context->preference('UsageStatsID') || 0,
98         },
99     };
100
101     # Get database volumetry.
102     foreach (qw/biblio auth_header old_issues old_reserves borrowers aqorders subscription/) {
103         $report->{volumetry}{$_} = _count($_);
104     }
105
106     # Get systempreferences.
107     foreach (qw/ AcqCreateItem
108  AcqWarnOnDuplicateInvoice
109  AcqViewBaskets
110  BasketConfirmations
111  OrderPdfFormat
112  casAuthentication
113  casLogout
114  AllowPkiAuth
115  DebugLevel
116  delimiter
117  noItemTypeImages
118  virtualshelves
119  AutoLocation
120  IndependentBranches
121  SessionStorage
122  Persona
123  AuthDisplayHierarchy
124  AutoCreateAuthorities
125  BiblioAddsAuthorities
126  dontmerge
127  UseAuthoritiesForTracings
128  CatalogModuleRelink
129  hide_marc
130  IntranetBiblioDefaultView
131  LabelMARCView
132  OpacSuppression
133  SeparateHoldings
134  UseControlNumber
135  advancedMARCeditor
136  DefaultClassificationSource
137  EasyAnalyticalRecords
138  autoBarcode
139  item-level_itypes
140  marcflavour
141  PrefillItem
142  z3950NormalizeAuthor
143  SpineLabelAutoPrint
144  SpineLabelShowPrintOnBibDetails
145  BlockReturnOfWithdrawnItems
146  CalculateFinesOnReturn
147  AgeRestrictionOverride
148  AllFinesNeedOverride
149  AllowFineOverride
150  AllowItemsOnHoldCheckout
151  AllowNotForLoanOverride
152  AllowRenewalLimitOverride
153  AllowReturnToBranch
154  AllowTooManyOverride
155  AutomaticItemReturn
156  AutoRemoveOverduesRestrictions
157  CircControl
158  HomeOrHoldingBranch
159  HomeOrHoldingBranchReturn
160  InProcessingToShelvingCart
161  IssueLostItem
162  IssuingInProcess
163  ManInvInNoissuesCharge
164  OverduesBlockCirc
165  RenewalPeriodBase
166  RenewalSendNotice
167  RentalsInNoissuesCharge
168  ReturnBeforeExpiry
169  ReturnToShelvingCart
170  TransfersMaxDaysWarning
171  UseBranchTransferLimits
172  useDaysMode
173  UseTransportCostMatrix
174  UseCourseReserves
175  finesCalendar
176  FinesIncludeGracePeriod
177  finesMode
178  RefundLostItemFeeOnReturn
179  WhenLostChargeReplacementFee
180  WhenLostForgiveFine
181  AllowHoldDateInFuture
182  AllowHoldPolicyOverride
183  AllowHoldsOnDamagedItems
184  AllowHoldsOnPatronsPossessions
185  AllowOnShelfHolds
186  AutoResumeSuspendedHolds
187  canreservefromotherbranches
188  decreaseLoanHighHolds
189  DisplayMultiPlaceHold
190  emailLibrarianWhenHoldIsPlaced
191  ExpireReservesMaxPickUpDelay
192  OPACAllowHoldDateInFuture
193  OPACAllowUserToChooseBranch
194  ReservesControlBranch
195  ReservesNeedReturns
196  SuspendHoldsIntranet
197  SuspendHoldsOpac
198  TransferWhenCancelAllWaitingHolds
199  AllowAllMessageDeletion
200  AllowOfflineCirculation
201  CircAutocompl
202  CircAutoPrintQuickSlip
203  DisplayClearScreenButton
204  FilterBeforeOverdueReport
205  FineNotifyAtCheckin
206  itemBarcodeFallbackSearch
207  itemBarcodeInputFilter
208  previousIssuesDefaultSortOrder
209  RecordLocalUseOnReturn
210  soundon
211  SpecifyDueDate
212  todaysIssuesDefaultSortOrder
213  UpdateTotalIssuesOnCirc
214  UseTablesortForCirc
215  WaitingNotifyAtCheckin
216  AllowSelfCheckReturns
217  AutoSelfCheckAllowed
218  FRBRizeEditions
219  OPACFRBRizeEditions
220  AmazonCoverImages
221  OPACAmazonCoverImages
222  Babeltheque
223  BakerTaylorEnabled
224  GoogleJackets
225  HTML5MediaEnabled
226  IDreamBooksReadometer
227  IDreamBooksResults
228  IDreamBooksReviews
229  LibraryThingForLibrariesEnabled
230  LocalCoverImages
231  OPACLocalCoverImages
232  NovelistSelectEnabled
233  XISBN
234  OpenLibraryCovers
235  UseKohaPlugins
236  SyndeticsEnabled
237   TagsEnabled
238  CalendarFirstDayOfWeek
239  opaclanguagesdisplay
240  AuthoritiesLog
241  BorrowersLog
242  CataloguingLog
243  FinesLog
244  IssueLog
245  LetterLog
246  ReturnLog
247  SubscriptionLog
248  AuthorisedValueImages
249  BiblioDefaultView
250  COinSinOPACResults
251  DisplayOPACiconsXSLT
252  hidelostitems
253  HighlightOwnItemsOnOPAC
254  OpacAddMastheadLibraryPulldown
255  OPACDisplay856uAsImage
256  OpacHighlightedWords
257  OpacKohaUrl
258  OpacMaintenance
259  OpacPublic
260  OpacSeparateHoldings
261  OPACShowBarcode
262  OPACShowCheckoutName
263  OpacShowFiltersPulldownMobile
264  OPACShowHoldQueueDetails
265  OpacShowLibrariesPulldownMobile
266  OpacShowRecentComments
267  OPACShowUnusedAuthorities
268  OpacStarRatings
269  opacthemes
270  OPACURLOpenInNewWindow
271  OpacAuthorities
272  opacbookbag
273  OpacBrowser
274  OpacBrowseResults
275  OpacCloud
276  OPACFinesTab
277  OpacHoldNotes
278  OpacItemLocation
279  OpacPasswordChange
280  OPACPatronDetails
281  OPACpatronimages
282  OPACPopupAuthorsSearch
283  OpacTopissue
284  opacuserlogin
285  QuoteOfTheDay
286  RequestOnOpac
287  reviewson
288  ShowReviewer
289  ShowReviewerPhoto
290  SocialNetworks
291  suggestion
292  AllowPurchaseSuggestionBranchChoice
293  OpacAllowPublicListCreation
294  OpacAllowSharingPrivateLists
295  OPACItemHolds
296  OpacRenewalAllowed
297  OpacRenewalBranch
298  OPACViewOthersSuggestions
299  SearchMyLibraryFirst
300  singleBranchMode
301  AnonSuggestions
302  EnableOpacSearchHistory
303  OPACPrivacy
304  opacreadinghistory
305  TrackClicks
306  PatronSelfRegistration
307  OPACShelfBrowser
308  AddPatronLists
309  AutoEmailOpacUser
310  AutoEmailPrimaryAddress
311  autoMemberNum
312  BorrowerRenewalPeriodBase
313  checkdigit
314  EnableBorrowerFiles
315  EnhancedMessagingPreferences
316  ExtendedPatronAttributes
317  intranetreadinghistory
318  memberofinstitution
319  patronimages
320  TalkingTechItivaPhoneNotification
321  uppercasesurnames
322  IncludeSeeFromInSearches
323  OpacGroupResults
324  QueryAutoTruncate
325  QueryFuzzy
326  QueryStemming
327  QueryWeightFields
328  TraceCompleteSubfields
329  TraceSubjectSubdivisions
330  UseICU
331  UseQueryParser
332  defaultSortField
333  displayFacetCount
334  OPACdefaultSortField
335  OPACItemsResultsDisplay
336  expandedSearchOption
337  IntranetNumbersPreferPhrase
338  OPACNumbersPreferPhrase
339  opacSerialDefaultTab
340  RenewSerialAddsSuggestion
341  RoutingListAddReserves
342  RoutingSerials
343  SubscriptionHistory
344  Display856uAsImage
345  DisplayIconsXSLT
346  StaffAuthorisedValueImages
347  template
348  yuipath
349  HidePatronName
350  intranetbookbag
351  StaffDetailItemSelection
352  viewISBD
353  viewLabeledMARC
354  viewMARC
355  ILS-DI
356  OAI-PMH
357  version/) {
358         $report->{systempreferences}{$_} = C4::Context->preference($_);
359     }
360     return $report;
361 }
362
363 =head2 ReportToCommunity
364
365   ReportToCommunity;
366
367 Send to hea.koha-community.org database informations
368
369 =cut
370
371 sub ReportToCommunity {
372     my $data = shift;
373     my $json = uri_encode(to_json($data), 1);
374
375     my $ua = LWP::UserAgent->new;
376     my $req = HTTP::Request->new(POST => "http://hea.koha-community.org/upload.pl");
377     $req->content_type('application/x-www-form-urlencoded');
378     $req->content("data=$json");
379     my $res = $ua->request($req);
380     my $content = from_json($res->decoded_content);
381     C4::Context->set_preference('UsageStatsID', $content->{library}{library_id});
382 }
383
384 =head2 _count
385
386   $data = _count($table);
387
388 Count the number of records in $table tables
389
390 =cut
391
392 sub _count {
393     my $table = shift;
394
395     my $dbh = C4::Context->dbh;
396     my $sth = $dbh->prepare("SELECT count(*) from $table");
397     $sth->execute;
398     return $sth->fetchrow_array;
399 }
400
401 &LaunchCron;
402 1;