configSection] public static $purgeDataOptions = [ 'delete_logs_enable' => 'Deletelogs', 'delete_logs_schedule_lowest_interval' => 'Deletelogs', 'delete_logs_older_than' => 'Deletelogs', 'delete_logs_max_rows_per_query' => 'Deletelogs', 'delete_logs_unused_actions_schedule_lowest_interval' => 'Deletelogs', 'delete_logs_unused_actions_max_rows_per_query' => 'Deletelogs', 'enable_auto_database_size_estimate' => 'Deletelogs', 'enable_database_size_estimate' => 'Deletelogs', 'delete_reports_enable' => 'Deletereports', 'delete_reports_older_than' => 'Deletereports', 'delete_reports_keep_basic_metrics' => 'Deletereports', 'delete_reports_keep_day_reports' => 'Deletereports', 'delete_reports_keep_week_reports' => 'Deletereports', 'delete_reports_keep_month_reports' => 'Deletereports', 'delete_reports_keep_year_reports' => 'Deletereports', 'delete_reports_keep_range_reports' => 'Deletereports', 'delete_reports_keep_segment_reports' => 'Deletereports', ]; private $dntChecker = null; private $ipAnonymizer = null; /** * Constructor. */ public function __construct() { parent::__construct(); $this->dntChecker = new DoNotTrackHeaderChecker(); $this->ipAnonymizer = new IPAnonymizer(); } public function install() { StaticContainer::get('Piwik\Plugins\PrivacyManager\Model\LogDataAnonymizations')->install(); } public function uninstall() { StaticContainer::get('Piwik\Plugins\PrivacyManager\Model\LogDataAnonymizations')->install(); } /** * Returns true if it is likely that the data for this report has been purged and if the * user should be told about that. * * In order for this function to return true, the following must also be true: * - The data table for this report must either be empty or not have been fetched. * - The period of this report is not a multiple period. * - The date of this report must be older than the delete_reports_older_than config option. * @param DataTableInterface $dataTable * @return bool */ public static function hasReportBeenPurged($dataTable) { $strPeriod = Common::getRequestVar('period', false); $strDate = Common::getRequestVar('date', false); if ( false !== $strPeriod && false !== $strDate && (is_null($dataTable) || (!empty($dataTable) && $dataTable->getRowsCount() == 0)) ) { $reportDate = self::getReportDate($strPeriod, $strDate); if (empty($reportDate)) { return false; } $reportYear = $reportDate->toString('Y'); $reportMonth = $reportDate->toString('m'); if (static::shouldReportBePurged($reportYear, $reportMonth)) { return true; } } return false; } /** * @param DataTable $dataTable * @param int|null $logsOlderThan If set, it is assumed that log deletion is enabled with the given amount of days * @return bool|void */ public static function haveLogsBeenPurged($dataTable, $logsOlderThan = null) { if (!empty($dataTable) && $dataTable->getRowsCount() != 0) { return false; } if ($logsOlderThan === null) { $settings = PrivacyManager::getPurgeDataSettings(); if ($settings['delete_logs_enable'] == 0) { return false; } $logsOlderThan = $settings['delete_logs_older_than']; } $logsOlderThan = (int) $logsOlderThan; $strPeriod = Common::getRequestVar('period', false); $strDate = Common::getRequestVar('date', false); if (false === $strPeriod || false === $strDate) { return false; } $logsOlderThan = Date::now()->subDay(1 + $logsOlderThan); $reportDate = self::getReportDate($strPeriod, $strDate); if (empty($reportDate)) { return false; } return $reportDate->isEarlier($logsOlderThan); } /** * @see \Piwik\Plugin::registerEvents */ public function registerEvents() { return [ 'AssetManager.getStylesheetFiles' => 'getStylesheetFiles', 'Tracker.setTrackerCacheGeneral' => 'setTrackerCacheGeneral', 'Tracker.isExcludedVisit' => [$this->dntChecker, 'checkHeaderInTracker'], 'Tracker.setVisitorIp' => [$this->ipAnonymizer, 'setVisitorIpAddress'], 'Installation.defaultSettingsForm.init' => 'installationFormInit', 'Installation.defaultSettingsForm.submit' => 'installationFormSubmit', 'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys', 'Template.pageFooter' => 'renderPrivacyPolicyLinks', 'Db.getTablesInstalled' => 'getTablesInstalled', 'Visualization.beforeRender' => 'onConfigureVisualisation', 'CustomJsTracker.shouldAddTrackerFile' => 'shouldAddTrackerFile', 'Request.shouldDisablePostProcessing' => 'shouldDisablePostProcessing' ]; } public function shouldDisablePostProcessing(&$shouldDisable, $request) { // We disable the post processor for this API method as it passes through the results of // `Live.getLastVisitsDetails`, which is already post processed. // Otherwise, the PostProcessor would trigger warning when trying to calculate a totals row. if ($request['method'] === 'PrivacyManager.findDataSubjects') { $shouldDisable = true; } } public function onConfigureVisualisation(Plugin\Visualization $view) { if ($view->requestConfig->getApiModuleToRequest() === 'Referrers' && !$view->requestConfig->idSubtable) { $config = new Config(); if ($config->anonymizeReferrer == ReferrerAnonymizer::EXCLUDE_NONE) { return; } if (!$view->config->show_footer_message) { $view->config->show_footer_message = ''; } $anonymizer = StaticContainer::get(ReferrerAnonymizer::class); $methods = $anonymizer->getAvailableAnonymizationOptions(); if (!empty($methods[$config->anonymizeReferrer])) { $view->config->show_footer_message .= Piwik::translate('PrivacyManager_InfoSomeReferrerInfoMayBeAnonymized', $methods[$config->anonymizeReferrer]); } } } /** * Register the new tables, so Matomo knows about them. * * @param array $allTablesInstalled */ public function getTablesInstalled(&$allTablesInstalled) { $allTablesInstalled[] = Common::prefixTable(LogDataAnonymizations::getDbTableName()); } public function isTrackerPlugin() { return true; } public function getClientSideTranslationKeys(&$translationKeys) { $translationKeys[] = 'CoreAdminHome_OptOutExplanation'; $translationKeys[] = 'CoreAdminHome_OptOutExplanationIntro'; $translationKeys[] = 'CoreAdminHome_OptOutCustomOptOutLink'; $translationKeys[] = 'CoreAdminHome_SettingsSaveSuccess'; $translationKeys[] = 'General_Action'; $translationKeys[] = 'General_ClickHere'; $translationKeys[] = 'General_DailyReports'; $translationKeys[] = 'General_Details'; $translationKeys[] = 'General_Id'; $translationKeys[] = 'General_MonthlyReports'; $translationKeys[] = 'General_RangeReports'; $translationKeys[] = 'General_Recommended'; $translationKeys[] = 'General_UserId'; $translationKeys[] = 'General_Visit'; $translationKeys[] = 'General_VisitId'; $translationKeys[] = 'General_VisitorID'; $translationKeys[] = 'General_VisitorIP'; $translationKeys[] = 'General_Website'; $translationKeys[] = 'General_WeeklyReports'; $translationKeys[] = 'General_YearlyReports'; $translationKeys[] = 'Intl_PeriodDays'; $translationKeys[] = 'Intl_PeriodMonths'; $translationKeys[] = 'Live_ViewVisitorProfile'; $translationKeys[] = 'PrivacyManager_AddUserIdToSearch'; $translationKeys[] = 'PrivacyManager_AddVisitorIPToSearch'; $translationKeys[] = 'PrivacyManager_AddVisitorIdToSearch'; $translationKeys[] = 'PrivacyManager_AnonymizeDataConfirm'; $translationKeys[] = 'PrivacyManager_AnonymizeDataNow'; $translationKeys[] = 'PrivacyManager_AnonymizeIp'; $translationKeys[] = 'PrivacyManager_AnonymizeIpDescription'; $translationKeys[] = 'PrivacyManager_AnonymizeIpHelp'; $translationKeys[] = 'PrivacyManager_AnonymizeIpInlineHelp'; $translationKeys[] = 'PrivacyManager_AnonymizeIpMaskLengtDescription'; $translationKeys[] = 'PrivacyManager_AnonymizeLocation'; $translationKeys[] = 'PrivacyManager_AnonymizeLocationHelp'; $translationKeys[] = 'PrivacyManager_AnonymizeOrderIdNote'; $translationKeys[] = 'PrivacyManager_AnonymizeProcessInfo'; $translationKeys[] = 'PrivacyManager_AnonymizeReferrer'; $translationKeys[] = 'PrivacyManager_AnonymizeReferrerNote'; $translationKeys[] = 'PrivacyManager_AnonymizeRowDataFrom'; $translationKeys[] = 'PrivacyManager_AnonymizeRowDataTo'; $translationKeys[] = 'PrivacyManager_AnonymizeSites'; $translationKeys[] = 'PrivacyManager_AnonymizeUserId'; $translationKeys[] = 'PrivacyManager_AnonymizeUserIdHelp'; $translationKeys[] = 'PrivacyManager_ApplyStyling'; $translationKeys[] = 'PrivacyManager_BackgroundColor'; $translationKeys[] = 'PrivacyManager_BuildYourOwn'; $translationKeys[] = 'PrivacyManager_DBPurged'; $translationKeys[] = 'PrivacyManager_DeleteAggregateReportsDetailedInfo'; $translationKeys[] = 'PrivacyManager_DeleteBothConfirm'; $translationKeys[] = 'PrivacyManager_DeleteDataInterval'; $translationKeys[] = 'PrivacyManager_DeleteLogsConfirm'; $translationKeys[] = 'PrivacyManager_DeleteLogsOlderThan'; $translationKeys[] = 'PrivacyManager_DeleteRawDataInfo'; $translationKeys[] = 'PrivacyManager_DeleteReportsConfirm'; $translationKeys[] = 'PrivacyManager_DeleteReportsInfo2'; $translationKeys[] = 'PrivacyManager_DeleteReportsInfo3'; $translationKeys[] = 'PrivacyManager_DeleteReportsOlderThan'; $translationKeys[] = 'PrivacyManager_DeleteSchedulingSettings'; $translationKeys[] = 'PrivacyManager_DeleteSelectedVisits'; $translationKeys[] = 'PrivacyManager_DeleteVisitsConfirm'; $translationKeys[] = 'PrivacyManager_DeletionFromMatomoOnly'; $translationKeys[] = 'PrivacyManager_DoNotTrack_Description'; $translationKeys[] = 'PrivacyManager_ExportSelectedVisits'; $translationKeys[] = 'PrivacyManager_ExportingNote'; $translationKeys[] = 'PrivacyManager_FindDataSubjectsBy'; $translationKeys[] = 'PrivacyManager_FindMatchingDataSubjects'; $translationKeys[] = 'PrivacyManager_FontColor'; $translationKeys[] = 'PrivacyManager_FontFamily'; $translationKeys[] = 'PrivacyManager_FontSize'; $translationKeys[] = 'PrivacyManager_ForceCookielessTracking'; $translationKeys[] = 'PrivacyManager_ForceCookielessTrackingDescription'; $translationKeys[] = 'PrivacyManager_ForceCookielessTrackingDescription2'; $translationKeys[] = 'PrivacyManager_ForceCookielessTrackingDescriptionNotWritable'; $translationKeys[] = 'PrivacyManager_GdprTools'; $translationKeys[] = 'PrivacyManager_GdprToolsOverviewHint'; $translationKeys[] = 'PrivacyManager_GdprToolsPageIntro1'; $translationKeys[] = 'PrivacyManager_GdprToolsPageIntro2'; $translationKeys[] = 'PrivacyManager_GdprToolsPageIntroAccessRight'; $translationKeys[] = 'PrivacyManager_GdprToolsPageIntroEraseRight'; $translationKeys[] = 'PrivacyManager_GeolocationAnonymizeIpNote'; $translationKeys[] = 'PrivacyManager_GetPurgeEstimate'; $translationKeys[] = 'PrivacyManager_KeepBasicMetrics'; $translationKeys[] = 'PrivacyManager_KeepBasicMetricsReportsDetailedInfo'; $translationKeys[] = 'PrivacyManager_KeepDataFor'; $translationKeys[] = 'PrivacyManager_KeepReportSegments'; $translationKeys[] = 'PrivacyManager_LastAction'; $translationKeys[] = 'PrivacyManager_LastDelete'; $translationKeys[] = 'PrivacyManager_LeastDaysInput'; $translationKeys[] = 'PrivacyManager_LeastMonthsInput'; $translationKeys[] = 'PrivacyManager_MatchingDataSubjects'; $translationKeys[] = 'PrivacyManager_NextDelete'; $translationKeys[] = 'PrivacyManager_NoDataSubjectsFound'; $translationKeys[] = 'PrivacyManager_OptOutAppearance'; $translationKeys[] = 'PrivacyManager_OptOutCustomize'; $translationKeys[] = 'PrivacyManager_OptOutHtmlCode'; $translationKeys[] = 'PrivacyManager_OptOutPreview'; $translationKeys[] = 'PrivacyManager_OptOutUseTracker'; $translationKeys[] = 'PrivacyManager_OptOutUseStandalone'; $translationKeys[] = 'PrivacyManager_OptOutCodeTypeExplanation'; $translationKeys[] = 'PrivacyManager_OptOutRememberToTest'; $translationKeys[] = 'PrivacyManager_OptOutRememberToTestBody'; $translationKeys[] = 'PrivacyManager_OptOutRememberToTestStep1'; $translationKeys[] = 'PrivacyManager_OptOutRememberToTestStep2'; $translationKeys[] = 'PrivacyManager_OptOutRememberToTestStep3'; $translationKeys[] = 'PrivacyManager_OptOutRememberToTestStep4'; $translationKeys[] = 'PrivacyManager_PseudonymizeUserId'; $translationKeys[] = 'PrivacyManager_PseudonymizeUserIdNote'; $translationKeys[] = 'PrivacyManager_PseudonymizeUserIdNote2'; $translationKeys[] = 'PrivacyManager_PurgingData'; $translationKeys[] = 'PrivacyManager_PurgeNow'; $translationKeys[] = 'PrivacyManager_PurgeNowConfirm'; $translationKeys[] = 'PrivacyManager_ReportsDataSavedEstimate'; $translationKeys[] = 'PrivacyManager_ResultIncludesAllVisits'; $translationKeys[] = 'PrivacyManager_ResultTruncated'; $translationKeys[] = 'PrivacyManager_SaveSettingsBeforePurge'; $translationKeys[] = 'PrivacyManager_SearchForDataSubject'; $translationKeys[] = 'PrivacyManager_SelectWebsite'; $translationKeys[] = 'PrivacyManager_ShowIntro'; $translationKeys[] = 'PrivacyManager_UnsetActionColumns'; $translationKeys[] = 'PrivacyManager_UnsetActionColumnsHelp'; $translationKeys[] = 'PrivacyManager_UnsetVisitColumns'; $translationKeys[] = 'PrivacyManager_UnsetVisitColumnsHelp'; $translationKeys[] = 'PrivacyManager_UseAnonymizeIp'; $translationKeys[] = 'PrivacyManager_UseAnonymizeOrderId'; $translationKeys[] = 'PrivacyManager_UseAnonymizedIpForVisitEnrichment'; $translationKeys[] = 'PrivacyManager_UseAnonymizedIpForVisitEnrichmentNote'; $translationKeys[] = 'PrivacyManager_UseDeleteLog'; $translationKeys[] = 'PrivacyManager_UseDeleteReports'; $translationKeys[] = 'PrivacyManager_VisitsMatchedCriteria'; $translationKeys[] = 'PrivacyManager_VisitsSuccessfullyDeleted'; $translationKeys[] = 'PrivacyManager_VisitsSuccessfullyExported'; $translationKeys[] = 'UsersManager_AllWebsites'; } public function setTrackerCacheGeneral(&$cacheContent) { $config = new Config(); $cacheContent = $config->setTrackerCacheGeneral($cacheContent); $cacheContent[self::OPTION_USERID_SALT] = self::getUserIdSalt(); $purgeSettings = PrivacyManager::getPurgeDataSettings(); $cacheContent['delete_logs_enable'] = $purgeSettings['delete_logs_enable']; $cacheContent['delete_logs_schedule_lowest_interval'] = $purgeSettings['delete_logs_schedule_lowest_interval']; $cacheContent['delete_logs_older_than'] = $purgeSettings['delete_logs_older_than']; } public function getStylesheetFiles(&$stylesheets) { $stylesheets[] = "plugins/PrivacyManager/vue/src/OptOutCustomizer/OptOutCustomizer.less"; $stylesheets[] = "plugins/PrivacyManager/vue/src/ManageGdpr/ManageGdpr.less"; $stylesheets[] = "plugins/PrivacyManager/stylesheets/gdprOverview.less"; $stylesheets[] = "plugins/PrivacyManager/vue/src/AnonymizeLogData/AnonymizeLogData.less"; $stylesheets[] = "plugins/PrivacyManager/stylesheets/footerLinks.less"; } /** * Customize the Installation "default settings" form. * * @param FormDefaultSettings $form */ public function installationFormInit(FormDefaultSettings $form) { $form->addElement( 'checkbox', 'do_not_track', null, [ 'content' => '