From d77ce6d0b2ea4e5487699663a6e20cac14cc7400 Mon Sep 17 00:00:00 2001 From: YuCheng Hu Date: Sat, 10 Jul 2010 02:23:15 +0000 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20Piwik=20=E5=88=B0=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E5=BA=93=E4=B8=AD=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit +YUCHENG HU+ git-svn-id: https://svn.code.sf.net/p/hawebs/svn@449 a2543c7e-f6e9-4f8a-8bff-1ffc34733512 --- .../trunk/plugins/VisitFrequency/API.php | 100 +++ .../plugins/VisitFrequency/Controller.php | 78 ++ .../plugins/VisitFrequency/VisitFrequency.php | 102 +++ .../VisitFrequency/templates/index.tpl | 11 + .../VisitFrequency/templates/sparklines.tpl | 11 + .../plugins/VisitorGenerator/Controller.php | 118 +++ .../plugins/VisitorGenerator/Generator.php | 623 ++++++++++++++++ .../plugins/VisitorGenerator/Tracker.php | 53 ++ .../trunk/plugins/VisitorGenerator/Visit.php | 47 ++ .../VisitorGenerator/VisitorGenerator.php | 44 ++ .../VisitorGenerator/data/AcceptLanguage.php | 544 ++++++++++++++ .../VisitorGenerator/data/Referers.php | 702 ++++++++++++++++++ .../VisitorGenerator/data/UserAgent.php | 69 ++ .../VisitorGenerator/templates/generate.tpl | 30 + .../VisitorGenerator/templates/index.tpl | 45 ++ 15 files changed, 2577 insertions(+) create mode 100644 oss/piwik/trunk/plugins/VisitFrequency/API.php create mode 100644 oss/piwik/trunk/plugins/VisitFrequency/Controller.php create mode 100644 oss/piwik/trunk/plugins/VisitFrequency/VisitFrequency.php create mode 100644 oss/piwik/trunk/plugins/VisitFrequency/templates/index.tpl create mode 100644 oss/piwik/trunk/plugins/VisitFrequency/templates/sparklines.tpl create mode 100644 oss/piwik/trunk/plugins/VisitorGenerator/Controller.php create mode 100644 oss/piwik/trunk/plugins/VisitorGenerator/Generator.php create mode 100644 oss/piwik/trunk/plugins/VisitorGenerator/Tracker.php create mode 100644 oss/piwik/trunk/plugins/VisitorGenerator/Visit.php create mode 100644 oss/piwik/trunk/plugins/VisitorGenerator/VisitorGenerator.php create mode 100644 oss/piwik/trunk/plugins/VisitorGenerator/data/AcceptLanguage.php create mode 100644 oss/piwik/trunk/plugins/VisitorGenerator/data/Referers.php create mode 100644 oss/piwik/trunk/plugins/VisitorGenerator/data/UserAgent.php create mode 100644 oss/piwik/trunk/plugins/VisitorGenerator/templates/generate.tpl create mode 100644 oss/piwik/trunk/plugins/VisitorGenerator/templates/index.tpl diff --git a/oss/piwik/trunk/plugins/VisitFrequency/API.php b/oss/piwik/trunk/plugins/VisitFrequency/API.php new file mode 100644 index 00000000..c1906885 --- /dev/null +++ b/oss/piwik/trunk/plugins/VisitFrequency/API.php @@ -0,0 +1,100 @@ +getDataTableFromNumeric($toFetch); + if($bounceRateReturningRequested !== false) + { + $dataTable->filter('ColumnCallbackAddColumnPercentage', array('bounce_rate_returning', 'bounce_count_returning', 'nb_visits_returning', 0)); + $dataTable->deleteColumns($toFetch); + } + return $dataTable; + } + + protected function getNumeric( $idSite, $period, $date, $toFetch ) + { + Piwik::checkUserHasViewAccess( $idSite ); + $archive = Piwik_Archive::build($idSite, $period, $date ); + $dataTable = $archive->getNumeric($toFetch); + return $dataTable; + } + + public function getVisitsReturning( $idSite, $period, $date ) + { + return $this->getNumeric( $idSite, $period, $date, 'nb_visits_returning'); + } + + public function getActionsReturning( $idSite, $period, $date ) + { + return $this->getNumeric( $idSite, $period, $date, 'nb_actions_returning'); + } + + public function getMaxActionsReturning( $idSite, $period, $date ) + { + return $this->getNumeric( $idSite, $period, $date, 'max_actions_returning'); + } + + public function getSumVisitsLengthReturning( $idSite, $period, $date ) + { + return $this->getNumeric( $idSite, $period, $date, 'sum_visit_length_returning'); + } + + public function getBounceCountReturning( $idSite, $period, $date ) + { + return $this->getNumeric( $idSite, $period, $date, 'bounce_count_returning'); + } + + public function getConvertedVisitsReturning( $idSite, $period, $date ) + { + return $this->getNumeric( $idSite, $period, $date, 'nb_visits_converted_returning'); + } +} diff --git a/oss/piwik/trunk/plugins/VisitFrequency/Controller.php b/oss/piwik/trunk/plugins/VisitFrequency/Controller.php new file mode 100644 index 00000000..48c9f2e5 --- /dev/null +++ b/oss/piwik/trunk/plugins/VisitFrequency/Controller.php @@ -0,0 +1,78 @@ +graphEvolutionVisitFrequency = $this->getEvolutionGraph(true, array('nb_visits_returning') ); + $this->setSparklinesAndNumbers($view); + echo $view->render(); + } + + public function getSparklines() + { + $view = Piwik_View::factory('sparklines'); + $this->setSparklinesAndNumbers($view); + echo $view->render(); + } + + public function getEvolutionGraph( $fetch = false, $columns = false) + { + $view = $this->getLastUnitGraph($this->pluginName, __FUNCTION__, "VisitFrequency.get"); + if(empty($columns)) + { + $columns = Piwik_Common::getRequestVar('columns'); + } + $view->setColumnsToDisplay($columns); + $view->setColumnsTranslations(array( + 'nb_visits_returning' => Piwik_Translate('VisitFrequency_ColumnReturningVisits'), + 'nb_actions_returning' => Piwik_Translate('VisitFrequency_ColumnActionsByReturningVisits'), + 'max_actions_returning' => Piwik_Translate('VisitFrequency_ColumnMaximumActionsByAReturningVisit'), + 'sum_visit_length_returning' => Piwik_Translate('VisitFrequency_ColumnTotalTimeSpentByReturningVisits'), + 'bounce_rate_returning' => Piwik_Translate('VisitFrequency_ColumnBounceRateForReturningVisits'), + )); + return $this->renderView($view, $fetch); + } + + protected function setSparklinesAndNumbers($view) + { + $view->urlSparklineNbVisitsReturning = $this->getUrlSparkline( 'getEvolutionGraph', array('columns' => array('nb_visits_returning'))); + $view->urlSparklineNbActionsReturning = $this->getUrlSparkline( 'getEvolutionGraph', array('columns' => array('nb_actions_returning'))); + $view->urlSparklineMaxActionsReturning = $this->getUrlSparkline( 'getEvolutionGraph', array('columns' => array('max_actions_returning'))); + $view->urlSparklineSumVisitLengthReturning = $this->getUrlSparkline( 'getEvolutionGraph', array('columns' => array('sum_visit_length_returning'))); + $view->urlSparklineBounceRateReturning = $this->getUrlSparkline( 'getEvolutionGraph', array('columns' => array('bounce_rate_returning'))); + + $dataTableFrequency = $this->getSummary(); + $dataRow = $dataTableFrequency->getFirstRow(); + $nbVisitsReturning = $dataRow->getColumn('nb_visits_returning'); + $view->nbVisitsReturning = $nbVisitsReturning; + $view->nbActionsReturning = $dataRow->getColumn('nb_actions_returning'); + $view->maxActionsReturning = $dataRow->getColumn('max_actions_returning'); + $view->sumVisitLengthReturning = $dataRow->getColumn('sum_visit_length_returning'); + $nbBouncedReturningVisits = $dataRow->getColumn('bounce_count_returning'); + $view->bounceRateReturning = Piwik::getPercentageSafe($nbBouncedReturningVisits, $nbVisitsReturning); + + } + + protected function getSummary() + { + $requestString = "method=VisitFrequency.get&format=original"; + $request = new Piwik_API_Request($requestString); + return $request->process(); + } +} diff --git a/oss/piwik/trunk/plugins/VisitFrequency/VisitFrequency.php b/oss/piwik/trunk/plugins/VisitFrequency/VisitFrequency.php new file mode 100644 index 00000000..8873a417 --- /dev/null +++ b/oss/piwik/trunk/plugins/VisitFrequency/VisitFrequency.php @@ -0,0 +1,102 @@ + Piwik_Translate('VisitFrequency_PluginDescription'), + 'author' => 'Piwik', + 'author_homepage' => 'http://piwik.org/', + 'version' => Piwik_Version::VERSION, + ); + return $info; + } + + function getListHooksRegistered() + { + $hooks = array( + 'ArchiveProcessing_Day.compute' => 'archiveDay', + 'ArchiveProcessing_Period.compute' => 'archivePeriod', + 'WidgetsList.add' => 'addWidgets', + 'Menu.add' => 'addMenu', + ); + return $hooks; + } + + function addWidgets() + { + Piwik_AddWidget( 'General_Visitors', 'VisitFrequency_WidgetOverview', 'VisitFrequency', 'getSparklines'); + Piwik_AddWidget( 'General_Visitors', 'VisitFrequency_WidgetGraphReturning', 'VisitFrequency', 'getEvolutionGraph', array('columns' => array('nb_visits_returning'))); + } + + function addMenu() + { + Piwik_AddMenu('General_Visitors', 'VisitFrequency_SubmenuFrequency', array('module' => 'VisitFrequency', 'action' => 'index')); + } + + function archivePeriod( $notification ) + { + $archiveProcessing = $notification->getNotificationObject(); + + $numericToSum = array( + 'nb_visits_returning', + 'nb_actions_returning', + 'sum_visit_length_returning', + 'bounce_count_returning', + 'nb_visits_converted_returning', + ); + $archiveProcessing->archiveNumericValuesSum($numericToSum); + $archiveProcessing->archiveNumericValuesMax('max_actions_returning'); + } + + function archiveDay($notification) + { + /* @var $archiveProcessing Piwik_ArchiveProcessing */ + $archiveProcessing = $notification->getNotificationObject(); + + $query = "SELECT count(distinct visitor_idcookie) as nb_uniq_visitors_returning, + count(*) as nb_visits_returning, + sum(visit_total_actions) as nb_actions_returning, + max(visit_total_actions) as max_actions_returning, + sum(visit_total_time) as sum_visit_length_returning, + sum(case visit_total_actions when 1 then 1 else 0 end) as bounce_count_returning, + sum(case visit_goal_converted when 1 then 1 else 0 end) as nb_visits_converted_returning + FROM ".$archiveProcessing->logTable." + WHERE visit_last_action_time >= ? + AND visit_last_action_time <= ? + AND idsite = ? + AND visitor_returning = 1"; + $row = $archiveProcessing->db->fetchRow($query, array( $archiveProcessing->getStartDatetimeUTC(), $archiveProcessing->getEndDatetimeUTC(), $archiveProcessing->idsite ) ); + + if($row === false || $row === null) + { + $row['nb_visits_returning'] = 0; + $row['nb_actions_returning'] = 0; + $row['max_actions_returning'] = 0; + $row['sum_visit_length_returning'] = 0; + $row['bounce_count_returning'] = 0; + $row['nb_visits_converted_returning'] = 0; + } + + foreach($row as $name => $value) + { + $archiveProcessing->insertNumericRecord($name, $value); + } + } +} + diff --git a/oss/piwik/trunk/plugins/VisitFrequency/templates/index.tpl b/oss/piwik/trunk/plugins/VisitFrequency/templates/index.tpl new file mode 100644 index 00000000..1d7e4831 --- /dev/null +++ b/oss/piwik/trunk/plugins/VisitFrequency/templates/index.tpl @@ -0,0 +1,11 @@ +{postEvent name="template_headerVisitsFrequency"} + + + +

{'VisitFrequency_ColumnReturningVisits'|translate}

+{$graphEvolutionVisitFrequency} +
+ +{include file=VisitFrequency/templates/sparklines.tpl} + +{postEvent name="template_footerVisitsFrequency"} diff --git a/oss/piwik/trunk/plugins/VisitFrequency/templates/sparklines.tpl b/oss/piwik/trunk/plugins/VisitFrequency/templates/sparklines.tpl new file mode 100644 index 00000000..a72ae2eb --- /dev/null +++ b/oss/piwik/trunk/plugins/VisitFrequency/templates/sparklines.tpl @@ -0,0 +1,11 @@ +
{sparkline src=$urlSparklineNbVisitsReturning} +{'VisitFrequency_ReturnVisits'|translate:"$nbVisitsReturning"}
+
{sparkline src=$urlSparklineNbActionsReturning} +{'VisitFrequency_ReturnActions'|translate:"$nbActionsReturning"}
+
{sparkline src=$urlSparklineMaxActionsReturning} + {'VisitFrequency_ReturnMaxActions'|translate:"$maxActionsReturning"}
+
{sparkline src=$urlSparklineSumVisitLengthReturning} + {assign var=sumtimeVisitLengthReturning value=$sumVisitLengthReturning|sumtime} + {'VisitFrequency_ReturnTotalTime'|translate:"$sumtimeVisitLengthReturning"}
+
{sparkline src=$urlSparklineBounceRateReturning} + {'VisitFrequency_ReturnBounceRate'|translate:"$bounceRateReturning%"}
\ No newline at end of file diff --git a/oss/piwik/trunk/plugins/VisitorGenerator/Controller.php b/oss/piwik/trunk/plugins/VisitorGenerator/Controller.php new file mode 100644 index 00000000..c20089e0 --- /dev/null +++ b/oss/piwik/trunk/plugins/VisitorGenerator/Controller.php @@ -0,0 +1,118 @@ +getSitesWithAdminAccess(); + + $view = Piwik_View::factory('index'); + $this->setGeneralVariablesView($view); + $view->assign('sitesList', $sitesList); + + $view->menu = Piwik_GetAdminMenu(); + echo $view->render(); + } + + public function generate() { + // Only admin is allowed to do this! + Piwik::checkUserIsSuperUser(); + $this->checkTokenInUrl(); + + $GET = $_GET; + $POST = $_POST; + $COOKIE = $_COOKIE; + $REQUEST = $_REQUEST; + + if(Piwik_Common::getRequestVar('choice', 'no') != 'yes') { + Piwik::redirectToModule('VisitorGenerator', 'index'); + } + + $minVisitors = Piwik_Common::getRequestVar('minVisitors', 20, 'int'); + $maxVisitors = Piwik_Common::getRequestVar('maxVisitors', 100, 'int'); + $nbActions = Piwik_Common::getRequestVar('nbActions', 10, 'int'); + $daysToCompute = Piwik_Common::getRequestVar('daysToCompute', 1, 'int'); + $idSite = Piwik_Common::getRequestVar('idSite'); + Piwik::setMaxExecutionTime(0); + + $loadedPlugins = Piwik_PluginsManager::getInstance()->getLoadedPlugins(); + $loadedPlugins = array_keys($loadedPlugins); + // we have to unload the Provider plugin otherwise it tries to lookup the IP for a hostname, and there is no dns server here + if(Piwik_PluginsManager::getInstance()->isPluginActivated('Provider')) { + Piwik_PluginsManager::getInstance()->unloadPlugin('Provider'); + } + + // we set the DO NOT load plugins so that the Tracker generator doesn't load the plugins we've just disabled. + // if for some reasons you want to load the plugins, comment this line, and disable the plugin Provider in the plugins interface + Piwik_PluginsManager::getInstance()->doNotLoadPlugins(); + + $generator = new Piwik_VisitorGenerator_Generator(); + $generator->setMaximumUrlDepth(3); + + //$generator->disableProfiler(); + $generator->setIdSite( $idSite ); + + $nbActionsTotal = 0; + //$generator->emptyAllLogTables(); + $generator->init(); + + $timer = new Piwik_Timer; + + $startTime = time() - ($daysToCompute-1)*86400; + $dates = array(); + while($startTime <= time()) { + $visitors = rand($minVisitors, $maxVisitors); + $actions = $nbActions; + $generator->setTimestampToUse($startTime); + + $nbActionsTotalThisDay = $generator->generate($visitors, $actions); + $actionsPerVisit = round($nbActionsTotalThisDay / $visitors); + + $date = array(); + $date['visitors'] = $visitors; + $date['actionsPerVisit'] = $actionsPerVisit; + $date['startTime'] = $startTime; + $dates[] = $date; + + $startTime += 86400; + $nbActionsTotal += $nbActionsTotalThisDay; + //sleep(1); + } + + $generator->end(); + + // Recover all super globals + $_GET = $GET; + $_POST = $POST; + $_COOKIE = $COOKIE; + $_REQUEST = $REQUEST; + + // Reload plugins + Piwik_PluginsManager::getInstance()->loadPlugins($loadedPlugins); + + // Init view + $view = Piwik_View::factory('generate'); + $view->menu = Piwik_GetAdminMenu(); + $this->setGeneralVariablesView($view); + $view->assign('dates', $dates); + $view->assign('timer', $timer); + $view->assign('nbActionsTotal', $nbActionsTotal); + $view->assign('nbRequestsPerSec', round($nbActionsTotal / $timer->getTime(),0)); + echo $view->render(); + } +} diff --git a/oss/piwik/trunk/plugins/VisitorGenerator/Generator.php b/oss/piwik/trunk/plugins/VisitorGenerator/Generator.php new file mode 100644 index 00000000..9017199b --- /dev/null +++ b/oss/piwik/trunk/plugins/VisitorGenerator/Generator.php @@ -0,0 +1,623 @@ + campaigns + * - campaign CPC + * - referer + * - search engine + * - misc site + * - same website + * - url => multiple directories, page names + * - multiple idsite + * - multiple settings configurations + * - action_name + * - HTML title + * + * @package Piwik_VisitorGenerator + * + * "Le Generator, il est trop Fort!" + * - Random fan + */ +class Piwik_VisitorGenerator_Generator +{ + /** + * GET parameters array of values to be used for the current visit + * + * @var array ('res' => '1024x768', 'urlref' => 'http://google.com/search?q=piwik', ...) + */ + protected $currentget = array(); + + /** + * Array of all the potential values for the visit parameters + * Values of 'resolution', 'urlref', etc. will be randomly read from this array + * + * @var array ( + * 'res' => array('1024x768','800x600'), + * 'urlref' => array('google.com','intel.com','amazon.com'), + * ....) + */ + protected $allget = array(); + + /** + * See @see setMaximumUrlDepth + * + * @var int + */ + protected $maximumUrlDepth = 1; + + /** + * Unix timestamp to use for the generated visitor + * + * @var int Unix timestamp + */ + protected $timestampToUse; + + /** + * See @see disableProfiler() + * The profiler is enabled by default + * + * @var bool + */ + protected $profiling = true; + + /** + * If set to true, this will TRUNCATE the profiling tables at every new generated visit + * @see initProfiler() + * + * @var bool + */ + public $reinitProfilingAtEveryRequest = true; + + /** + * Hostname used to prefix all the generated URLs + * we could make this variable dynamic so that a visitor can make hit on several hosts and + * only the good ones should be kept (feature not yet implemented in piwik) + * + * @var string + */ + public $host = 'http://localhost'; + + /** + * IdSite to generate visits for (@see setIdSite()) + * + * @var int + */ + public $idSite = 1; + + /** + * Overwrite the global GET/POST/COOKIE variables and set the fake ones @see setFakeRequest() + * Reads the configuration file but disables write to this file + * Creates the database object & enable profiling by default (@see disableProfiler()) + * + */ + public function __construct() + { + $_COOKIE = $_GET = $_POST = array(); + + // init GET and REQUEST to the empty array + $this->setFakeRequest(); + + Piwik::createConfigObject(PIWIK_USER_PATH . '/config/config.ini.php'); + Zend_Registry::get('config')->disableSavingConfigurationFileUpdates(); + + // setup database + Piwik::createDatabaseObject(); + + Piwik_Tracker_Db::enableProfiling(); + + $this->timestampToUse = time(); + } + + /** + * Sets the depth level of the generated URLs + * value = 1 => path OR path/page1 + * value = 2 => path OR path/pageRand OR path/dir1/pageRand + * + * @param int Depth + */ + public function setMaximumUrlDepth($value) + { + $this->maximumUrlDepth = (int)$value; + } + + /** + * Set the timestamp to use as the starting time for the visitors times + * You have to call this method for every day you want to generate data + * + * @param int Unix timestamp + */ + public function setTimestampToUse($timestamp) + { + $this->timestampToUse = $timestamp; + } + + /** + * Returns the timestamp to be used as the visitor timestamp + * + * @return int Unix timestamp + */ + public function getTimestampToUse() + { + return $this->timestampToUse; + } + + /** + * Set the idsite to generate the visits for + * To be called before init() + * + * @param int idSite + */ + public function setIdSite($idSite) + { + $this->idSite = $idSite; + } + + /** + * Add a value to the GET global array. + * The generator script will then randomly read a value from this array. + * + * For example, $name = 'res' $aValue = '1024x768' + * + * @param string Name of the parameter _GET[$name] + * @param array|mixed Value of the parameter + */ + protected function addParam( $name, $aValue) + { + if(is_array($aValue)) + { + $this->allget[$name] = array_merge( $aValue, + (array)@$this->allget[$name]); + } + else + { + $this->allget[$name][] = $aValue; + } + } + + /** + * TRUNCATE all logs related tables to start a fresh logging database. + * Be careful, any data deleted this way is deleted forever + */ + public function emptyAllLogTables() + { + $db = Zend_Registry::get('db'); + $db->query('TRUNCATE TABLE '.Piwik_Common::prefixTable('log_action')); + $db->query('TRUNCATE TABLE '.Piwik_Common::prefixTable('log_visit')); + $db->query('TRUNCATE TABLE '.Piwik_Common::prefixTable('log_link_visit_action')); + } + + /** + * Call this method to disable the SQL query profiler + */ + public function disableProfiler() + { + $this->profiling = false; + Piwik_Tracker_Db::disableProfiling(); + } + + /** + * This is called at the end of the Generator script. + * Calls the Profiler output if the profiler is enabled. + */ + public function end() + { + if($this->profiling) + { + Piwik::printSqlProfilingReportTracker(); + } + Piwik_Tracker::disconnectDatabase(); + } + + /** + * Init the Generator script: + * - init the SQL profiler + * - init the random generator + * - setup the different possible values for parameters such as 'resolution', + * 'color', 'hour', 'minute', etc. + * - load from DataFiles and setup values for the other parameters such as UserAgent, Referers, AcceptedLanguages, etc. + * @see misc/generateVisitsData/ + */ + public function init() + { + Piwik::createLogObject(); + + $this->initProfiler(); + + /* + * Init the random number generator + */ + function make_seed() + { + list($usec, $sec) = explode(' ', microtime()); + return (float) $sec + ((float) $usec * 100000); + } + mt_srand(make_seed()); + + // set rec=1 parameter, required as of 0.5.5 in order to force the request to be recorded + $this->setCurrentRequest('rec', 1); + + /* + * Sets values for: resolutions, colors, idSite, times + */ + $common = array( + 'res' => array('1289x800','1024x768','800x600','564x644','200x100','50x2000',), + 'col' => array(24,32,16), + 'idsite'=> $this->idSite, + 'h' => range(0,23), + 'm' => range(0,59), + 's' => range(0,59), + ); + + foreach($common as $label => $values) + { + $this->addParam($label,$values); + } + + /* + * Sets values for: outlinks, downloads, campaigns + */ + // we get the name of the Download/outlink variables + $downloadOrOutlink = array('download', 'link'); + + // we have a 20% chance to add a download or outlink variable to the URL + $this->addParam('piwik_downloadOrOutlink', $downloadOrOutlink); + $this->addParam('piwik_downloadOrOutlink', array_fill(0,8,'')); + + // we get the variables name for the campaign parameters + $campaigns = array( + Piwik_Tracker_Config::getInstance()->Tracker['campaign_var_name'] + ); + // we generate a campaign in the URL in 3/18 % of the generated URls + $this->addParam('piwik_vars_campaign', $campaigns); + $this->addParam('piwik_vars_campaign', array_fill(0,15,'')); + + + /* + * Sets values for: Referers, user agents, accepted languages + */ + // we load some real referers to be used by the generator + $referers = array(); + require_once PIWIK_INCLUDE_PATH . '/plugins/VisitorGenerator/data/Referers.php'; + + $this->addParam('urlref',$referers); + + // and we add 2000 empty referers so that some visitors don't come using a referer (direct entry) + $this->addParam('urlref',array_fill(0,2000,'')); + + // load some user agent and accept language + $userAgent = $acceptLanguages = array(); + require_once PIWIK_INCLUDE_PATH . '/plugins/VisitorGenerator/data/UserAgent.php'; + require_once PIWIK_INCLUDE_PATH . '/plugins/VisitorGenerator/data/AcceptLanguage.php'; + $this->userAgents=$userAgent; + $this->acceptLanguage=$acceptLanguages; + } + + /** + * If the SQL profiler is enabled and if the reinit at every request is set to true, + * then we TRUNCATE the profiling information so that we only profile one visitor at a time + */ + protected function initProfiler() + { + /* + * Inits the profiler + */ + if($this->profiling) + { + if($this->reinitProfilingAtEveryRequest) + { + $all = Piwik_Query('TRUNCATE TABLE '.Piwik_Common::prefixTable('log_profiling').'' ); + } + } + } + /** + * Launches the process and generates an exact number of nbVisitors + * For each visit, we setup the timestamp to the common timestamp + * Then we generate between 1 and nbActionsMaxPerVisit actions for this visit + * The generated actions will have a growing timestamp so it looks like a real visit + * + * @param int The number of visits to generate + * @param int The maximum number of actions to generate per visit + * + * @return int The number of total actions generated + */ + public function generate( $nbVisitors, $nbActionsMaxPerVisit ) + { + $nbActionsTotal = 0; + for($i = 0; $i < $nbVisitors; $i++) + { + $nbActions = mt_rand(1, $nbActionsMaxPerVisit); + Piwik_VisitorGenerator_Visit::setTimestampToUse($this->getTimestampToUse()); + + $this->generateNewVisit(); + for($j = 1; $j <= $nbActions; $j++) + { + $this->generateActionVisit(); + $this->saveVisit(); + } + $nbActionsTotal += $nbActions; + } + return $nbActionsTotal; + } + + /** + * Generates a new visitor. + * Loads random values for all the necessary parameters (resolution, local time, referers, etc.) from the fake GET array. + * Also generates a random IP. + * + * We change the superglobal values of HTTP_USER_AGENT, HTTP_CLIENT_IP, HTTP_ACCEPT_LANGUAGE to the generated value. + */ + protected function generateNewVisit() + { + $this->setCurrentRequest( 'urlref' , $this->getRandom('urlref')); + $this->setCurrentRequest( 'idsite', $this->getRandom('idsite')); + $this->setCurrentRequest( 'res' ,$this->getRandom('res')); + $this->setCurrentRequest( 'col' ,$this->getRandom('col')); + $this->setCurrentRequest( 'h' ,$this->getRandom('h')); + $this->setCurrentRequest( 'm' ,$this->getRandom('m')); + $this->setCurrentRequest( 's' ,$this->getRandom('s')); + $this->setCurrentRequest( 'fla' ,$this->getRandom01()); + $this->setCurrentRequest( 'java' ,$this->getRandom01()); + $this->setCurrentRequest( 'dir' ,$this->getRandom01()); + $this->setCurrentRequest( 'qt' ,$this->getRandom01()); + $this->setCurrentRequest( 'realp' ,$this->getRandom01()); + $this->setCurrentRequest( 'pdf' ,$this->getRandom01()); + $this->setCurrentRequest( 'wma' ,$this->getRandom01()); + $this->setCurrentRequest( 'gears' ,$this->getRandom01()); + $this->setCurrentRequest( 'ag' ,$this->getRandom01()); + $this->setCurrentRequest( 'cookie',$this->getRandom01()); + + $_SERVER['HTTP_CLIENT_IP'] = mt_rand(0,255).".".mt_rand(0,255).".".mt_rand(0,255).".".mt_rand(0,255); + $_SERVER['HTTP_USER_AGENT'] = $this->userAgents[mt_rand(0,count($this->userAgents)-1)]; + $_SERVER['HTTP_ACCEPT_LANGUAGE'] = $this->acceptLanguage[mt_rand(0,count($this->acceptLanguage)-1)]; + } + + /** + * Generates a new action for the current visitor. + * We random generate some campaigns, action names, download or outlink clicks, etc. + * We generate a new Referer, that would be read in the case the visit last page is older than 30 minutes. + * + * This function tries to generate actions that use the features of Piwik (campaigns, downloads, outlinks, action_name set in the JS tag, etc.) + */ + protected function generateActionVisit() + { + // we don't keep the previous action values + // reinit them to empty string + $this->setCurrentRequest( 'download', ''); + $this->setCurrentRequest( 'link', ''); + $this->setCurrentRequest( 'action_name', ''); + + // generate new url referer ; case the visitor stays more than 30min + // (when the visit is known this value will simply be ignored) + $this->setCurrentRequest( 'urlref' , $this->getRandom('urlref')); + + // generates the current URL + $url = $this->getRandomUrlFromHost($this->host); + + // we generate a campaign + $urlVars = $this->getRandom('piwik_vars_campaign'); + + // if we actually generated a campaign + if(!empty($urlVars)) + { + // campaign name + $urlValue = $this->getRandomString(5,3,'lower'); + + // add the parameter to the url + $url .= '?'. $urlVars . '=' . $urlValue; + + // for a campaign of the CPC kind, we sometimes generate a keyword + if($urlVars == Piwik_Tracker_Config::getInstance()->Tracker['campaign_var_name'] + && mt_rand(0,1)==0) + { + $url .= '&'. Piwik_Tracker_Config::getInstance()->Tracker['campaign_keyword_var_name'] + . '=' . $this->getRandomString(6,3,'ALL');; + } + } + else + { + // we generate a download Or Outlink parameter in the GET request so that + // the current action is counted as a download action OR a outlink click action + $GETParamToAdd = $this->getRandom('piwik_downloadOrOutlink'); + if(!empty($GETParamToAdd)) + { + + $possibleDownloadHosts = array('http://piwik.org/',$this->host); + $nameDownload = $this->getRandomUrlFromHost($possibleDownloadHosts[mt_rand(0,1)]); + $extensions = array('.zip','.tar.gz'); + $nameDownload .= $extensions[mt_rand(0,1)]; + $urlValue = $nameDownload; + + // add the parameter to the url + $this->setCurrentRequest( $GETParamToAdd , $urlValue); + } + } + + $this->setCurrentRequest( 'url' ,$url); + + // setup the title of the page + $this->setCurrentRequest( 'action_name',$this->getRandomString(15,5)); + } + + /** + * Returns a random URL using the $host as the URL host. + * Depth level depends on @see setMaximumUrlDepth() + * + * @param string Hostname of the URL to generate, eg. http://example.com/ + * + * @return string The generated URL + */ + protected function getRandomUrlFromHost( $host ) + { + $url = $host; + + $deep = mt_rand(0,$this->maximumUrlDepth); + for($i=0;$i<$deep;$i++) + { + $name = $this->getRandomString(1,1,'alnum'); + + $url .= '/'.$name; + } + return $url; + } + + /** + * Generates a random string from minLength to maxLength using a specified set of characters + * + * Taken from php.net and then badly hacked by some unknown monkey + * + * @param int (optional) Maximum length of the string to generate + * @param int (optional) Minimum length of the string to generate + * @param string (optional) Characters set to use, 'ALL' or 'lower' or 'upper' or 'numeric' or 'ALPHA' or 'ALNUM' + * + * @return string The generated random string + */ + protected function getRandomString($maxLength = 15, $minLength = 5, $type = 'ALL') + { + $len = mt_rand($minLength, $maxLength); + + // Register the lower case alphabet array + $alpha = array('a', 'd', 'e', 'f', 'g'); + + // Register the upper case alphabet array + $ALPHA = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'); + + // Register the numeric array + $num = array('1', '2', '3', '8', '9', '0'); + + // Register the strange array + $strange = array('/', '?', '!','"','£','$','%','^','&','*','(',')',' '); + + // Initialize the keyVals array for use in the for loop + $keyVals = array(); + + // Initialize the key array to register each char + $key = array(); + + // Loop through the choices and register + // The choice to keyVals array + switch ($type) + { + case 'lower' : + $keyVals = $alpha; + break; + case 'upper' : + $keyVals = $ALPHA; + break; + case 'numeric' : + $keyVals = $num; + break; + case 'ALPHA' : + $keyVals = array_merge($alpha, $ALPHA); + break; + case 'alnum' : + $keyVals = array_merge($alpha, $num); + break; + case 'ALNUM' : + $keyVals = array_merge($alpha, $ALPHA, $num); + break; + case 'ALL' : + $keyVals = array_merge($alpha, $ALPHA, $num, $strange); + break; + } + + // Loop as many times as specified + // Register each value to the key array + for($i = 0; $i <= $len-1; $i++) + { + $r = mt_rand(0,count($keyVals)-1); + $key[$i] = $keyVals[$r]; + } + + // Glue the key array into a string and return it + return join("", $key); + } + + /** + * Sets the _GET and _REQUEST superglobal to the current generated array of values. + * @see setCurrentRequest() + * This method is called once the current action parameters array has been generated from + * the global parameters array + */ + protected function setFakeRequest() + { + $_GET = $this->currentget; + } + + /** + * Sets a value in the current action request array. + * + * @param string Name of the parameter to set + * @param string Value of the parameter + */ + protected function setCurrentRequest($name,$value) + { + $this->currentget[$name] = $value; + } + + /** + * Returns a value for the given parameter $name read randomly from the global parameter array. + * @see init() + * + * @param string Name of the parameter value to randomly load and return + * @return mixed Random value for the parameter named $name + * @throws Exception if the parameter asked for has never been set + * + */ + protected function getRandom( $name ) + { + if(!isset($this->allget[$name])) + { + throw new exception("You are asking for $name which doesnt exist"); + } + else + { + $index = mt_rand(0,count($this->allget[$name])-1); + $value =$this->allget[$name][$index]; + return $value; + } + } + + /** + * Returns either 0 or 1 + * + * @return int 0 or 1 + */ + protected function getRandom01() + { + return mt_rand(0,1); + } + + /** + * Saves the visit + * - replaces GET and REQUEST by the fake generated request + * - load the Tracker class and call the method to launch the recording + * + * This will save the visit in the database + */ + protected function saveVisit() + { + $this->setFakeRequest(); + $process = new Piwik_VisitorGenerator_Tracker(); + $process->main(); + unset($process); + } +} diff --git a/oss/piwik/trunk/plugins/VisitorGenerator/Tracker.php b/oss/piwik/trunk/plugins/VisitorGenerator/Tracker.php new file mode 100644 index 00000000..c70fde4d --- /dev/null +++ b/oss/piwik/trunk/plugins/VisitorGenerator/Tracker.php @@ -0,0 +1,53 @@ +generateTimestamp(); + return $visit; + } + + static function disconnectDatabase() + { + return; + } +} diff --git a/oss/piwik/trunk/plugins/VisitorGenerator/Visit.php b/oss/piwik/trunk/plugins/VisitorGenerator/Visit.php new file mode 100644 index 00000000..0ecc1b7b --- /dev/null +++ b/oss/piwik/trunk/plugins/VisitorGenerator/Visit.php @@ -0,0 +1,47 @@ +getCurrentTimestamp() ); + } + + protected function getCurrentTimestamp() + { + return self::$timestampToUse; + } + + public function generateTimestamp() + { + self::$timestampToUse = max(@$this->visitorInfo['visit_last_action_time'],self::$timestampToUse); + self::$timestampToUse += mt_rand(4,1840); + } + + protected function updateCookie() + { + @parent::updateCookie(); + } +} diff --git a/oss/piwik/trunk/plugins/VisitorGenerator/VisitorGenerator.php b/oss/piwik/trunk/plugins/VisitorGenerator/VisitorGenerator.php new file mode 100644 index 00000000..d4ae66af --- /dev/null +++ b/oss/piwik/trunk/plugins/VisitorGenerator/VisitorGenerator.php @@ -0,0 +1,44 @@ + Piwik_Translate('VisitorGenerator_PluginDescription'), + 'author' => 'Piwik', + 'author_homepage' => 'http://piwik.org/', + 'version' => Piwik_Version::VERSION, + ); + return $info; + } + + public function getListHooksRegistered() { + return array( + 'AdminMenu.add' => 'addMenu', + ); + } + + public function addMenu() { + Piwik_AddAdminMenu( + 'VisitorGenerator_VisitorGenerator', + array('module' => 'VisitorGenerator', 'action' => 'index'), + Piwik::isUserIsSuperUser(), + $order = 10 + ); + } +} +?> diff --git a/oss/piwik/trunk/plugins/VisitorGenerator/data/AcceptLanguage.php b/oss/piwik/trunk/plugins/VisitorGenerator/data/AcceptLanguage.php new file mode 100644 index 00000000..c6801720 --- /dev/null +++ b/oss/piwik/trunk/plugins/VisitorGenerator/data/AcceptLanguage.php @@ -0,0 +1,544 @@ +{'VisitorGenerator_VisitorGenerator'|translate} + + + + + + + + + + +{foreach from=$dates item=date} + + + + + +{/foreach} + +
{'VisitorGenerator_Visitors'|translate}{'VisitorGenerator_ActionsPerVisit'|translate}{'VisitorGenerator_Date'|translate}
{$date.visitors}{$date.actionsPerVisit}{$date.startTime|date_format:"%Y-%m-%d"}
+ +

{'VisitorGenerator_NbActions'|translate}: {$nbActionsTotal}
+{'VisitorGenerator_NbRequestsPerSec'|translate}: {$nbRequestsPerSec}
+{$timer}

+ +{include file="CoreAdminHome/templates/footer.tpl"} \ No newline at end of file diff --git a/oss/piwik/trunk/plugins/VisitorGenerator/templates/index.tpl b/oss/piwik/trunk/plugins/VisitorGenerator/templates/index.tpl new file mode 100644 index 00000000..f54349b4 --- /dev/null +++ b/oss/piwik/trunk/plugins/VisitorGenerator/templates/index.tpl @@ -0,0 +1,45 @@ +{assign var=showSitesSelection value=false} +{assign var=showPeriodSelection value=false} +{include file="CoreAdminHome/templates/header.tpl"} + +

{'VisitorGenerator_VisitorGenerator'|translate}

+

{'VisitorGenerator_PluginDescription'|translate}

+ +
+ + + + + + + + + + + + + + + + + + + + + +
+

{'VisitorGenerator_Warning'|translate}
+{'VisitorGenerator_NotReversible'|translate:'':''}

+{'VisitorGenerator_AreYouSure'|translate}
+

+ +
+ + +
+ +{include file="CoreAdminHome/templates/footer.tpl"} \ No newline at end of file