/** * runTasks collects tasks defined within piwik plugins, runs them if they are scheduled and reschedules * the tasks that have been executed. * * @return array */ public static function runTasks() { // Gets the array where rescheduled timetables are stored $option = Piwik_GetOption(self::TIMETABLE_OPTION_STRING); $timetable = self::getTimetableFromOption($option); if ($timetable === false) { return; } $forceScheduledTasks = false; if (isset($GLOBALS['PIWIK_TRACKER_DEBUG_FORCE_SCHEDULED_TASKS']) && $GLOBALS['PIWIK_TRACKER_DEBUG_FORCE_SCHEDULED_TASKS'] || DEBUG_FORCE_SCHEDULED_TASKS) { $forceScheduledTasks = true; $timetable = array(); } // Collects tasks Piwik_PostEvent(self::GET_TASKS_EVENT, $tasks); $return = array(); // for every priority level, starting with the highest and concluding with the lowest for ($priority = Piwik_ScheduledTask::HIGHEST_PRIORITY; $priority <= Piwik_ScheduledTask::LOWEST_PRIORITY; ++$priority) { // Loop through each task foreach ($tasks as $task) { // if the task does not have the current priority level, don't execute it yet if ($task->getPriority() != $priority) { continue; } $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] || $forceScheduledTasks) { // Updates the rescheduled time $timetable[$fullyQualifiedMethodName] = $scheduledTime->getRescheduledTime(); Piwik_SetOption(self::TIMETABLE_OPTION_STRING, serialize($timetable)); self::$running = true; // Run the task try { $timer = new Piwik_Timer(); call_user_func(array($className, $methodName)); $message = $timer->__toString(); } catch (Exception $e) { $message = 'ERROR: ' . $e->getMessage(); } self::$running = false; $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; }
/** * Tracker requests will automatically trigger the Scheduled tasks. * This is useful for users who don't setup the cron, * but still want daily/weekly/monthly PDF reports emailed automatically. * * This is similar to calling the API CoreAdminHome.runScheduledTasks (see misc/cron/archive.sh) * * @param int $now Current timestamp */ public static function runScheduledTasks($now) { // Currently, there is no hourly tasks. When there are some, // this could be too agressive minimum interval (some hours would be skipped in case of low traffic) $minimumInterval = Piwik_Config::getInstance()->Tracker['scheduled_tasks_min_interval']; // If the user disabled browser archiving, he has already setup a cron // To avoid parallel requests triggering the Scheduled Tasks, // Get last time tasks started executing $cache = Piwik_Common::getCacheGeneral(); if ($minimumInterval <= 0 || empty($cache['isBrowserTriggerArchivingEnabled'])) { printDebug("-> Scheduled tasks not running in Tracker: Browser archiving is disabled."); return; } $nextRunTime = $cache['lastTrackerCronRun'] + $minimumInterval; if (isset($GLOBALS['PIWIK_TRACKER_DEBUG_FORCE_SCHEDULED_TASKS']) && $GLOBALS['PIWIK_TRACKER_DEBUG_FORCE_SCHEDULED_TASKS'] || $cache['lastTrackerCronRun'] === false || $nextRunTime < $now) { $cache['lastTrackerCronRun'] = $now; Piwik_Common::setCacheGeneral($cache); Piwik_Common::initCorePiwikInTrackerMode(); Piwik_SetOption('lastTrackerCronRun', $cache['lastTrackerCronRun']); printDebug('-> Scheduled Tasks: Starting...'); // save current user privilege and temporarily assume super user privilege $isSuperUser = Piwik::isUserIsSuperUser(); // Scheduled tasks assume Super User is running Piwik::setUserIsSuperUser(); // While each plugins should ensure that necessary languages are loaded, // we ensure English translations at least are loaded Piwik_Translate::getInstance()->loadEnglishTranslation(); $resultTasks = Piwik_TaskScheduler::runTasks(); // restore original user privilege Piwik::setUserIsSuperUser($isSuperUser); printDebug($resultTasks); printDebug('Finished Scheduled Tasks.'); } else { printDebug("-> Scheduled tasks not triggered."); } printDebug("Next run will be from: " . date('Y-m-d H:i:s', $nextRunTime) . ' UTC'); }
/** * Will run all scheduled tasks due to run at this time. * @return void */ public function runScheduledTasks() { Piwik::checkUserIsSuperUser(); return Piwik_TaskScheduler::runTasks(); }
private function buildDataTable($sites, $period, $date, $segment, $_restrictSitesToLogin, $enhanced) { $allWebsitesRequested = $sites == 'all'; if ($allWebsitesRequested) { if (Piwik::isUserIsSuperUser() && !Piwik_TaskScheduler::isTaskBeingExecuted()) { Piwik_Site::setSites(Piwik_SitesManager_API::getInstance()->getAllSites()); } else { Piwik_Site::setSitesFromArray(Piwik_SitesManager_API::getInstance()->getSitesWithAtLeastViewAccess($limit = false, $_restrictSitesToLogin)); } } // build the archive type used to query archive data $archive = Piwik_Archive::build($sites, $period, $date, $segment, $_restrictSitesToLogin); // determine what data will be displayed $fieldsToGet = array(); $columnNameRewrites = array(); $apiECommerceMetrics = array(); $apiMetrics = Piwik_MultiSites_API::getApiMetrics($enhanced); foreach ($apiMetrics as $metricName => $metricSettings) { $fieldsToGet[] = $metricSettings[self::METRIC_RECORD_NAME_KEY]; $columnNameRewrites[$metricSettings[self::METRIC_RECORD_NAME_KEY]] = $metricName; if ($metricSettings[self::METRIC_IS_ECOMMERCE_KEY]) { $apiECommerceMetrics[$metricName] = $metricSettings; } } // get the data // $dataTable instanceOf Piwik_DataTable_Array $dataTable = $archive->getDataTableFromNumeric($fieldsToGet); // get rid of the DataTable_Array that is created by the IndexedBySite archive type if ($dataTable instanceof Piwik_DataTable_Array && $allWebsitesRequested) { $dataTable = $dataTable->mergeChildren(); } else { if (!$dataTable instanceof Piwik_DataTable_Array) { $firstDataTableRow = $dataTable->getFirstRow(); $firstDataTableRow->setColumn('label', $sites); } } // if the period isn't a range & a lastN/previousN date isn't used, we get the same // data for the last period to show the evolution of visits/actions/revenue if ($period != 'range' && !preg_match('/(last|previous)([0-9]*)/', $date, $regs)) { if (strpos($date, ',')) { $rangePeriod = new Piwik_Period_Range($period, $date); $lastStartDate = Piwik_Period_Range::removePeriod($period, $rangePeriod->getDateStart(), $n = 1); $lastEndDate = Piwik_Period_Range::removePeriod($period, $rangePeriod->getDateEnd(), $n = 1); $strLastDate = "{$lastStartDate},{$lastEndDate}"; } else { $strLastDate = Piwik_Period_Range::removePeriod($period, Piwik_Date::factory($date), $n = 1)->toString(); } $pastArchive = Piwik_Archive::build('all', $period, $strLastDate, $segment, $_restrictSitesToLogin); $pastData = $pastArchive->getDataTableFromNumeric($fieldsToGet); $pastData = $pastData->mergeChildren(); // use past data to calculate evolution percentages $this->calculateEvolutionPercentages($dataTable, $pastData, $apiMetrics); } // remove eCommerce related metrics on non eCommerce Piwik sites // note: this is not optimal in terms of performance: those metrics should not be retrieved in the first place if ($enhanced) { // $dataTableRows instanceOf Piwik_DataTable_Row[] $dataTableRows = $dataTable->getRows(); foreach ($dataTableRows as $dataTableRow) { $siteId = $dataTableRow->getColumn('label'); if (!Piwik_Site::isEcommerceEnabledFor($siteId)) { foreach ($apiECommerceMetrics as $metricSettings) { $dataTableRow->deleteColumn($metricSettings[self::METRIC_RECORD_NAME_KEY]); $dataTableRow->deleteColumn($metricSettings[self::METRIC_EVOLUTION_COL_NAME_KEY]); } } } } // move the site id to a metadata column $dataTable->filter('ColumnCallbackAddMetadata', array('label', 'idsite')); // set the label of each row to the site name if ($allWebsitesRequested) { $getNameFor = array('Piwik_Site', 'getNameFor'); $dataTable->filter('ColumnCallbackReplace', array('label', $getNameFor)); } else { $dataTable->filter('ColumnDelete', array('label')); } // replace record names with user friendly metric names $dataTable->filter('ReplaceColumnNames', array($columnNameRewrites)); // Ensures data set sorted, for Metadata output $dataTable->filter('Sort', array(self::NB_VISITS_METRIC, 'desc', $naturalSort = false)); // filter rows without visits // note: if only one website is queried and there are no visits, we can not remove the row otherwise Piwik_API_ResponseBuilder throws 'Call to a member function getColumns() on a non-object' if ($allWebsitesRequested) { $dataTable->filter('ColumnCallbackDeleteRow', array(self::NB_VISITS_METRIC, create_function('$value', 'return $value != 0;'))); } return $dataTable; }
/** * Returns the list of websites ID with the 'view' or 'admin' access for the current user. * For the superUser it returns all the websites in the database. * * @return array list of websites ID */ public function getSitesIdWithAtLeastViewAccess($_restrictSitesToLogin = false) { if (!empty($_restrictSitesToLogin) && Piwik_TaskScheduler::isTaskBeingExecuted()) { $accessRaw = Piwik_Access::getRawSitesWithSomeViewAccess($_restrictSitesToLogin); $sitesId = array(); foreach ($accessRaw as $access) { $sitesId[] = $access['idsite']; } return $sitesId; } else { return Zend_Registry::get('access')->getSitesIdWithAtLeastViewAccess(); } }