init(); $archiving->run(); $archiving->end(); } catch (Exception $e) { $archiving->logFatalError($e->getMessage()); } class Archiving { const OPTION_ARCHIVING_FINISHED_TS = "LastCompletedFullArchiving"; const TRUNCATE_ERROR_MESSAGE_SUMMARY = 400; // Seconds window to look back to define "active websites" to archive on the first archive.php script execution private $firstRunActiveWebsitesWithTraffic = 604800; // 7 days // By default, we only process the current week/month/year at most once an hour private $processPeriodsMaximumEverySeconds = 3600; private $websiteDayHasFinishedSinceLastRun = array(); private $idSitesInvalidatedOldReports = array(); private $piwikUrl = false; private $token_auth = false; private $visits = 0; private $requests = 0; private $output = ''; private $shouldResetState = false; private $shouldArchiveAllWebsites = false; private $acceptInvalidSSLCertificate = false; /** * By default, will process last 52 days/weeks/months/year. * It will be overwritten by the number of days since last archiving ran until completion. */ const DEFAULT_DATE_LAST = 52; // Since weeks are not used in yearly archives, we make sure that all possible weeks are processed const DEFAULT_DATE_LAST_WEEKS = 520; private $timeLastCompleted = false; private $requestPrepend = '&trigger=archivephp'; private $errors = array(); public function init() { $this->initCore(); $this->initTokenAuth(); $this->initCheckCli(); $this->initLog(); $this->displayHelp(); $this->initPiwikHost(); $this->initStateFromParameters(); Piwik::setUserIsSuperUser(true); $this->logSection("INIT"); $this->log("Querying Piwik API at: {$this->piwikUrl}"); $this->log("Running Piwik " . Piwik_Version::VERSION . " as Super User: " . $this->login); $this->acceptInvalidSSLCertificate = $this->isParameterSet("accept-invalid-ssl-certificate"); // Test the specified piwik URL is valid $response = $this->request("?module=API&method=API.getDefaultMetricTranslations&format=original&serialize=1"); $responseUnserialized = @unserialize($response); if ($response === false || !is_array($responseUnserialized) ) { $this->logFatalError("The Piwik URL {$this->piwikUrl} does not seem to be pointing to a Piwik server. Response was '$response'."); } $this->log("Notes"); // Information about timeout $this->todayArchiveTimeToLive = Piwik_ArchiveProcessor_Rules::getTodayArchiveTimeToLive(); $this->log("- Reports for today will be processed at most every " . $this->todayArchiveTimeToLive . " seconds. You can change this value in Piwik UI > Settings > General Settings."); $this->log("- Reports for the current week/month/year will be refreshed at most every " . $this->processPeriodsMaximumEverySeconds . " seconds."); $this->initSegmentsToArchive(); // Try and not request older data we know is already archived if ($this->timeLastCompleted !== false) { $dateLast = time() - $this->timeLastCompleted; $this->log("- Archiving was last executed without error " . Piwik::getPrettyTimeFromSeconds($dateLast, true, $isHtml = false) . " ago"); } $this->initWebsitesToProcess(); flush(); } /** * Returns URL to process reports for the $idsite on a given period with no segment */ private function getVisitsRequestUrl($idsite, $period, $lastTimestampWebsiteProcessed = false) { if (empty($lastTimestampWebsiteProcessed)) { $dateLast = self::DEFAULT_DATE_LAST; if ($period == 'week') { $dateLast = self::DEFAULT_DATE_LAST_WEEKS; } } else { // Enforcing last2 at minimum to work around timing issues and ensure we make most archives available $dateLast = floor((time() - $lastTimestampWebsiteProcessed) / 86400) + 2; if ($dateLast > self::DEFAULT_DATE_LAST) { $dateLast = self::DEFAULT_DATE_LAST; } } return "?module=API&method=VisitsSummary.getVisits&idSite=$idsite&period=$period&date=last" . $dateLast . "&format=php&token_auth=" . $this->token_auth; } private function lastRunKey($idsite, $period) { return Piwik::getArchiveCronLastRunOptionName($period, $idsite); } /** * Main function, runs archiving on all websites with new activity */ public function run() { $websitesWithVisitsSinceLastRun = $skippedPeriodsArchivesWebsite = $skippedDayArchivesWebsites = $skipped = $processed = $archivedPeriodsArchivesWebsite = 0; $timer = new Piwik_Timer; $this->logSection("START"); $this->log("Starting Piwik reports archiving..."); $this->websites = array_unique($this->websites); foreach ($this->websites as $idsite) { flush(); $requestsBefore = $this->requests; if ($idsite <= 0) { continue; } $timerWebsite = new Piwik_Timer; $lastTimestampWebsiteProcessedPeriods = $lastTimestampWebsiteProcessedDay = false; if (!$this->shouldResetState) { $lastTimestampWebsiteProcessedPeriods = Piwik_GetOption($this->lastRunKey($idsite, "periods")); $lastTimestampWebsiteProcessedDay = Piwik_GetOption($this->lastRunKey($idsite, "day")); } // For period other than days, we only re-process the reports at most // 1) every $processPeriodsMaximumEverySeconds $secondsSinceLastExecution = time() - $lastTimestampWebsiteProcessedPeriods; // if timeout is more than 10 min, we account for a 5 min processing time, and allow trigger 1 min earlier if ($this->processPeriodsMaximumEverySeconds > 10 * 60) { $secondsSinceLastExecution += 5 * 60; } $shouldArchivePeriods = $secondsSinceLastExecution > $this->processPeriodsMaximumEverySeconds; if (empty($lastTimestampWebsiteProcessedPeriods)) { // 2) OR always if script never executed for this website before $shouldArchivePeriods = true; } // (*) If the website is archived because it is a new day in its timezone // We make sure all periods are archived, even if there is 0 visit today $dayHasEndedMustReprocess = in_array($idsite, $this->websiteDayHasFinishedSinceLastRun); if ($dayHasEndedMustReprocess) { $shouldArchivePeriods = true; } // (*) If there was some old reports invalidated for this website // we make sure all these old reports are triggered at least once $websiteIsOldDataInvalidate = in_array($idsite, $this->idSitesInvalidatedOldReports); if ($websiteIsOldDataInvalidate) { $shouldArchivePeriods = true; } // Test if we should process this website at all $elapsedSinceLastArchiving = time() - $lastTimestampWebsiteProcessedDay; if (!$websiteIsOldDataInvalidate // Invalidate old website forces the archiving for this site && !$dayHasEndedMustReprocess // Also reprocess when day has ended since last run && $elapsedSinceLastArchiving < $this->todayArchiveTimeToLive ) { $this->log("Skipped website id $idsite, already processed today's report in recent run, " . Piwik::getPrettyTimeFromSeconds($elapsedSinceLastArchiving, true, $isHtml = false) . " ago, " . $timerWebsite->__toString()); $skippedDayArchivesWebsites++; $skipped++; continue; } // Fake that the request is already done, so that other archive.php // running do not grab the same website from the queue Piwik_SetOption($this->lastRunKey($idsite, "day"), time()); $url = $this->getVisitsRequestUrl($idsite, "day", // when some data was purged from this website // we make sure we query all previous days/weeks/months ($websiteIsOldDataInvalidate // when --force-all-websites option, // also forces to archive last52 days to be safe || $this->shouldArchiveAllWebsites) ? false : $lastTimestampWebsiteProcessedDay ); $content = $this->request($url); $response = @unserialize($content); if (empty($content) || !is_array($response) || count($response) == 0 ) { // cancel the succesful run flag Piwik_SetOption($this->lastRunKey($idsite, "day"), 0); $this->log("WARNING: Empty or invalid response '$content' for website id $idsite, " . $timerWebsite->__toString() . ", skipping"); $skipped++; continue; } $visitsToday = end($response); if(empty($visitsToday)) { $visitsToday = 0; } $this->requests++; $processed++; // If there is no visit today and we don't need to process this website, we can skip remaining archives if ($visitsToday == 0 && !$shouldArchivePeriods ) { $this->log("Skipped website id $idsite, no visit today, " . $timerWebsite->__toString()); $skipped++; continue; } $visitsAllDays = array_sum($response); if ($visitsAllDays == 0 && !$shouldArchivePeriods && $this->shouldArchiveAllWebsites ) { $this->log("Skipped website id $idsite, no visits in the last " . count($response) . " days, " . $timerWebsite->__toString()); $skipped++; continue; } $this->visits += $visitsToday; $websitesWithVisitsSinceLastRun++; $this->archiveVisitsAndSegments($idsite, "day", $lastTimestampWebsiteProcessedDay, $timerWebsite); if ($shouldArchivePeriods) { $success = true; foreach (array('week', 'month', 'year') as $period) { $success = $this->archiveVisitsAndSegments($idsite, $period, $lastTimestampWebsiteProcessedPeriods) && $success; } // Record succesful run of this website's periods archiving if ($success) { Piwik_SetOption($this->lastRunKey($idsite, "periods"), time()); // Remove this website from the list of websites to be invalidated // since it's now just been re-processing the reports, job is done! if ($websiteIsOldDataInvalidate) { $websiteIdsInvalidated = Piwik_CoreAdminHome_API::getWebsiteIdsToInvalidate(); if (count($websiteIdsInvalidated)) { $found = array_search($idsite, $websiteIdsInvalidated); if ($found !== false) { unset($websiteIdsInvalidated[$found]); // $this->log("Websites left to invalidate: " . implode(", ", $websiteIdsInvalidated)); Piwik_SetOption(Piwik_CoreAdminHome_API::OPTION_INVALIDATED_IDSITES, serialize($websiteIdsInvalidated)); } } } } } $archivedPeriodsArchivesWebsite++; $requestsWebsite = $this->requests - $requestsBefore; $debug = $this->shouldArchiveAllWebsites ? ", last days = $visitsAllDays visits" : ""; Piwik::log("Archived website id = $idsite, today = $visitsToday visits" . $debug . ", $requestsWebsite API requests, " . $timerWebsite->__toString() . " [" . ($websitesWithVisitsSinceLastRun + $skipped) . "/" . count($this->websites) . " done]"); } $this->log("Done archiving!"); $this->logSection("SUMMARY"); $this->log("Total daily visits archived: " . $this->visits); $totalWebsites = count($this->allWebsites); $skipped = $totalWebsites - $websitesWithVisitsSinceLastRun; $this->log("Archived today's reports for $websitesWithVisitsSinceLastRun websites"); $this->log("Archived week/month/year for $archivedPeriodsArchivesWebsite websites. "); $this->log("Skipped $skipped websites: no new visit since the last script execution"); $this->log("Skipped $skippedDayArchivesWebsites websites day archiving: existing daily reports are less than {$this->todayArchiveTimeToLive} seconds old"); $this->log("Skipped $skippedPeriodsArchivesWebsite websites week/month/year archiving: existing periods reports are less than {$this->processPeriodsMaximumEverySeconds} seconds old"); $this->log("Total API requests: $this->requests"); //DONE: done/total, visits, wtoday, wperiods, reqs, time, errors[count]: first eg. $percent = count($this->websites) == 0 ? "" : " " . round($processed * 100 / count($this->websites), 0) . "%"; $otherInParallel = $skippedDayArchivesWebsites; $this->log("done: " . $processed . "/" . count($this->websites) . "" . $percent . ", " . $this->visits . " v, $websitesWithVisitsSinceLastRun wtoday, $archivedPeriodsArchivesWebsite wperiods, " . $this->requests . " req, " . round($timer->getTimeMs()) . " ms, " . (empty($this->errors) ? "no error" : (count($this->errors) . " errors. eg. '" . reset($this->errors) . "'")) ); $this->log($timer->__toString()); $this->logSection("SCHEDULED TASKS"); $this->log("Starting Scheduled tasks... "); $tasksOutput = $this->request("?module=API&method=CoreAdminHome.runScheduledTasks&format=csv&convertToUnicode=0&token_auth=" . $this->token_auth); if ($tasksOutput == "No data available") { $tasksOutput = " No task to run"; } $this->log($tasksOutput); $this->log("done"); } private function initSegmentsToArchive() { // Fetching segments to process $this->segments = Piwik_CoreAdminHome_API::getInstance()->getKnownSegmentsToArchive(); if (empty($this->segments)) $this->segments = array(); if (!empty($this->segments)) { $this->log("- Will pre-process " . count($this->segments) . " Segments for each website and each period: " . implode(", ", $this->segments)); } } private function getSegmentsForSite($idsite) { $segmentsAllSites = $this->segments; $segmentsThisSite = Piwik::getKnownSegmentsToArchiveForSite($idsite); if (!empty($segmentsThisSite)) { $this->log("Will pre-process the following " . count($segmentsThisSite) . " Segments for this website (id = $idsite): " . implode(", ", $segmentsThisSite)); } $segments = array_unique(array_merge($segmentsAllSites, $segmentsThisSite)); return $segments; } /** * Archive visits and segments. * * @param $idsite int * @param $period * @param $lastTimestampWebsiteProcessed * @param Piwik_Timer $timerWebsite * @return bool True on success, false if some request failed */ private function archiveVisitsAndSegments($idsite, $period, $lastTimestampWebsiteProcessed, Piwik_Timer $timerWebsite = null) { $timer = new Piwik_Timer; $aCurl = array(); $mh = false; $url = $this->piwikUrl . $this->getVisitsRequestUrl($idsite, $period, $lastTimestampWebsiteProcessed) . $this->requestPrepend; // already processed above for "day" if ($period != "day") { $ch = $this->getNewCurlHandle($url); $aCurl[$url] = $ch; $this->requests++; } $urlNoSegment = $url; foreach ($this->getSegmentsForSite($idsite) as $segment) { $segmentUrl = $url . '&segment=' . urlencode($segment); $ch = $this->getNewCurlHandle($segmentUrl); $aCurl[$segmentUrl] = $ch; $this->requests++; } $success = true; $visitsAllDaysInPeriod = false; if (!empty($aCurl)) { // FIXME: This code used to execute multiple curl requests asynchronously. This caused // deadlocks since archive tables are locked for the entire archiving process. Moving back // to synchronous requests is a quick fix, but the locking mechanism can be changed to // only lock when getting the new archive ID. When that is done, this code should be changed // back to use asnychronous requests. foreach ($aCurl as $url => $ch) { $content = curl_exec($ch); $successResponse = $this->checkResponse($content, $url); $success = $successResponse && $success; if ($url == $urlNoSegment && $successResponse ) { $stats = unserialize($content); if (!is_array($stats)) { $this->logError("Error unserializing the following response: " . $content); } $visitsAllDaysInPeriod = @array_sum($stats); } curl_close($ch); } } $this->log("Archived website id = $idsite, period = $period, " . ($period != "day" ? (int)$visitsAllDaysInPeriod . " visits, " : "") . (!empty($timerWebsite) ? $timerWebsite->__toString() : $timer->__toString())); return $success; } private function addCurlHandleToMulti(&$mh, $ch) { if (!$mh) { $mh = curl_multi_init(); } curl_multi_add_handle($mh, $ch); } private function getNewCurlHandle($url) { $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); if ($this->acceptInvalidSSLCertificate) { curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); } curl_setopt($ch, CURLOPT_USERAGENT, Piwik_Http::getUserAgent()); Piwik_Http::configCurlCertificate($ch); return $ch; } /** * Logs a section in the output */ private function logSection($title = "") { $this->log("---------------------------"); $this->log($title); } /** * End of the script */ public function end() { // How to test the error handling code? // - Generate some hits since last archive.php run // - Start the script, in the middle, shutdown apache, then restore // Some errors should be logged and script should successfully finish and then report the errors and trigger a PHP error if (!empty($this->errors)) { $this->logSection("SUMMARY OF ERRORS"); foreach ($this->errors as $error) { $this->log("Error: " . $error); } $summary = count($this->errors) . " total errors during this script execution, please investigate and try and fix these errors"; $this->log($summary); $summary .= '. First error was: ' . reset($this->errors); $this->logFatalError($summary); } else { // No error -> Logs the successful script execution until completion Piwik_SetOption(self::OPTION_ARCHIVING_FINISHED_TS, time()); } } private function log($m) { $this->output .= $m . "\n"; Piwik::log($m); } /** * Issues a request to $url */ private function request($url) { $url = $this->piwikUrl . $url . $this->requestPrepend; //$this->log($url); try { $response = Piwik_Http::sendHttpRequestBy('curl', $url, $timeout = 300, $userAgent = null, $destinationPath = null, $file = null, $followDepth = 0, $acceptLanguage = false, $acceptInvalidSSLCertificate = $this->acceptInvalidSSLCertificate); } catch (Exception $e) { return $this->logNetworkError($url, $e->getMessage()); } if ($this->checkResponse($response, $url)) { return $response; } return false; } private function checkResponse($response, $url) { if (empty($response) || stripos($response, 'error') ) { return $this->logNetworkError($url, $response); } return true; } private function logError($m) { $this->errors[] = substr($m, 0, self::TRUNCATE_ERROR_MESSAGE_SUMMARY); $this->log("ERROR: $m"); } public function logFatalError($m, $backtrace = true) { $this->logError($m); $fe = fopen('php://stderr', 'w'); fwrite($fe, "Error in the last Piwik archive.php run: \n" . $m . ($backtrace ? "\n\n Here is the full errors output:\n\n" . $this->output : '') ); trigger_error($m, E_USER_ERROR); exit; } private function logNetworkError($url, $response) { $message = "Got invalid response from API request: $url. "; if (empty($response)) { $message .= "The response was empty. This usually means a server error. This solution to this error is generally to increase the value of 'memory_limit' in your php.ini file. Please check your Web server Error Log file for more details."; } else { $message .= "Response was '$response'"; } $this->logError($message); return false; } /** * Displays script usage */ private function usage() { global $USAGE; $this->logLines($USAGE); } private function logLines($t) { foreach (explode(PHP_EOL, $t) as $line) { $this->log($line); } } private function initLog() { $config = Config::getInstance(); $config->log['log_only_when_debug_parameter'] = 0; $config->log['logger_message'] = array("logger_message" => "screen"); Piwik::createLogObject(); if (!function_exists("curl_multi_init")) { $this->log("ERROR: this script requires curl extension php_curl enabled in your CLI php.ini"); $this->usage(); exit; } } /** * Script does run on http:// ONLY if the SU token is specified */ private function initCheckCli() { if (!Common::isPhpCliMode()) { $token_auth = Common::getRequestVar('token_auth', '', 'string'); if ($token_auth != $this->token_auth || strlen($token_auth) != 32 ) { die('You must specify the Super User token_auth as a parameter to this script, eg. ?token_auth=XYZ if you wish to run this script through the browser.
However it is recommended to run it via cron in the command line, since it can take a long time to run.
In a shell, execute for example the following to trigger archiving on the local Piwik server:
$ /path/to/php /path/to/piwik/misc/cron/archive.php --url=http://your-website.org/path/to/piwik/'); } } } /** * Init Piwik, connect DB, create log & config objects, etc. */ private function initCore() { try { Piwik_FrontController::getInstance()->init(); } catch (Exception $e) { echo "ERROR: During Piwik init, Message: " . $e->getMessage(); exit; } } private function displayHelp() { $displayHelp = $this->isParameterSet('help') || $this->isParameterSet('h'); if ($displayHelp) { $this->usage(); exit; } } private 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 ) // in case --force-timeout-for-periods= without [seconds] specified { // Ensure the cache for periods is at least as high as cache for today $todayTTL = Piwik_ArchiveProcessor_Rules::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_ArchiveProcessor_Rules::isBrowserTriggerEnabled()) { $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; } } // Fetching websites to process private function initWebsitesToProcess() { $this->allWebsites = Piwik_SitesManager_API::getInstance()->getAllSitesId(); if ($this->shouldArchiveAllWebsites) { $this->websites = $this->allWebsites; $this->log("Will process " . count($this->websites) . " websites"); } else { // 1) All websites with visits since the last archive.php execution $timestampActiveTraffic = $this->timeLastCompleted; if (empty($timestampActiveTraffic)) { $timestampActiveTraffic = time() - $this->firstRunActiveWebsitesWithTraffic; $this->log("--force-all-periods was detected: we will process websites with visits in the last " . Piwik::getPrettyTimeFromSeconds($this->firstRunActiveWebsitesWithTraffic, true, false) ); } $this->websites = Piwik_SitesManager_API::getInstance()->getSitesIdWithVisits($timestampActiveTraffic); $websiteIds = !empty($this->websites) ? ", IDs: " . implode(", ", $this->websites) : ""; $prettySeconds = Piwik::getPrettyTimeFromSeconds(empty($this->timeLastCompleted) ? $this->firstRunActiveWebsitesWithTraffic : (time() - $this->timeLastCompleted), true, false); $this->log("Will process " . count($this->websites) . " websites with new visits since " . $prettySeconds . " " . $websiteIds); // 2) All websites that had reports in the past invalidated recently // eg. when using Python log import script $this->idSitesInvalidatedOldReports = Piwik_CoreAdminHome_API::getWebsiteIdsToInvalidate(); $this->idSitesInvalidatedOldReports = array_intersect($this->idSitesInvalidatedOldReports, $this->allWebsites); if (count($this->idSitesInvalidatedOldReports) > 0) { $websiteIds = ", IDs: " . implode(", ", $this->idSitesInvalidatedOldReports); $this->log("Will process " . count($this->idSitesInvalidatedOldReports) . " other websites because some old data reports have been invalidated (eg. using the Log Import script) " . $websiteIds); $this->websites = array_merge($this->websites, $this->idSitesInvalidatedOldReports); } // 3) Also process all other websites which days have finished since the last run. // This ensures we process the previous day/week/month/year that just finished, even if there was no new visit $uniqueTimezones = Piwik_SitesManager_API::getInstance()->getUniqueSiteTimezones(); $timezoneToProcess = array(); foreach ($uniqueTimezones as &$timezone) { $processedDateInTz = Piwik_Date::factory((int)$timestampActiveTraffic, $timezone); $currentDateInTz = Piwik_Date::factory('now', $timezone); if ($processedDateInTz->toString() != $currentDateInTz->toString()) { $timezoneToProcess[] = $timezone; } } $websiteDayHasFinishedSinceLastRun = Piwik_SitesManager_API::getInstance()->getSitesIdFromTimezones($timezoneToProcess); $websiteDayHasFinishedSinceLastRun = array_diff($websiteDayHasFinishedSinceLastRun, $this->websites); $this->websiteDayHasFinishedSinceLastRun = $websiteDayHasFinishedSinceLastRun; if (count($websiteDayHasFinishedSinceLastRun) > 0) { $websiteIds = !empty($websiteDayHasFinishedSinceLastRun) ? ", IDs: " . implode(", ", $websiteDayHasFinishedSinceLastRun) : ""; $this->log("Will process " . count($websiteDayHasFinishedSinceLastRun) . " other websites because the last time they were archived was on a different day (in the website's timezone) " . $websiteIds); $this->websites = array_merge($this->websites, $websiteDayHasFinishedSinceLastRun); } } } private function initTokenAuth() { $login = Config::getInstance()->superuser['login']; $md5Password = Config::getInstance()->superuser['password']; $this->token_auth = md5($login . $md5Password); $this->login = $login; } private function initPiwikHost() { // If archive.php run as a web cron, we use the current hostname if (!Common::isPhpCliMode()) { // example.org/piwik/misc/cron/ $piwikUrl = Common::sanitizeInputValue(Piwik_Url::getCurrentUrlWithoutFileName()); // example.org/piwik/ $piwikUrl = $piwikUrl . "../../"; } // If archive.php run as CLI/shell we require the piwik url to be set else { $piwikUrl = $this->isParameterSet("url", true); if (!$piwikUrl || !Common::isLookLikeUrl($piwikUrl) ) { $this->logFatalError("archive.php expects the argument --url to be set to your Piwik URL, for example: --url=http://example.org/piwik/ ", $backtrace = false); } // ensure there is a trailing slash if ($piwikUrl[strlen($piwikUrl) - 1] != '/') { $piwikUrl .= '/'; } } if (Config::getInstance()->General['force_ssl'] == 1) { $piwikUrl = str_replace('http://', 'https://', $piwikUrl); } $this->piwikUrl = $piwikUrl . "index.php"; } /** * Returns if the requested parameter is defined in the command line arguments. * If $valuePossible is true, then a value is possibly set for this parameter, * ie. --force-timeout-for-periods=3600 would return 3600 * * @param $parameter * @param bool $valuePossible * @return true or the value (int,string) if set, false otherwise */ private function isParameterSet($parameter, $valuePossible = false) { if (!Common::isPhpCliMode()) { return false; } $parameters = array( "--$parameter", "-$parameter", $parameter ); foreach ($parameters as $parameter) { foreach ($_SERVER['argv'] as $arg) { if (strpos($arg, $parameter) === 0) { if ($valuePossible) { $parameterFound = $arg; if (($posEqual = strpos($parameterFound, '=')) !== false) { $return = substr($parameterFound, $posEqual + 1); if ($return !== false) { return $return; } } } return true; } } } return false; } }