Open Monograph Press  3.3.0
UsageStatsPlugin.inc.php
1 <?php
2 
16 import('lib.pkp.classes.plugins.GenericPlugin');
17 
19 
22 
25 
27  var $_optedOut;
28 
31 
35  function __construct() {
36  parent::__construct();
37 
38  // The upgrade and install processes will need access
39  // to constants defined in that report plugin.
41  $applicationName = $application->getName();
42  switch ($applicationName) {
43  case 'ojs2':
44  import('plugins.generic.usageStats.OJSUsageStatsReportPlugin');
45  break;
46  case 'omp':
47  import('plugins.generic.usageStats.OMPUsageStatsReportPlugin');
48  break;
49  case 'ops':
50  import('plugins.generic.usageStats.OPSUsageStatsReportPlugin');
51  break;
52  }
53  }
54 
55 
56  //
57  // Public methods.
58  //
64  function getReportPlugin() {
66  $applicationName = $application->getName();
67  switch ($applicationName) {
68  case 'ojs2':
69  $this->import('OJSUsageStatsReportPlugin');
70  return new OJSUsageStatsReportPlugin();
71  case 'omp':
72  $this->import('OMPUsageStatsReportPlugin');
73  return new OMPUsageStatsReportPlugin();
74  case 'ops':
75  $this->import('OPSUsageStatsReportPlugin');
77  default:
78  assert(false);
79  }
80  }
81 
82 
83  //
84  // Implement methods from Plugin.
85  //
89  function register($category, $path, $mainContextId = null) {
90  $success = parent::register($category, $path, $mainContextId);
91 
92  HookRegistry::register('AcronPlugin::parseCronTab', array($this, 'callbackParseCronTab'));
93 
94  if ($this->getEnabled($mainContextId) && $success) {
95 
96  $this->_dataPrivacyOn = $this->getSetting(CONTEXT_ID_NONE, 'dataPrivacyOption');
97  $this->_saltpath = $this->getSetting(CONTEXT_ID_NONE, 'saltFilepath');
98  // Check config for backward compatibility.
99  if (!$this->_saltpath) $this->_saltpath = Config::getVar('usageStats', 'salt_filepath');
100  $request = Application::get()->getRequest();
101  $this->_optedOut = $request->getCookieVar('usageStats-opt-out');
102  if ($this->_optedOut) {
103  // Renew the Opt-Out cookie if present.
104  $request->setCookieVar('usageStats-opt-out', true, time() + 60*60*24*365);
105  }
106 
107  if ($this->_dataPrivacyOn) {
108  $this->import('UsageStatsOptoutBlockPlugin');
110  }
111 
112  PluginRegistry::register('reports', $this->getReportPlugin(), $this->getPluginPath());
113 
114  // Register callbacks.
115  HookRegistry::register('LoadHandler', array($this, 'callbackLoadHandler'));
116 
117  // If the plugin will provide the access logs,
118  // register to the usage event hook provider.
119  if ($this->getSetting(CONTEXT_ID_NONE, 'createLogFiles')) {
120  HookRegistry::register('UsageEventPlugin::getUsageEvent', array(&$this, 'logUsageEvent'));
121  }
122 
123  $this->_registerTemplateResource(true);
124 
125  $this->displayReaderStatistics();
126  }
127 
128  return $success;
129  }
130 
137  function displayReaderStatistics() {
139  $applicationName = $application->getName();
140  switch($applicationName) {
141  case 'ojs2':
142  // Add chart to article view page
143  HookRegistry::register('Templates::Article::Main', array($this, 'displayReaderArticleGraph'));
144  break;
145  case 'omp':
146  // Add chart to book view page
147  HookRegistry::register('Templates::Catalog::Book::Main', array($this, 'displayReaderMonographGraph'));
148  break;
149  case 'ops':
150  // Add chart to preprint view page
151  HookRegistry::register('Templates::Preprint::Main', array($this, 'displayReaderPreprintGraph'));
152  break;
153  default:
154  assert(false);
155  }
156  }
157 
162  function getSaltpath() {
163  return $this->_saltpath;
164  }
165 
169  function getDisplayName() {
170  return __('plugins.generic.usageStats.displayName');
171  }
172 
176  function getDescription() {
177  return __('plugins.generic.usageStats.description');
178  }
179 
183  function isSitePlugin() {
184  return true;
185  }
186 
191  return $this->getPluginPath() . DIRECTORY_SEPARATOR . 'settings.xml';
192  }
193 
197  function getInstallMigration() {
198  $this->import('UsageStatsMigration');
199  return new UsageStatsMigration();
200  }
201 
205  function manage($args, $request) {
206  $this->import('UsageStatsSettingsForm');
207  switch($request->getUserVar('verb')) {
208  case 'settings':
209  $settingsForm = new UsageStatsSettingsForm($this);
210  $settingsForm->initData();
211  return new JSONMessage(true, $settingsForm->fetch($request));
212  case 'save':
213  $settingsForm = new UsageStatsSettingsForm($this);
214  $settingsForm->readInputData();
215  if ($settingsForm->validate()) {
216  $settingsForm->execute();
217  $notificationManager = new NotificationManager();
218  $notificationManager->createTrivialNotification(
219  $request->getUser()->getId(),
220  NOTIFICATION_TYPE_SUCCESS,
221  array('contents' => __('plugins.generic.usageStats.settings.saved'))
222  );
223  return new JSONMessage(true);
224  }
225  return new JSONMessage(true, $settingsForm->fetch($request));
226  }
227  return parent::manage($args, $request);
228  }
229 
230 
231  //
232  // Implement template methods from GenericPlugin.
233  //
237  function getActions($request, $verb) {
238  $router = $request->getRouter();
239  import('lib.pkp.classes.linkAction.request.AjaxModal');
240  return array_merge(
241  $this->getEnabled()?array(
242  new LinkAction(
243  'settings',
244  new AjaxModal(
245  $router->url($request, null, null, 'manage', null, array('verb' => 'settings', 'plugin' => $this->getName(), 'category' => 'generic')),
246  $this->getDisplayName()
247  ),
248  __('manager.plugins.settings'),
249  null
250  ),
251  ):array(),
252  parent::getActions($request, $verb)
253  );
254  }
255 
256 
257  //
258  // Hook implementations.
259  //
270  function callbackLoadHandler($hookName, $args) {
271  // Check the page.
272  $page = $args[0];
273  if ($page !== 'usageStats') return;
274  // Check the operation.
275  $availableOps = array('privacyInformation');
276  $op = $args[1];
277  if (!in_array($op, $availableOps)) return;
278  // The handler had been requested.
279  define('HANDLER_CLASS', 'UsageStatsHandler');
280  define('USAGESTATS_PLUGIN_NAME', $this->getName());
281  $handlerFile =& $args[2];
282  $handlerFile = $this->getPluginPath() . '/' . 'UsageStatsHandler.inc.php';
283  }
284 
293  function callbackParseCronTab($hookName, $args) {
294  if ($this->getEnabled() || !Config::getVar('general', 'installed')) {
295  $taskFilesPath =& $args[0]; // Reference needed.
296  $taskFilesPath[] = $this->getPluginPath() . DIRECTORY_SEPARATOR . 'scheduledTasksAutoStage.xml';
297  }
298  return false;
299  }
300 
306  function validateSaltpath($saltpath) {
307  if (!file_exists($saltpath)) {
308  touch($saltpath);
309  }
310  if (is_writable($saltpath)) {
311  return true;
312  }
313  return false;
314  }
315 
321  protected function getDownloadFinishedEventHooks() {
322  $hooks = array('FileManager::downloadFileFinished');
324  $applicationName = $application->getName();
325  switch ($applicationName) {
326  case 'ojs2':
327  $hooks[] = 'HtmlArticleGalleyPlugin::articleDownloadFinished';
328  break;
329  case 'omp':
330  $hooks[] = 'HtmlMonographFilePlugin::monographDownloadFinished';
331  break;
332  case 'ops':
333  $hooks[] = 'HtmlArticleGalleyPlugin::articleDownloadFinished';
334  break;
335  }
336  return $hooks;
337  }
338 
352  function logUsageEvent($hookName, $args) {
353  $hookName = $args[0];
354  $usageEvent = $args[1];
355 
356  // Check the statistics opt-out.
357  if ($this->_optedOut) return false;
358 
359  if (in_array($hookName, $this->getDownloadFinishedEventHooks()) && !$usageEvent && $this->_currentUsageEvent) {
360  // File download is finished, try to log the current usage event.
361  $downloadSuccess = $args[2];
362  if ($downloadSuccess && !connection_aborted()) {
363  $this->_currentUsageEvent['downloadSuccess'] = true;
365  }
366  }
367 
368  if ($usageEvent && !$usageEvent['downloadSuccess']) {
369  // Don't log until we get the download finished hook call.
370  $this->_currentUsageEvent = $usageEvent;
371  return false;
372  }
373 
374  if ($usageEvent) {
375  $this->_writeUsageEventInLogFile($usageEvent);
376  }
377 
378  return false;
379  }
380 
386  function &getGeoLocationTool() {
390  $this->import('GeoLocationTool');
391 
392  $null = null;
393  $tool = new GeoLocationTool();
394  if ($tool->isPresent()) {
395  return $tool;
396  } else {
397  return $null;
398  }
399  }
400 
405  function getFilesPath() {
406  import('lib.pkp.classes.file.PrivateFileManager');
407  $fileMgr = new PrivateFileManager();
408 
409  return realpath($fileMgr->getBasePath()) . DIRECTORY_SEPARATOR . 'usageStats';
410  }
411 
416  function getUsageEventLogsPath() {
417  return $this->getFilesPath() . DIRECTORY_SEPARATOR . 'usageEventLogs';
418  }
419 
424  function getUsageEventCurrentDayLogName() {
425  return 'usage_events_' . date("Ymd") . '.log';
426  }
427 
434  function loadJavascript($contexts) {
435 
436  $request = Application::get()->getRequest();
437  $templateMgr = TemplateManager::getManager($request);
438 
439  // Register Chart.js on the frontend article view
440  $templateMgr->addJavaScript(
441  'chartJS',
442  'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.0.1/Chart.js',
443  array(
444  'contexts' => $contexts,
445  )
446  );
447 
448  // Add locale and configuration data
449  $context = $request->getContext();
450  $chartType = $this->_getPluginSetting($context, 'chartType');
451  $script_data = 'var pkpUsageStats = pkpUsageStats || {};';
452  $script_data .= 'pkpUsageStats.locale = pkpUsageStats.locale || {};';
453  $script_data .= 'pkpUsageStats.locale.months = ' . json_encode(explode(' ', __('plugins.generic.usageStats.monthInitials'))) . ';';
454  $script_data .= 'pkpUsageStats.config = pkpUsageStats.config || {};';
455  $script_data .= 'pkpUsageStats.config.chartType = ' . json_encode($chartType) . ';';
456  $templateMgr->addJavaScript(
457  'pkpUsageStatsConfig',
458  $script_data,
459  array(
460  'inline' => true,
461  'contexts' => $contexts,
462  )
463  );
464 
465  // Register the JS which initializes the chart
466  $baseImportPath = $request->getBaseUrl() . DIRECTORY_SEPARATOR . $this->getPluginPath() . DIRECTORY_SEPARATOR;
467  $templateMgr->addJavaScript(
468  'usageStatsFrontend',
469  $baseImportPath . 'js/UsageStatsFrontendHandler.js',
470  array(
471  'contexts' => $contexts,
472  )
473  );
474  }
475 
485  function addJavascriptData($data, $pubObjectType, $pubObjectId, $contexts) {
486 
487  // Initialize the name space
488  $script_data = 'var pkpUsageStats = pkpUsageStats || {};';
489  $script_data .= 'pkpUsageStats.data = pkpUsageStats.data || {};';
490  $script_data .= 'pkpUsageStats.data.' . $pubObjectType . ' = pkpUsageStats.data.' . $pubObjectType . ' || {};';
491  $namespace = $pubObjectType . '[' . $pubObjectId . ']';
492  $script_data .= 'pkpUsageStats.data.' . $namespace . ' = ' . json_encode($data) .';';
493 
494  // Register the data
495  $request = Application::get()->getRequest();
496  $templateMgr = TemplateManager::getManager($request);
497  $templateMgr->addJavaScript(
498  'pkpUsageStatsData',
499  $script_data,
500  array(
501  'inline' => true,
502  'contexts' => $contexts,
503  )
504  );
505  }
506 
515  function getTemplate($args, $template, $smarty) {
516  $smarty->assign($args);
517  return $smarty->fetch($this->getTemplateResource($template));
518  }
519 
530  function displayReaderArticleGraph($hookName, $params) {
531  $smarty =& $params[1];
532  $output =& $params[2];
533 
534  $context = $smarty->getTemplateVars('currentContext');
535  $pluginSettingsDao = DAORegistry::getDAO('PluginSettingsDAO');
536  $contextDisplaySettingExists = $pluginSettingsDao->settingExists($context->getId(), $this->getName(), 'displayStatistics');
537  $contextDisplaySetting = $this->getSetting($context->getId(), 'displayStatistics');
538  $siteDisplaySetting = $this->getSetting(CONTEXT_ID_NONE, 'displayStatistics');
539  if (($contextDisplaySettingExists && $contextDisplaySetting) ||
540  (!$contextDisplaySettingExists && $siteDisplaySetting)) {
541 
542  $pubObject = $smarty->getTemplateVars('article');
543  assert(is_a($pubObject, 'Submission'));
544  $pubObjectId = $pubObject->getId();
545  $pubObjectType = 'Submission';
546 
547  $output .= $this->getTemplate(
548  array(
549  'pubObjectType' => $pubObjectType,
550  'pubObjectId' => $pubObjectId,
551  ),
552  'outputFrontend.tpl',
553  $smarty
554  );
555 
556  $this->addJavascriptData($this->getAllDownloadsStats($pubObjectId), $pubObjectType, $pubObjectId, 'frontend-article-view');
557  $this->loadJavascript('frontend-article-view' );
558  }
559  return false;
560  }
561 
572  function displayReaderMonographGraph($hookName, $params) {
573  $smarty =& $params[1];
574  $output =& $params[2];
575 
576  $context = $smarty->getTemplateVars('currentContext');
577  $pluginSettingsDao = DAORegistry::getDAO('PluginSettingsDAO');
578  $contextDisplaySettingExists = $pluginSettingsDao->settingExists($context->getId(), $this->getName(), 'displayStatistics');
579  $contextDisplaySetting = $this->getSetting($context->getId(), 'displayStatistics');
580  $siteDisplaySetting = $this->getSetting(CONTEXT_ID_NONE, 'displayStatistics');
581  if (($contextDisplaySettingExists && $contextDisplaySetting) ||
582  (!$contextDisplaySettingExists && $siteDisplaySetting)) {
583 
584  $pubObject = $smarty->getTemplateVars('publication');
585  assert(is_a($pubObject, 'Publication'));
586  $pubObjectId = $pubObject->getId();
587  $pubObjectType = 'Publication';
588 
589  $output .= $this->getTemplate(
590  array(
591  'pubObjectType' => $pubObjectType,
592  'pubObjectId' => $pubObjectId,
593  ),
594  'outputFrontend.tpl',
595  $smarty
596  );
597 
598  $this->addJavascriptData($this->getAllDownloadsStats($pubObjectId), $pubObjectType, $pubObjectId, 'frontend-catalog-book');
599  $this->loadJavascript('frontend-catalog-book' );
600  }
601  return false;
602  }
603 
614  function displayReaderPreprintGraph($hookName, $params) {
615  $smarty =& $params[1];
616  $output =& $params[2];
617 
618  $context = $smarty->getTemplateVars('currentContext');
619  $pluginSettingsDao = DAORegistry::getDAO('PluginSettingsDAO');
620  $contextDisplaySettingExists = $pluginSettingsDao->settingExists($context->getId(), $this->getName(), 'displayStatistics');
621  $contextDisplaySetting = $this->getSetting($context->getId(), 'displayStatistics');
622  $siteDisplaySetting = $this->getSetting(CONTEXT_ID_NONE, 'displayStatistics');
623  if (($contextDisplaySettingExists && $contextDisplaySetting) ||
624  (!$contextDisplaySettingExists && $siteDisplaySetting)) {
625 
626  $pubObject = $smarty->getTemplateVars('preprint');
627  assert(is_a($pubObject, 'Submission'));
628  $pubObjectId = $pubObject->getId();
629  $pubObjectType = 'Submission';
630 
631  $output .= $this->getTemplate(
632  array(
633  'pubObjectType' => $pubObjectType,
634  'pubObjectId' => $pubObjectId,
635  ),
636  'outputFrontend.tpl',
637  $smarty
638  );
639 
640  $this->addJavascriptData($this->getAllDownloadsStats($pubObjectId), $pubObjectType, $pubObjectId, 'frontend-preprint-view');
641  $this->loadJavascript('frontend-preprint-view' );
642  }
643  return false;
644  }
645 
646 
647  //
648  // Private helper methods.
649  //
657  function _writeUsageEventInLogFile($usageEvent) {
658  $salt = null;
659  if ($this->_dataPrivacyOn) {
660  // Salt management.
661  $saltFilename = $this->getSaltpath();
662  if (!$this->validateSaltpath($saltFilename)) return false;
663  $currentDate = date("Ymd");
664  $saltFilenameLastModified = date("Ymd", filemtime($saltFilename));
665  $file = fopen($saltFilename, 'r');
666  $salt = trim(fread($file,filesize($saltFilename)));
667  fclose($file);
668  if (empty($salt) || ($currentDate != $saltFilenameLastModified)) {
669  if(function_exists('mcrypt_create_iv')) {
670  $newSalt = bin2hex(mcrypt_create_iv(16, MCRYPT_DEV_URANDOM|MCRYPT_RAND));
671  } elseif (function_exists('openssl_random_pseudo_bytes')){
672  $newSalt = bin2hex(openssl_random_pseudo_bytes(16, $cstrong));
673  } elseif (file_exists('/dev/urandom')){
674  $newSalt = bin2hex(file_get_contents('/dev/urandom', false, null, 0, 16));
675  } else {
676  $newSalt = mt_rand();
677  }
678  $file = fopen($saltFilename,'wb');
679  if (flock($file, LOCK_EX)) {
680  fwrite($file, $newSalt);
681  flock($file, LOCK_UN);
682  } else {
683  assert(false);
684  }
685  fclose($file);
686  $salt = $newSalt;
687  }
688  }
689 
690  // Manage the IP address (evtually hash it)
691  if ($this->_dataPrivacyOn) {
692  if (!isset($salt)) return false;
693  // Hash the IP
694  $hashedIp = $this->_hashIp($usageEvent['ip'], $salt);
695  // Never store unhashed IPs!
696  if ($hashedIp === false) return false;
697  $desiredParams = array($hashedIp);
698  } else {
699  $desiredParams = array($usageEvent['ip']);
700  }
701 
702  if (isset($usageEvent['classification'])) {
703  $desiredParams[] = $usageEvent['classification'];
704  } else {
705  $desiredParams[] = '-';
706  }
707 
708  if (!$this->_dataPrivacyOn && isset($usageEvent['user'])) {
709  $desiredParams[] = $usageEvent['user']->getId();
710  } else {
711  $desiredParams[] = '-';
712  }
713 
714  $desiredParams = array_merge($desiredParams,
715  array('"' . $usageEvent['time'] . '"', $usageEvent['canonicalUrl'],
716  '200', // The usage event plugin always log requests that returned this code.
717  '"' . $usageEvent['userAgent'] . '"'));
718 
719  $usageLogEntry = implode(' ', $desiredParams) . PHP_EOL;
720 
721  import('lib.pkp.classes.file.PrivateFileManager');
722  $fileMgr = new PrivateFileManager();
723 
724  // Get the current day filename.
725  $filename = $this->getUsageEventCurrentDayLogName();
726 
727  // Check the plugin file directory.
728  $usageEventFilesPath = $this->getUsageEventLogsPath();
729  if (!$fileMgr->fileExists($usageEventFilesPath, 'dir')) {
730  $success = $fileMgr->mkdirtree($usageEventFilesPath);
731  if (!$success) {
732  // Files directory wrong configuration?
733  assert(false);
734  return false;
735  }
736  }
737 
738  $filePath = $usageEventFilesPath . DIRECTORY_SEPARATOR . $filename;
739  $fp = fopen($filePath, 'ab');
740  if (flock($fp, LOCK_EX)) {
741  fwrite($fp, $usageLogEntry);
742  flock($fp, LOCK_UN);
743  } else {
744  // Couldn't lock the file.
745  assert(false);
746  }
747  fclose($fp);
748  }
749 
761  function _hashIp($ip, $salt) {
762  if(function_exists('mhash')) {
763  return bin2hex(mhash(MHASH_SHA256, $ip.$salt));
764  } else {
765  assert(function_exists('hash'));
766  if (!function_exists('hash')) return false;
767  return hash('sha256', $ip.$salt);
768  }
769  }
770 
776  function _getDownloadStats($pubObjectId) {
777  $cache = CacheManager::getManager()->getCache('downloadStats', $pubObjectId, array($this, '_downloadStatsCacheMiss'));
778  if (time() - $cache->getCacheTime() > 60 * 60 * 24) {
779  // Cache is older than one day, erase it.
780  $cache->flush();
781  }
782  $statsReports = $cache->get($pubObjectId);
783 
784  $currentYear = date("Y");
785  $months = range(1, 12);
786  $statsByFormat = $statsByMonth = $years = array();
787  $totalDownloads = 0;
788  foreach ($statsReports as $statsReport) {
789  $month = (int) substr($statsReport[STATISTICS_DIMENSION_MONTH], -2);
790  $year = (int) substr($statsReport[STATISTICS_DIMENSION_MONTH], 0, 4);
791  $metric = $statsReport[STATISTICS_METRIC];
792 
793  // Keep track of the years, avoiding duplicates.
794  $years[$year] = null;
795 
796  $representationId = $statsReport[STATISTICS_DIMENSION_REPRESENTATION_ID];
797 
798  // Prepare the stats aggregating by Representation.
799  // Create entries for all months, so all representations will have the same entries count.
800  if (!array_key_exists($representationId, $statsByFormat)) {
801  $representationDao = Application::getRepresentationDAO();
802  $representation = $representationDao->getById($representationId);
803  if (empty($representation)) {
804  continue;
805  }
806  $statsByFormat[$representationId] = array(
807  'data' => array(),
808  'label' => $representation->getLocalizedName(),
809  'color' => $this->_getColor($representationId),
810  'total' => 0);
811  }
812 
813  // Make sure we have entries for all years with stats.
814  if (!array_key_exists($year, $statsByFormat[$representationId]['data'])) {
815  $statsByFormat[$representationId]['data'][$year] = array_fill_keys($months, 0);
816  }
817  $statsByFormat[$representationId]['data'][$year][$month] = $metric;
818  $statsByFormat[$representationId]['total'] += $metric;
819 
820  // Prepare the stats aggregating only by Month.
821  if (!array_key_exists($year, $statsByMonth)) {
822  $statsByMonth[$year] = array_fill_keys($months, 0);
823  }
824  $statsByMonth[$year][$month] += $metric;
825  $totalDownloads += $metric;
826  }
827 
828  if ($statsByMonth) {
829  $datasetId = 'allDownloads'; // GraphJS works with datasets.
830  $statsByMonth = array($datasetId => array(
831  'data' => $statsByMonth,
832  'label' => __('common.allDownloads'),
833  'color' => $this->_getColor(REALLY_BIG_NUMBER),
834  'total' => $totalDownloads
835  ));
836  }
837 
838  return array($statsByFormat, $statsByMonth, array_keys($years));
839  }
840 
849  function getAllDownloadsStats($pubObjectId, $stats = array()) {
850 
851  if (empty($stats)) {
852  $stats = $this->_getDownloadStats($pubObjectId);
853  }
854 
855  $allDownloadStats = array();
856  foreach($stats as $dataset) {
857  if (array_key_exists('allDownloads', $dataset)) {
858  $allDownloadStats = $dataset['allDownloads'];
859  }
860  }
861 
862  return $allDownloadStats;
863  }
864 
871  function _downloadStatsCacheMiss($cache, $pubObjectId) {
872  $filter = array(
873  STATISTICS_DIMENSION_SUBMISSION_ID => $pubObjectId,
874  STATISTICS_DIMENSION_ASSOC_TYPE => ASSOC_TYPE_SUBMISSION_FILE
875  );
876  $orderBy = array(STATISTICS_DIMENSION_MONTH => STATISTICS_ORDER_ASC);
877  $reportPlugin = $this->getReportPlugin();
878 
880 
881  $statsReports = $application->getMetrics(current($reportPlugin->getMetricTypes()), array(STATISTICS_DIMENSION_MONTH, STATISTICS_DIMENSION_REPRESENTATION_ID), $filter, $orderBy);
882  $cache->setEntireCache(array($pubObjectId => $statsReports));
883  return $statsReports;
884  }
885 
892  function _getColor($num) {
893  $hash = md5('color' . $num * 2);
894  return hexdec(substr($hash, 0, 2)) . ',' . hexdec(substr($hash, 2, 2)) . ',' . hexdec(substr($hash, 4, 2));
895  }
896 
904  function _getPluginSetting($context, $name) {
905  $pluginSettingsDao = DAORegistry::getDAO('PluginSettingsDAO');
906  if ($context && $pluginSettingsDao->settingExists($context->getId(), $this->getName(), $name)) {
907  return $this->getSetting($context->getId(), $name);
908  } else {
909  return $this->getSetting(CONTEXT_ID_NONE, $name);
910  }
911  }
912 
913 }
914 
UsageStatsPlugin\getDisplayName
getDisplayName()
Definition: UsageStatsPlugin.inc.php:181
PrivateFileManager
Class defining operations for private file management.
Definition: PrivateFileManager.inc.php:18
$op
$op
Definition: lib/pkp/pages/help/index.php:18
UsageStatsPlugin\getDescription
getDescription()
Definition: UsageStatsPlugin.inc.php:188
UsageStatsPlugin\validateSaltpath
validateSaltpath($saltpath)
Definition: UsageStatsPlugin.inc.php:318
UsageStatsPlugin\getFilesPath
getFilesPath()
Definition: UsageStatsPlugin.inc.php:417
UsageStatsPlugin\_getDownloadStats
_getDownloadStats($pubObjectId)
Definition: UsageStatsPlugin.inc.php:788
Application\getRepresentationDAO
static getRepresentationDAO()
Definition: Application.inc.php:160
$application
$application
Definition: index.php:61
UsageStatsPlugin\displayReaderPreprintGraph
displayReaderPreprintGraph($hookName, $params)
Definition: UsageStatsPlugin.inc.php:626
DAORegistry\getDAO
static & getDAO($name, $dbconn=null)
Definition: DAORegistry.inc.php:57
UsageStatsPlugin\getDownloadFinishedEventHooks
getDownloadFinishedEventHooks()
Definition: UsageStatsPlugin.inc.php:333
UsageStatsPlugin\$_dataPrivacyOn
$_dataPrivacyOn
Definition: UsageStatsPlugin.inc.php:30
UsageStatsPlugin\$_optedOut
$_optedOut
Definition: UsageStatsPlugin.inc.php:36
UsageStatsPlugin\_hashIp
_hashIp($ip, $salt)
Definition: UsageStatsPlugin.inc.php:773
GeoLocationTool
Geo location by ip wrapper class.
Definition: GeoLocationTool.inc.php:19
$tool
$tool
Definition: mergeCoverageReportTool.php:120
UsageStatsPlugin\isSitePlugin
isSitePlugin()
Definition: UsageStatsPlugin.inc.php:195
UsageStatsPlugin\getActions
getActions($request, $verb)
Definition: UsageStatsPlugin.inc.php:249
UsageStatsPlugin\callbackParseCronTab
callbackParseCronTab($hookName, $args)
Definition: UsageStatsPlugin.inc.php:305
UsageStatsPlugin\getAllDownloadsStats
getAllDownloadsStats($pubObjectId, $stats=array())
Definition: UsageStatsPlugin.inc.php:861
UsageStatsPlugin
Provide usage statistics to data objects.
Definition: UsageStatsPlugin.inc.php:18
UsageStatsPlugin\$_saltpath
$_saltpath
Definition: UsageStatsPlugin.inc.php:42
OPSUsageStatsReportPlugin
OPS default statistics report plugin (and metrics provider)
Definition: OPSUsageStatsReportPlugin.inc.php:21
UsageStatsPlugin\getInstallSitePluginSettingsFile
getInstallSitePluginSettingsFile()
Definition: UsageStatsPlugin.inc.php:202
UsageStatsPlugin\getUsageEventLogsPath
getUsageEventLogsPath()
Definition: UsageStatsPlugin.inc.php:428
OJSUsageStatsReportPlugin
Definition: OJSUsageStatsReportPlugin.inc.php:21
UsageStatsPlugin\displayReaderStatistics
displayReaderStatistics()
Definition: UsageStatsPlugin.inc.php:149
UsageStatsPlugin\displayReaderArticleGraph
displayReaderArticleGraph($hookName, $params)
Definition: UsageStatsPlugin.inc.php:542
UsageStatsPlugin\_downloadStatsCacheMiss
_downloadStatsCacheMiss($cache, $pubObjectId)
Definition: UsageStatsPlugin.inc.php:883
UsageStatsPlugin\getGeoLocationTool
& getGeoLocationTool()
Definition: UsageStatsPlugin.inc.php:398
UsageStatsPlugin\loadJavascript
loadJavascript($contexts)
Definition: UsageStatsPlugin.inc.php:446
Plugin\getEnabled
getEnabled()
Definition: Plugin.inc.php:868
CacheManager\getManager
static getManager()
Definition: CacheManager.inc.php:27
JSONMessage
Class to represent a JSON (Javascript Object Notation) message.
Definition: JSONMessage.inc.php:18
Plugin\getSetting
getSetting($contextId, $name)
Definition: Plugin.inc.php:473
OMPUsageStatsReportPlugin
OMP default statistics report plugin (and metrics provider)
Definition: OMPUsageStatsReportPlugin.inc.php:21
Config\getVar
static getVar($section, $key, $default=null)
Definition: Config.inc.php:35
UsageStatsMigration
Describe database table structures.
Definition: UsageStatsMigration.inc.php:19
AjaxModal
A modal that retrieves its content from via AJAX.
Definition: AjaxModal.inc.php:18
LinkAction
Base class defining an action that can be performed by the user in the user interface.
Definition: LinkAction.inc.php:22
UsageStatsPlugin\callbackLoadHandler
callbackLoadHandler($hookName, $args)
Definition: UsageStatsPlugin.inc.php:282
UsageStatsPlugin\logUsageEvent
logUsageEvent($hookName, $args)
Definition: UsageStatsPlugin.inc.php:364
LazyLoadPlugin\getName
getName()
Definition: LazyLoadPlugin.inc.php:40
PKPTemplateManager\getManager
static & getManager($request=null)
Definition: PKPTemplateManager.inc.php:1239
UsageStatsPlugin\getReportPlugin
getReportPlugin()
Definition: UsageStatsPlugin.inc.php:76
Plugin\_registerTemplateResource
_registerTemplateResource($inCore=false)
Definition: Plugin.inc.php:376
Plugin\getTemplateResource
getTemplateResource($template=null, $inCore=false)
Definition: Plugin.inc.php:349
UsageStatsPlugin\getInstallMigration
getInstallMigration()
Definition: UsageStatsPlugin.inc.php:209
Plugin\getPluginPath
getPluginPath()
Definition: Plugin.inc.php:330
UsageStatsPlugin\displayReaderMonographGraph
displayReaderMonographGraph($hookName, $params)
Definition: UsageStatsPlugin.inc.php:584
Plugin\$request
$request
Definition: Plugin.inc.php:68
UsageStatsPlugin\$_currentUsageEvent
$_currentUsageEvent
Definition: UsageStatsPlugin.inc.php:24
HookRegistry\register
static register($hookName, $callback, $hookSequence=HOOK_SEQUENCE_NORMAL)
Definition: HookRegistry.inc.php:70
UsageStatsPlugin\manage
manage($args, $request)
Definition: UsageStatsPlugin.inc.php:217
NotificationManager
Definition: NotificationManager.inc.php:19
UsageStatsPlugin\addJavascriptData
addJavascriptData($data, $pubObjectType, $pubObjectId, $contexts)
Definition: UsageStatsPlugin.inc.php:497
UsageStatsPlugin\getUsageEventCurrentDayLogName
getUsageEventCurrentDayLogName()
Definition: UsageStatsPlugin.inc.php:436
UsageStatsPlugin\_writeUsageEventInLogFile
_writeUsageEventInLogFile($usageEvent)
Definition: UsageStatsPlugin.inc.php:669
UsageStatsPlugin\__construct
__construct()
Definition: UsageStatsPlugin.inc.php:47
PKPApplication\get
static get()
Definition: PKPApplication.inc.php:235
GuzzleHttp\Psr7\hash
hash(StreamInterface $stream, $algo, $rawOutput=false)
Definition: guzzlehttp/psr7/src/functions.php:410
PluginRegistry\register
static register($category, $plugin, $path, $mainContextId=null)
Definition: PluginRegistry.inc.php:64
UsageStatsPlugin\getSaltpath
getSaltpath()
Definition: UsageStatsPlugin.inc.php:174
UsageStatsSettingsForm
Form for journal managers to modify usage statistics plugin settings.
Definition: UsageStatsSettingsForm.inc.php:18
GenericPlugin
Abstract class for generic plugins.
Definition: GenericPlugin.inc.php:18
UsageStatsPlugin\_getPluginSetting
_getPluginSetting($context, $name)
Definition: UsageStatsPlugin.inc.php:916
UsageStatsPlugin\getTemplate
getTemplate($args, $template, $smarty)
Definition: UsageStatsPlugin.inc.php:527
UsageStatsOptoutBlockPlugin
Opt-out component.
Definition: UsageStatsOptoutBlockPlugin.inc.php:18