/** * @return string|false false if current version is the latest available, * or the latest version number if a newest release is available */ public static function isNewestVersionAvailable() { $latestVersion = Piwik_GetOption(self::LATEST_VERSION); if (!empty($latestVersion) && version_compare(Piwik_Version::VERSION, $latestVersion) == -1) { return $latestVersion; } return false; }
function deleteLogTables() { $deleteSettings = Zend_Registry::get('config')->Deletelogs; //Make sure, log deletion is enabled if ($deleteSettings->delete_logs_enable == 0) { return; } //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 = Piwik_GetOption(self::OPTION_LAST_DELETE_PIWIK_LOGS_INITIAL); if (empty($initialDelete)) { Piwik_SetOption(self::OPTION_LAST_DELETE_PIWIK_LOGS_INITIAL, 1); return; } //Make sure, log purging is allowed to run now $lastDelete = Piwik_GetOption(self::OPTION_LAST_DELETE_PIWIK_LOGS); $deleteIntervalSeconds = $this->getDeleteIntervalInSeconds($deleteSettings->delete_logs_schedule_lowest_interval); if ($lastDelete === false || ($lastDelete !== false && ((int)$lastDelete + $deleteIntervalSeconds) <= time()) ) { $maxIdVisit = $this->getDeleteIdVisitOffset($deleteSettings->delete_logs_older_than); $logTables = $this->getDeleteTableLogTables(); //set lastDelete time to today $date = Piwik_Date::factory("today"); $lastDeleteDate = $date->getTimestamp(); /* * 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. */ Piwik_SetOption(self::OPTION_LAST_DELETE_PIWIK_LOGS, $lastDeleteDate); //Break if no ID was found (nothing to delete for given period) if (empty($maxIdVisit)) { return; } foreach ($logTables as $logTable) { $this->deleteRowsFromTable($logTable, $maxIdVisit, $deleteSettings->delete_max_rows_per_run * self::DELETE_MAX_ROWS_MULTIPLICATOR); } //optimize table overhead after deletion $query = "OPTIMIZE TABLE " . implode(",", $logTables); Piwik_Query($query); } }
public static function getScheduledTimeForTask($className, $methodName) { // Gets the array where rescheduled timetables are stored $option = Piwik_GetOption(self::TIMETABLE_OPTION_STRING); $timetable = self::getTimetableFromOption($option); if ($timetable === false) { return; } $taskName = $className . '.' . $methodName; if (isset($timetable[$taskName])) { return $timetable[$taskName]; } else { return false; } }
public static function runTasks() { // Gets the array where rescheduled timetables are stored $option = Piwik_GetOption(self::TIMETABLE_OPTION_STRING); if ($option === false) { $timetable = array(); } elseif (!is_string($option)) { return; } else { $timetable = unserialize($option); } if (isset($GLOBALS['PIWIK_TRACKER_DEBUG_FORCE_SCHEDULED_TASKS']) && $GLOBALS['PIWIK_TRACKER_DEBUG_FORCE_SCHEDULED_TASKS']) { $timetable = array(); } // Collects tasks Piwik_PostEvent(self::GET_TASKS_EVENT, $tasks); $return = array(); // Loop through each task foreach ($tasks as $task) { $scheduledTime = $task->getScheduledTime(); $className = $task->getClassName(); $methodName = $task->getMethodName(); $fullyQualifiedMethodName = get_class($className) . '.' . $methodName; /* * Task has to be executed if : * - it is the first time, ie. rescheduledTime is not set * - that task has already been executed and the current system time is greater than the * rescheduled time. */ if (!isset($timetable[$fullyQualifiedMethodName]) || isset($timetable[$fullyQualifiedMethodName]) && time() >= $timetable[$fullyQualifiedMethodName]) { // Updates the rescheduled time $timetable[$fullyQualifiedMethodName] = $scheduledTime->getRescheduledTime(); Piwik_SetOption(self::TIMETABLE_OPTION_STRING, serialize($timetable)); // Run the task try { $timer = new Piwik_Timer(); call_user_func(array($className, $methodName)); $message = $timer->__toString(); } catch (Exception $e) { $message = 'ERROR: ' . $e->getMessage(); } $return[] = array('task' => $fullyQualifiedMethodName, 'output' => $message); } } return $return; }
protected function getDeleteLogsInfo() { Piwik::checkUserIsSuperUser(); $deleteLogsInfos = array(); $taskScheduler = new Piwik_TaskScheduler(); $deleteLogsInfos["config"] = Zend_Registry::get('config')->Deletelogs->toArray(); $privacyManager = new Piwik_PrivacyManager(); $deleteLogsInfos["deleteTables"] = implode(", ", $privacyManager->getDeleteTableLogTables()); $scheduleTimetable = $taskScheduler->getScheduledTimeForTask("Piwik_PrivacyManager", "deleteLogTables"); $optionTable = Piwik_GetOption(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 = Piwik_Date::factory("today"); $nextPossibleSchedule = $date->addDay(1)->getTimestamp(); } //deletion schedule did not run before if (empty($optionTable)) { $deleteLogsInfos["lastRun"] = false; //next run ASAP (with next schedule run) $date = Piwik_Date::factory("today"); $deleteLogsInfos["nextScheduleTime"] = $nextPossibleSchedule; } else { $deleteLogsInfos["lastRun"] = $optionTable; $deleteLogsInfos["lastRunPretty"] = Piwik_Date::factory((int) $optionTable)->getLocalized('%day% %shortMonth% %longYear%'); //Calculate next run based on last run + interval $nextScheduleRun = (int) ($deleteLogsInfos["lastRun"] + $deleteLogsInfos["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) { $deleteLogsInfos["nextScheduleTime"] = $nextPossibleSchedule; } else { $deleteLogsInfos["nextScheduleTime"] = $nextScheduleRun; } } $deleteLogsInfos["nextRunPretty"] = Piwik::getPrettyTimeFromSeconds($deleteLogsInfos["nextScheduleTime"] - time()); return $deleteLogsInfos; }
public static function setUpBeforeClass() { $dbName = false; if (!empty($GLOBALS['PIWIK_BENCHMARK_DATABASE'])) { $dbName = $GLOBALS['PIWIK_BENCHMARK_DATABASE']; } // connect to database self::createTestConfig(); self::connectWithoutDatabase(); // create specified fixture (global var not set, use default no-data fixture (see end of this file)) if (empty($GLOBALS['PIWIK_BENCHMARK_FIXTURE'])) { $fixtureName = 'Piwik_Test_Fixture_EmptyOneSite'; } else { $fixtureName = 'Piwik_Test_Fixture_' . $GLOBALS['PIWIK_BENCHMARK_FIXTURE']; } self::$fixture = new $fixtureName(); // figure out if the desired fixture has already been setup, and if not empty the database $installedFixture = false; try { if (isset(self::$fixture->tablesPrefix)) { Piwik_Config::getInstance()->database['tables_prefix'] = self::$fixture->tablesPrefix; Piwik_Common::$cachedTablePrefix = null; } Piwik_Query("USE " . $dbName); $installedFixture = Piwik_GetOption('benchmark_fixture_name'); } catch (Exception $ex) { // ignore } $createEmptyDatabase = $fixtureName != $installedFixture; parent::setUpBeforeClass($dbName, $createEmptyDatabase, $createConfig = false); // if we created an empty database, setup the fixture if ($createEmptyDatabase) { self::$fixture->setUp(); Piwik_SetOption('benchmark_fixture_name', $fixtureName); } }
/** * Returns the cached the Piwik URL, eg. http://demo.piwik.org/ or http://example.org/piwik/ * If not found, then tries to cache it and returns the value. * * If the Piwik URL changes (eg. Piwik moved to new server), the value will automatically be refreshed in the cache. * @return string */ public static function getPiwikUrl() { $key = 'piwikUrl'; $url = Piwik_GetOption($key); if (Piwik_Common::isPhpCliMode() || Piwik_Common::isArchivePhpTriggered() || defined('PIWIK_MODE_ARCHIVE')) { return $url; } $currentUrl = Piwik_Common::sanitizeInputValue(Piwik_Url::getCurrentUrlWithoutFileName()); if (empty($url) || $currentUrl != $url) { if (strlen($currentUrl) >= strlen('http://a/')) { Piwik_SetOption($key, $currentUrl, $autoload = true); } $url = $currentUrl; } return $url; }
protected function buildView() { // access control $idSite = Piwik_Common::getRequestVar('idSite', 1, 'int'); Piwik_API_Request::reloadAuthUsingTokenAuth(); if (!Piwik::isUserHasViewAccess($idSite)) { throw new Exception(Piwik_TranslateException('General_ExceptionPrivilegeAccessWebsite', array("'view'", $idSite))); } // collect data $this->parametersToModify['action'] = $this->currentControllerAction; $this->parametersToModify = array_merge($this->variablesDefault, $this->parametersToModify); $this->graphData = $this->getGraphData(); // build view $view = new Piwik_View($this->dataTableTemplate); $view->width = $this->width; $view->height = $this->height; $view->chartDivId = $this->getUniqueIdViewDataTable() . "Chart"; $view->graphType = $this->graphType; $view->data = $this->graphData; $view->isDataAvailable = strpos($this->graphData, '"series":[]') === false; $view->javascriptVariablesToSet = $this->getJavascriptVariablesToSet(); $view->properties = $this->getViewProperties(); $view->reportDocumentation = $this->getReportDocumentation(); // if it's likely that the report data for this data table has been purged, // set whether we should display a message to that effect. $view->showReportDataWasPurgedMessage = $this->hasReportBeenPurged(); $view->deleteReportsOlderThan = Piwik_GetOption('delete_reports_older_than'); return $view; }
private function doWelcomeUpdates($view, $componentsWithUpdateFile) { $view->new_piwik_version = Piwik_Version::VERSION; $view->commandUpgradePiwik = "<br /><code>php " . Piwik_Common::getPathToPiwikRoot() . "/index.php -- \"module=CoreUpdater\" </code>"; $pluginNamesToUpdate = array(); $coreToUpdate = false; // handle case of existing database with no tables if (!Piwik::isInstalled()) { $this->errorMessages[] = Piwik_Translate('CoreUpdater_EmptyDatabaseError', Zend_Registry::get('config')->database->dbname); $this->coreError = true; $currentVersion = 'N/A'; } else { $this->errorMessages = array(); try { $currentVersion = Piwik_GetOption('version_core'); } catch (Exception $e) { $currentVersion = '<= 0.2.9'; } foreach ($componentsWithUpdateFile as $name => $filenames) { if ($name == 'core') { $coreToUpdate = true; } else { $pluginNamesToUpdate[] = $name; } } } // check file integrity $integrityInfo = Piwik::getFileIntegrityInformation(); if (isset($integrityInfo[1])) { if ($integrityInfo[0] == false) { $this->warningMessages[] = '<b>' . Piwik_Translate('General_FileIntegrityWarningExplanation') . '</b>'; } $this->warningMessages = array_merge($this->warningMessages, array_slice($integrityInfo, 1)); } Piwik::deleteAllCacheOnUpdate(); $view->coreError = $this->coreError; $view->warningMessages = $this->warningMessages; $view->errorMessages = $this->errorMessages; $view->current_piwik_version = $currentVersion; $view->pluginNamesToUpdate = $pluginNamesToUpdate; $view->coreToUpdate = $coreToUpdate; echo $view->render(); }
public static function start($options = false) { if(Piwik_Common::isPhpCliMode() || version_compare(Piwik_GetOption('version_core'), '1.5-b5') < 0) { return; } // use cookies to store session id on the client side @ini_set('session.use_cookies', '1'); // prevent attacks involving session ids passed in URLs @ini_set('session.use_only_cookies', '1'); // advise browser that session cookie should only be sent over secure connection if(Piwik_Url::getCurrentScheme() === 'https') { @ini_set('session.cookie_secure', '1'); } // advise browser that session cookie should only be accessible through the HTTP protocol (i.e., not JavaScript) @ini_set('session.cookie_httponly', '1'); // don't use the default: PHPSESSID $sessionName = defined('PIWIK_SESSION_NAME') ? PIWIK_SESSION_NAME : 'PIWIK_SESSID'; @ini_set('session.name', $sessionName); // proxies may cause the referer check to fail and // incorrectly invalidate the session @ini_set('session.referer_check', ''); // we consider these to be misconfigurations, in that // - user - we can't verify that user-defined session handler functions have been set via session_set_save_handler() // - mm - this handler is not recommended, unsupported, not available for Windows, and has a potential concurrency issue // - files - this handler doesn't work well in load-balanced environments and may have a concurrency issue with locked session files $currentSaveHandler = ini_get('session.save_handler'); if(in_array($currentSaveHandler, array('user', 'mm', 'files'))) { $db = Zend_Registry::get('db'); $config = array( 'name' => Piwik_Common::prefixTable('session'), 'primary' => 'id', 'modifiedColumn' => 'modified', 'dataColumn' => 'data', 'lifetimeColumn' => 'lifetime', 'db' => $db, ); $saveHandler = new Piwik_Session_SaveHandler_DbTable($config); if($saveHandler) { self::setSaveHandler($saveHandler); } } // garbage collection may disabled by default (e.g., Debian) if(ini_get('session.gc_probability') == 0) { @ini_set('session.gc_probability', 1); } try { Zend_Session::start(); register_shutdown_function(array('Zend_Session', 'writeClose'), true); } catch(Exception $e) { Piwik::log('Unable to start session: ' . $e->getMessage()); Piwik_ExitWithMessage(Piwik_Translate('General_ExceptionUnableToStartSession')); } }
/** Returns the date when the cacheDataByArchiveNameReports was last run. */ public static function getDateOfLastCachingRun() { return Piwik_GetOption(self::TIME_OF_LAST_TASK_RUN_OPTION); }
/** * Returns contents of general (global) cache * * @return array */ protected static function getCacheGeneral() { $cache = self::getTrackerCache(); $cacheId = 'general'; $expectedRows = 3; if (($cacheContent = $cache->get($cacheId)) !== false && count($cacheContent) == $expectedRows) { return $cacheContent; } self::initCorePiwikInTrackerMode(); $cacheContent = array('isBrowserTriggerArchivingEnabled' => Piwik_ArchiveProcessing::isBrowserTriggerArchivingEnabled(), 'lastTrackerCronRun' => Piwik_GetOption('lastTrackerCronRun'), 'currentLocationProviderId' => Piwik_UserCountry_LocationProvider::getCurrentProviderId()); return $cacheContent; }
private function doWelcomeUpdates($view, $componentsWithUpdateFile) { $view->new_piwik_version = Piwik_Version::VERSION; $pluginNamesToUpdate = array(); $coreToUpdate = false; // handle case of existing database with no tables $tablesInstalled = Piwik::getTablesInstalled(); if (count($tablesInstalled) == 0) { $this->errorMessages[] = Piwik_Translate('CoreUpdater_EmptyDatabaseError', Zend_Registry::get('config')->database->dbname); $this->coreError = true; $currentVersion = 'N/A'; } else { $this->errorMessages = array(); try { $currentVersion = Piwik_GetOption('version_core'); } catch (Exception $e) { $currentVersion = '<= 0.2.9'; } foreach ($componentsWithUpdateFile as $name => $filenames) { if ($name == 'core') { $coreToUpdate = true; } else { $pluginNamesToUpdate[] = $name; } } } $view->coreError = $this->coreError; $view->errorMessages = $this->errorMessages; $view->current_piwik_version = $currentVersion; $view->pluginNamesToUpdate = $pluginNamesToUpdate; $view->coreToUpdate = $coreToUpdate; $view->clearCompiledTemplates(); echo $view->render(); }
static public function isBrowserTriggerArchivingEnabled() { $browserArchivingEnabled = Piwik_GetOption(self::OPTION_BROWSER_TRIGGER_ARCHIVING); if($browserArchivingEnabled !== false) { return (bool)$browserArchivingEnabled; } return (bool)Zend_Registry::get('config')->General->enable_browser_archiving_triggering; }
protected function initStateFromParameters() { // Detect parameters $reset = $this->isParameterSet("force-all-periods", $valuePossible = true); $forceAll = $this->isParameterSet("force-all-websites"); $forceTimeoutPeriod = $this->isParameterSet("force-timeout-for-periods", $valuePossible = true); if (!empty($forceTimeoutPeriod) && $forceTimeoutPeriod !== true) { // Ensure the cache for periods is at least as high as cache for today $todayTTL = Piwik_ArchiveProcessing::getTodayArchiveTimeToLive(); if ($forceTimeoutPeriod < $todayTTL) { $this->log("WARNING: Automatically increasing --force-timeout-for-periods from {$forceTimeoutPeriod} to " . $todayTTL . " to match the cache timeout for Today's report specified in Piwik UI > Settings > General Settings"); $forceTimeoutPeriod = $todayTTL; } $this->processPeriodsMaximumEverySeconds = $forceTimeoutPeriod; } // Recommend to disable browser archiving when using this script if (Piwik_ArchiveProcessing::isBrowserTriggerArchivingEnabled()) { $this->log("NOTE: if you execute this script at least once per hour (or more often) in a crontab, you may disable 'Browser trigger archiving' in Piwik UI > Settings > General Settings. "); $this->log(" see doc at: http://piwik.org/docs/setup-auto-archiving/"); } if ($reset) { $this->log("--force-all-periods was detected: the script will run as if it was its first run, and will trigger archiving for all periods."); $this->shouldResetState = true; if (!$forceAll && is_numeric($reset) && $reset > 0) { $this->firstRunActiveWebsitesWithTraffic = (int) $reset; } } if ($forceAll) { $this->log("--force-all-websites was detected: the script will archive all websites and all periods sequentially"); $this->shouldArchiveAllWebsites = true; } $this->timeLastCompleted = Piwik_GetOption(self::OPTION_ARCHIVING_FINISHED_TS); if ($this->shouldResetState) { $this->timeLastCompleted = false; } }
/** * Determine if normal users can manage their own SMS API credential * * @return bool false if SMS API credential only manageable by super admin, true otherwise */ public function getDelegatedManagement() { Piwik::checkUserIsNotAnonymous(); return Piwik_GetOption(Piwik_MobileMessaging::DELEGATED_MANAGEMENT_OPTION) == 'true'; }
protected function buildView() { $view = new Piwik_View($this->dataTableTemplate); if (!$this->isDataAvailable) { $view->cloudValues = array(); } else { $columnToDisplay = $this->getColumnToDisplay(); $columnTranslation = $this->getColumnTranslation($columnToDisplay); $values = $this->dataTable->getColumn($columnToDisplay); $labels = $this->dataTable->getColumn('label'); $labelMetadata = array(); foreach ($this->dataTable->getRows() as $row) { $logo = false; if ($this->displayLogoInsteadOfLabel) { $logo = $row->getMetadata('logo'); } $labelMetadata[$row->getColumn('label')] = array('logo' => $logo, 'url' => $row->getMetadata('url')); } $cloud = new Piwik_Visualization_Cloud(); foreach ($labels as $i => $label) { $cloud->addWord($label, $values[$i]); } $cloudValues = $cloud->render('array'); foreach ($cloudValues as &$value) { $value['logoWidth'] = round(max(16, $value['percent'])); } $view->columnTranslation = $columnTranslation; $view->labelMetadata = $labelMetadata; $view->cloudValues = $cloudValues; } $view->javascriptVariablesToSet = $this->getJavascriptVariablesToSet(); $view->properties = $this->getViewProperties(); $view->reportDocumentation = $this->getReportDocumentation(); // if it's likely that the report data for this data table has been purged, // set whether we should display a message to that effect. $view->showReportDataWasPurgedMessage = $this->hasReportBeenPurged(); $view->deleteReportsOlderThan = Piwik_GetOption('delete_reports_older_than'); return $view; }
/** * Called at the end of the archiving process. * Does some cleaning job in the database. * * @return void */ protected function postCompute() { parent::postCompute(); $blobTable = $this->tableArchiveBlob->getTableName(); $numericTable = $this->tableArchiveNumeric->getTableName(); // delete out of date records maximum once per day (DELETE request is costly) $key = 'lastPurge_' . $blobTable; $timestamp = Piwik_GetOption($key); if (!$timestamp || $timestamp < time() - 86400) { // we delete out of date daily archives from table, maximum once per day // those for day N that were processed on day N (means the archives are only partial as the day wasn't finished) $query = "/* SHARDING_ID_SITE = " . $this->idsite . " */ \tDELETE \n\t\t\t\t\t\tFROM %s\n\t\t\t\t\t\tWHERE period = ? \n\t\t\t\t\t\t\tAND date1 = DATE(ts_archived)\n\t\t\t\t\t\t\tAND DATE(ts_archived) <> CURRENT_DATE()\n\t\t\t\t\t\t"; Piwik_Query(sprintf($query, $blobTable), Piwik::$idPeriods['day']); Piwik_Query(sprintf($query, $numericTable), Piwik::$idPeriods['day']); // we delete out of date Period records (week/month/etc) // we delete archives that were archived before the end of the period // and only if they are at least 1 day old (so we don't delete archives computed today that may be stil valid) $query = "\tDELETE \n\t\t\t\t\t\tFROM %s\n\t\t\t\t\t\tWHERE period > ? \n\t\t\t\t\t\t\tAND DATE(ts_archived) <= date2\n\t\t\t\t\t\t\tAND date(ts_archived) < date_sub(CURRENT_DATE(), INTERVAL 1 DAY)\n\t\t\t\t\t\t"; Piwik_Query(sprintf($query, $blobTable), Piwik::$idPeriods['day']); Piwik_Query(sprintf($query, $numericTable), Piwik::$idPeriods['day']); Piwik_SetOption($key, time()); } foreach ($this->archives as $archive) { destroy($archive); } $this->archives = array(); }
/** * Gets password hash stored in password reset info. * * @param string $login The user login to check for. * @return string|false The hashed password or false if no reset info exists. */ public static function getPasswordToResetTo($login) { $optionName = self::getPasswordResetInfoOptionName($login); return Piwik_GetOption($optionName); }
/** * Called at the end of the archiving process. * Does some cleaning job in the database. */ protected function postCompute() { parent::postCompute(); $blobTable = $this->tableArchiveBlob->getTableName(); $numericTable = $this->tableArchiveNumeric->getTableName(); $key = 'lastPurge_' . $blobTable; $timestamp = Piwik_GetOption($key); if (!$timestamp || $timestamp < time() - 86400) { Piwik_SetOption($key, time()); // we delete out of date daily archives from table, maximum once per day // we only delete archives processed that are older than 1 day, to not delete archives we just processed $yesterday = Piwik_Date::factory('yesterday')->getDateTime(); $result = Piwik_FetchAll("\n\t\t\t\t\t\t\tSELECT idarchive\n\t\t\t\t\t\t\tFROM {$numericTable}\n\t\t\t\t\t\t\tWHERE name LIKE 'done%'\n\t\t\t\t\t\t\t\tAND value = " . Piwik_ArchiveProcessing::DONE_OK_TEMPORARY . "\n\t\t\t\t\t\t\t\tAND ts_archived < ?", array($yesterday)); $idArchivesToDelete = array(); if (!empty($result)) { foreach ($result as $row) { $idArchivesToDelete[] = $row['idarchive']; } $query = "DELETE \n \t\t\t\t\t\tFROM %s\n \t\t\t\t\t\tWHERE idarchive IN (" . implode(',', $idArchivesToDelete) . ")\n \t\t\t\t\t\t"; Piwik_Query(sprintf($query, $blobTable)); Piwik_Query(sprintf($query, $numericTable)); } Piwik::log("Purging temporary archives: done [ purged archives older than {$yesterday} from {$blobTable} and {$numericTable} ] [Deleted IDs: " . implode(',', $idArchivesToDelete) . "]"); // Deleting "Custom Date Range" reports after 1 day, since they can be re-processed // and would take up unecessary space $query = "DELETE \n \t\t\t\t\tFROM %s\n \t\t\t\t\tWHERE period = ?\n \t\t\t\t\t\tAND ts_archived < ?"; $bind = array(Piwik::$idPeriods['range'], $yesterday); Piwik_Query(sprintf($query, $blobTable), $bind); Piwik_Query(sprintf($query, $numericTable), $bind); } else { Piwik::log("Purging temporary archives: skipped."); } if (!isset($this->archives)) { return; } foreach ($this->archives as $archive) { destroy($archive); } $this->archives = array(); }
public function test_deleteLike() { // empty table, expect false (i.e., not found) $this->assertTrue(Piwik_GetOption('anonymous_defaultReport') === false); $this->assertTrue(Piwik_GetOption('admin_defaultReport') === false); $this->assertTrue(Piwik_GetOption('visitor_defaultReport') === false); // insert guard - to test unescaped underscore Piwik_SetOption('adefaultReport', '0', true); $this->assertTrue(Piwik_GetOption('adefaultReport') === '0'); // populate table, expect '1' Piwik_SetOption('anonymous_defaultReport', '1', true); Piwik_Option::getInstance()->deleteLike('\\_defaultReport'); $this->assertTrue(Piwik_Option::getInstance()->get('anonymous_defaultReport') === '1'); $this->assertTrue(Piwik_GetOption('adefaultReport') === '0'); // populate table, expect '2' Piwik_SetOption('admin_defaultReport', '2', false); Piwik_Option::getInstance()->deleteLike('\\_defaultReport'); $this->assertTrue(Piwik_Option::getInstance()->get('admin_defaultReport') === '2'); $this->assertTrue(Piwik_GetOption('adefaultReport') === '0'); // populate table, expect '3' Piwik_SetOption('visitor_defaultReport', '3', false); Piwik_Option::getInstance()->deleteLike('\\_defaultReport'); $this->assertTrue(Piwik_Option::getInstance()->get('visitor_defaultReport') === '3'); $this->assertTrue(Piwik_GetOption('adefaultReport') === '0'); // delete with non-matching value, expect '1' Piwik_Option::getInstance()->deleteLike('%\\_defaultReport', '4'); $this->assertTrue(Piwik_Option::getInstance()->get('anonymous_defaultReport') === '1'); $this->assertTrue(Piwik_GetOption('adefaultReport') === '0'); // delete with matching pattern, expect false Piwik_Option::getInstance()->deleteLike('%\\_defaultReport', '1'); $this->assertTrue(Piwik_Option::getInstance()->get('anonymous_defaultReport') === false); $this->assertTrue(Piwik_GetOption('adefaultReport') === '0'); // this shouldn't have been deleted, expect '2' and '3' $this->assertTrue(Piwik_Option::getInstance()->get('admin_defaultReport') === '2'); $this->assertTrue(Piwik_Option::getInstance()->get('visitor_defaultReport') === '3'); $this->assertTrue(Piwik_GetOption('adefaultReport') === '0'); // deleted, expect false (except for the guard) Piwik_Option::getInstance()->deleteLike('%\\_defaultReport'); $this->assertTrue(Piwik_Option::getInstance()->get('admin_defaultReport') === false); $this->assertTrue(Piwik_Option::getInstance()->get('visitor_defaultReport') === false); // unescaped backslash (single quotes) Piwik_Option::getInstance()->deleteLike('%\\_defaultReport'); $this->assertTrue(Piwik_GetOption('adefaultReport') === '0'); // escaped backslash (single quotes) Piwik_Option::getInstance()->deleteLike('%\\_defaultReport'); $this->assertTrue(Piwik_GetOption('adefaultReport') === '0'); // unescaped backslash (double quotes) Piwik_Option::getInstance()->deleteLike("%\\_defaultReport"); $this->assertTrue(Piwik_GetOption('adefaultReport') === '0'); // escaped backslash (double quotes) Piwik_Option::getInstance()->deleteLike("%\\_defaultReport"); $this->assertTrue(Piwik_GetOption('adefaultReport') === '0'); }
/** * Gets a user preference * @param string $userLogin * @param string $preferenceName * @return bool|string */ public function getUserPreference($userLogin, $preferenceName) { Piwik::checkUserIsSuperUserOrTheUser($userLogin); return Piwik_GetOption($this->getPreferenceId($userLogin, $preferenceName)); }
/** * Returns the default timezone that will be set when creating a website through the API. * Via the UI, if the default timezone is not UTC, it will be pre-selected in the drop down * * @return string Timezone eg. UTC+7 or Europe/Paris */ public function getDefaultTimezone() { $defaultTimezone = Piwik_GetOption(self::OPTION_DEFAULT_TIMEZONE); if($defaultTimezone) { return $defaultTimezone; } return 'UTC'; }
/** * Called at the end of the archiving process. * Does some cleaning job in the database. */ protected function postCompute() { parent::postCompute(); $blobTable = $this->tableArchiveBlob->getTableName(); $numericTable = $this->tableArchiveNumeric->getTableName(); $key = 'lastPurge_' . $blobTable; $timestamp = Piwik_GetOption($key); // we shall purge temporary archives after their timeout is finished, plus an extra 2 hours // in case archiving is disabled and is late to run, we give it this extra time to run and re-process more recent records $temporaryArchivingTimeout = self::getTodayArchiveTimeToLive(); $purgeEveryNSeconds = $temporaryArchivingTimeout + 2 * 3600; // we only delete archives if we are able to process them, otherwise, the browser might process reports // when &segment= is specified (or custom date range) and would below, delete temporary archives that the // browser is not able to process until next cron run (which could be more than 1 hour away) if ($this->isRequestAuthorizedToArchive() && (!$timestamp || $timestamp < time() - $purgeEveryNSeconds)) { Piwik_SetOption($key, time()); $purgeArchivesOlderThan = Piwik_Date::factory(time() - $purgeEveryNSeconds)->getDateTime(); $result = Piwik_FetchAll("\n\t\t\t\t\t\t\tSELECT idarchive\n\t\t\t\t\t\t\tFROM {$numericTable}\n\t\t\t\t\t\t\tWHERE name LIKE 'done%'\n\t\t\t\t\t\t\t\tAND value = " . Piwik_ArchiveProcessing::DONE_OK_TEMPORARY . "\n\t\t\t\t\t\t\t\tAND ts_archived < ?", array($purgeArchivesOlderThan)); $idArchivesToDelete = array(); if (!empty($result)) { foreach ($result as $row) { $idArchivesToDelete[] = $row['idarchive']; } $query = "DELETE \n \t\t\t\t\t\tFROM %s\n \t\t\t\t\t\tWHERE idarchive IN (" . implode(',', $idArchivesToDelete) . ")\n \t\t\t\t\t\t"; Piwik_Query(sprintf($query, $blobTable)); Piwik_Query(sprintf($query, $numericTable)); } Piwik::log("Purging temporary archives: done [ purged archives older than {$purgeArchivesOlderThan} from {$blobTable} and {$numericTable} ] [Deleted IDs: " . implode(',', $idArchivesToDelete) . "]"); // Deleting "Custom Date Range" reports after 1 day, since they can be re-processed // and would take up unecessary space $yesterday = Piwik_Date::factory('yesterday')->getDateTime(); $query = "DELETE \n \t\t\t\t\tFROM %s\n \t\t\t\t\tWHERE period = ?\n \t\t\t\t\t\tAND ts_archived < ?"; $bind = array(Piwik::$idPeriods['range'], $yesterday); Piwik::log("Purging Custom Range archives: done [ purged archives older than {$yesterday} from {$blobTable} and {$numericTable} ]"); Piwik_Query(sprintf($query, $blobTable), $bind); Piwik_Query(sprintf($query, $numericTable), $bind); // these tables will be OPTIMIZEd daily in a scheduled task, to claim lost space } else { Piwik::log("Purging temporary archives: skipped."); } if (!isset($this->archives)) { return; } foreach ($this->archives as $archive) { destroy($archive); } $this->archives = array(); }
function _retrieveCurrentValue() { $this->current_value = Piwik_Version::VERSION; $this->recommended_value = Piwik_GetOption(Piwik_UpdateCheck::LATEST_VERSION); }
/** * @return Piwik_View with all data set */ protected function buildView() { $view = new Piwik_View($this->dataTableTemplate); if (!$this->isDataAvailable) { $view->arrayDataTable = array(); } else { $columns = $this->getColumnsToDisplay(); $columnTranslations = $columnDocumentation = array(); foreach ($columns as $columnName) { $columnTranslations[$columnName] = $this->getColumnTranslation($columnName); $columnDocumentation[$columnName] = $this->getMetricDocumentation($columnName); } $nbColumns = count($columns); // case no data in the array we use the number of columns set to be displayed if ($nbColumns == 0) { $nbColumns = count($this->columnsToDisplay); } $view->arrayDataTable = $this->getPHPArrayFromDataTable(); $view->dataTableColumns = $columns; $view->reportDocumentation = $this->getReportDocumentation(); $view->columnTranslations = $columnTranslations; $view->columnDocumentation = $columnDocumentation; $view->nbColumns = $nbColumns; $view->defaultWhenColumnValueNotDefined = '-'; // if it's likely that the report data for this data table has been purged, // set whether we should display a message to that effect. $view->showReportDataWasPurgedMessage = $this->hasReportBeenPurged(); $view->deleteReportsOlderThan = Piwik_GetOption('delete_reports_older_than'); } $view->javascriptVariablesToSet = $this->getJavascriptVariablesToSet(); $view->properties = $this->getViewProperties(); return $view; }
/** * Given a monthly archive table, will delete all reports that are now outdated, * or reports that ended with an error */ public static function doPurgeOutdatedArchives($numericTable) { $blobTable = str_replace("numeric", "blob", $numericTable); $key = self::FLAG_TABLE_PURGED . $blobTable; $timestamp = Piwik_GetOption($key); // we shall purge temporary archives after their timeout is finished, plus an extra 6 hours // in case archiving is disabled or run once a day, we give it this extra time to run // and re-process more recent records... // TODO: Instead of hardcoding 6 we should put the actual number of hours between 2 archiving runs $temporaryArchivingTimeout = self::getTodayArchiveTimeToLive(); $purgeEveryNSeconds = max($temporaryArchivingTimeout, 6 * 3600); // we only delete archives if we are able to process them, otherwise, the browser might process reports // when &segment= is specified (or custom date range) and would below, delete temporary archives that the // browser is not able to process until next cron run (which could be more than 1 hour away) if (self::isRequestAuthorizedToArchive() && (!$timestamp || $timestamp < time() - $purgeEveryNSeconds)) { Piwik_SetOption($key, time()); // If Browser Archiving is enabled, it is likely there are many more temporary archives // We delete more often which is safe, since reports are re-processed on demand if (self::isBrowserTriggerArchivingEnabled()) { $purgeArchivesOlderThan = Piwik_Date::factory(time() - 2 * $temporaryArchivingTimeout)->getDateTime(); } else { $purgeArchivesOlderThan = Piwik_Date::factory('today')->getDateTime(); } $result = Piwik_FetchAll("\n\t\t\t\tSELECT idarchive\n\t\t\t\tFROM {$numericTable}\n\t\t\t\tWHERE name LIKE 'done%'\n\t\t\t\t\tAND (( value = " . Piwik_ArchiveProcessing::DONE_OK_TEMPORARY . "\n\t\t\t\t\t\t AND ts_archived < ?)\n\t\t\t\t\t\t OR value = " . Piwik_ArchiveProcessing::DONE_ERROR . ")", array($purgeArchivesOlderThan)); $idArchivesToDelete = array(); if (!empty($result)) { foreach ($result as $row) { $idArchivesToDelete[] = $row['idarchive']; } $query = "DELETE \n \t\t\t\t\t\tFROM %s\n \t\t\t\t\t\tWHERE idarchive IN (" . implode(',', $idArchivesToDelete) . ")\n \t\t\t\t\t\t"; Piwik_Query(sprintf($query, $numericTable)); // Individual blob tables could be missing try { Piwik_Query(sprintf($query, $blobTable)); } catch (Exception $e) { } } Piwik::log("Purging temporary archives: done [ purged archives older than {$purgeArchivesOlderThan} from {$blobTable} and {$numericTable} ] [Deleted IDs: " . implode(',', $idArchivesToDelete) . "]"); // Deleting "Custom Date Range" reports after 1 day, since they can be re-processed // and would take up unecessary space $yesterday = Piwik_Date::factory('yesterday')->getDateTime(); $query = "DELETE \n \t\t\t\t\tFROM %s\n \t\t\t\t\tWHERE period = ?\n \t\t\t\t\t\tAND ts_archived < ?"; $bind = array(Piwik::$idPeriods['range'], $yesterday); Piwik::log("Purging Custom Range archives: done [ purged archives older than {$yesterday} from {$blobTable} and {$numericTable} ]"); Piwik_Query(sprintf($query, $numericTable), $bind); // Individual blob tables could be missing try { Piwik_Query(sprintf($query, $blobTable), $bind); } catch (Exception $e) { } // these tables will be OPTIMIZEd daily in a scheduled task, to claim lost space } else { Piwik::log("Purging temporary archives: skipped."); } }
public static function isBrowserTriggerArchivingEnabled() { $browserArchivingEnabled = Piwik_GetOption(self::OPTION_BROWSER_TRIGGER_ARCHIVING); if ($browserArchivingEnabled !== false) { return (bool) $browserArchivingEnabled; } return (bool) Piwik_Config::getInstance()->General['enable_browser_archiving_triggering']; }
/** Make sure the first time deleteReportData is run, nothing happens. */ public function test_deleteReportData_initialRun() { $this->addLogData(); $this->addReportData(); $this->instance->deleteReportData(); // check that initial option is set $this->assertEqual(1, Piwik_GetOption(Piwik_PrivacyManager::OPTION_LAST_DELETE_PIWIK_LOGS_INITIAL)); // perform other checks $this->checkNoDataChanges(); }
/** * Construct list of outdated components * * @return array array( componentName => array( oldVersion, newVersion), [...]) */ private function loadComponentsWithNewVersion() { $componentsToUpdate = array(); // we make sure core updates are processed before any plugin updates if (isset($this->componentsToCheck['core'])) { $coreVersions = $this->componentsToCheck['core']; unset($this->componentsToCheck['core']); $this->componentsToCheck = array_merge(array('core' => $coreVersions), $this->componentsToCheck); } foreach ($this->componentsToCheck as $name => $version) { try { $currentVersion = Piwik_GetOption('version_' . $name); } catch (Exception $e) { // mysql error 1146: table doesn't exist if (Zend_Registry::get('db')->isErrNo($e, '1146')) { // case when the option table is not yet created (before 0.2.10) $currentVersion = false; } else { // failed for some other reason throw $e; } } if ($currentVersion === false) { if ($name === 'core') { $currentVersion = '0.2.9'; } else { $currentVersion = '0.0.1'; } $this->recordComponentSuccessfullyUpdated($name, $currentVersion); } $versionCompare = version_compare($currentVersion, $version); if ($versionCompare == -1) { $componentsToUpdate[$name] = array(self::INDEX_CURRENT_VERSION => $currentVersion, self::INDEX_NEW_VERSION => $version); } else { if ($versionCompare == 1) { // the version in the DB is newest.. we choose to ignore (for the time being) } } } return $componentsToUpdate; }