
<center><h2><strong>Ubuntu</strong></h2>
­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
<!DOCTYPE html>
<html>
<?php

/**
 * Matomo - free/libre analytics platform
 *
 * @link    https://matomo.org
 * @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
 */
namespace Piwik\Plugins\PrivacyManager;

use HTML_QuickForm2_DataSource_Array;
use Piwik\Common;
use Piwik\Config as PiwikConfig;
use Piwik\Container\StaticContainer;
use Piwik\DataTable;
use Piwik\DataTable\DataTableInterface;
use Piwik\Date;
use Piwik\Db;
use Piwik\Metrics;
use Piwik\Option;
use Piwik\Period;
use Piwik\Period\Range;
use Piwik\Piwik;
use Piwik\Plugin;
use Piwik\Plugins\FeatureFlags\FeatureFlagManager;
use Piwik\Plugins\Goals\Archiver;
use Piwik\Plugins\Installation\FormDefaultSettings;
use Piwik\Plugins\PrivacyManager\FeatureFlags\PrivacyCompliance;
use Piwik\Plugins\PrivacyManager\Model\LogDataAnonymizations;
use Piwik\Plugins\PrivacyManager\Settings\IPAnonymisation;
use Piwik\Request;
use Piwik\Site;
use Piwik\Tracker\Cache;
use Piwik\Tracker\GoalManager;
use Piwik\View;
use Piwik\Plugins\PrivacyManager\Settings\ReportRetention as ReportRetentionSetting;
use Piwik\Policy\PolicyManager;
/**
 * Specifically include this for Tracker API (which does not use autoloader)
 */
require_once PIWIK_INCLUDE_PATH . '/plugins/PrivacyManager/DoNotTrackHeaderChecker.php';
require_once PIWIK_INCLUDE_PATH . '/plugins/PrivacyManager/IPAnonymizer.php';
/**
 */
class PrivacyManager extends Plugin
{
    public const OPTION_LAST_DELETE_PIWIK_LOGS = "lastDelete_piwik_logs";
    public const OPTION_LAST_DELETE_UNUSED_LOG_ACTIONS = "lastDelete_piwik_unused_log_actions";
    public const OPTION_LAST_DELETE_PIWIK_REPORTS = 'lastDelete_piwik_reports';
    public const OPTION_LAST_DELETE_PIWIK_LOGS_INITIAL = "lastDelete_piwik_logs_initial";
    public const OPTION_USERID_SALT = 'useridsalt';
    // options for data purging feature array[configName => 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 \Piwik\Plugins\PrivacyManager\DoNotTrackHeaderChecker();
        $this->ipAnonymizer = new \Piwik\Plugins\PrivacyManager\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 = \Piwik\Plugins\PrivacyManager\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.Cache.getSiteAttributes' => 'setTrackerCacheSiteAttributes', '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', 'SitesManager.deleteSite.end' => 'deleteSiteSpecificAnonymisationSettings'];
    }
    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 (isset($request['method']) && $request['method'] === 'PrivacyManager.findDataSubjects') {
            $shouldDisable = \true;
        }
    }
    public function onConfigureVisualisation(Plugin\Visualization $view)
    {
        if ($view->requestConfig->getApiModuleToRequest() === 'Referrers' && !$view->requestConfig->idSubtable) {
            $idSite = $view->requestConfig->getRequestParam('idsite');
            if (!is_numeric($idSite) || !$idSite) {
                $idSite = null;
            } else {
                $idSite = (int) $idSite;
            }
            $config = new \Piwik\Plugins\PrivacyManager\Config($idSite);
            if ($config->anonymizeReferrer == \Piwik\Plugins\PrivacyManager\ReferrerAnonymizer::EXCLUDE_NONE) {
                return;
            }
            if (!$view->config->show_footer_message) {
                $view->config->show_footer_message = '';
            }
            $methods = \Piwik\Plugins\PrivacyManager\ReferrerAnonymizer::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_Ok';
        $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_AnonymizeData';
        $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[] = 'Ecommerce_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_AskingForConsent';
        $translationKeys[] = 'PrivacyManager_AwarenessDocumentation';
        $translationKeys[] = 'PrivacyManager_AwarenessDocumentationDesc1';
        $translationKeys[] = 'PrivacyManager_AwarenessDocumentationDesc2';
        $translationKeys[] = 'PrivacyManager_AwarenessDocumentationDesc3';
        $translationKeys[] = 'PrivacyManager_AwarenessDocumentationDesc4';
        $translationKeys[] = 'PrivacyManager_AwarenessDocumentationIntro';
        $translationKeys[] = 'PrivacyManager_BackgroundColor';
        $translationKeys[] = 'PrivacyManager_ConsentExplanation';
        $translationKeys[] = 'PrivacyManager_ApplyStyling';
        $translationKeys[] = 'PrivacyManager_BackgroundColor';
        $translationKeys[] = 'PrivacyManager_BuildYourOwn';
        $translationKeys[] = 'PrivacyManager_DBPurged';
        $translationKeys[] = 'PrivacyManager_DataRetention';
        $translationKeys[] = 'PrivacyManager_DataRetentionInMatomo';
        $translationKeys[] = 'PrivacyManager_DataRetentionOverall';
        $translationKeys[] = 'PrivacyManager_DeleteAggregateReportsDetailedInfo';
        $translationKeys[] = 'PrivacyManager_DeleteBothConfirm';
        $translationKeys[] = 'PrivacyManager_DeleteDataDescription';
        $translationKeys[] = 'PrivacyManager_DeleteDataInterval';
        $translationKeys[] = 'PrivacyManager_DeleteLogsConfirm';
        $translationKeys[] = 'PrivacyManager_DeleteLogsOlderThan';
        $translationKeys[] = 'PrivacyManager_DeleteOldAggregatedReports';
        $translationKeys[] = 'PrivacyManager_DeleteOldRawData';
        $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_DoNotTrack_Disabled';
        $translationKeys[] = 'PrivacyManager_DoNotTrack_DisabledMoreInfo';
        $translationKeys[] = 'PrivacyManager_DoNotTrack_Enabled';
        $translationKeys[] = 'PrivacyManager_DoNotTrack_EnabledMoreInfo';
        $translationKeys[] = 'PrivacyManager_DoNotTrack_SupportDNTPreference';
        $translationKeys[] = 'PrivacyManager_DoNotTrack_Deprecated';
        $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_GdprChecklistDesc1';
        $translationKeys[] = 'PrivacyManager_GdprChecklistDesc2';
        $translationKeys[] = 'PrivacyManager_GdprChecklists';
        $translationKeys[] = 'PrivacyManager_GdprOverview';
        $translationKeys[] = 'PrivacyManager_GdprOverviewIntro1';
        $translationKeys[] = 'PrivacyManager_GdprOverviewIntro2';
        $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_HowDoIAskForConsent';
        $translationKeys[] = 'PrivacyManager_HowDoIAskForConsentIntro';
        $translationKeys[] = 'PrivacyManager_HowDoIAskForConsentOutro';
        $translationKeys[] = 'PrivacyManager_IndividualsRights';
        $translationKeys[] = 'PrivacyManager_IndividualsRightsAccess';
        $translationKeys[] = 'PrivacyManager_IndividualsRightsChildren';
        $translationKeys[] = 'PrivacyManager_IndividualsRightsErasure';
        $translationKeys[] = 'PrivacyManager_IndividualsRightsInform';
        $translationKeys[] = 'PrivacyManager_IndividualsRightsIntro';
        $translationKeys[] = 'PrivacyManager_IndividualsRightsObject';
        $translationKeys[] = 'PrivacyManager_IndividualsRightsPortability';
        $translationKeys[] = 'PrivacyManager_IndividualsRightsRectification';
        $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_PurgeNow';
        $translationKeys[] = 'PrivacyManager_PurgeNowConfirm';
        $translationKeys[] = 'PrivacyManager_PurgingData';
        $translationKeys[] = 'PrivacyManager_RawDataNeverRemoved';
        $translationKeys[] = 'PrivacyManager_RawDataRemovedAfter';
        $translationKeys[] = 'PrivacyManager_ReportsDataSavedEstimate';
        $translationKeys[] = 'PrivacyManager_ReportsNeverRemoved';
        $translationKeys[] = 'PrivacyManager_ReportsRemovedAfter';
        $translationKeys[] = 'PrivacyManager_ResultIncludesAllVisits';
        $translationKeys[] = 'PrivacyManager_ResultTruncated';
        $translationKeys[] = 'PrivacyManager_SaveSettingsBeforePurge';
        $translationKeys[] = 'PrivacyManager_SearchForDataSubject';
        $translationKeys[] = 'PrivacyManager_SecurityProcedures';
        $translationKeys[] = 'PrivacyManager_SecurityProceduresDesc1';
        $translationKeys[] = 'PrivacyManager_SecurityProceduresDesc2';
        $translationKeys[] = 'PrivacyManager_SecurityProceduresDesc3';
        $translationKeys[] = 'PrivacyManager_SecurityProceduresDesc4';
        $translationKeys[] = 'PrivacyManager_SecurityProceduresIntro';
        $translationKeys[] = 'PrivacyManager_SeeAlsoOurOfficialGuidePrivacy';
        $translationKeys[] = 'PrivacyManager_SelectWebsite';
        $translationKeys[] = 'PrivacyManager_SiteDataNotAvailable';
        $translationKeys[] = 'PrivacyManager_SiteDataNotAvailableCertainSites';
        $translationKeys[] = 'PrivacyManager_VisitorLogsProfilesDisabledMessage';
        $translationKeys[] = 'PrivacyManager_VisitorLogsProfilesSiteNamesDisabledMessage';
        $translationKeys[] = 'PrivacyManager_PleaseEnableVisitorLogsProfiles';
        $translationKeys[] = 'PrivacyManager_PleaseEnableVisitorLogsProfilesSites';
        $translationKeys[] = 'PrivacyManager_TeaserHeader';
        $translationKeys[] = 'PrivacyManager_TrackingOptOut';
        $translationKeys[] = 'PrivacyManager_ShowIntro';
        $translationKeys[] = 'PrivacyManager_UnsetActionColumns';
        $translationKeys[] = 'PrivacyManager_UnsetActionColumnsHelp';
        $translationKeys[] = 'PrivacyManager_UnsetVisitColumns';
        $translationKeys[] = 'PrivacyManager_UnsetVisitColumnsHelp';
        $translationKeys[] = 'PrivacyManager_UseAnonymizeIp';
        $translationKeys[] = 'Ecommerce_UseAnonymizeOrderId';
        $translationKeys[] = 'PrivacyManager_UseAnonymizeTrackingData';
        $translationKeys[] = 'PrivacyManager_UseAnonymizedIpForVisitEnrichment';
        $translationKeys[] = 'PrivacyManager_UseAnonymizedIpForVisitEnrichmentNote';
        $translationKeys[] = 'PrivacyManager_UseDeleteLog';
        $translationKeys[] = 'PrivacyManager_UseDeleteReports';
        $translationKeys[] = 'PrivacyManager_VisitsMatchedCriteria';
        $translationKeys[] = 'PrivacyManager_VisitsSuccessfullyDeleted';
        $translationKeys[] = 'PrivacyManager_VisitsSuccessfullyExported';
        $translationKeys[] = 'PrivacyManager_WhenConsentIsNeededPart1';
        $translationKeys[] = 'PrivacyManager_WhenConsentIsNeededPart2';
        $translationKeys[] = 'PrivacyManager_WhenConsentIsNeededPart3';
        $translationKeys[] = 'PrivacyManager_WhenDoINeedConsent';
        $translationKeys[] = 'UsersManager_AllWebsites';
        $translationKeys[] = 'PrivacyManager_ConsentManager';
        $translationKeys[] = 'PrivacyManager_ConsentManagerDetected';
        $translationKeys[] = 'PrivacyManager_ConsentManagerConnected';
        $translationKeys[] = 'PrivacyManager_PreviousRawDataAnonymizations';
        $translationKeys[] = 'PrivacyManager_Requester';
        $translationKeys[] = 'PrivacyManager_AffectedIDSites';
        $translationKeys[] = 'PrivacyManager_AffectedDate';
        $translationKeys[] = 'PrivacyManager_Anonymize';
        $translationKeys[] = 'PrivacyManager_VisitColumns';
        $translationKeys[] = 'CorePluginsAdmin_Status';
        $translationKeys[] = 'PrivacyManager_LinkVisitActionColumns';
        $translationKeys[] = 'PrivacyManager_IPAddress';
        $translationKeys[] = 'PrivacyManager_ScheduledDate';
        $translationKeys[] = 'PrivacyManager_JobStartDate';
        $translationKeys[] = 'PrivacyManager_JobFinishDate';
        $translationKeys[] = 'PrivacyManager_CurrentOutput';
        $translationKeys[] = 'PrivacyManager_Output';
        $translationKeys[] = 'PrivacyManager_Scheduled';
        $translationKeys[] = 'PrivacyManager_InProgress';
        $translationKeys[] = 'PrivacyManager_AnonymizePreviousData';
        $translationKeys[] = 'PrivacyManager_AnonymizePreviousDataDescription';
        $translationKeys[] = 'PrivacyManager_AnonymizePreviousDataOnlySuperUser';
        $translationKeys[] = 'Overlay_Location';
        $translationKeys[] = 'General_UserId';
        $translationKeys[] = 'General_Done';
        $translationKeys[] = 'PrivacyManager_UseRandomizeConfigId';
        $translationKeys[] = 'PrivacyManager_RandomizeConfigIdNote';
        $translationKeys[] = 'PrivacyManager_RandomizeConfigIdNoteWarning';
        $translationKeys[] = 'PrivacyManager_ConfirmConfigRandomisationEnabled';
        $translationKeys[] = 'PrivacyManager_ConfirmConfigRandomisationEnabledPerSite';
        $translationKeys[] = 'PrivacyManager_ConfirmConfigRandomisationExplanation';
        $translationKeys[] = 'PrivacyManager_SiteAnonymizationConfig';
        $translationKeys[] = 'PrivacyManager_UseSystemSettings';
        $translationKeys[] = 'PrivacyManager_UseSiteSpecificSettings';
        $translationKeys[] = 'PrivacyManager_UseSiteSpecificSettingsHelpText';
        $translationKeys[] = 'PrivacyManager_Compliance';
        $translationKeys[] = 'PrivacyManager_ComplianceSelectSite';
        $translationKeys[] = 'PrivacyManager_ComplianceEnforceCheckboxIntro';
        $translationKeys[] = 'PrivacyManager_ComplianceEnforceCheckboxTitle';
        $translationKeys[] = 'PrivacyManager_ComplianceEnforceCheckboxHelp';
        $translationKeys[] = 'PrivacyManager_ComplianceTableSettingName';
        $translationKeys[] = 'PrivacyManager_ComplianceTableSettingStatus';
        $translationKeys[] = 'PrivacyManager_ComplianceTableSettingNotes';
        $translationKeys[] = 'PrivacyManager_ComplianceCompliant';
        $translationKeys[] = 'PrivacyManager_ComplianceNonCompliant';
        $translationKeys[] = 'PrivacyManager_ComplianceComplianceUnknown';
        $translationKeys[] = 'General_ErrorTryAgain';
        $translationKeys[] = 'General_ExceptionContactSupportGeneric';
        $translationKeys[] = 'PrivacyManager_ComplianceCNILTitle';
        $translationKeys[] = 'PrivacyManager_ComplianceCNILDescription';
        $translationKeys[] = 'General_MultiSitesSummary';
    }
    public function setTrackerCacheGeneral(&$cacheContent)
    {
        $config = new \Piwik\Plugins\PrivacyManager\Config();
        $config->setTrackerCache($cacheContent);
        $cacheContent[self::OPTION_USERID_SALT] = self::getUserIdSalt();
        $purgeSettings = \Piwik\Plugins\PrivacyManager\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 setTrackerCacheSiteAttributes(&$cacheContent, int $idSite) : void
    {
        $config = new \Piwik\Plugins\PrivacyManager\Config($idSite);
        $config->setTrackerCache($cacheContent);
        PolicyManager::storePolicySettingValuesInTrackerCache($cacheContent, $idSite);
    }
    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";
        $stylesheets[] = "plugins/PrivacyManager/stylesheets/compliance.less";
    }
    /**
     * Customize the Installation "default settings" form.
     *
     */
    public function installationFormInit(FormDefaultSettings $form)
    {
        $form->addElement('checkbox', 'anonymise_ip', null, ['content' => '<div class="form-help">' . Piwik::translate('PrivacyManager_AnonymizeIpExtendedHelp', ['213.34.51.91', '213.34.0.0']) . '</div> &nbsp;&nbsp;' . IPAnonymisation::getInlineHelp()]);
        // default values
        $form->addDataSource(new HTML_QuickForm2_DataSource_Array(['do_not_track' => $this->dntChecker->isActive(), 'anonymise_ip' => \Piwik\Plugins\PrivacyManager\IPAnonymizer::isActive()]));
    }
    /**
     * Process the Installation "default settings" form submission
     *
     */
    public function installationFormSubmit(FormDefaultSettings $form)
    {
        $anonymiseIp = (bool) $form->getSubmitValue('anonymise_ip');
        if ($anonymiseIp) {
            \Piwik\Plugins\PrivacyManager\IPAnonymizer::activate();
        } else {
            \Piwik\Plugins\PrivacyManager\IPAnonymizer::deactivate();
        }
    }
    /**
     * Returns the settings for the data purging feature.
     *
     * @return array<string, int>
     */
    public static function getPurgeDataSettings() : array
    {
        $settings = [];
        // load settings from ini config
        $config = PiwikConfig::getInstance();
        foreach (self::$purgeDataOptions as $configKey => $configSection) {
            $values = $config->{$configSection};
            $settings[$configKey] = (int) $values[$configKey];
        }
        if (!\Piwik\Plugins\PrivacyManager\Controller::isDataPurgeSettingsEnabled()) {
            return $settings;
        }
        // load the settings for the data purging settings
        foreach (self::$purgeDataOptions as $configName => $configSection) {
            $value = Option::get($configName);
            if ($value !== \false) {
                $settings[$configName] = (int) $value;
            }
        }
        $featureFlagManager = StaticContainer::get(FeatureFlagManager::class);
        if ($featureFlagManager->isFeatureActive(PrivacyCompliance::class)) {
            if (!empty($settings['delete_logs_older_than'])) {
                $settings['delete_logs_older_than'] = ReportRetentionSetting::getInstance()->getValue();
            }
        }
        return $settings;
    }
    /**
     * Saves the supplied data purging settings.
     *
     * @param array $settings The settings to save.
     */
    public static function savePurgeDataSettings($settings)
    {
        foreach (self::$purgeDataOptions as $configName => $configSection) {
            if (isset($settings[$configName])) {
                Option::set($configName, (int) $settings[$configName]);
            }
        }
        Cache::deleteTrackerCache();
    }
    /**
     * Deletes old archived data (reports & metrics).
     *
     * Archive tables are not optimized after, as that is handled by a separate scheduled task
     * in CoreAdminHome. This is a scheduled task and will only execute every N days. The number
     * of days is determined by the delete_logs_schedule_lowest_interval config option.
     *
     * If delete_reports_enable is set to 1, old archive data is deleted. The following
     * config options can tweak this behavior:
     * - delete_reports_older_than: The number of months after which archive data is considered
     *                              old. The current month is not considered when applying this
     *                              value.
     * - delete_reports_keep_basic_metrics: If set to 1, keeps certain metric data. Right now,
     *                                      all metric data is kept.
     * - delete_reports_keep_day_reports: If set to 1, keeps old daily reports.
     * - delete_reports_keep_week_reports: If set to 1, keeps old weekly reports.
     * - delete_reports_keep_month_reports: If set to 1, keeps old monthly reports.
     * - delete_reports_keep_year_reports: If set to 1, keeps old yearly reports.
     */
    public function deleteReportData()
    {
        $settings = self::getPurgeDataSettings();
        // Make sure, data deletion is enabled
        if ($settings['delete_reports_enable'] == 0) {
            return \false;
        }
        // make sure purging should run at this time (unless this is a forced purge)
        if (!$this->shouldPurgeData($settings, self::OPTION_LAST_DELETE_PIWIK_REPORTS, 'delete_logs_schedule_lowest_interval')) {
            return \false;
        }
        // set last run time
        Option::set(self::OPTION_LAST_DELETE_PIWIK_REPORTS, Date::factory('today')->getTimestamp());
        \Piwik\Plugins\PrivacyManager\ReportsPurger::make($settings, self::getAllMetricsToKeep())->purgeData();
        return \true;
    }
    /**
     * Deletes old raw data based on the options set in the Deletelogs config
     * section. This is a scheduled task and will only execute every N days. The number
     * of days is determined by the delete_logs_schedule_lowest_interval config option.
     *
     * If delete_logs_enable is set to 1, old data in the log_visit, log_conversion,
     * log_conversion_item and log_link_visit_action tables is deleted. The following
     * options can tweak this behavior:
     * - delete_logs_older_than: The number of days after which raw data is considered old.
     *
     * @ToDo: return number of Rows deleted in last run; Display age of "oldest" row to help the user setting
     *        the day offset;
     */
    public function deleteLogData()
    {
        $settings = self::getPurgeDataSettings();
        // Make sure, data deletion is enabled
        if ($settings['delete_logs_enable'] == 0) {
            return \false;
        }
        // make sure purging should run at this time
        if (!$this->shouldPurgeData($settings, self::OPTION_LAST_DELETE_PIWIK_LOGS, 'delete_logs_schedule_lowest_interval')) {
            return \false;
        }
        /*
         * Tell the DB that log deletion has run BEFORE deletion is executed;
         * If deletion / table optimization exceeds execution time, other tasks maybe prevented of being executed
         * every time, when the schedule is triggered.
         */
        $lastDeleteDate = Date::factory("today")->getTimestamp();
        Option::set(self::OPTION_LAST_DELETE_PIWIK_LOGS, $lastDeleteDate);
        $shouldDeleteUnusedLogActions = $this->shouldPurgeData($settings, self::OPTION_LAST_DELETE_UNUSED_LOG_ACTIONS, 'delete_logs_unused_actions_schedule_lowest_interval');
        if ($shouldDeleteUnusedLogActions) {
            Option::set(self::OPTION_LAST_DELETE_UNUSED_LOG_ACTIONS, $lastDeleteDate);
        }
        // execute the purge
        /** @var LogDataPurger $logDataPurger */
        $logDataPurger = StaticContainer::get('Piwik\\Plugins\\PrivacyManager\\LogDataPurger');
        $logDataPurger->purgeData($settings['delete_logs_older_than'], $shouldDeleteUnusedLogActions);
        return \true;
    }
    /**
     * Returns an array describing what data would be purged if both raw data & report
     * purging is invoked.
     *
     * The returned array maps table names with the number of rows that will be deleted.
     * If the table name is mapped with -1, the table will be dropped.
     *
     * @param array $settings The config options to use in the estimate. If null, the real
     *                        options are used.
     * @return array
     */
    public static function getPurgeEstimate($settings = null)
    {
        if (is_null($settings)) {
            $settings = self::getPurgeDataSettings();
        }
        $result = [];
        if ($settings['delete_logs_enable']) {
            /** @var LogDataPurger $logDataPurger */
            $logDataPurger = StaticContainer::get('Piwik\\Plugins\\PrivacyManager\\LogDataPurger');
            $result = array_merge($result, $logDataPurger->getPurgeEstimate($settings['delete_logs_older_than']));
        }
        if ($settings['delete_reports_enable']) {
            $reportsPurger = \Piwik\Plugins\PrivacyManager\ReportsPurger::make($settings, self::getAllMetricsToKeep());
            $result = array_merge($result, $reportsPurger->getPurgeEstimate());
        }
        return $result;
    }
    private static function getReportDate($strPeriod, $strDate)
    {
        // if range, only look at the first date
        if ($strPeriod === 'range') {
            $idSite = Request::fromRequest()->getIntegerParameter('idSite', 0);
            if ($idSite) {
                $site = new Site($idSite);
                $timezone = $site->getTimezone();
            } else {
                $timezone = 'UTC';
            }
            $period = new Range('range', $strDate, $timezone);
            $reportDate = $period->getDateStart();
        } elseif (Period::isMultiplePeriod($strDate, $strPeriod)) {
            // if a multiple period, this function is irrelevant
            return \false;
        } else {
            // otherwise, use the date as given
            $reportDate = Date::factory($strDate);
        }
        return $reportDate;
    }
    /**
     * Returns true if a report with the given year & month should be purged or not.
     *
     * If reportsOlderThan is set to null or not supplied, this function will check if
     * a report should be purged, based on existing configuration. In this case, if
     * delete_reports_enable is set to 0, this function will return false.
     *
     * @param int $reportDateYear The year of the report in question.
     * @param int $reportDateMonth The month of the report in question.
     * @param int|Date $reportsOlderThan If an int, the number of months a report must be older than
     *                                         in order to be purged. If a date, the date a report must be
     *                                         older than in order to be purged.
     * @return bool
     */
    public static function shouldReportBePurged($reportDateYear, $reportDateMonth, $reportsOlderThan = null)
    {
        // if no 'older than' value/date was supplied, use existing config
        if (is_null($reportsOlderThan)) {
            // if report deletion is not enabled, the report shouldn't be purged
            $settings = self::getPurgeDataSettings();
            if ($settings['delete_reports_enable'] == 0) {
                return \false;
            }
            $reportsOlderThan = $settings['delete_reports_older_than'];
        }
        // if a integer was supplied, assume it is the number of months a report must be older than
        if (!$reportsOlderThan instanceof Date) {
            $reportsOlderThan = Date::factory('today')->subMonth(1 + $reportsOlderThan);
        }
        return \Piwik\Plugins\PrivacyManager\ReportsPurger::shouldReportBePurged($reportDateYear, $reportDateMonth, $reportsOlderThan);
    }
    /**
     * Returns the general metrics to keep when the 'delete_reports_keep_basic_metrics'
     * config is set to 1.
     */
    private static function getMetricsToKeep()
    {
        return ['nb_uniq_visitors', 'nb_visits', 'nb_users', 'nb_actions', 'max_actions', 'sum_visit_length', 'bounce_count', 'nb_visits_converted', 'nb_conversions', 'revenue', 'quantity', 'price', 'orders'];
    }
    /**
     * Returns the goal metrics to keep when the 'delete_reports_keep_basic_metrics'
     * config is set to 1.
     */
    private static function getGoalMetricsToKeep()
    {
        // keep all goal metrics
        return array_values(Metrics::$mappingFromIdToNameGoal);
    }
    /**
     * Returns the names of metrics that should be kept when purging as they appear in
     * archive tables.
     */
    public static function getAllMetricsToKeep()
    {
        $metricsToKeep = self::getMetricsToKeep();
        // convert goal metric names to correct archive names
        if (Common::isGoalPluginEnabled()) {
            $goalMetricsToKeep = self::getGoalMetricsToKeep();
            $maxGoalId = self::getMaxGoalId();
            // for each goal metric, there's a different name for each goal, including the overview,
            // the order report & cart report
            foreach ($goalMetricsToKeep as $metric) {
                for ($i = 1; $i <= $maxGoalId; ++$i) {
                    // maxGoalId can be 0
                    $metricsToKeep[] = Archiver::getRecordName($metric, $i);
                }
                $metricsToKeep[] = Archiver::getRecordName($metric);
                $metricsToKeep[] = Archiver::getRecordName($metric, GoalManager::IDGOAL_ORDER);
                $metricsToKeep[] = Archiver::getRecordName($metric, GoalManager::IDGOAL_CART);
            }
        }
        return $metricsToKeep;
    }
    /**
     * Returns true if one of the purge data tasks should run now, false if it shouldn't.
     */
    private function shouldPurgeData($settings, $lastRanOption, $setting)
    {
        // Log deletion may not run until it is once rescheduled (initial run). This is the
        // only way to guarantee the calculated next scheduled deletion time.
        $initialDelete = Option::get(self::OPTION_LAST_DELETE_PIWIK_LOGS_INITIAL);
        if (empty($initialDelete)) {
            Option::set(self::OPTION_LAST_DELETE_PIWIK_LOGS_INITIAL, 1);
            return \false;
        }
        // Make sure, log purging is allowed to run now
        $lastDelete = Option::get($lastRanOption);
        $deleteIntervalDays = $settings[$setting];
        $deleteIntervalSeconds = $this->getDeleteIntervalInSeconds($deleteIntervalDays);
        if ($lastDelete === \false || $lastDelete === '' || (int) $lastDelete + $deleteIntervalSeconds <= time()) {
            return \true;
        } else {
            // not time to run data purge
            return \false;
        }
    }
    private function getDeleteIntervalInSeconds($deleteInterval)
    {
        return (int) $deleteInterval * 24 * 60 * 60;
    }
    private static function getMaxGoalId()
    {
        return Db::fetchOne("SELECT MAX(idgoal) FROM " . Common::prefixTable('goal'));
    }
    /**
     * Returns a unique salt used for pseudonimisation of user id only
     *
     * @return string
     */
    public static function getUserIdSalt()
    {
        $salt = Option::get(self::OPTION_USERID_SALT);
        if (empty($salt)) {
            $salt = Common::getRandomString($len = 40, $alphabet = "abcdefghijklmnoprstuvwxyzABCDEFGHIJKLMNOPRSTUVWXYZ0123456789_-\$");
            Option::set(self::OPTION_USERID_SALT, $salt, 1);
        }
        return $salt;
    }
    public function renderPrivacyPolicyLinks(&$out)
    {
        $settings = new \Piwik\Plugins\PrivacyManager\SystemSettings();
        if (!$this->shouldRenderFooterLinks($settings)) {
            return;
        }
        $imprintUrl = $settings->imprintUrl->getValue();
        $privacyPolicyUrl = $settings->privacyPolicyUrl->getValue();
        $termsAndConditionUrl = $settings->termsAndConditionUrl->getValue();
        if (empty($imprintUrl) && empty($privacyPolicyUrl) && empty($termsAndConditionUrl)) {
            return;
        }
        $view = new View('@PrivacyManager/footerLinks.twig');
        $view->imprintUrl = $imprintUrl;
        $view->privacyPolicyUrl = $privacyPolicyUrl;
        $view->termsAndCondition = $termsAndConditionUrl;
        $out .= $view->render();
    }
    private function shouldRenderFooterLinks(\Piwik\Plugins\PrivacyManager\SystemSettings $settings)
    {
        if (Piwik::isUserIsAnonymous()) {
            return \true;
        }
        $module = Common::getRequestVar('module', \false);
        if ($module == 'Widgetize') {
            return (bool) $settings->showInEmbeddedWidgets->getValue();
        }
        return \false;
    }
    public function shouldAddTrackerFile(&$shouldAdd, $pluginName)
    {
        if ($pluginName === 'PrivacyManager') {
            $shouldAdd = self::isCookieLessTrackingForced();
        }
    }
    /**
     * Returns if cookie less tracking is forced
     *
     */
    public static function isCookieLessTrackingForced() : bool
    {
        $config = new \Piwik\Plugins\PrivacyManager\Config();
        return $config->forceCookielessTracking;
    }
    public static function getMaskLengthOptions() : array
    {
        return [['key' => '1', 'value' => Piwik::translate('PrivacyManager_AnonymizeIpMaskLength', ["1", "192.168.100.xxx"]), 'description' => ''], ['key' => '2', 'value' => Piwik::translate('PrivacyManager_AnonymizeIpMaskLength', ["2", "192.168.xxx.xxx"]), 'description' => Piwik::translate('General_Recommended')], ['key' => '3', 'value' => Piwik::translate('PrivacyManager_AnonymizeIpMaskLength', ["3", "192.xxx.xxx.xxx"]), 'description' => ''], ['key' => '4', 'value' => Piwik::translate('PrivacyManager_AnonymizeIpMaskFully'), 'description' => '']];
    }
    public static function getUseAnonymizedIpForVisitEnrichmentOptions() : array
    {
        return [['key' => '1', 'value' => Piwik::translate('General_Yes'), 'description' => Piwik::translate('PrivacyManager_RecommendedForPrivacy')], ['key' => '0', 'value' => Piwik::translate('General_No'), 'description' => '']];
    }
    public static function getScheduleDeletionOptions() : array
    {
        return [['key' => '1', 'value' => Piwik::translate('Intl_PeriodDay')], ['key' => '7', 'value' => Piwik::translate('Intl_PeriodWeek')], ['key' => '30', 'value' => Piwik::translate('Intl_PeriodMonth')]];
    }
    /**
     * Delete site-specific anonymisation settings (option values) for a given site
     */
    public function deleteSiteSpecificAnonymisationSettings(int $idSite) : void
    {
        (new \Piwik\Plugins\PrivacyManager\Config($idSite))->removeForSite();
    }
}
