/**
  * Returns an array describing what data would be purged if both log 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 = array();
     if ($settings['delete_logs_enable']) {
         $logDataPurger = LogDataPurger::make($settings);
         $result = array_merge($result, $logDataPurger->getPurgeEstimate());
     }
     if ($settings['delete_reports_enable']) {
         $reportsPurger = ReportsPurger::make($settings, self::getAllMetricsToKeep());
         $result = array_merge($result, $reportsPurger->getPurgeEstimate());
     }
     return $result;
 }
 /**
  * Test no concurrency issues when deleting log data from log_action table.
  *
  * @group Integration
  */
 public function testPurgeLogDataConcurrency()
 {
     \Piwik\Piwik::addAction("LogDataPurger.ActionsToKeepInserted.olderThan", array($this, 'addReferenceToUnusedAction'));
     $purger = LogDataPurger::make($this->settings, true);
     $this->unusedIdAction = Db::fetchOne("SELECT idaction FROM " . Common::prefixTable('log_action') . " WHERE name = ?", array('whatever.com/_40'));
     $this->assertTrue($this->unusedIdAction > 0);
     // purge data
     $purger->purgeData();
     // check that actions were purged
     $this->assertEquals(22 + $this->getCountEventIdsNotPurged(), $this->_getTableCount('log_action'));
     // January
     // check that the unused action still exists
     $count = Db::fetchOne("SELECT COUNT(*) FROM " . Common::prefixTable('log_action') . " WHERE idaction = ?", array($this->unusedIdAction));
     $this->assertEquals(1, $count);
     $this->unusedIdAction = null;
     // so the hook won't get executed twice
 }
 protected function getDeleteDataInfo()
 {
     Piwik::checkUserHasSuperUserAccess();
     $deleteDataInfos = array();
     $taskScheduler = new TaskScheduler();
     $deleteDataInfos["config"] = PrivacyManager::getPurgeDataSettings();
     $deleteDataInfos["deleteTables"] = "<br/>" . implode(", ", LogDataPurger::getDeleteTableLogTables());
     $scheduleTimetable = $taskScheduler->getScheduledTimeForMethod("PrivacyManager", "deleteLogTables");
     $optionTable = Option::get(self::OPTION_LAST_DELETE_PIWIK_LOGS);
     //If task was already rescheduled, read time from taskTimetable. Else, calculate next possible runtime.
     if (!empty($scheduleTimetable) && $scheduleTimetable - time() > 0) {
         $nextPossibleSchedule = (int) $scheduleTimetable;
     } else {
         $date = Date::factory("today");
         $nextPossibleSchedule = $date->addDay(1)->getTimestamp();
     }
     //deletion schedule did not run before
     if (empty($optionTable)) {
         $deleteDataInfos["lastRun"] = false;
         //next run ASAP (with next schedule run)
         $date = Date::factory("today");
         $deleteDataInfos["nextScheduleTime"] = $nextPossibleSchedule;
     } else {
         $deleteDataInfos["lastRun"] = $optionTable;
         $deleteDataInfos["lastRunPretty"] = Date::factory((int) $optionTable)->getLocalized('%day% %shortMonth% %longYear%');
         //Calculate next run based on last run + interval
         $nextScheduleRun = (int) ($deleteDataInfos["lastRun"] + $deleteDataInfos["config"]["delete_logs_schedule_lowest_interval"] * 24 * 60 * 60);
         //is the calculated next run in the past? (e.g. plugin was disabled in the meantime or something) -> run ASAP
         if ($nextScheduleRun - time() <= 0) {
             $deleteDataInfos["nextScheduleTime"] = $nextPossibleSchedule;
         } else {
             $deleteDataInfos["nextScheduleTime"] = $nextScheduleRun;
         }
     }
     $deleteDataInfos["nextRunPretty"] = MetricsFormatter::getPrettyTimeFromSeconds($deleteDataInfos["nextScheduleTime"] - time());
     return $deleteDataInfos;
 }
 /**
  * Test no concurrency issues when deleting log data from log_action table.
  */
 public function testPurgeLogDataConcurrency()
 {
     $rawLogDao = new DataPurgingTest_RawLogDao(new DimensionMetadataProvider());
     $rawLogDao->insertActionsOlderThanCallback = array($this, 'addReferenceToUnusedAction');
     $purger = new LogDataPurger(new LogDeleter($rawLogDao), $rawLogDao);
     $this->unusedIdAction = Db::fetchOne("SELECT idaction FROM " . Common::prefixTable('log_action') . " WHERE name = ?", array('whatever.com/_40'));
     $this->assertTrue($this->unusedIdAction > 0);
     // purge data
     $purger->purgeData($this->settings['delete_logs_older_than'], $this->settings['delete_logs_max_rows_per_query']);
     // check that actions were purged
     $contentsNotPurged = 3;
     $this->assertEquals(22 + $this->getCountEventIdsNotPurged() + $contentsNotPurged, $this->_getTableCount('log_action'));
     // January
     // check that the unused action still exists
     $count = Db::fetchOne("SELECT COUNT(*) FROM " . Common::prefixTable('log_action') . " WHERE idaction = ?", array($this->unusedIdAction));
     $this->assertEquals(1, $count);
     $this->unusedIdAction = null;
     // so the hook won't get executed twice
 }