| <?php |
|
|
| |
| |
| |
| |
| |
| |
|
|
| namespace Piwik\Plugin; |
|
|
| use Piwik\ArchiveProcessor; |
| use Piwik\Cache; |
| use Piwik\CacheId; |
| use Piwik\Config as PiwikConfig; |
| use Piwik\Container\StaticContainer; |
| use Piwik\ErrorHandler; |
| use Piwik\Log; |
| use Piwik\Piwik; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| class Archiver |
| { |
| public static $ARCHIVE_DEPENDENT = true; |
|
|
| |
| |
| |
| private $processor; |
|
|
| |
| |
| |
| private $enabled; |
|
|
| |
| |
| |
| protected $maximumRows; |
|
|
| |
| |
| |
| |
| |
| private $pluginName = null; |
|
|
| |
| |
| |
| |
| public function __construct(ArchiveProcessor $processor, ?string $pluginName = null) |
| { |
| $this->maximumRows = PiwikConfig::getInstance()->General['datatable_archiving_maximum_rows_standard']; |
| $this->processor = $processor; |
| $this->enabled = true; |
| $this->pluginName = $pluginName; |
| } |
|
|
| private function getPluginName(): string |
| { |
| return $this->pluginName ?: Piwik::getPluginNameOfMatomoClass(get_class($this)); |
| } |
|
|
| |
| |
| |
| |
| |
| private function getRecordBuilders(string $pluginName): array |
| { |
| $transientCache = Cache::getTransientCache(); |
| $cacheKey = CacheId::siteAware('Archiver.RecordBuilders') . '.' . $pluginName; |
|
|
| $recordBuilders = $transientCache->fetch($cacheKey); |
| if ($recordBuilders === false) { |
| $recordBuilderClasses = $this->getAllRecordBuilderClasses(); |
|
|
| |
| $recordBuilderClasses = array_filter($recordBuilderClasses, function ($className) use ($pluginName) { |
| return Piwik::getPluginNameOfMatomoClass($className) == $pluginName; |
| }); |
|
|
| $recordBuilders = array_map(function ($className) { |
| return StaticContainer::getContainer()->make($className); |
| }, $recordBuilderClasses); |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| Piwik::postEvent('Archiver.addRecordBuilders', [&$recordBuilders], false, [$pluginName]); |
|
|
| $transientCache->save($cacheKey, $recordBuilders); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| Piwik::postEvent('Archiver.filterRecordBuilders', [&$recordBuilders]); |
|
|
| return $recordBuilders; |
| } |
|
|
| private function filterRecordBuildersByRequestedRecords(array $recordBuilders, array $requestedReports): array |
| { |
| |
| if (empty($recordBuilders)) { |
| return $recordBuilders; |
| } |
|
|
| if (!empty($requestedReports)) { |
| $recordBuilders = array_filter($recordBuilders, function (ArchiveProcessor\RecordBuilder $builder) use ($requestedReports) { |
| return $builder->isBuilderForAtLeastOneOf($this->processor, $requestedReports); |
| }); |
| } |
|
|
| if (0 === count($recordBuilders)) { |
| Log::debug( |
| 'Archiver: No record builders found for requested records %s', |
| implode(',', $this->processor->getParams()->getArchiveOnlyReportAsArray()) |
| ); |
| } |
|
|
| return $recordBuilders; |
| } |
|
|
| |
| |
| |
| final public function callAggregateDayReport() |
| { |
| try { |
| ErrorHandler::pushFatalErrorBreadcrumb(static::class); |
|
|
| $pluginName = $this->getPluginName(); |
|
|
| if (Manager::getInstance()->isPluginLoaded($pluginName)) { |
| $allRecordBuilders = $this->getRecordBuilders($pluginName); |
| $recordBuilders = $this->filterRecordBuildersByRequestedRecords($allRecordBuilders, $this->processor->getParams()->getArchiveOnlyReportAsArray()); |
|
|
| foreach ($recordBuilders as $recordBuilder) { |
| if (!$recordBuilder->isEnabled($this->getProcessor())) { |
| continue; |
| } |
|
|
| $originalQueryHint = $this->getProcessor()->getLogAggregator()->getQueryOriginHint(); |
| $newQueryHint = $originalQueryHint . ' ' . $recordBuilder->getQueryOriginHint(); |
| try { |
| $this->getProcessor()->getLogAggregator()->setQueryOriginHint($newQueryHint); |
| $recordBuilder->buildFromLogs($this->getProcessor()); |
| } finally { |
| $this->getProcessor()->getLogAggregator()->setQueryOriginHint($originalQueryHint); |
| } |
| } |
| } |
|
|
| $this->aggregateDayReport(); |
|
|
| $this->processDependentArchivesForPlugins(); |
| } finally { |
| ErrorHandler::popFatalErrorBreadcrumb(); |
| } |
| } |
|
|
| |
| |
| |
| final public function callAggregateMultipleReports() |
| { |
| try { |
| ErrorHandler::pushFatalErrorBreadcrumb(static::class); |
|
|
| $pluginName = $this->getPluginName(); |
|
|
| if (Manager::getInstance()->isPluginLoaded($pluginName)) { |
| $allRecordBuilders = $this->getRecordBuilders($pluginName); |
| $recordBuilders = $this->filterRecordBuildersByRequestedRecords($allRecordBuilders, $this->processor->getParams()->getArchiveOnlyReportAsArray()); |
|
|
| foreach ($recordBuilders as $recordBuilder) { |
| if (!$recordBuilder->isEnabled($this->getProcessor())) { |
| continue; |
| } |
|
|
| $originalQueryHint = $this->getProcessor()->getLogAggregator()->getQueryOriginHint(); |
| $newQueryHint = $originalQueryHint . ' ' . $recordBuilder->getQueryOriginHint(); |
| try { |
| $this->getProcessor()->getLogAggregator()->setQueryOriginHint($newQueryHint); |
| $recordBuilder->buildForNonDayPeriod($this->getProcessor()); |
| } finally { |
| $this->getProcessor()->getLogAggregator()->setQueryOriginHint($originalQueryHint); |
| } |
| } |
| } |
|
|
| $this->aggregateMultipleReports(); |
|
|
| $this->processDependentArchivesForPlugins(); |
| } finally { |
| ErrorHandler::popFatalErrorBreadcrumb(); |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public function aggregateDayReport() |
| { |
| |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public function aggregateMultipleReports() |
| { |
| |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| protected function getProcessor() |
| { |
| return $this->processor; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| protected function getLogAggregator() |
| { |
| return $this->getProcessor()->getLogAggregator(); |
| } |
|
|
| public function disable() |
| { |
| $this->enabled = false; |
| } |
|
|
| |
| |
| |
| |
| |
| public function isEnabled() |
| { |
| return $this->enabled; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| public static function shouldRunEvenWhenNoVisits() |
| { |
| return false; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public function getDependentSegmentsToArchive(): array |
| { |
| return []; |
| } |
|
|
| protected function isRequestedReport(string $reportName) |
| { |
| $requestedReport = $this->getProcessor()->getParams()->getArchiveOnlyReport(); |
|
|
| return empty($requestedReport) || $requestedReport == $reportName; |
| } |
|
|
| private function processDependentArchivesForPlugins() |
| { |
| if (!self::$ARCHIVE_DEPENDENT) { |
| return; |
| } |
|
|
| $dependentSegments = $this->getDependentSegmentsToArchive(); |
| foreach ($dependentSegments as $dependentSegment) { |
| $plugin = $this->getPluginName(); |
| $segment = $dependentSegment; |
|
|
| if (is_array($dependentSegment)) { |
| $plugin = $dependentSegment['plugin'] ?? $plugin; |
| $segment = $dependentSegment['segment']; |
| } |
|
|
| $this->getProcessor()->processDependentArchive($plugin, $segment); |
| } |
| } |
|
|
| private static function getDefaultConstructibleClasses(array $classes): array |
| { |
| return array_filter($classes, function ($className) { |
| return (new \ReflectionClass($className))->getConstructor()->getNumberOfRequiredParameters() == 0; |
| }); |
| } |
|
|
| private static function getAllRecordBuilderClasses(): array |
| { |
| $transientCache = Cache::getTransientCache(); |
| $cacheKey = CacheId::siteAware('RecordBuilders.allRecordBuilders'); |
|
|
| $recordBuilderClasses = $transientCache->fetch($cacheKey); |
| if ($recordBuilderClasses === false) { |
| $recordBuilderClasses = Manager::getInstance()->findMultipleComponents('RecordBuilders', ArchiveProcessor\RecordBuilder::class); |
| $recordBuilderClasses = self::getDefaultConstructibleClasses($recordBuilderClasses); |
|
|
| $transientCache->save($cacheKey, $recordBuilderClasses); |
| } |
| return $recordBuilderClasses; |
| } |
|
|
| public static function doesPluginHaveRecordBuilders(string $pluginName): bool |
| { |
| $recordBuilders = self::getAllRecordBuilderClasses(); |
| foreach ($recordBuilders as $builder) { |
| if ($pluginName === Piwik::getPluginNameOfMatomoClass($builder)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| } |
|
|