File Manager
Upload
Current Directory: /home/lartcid/public_html/journal.lartc.id
[Back]
..
[Open]
Hapus
Rename
.htaccess
[Edit]
Hapus
Rename
.well-known
[Open]
Hapus
Rename
README.md
[Edit]
Hapus
Rename
api
[Open]
Hapus
Rename
cache
[Open]
Hapus
Rename
cgi-bin
[Open]
Hapus
Rename
classes
[Open]
Hapus
Rename
config.TEMPLATE.inc.php
[Edit]
Hapus
Rename
config.inc.php
[Edit]
Hapus
Rename
controllers
[Open]
Hapus
Rename
cypress.json
[Edit]
Hapus
Rename
dbscripts
[Open]
Hapus
Rename
docs
[Open]
Hapus
Rename
error_log
[Edit]
Hapus
Rename
favicon.ico
[Edit]
Hapus
Rename
index.php
[Edit]
Hapus
Rename
js
[Open]
Hapus
Rename
lib
[Open]
Hapus
Rename
locale
[Open]
Hapus
Rename
mini.php
[Edit]
Hapus
Rename
pages
[Open]
Hapus
Rename
php.ini
[Edit]
Hapus
Rename
plugins
[Open]
Hapus
Rename
public
[Open]
Hapus
Rename
registry
[Open]
Hapus
Rename
scheduledTaskLogs
[Open]
Hapus
Rename
schemas
[Open]
Hapus
Rename
styles
[Open]
Hapus
Rename
templates
[Open]
Hapus
Rename
tools
[Open]
Hapus
Rename
Edit File
<?php /** * @file plugins/generic/usageStats/UsageStatsPlugin.inc.php * * Copyright (c) 2013-2020 Simon Fraser University * Copyright (c) 2003-2020 John Willinsky * Distributed under the GNU GPL v3. For full terms see the file docs/COPYING. * * @class UsageStatsPlugin * @ingroup plugins_generic_usageStats * * @brief Provide usage statistics to data objects. */ import('lib.pkp.classes.plugins.GenericPlugin'); class UsageStatsPlugin extends GenericPlugin { /** @var $_currentUsageEvent array */ var $_currentUsageEvent; /** @var $_dataPrivacyOn boolean */ var $_dataPrivacyOn; /** @var $_optedOut boolean */ var $_optedOut; /** @var $_saltpath string */ var $_saltpath; /** * Constructor. */ function __construct() { parent::__construct(); // The upgrade and install processes will need access // to constants defined in that report plugin. $application = Application::get(); $applicationName = $application->getName(); switch ($applicationName) { case 'ojs2': import('plugins.generic.usageStats.OJSUsageStatsReportPlugin'); break; case 'omp': import('plugins.generic.usageStats.OMPUsageStatsReportPlugin'); break; case 'ops': import('plugins.generic.usageStats.OPSUsageStatsReportPlugin'); break; } } // // Public methods. // /** * Determine whether the plugin can be enabled. * * Can only be enabled or disabled at the site-wide level. * * @return boolean */ function getCanEnable() { return !((bool) Application::get()->getRequest()->getContext()); } /** * Determine whether the plugin can be disabled. * * Can only be enabled or disabled at the site-wide level. * * @return boolean */ function getCanDisable() { return !((bool) Application::get()->getRequest()->getContext()); } /** * Get the report plugin object that implements * the metric type details. * @return UsageStatsReportPlugin */ function getReportPlugin() { $application = Application::get(); $applicationName = $application->getName(); switch ($applicationName) { case 'ojs2': $this->import('OJSUsageStatsReportPlugin'); return new OJSUsageStatsReportPlugin(); case 'omp': $this->import('OMPUsageStatsReportPlugin'); return new OMPUsageStatsReportPlugin(); case 'ops': $this->import('OPSUsageStatsReportPlugin'); return new OPSUsageStatsReportPlugin(); default: assert(false); } } // // Implement methods from Plugin. // /** * @copydoc Plugin::register() */ function register($category, $path, $mainContextId = null) { $success = parent::register($category, $path, $mainContextId); HookRegistry::register('AcronPlugin::parseCronTab', array($this, 'callbackParseCronTab')); if ($this->getEnabled($mainContextId) && $success) { $this->_dataPrivacyOn = $this->getSetting(CONTEXT_ID_NONE, 'dataPrivacyOption'); $this->_saltpath = $this->getSetting(CONTEXT_ID_NONE, 'saltFilepath'); // Check config for backward compatibility. if (!$this->_saltpath) $this->_saltpath = Config::getVar('usageStats', 'salt_filepath'); $request = Application::get()->getRequest(); $this->_optedOut = $request->getCookieVar('usageStats-opt-out'); if ($this->_optedOut) { // Renew the Opt-Out cookie if present. $request->setCookieVar('usageStats-opt-out', true, time() + 60*60*24*365); } if ($this->_dataPrivacyOn) { $this->import('UsageStatsOptoutBlockPlugin'); PluginRegistry::register('blocks', new UsageStatsOptoutBlockPlugin($this), $this->getPluginPath()); } PluginRegistry::register('reports', $this->getReportPlugin(), $this->getPluginPath()); // Register callbacks. HookRegistry::register('LoadHandler', array($this, 'callbackLoadHandler')); // If the plugin will provide the access logs, // register to the usage event hook provider. if ($this->getSetting(CONTEXT_ID_NONE, 'createLogFiles')) { HookRegistry::register('UsageEventPlugin::getUsageEvent', array(&$this, 'logUsageEvent')); } $this->_registerTemplateResource(true); $this->displayReaderStatistics(); } return $success; } /** * Register assets and output hooks to display statistics on the reader * frontend. * * @return null */ function displayReaderStatistics() { $application = Application::get(); $applicationName = $application->getName(); switch($applicationName) { case 'ojs2': // Add chart to article view page HookRegistry::register('Templates::Article::Main', array($this, 'displayReaderArticleGraph')); break; case 'omp': // Add chart to book view page HookRegistry::register('Templates::Catalog::Book::Main', array($this, 'displayReaderMonographGraph')); break; case 'ops': // Add chart to preprint view page HookRegistry::register('Templates::Preprint::Main', array($this, 'displayReaderPreprintGraph')); break; default: assert(false); } } /** * Get the path to the salt file. * @return string */ function getSaltpath() { return $this->_saltpath; } /** * @copydoc Plugin::getDisplayName() */ function getDisplayName() { return __('plugins.generic.usageStats.displayName'); } /** * @copydoc Plugin::getDescription() */ function getDescription() { return __('plugins.generic.usageStats.description'); } /** * @copydoc Plugin::isSitePlugin() */ function isSitePlugin() { return true; } /** * @copydoc Plugin::getInstallSitePluginSettingsFile() */ function getInstallSitePluginSettingsFile() { return $this->getPluginPath() . DIRECTORY_SEPARATOR . 'settings.xml'; } /** * @copydoc Plugin::getInstallMigration() */ function getInstallMigration() { $this->import('UsageStatsMigration'); return new UsageStatsMigration(); } /** * @copydoc Plugin::manage() */ function manage($args, $request) { $singleContextSite = (Services::get('context')->getCount() == 1); if ($request->getContext() && !$singleContextSite) { $this->import('UsageStatsSettingsForm'); $settingsForm = new UsageStatsSettingsForm($this); } else { $this->import('UsageStatsSiteSettingsForm'); $settingsForm = new UsageStatsSiteSettingsForm($this); } switch($request->getUserVar('verb')) { case 'settings': $settingsForm->initData(); return new JSONMessage(true, $settingsForm->fetch($request)); case 'save': $settingsForm->readInputData(); if ($settingsForm->validate()) { $settingsForm->execute(); $notificationManager = new NotificationManager(); $notificationManager->createTrivialNotification( $request->getUser()->getId(), NOTIFICATION_TYPE_SUCCESS, array('contents' => __('plugins.generic.usageStats.settings.saved')) ); return new JSONMessage(true); } return new JSONMessage(true, $settingsForm->fetch($request)); } return parent::manage($args, $request); } // // Implement template methods from GenericPlugin. // /** * @copydoc Plugin::getActions() */ function getActions($request, $verb) { $router = $request->getRouter(); import('lib.pkp.classes.linkAction.request.AjaxModal'); return array_merge( $this->getEnabled()?array( new LinkAction( 'settings', new AjaxModal( $router->url($request, null, null, 'manage', null, array('verb' => 'settings', 'plugin' => $this->getName(), 'category' => 'generic')), $this->getDisplayName() ), __('manager.plugins.settings'), null ), ):array(), parent::getActions($request, $verb) ); } // // Hook implementations. // /** * @see PKPPageRouter::route() * @param $hookName string * @param $args array [ * @option string page * @option string op * @option string handler file * ] * */ function callbackLoadHandler($hookName, $args) { // Check the page. $page = $args[0]; if ($page !== 'usageStats') return; // Check the operation. $availableOps = array('privacyInformation'); $op = $args[1]; if (!in_array($op, $availableOps)) return; // The handler had been requested. define('HANDLER_CLASS', 'UsageStatsHandler'); define('USAGESTATS_PLUGIN_NAME', $this->getName()); $handlerFile =& $args[2]; $handlerFile = $this->getPluginPath() . '/' . 'UsageStatsHandler.inc.php'; } /** * @see AcronPlugin::parseCronTab() * @param $hookName string * @param $args array [ * @option array Task files paths * ] * @return bolean */ function callbackParseCronTab($hookName, $args) { if ($this->getEnabled() || !Config::getVar('general', 'installed')) { $taskFilesPath =& $args[0]; // Reference needed. $taskFilesPath[] = $this->getPluginPath() . DIRECTORY_SEPARATOR . 'scheduledTasksAutoStage.xml'; } return false; } /** * Validate that the path of the salt file exists and is writable. * @param $saltpath string * @return boolean */ function validateSaltpath($saltpath) { if (!file_exists($saltpath)) { touch($saltpath); } if (is_writable($saltpath)) { return true; } return false; } /** * Get all hooks that define the * finished file download. * @return array */ protected function getDownloadFinishedEventHooks() { $hooks = array('FileManager::downloadFileFinished'); $application = Application::get(); $applicationName = $application->getName(); switch ($applicationName) { case 'ojs2': $hooks[] = 'HtmlArticleGalleyPlugin::articleDownloadFinished'; $hooks[] = 'LensGalleyPlugin::articleDownloadFinished'; break; case 'omp': $hooks[] = 'HtmlMonographFilePlugin::monographDownloadFinished'; break; case 'ops': $hooks[] = 'HtmlArticleGalleyPlugin::articleDownloadFinished'; break; } return $hooks; } /** * Log the usage event into a file. * @param $hookName string * @param $args array [ * @option string hook name * @option array usage event = compact( * 'time', 'pubObject', 'assocType', 'canonicalUrl', 'mimeType', * 'identifiers', 'downloadSuccess', 'serviceUri', * 'ip', 'host', 'user', 'roles', 'userAgent', 'referrer', * 'classification') * ] * @return boolean */ function logUsageEvent($hookName, $args) { $hookName = $args[0]; $usageEvent = $args[1]; // Check the statistics opt-out. if ($this->_optedOut) return false; if (in_array($hookName, $this->getDownloadFinishedEventHooks()) && !$usageEvent && $this->_currentUsageEvent) { // File download is finished, try to log the current usage event. $downloadSuccess = $args[2]; if ($downloadSuccess && !connection_aborted()) { $this->_currentUsageEvent['downloadSuccess'] = true; $usageEvent = $this->_currentUsageEvent; } } if ($usageEvent && !$usageEvent['downloadSuccess']) { // Don't log until we get the download finished hook call. $this->_currentUsageEvent = $usageEvent; return false; } if ($usageEvent) { $this->_writeUsageEventInLogFile($usageEvent); } return false; } /** * Get the geolocation tool to process geo localization * data. * @return mixed GeoLocationTool object or null */ function &getGeoLocationTool() { /** Geo location tool wrapper class. If changing the geo location tool * is required, change the code inside this class, keeping the public * interface. */ $this->import('GeoLocationTool'); $null = null; $tool = new GeoLocationTool(); if ($tool->isPresent()) { return $tool; } else { return $null; } } /** * Get the plugin's files path. * @return string */ function getFilesPath() { import('lib.pkp.classes.file.PrivateFileManager'); $fileMgr = new PrivateFileManager(); return realpath($fileMgr->getBasePath()) . DIRECTORY_SEPARATOR . 'usageStats'; } /** * Get the plugin's usage event logs path. * @return string */ function getUsageEventLogsPath() { return $this->getFilesPath() . DIRECTORY_SEPARATOR . 'usageEventLogs'; } /** * Get current day usage event log name. * @return string */ function getUsageEventCurrentDayLogName() { return 'usage_events_' . date("Ymd") . '.log'; } /** * Load the JavaScript assets and pass data to the scripts * * @param $contexts string|array Contexts in which to load the scripts. * @return null */ function loadJavascript($contexts) { $request = Application::get()->getRequest(); $templateMgr = TemplateManager::getManager($request); // Register Chart.js on the frontend article view $templateMgr->addJavaScript( 'chartJS', 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.0.1/Chart.js', array( 'contexts' => $contexts, ) ); // Add locale and configuration data $context = $request->getContext(); $chartType = $this->_getPluginSetting($context, 'chartType'); $script_data = 'var pkpUsageStats = pkpUsageStats || {};'; $script_data .= 'pkpUsageStats.locale = pkpUsageStats.locale || {};'; $script_data .= 'pkpUsageStats.locale.months = ' . json_encode(explode(' ', __('plugins.generic.usageStats.monthInitials'))) . ';'; $script_data .= 'pkpUsageStats.config = pkpUsageStats.config || {};'; $script_data .= 'pkpUsageStats.config.chartType = ' . json_encode($chartType) . ';'; $templateMgr->addJavaScript( 'pkpUsageStatsConfig', $script_data, array( 'inline' => true, 'contexts' => $contexts, ) ); // Register the JS which initializes the chart $baseImportPath = $request->getBaseUrl() . DIRECTORY_SEPARATOR . $this->getPluginPath() . DIRECTORY_SEPARATOR; $templateMgr->addJavaScript( 'usageStatsFrontend', $baseImportPath . 'js/UsageStatsFrontendHandler.js', array( 'contexts' => $contexts, ) ); } /** * Add a data set to the script data output * * @param $data array JS data to pass to the scripts * @param $pubObjectType string The type of object this data is for * @param $pubObjectId string The id of the object this data is for * @param $contexts string|array Contexts in which to load the scripts. * @return null */ function addJavascriptData($data, $pubObjectType, $pubObjectId, $contexts) { // Initialize the name space $script_data = 'var pkpUsageStats = pkpUsageStats || {};'; $script_data .= 'pkpUsageStats.data = pkpUsageStats.data || {};'; $script_data .= 'pkpUsageStats.data.' . $pubObjectType . ' = pkpUsageStats.data.' . $pubObjectType . ' || {};'; $namespace = $pubObjectType . '[' . $pubObjectId . ']'; $script_data .= 'pkpUsageStats.data.' . $namespace . ' = ' . json_encode($data) .';'; // Register the data $request = Application::get()->getRequest(); $templateMgr = TemplateManager::getManager($request); $templateMgr->addJavaScript( 'pkpUsageStatsData', $script_data, array( 'inline' => true, 'contexts' => $contexts, ) ); } /** * Fetch a template with the requested params * * @param $args array Variables to assign to the template * @param $template string Template file name * @param $smarty object Smarty template object * @return string */ function getTemplate($args, $template, $smarty) { $smarty->assign($args); return $smarty->fetch($this->getTemplateResource($template)); } /** * Add chart to article view page * * Hooked to `Templates::Article::Main` * @param $hookName string * @param $params array [ * @option Smarty * @option string HTML output to return * ] */ function displayReaderArticleGraph($hookName, $params) { $smarty =& $params[1]; $output =& $params[2]; $context = $smarty->getTemplateVars('currentContext'); $pluginSettingsDao = DAORegistry::getDAO('PluginSettingsDAO'); $contextDisplaySettingExists = $pluginSettingsDao->settingExists($context->getId(), $this->getName(), 'displayStatistics'); $contextDisplaySetting = $this->getSetting($context->getId(), 'displayStatistics'); $siteDisplaySetting = $this->getSetting(CONTEXT_ID_NONE, 'displayStatistics'); if (($contextDisplaySettingExists && $contextDisplaySetting) || (!$contextDisplaySettingExists && $siteDisplaySetting)) { $pubObject = $smarty->getTemplateVars('article'); assert(is_a($pubObject, 'Submission')); $pubObjectId = $pubObject->getId(); $pubObjectType = 'Submission'; $output .= $this->getTemplate( array( 'pubObjectType' => $pubObjectType, 'pubObjectId' => $pubObjectId, ), 'outputFrontend.tpl', $smarty ); $this->addJavascriptData($this->getAllDownloadsStats($pubObjectId), $pubObjectType, $pubObjectId, 'frontend-article-view'); $this->loadJavascript('frontend-article-view' ); } return false; } /** * Add chart to book view page * * Hooked to `Templates::Catalog::Book::Main` * @param $hookName string * @param $params arrayarray [ * @option Smarty * @option string HTML output to return * ] */ function displayReaderMonographGraph($hookName, $params) { $smarty =& $params[1]; $output =& $params[2]; $context = $smarty->getTemplateVars('currentContext'); $pluginSettingsDao = DAORegistry::getDAO('PluginSettingsDAO'); $contextDisplaySettingExists = $pluginSettingsDao->settingExists($context->getId(), $this->getName(), 'displayStatistics'); $contextDisplaySetting = $this->getSetting($context->getId(), 'displayStatistics'); $siteDisplaySetting = $this->getSetting(CONTEXT_ID_NONE, 'displayStatistics'); if (($contextDisplaySettingExists && $contextDisplaySetting) || (!$contextDisplaySettingExists && $siteDisplaySetting)) { $pubObject = $smarty->getTemplateVars('publishedSubmission'); assert(is_a($pubObject, 'Submission')); $pubObjectId = $pubObject->getId(); $pubObjectType = 'Submission'; $output .= $this->getTemplate( array( 'pubObjectType' => $pubObjectType, 'pubObjectId' => $pubObjectId, ), 'outputFrontend.tpl', $smarty ); $this->addJavascriptData($this->getAllDownloadsStats($pubObjectId), $pubObjectType, $pubObjectId, 'frontend-catalog-book'); $this->loadJavascript('frontend-catalog-book' ); } return false; } /** * Add chart to preprint view page * * Hooked to `Templates::Preprint::Main` * @param $hookName string * @param $params array [ * @option Smarty * @option string HTML output to return * ] */ function displayReaderPreprintGraph($hookName, $params) { $smarty =& $params[1]; $output =& $params[2]; $context = $smarty->getTemplateVars('currentContext'); $pluginSettingsDao = DAORegistry::getDAO('PluginSettingsDAO'); $contextDisplaySettingExists = $pluginSettingsDao->settingExists($context->getId(), $this->getName(), 'displayStatistics'); $contextDisplaySetting = $this->getSetting($context->getId(), 'displayStatistics'); $siteDisplaySetting = $this->getSetting(CONTEXT_ID_NONE, 'displayStatistics'); if (($contextDisplaySettingExists && $contextDisplaySetting) || (!$contextDisplaySettingExists && $siteDisplaySetting)) { $pubObject = $smarty->getTemplateVars('preprint'); assert(is_a($pubObject, 'Submission')); $pubObjectId = $pubObject->getId(); $pubObjectType = 'Submission'; $output .= $this->getTemplate( array( 'pubObjectType' => $pubObjectType, 'pubObjectId' => $pubObjectId, ), 'outputFrontend.tpl', $smarty ); $this->addJavascriptData($this->getAllDownloadsStats($pubObjectId), $pubObjectType, $pubObjectId, 'frontend-preprint-view'); $this->loadJavascript('frontend-preprint-view' ); } return false; } // // Private helper methods. // /** * @param $usageEvent array = compact( * 'time', 'pubObject', 'assocType', 'canonicalUrl', 'mimeType', * 'identifiers', 'downloadSuccess', 'serviceUri', * 'ip', 'host', 'user', 'roles', 'userAgent', 'referrer', * 'classification') */ function _writeUsageEventInLogFile($usageEvent) { $salt = null; if ($this->_dataPrivacyOn) { // Salt management. $saltFilename = $this->getSaltpath(); if (!$this->validateSaltpath($saltFilename)) return false; $currentDate = date("Ymd"); $saltFilenameLastModified = date("Ymd", filemtime($saltFilename)); $file = fopen($saltFilename, 'r'); $salt = trim(fread($file,filesize($saltFilename))); fclose($file); if (empty($salt) || ($currentDate != $saltFilenameLastModified)) { if(function_exists('mcrypt_create_iv')) { $newSalt = bin2hex(mcrypt_create_iv(16, MCRYPT_DEV_URANDOM|MCRYPT_RAND)); } elseif (function_exists('openssl_random_pseudo_bytes')){ $newSalt = bin2hex(openssl_random_pseudo_bytes(16, $cstrong)); } elseif (file_exists('/dev/urandom')){ $newSalt = bin2hex(file_get_contents('/dev/urandom', false, null, 0, 16)); } else { $newSalt = mt_rand(); } $file = fopen($saltFilename,'wb'); if (flock($file, LOCK_EX)) { fwrite($file, $newSalt); flock($file, LOCK_UN); } else { assert(false); } fclose($file); $salt = $newSalt; } } // Manage the IP address (evtually hash it) if ($this->_dataPrivacyOn) { if (!isset($salt)) return false; // Hash the IP $hashedIp = $this->_hashIp($usageEvent['ip'], $salt); // Never store unhashed IPs! if ($hashedIp === false) return false; $desiredParams = array($hashedIp); } else { $desiredParams = array($usageEvent['ip']); } if (isset($usageEvent['classification'])) { $desiredParams[] = $usageEvent['classification']; } else { $desiredParams[] = '-'; } if (!$this->_dataPrivacyOn && isset($usageEvent['user'])) { $desiredParams[] = $usageEvent['user']->getId(); } else { $desiredParams[] = '-'; } $desiredParams = array_merge($desiredParams, array('"' . $usageEvent['time'] . '"', $usageEvent['canonicalUrl'], '200', // The usage event plugin always log requests that returned this code. '"' . $usageEvent['userAgent'] . '"')); $usageLogEntry = implode(' ', $desiredParams) . PHP_EOL; import('lib.pkp.classes.file.PrivateFileManager'); $fileMgr = new PrivateFileManager(); // Get the current day filename. $filename = $this->getUsageEventCurrentDayLogName(); // Check the plugin file directory. $usageEventFilesPath = $this->getUsageEventLogsPath(); if (!$fileMgr->fileExists($usageEventFilesPath, 'dir')) { $success = $fileMgr->mkdirtree($usageEventFilesPath); if (!$success) { // Files directory wrong configuration? assert(false); return false; } } $filePath = $usageEventFilesPath . DIRECTORY_SEPARATOR . $filename; $fp = fopen($filePath, 'ab'); if (flock($fp, LOCK_EX)) { fwrite($fp, $usageLogEntry); flock($fp, LOCK_UN); } else { // Couldn't lock the file. assert(false); } fclose($fp); } /** * Hash (SHA256) the given IP using the given SALT. * * NB: This implementation was taken from OA-S directly. See * http://sourceforge.net/p/openaccessstati/code-0/3/tree/trunk/logfile-parser/lib/logutils.php * We just do not implement the PHP4 part as OJS dropped PHP4 support. * * @param $ip string * @param $salt string * @return string|boolean The hashed IP or boolean false if something went wrong. */ function _hashIp($ip, $salt) { if(function_exists('mhash')) { return bin2hex(mhash(MHASH_SHA256, $ip.$salt)); } else { assert(function_exists('hash')); if (!function_exists('hash')) return false; return hash('sha256', $ip.$salt); } } /** * Get prepared download statistics from the DB * @param $pubObjectId integer * @return array */ function _getDownloadStats($pubObjectId) { $cache = CacheManager::getManager()->getCache('downloadStats', $pubObjectId, array($this, '_downloadStatsCacheMiss')); if (time() - $cache->getCacheTime() > 60 * 60 * 24) { // Cache is older than one day, erase it. $cache->flush(); } $statsReports = $cache->get($pubObjectId); $currentYear = date("Y"); $months = range(1, 12); $statsByFormat = $statsByMonth = $years = array(); $totalDownloads = 0; foreach ($statsReports as $statsReport) { $month = (int) substr($statsReport[STATISTICS_DIMENSION_MONTH], -2); $year = (int) substr($statsReport[STATISTICS_DIMENSION_MONTH], 0, 4); $metric = $statsReport[STATISTICS_METRIC]; // Keep track of the years, avoiding duplicates. $years[$year] = null; $representationId = $statsReport[STATISTICS_DIMENSION_REPRESENTATION_ID]; // Prepare the stats aggregating by Representation. // Create entries for all months, so all representations will have the same entries count. if (!array_key_exists($representationId, $statsByFormat)) { $representationDao = Application::getRepresentationDAO(); $representation = $representationDao->getById($representationId); if (empty($representation)) { continue; } $statsByFormat[$representationId] = array( 'data' => array(), 'label' => $representation->getLocalizedName(), 'color' => $this->_getColor($representationId), 'total' => 0); } // Make sure we have entries for all years with stats. if (!array_key_exists($year, $statsByFormat[$representationId]['data'])) { $statsByFormat[$representationId]['data'][$year] = array_fill_keys($months, 0); } $statsByFormat[$representationId]['data'][$year][$month] = $metric; $statsByFormat[$representationId]['total'] += $metric; // Prepare the stats aggregating only by Month. if (!array_key_exists($year, $statsByMonth)) { $statsByMonth[$year] = array_fill_keys($months, 0); } $statsByMonth[$year][$month] += $metric; $totalDownloads += $metric; } if ($statsByMonth) { $datasetId = 'allDownloads'; // GraphJS works with datasets. $statsByMonth = array($datasetId => array( 'data' => $statsByMonth, 'label' => __('common.allDownloads'), 'color' => $this->_getColor(REALLY_BIG_NUMBER), 'total' => $totalDownloads )); } return array($statsByFormat, $statsByMonth, array_keys($years)); } /** * Retrieve the `allDownloads` dataset from the download stats * * @param $pubObjectId int ID of the object to get stats for * @param $stats array Optionally pass in stats that have already been * fetched from _getDownloadStats(). * @return $allDownloadStats array The `allDownloads` dataset */ function getAllDownloadsStats($pubObjectId, $stats = array()) { if (empty($stats)) { $stats = $this->_getDownloadStats($pubObjectId); } $allDownloadStats = array(); foreach($stats as $dataset) { if (array_key_exists('allDownloads', $dataset)) { $allDownloadStats = $dataset['allDownloads']; } } return $allDownloadStats; } /** * Callback to fill cache with data, if empty. * @param $cache FileCache * @param $pubObjectId int * @return array */ function _downloadStatsCacheMiss($cache, $pubObjectId) { $filter = array( STATISTICS_DIMENSION_SUBMISSION_ID => $pubObjectId, STATISTICS_DIMENSION_ASSOC_TYPE => ASSOC_TYPE_SUBMISSION_FILE ); $orderBy = array(STATISTICS_DIMENSION_MONTH => STATISTICS_ORDER_ASC); $reportPlugin = $this->getReportPlugin(); $application = Application::get(); $statsReports = $application->getMetrics(current($reportPlugin->getMetricTypes()), array(STATISTICS_DIMENSION_MONTH, STATISTICS_DIMENSION_REPRESENTATION_ID), $filter, $orderBy); $cache->setEntireCache(array($pubObjectId => $statsReports)); return $statsReports; } /** * Return a color RGB code to be used in the graph. * @private * @param $num integer * @return string */ function _getColor($num) { $hash = md5('color' . $num * 2); return hexdec(substr($hash, 0, 2)) . ',' . hexdec(substr($hash, 2, 2)) . ',' . hexdec(substr($hash, 4, 2)); } /** * Get context wide setting. If the context or the setting does not exist, * get the site wide setting. * @param $context Context * @param $name Setting name * @return mixed */ function _getPluginSetting($context, $name) { $pluginSettingsDao = DAORegistry::getDAO('PluginSettingsDAO'); if ($context && $pluginSettingsDao->settingExists($context->getId(), $this->getName(), $name)) { return $this->getSetting($context->getId(), $name); } else { return $this->getSetting(CONTEXT_ID_NONE, $name); } } }
Simpan