protected function sendRequest($url, $method = 'GET', $data = null, $force = false) { // if doing a bulk request, store the url if ($this->doBulkRequests && !$force) { $this->storedTrackingActions[] = $url; return true; } if ($method == 'POST') { $requests = array(); foreach ($this->storedTrackingActions as $action) { $requests[] = $this->parseUrl($action); } $testEnvironmentArgs = array(); } else { $testEnvironmentArgs = $this->parseUrl($url); $requests = array($testEnvironmentArgs); } // unset cached values Cache::$trackerCache = null; Tracker::setForceIp(null); Tracker::setForceDateTime(null); // save some values $plugins = Config::getInstance()->Plugins['Plugins']; $oldTrackerConfig = Config::getInstance()->Tracker; \Piwik\Plugin\Manager::getInstance()->unloadPlugins(); // modify config $GLOBALS['PIWIK_TRACKER_MODE'] = true; $GLOBALS['PIWIK_TRACKER_LOCAL_TRACKING'] = true; Tracker::$initTrackerMode = false; Tracker::setTestEnvironment($testEnvironmentArgs, $method); // set language $oldLang = isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? $_SERVER['HTTP_ACCEPT_LANGUAGE'] : ''; $_SERVER['HTTP_ACCEPT_LANGUAGE'] = $this->acceptLanguage; // set user agent $oldUserAgent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ''; $_SERVER['HTTP_USER_AGENT'] = $this->userAgent; // set cookie $oldCookie = $_COOKIE; // parse_str(parse_url($this->requestCookie, PHP_URL_QUERY), $_COOKIE); // do tracking and capture output ob_start(); $localTracker = new Tracker(); $localTracker->main($requests); $output = ob_get_contents(); ob_end_clean(); // restore vars Config::getInstance()->Tracker = $oldTrackerConfig; $_SERVER['HTTP_ACCEPT_LANGUAGE'] = $oldLang; $_SERVER['HTTP_USER_AGENT'] = $oldUserAgent; $_COOKIE = $oldCookie; $GLOBALS['PIWIK_TRACKER_LOCAL_TRACKING'] = false; $GLOBALS['PIWIK_TRACKER_MODE'] = false; unset($_GET['bots']); // reload plugins \Piwik\Plugin\Manager::getInstance()->loadPlugins($plugins); return $output; }
public function shouldRun(Tracker $tracker) { if (Common::isPhpCliMode()) { // don't run scheduled tasks in CLI mode from Tracker, this is the case // where we bulk load logs & don't want to lose time with tasks return false; } return $tracker->shouldRecordStatistics(); }
public function process(Tracker $tracker, RequestSet $requestSet) { $queueManager = $this->getQueueManager(); $queueManager->addRequestSetToQueues($requestSet); $tracker->setCountOfLoggedRequests($requestSet->getNumberOfRequests()); $this->sendResponseNow($tracker, $requestSet); if ($this->isAllowedToProcessInTrackerMode() && $queueManager->canAcquireMoreLocks()) { $this->processQueue($queueManager); } }
public function test_process_ShouldTrackAllSetRequests() { $this->assertSame(0, $this->tracker->getCountOfLoggedRequests()); $this->requestSet->setRequests(array(array('idsite' => 1, 'url' => 'http://localhost/foo?bar'), array('idsite' => 1, 'url' => 'http://localhost'))); $this->handler->process($this->tracker, $this->requestSet); $this->assertSame(2, $this->tracker->getCountOfLoggedRequests()); }
/** * Returns the database connection and creates it if it hasn't been already. * * @return \Piwik\Tracker\Db|\Piwik\Db\AdapterInterface|\Piwik\Db */ public static function get() { if (!empty($GLOBALS['PIWIK_TRACKER_MODE'])) { return Tracker::getDatabase(); } if (self::$connection === null) { self::createDatabaseObject(); } return self::$connection; }
/** * Returns the database connection and creates it if it hasn't been already. * * @return \Piwik\Tracker\Db|\Piwik\Db\AdapterInterface|\Piwik\Db */ public static function get() { if (SettingsServer::isTrackerApiRequest()) { return Tracker::getDatabase(); } if (!self::hasDatabaseObject()) { self::createDatabaseObject(); } return self::$connection; }
/** * @return array names of plugins that have been loaded */ public function loadTrackerPlugins() { $this->unloadPlugins(); $pluginsTracker = PiwikConfig::getInstance()->Plugins_Tracker['Plugins_Tracker']; if (empty($pluginsTracker)) { return array(); } $pluginsTracker = array_diff($pluginsTracker, Tracker::getPluginsNotToLoad()); $this->doNotLoadAlwaysActivatedPlugins(); $this->loadPlugins($pluginsTracker); return $pluginsTracker; }
/** * @return array names of plugins that have been loaded */ public function loadTrackerPlugins() { $this->unloadPlugins(); $pluginsTracker = PiwikConfig::getInstance()->Plugins_Tracker['Plugins_Tracker']; if (empty($pluginsTracker)) { return array(); } $pluginsTracker = array_diff($pluginsTracker, Tracker::getPluginsNotToLoad()); if (defined('PIWIK_TEST_MODE')) { $pluginsTracker = array_intersect($pluginsTracker, $this->getPluginsToLoadDuringTests()); } $this->doNotLoadAlwaysActivatedPlugins(); $this->loadPlugins($pluginsTracker); return $pluginsTracker; }
protected function execute(InputInterface $input, OutputInterface $output) { $systemCheck = new SystemCheck(); $systemCheck->checkRedisIsInstalled(); $trackerEnvironment = new Environment('tracker'); $trackerEnvironment->init(); Log::unsetInstance(); $trackerEnvironment->getContainer()->get('Piwik\\Access')->setSuperUserAccess(false); $trackerEnvironment->getContainer()->get('Piwik\\Plugin\\Manager')->setTrackerPluginsNotToLoad(array('Provider')); Tracker::loadTrackerEnvironment(); if (OutputInterface::VERBOSITY_VERY_VERBOSE <= $output->getVerbosity()) { $GLOBALS['PIWIK_TRACKER_DEBUG'] = true; } $backend = Queue\Factory::makeBackend(); $queueManager = Queue\Factory::makeQueueManager($backend); if (!$queueManager->canAcquireMoreLocks()) { $trackerEnvironment->destroy(); $this->writeSuccessMessage($output, array("Nothing to proccess. Already max number of workers in process.")); return; } $shouldProcess = false; foreach ($queueManager->getAllQueues() as $queue) { if ($queue->shouldProcess()) { $shouldProcess = true; break; } } if (!$shouldProcess) { $trackerEnvironment->destroy(); $this->writeSuccessMessage($output, array("No queue currently needs processing")); return; } $output->writeln("<info>Starting to process request sets, this can take a while</info>"); register_shutdown_function(function () use($queueManager) { $queueManager->unlock(); }); $startTime = microtime(true); $processor = new Processor($queueManager); $processor->setNumberOfMaxBatchesToProcess(1000); $tracker = $processor->process(); $neededTime = microtime(true) - $startTime; $numRequestsTracked = $tracker->getCountOfLoggedRequests(); $requestsPerSecond = $this->getNumberOfRequestsPerSecond($numRequestsTracked, $neededTime); Piwik::postEvent('Tracker.end'); $trackerEnvironment->destroy(); $this->writeSuccessMessage($output, array(sprintf('This worker finished queue processing with %sreq/s (%s requests in %02.2f seconds)', $requestsPerSecond, $numRequestsTracked, $neededTime))); }
public function test_rowCount_whenUpdating_returnsAllMatchedRowsNotOnlyUpdatedRows() { $db = Tracker::getDatabase(); // insert one record $db->query("INSERT INTO `" . Common::prefixTable('option') . "` VALUES ('rowid', '1', false)"); // We will now UPDATE this table and check rowCount() value $sqlUpdate = "UPDATE `" . Common::prefixTable('option') . "` SET option_value = 2"; // when no record was updated, return 0 $result = $db->query($sqlUpdate . " WHERE option_name = 'NOT FOUND'"); $this->assertSame(0, $db->rowCount($result)); // when one record was found and updated, returns 1 $result = $db->query($sqlUpdate . " WHERE option_name = 'rowid'"); $this->assertSame(1, $db->rowCount($result)); // when one record was found but NOT actually updated (as values have not changed), we make sure to return 1 // testing for MYSQLI_CLIENT_FOUND_ROWS and MYSQL_ATTR_FOUND_ROWS $result = $db->query($sqlUpdate . " WHERE option_name = 'rowid'"); $this->assertSame(1, $db->rowCount($result)); }
/** * 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 */ public function runScheduledTasks() { $now = time(); // Currently, there are no hourly tasks. When there are some, // this could be too aggressive minimum interval (some hours would be skipped in case of low traffic) $minimumInterval = TrackerConfig::getConfigValue('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 = Cache::getCacheGeneral(); if ($minimumInterval <= 0 || empty($cache['isBrowserTriggerEnabled'])) { Common::printDebug("-> Scheduled tasks not running in Tracker: Browser archiving is disabled."); return; } $nextRunTime = $cache['lastTrackerCronRun'] + $minimumInterval; if (defined('DEBUG_FORCE_SCHEDULED_TASKS') && DEBUG_FORCE_SCHEDULED_TASKS || $cache['lastTrackerCronRun'] === false || $nextRunTime < $now) { $cache['lastTrackerCronRun'] = $now; Cache::setCacheGeneral($cache); Tracker::initCorePiwikInTrackerMode(); Option::set('lastTrackerCronRun', $cache['lastTrackerCronRun']); Common::printDebug('-> Scheduled Tasks: Starting...'); // save current user privilege and temporarily assume Super User privilege $isSuperUser = Piwik::hasUserSuperUserAccess(); // Scheduled tasks assume Super User is running Piwik::setUserHasSuperUserAccess(); $tokens = CronArchive::getSuperUserTokenAuths(); $tokenAuth = reset($tokens); $invokeScheduledTasksUrl = SettingsPiwik::getPiwikUrl() . "?module=API&format=csv&convertToUnicode=0&method=CoreAdminHome.runScheduledTasks&trigger=archivephp&token_auth={$tokenAuth}"; $cliMulti = new CliMulti(); $responses = $cliMulti->request(array($invokeScheduledTasksUrl)); $resultTasks = reset($responses); // restore original user privilege Piwik::setUserHasSuperUserAccess($isSuperUser); Common::printDebug($resultTasks); Common::printDebug('Finished Scheduled Tasks.'); } else { Common::printDebug("-> Scheduled tasks not triggered."); } Common::printDebug("Next run will be from: " . date('Y-m-d H:i:s', $nextRunTime) . ' UTC'); }
public function shouldRecordStatistics() { if (!$this->record) { return false; } return parent::shouldRecordStatistics(); }
private function getDb() { return Tracker::getDatabase(); }
require_once PIWIK_INCLUDE_PATH . '/core/Db/DAO/Base.php'; require_once PIWIK_INCLUDE_PATH . '/core/Db/DAO/Generic.php'; require_once PIWIK_INCLUDE_PATH . '/core/Db/DAO/Mysql/Generic.php'; require_once PIWIK_INCLUDE_PATH . '/core/Db/DAO/Pgsql/Generic.php'; require_once PIWIK_INCLUDE_PATH . '/core/Db/DAO/Mysql/LogAction.php'; require_once PIWIK_INCLUDE_PATH . '/core/Db/DAO/Pgsql/LogAction.php'; require_once PIWIK_INCLUDE_PATH . '/core/Db/DAO/Mysql/LogVisit.php'; require_once PIWIK_INCLUDE_PATH . '/core/Db/DAO/Pgsql/LogVisit.php'; require_once PIWIK_INCLUDE_PATH . '/core/Db/DAO/Mysql/LogLinkVisitAction.php'; require_once PIWIK_INCLUDE_PATH . '/core/Db/DAO/Pgsql/LogLinkVisitAction.php'; // TODO should move to Tracker application class later. currently needed for environment validation. SettingsServer::setIsTrackerApiRequest(); $environment = new \Piwik\Application\Environment('tracker'); $environment->init(); Tracker::loadTrackerEnvironment(); $tracker = new Tracker(); $requestSet = new RequestSet(); ob_start(); try { $handler = Handler\Factory::make(); $response = $tracker->main($handler, $requestSet); if (!is_null($response)) { echo $response; } } catch (Exception $e) { echo "Error:" . $e->getMessage(); exit(1); } if (ob_get_level() > 1) { ob_end_flush(); }
private static function queryIdsAction($actionsNameAndType) { $sql = TableLogAction::getSqlSelectActionId(); $bind = array(); $i = 0; foreach ($actionsNameAndType as &$actionNameType) { list($name, $type, $urlPrefix) = $actionNameType; if (empty($name)) { continue; } if ($i > 0) { $sql .= " OR ( hash = CRC32(?) AND name = ? AND type = ? ) "; } $bind[] = $name; $bind[] = $name; $bind[] = $type; $i++; } // Case URL & Title are empty if (empty($bind)) { return false; } $actionIds = Tracker::getDatabase()->fetchAll($sql, $bind); return $actionIds; }
public function test_process_ShouldUpdateNumberOfLoggedRequests() { $this->assertSame(0, $this->tracker->getCountOfLoggedRequests()); $this->processDummyRequests(); $this->assertSame(2, $this->tracker->getCountOfLoggedRequests()); }
private function outputApiResponse(Tracker $tracker) { if ($tracker->isDebugModeEnabled()) { return; } if ($this->hasAlreadyPrintedOutput()) { return; } $request = $_GET + $_POST; if (array_key_exists('send_image', $request) && $request['send_image'] === '0') { Common::sendResponseCode(204); return; } $this->outputTransparentGif(); }
/** * Print profiling report for the tracker * * @param \Piwik\Db $db Tracker database object (or null) */ public static function displayDbTrackerProfile($db = null) { if (is_null($db)) { $db = Tracker::getDatabase(); } $LogProfiling = Factory::getDAO('log_profiling', $db); $all = $LogProfiling->getAll(); if ($all === false) { return; } uasort($all, 'self::maxSumMsFirst'); $infoIndexedByQuery = array(); foreach ($all as $infoQuery) { $query = $infoQuery['query']; $count = $infoQuery['count']; $sum_time_ms = $infoQuery['sum_time_ms']; $infoIndexedByQuery[$query] = array('count' => $count, 'sumTimeMs' => $sum_time_ms); } self::getSqlProfilingQueryBreakdownOutput($infoIndexedByQuery); }
/** * Gather fields=>values that needs to be updated for the existing visit in log_visit * * @param $action * @param $visitIsConverted * @return array */ protected function getExistingVisitFieldsToUpdate($action, $visitIsConverted) { $valuesToUpdate = array(); if ($action) { $idActionUrl = $action->getIdActionUrlForEntryAndExitIds(); $idActionName = $action->getIdActionNameForEntryAndExitIds(); $actionType = $action->getActionType(); if ($idActionName !== false) { $valuesToUpdate['visit_exit_idaction_name'] = $idActionName; } $incrementActions = false; if ($idActionUrl !== false) { $valuesToUpdate['visit_exit_idaction_url'] = $idActionUrl; $incrementActions = true; } if ($actionType == Action::TYPE_SITE_SEARCH) { $valuesToUpdate['visit_total_searches'] = 'visit_total_searches + 1'; $incrementActions = true; } else { if ($actionType == Action::TYPE_EVENT) { $valuesToUpdate['visit_total_events'] = 'visit_total_events + 1'; $incrementActions = true; } } if ($incrementActions) { $valuesToUpdate['visit_total_actions'] = 'visit_total_actions + 1'; } } $datetimeServer = Tracker::getDatetimeFromTimestamp($this->request->getCurrentTimestamp()); $valuesToUpdate['visit_last_action_time'] = $datetimeServer; // Add 1 so it's always > 0 $visitTotalTime = 1 + $this->request->getCurrentTimestamp() - $this->visitorInfo['visit_first_action_time']; $valuesToUpdate['visit_total_time'] = self::cleanupVisitTotalTime($visitTotalTime); // Goal conversion if ($visitIsConverted) { $valuesToUpdate['visit_goal_converted'] = 1; // If a pageview and goal conversion in the same second, with previously a goal conversion recorded // the request would not "update" the row since all values are the same as previous // therefore the request below throws exception, instead we make sure the UPDATE will affect the row $valuesToUpdate['visit_total_time'] = self::cleanupVisitTotalTime($valuesToUpdate['visit_total_time'] + $this->goalManager->idGoal + 2); } // Might update the idvisitor when it was forced or overwritten for this visit if (strlen($this->visitorInfo['idvisitor']) == Tracker::LENGTH_BINARY_ID) { $valuesToUpdate['idvisitor'] = $this->visitorInfo['idvisitor']; } // Ecommerce buyer status $visitEcommerceStatus = $this->goalManager->getBuyerType($this->visitorInfo['visit_goal_buyer']); if ($visitEcommerceStatus != GoalManager::TYPE_BUYER_NONE && $visitEcommerceStatus != $this->visitorInfo['visit_goal_buyer']) { $valuesToUpdate['visit_goal_buyer'] = $visitEcommerceStatus; } // Custom Variables overwrite previous values on each page view $valuesToUpdate = array_merge($valuesToUpdate, $this->visitorCustomVariables); return $valuesToUpdate; }
public function performSetUp($setupEnvironmentOnly = false) { // TODO: don't use static var, use test env var for this TestingEnvironmentManipulator::$extraPluginsToLoad = $this->extraPluginsToLoad; $this->dbName = $this->getDbName(); if ($this->persistFixtureData) { $this->dropDatabaseInSetUp = false; $this->dropDatabaseInTearDown = false; $this->overwriteExisting = false; $this->removeExistingSuperUser = false; } $testEnv = $this->getTestEnvironment(); $testEnv->testCaseClass = $this->testCaseClass; $testEnv->fixtureClass = get_class($this); $testEnv->dbName = $this->dbName; $testEnv->extraDiEnvironments = $this->extraDiEnvironments; foreach ($this->extraTestEnvVars as $name => $value) { $testEnv->{$name} = $value; } $testEnv->save(); $this->createEnvironmentInstance(); if ($this->dbName === false) { // must be after test config is created $this->dbName = self::getConfig()->database['dbname']; } try { static::connectWithoutDatabase(); if ($this->dropDatabaseInSetUp || $this->resetPersistedFixture) { $this->dropDatabase(); } DbHelper::createDatabase($this->dbName); DbHelper::disconnectDatabase(); Tracker::disconnectCachedDbConnection(); // reconnect once we're sure the database exists self::getConfig()->database['dbname'] = $this->dbName; Db::createDatabaseObject(); Db::get()->query("SET wait_timeout=28800;"); DbHelper::createTables(); self::getPluginManager()->unloadPlugins(); } catch (Exception $e) { static::fail("TEST INITIALIZATION FAILED: " . $e->getMessage() . "\n" . $e->getTraceAsString()); } include "DataFiles/Providers.php"; if (!$this->isFixtureSetUp()) { DbHelper::truncateAllTables(); } // We need to be SU to create websites for tests Access::getInstance()->setSuperUserAccess(); Cache::deleteTrackerCache(); self::resetPluginsInstalledConfig(); $testEnvironment = $this->getTestEnvironment(); static::loadAllPlugins($testEnvironment, $this->testCaseClass, $this->extraPluginsToLoad); self::updateDatabase(); self::installAndActivatePlugins($testEnvironment); $_GET = $_REQUEST = array(); $_SERVER['HTTP_REFERER'] = ''; FakeAccess::$superUserLogin = '******'; File::$invalidateOpCacheBeforeRead = true; if ($this->configureComponents) { IPAnonymizer::deactivate(); $dntChecker = new DoNotTrackHeaderChecker(); $dntChecker->deactivate(); } if ($this->createSuperUser) { self::createSuperUser($this->removeExistingSuperUser); if (!Access::getInstance() instanceof FakeAccess) { $this->loginAsSuperUser(); } APILanguageManager::getInstance()->setLanguageForUser('superUserLogin', 'en'); } SettingsPiwik::overwritePiwikUrl(self::getTestRootUrl()); if ($setupEnvironmentOnly) { return; } PiwikCache::getTransientCache()->flushAll(); if ($this->overwriteExisting || !$this->isFixtureSetUp()) { $this->setUp(); $this->markFixtureSetUp(); $this->log("Database {$this->dbName} marked as successfully set up."); } else { $this->log("Using existing database {$this->dbName}."); } }
public function sendReport($reportType, $report, $contents, $filename, $prettyDate, $reportSubject, $reportTitle, $additionalFiles, Period $period = null, $force) { if (!self::manageEvent($reportType)) { return; } // Safeguard against sending the same report twice to the same email (unless $force is true) if (!$force && $this->reportAlreadySent($report, $period)) { Log::warning('Preventing the same scheduled report from being sent again (report #%s for period "%s")', $report['idreport'], $prettyDate); return; } $periods = self::getPeriodToFrequencyAsAdjective(); $message = Piwik::translate('ScheduledReports_EmailHello'); $subject = Piwik::translate('General_Report') . ' ' . $reportTitle . " - " . $prettyDate; $mail = new Mail(); $mail->setDefaultFromPiwik(); $mail->setSubject($subject); $attachmentName = $subject; $this->setReplyToAsSender($mail, $report); $displaySegmentInfo = false; $segmentInfo = null; $segment = API::getSegment($report['idsegment']); if ($segment != null) { $displaySegmentInfo = true; $segmentInfo = Piwik::translate('ScheduledReports_SegmentAppliedToReports', $segment['name']); } $messageFindAttached = Piwik::translate('ScheduledReports_PleaseFindAttachedFile', array($periods[$report['period']], $reportTitle)); $messageFindBelow = Piwik::translate('ScheduledReports_PleaseFindBelow', array($periods[$report['period']], $reportTitle)); $messageSentFrom = ''; $piwikUrl = SettingsPiwik::getPiwikUrl(); if (!empty($piwikUrl)) { $messageSentFrom = Piwik::translate('ScheduledReports_SentFromX', $piwikUrl); } switch ($report['format']) { case 'html': // Needed when using images as attachment with cid $mail->setType(Zend_Mime::MULTIPART_RELATED); $message .= "<br/>{$messageFindBelow}<br/>{$messageSentFrom}"; if ($displaySegmentInfo) { $message .= " " . $segmentInfo; } $mail->setBodyHtml($message . "<br/><br/>" . $contents); break; case 'csv': $message .= "\n{$messageFindAttached}\n{$messageSentFrom}"; if ($displaySegmentInfo) { $message .= " " . $segmentInfo; } $mail->setBodyText($message); $mail->createAttachment($contents, 'application/csv', Zend_Mime::DISPOSITION_INLINE, Zend_Mime::ENCODING_BASE64, $attachmentName . '.csv'); break; default: case 'pdf': $message .= "\n{$messageFindAttached}\n{$messageSentFrom}"; if ($displaySegmentInfo) { $message .= " " . $segmentInfo; } $mail->setBodyText($message); $mail->createAttachment($contents, 'application/pdf', Zend_Mime::DISPOSITION_INLINE, Zend_Mime::ENCODING_BASE64, $attachmentName . '.pdf'); break; } foreach ($additionalFiles as $additionalFile) { $fileContent = $additionalFile['content']; $at = $mail->createAttachment($fileContent, $additionalFile['mimeType'], Zend_Mime::DISPOSITION_INLINE, $additionalFile['encoding'], $additionalFile['filename']); $at->id = $additionalFile['cid']; unset($fileContent); } // Get user emails and languages $reportParameters = $report['parameters']; $emails = array(); if (isset($reportParameters[self::ADDITIONAL_EMAILS_PARAMETER])) { $emails = $reportParameters[self::ADDITIONAL_EMAILS_PARAMETER]; } if ($reportParameters[self::EMAIL_ME_PARAMETER] == 1) { if (Piwik::getCurrentUserLogin() == $report['login']) { $emails[] = Piwik::getCurrentUserEmail(); } else { try { $user = APIUsersManager::getInstance()->getUser($report['login']); } catch (Exception $e) { return; } $emails[] = $user['email']; } } if (!$force) { $this->markReportAsSent($report, $period); } foreach ($emails as $email) { if (empty($email)) { continue; } $mail->addTo($email); try { $mail->send(); } catch (Exception $e) { // If running from piwik.php with debug, we ignore the 'email not sent' error $tracker = new Tracker(); if (!$tracker->isDebugModeEnabled()) { throw new Exception("An error occured while sending '{$filename}' " . " to " . implode(', ', $mail->getRecipients()) . ". Error was '" . $e->getMessage() . "'"); } } $mail->clearRecipients(); } }
protected function updateExistingConversion($newGoal, $updateWhere) { $updateParts = $sqlBind = $updateWhereParts = array(); foreach ($newGoal as $name => $value) { $updateParts[] = $name . " = ?"; $sqlBind[] = $value; } foreach ($updateWhere as $name => $value) { $updateWhereParts[] = $name . " = ?"; $sqlBind[] = $value; } $sql = 'UPDATE ' . Common::prefixTable('log_conversion') . "\n\t\t\t\t\tSET " . implode($updateParts, ', ') . "\n\t\t\t\t\t\tWHERE " . implode($updateWhereParts, ' AND '); try { Tracker::getDatabase()->query($sql, $sqlBind); } catch (Exception $e) { Common::printDebug("There was an error while updating the Conversion: " . $e->getMessage()); return false; } return true; }
/** * Print profiling report for the tracker * * @param \Piwik\Db $db Tracker database object (or null) */ public static function displayDbTrackerProfile($db = null) { if (is_null($db)) { $db = Tracker::getDatabase(); } $tableName = Common::prefixTable('log_profiling'); $all = $db->fetchAll('SELECT * FROM ' . $tableName); if ($all === false) { return; } uasort($all, 'self::maxSumMsFirst'); $infoIndexedByQuery = array(); foreach ($all as $infoQuery) { $query = $infoQuery['query']; $count = $infoQuery['count']; $sum_time_ms = $infoQuery['sum_time_ms']; $infoIndexedByQuery[$query] = array('count' => $count, 'sumTimeMs' => $sum_time_ms); } self::getSqlProfilingQueryBreakdownOutput($infoIndexedByQuery); }
/** * This methods tries to see if the visitor has visited the website before. * * We have to split the visitor into one of the category * - Known visitor * - New visitor */ public function recognize() { $this->setIsVisitorKnown(false); $configId = $this->configId; $idVisitor = $this->request->getVisitorId(); $isVisitorIdToLookup = !empty($idVisitor); if ($isVisitorIdToLookup) { $this->visitorInfo['idvisitor'] = $idVisitor; Common::printDebug("Matching visitors with: visitorId=" . bin2hex($this->visitorInfo['idvisitor']) . " OR configId=" . bin2hex($configId)); } else { Common::printDebug("Visitor doesn't have the piwik cookie..."); } $selectCustomVariables = ''; // No custom var were found in the request, so let's copy the previous one in a potential conversion later if (!$this->customVariables) { $maxCustomVariables = CustomVariables::getMaxCustomVariables(); for ($index = 1; $index <= $maxCustomVariables; $index++) { $selectCustomVariables .= ', custom_var_k' . $index . ', custom_var_v' . $index; } } $persistedVisitAttributes = self::getVisitFieldsPersist(); array_unshift($persistedVisitAttributes, 'visit_first_action_time'); array_unshift($persistedVisitAttributes, 'visit_last_action_time'); $persistedVisitAttributes = array_unique($persistedVisitAttributes); $selectFields = implode(", ", $persistedVisitAttributes); $select = "SELECT\n {$selectFields}\n {$selectCustomVariables}\n "; $from = "FROM " . Common::prefixTable('log_visit'); list($timeLookBack, $timeLookAhead) = $this->getWindowLookupThisVisit(); $shouldMatchOneFieldOnly = $this->shouldLookupOneVisitorFieldOnly($isVisitorIdToLookup); // Two use cases: // 1) there is no visitor ID so we try to match only on config_id (heuristics) // Possible causes of no visitor ID: no browser cookie support, direct Tracking API request without visitor ID passed, // importing server access logs with import_logs.py, etc. // In this case we use config_id heuristics to try find the visitor in tahhhe past. There is a risk to assign // this page view to the wrong visitor, but this is better than creating artificial visits. // 2) there is a visitor ID and we trust it (config setting trust_visitors_cookies, OR it was set using &cid= in tracking API), // and in these cases, we force to look up this visitor id $whereCommon = "visit_last_action_time >= ? AND visit_last_action_time <= ? AND idsite = ?"; $bindSql = array($timeLookBack, $timeLookAhead, $this->request->getIdSite()); if ($shouldMatchOneFieldOnly) { if ($isVisitorIdToLookup) { $whereCommon .= ' AND idvisitor = ?'; $bindSql[] = $this->visitorInfo['idvisitor']; } else { $whereCommon .= ' AND config_id = ?'; $bindSql[] = $configId; } $sql = "{$select}\n {$from}\n WHERE " . $whereCommon . "\n ORDER BY visit_last_action_time DESC\n LIMIT 1"; } else { // will use INDEX index_idsite_config_datetime (idsite, config_id, visit_last_action_time) $where = ' AND config_id = ?'; $bindSql[] = $configId; $sqlConfigId = "{$select} ,\n 0 as priority\n {$from}\n WHERE {$whereCommon} {$where}\n ORDER BY visit_last_action_time DESC\n LIMIT 1\n "; // will use INDEX index_idsite_idvisitor (idsite, idvisitor) $bindSql[] = $timeLookBack; $bindSql[] = $timeLookAhead; $bindSql[] = $this->request->getIdSite(); $where = ' AND idvisitor = ?'; $bindSql[] = $this->visitorInfo['idvisitor']; $sqlVisitorId = "{$select} ,\n 1 as priority\n {$from}\n WHERE {$whereCommon} {$where}\n ORDER BY visit_last_action_time DESC\n LIMIT 1\n "; // We join both queries and favor the one matching the visitor_id if it did match $sql = " ( {$sqlConfigId} )\n UNION\n ( {$sqlVisitorId} )\n ORDER BY priority DESC\n LIMIT 1"; } $visitRow = Tracker::getDatabase()->fetch($sql, $bindSql); $isNewVisitForced = $this->request->getParam('new_visit'); $isNewVisitForced = !empty($isNewVisitForced); $newVisitEnforcedAPI = $isNewVisitForced && ($this->request->isAuthenticated() || !Config::getInstance()->Tracker['new_visit_api_requires_admin']); $enforceNewVisit = $newVisitEnforcedAPI || Config::getInstance()->Debug['tracker_always_new_visitor']; if (!$enforceNewVisit && $visitRow && count($visitRow) > 0) { // These values will be used throughout the request foreach ($persistedVisitAttributes as $field) { $this->visitorInfo[$field] = $visitRow[$field]; } $this->visitorInfo['visit_last_action_time'] = strtotime($visitRow['visit_last_action_time']); $this->visitorInfo['visit_first_action_time'] = strtotime($visitRow['visit_first_action_time']); // Custom Variables copied from Visit in potential later conversion if (!empty($selectCustomVariables)) { $maxCustomVariables = CustomVariables::getMaxCustomVariables(); for ($i = 1; $i <= $maxCustomVariables; $i++) { if (isset($visitRow['custom_var_k' . $i]) && strlen($visitRow['custom_var_k' . $i])) { $this->visitorInfo['custom_var_k' . $i] = $visitRow['custom_var_k' . $i]; } if (isset($visitRow['custom_var_v' . $i]) && strlen($visitRow['custom_var_v' . $i])) { $this->visitorInfo['custom_var_v' . $i] = $visitRow['custom_var_v' . $i]; } } } $this->setIsVisitorKnown(true); Common::printDebug("The visitor is known (idvisitor = " . bin2hex($this->visitorInfo['idvisitor']) . ",\n config_id = " . bin2hex($configId) . ",\n idvisit = {$this->visitorInfo['idvisit']},\n last action = " . date("r", $this->visitorInfo['visit_last_action_time']) . ",\n first action = " . date("r", $this->visitorInfo['visit_first_action_time']) . ",\n visit_goal_buyer' = " . $this->visitorInfo['visit_goal_buyer'] . ")"); //Common::printDebug($this->visitorInfo); } else { Common::printDebug("The visitor was not matched with an existing visitor..."); } }
/** * @return array names of plugins that have been loaded */ public function loadTrackerPlugins() { $cache = new PersistentCache('PluginsTracker'); if ($cache->has()) { $pluginsTracker = $cache->get(); } else { $this->unloadPlugins(); $this->loadActivatedPlugins(); $pluginsTracker = array(); foreach ($this->loadedPlugins as $pluginName => $plugin) { if ($this->isTrackerPlugin($plugin)) { $pluginsTracker[] = $pluginName; } } if (!empty($pluginsTracker)) { $cache->set($pluginsTracker); } } $this->unloadPlugins(); if (empty($pluginsTracker)) { return array(); } $pluginsTracker = array_diff($pluginsTracker, Tracker::getPluginsNotToLoad()); $this->doNotLoadAlwaysActivatedPlugins(); $this->loadPlugins($pluginsTracker); return $pluginsTracker; }
private function getGoalFromVisitor(Visitor $visitor, $visitorInformation, $action) { $goal = array('idvisit' => $visitorInformation['idvisit'], 'idvisitor' => $visitorInformation['idvisitor'], 'server_time' => Tracker::getDatetimeFromTimestamp($visitorInformation['visit_last_action_time'])); $visitDimensions = VisitDimension::getAllDimensions(); foreach ($visitDimensions as $dimension) { $value = $dimension->onAnyGoalConversion($this->request, $visitor, $action); if (false !== $value) { $goal[$dimension->getColumnName()] = $value; } } return $goal; }
protected function loadTrackerPlugins(Request $request) { // Adding &dp=1 will disable the provider plugin, if token_auth is used (used to speed up bulk imports) $disableProvider = $request->getParam('dp'); if (!empty($disableProvider)) { Tracker::setPluginsNotToLoad(array('Provider')); } try { $pluginsTracker = \Piwik\Plugin\Manager::getInstance()->loadTrackerPlugins(); Common::printDebug("Loading plugins: { " . implode(", ", $pluginsTracker) . " }"); } catch (Exception $e) { Common::printDebug("ERROR: " . $e->getMessage()); } }
require_once PIWIK_INCLUDE_PATH . '/core/Filesystem.php'; require_once PIWIK_INCLUDE_PATH . '/core/Cookie.php'; session_cache_limiter('nocache'); @date_default_timezone_set('UTC'); if (!defined('PIWIK_ENABLE_TRACKING') || PIWIK_ENABLE_TRACKING) { ob_start(); } if ($GLOBALS['PIWIK_TRACKER_DEBUG'] === true) { require_once PIWIK_INCLUDE_PATH . '/core/Loader.php'; require_once PIWIK_INCLUDE_PATH . '/core/Error.php'; \Piwik\Error::setErrorHandler(); require_once PIWIK_INCLUDE_PATH . '/core/ExceptionHandler.php'; \Piwik\ExceptionHandler::setUp(); $timer = new Timer(); Common::printDebug("Debug enabled - Input parameters: <br/>" . var_export($_GET, true)); \Piwik\Tracker\Db::enableProfiling(); \Piwik\FrontController::createConfigObject(); } if (!defined('PIWIK_ENABLE_TRACKING') || PIWIK_ENABLE_TRACKING) { $process = new Tracker(); try { $process->main(); } catch (Exception $e) { echo "Error:" . $e->getMessage(); } ob_end_flush(); if ($GLOBALS['PIWIK_TRACKER_DEBUG'] === true) { Common::printDebug($_COOKIE); Common::printDebug($timer); } }
<?php /** * Proxy to normal piwik.php, but in testing mode * * - Use the tests database to record Tracking data * - Allows to overwrite the Visitor IP, and Server datetime * */ use Piwik\DataTable\Manager; use Piwik\Option; use Piwik\Plugins\UserCountry\LocationProvider\GeoIp; use Piwik\Site; use Piwik\Tracker\Cache; use Piwik\Tracker; require realpath(dirname(__FILE__)) . "/includes.php"; // Wrapping the request inside ob_start() calls to ensure that the Test // calling us waits for the full request to process before unblocking ob_start(); try { Piwik_TestingEnvironment::addHooks(); GeoIp::$geoIPDatabaseDir = 'tests/lib/geoip-files'; Tracker::setTestEnvironment(); Manager::getInstance()->deleteAll(); Option::clearCache(); Site::clearCache(); include PIWIK_INCLUDE_PATH . '/piwik.php'; } catch (Exception $ex) { echo "Unexpected error during tracking: " . $ex->getMessage() . "\n" . $ex->getTraceAsString() . "\n"; } ob_end_flush();
/** * Returns contents of general (global) cache. * If the cache file tmp/cache/tracker/general.php does not exist yet, create it * * @return array */ public static function getCacheGeneral() { $cache = self::getCache(); $cacheContent = $cache->fetch(self::$cacheIdGeneral); if (false !== $cacheContent) { return $cacheContent; } Tracker::initCorePiwikInTrackerMode(); $cacheContent = array('isBrowserTriggerEnabled' => Rules::isBrowserTriggerEnabled(), 'lastTrackerCronRun' => Option::get('lastTrackerCronRun')); /** * Triggered before the [general tracker cache](/guides/all-about-tracking#the-tracker-cache) * is saved to disk. This event can be used to add extra content to the cache. * * Data that is used during tracking but is expensive to compute/query should be * cached to keep tracking efficient. One example of such data are options * that are stored in the piwik_option table. Querying data for each tracking * request means an extra unnecessary database query for each visitor action. Using * a cache solves this problem. * * **Example** * * public function setTrackerCacheGeneral(&$cacheContent) * { * $cacheContent['MyPlugin.myCacheKey'] = Option::get('MyPlugin_myOption'); * } * * @param array &$cacheContent Array of cached data. Each piece of data must be * mapped by name. */ Piwik::postEvent('Tracker.setTrackerCacheGeneral', array(&$cacheContent)); self::setCacheGeneral($cacheContent); Common::printDebug("General tracker cache was re-created."); Tracker::restoreTrackerPlugins(); return $cacheContent; }