Open Monograph Press  3.3.0
UsageStatsLoader.inc.php
1 <?php
2 
16 import('lib.pkp.classes.task.FileLoader');
17 
20 define('COUNTER_DOUBLE_CLICK_TIME_FILTER_SECONDS_HTML', 10);
21 define('COUNTER_DOUBLE_CLICK_TIME_FILTER_SECONDS_OTHER', 30);
22 
24 
27 
29  var $_plugin;
30 
32  var $_contextsByPath;
33 
36 
39 
44  function __construct($args) {
45  $plugin = PluginRegistry::getPlugin('generic', 'usagestatsplugin'); /* @var $plugin UsageStatsPlugin */
46  $this->_plugin = $plugin;
47 
48  if ($plugin->getSetting(CONTEXT_ID_NONE, 'compressArchives')) {
49  $this->setCompressArchives(true);
50  }
51 
52  $arg = current($args);
53 
54  switch ($arg) {
55  case 'autoStage':
56  if ($plugin->getSetting(0, 'createLogFiles')) {
57  $this->_autoStage = true;
58  }
59  break;
60  case 'externalLogFiles':
61  $this->_externalLogFiles = true;
62  break;
63  }
64 
65 
66  // Define the base filesystem path.
67  $args[0] = $plugin->getFilesPath();
68 
69  parent::__construct($args);
70 
71  if ($plugin->getEnabled()) {
72  // Load the metric type constant.
74 
75  import('classes.statistics.StatisticsHelper');
76  $statsHelper = new StatisticsHelper();
77  $geoLocationTool = $statsHelper->getGeoLocationTool();
78  $this->_geoLocationTool = $geoLocationTool;
79 
80  $plugin->import('UsageStatsTemporaryRecordDAO');
81  $statsDao = new UsageStatsTemporaryRecordDAO();
82  DAORegistry::registerDAO('UsageStatsTemporaryRecordDAO', $statsDao);
83 
84  $contextDao = Application::getContextDAO(); /* @var $contextDao ContextDAO */
85  $contextFactory = $contextDao->getAll(); /* @var $contextFactory DAOResultFactory */
86  $contextsByPath = array();
87  while ($context = $contextFactory->next()) { /* @var $context Context */
88  $contextsByPath[$context->getPath()] = $context;
89  }
90  $this->_contextsByPath = $contextsByPath;
91 
92  $this->checkFolderStructure(true);
93 
94 
95  }
96  }
97 
101  function getName() {
102  return __('plugins.generic.usageStats.usageStatsLoaderName');
103  }
104 
108  protected function executeActions() {
109  $plugin = $this->_plugin;
110  if (!$plugin->getEnabled()) {
111  $this->addExecutionLogEntry(__('plugins.generic.usageStats.pluginNotEnabled'), SCHEDULED_TASK_MESSAGE_TYPE_WARNING);
112  return false;
113  }
114 
115  // It's possible that the processing directory has files that
116  // were being processed but the php process was stopped before
117  // finishing the processing, or there may be a concurrent process running.
118  // Warn the user if this is the case.
119  $processingDirFiles = glob($this->getProcessingPath() . DIRECTORY_SEPARATOR . '*');
120  $processingDirError = is_array($processingDirFiles) && count($processingDirFiles);
121  if ($processingDirError) {
122  $this->addExecutionLogEntry(__('plugins.generic.usageStats.processingPathNotEmpty', array('directory' => $this->getProcessingPath())), SCHEDULED_TASK_MESSAGE_TYPE_ERROR);
123  }
124 
125  if ($this->_autoStage) $this->autoStage();
126 
127  return (parent::executeActions() && !$processingDirError);
128  }
129 
135  protected function processFile($filePath) {
136  $fhandle = fopen($filePath, 'r');
137  $geoTool = $this->_geoLocationTool;
138  if (!$fhandle) {
139  throw new Exception(__('plugins.generic.usageStats.openFileFailed', array('file' => $filePath)));
140  }
141 
142  $loadId = basename($filePath);
143  $statsDao = DAORegistry::getDAO('UsageStatsTemporaryRecordDAO'); /* @var $statsDao UsageStatsTemporaryRecordDAO */
144 
145  // Make sure we don't have any temporary records associated
146  // with the current load id in database.
147  $statsDao->deleteByLoadId($loadId);
148 
149  $lastInsertedEntries = array();
150  $lineNumber = 0;
151 
152  while(!feof($fhandle)) {
153  $lineNumber++;
154  $line = trim(fgets($fhandle));
155  if (empty($line) || substr($line, 0, 1) === "#") continue; // Spacing or comment lines.
156  $entryData = $this->_getDataFromLogEntry($line);
157  if (!$this->_isLogEntryValid($entryData, $lineNumber)) {
158  throw new Exception(__('plugins.generic.usageStats.invalidLogEntry',
159  array('file' => $filePath, 'lineNumber' => $lineNumber)));
160  }
161 
162  // Avoid internal apache requests.
163  if ($entryData['url'] == '*') continue;
164 
165  // Avoid non sucessful requests.
166  $sucessfulReturnCodes = array(200, 304);
167  if (!in_array($entryData['returnCode'], $sucessfulReturnCodes)) continue;
168 
169  // Avoid bots.
170  if (Core::isUserAgentBot($entryData['userAgent'])) continue;
171 
172  list($assocType, $contextPaths, $page, $op, $args) = $this->_getUrlMatches($entryData['url'], $filePath, $lineNumber);
173  if ($assocType && $contextPaths && $page && $op) {
174  list($assocId, $assocType) = $this->getAssoc($assocType, $contextPaths, $page, $op, $args);
175  } else {
176  $assocId = $assocType = null;
177  }
178 
179  if(!$assocId || !$assocType) continue;
180 
181  $countryCode = $cityName = $region = null;
182  $plugin = $this->_plugin;
183  if (!$plugin->getSetting(CONTEXT_ID_NONE, 'dataPrivacyOption')) {
184  list($countryCode, $cityName, $region) = $geoTool ? $geoTool->getGeoLocation($entryData['ip']) : array(null, null, null);
185  // Check optional columns setting.
186  $optionalColumns = $plugin->getSetting(CONTEXT_ID_NONE, 'optionalColumns');
187  if (!in_array(STATISTICS_DIMENSION_CITY, $optionalColumns)) $cityName = null;
188  if (!in_array(STATISTICS_DIMENSION_REGION, $optionalColumns)) $cityName = $region = null;
189  }
190  $day = date('Ymd', $entryData['date']);
191 
192  $type = $this->getFileTypeFromAssoc($assocType, $assocId);
193 
194  // Implement double click filtering.
195  $entryHash = $assocType . $assocId . $entryData['ip'];
196 
197  // Clean the last inserted entries, removing the entries that have
198  // no importance for the time between requests check.
199  $biggestTimeFilter = COUNTER_DOUBLE_CLICK_TIME_FILTER_SECONDS_OTHER;
200  foreach($lastInsertedEntries as $hash => $time) {
201  if ($time + $biggestTimeFilter < $entryData['date']) {
202  unset($lastInsertedEntries[$hash]);
203  }
204  }
205 
206  // Time between requests check.
207  if (isset($lastInsertedEntries[$entryHash])) {
208  // Decide what time filter to use, depending on object type.
209  if ($type == STATISTICS_FILE_TYPE_PDF || $type == STATISTICS_FILE_TYPE_OTHER) {
210  $timeFilter = COUNTER_DOUBLE_CLICK_TIME_FILTER_SECONDS_OTHER;
211  } else {
212  $timeFilter = COUNTER_DOUBLE_CLICK_TIME_FILTER_SECONDS_HTML;
213  }
214 
215  $secondsBetweenRequests = $entryData['date'] - $lastInsertedEntries[$entryHash];
216  if ($secondsBetweenRequests < $timeFilter) {
217  // We have to store the last access,
218  // so we delete the most recent one.
219  $statsDao->deleteRecord($assocType, $assocId, $lastInsertedEntries[$entryHash], $loadId);
220  }
221  }
222 
223  $lastInsertedEntries[$entryHash] = $entryData['date'];
224  $statsDao->insert($assocType, $assocId, $day, $entryData['date'], $countryCode, $region, $cityName, $type, $loadId);
225  }
226 
227  fclose($fhandle);
228  $loadResult = $this->_loadData($loadId);
229  $statsDao->deleteByLoadId($loadId);
230 
231  if (!$loadResult) {
232  $this->addExecutionLogEntry(__('plugins.generic.usageStats.loadDataError',
233  array('file' => $filePath)), SCHEDULED_TASK_MESSAGE_TYPE_ERROR);
234  return FILE_LOADER_RETURN_TO_STAGING;
235  } else {
236  return true;
237  }
238  }
239 
240 
241  //
242  // Protected methods.
243  //
247  protected function getMetricType() {
249  $applicationName = $application->getName();
250  switch ($applicationName) {
251  case 'ojs2':
252  return OJS_METRIC_TYPE_COUNTER;
253  break;
254  case 'omp':
255  return OMP_METRIC_TYPE_COUNTER;
256  break;
257  case 'ops':
258  return OPS_METRIC_TYPE_COUNTER;
259  break;
260  default:
261  assert(false);
262  }
263  }
264 
265 
266  //
267  // Protected methods.
268  //
273  protected function autoStage() {
274  $plugin = $this->_plugin;
275 
276  // Copy all log files to stage directory, except the current day one.
277  $fileMgr = new FileManager();
278  $logFiles = array();
279  $logsDirFiles = glob($plugin->getUsageEventLogsPath() . DIRECTORY_SEPARATOR . '*');
280  // It's possible that the processing directory have files that
281  // were being processed but the php process was stopped before
282  // finishing the processing. Just copy them to the stage directory too.
283  $processingDirFiles = glob($this->getProcessingPath() . DIRECTORY_SEPARATOR . '*');
284  if (is_array($logsDirFiles)) {
285  $logFiles = array_merge($logFiles, $logsDirFiles);
286  }
287 
288  if (is_array($processingDirFiles)) {
289  $logFiles = array_merge($logFiles, $processingDirFiles);
290  }
291 
292  foreach ($logFiles as $filePath) {
293  // Make sure it's a file.
294  if ($fileMgr->fileExists($filePath)) {
295  // Avoid current day file.
296  $filename = pathinfo($filePath, PATHINFO_BASENAME);
297  $currentDayFilename = $plugin->getUsageEventCurrentDayLogName();
298  if ($filename == $currentDayFilename) continue;
299  $this->moveFile(pathinfo($filePath, PATHINFO_DIRNAME), $this->getStagePath(), $filename);
300  }
301  }
302  }
303 
312  protected function getFileTypeFromAssoc($assocType, $assocId) {
313  // Check downloaded file type, if any.
314  $file = null;
315  $type = null;
316  if ($assocType == ASSOC_TYPE_SUBMISSION_FILE || $assocType == ASSOC_TYPE_SUBMISSION_FILE_COUNTER_OTHER) {
317  $submissionFileDao = DAORegistry::getDAO('SubmissionFileDAO'); /* @var $submissionFileDao SubmissionFileDAO */
318  $file = $submissionFileDao->getLatestRevision($assocId);
319  }
320 
321  if ($file) $type = $this->getFileTypeFromFile($file);
322 
323  if (!$type) {
325  $applicationName = $application->getName();
326  switch ($applicationName) {
327  case 'ojs2':
328  $type = $this->getOJSFileTypeFromAssoc($assocType, $assocId);
329  break;
330  }
331  }
332  return $type;
333  }
334 
343  function getOJSFileTypeFromAssoc($assocType, $assocId) {
344  $type = null;
345  switch ($assocType) {
346  case ASSOC_TYPE_ISSUE_GALLEY:
347  $issueGalleyDao = DAORegistry::getDAO('IssueGalleyDAO');
348  $issueGalley = $issueGalleyDao->getById($assocId);
349  $type = $this->getFileTypeFromFile($issueGalley);
350  break;
351  }
352  return $type;
353  }
354 
361  protected function getFileTypeFromFile($file) {
362  if (!is_a($file, 'PKPFile')) {
363  throw new Exception('Wrong object type, expected PKPFile.');
364  }
365  $fileType = $file->getFileType();
366  $fileExtension = pathinfo($file->getOriginalFileName(), PATHINFO_EXTENSION);
367  switch ($fileType) {
368  case 'application/pdf':
369  case 'application/x-pdf':
370  case 'text/pdf':
371  case 'text/x-pdf':
372  $type = STATISTICS_FILE_TYPE_PDF;
373  break;
374  case 'application/octet-stream':
375  if ($fileExtension == 'pdf') {
376  $type = STATISTICS_FILE_TYPE_PDF;
377  } else {
378  $type = STATISTICS_FILE_TYPE_OTHER;
379  }
380  break;
381  case 'application/msword':
382  $type = STATISTICS_FILE_TYPE_DOC;
383  break;
384  case 'application/zip':
385  if ($fileExtension == 'docx') {
386  $type = STATISTICS_FILE_TYPE_DOC;
387  } else {
388  $type = STATISTICS_FILE_TYPE_OTHER;
389  }
390  break;
391  case 'text/html':
392  $type = STATISTICS_FILE_TYPE_HTML;
393  break;
394  default:
395  $type = STATISTICS_FILE_TYPE_OTHER;
396  }
397 
398  return $type;
399  }
400 
411  protected function getAssoc($assocType, $contextPaths, $page, $op, $args) {
412  $assocId = $assocTypeToReturn = null;
413  switch ($assocType) {
414  case ASSOC_TYPE_SUBMISSION:
415  if (!isset($args[0])) break;
416  $submissionId = $args[0];
417  $submissionDao = DAORegistry::getDAO('SubmissionDAO'); /* @var $submissionDao SubmissionDAO */
418  $submission = $submissionDao->getById($submissionId);
419  if ($submission) {
420  $assocId = $submission->getId();
421  $assocTypeToReturn = $assocType;
422  }
423  break;
425  $context = $this->getContextByPath($contextPaths);
426  if ($context) {
427  $assocId = $context->getId();
428  $assocTypeToReturn = $assocType;
429  }
430  break;
431  }
432 
433  // Object not found, return no assoc info at all.
434  if (!$assocId) $assocTypeToReturn = null;
435 
436  if (!$assocId && !$assocTypeToReturn) {
438  $applicationName = $application->getName();
439  switch ($applicationName) {
440  case 'ojs2':
441  list($assocId, $assocTypeToReturn) = $this->getOJSAssoc($assocType, $contextPaths, $page, $op, $args);
442  break;
443  case 'omp':
444  list($assocId, $assocTypeToReturn) = $this->getOMPAssoc($assocType, $contextPaths, $page, $op, $args);
445  break;
446  case 'ops':
447  list($assocId, $assocTypeToReturn) = $this->getOPSAssoc($assocType, $contextPaths, $page, $op, $args);
448  break;
449  }
450  }
451  return array($assocId, $assocTypeToReturn);
452  }
453 
464  protected function getOJSAssoc($assocType, $contextPaths, $page, $op, $args) {
465  $assocId = $assocTypeToReturn = null;
466  switch ($assocType) {
467  case ASSOC_TYPE_SUBMISSION_FILE:
468  if (!isset($args[0])) break;
469  $submissionId = $args[0];
470  $submissionDao = DAORegistry::getDAO('SubmissionDAO'); /* @var $submissionDao SubmissionDAO */
471  $article = $submissionDao->getById($submissionId);
472  if (!$article) break;
473 
474  if (!isset($args[2])) break;
475  $fileId = $args[2];
476  $articleFileDao = DAORegistry::getDAO('SubmissionFileDAO');
477  $articleFile = $articleFileDao->getLatestRevision($fileId);
478  if (!$articleFile) break;
479 
480  $assocId = $articleFile->getFileId();
481 
482  // is the file article full text
483  $genreDao = DAORegistry::getDAO('GenreDAO');
484  $genre = $genreDao->getById($articleFile->getGenreId());
485  if ($genre->getCategory() != GENRE_CATEGORY_DOCUMENT || $genre->getSupplementary() || $genre->getDependent()) {
486  $assocTypeToReturn = ASSOC_TYPE_SUBMISSION_FILE_COUNTER_OTHER;
487  } else {
488  $assocTypeToReturn = $assocType;
489  }
490  break;
491  case ASSOC_TYPE_ISSUE:
492  case ASSOC_TYPE_ISSUE_GALLEY:
493  if (!isset($args[0])) break;
494  $issueId = $args[0];
495  $issueDao = DAORegistry::getDAO('IssueDAO');
496  if (isset($this->_contextsByPath[current($contextPaths)])) {
497  $context = $this->_contextsByPath[current($contextPaths)];
498  $issue = $issueDao->getById($issueId, $context->getId());
499  if ($issue) {
500  $assocId = $issue->getId();
501  } else {
502  break;
503  }
504  } else {
505  break;
506  }
507 
508  $assocTypeToReturn = $assocType;
509  // Allows next case.
510  case ASSOC_TYPE_ISSUE_GALLEY:
511  if (!isset($issue) || !isset($args[1])) break;
512  $issueGalleyId = $args[1];
513  $issueGalleyDao = DAORegistry::getDAO('IssueGalleyDAO');
514  $issueGalley = $issueGalleyDao->getById($issueGalleyId, $issue->getId());
515  if ($issueGalley) {
516  $assocId = $issueGalley->getId();
517  } else {
518  // Make sure we clean up values from the above case.
519  $assocId = $assocTypeToReturn = null;
520  }
521  break;
522  }
523  return array($assocId, $assocTypeToReturn);
524  }
525 
534  protected function getOMPAssoc($assocType, $contextPaths, $page, $op, $args) {
535  $assocId = $assocTypeToReturn = null;
536  switch ($assocType) {
537  case ASSOC_TYPE_SUBMISSION_FILE:
538  if (!isset($args[0])) break;
539  $submissionId = $args[0];
540  $submissionDao = DAORegistry::getDAO('SubmissionDAO'); /* @var $submissionDao SubmissionDAO */
541  $monograph = $submissionDao->getById($submissionId);
542  if (!$monograph) break;
543 
544  if (!isset($args[2])) break;
545  $fileIdAndRevision = $args[2];
546  list($fileId, $revision) = array_map(function($a) {
547  return (int) $a;
548  }, preg_split('/-/', $fileIdAndRevision));
549 
550  $monographFileDao = DAORegistry::getDAO('SubmissionFileDAO'); /* @var $monographFileDao SubmissionFileDAO */
551  $monographFile = $monographFileDao->getRevision($fileId, $revision);
552  if ($monographFile) {
553  $assocId = $monographFile->getFileId();
554  }
555 
556  $assocTypeToReturn = $assocType;
557  break;
558  case ASSOC_TYPE_SERIES:
559  if (!isset($args[0])) break;
560  $seriesPath = $args[0];
561  $seriesDao = Application::getSectionDAO(); /* @var $seriesDao SeriesDAO */
562  if (isset($this->_contextsByPath[current($contextPaths)])) {
563  $context = $this->_contextsByPath[current($contextPaths)];
564  $series = $seriesDao->getByPath($seriesPath, $context->getId());
565  if ($series) {
566  $assocId = $series->getId();
567  }
568  }
569 
570  $assocTypeToReturn = $assocType;
571  break;
572  }
573 
574  return array($assocId, $assocTypeToReturn);
575  }
576 
587  protected function getOPSAssoc($assocType, $contextPaths, $page, $op, $args) {
588  $assocId = $assocTypeToReturn = null;
589  switch ($assocType) {
590  case ASSOC_TYPE_SUBMISSION_FILE:
591  if (!isset($args[0])) break;
592  $submissionId = $args[0];
593  $submissionDao = DAORegistry::getDAO('SubmissionDAO');
594  $article = $submissionDao->getById($submissionId);
595  if (!$article) break;
596 
597  if (!isset($args[2])) break;
598  $fileId = $args[2];
599  $articleFileDao = DAORegistry::getDAO('SubmissionFileDAO');
600  $articleFile = $articleFileDao->getLatestRevision($fileId);
601  if (!$articleFile) break;
602 
603  $assocId = $articleFile->getFileId();
604 
605  // is the file article full text
606  $genreDao = DAORegistry::getDAO('GenreDAO');
607  $genre = $genreDao->getById($articleFile->getGenreId());
608  if ($genre->getCategory() != GENRE_CATEGORY_DOCUMENT || $genre->getSupplementary() || $genre->getDependent()) {
609  $assocTypeToReturn = ASSOC_TYPE_SUBMISSION_FILE_COUNTER_OTHER;
610  } else {
611  $assocTypeToReturn = $assocType;
612  }
613  break;
614  }
615  return array($assocId, $assocTypeToReturn);
616  }
617 
625  protected function getContextByPath($contextPaths) {
627  $deepestContextDepthIndex = $application->getContextDepth() - 1;
628  $contextPath = $contextPaths[$deepestContextDepthIndex];
629 
630  $context = null;
631  if (isset($this->_contextsByPath[$contextPath])) {
632  $context = $this->_contextsByPath[$contextPath];
633  }
634 
635  return $context;
636  }
637 
644  protected function getExpectedPageAndOp() {
645  $pageAndOp = array(
647  'index/index'
648  )
649  );
651  $applicationName = $application->getName();
652  switch ($applicationName) {
653  case 'ojs2':
654  $pageAndOp = $pageAndOp + array(
655  ASSOC_TYPE_SUBMISSION_FILE => array(
656  'article/download'),
657  ASSOC_TYPE_SUBMISSION => array(
658  'article/view'),
659  ASSOC_TYPE_ISSUE => array(
660  'issue/view'),
661  ASSOC_TYPE_ISSUE_GALLEY => array(
662  'issue/download')
663  );
664  $pageAndOp[Application::getContextAssocType()][] = 'index';
665  break;
666  case 'omp':
667  $pageAndOp = $pageAndOp + array(
668  ASSOC_TYPE_SUBMISSION_FILE => array(
669  'catalog/download'),
670  ASSOC_TYPE_MONOGRAPH => array(
671  'catalog/book'),
672  ASSOC_TYPE_SERIES => array(
673  'catalog/series')
674  );
675  $pageAndOp[Application::getContextAssocType()][] = 'catalog/index';
676  break;
677  case 'ops':
678  $pageAndOp = $pageAndOp + array(
679  ASSOC_TYPE_SUBMISSION_FILE => array(
680  'preprint/download'),
681  ASSOC_TYPE_SUBMISSION => array(
682  'preprint/view')
683  );
684  $pageAndOp[Application::getContextAssocType()][] = 'index';
685  break;
686  }
687  return $pageAndOp;
688  }
689 
690 
691  //
692  // Private helper methods.
693  //
700  private function _isLogEntryValid($entry, $lineNumber) {
701  if (empty($entry)) {
702  return false;
703  }
704 
705  $date = $entry['date'];
706  if (!is_numeric($date) && $date <= 0) {
707  return false;
708  }
709 
710  return true;
711  }
712 
718  private function _getDataFromLogEntry($entry) {
719  $plugin = $this->_plugin; /* @var $plugin Plugin */
720  $createLogFiles = $plugin->getSetting(0, 'createLogFiles');
721  if (!$createLogFiles || $this->_externalLogFiles) {
722  // User wants to process log files that were not created by
723  // the usage stats plugin. Try to get a user defined regex to
724  // parse those external log files then.
725  $parseRegex = $plugin->getSetting(0, 'accessLogFileParseRegex');
726  } else {
727  // Regex to parse this plugin's log access files.
728  $parseRegex = '/^(?P<ip>\S+) \S+ \S+ "(?P<date>.*?)" (?P<url>\S+) (?P<returnCode>\S+) "(?P<userAgent>.*?)"/';
729  }
730 
731  // The default regex will parse only apache log files in combined format.
732  if (!$parseRegex) $parseRegex = '/^(?P<ip>\S+) \S+ \S+ \[(?P<date>.*?)\] "\S+ (?P<url>\S+).*?" (?P<returnCode>\S+) \S+ ".*?" "(?P<userAgent>.*?)"/';
733 
734  $returner = array();
735  if (preg_match($parseRegex, $entry, $m)) {
736  $associative = count(array_filter(array_keys($m), 'is_string')) > 0;
737  $returner['ip'] = $associative ? $m['ip'] : $m[1];
738  $returner['date'] = strtotime($associative ? $m['date'] : $m[2]);
739  $returner['url'] = urldecode($associative ? $m['url'] : $m[3]);
740  $returner['returnCode'] = $associative ? $m['returnCode'] : $m[4];
741  $returner['userAgent'] = $associative ? $m['userAgent'] : $m[5];
742  }
743 
744  return $returner;
745  }
746 
757  private function _getUrlMatches($url, $filePath, $lineNumber) {
758  $noMatchesReturner = array(null, null, null, null, null);
759  // Check the passed url.
760  $expectedPageAndOp = $this->getExpectedPageAndOp();
761 
762  $pathInfoDisabled = Config::getVar('general', 'disable_path_info');
763 
764  // Apache and usage stats plugin log files comes with complete or partial
765  // base url, remove it so system can retrieve path, page,
766  // operation and args.
767  $url = Core::removeBaseUrl($url);
768  if ($url) {
769  $contextPaths = Core::getContextPaths($url, !$pathInfoDisabled);
770  $page = Core::getPage($url, !$pathInfoDisabled);
771  $operation = Core::getOp($url, !$pathInfoDisabled);
772  $args = Core::getArgs($url, !$pathInfoDisabled);
773  } else {
774  // Could not remove the base url, can't go on.
775  $this->addExecutionLogEntry( __('plugins.generic.usageStats.removeUrlError',
776  array('file' => $filePath, 'lineNumber' => $lineNumber)), SCHEDULED_TASK_MESSAGE_TYPE_WARNING);
777  return $noMatchesReturner;
778  }
779 
780  // See bug #8698#.
781  if (is_array($contextPaths) && !$page && $operation == 'index') {
782  $page = 'index';
783  }
784 
785  if (empty($contextPaths) || !$page || !$operation) return $noMatchesReturner;
786 
787  $pageAndOperation = $page . '/' . $operation;
788 
789  $pageAndOpMatch = false;
790  // It matches the expected ones?
791  foreach ($expectedPageAndOp as $workingAssocType => $workingPageAndOps) {
792  foreach($workingPageAndOps as $workingPageAndOp) {
793  if ($pageAndOperation == $workingPageAndOp) {
794  // Expected url, don't look any futher.
795  $pageAndOpMatch = true;
796  break 2;
797  }
798  }
799  }
800 
801  if ($pageAndOpMatch) {
802  return array($workingAssocType, $contextPaths, $page, $operation, $args);
803  } else {
804  return $noMatchesReturner;
805  }
806  }
807 
816  private function _loadData($loadId) {
817  $statsDao = DAORegistry::getDAO('UsageStatsTemporaryRecordDAO'); /* @var $statsDao UsageStatsTemporaryRecordDAO */
818  $metricsDao = DAORegistry::getDAO('MetricsDAO'); /* @var $metricsDao PKPMetricsDAO */
819  $metricsDao->purgeLoadBatch($loadId);
820 
821  while ($record = $statsDao->getNextByLoadId($loadId)) {
822  $record['metric_type'] = $this->getMetricType();
823  $metricsDao->insertRecord($record);
824  }
825 
826  return true;
827  }
828 
829 }
830 
Application\getContextDAO
static getContextDAO()
Definition: Application.inc.php:145
$op
$op
Definition: lib/pkp/pages/help/index.php:18
$application
$application
Definition: index.php:61
UsageStatsLoader\__construct
__construct($args)
Definition: UsageStatsLoader.inc.php:59
DAORegistry\getDAO
static & getDAO($name, $dbconn=null)
Definition: DAORegistry.inc.php:57
UsageStatsLoader\$_contextsByPath
$_contextsByPath
Definition: UsageStatsLoader.inc.php:41
UsageStatsLoader\getExpectedPageAndOp
getExpectedPageAndOp()
Definition: UsageStatsLoader.inc.php:659
StatisticsHelper
Statistics helper class.
Definition: StatisticsHelper.inc.php:22
UsageStatsLoader\getOJSFileTypeFromAssoc
getOJSFileTypeFromAssoc($assocType, $assocId)
Definition: UsageStatsLoader.inc.php:358
Core\getArgs
static getArgs($urlInfo, $isPathInfo, $userVars=array())
Definition: Core.inc.php:221
UsageStatsLoader\getAssoc
getAssoc($assocType, $contextPaths, $page, $op, $args)
Definition: UsageStatsLoader.inc.php:426
UsageStatsLoader\getName
getName()
Definition: UsageStatsLoader.inc.php:116
UsageStatsLoader
Scheduled task to extract transform and load usage statistics data into database.
Definition: UsageStatsLoader.inc.php:23
UsageStatsLoader\$_autoStage
$_autoStage
Definition: UsageStatsLoader.inc.php:47
Core\getContextPaths
static getContextPaths($urlInfo, $isPathInfo, $contextList=null, $contextDepth=null, $userVars=array())
Definition: Core.inc.php:137
PluginRegistry\loadCategory
static loadCategory($category, $enabledOnly=false, $mainContextId=null)
Definition: PluginRegistry.inc.php:103
FileLoader\moveFile
moveFile($sourceDir, $destDir, $filename)
Definition: FileLoader.inc.php:295
Application\getContextAssocType
static getContextAssocType()
Definition: Application.inc.php:203
UsageStatsLoader\getOPSAssoc
getOPSAssoc($assocType, $contextPaths, $page, $op, $args)
Definition: UsageStatsLoader.inc.php:602
UsageStatsLoader\getFileTypeFromAssoc
getFileTypeFromAssoc($assocType, $assocId)
Definition: UsageStatsLoader.inc.php:327
UsageStatsLoader\getMetricType
getMetricType()
Definition: UsageStatsLoader.inc.php:262
Config\getVar
static getVar($section, $key, $default=null)
Definition: Config.inc.php:35
DAORegistry\registerDAO
static registerDAO($name, $dao)
Definition: DAORegistry.inc.php:40
Core\getOp
static getOp($urlInfo, $isPathInfo, $userVars=array())
Definition: Core.inc.php:204
UsageStatsLoader\$_geoLocationTool
$_geoLocationTool
Definition: UsageStatsLoader.inc.php:29
UsageStatsLoader\getFileTypeFromFile
getFileTypeFromFile($file)
Definition: UsageStatsLoader.inc.php:376
Core\isUserAgentBot
static isUserAgentBot($userAgent, $botRegexpsFile=COUNTER_USER_AGENTS_FILE)
Definition: Core.inc.php:103
FileLoader
Base scheduled task class to reliably handle files processing.
Definition: FileLoader.inc.php:26
FileLoader\setCompressArchives
setCompressArchives($compressArchives)
Definition: FileLoader.inc.php:175
Core\getPage
static getPage($urlInfo, $isPathInfo, $userVars=array())
Definition: Core.inc.php:188
UsageStatsLoader\$_externalLogFiles
$_externalLogFiles
Definition: UsageStatsLoader.inc.php:53
UsageStatsLoader\autoStage
autoStage()
Definition: UsageStatsLoader.inc.php:288
UsageStatsTemporaryRecordDAO
Operations for retrieving and adding temporary usage statistics records.
Definition: UsageStatsTemporaryRecordDAO.inc.php:17
FileLoader\getStagePath
getStagePath()
Definition: FileLoader.inc.php:135
UsageStatsLoader\getOMPAssoc
getOMPAssoc($assocType, $contextPaths, $page, $op, $args)
Definition: UsageStatsLoader.inc.php:549
ScheduledTask\addExecutionLogEntry
addExecutionLogEntry($message, $type=null)
Definition: ScheduledTask.inc.php:111
UsageStatsLoader\getContextByPath
getContextByPath($contextPaths)
Definition: UsageStatsLoader.inc.php:640
PluginRegistry\getPlugin
static getPlugin($category, $name)
Definition: PluginRegistry.inc.php:85
UsageStatsLoader\processFile
processFile($filePath)
Definition: UsageStatsLoader.inc.php:150
FileLoader\checkFolderStructure
checkFolderStructure($install=false)
Definition: FileLoader.inc.php:233
PKPApplication\get
static get()
Definition: PKPApplication.inc.php:235
UsageStatsLoader\getOJSAssoc
getOJSAssoc($assocType, $contextPaths, $page, $op, $args)
Definition: UsageStatsLoader.inc.php:479
UsageStatsLoader\$_plugin
$_plugin
Definition: UsageStatsLoader.inc.php:35
FileManager
Class defining basic operations for file management.
Definition: FileManager.inc.php:35
FileLoader\getProcessingPath
getProcessingPath()
Definition: FileLoader.inc.php:143
Application\getSectionDAO
static getSectionDAO()
Definition: Application.inc.php:153
Core\removeBaseUrl
removeBaseUrl($url)
Definition: Core.inc.php:233
UsageStatsLoader\executeActions
executeActions()
Definition: UsageStatsLoader.inc.php:123