Exemplo n.º 1
0
 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;
 }
Exemplo n.º 2
0
 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();
 }
Exemplo n.º 3
0
 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);
     }
 }
Exemplo n.º 4
0
 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());
 }
Exemplo n.º 5
0
 /**
  * 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;
 }
Exemplo n.º 6
0
 /**
  * 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;
 }
Exemplo n.º 7
0
 /**
  * @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;
 }
Exemplo n.º 8
0
 /**
  * @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;
 }
Exemplo n.º 9
0
 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)));
 }
Exemplo n.º 10
0
 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));
 }
Exemplo n.º 11
0
 /**
  * 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');
 }
Exemplo n.º 12
0
 public function shouldRecordStatistics()
 {
     if (!$this->record) {
         return false;
     }
     return parent::shouldRecordStatistics();
 }
Exemplo n.º 13
0
 private function getDb()
 {
     return Tracker::getDatabase();
 }
Exemplo n.º 14
0
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();
}
Exemplo n.º 15
0
 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());
 }
Exemplo n.º 17
0
 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();
 }
Exemplo n.º 18
0
 /**
  * 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);
 }
Exemplo n.º 19
0
 /**
  * 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;
 }
Exemplo n.º 20
0
 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}.");
     }
 }
Exemplo n.º 21
0
 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();
     }
 }
Exemplo n.º 22
0
 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;
 }
Exemplo n.º 23
0
 /**
  * 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);
 }
Exemplo n.º 24
0
 /**
  * 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...");
     }
 }
Exemplo n.º 25
0
 /**
  * @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;
 }
Exemplo n.º 26
0
 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;
 }
Exemplo n.º 27
0
 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());
     }
 }
Exemplo n.º 28
0
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);
    }
}
Exemplo n.º 29
0
<?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();
Exemplo n.º 30
0
 /**
  * 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;
 }