添加 Piwik 到代码库中。
+YUCHENG HU+ git-svn-id: https://svn.code.sf.net/p/hawebs/svn@475 a2543c7e-f6e9-4f8a-8bff-1ffc34733512
@@ -0,0 +1,299 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
|
||||
* @version $Id: API.php 2333 2010-06-22 04:58:13Z vipsoft $
|
||||
*
|
||||
* @category Piwik_Plugins
|
||||
* @package Piwik_Live
|
||||
*/
|
||||
|
||||
/**
|
||||
* @see plugins/Referers/functions.php
|
||||
*/
|
||||
require_once PIWIK_INCLUDE_PATH . '/plugins/Live/Visitor.php';
|
||||
|
||||
/**
|
||||
* @package Piwik_Live
|
||||
*/
|
||||
class Piwik_Live_API
|
||||
{
|
||||
static private $instance = null;
|
||||
/*
|
||||
* @return Piwik_Live_API
|
||||
*/
|
||||
static public function getInstance()
|
||||
{
|
||||
if (self::$instance == null)
|
||||
{
|
||||
$c = __CLASS__;
|
||||
self::$instance = new $c();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
const TYPE_FETCH_VISITS = 1;
|
||||
const TYPE_FETCH_PAGEVIEWS = 2;
|
||||
|
||||
/*
|
||||
* @return Piwik_DataTable
|
||||
*/
|
||||
public function getLastVisitForVisitor( $visitorId, $idSite )
|
||||
{
|
||||
return $this->getLastVisitsForVisitor($visitorId, $idSite, $limit = 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* @return Piwik_DataTable
|
||||
*/
|
||||
public function getLastVisitsForVisitor( $visitorId, $idSite, $limit = 10 )
|
||||
{
|
||||
Piwik::checkUserHasViewAccess($idSite);
|
||||
$visitorDetails = $this->loadLastVisitorDetailsFromDatabase($idSite, $visitorId, $limit);
|
||||
$table = $this->getCleanedVisitorsFromDetails($visitorDetails, $idSite);
|
||||
return $table;
|
||||
}
|
||||
|
||||
/*
|
||||
* @return Piwik_DataTable
|
||||
*/
|
||||
public function getLastVisits( $idSite, $limit = 10, $minIdVisit = false )
|
||||
{
|
||||
Piwik::checkUserHasViewAccess($idSite);
|
||||
$visitorDetails = $this->loadLastVisitorDetailsFromDatabase($idSite, $visitorId = null, $limit, $minIdVisit);
|
||||
$table = $this->getCleanedVisitorsFromDetails($visitorDetails, $idSite);
|
||||
return $table;
|
||||
}
|
||||
|
||||
/*
|
||||
* @return Piwik_DataTable
|
||||
*/
|
||||
public function getLastVisitsDetails( $idSite, $limit = 1000, $minIdVisit = false )
|
||||
{
|
||||
Piwik::checkUserHasViewAccess($idSite);
|
||||
$visitorDetails = $this->loadLastVisitorDetailsFromDatabase($idSite, $visitorId = null, $limit, $minIdVisit);
|
||||
$dataTable = $this->getCleanedVisitorsFromDetails($visitorDetails, $idSite);
|
||||
return $dataTable;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @return Piwik_DataTable
|
||||
*/
|
||||
public function getUsersInLastXMin( $idSite, $minutes = 30 )
|
||||
{
|
||||
Piwik::checkUserHasViewAccess($idSite);
|
||||
$visitorData = $this->loadLastVisitorInLastXTimeFromDatabase($idSite, $minutes, $days = 0, self::TYPE_FETCH_VISITS);
|
||||
return $visitorData;
|
||||
}
|
||||
|
||||
/*
|
||||
* @return Piwik_DataTable
|
||||
*/
|
||||
public function getUsersInLastXDays( $idSite, $days = 10 )
|
||||
{
|
||||
Piwik::checkUserHasViewAccess($idSite);
|
||||
$visitorData = $this->loadLastVisitorInLastXTimeFromDatabase($idSite, $minutes = 0, $days, self::TYPE_FETCH_VISITS);
|
||||
return $visitorData;
|
||||
}
|
||||
|
||||
/*
|
||||
* @return array
|
||||
*/
|
||||
public function getPageImpressionsInLastXDays($idSite, $days = 10)
|
||||
{
|
||||
Piwik::checkUserHasViewAccess($idSite);
|
||||
$visitorData = $this->loadLastVisitorInLastXTimeFromDatabase($idSite, $minutes = 0, $days, self::TYPE_FETCH_PAGEVIEWS);
|
||||
return $visitorData;
|
||||
}
|
||||
|
||||
/*
|
||||
* @return array
|
||||
*/
|
||||
public function getPageImpressionsInLastXMin($idSite, $minutes = 30)
|
||||
{
|
||||
Piwik::checkUserHasViewAccess($idSite);
|
||||
$visitorData = $this->loadLastVisitorInLastXTimeFromDatabase($idSite, $minutes, $days = 0, self::TYPE_FETCH_PAGEVIEWS);
|
||||
return $visitorData;
|
||||
}
|
||||
|
||||
/*
|
||||
* @return Piwik_DataTable
|
||||
*/
|
||||
private function getCleanedVisitorsFromDetails($visitorDetails, $idSite)
|
||||
{
|
||||
$table = new Piwik_DataTable();
|
||||
|
||||
foreach($visitorDetails as $visitorDetail)
|
||||
{
|
||||
$this->cleanVisitorDetails($visitorDetail);
|
||||
$visitor = new Piwik_Live_Visitor($visitorDetail);
|
||||
$visitorDetailsArray = $visitor->getAllVisitorDetails();
|
||||
|
||||
$site = new Piwik_Site($idSite);
|
||||
$timezone = $site->getTimezone();
|
||||
$dateTimeVisit = Piwik_Date::factory($visitorDetailsArray['firstActionTimestamp'], $timezone);
|
||||
$visitorDetailsArray['serverDatePretty'] = $dateTimeVisit->getLocalized('%shortDay% %day% %shortMonth%');
|
||||
$visitorDetailsArray['serverTimePretty'] = $dateTimeVisit->getLocalized('%time%');
|
||||
|
||||
// get Detail - 100 single SQL Statements - Performance Issue
|
||||
$idvisit = $visitorDetailsArray['idVisit'];
|
||||
|
||||
$sql = "
|
||||
SELECT DISTINCT " .Piwik_Common::prefixTable('log_action').".name AS pageUrl
|
||||
FROM " .Piwik_Common::prefixTable('log_link_visit_action')."
|
||||
INNER JOIN " .Piwik_Common::prefixTable('log_action')."
|
||||
ON " .Piwik_Common::prefixTable('log_link_visit_action').".idaction_url = " .Piwik_Common::prefixTable('log_action').".idaction
|
||||
WHERE " .Piwik_Common::prefixTable('log_link_visit_action').".idvisit = $idvisit;
|
||||
";
|
||||
|
||||
$visitorDetailsArray['actionDetails'] = Piwik_FetchAll($sql);
|
||||
|
||||
$sql = "
|
||||
SELECT DISTINCT " .Piwik_Common::prefixTable('log_action').".name AS pageUrl
|
||||
FROM " .Piwik_Common::prefixTable('log_link_visit_action')."
|
||||
INNER JOIN " .Piwik_Common::prefixTable('log_action')."
|
||||
ON " .Piwik_Common::prefixTable('log_link_visit_action').".idaction_name = " .Piwik_Common::prefixTable('log_action').".idaction
|
||||
WHERE " .Piwik_Common::prefixTable('log_link_visit_action').".idvisit = $idvisit;
|
||||
";
|
||||
|
||||
$visitorDetailsArray['actionDetailsTitle'] = Piwik_FetchAll($sql);
|
||||
$table->addRowFromArray( array(Piwik_DataTable_Row::COLUMNS => $visitorDetailsArray));
|
||||
}
|
||||
|
||||
return $table;
|
||||
}
|
||||
|
||||
/*
|
||||
* @return array
|
||||
*/
|
||||
private function loadLastVisitorDetailsFromDatabase($idSite, $visitorId = null, $limit = null, $minIdVisit = false )
|
||||
{
|
||||
$where = $whereBind = array();
|
||||
|
||||
$where[] = Piwik_Common::prefixTable('log_visit') . ".idsite = ? ";
|
||||
$whereBind[] = $idSite;
|
||||
|
||||
if(!empty($visitorId))
|
||||
{
|
||||
$where[] = Piwik_Common::prefixTable('log_visit') . ".visitor_idcookie = ? ";
|
||||
$whereBind[] = $visitorId;
|
||||
}
|
||||
|
||||
if(!empty($minIdVisit))
|
||||
{
|
||||
$where[] = Piwik_Common::prefixTable('log_visit') . ".idvisit > ? ";
|
||||
$whereBind[] = $minIdVisit;
|
||||
}
|
||||
|
||||
$sqlWhere = "";
|
||||
if(count($where) > 0)
|
||||
{
|
||||
$sqlWhere = " WHERE " . join(' AND ', $where);
|
||||
}
|
||||
|
||||
$sql = "SELECT " . Piwik_Common::prefixTable('log_visit') . ".* ,
|
||||
" . Piwik_Common::prefixTable ( 'goal' ) . ".match_attribute
|
||||
FROM " . Piwik_Common::prefixTable('log_visit') . "
|
||||
LEFT JOIN ".Piwik_Common::prefixTable('log_conversion')."
|
||||
ON " . Piwik_Common::prefixTable('log_visit') . ".idvisit = " . Piwik_Common::prefixTable('log_conversion') . ".idvisit
|
||||
LEFT JOIN ".Piwik_Common::prefixTable('goal')."
|
||||
ON (" . Piwik_Common::prefixTable('goal') . ".idsite = " . Piwik_Common::prefixTable('log_visit') . ".idsite
|
||||
AND " . Piwik_Common::prefixTable('goal') . ".idgoal = " . Piwik_Common::prefixTable('log_conversion') . ".idgoal)
|
||||
AND " . Piwik_Common::prefixTable('goal') . ".deleted = 0
|
||||
$sqlWhere
|
||||
ORDER BY idsite,idvisit DESC
|
||||
LIMIT $limit";
|
||||
|
||||
return Piwik_FetchAll($sql, $whereBind);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load last Visitors PAGES or DETAILS in MINUTES or DAYS from database
|
||||
*
|
||||
* @param int $idSite
|
||||
* @param int $minutes
|
||||
* @param int $days
|
||||
* @param int $type self::TYPE_FETCH_VISITS or self::TYPE_FETCH_PAGEVIEWS
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
private function loadLastVisitorInLastXTimeFromDatabase($idSite, $minutes = 0, $days = 0, $type = false )
|
||||
{
|
||||
$where = $whereBind = array();
|
||||
|
||||
$where[] = " " . Piwik_Common::prefixTable('log_visit') . ".idsite = ? ";
|
||||
$whereBind[] = $idSite;
|
||||
|
||||
if($minutes != 0)
|
||||
{
|
||||
$timeLimit = mktime(date("H"), date("i") - $minutes, 0, date("m"), date("d"), date("Y"));
|
||||
$where[] = " visit_last_action_time > '".date('Y-m-d H:i:s',$timeLimit)."'";
|
||||
}
|
||||
|
||||
if($days != 0)
|
||||
{
|
||||
$timeLimit = mktime(0, 0, 0, date("m"), date("d") - $days + 1, date("Y"));
|
||||
$where[] = " visit_last_action_time > '".date('Y-m-d H:i:s', $timeLimit)."'";
|
||||
}
|
||||
|
||||
$sqlWhere = "";
|
||||
if(count($where) > 0)
|
||||
{
|
||||
$sqlWhere = " WHERE " . join(' AND ', $where);
|
||||
}
|
||||
|
||||
// Details
|
||||
if($type == self::TYPE_FETCH_VISITS)
|
||||
{
|
||||
$sql = "SELECT " . Piwik_Common::prefixTable('log_visit') . ".idvisit
|
||||
FROM " . Piwik_Common::prefixTable('log_visit') . "
|
||||
$sqlWhere
|
||||
ORDER BY idsite,idvisit DESC";
|
||||
}
|
||||
// Pages
|
||||
elseif($type == self::TYPE_FETCH_PAGEVIEWS)
|
||||
{
|
||||
$sql = "SELECT " . Piwik_Common::prefixTable('log_link_visit_action') . ".idaction_url
|
||||
FROM " . Piwik_Common::prefixTable('log_link_visit_action') . "
|
||||
INNER JOIN " . Piwik_Common::prefixTable('log_visit') . "
|
||||
ON " . Piwik_Common::prefixTable('log_visit') . ".idvisit = " . Piwik_Common::prefixTable('log_link_visit_action') . ".idvisit
|
||||
$sqlWhere";
|
||||
}
|
||||
else
|
||||
{
|
||||
// no $type is set --> ERROR
|
||||
throw new Exception("type parameter is not properly set.");
|
||||
}
|
||||
|
||||
// return $sql by fetching
|
||||
return Piwik_FetchAll($sql, $whereBind);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes fields that are not meant to be displayed (md5 config hash)
|
||||
* Or that the user should only access if he is super user (cookie, IP)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function cleanVisitorDetails( &$visitorDetails )
|
||||
{
|
||||
$toUnset = array('config_md5config');
|
||||
if(!Piwik::isUserIsSuperUser())
|
||||
{
|
||||
$toUnset[] = 'visitor_idcookie';
|
||||
$toUnset[] = 'location_ip';
|
||||
}
|
||||
foreach($toUnset as $keyName)
|
||||
{
|
||||
if(isset($visitorDetails[$keyName]))
|
||||
{
|
||||
unset($visitorDetails[$keyName]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
|
||||
* @version $Id: Controller.php 2080 2010-04-12 07:34:46Z matt $
|
||||
*
|
||||
* @category Piwik_Plugins
|
||||
* @package Piwik_Live
|
||||
*/
|
||||
|
||||
/**
|
||||
* @package Piwik_Live
|
||||
*/
|
||||
class Piwik_Live_Controller extends Piwik_Controller
|
||||
{
|
||||
function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->idSite = Piwik_Common::getRequestVar('idSite');
|
||||
$this->minIdVisit = Piwik_Common::getRequestVar('minIdVisit', 0, 'int');
|
||||
}
|
||||
|
||||
function index()
|
||||
{
|
||||
$this->widget(true);
|
||||
}
|
||||
|
||||
public function widget($fetch = false)
|
||||
{
|
||||
$view = Piwik_View::factory('index');
|
||||
$view->idSite = Piwik_Common::getRequestVar('idSite');
|
||||
$view->visitorsCountHalfHour = $this->getUsersInLastXMin(30);
|
||||
$view->visitorsCountToday = $this->getUsersInLastXDays(1);
|
||||
$view->pisHalfhour = $this->getPageImpressionsInLastXMin(30);
|
||||
$view->pisToday = $this->getPageImpressionsInLastXDays(1);
|
||||
$view->visitors = $this->getLastVisitsStart($fetch = true);
|
||||
|
||||
echo $view->render();
|
||||
}
|
||||
|
||||
public function getLastVisitsDetails($fetch = false)
|
||||
{
|
||||
$view = Piwik_ViewDataTable::factory('');
|
||||
$view->init( $this->pluginName,
|
||||
__FUNCTION__,
|
||||
'Live.getLastVisitsDetails',
|
||||
'getPagesFromVisitId');
|
||||
// All colomns in DB which could be shown
|
||||
//'ip', 'idVisit', 'countActions', 'isVisitorReturning', 'country', 'countryFlag', 'continent', 'provider', 'providerUrl', 'idSite',
|
||||
//'serverDate', 'visitLength', 'visitLengthPretty', 'firstActionTimestamp', 'lastActionTimestamp', 'refererType', 'refererName',
|
||||
//'keywords', 'refererUrl', 'searchEngineUrl', 'searchEngineIcon', 'operatingSystem', 'operatingSystemShortName', 'operatingSystemIcon',
|
||||
//'browserFamily', 'browserFamilyDescription', 'browser', 'browserIcon', 'screen', 'resolution', 'screenIcon', 'plugins', 'lastActionDateTime',
|
||||
//'serverDatePretty', 'serverTimePretty', 'actionDetails'
|
||||
|
||||
$view->setColumnsToDisplay(array(
|
||||
'idVisit',
|
||||
'serverDatePretty',
|
||||
'serverTimePretty',
|
||||
'ip',
|
||||
'countActions',
|
||||
'visitLengthPretty',
|
||||
'keywords',
|
||||
'refererUrl',
|
||||
'operatingSystemShortName',
|
||||
'browser',
|
||||
'screen',
|
||||
'resolution',
|
||||
'plugins',
|
||||
));
|
||||
|
||||
$view->setColumnsTranslations(array(
|
||||
'idVisit' => Piwik_Translate(''),
|
||||
'serverDatePretty' => Piwik_Translate('Live_Date'),
|
||||
'serverTimePretty' => Piwik_Translate('Live_Time'),
|
||||
'ip' => 'IP',
|
||||
'countActions' => Piwik_Translate('VisitorInterest_ColumnPagesPerVisit'),
|
||||
'visitLengthPretty' => Piwik_Translate('VisitorInterest_ColumnVisitDuration'),
|
||||
'keywords' => Piwik_Translate('Referers_ColumnKeyword'),
|
||||
'refererUrl' => Piwik_Translate('Live_Referrer_URL'),
|
||||
'operatingSystemShortName' => Piwik_Translate('UserSettings_ColumnOperatingSystem'),
|
||||
'browser' => Piwik_Translate('UserSettings_ColumnBrowser'),
|
||||
'screen' => Piwik_Translate('UserSettings_ColumnTypeOfScreen'),
|
||||
'resolution' => Piwik_Translate('UserSettings_ColumnResolution'),
|
||||
'plugins' => Piwik_Translate('UserSettings_ColumnPlugin'),
|
||||
));
|
||||
|
||||
$view->disableSort();
|
||||
$view->setLimit(10);
|
||||
$view->disableExcludeLowPopulation();
|
||||
$view->setSortedColumn('idVisit', 'ASC');
|
||||
$view->disableSearchBox();
|
||||
// "Include low population" link won't be displayed under this table
|
||||
$view->disableExcludeLowPopulation();
|
||||
// disable the tag cloud, pie charts, bar chart icons
|
||||
$view->disableShowAllViewsIcons();
|
||||
// disable the button "show more datas"
|
||||
$view->disableShowAllColumns();
|
||||
|
||||
return $this->renderView($view, $fetch);
|
||||
}
|
||||
|
||||
function getPagesFromVisitId( $fetch = false)
|
||||
{
|
||||
$view = Piwik_ViewDataTable::factory('');
|
||||
$view->init( $this->pluginName,
|
||||
__FUNCTION__,
|
||||
'Live.getLastVisitsForVisitor',
|
||||
'getPagesFromVisitId');
|
||||
|
||||
return $this->renderView($view, $fetch);
|
||||
}
|
||||
|
||||
public function getLastVisitsStart($fetch = false)
|
||||
{
|
||||
$view = Piwik_View::factory('lastVisits');
|
||||
$view->idSite = Piwik_Common::getRequestVar('idSite');
|
||||
|
||||
$view->visitors = $this->getLastVisits(10);
|
||||
|
||||
$rendered = $view->render($fetch);
|
||||
|
||||
if($fetch)
|
||||
{
|
||||
return $rendered;
|
||||
}
|
||||
echo $rendered;
|
||||
}
|
||||
|
||||
public function getLastVisits($limit = 10)
|
||||
{
|
||||
$api = new Piwik_API_Request("method=Live.getLastVisits&idSite=$this->idSite&limit=$limit&format=php&serialize=0&disable_generic_filters=1");
|
||||
$visitors = $api->process();
|
||||
|
||||
return $visitors;
|
||||
}
|
||||
|
||||
public function getUsersInLastXMin($minutes = 30) {
|
||||
$api = new Piwik_API_Request("method=Live.getUsersInLastXMin&idSite=".$this->idSite."&minutes=".$minutes."&format=php&serialize=0&disable_generic_filters=1");
|
||||
$visitors_halfhour = $api->process();
|
||||
|
||||
return count($visitors_halfhour);
|
||||
}
|
||||
|
||||
public function getUsersInLastXDays($days = 1) {
|
||||
$api = new Piwik_API_Request("method=Live.getUsersInLastXDays&idSite=$this->idSite&days=$days&format=php&serialize=0&disable_generic_filters=1");
|
||||
$visitors_today = $api->process();
|
||||
|
||||
return count($visitors_today);
|
||||
}
|
||||
|
||||
public function getPageImpressionsInLastXMin($minutes = 30) {
|
||||
$api = new Piwik_API_Request("method=Live.getPageImpressionsInLastXMin&idSite=$this->idSite&minutes=$minutes&format=php&serialize=0&disable_generic_filters=1");
|
||||
$pis_halfhour = $api->process();
|
||||
|
||||
return count($pis_halfhour);
|
||||
}
|
||||
|
||||
public function getPageImpressionsInLastXDays($days = 1) {
|
||||
$api = new Piwik_API_Request("method=Live.getPageImpressionsInLastXDays&idSite=$this->idSite&days=$days&format=php&serialize=0&disable_generic_filters=1");
|
||||
$pis_today = $api->process();
|
||||
|
||||
return count($pis_today);
|
||||
}
|
||||
|
||||
public function ajaxTotalVisitors($fetch = false)
|
||||
{
|
||||
$view = Piwik_View::factory('totalVisits');
|
||||
$view->idSite = Piwik_Common::getRequestVar('idSite');
|
||||
$view->visitorsCountHalfHour = $this->getUsersInLastXMin(30);
|
||||
$view->visitorsCountToday = $this->getUsersInLastXDays(1);
|
||||
$view->pisHalfhour = $this->getPageImpressionsInLastXMin(30);
|
||||
$view->pisToday = $this->getPageImpressionsInLastXDays(1);
|
||||
|
||||
$rendered = $view->render($fetch);
|
||||
|
||||
if($fetch)
|
||||
{
|
||||
return $rendered;
|
||||
}
|
||||
echo $rendered;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
|
||||
* @version $Id: Live.php 2264 2010-06-03 16:53:43Z vipsoft $
|
||||
*
|
||||
* @category Piwik_Plugins
|
||||
* @package Piwik_Live
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @package Piwik_Live
|
||||
*/
|
||||
class Piwik_Live extends Piwik_Plugin
|
||||
{
|
||||
public function getInformation()
|
||||
{
|
||||
return array(
|
||||
'description' => Piwik_Translate('Live_PluginDescription'),
|
||||
'author' => 'Piwik',
|
||||
'author_homepage' => 'http://piwik.org/',
|
||||
'version' => Piwik_Version::VERSION,
|
||||
);
|
||||
}
|
||||
|
||||
function getListHooksRegistered()
|
||||
{
|
||||
return array(
|
||||
'template_css_import' => 'css',
|
||||
'WidgetsList.add' => 'addWidget',
|
||||
'Menu.add' => 'addMenu',
|
||||
);
|
||||
}
|
||||
|
||||
function css()
|
||||
{
|
||||
echo "<link rel=\"stylesheet\" type=\"text/css\" href=\"themes/default/styles.css\" />\n";
|
||||
}
|
||||
|
||||
function addMenu()
|
||||
{
|
||||
Piwik_AddMenu('General_Visitors', 'Live_VisitorLog', array('module' => 'Live', 'action' => 'getLastVisitsDetails'));
|
||||
}
|
||||
|
||||
public function addWidget() {
|
||||
Piwik_AddWidget('Live!', 'Live Visitors!', 'Live', 'widget');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,327 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
|
||||
* @version $Id: Visitor.php 2147 2010-05-06 18:50:38Z vipsoft $
|
||||
*
|
||||
* @category Piwik_Plugins
|
||||
* @package Piwik_Live
|
||||
*/
|
||||
|
||||
/**
|
||||
* @see plugins/Referers/functions.php
|
||||
* @see plugins/UserCountry/functions.php
|
||||
* @see plugins/UserSettings/functions.php
|
||||
* @see plugins/Provider/functions.php
|
||||
*/
|
||||
|
||||
require_once PIWIK_INCLUDE_PATH . '/plugins/Referers/functions.php';
|
||||
require_once PIWIK_INCLUDE_PATH . '/plugins/UserCountry/functions.php';
|
||||
require_once PIWIK_INCLUDE_PATH . '/plugins/UserSettings/functions.php';
|
||||
require_once PIWIK_INCLUDE_PATH . '/plugins/Provider/functions.php';
|
||||
|
||||
/**
|
||||
*
|
||||
* @package Piwik_Live
|
||||
*/
|
||||
class Piwik_Live_Visitor
|
||||
{
|
||||
function __construct($visitorRawData)
|
||||
{
|
||||
$this->details = $visitorRawData;
|
||||
}
|
||||
|
||||
function getAllVisitorDetails()
|
||||
{
|
||||
return array(
|
||||
'ip' => $this->getIp(),
|
||||
'idVisit' => $this->getIdVisit(),
|
||||
'countActions' => $this->getNumberOfActions(),
|
||||
'isVisitorReturning' => $this->isVisitorReturning(),
|
||||
'country' => $this->getCountryName(),
|
||||
'countryFlag' => $this->getCountryFlag(),
|
||||
'continent' => $this->getContinent(),
|
||||
'provider' => $this->getProvider(),
|
||||
'providerUrl' => $this->getProviderUrl(),
|
||||
'idSite' => $this->getIdSite(),
|
||||
'serverDate' => $this->getServerDate(),
|
||||
'visitLength' => $this->getVisitLength(),
|
||||
'visitLengthPretty' => $this->getVisitLengthPretty(),
|
||||
'firstActionTimestamp' => $this->getTimestampFirstAction(),
|
||||
'lastActionTimestamp' => $this->getTimestampLastAction(),
|
||||
|
||||
'refererType' => $this->getRefererType(),
|
||||
'refererName' => $this->getRefererTypeName(),
|
||||
'keywords' => $this->getKeywords(),
|
||||
'refererUrl' => $this->getRefererUrl(),
|
||||
'refererName' => $this->getRefererName(),
|
||||
'searchEngineUrl' => $this->getSearchEngineUrl(),
|
||||
'searchEngineIcon' => $this->getSearchEngineIcon(),
|
||||
|
||||
'operatingSystem' => $this->getOperatingSystem(),
|
||||
'operatingSystemShortName' => $this->getOperatingSystemShortName(),
|
||||
'operatingSystemIcon' => $this->getOperatingSystemIcon(),
|
||||
'browserFamily' => $this->getBrowserFamily(),
|
||||
'browserFamilyDescription' => $this->getBrowserFamilyDescription(),
|
||||
'browser' => $this->getBrowser(),
|
||||
'browserIcon' => $this->getBrowserIcon(),
|
||||
'screen' => $this->getScreenType(),
|
||||
'resolution' => $this->getResolution(),
|
||||
'screenIcon' => $this->getScreenTypeIcon(),
|
||||
'plugins' => $this->getPlugins(),
|
||||
'lastActionDateTime' => $this->getDateTimeLastAction(),
|
||||
'isVisitorGoalConverted' => $this->isVisitorGoalConverted(),
|
||||
'goalIcon' => $this->getGoalIcon(),
|
||||
'goalType' => $this->getGoalType(),
|
||||
);
|
||||
}
|
||||
|
||||
function getServerDate()
|
||||
{
|
||||
return date('Y-m-d', strtotime($this->details['visit_last_action_time']));
|
||||
}
|
||||
|
||||
function getIp()
|
||||
{
|
||||
if(isset($this->details['location_ip']))
|
||||
{
|
||||
return long2ip($this->details['location_ip']);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getIdVisit()
|
||||
{
|
||||
return $this->details['idvisit'];
|
||||
}
|
||||
|
||||
function getIdSite()
|
||||
{
|
||||
return $this->details['idsite'];
|
||||
}
|
||||
|
||||
function getNumberOfActions()
|
||||
{
|
||||
return $this->details['visit_total_actions'];
|
||||
}
|
||||
|
||||
function getVisitLength()
|
||||
{
|
||||
return $this->details['visit_total_time'];
|
||||
}
|
||||
|
||||
function getVisitLengthPretty()
|
||||
{
|
||||
return Piwik::getPrettyTimeFromSeconds($this->details['visit_total_time']);
|
||||
}
|
||||
|
||||
function isVisitorReturning()
|
||||
{
|
||||
return $this->details['visitor_returning'];
|
||||
}
|
||||
|
||||
function getTimestampFirstAction()
|
||||
{
|
||||
return strtotime($this->details['visit_first_action_time']);
|
||||
}
|
||||
|
||||
function getTimestampLastAction()
|
||||
{
|
||||
return strtotime($this->details['visit_last_action_time']);
|
||||
}
|
||||
|
||||
function getCountryName()
|
||||
{
|
||||
return Piwik_CountryTranslate($this->details['location_country']);
|
||||
}
|
||||
|
||||
function getCountryFlag()
|
||||
{
|
||||
return Piwik_getFlagFromCode($this->details['location_country']);
|
||||
}
|
||||
|
||||
function getContinent()
|
||||
{
|
||||
return Piwik_ContinentTranslate($this->details['location_continent']);
|
||||
}
|
||||
|
||||
function getRefererType()
|
||||
{
|
||||
$map = array(
|
||||
Piwik_Common::REFERER_TYPE_SEARCH_ENGINE => 'searchEngine',
|
||||
Piwik_Common::REFERER_TYPE_WEBSITE => 'website',
|
||||
Piwik_Common::REFERER_TYPE_DIRECT_ENTRY => 'directEntry',
|
||||
Piwik_Common::REFERER_TYPE_CAMPAIGN => 'campaign',
|
||||
);
|
||||
if(isset($map[$this->details['referer_type']]))
|
||||
{
|
||||
return $map[$this->details['referer_type']];
|
||||
}
|
||||
return $map[Piwik_Common::REFERER_TYPE_DIRECT_ENTRY];
|
||||
}
|
||||
|
||||
function getRefererTypeName()
|
||||
{
|
||||
return Piwik_getRefererTypeLabel($this->details['referer_type']);
|
||||
}
|
||||
|
||||
function getKeywords()
|
||||
{
|
||||
return $this->details['referer_keyword'];
|
||||
}
|
||||
|
||||
function getRefererUrl()
|
||||
{
|
||||
return $this->details['referer_url'];
|
||||
}
|
||||
|
||||
function getRefererName()
|
||||
{
|
||||
return $this->details['referer_name'];
|
||||
}
|
||||
|
||||
function getSearchEngineUrl()
|
||||
{
|
||||
if($this->getRefererType() == 'searchEngine'
|
||||
&& !empty($this->details['referer_name']))
|
||||
{
|
||||
return Piwik_getSearchEngineUrlFromName($this->details['referer_name']);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function getSearchEngineIcon()
|
||||
{
|
||||
$searchEngineUrl = $this->getSearchEngineUrl();
|
||||
if( !is_null($searchEngineUrl) )
|
||||
{
|
||||
return Piwik_getSearchEngineLogoFromUrl($searchEngineUrl);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function getPlugins()
|
||||
{
|
||||
$plugins = array(
|
||||
'config_pdf',
|
||||
'config_flash',
|
||||
'config_java',
|
||||
'config_director',
|
||||
'config_quicktime',
|
||||
'config_realplayer',
|
||||
'config_windowsmedia',
|
||||
'config_gears',
|
||||
'config_silverlight',
|
||||
);
|
||||
$return = array();
|
||||
foreach($plugins as $plugin)
|
||||
{
|
||||
if($this->details[$plugin] == 1)
|
||||
{
|
||||
$pluginShortName = substr($plugin, 7);
|
||||
$return[] = $pluginShortName;
|
||||
}
|
||||
}
|
||||
return implode(", ", $return);
|
||||
}
|
||||
|
||||
function getOperatingSystem()
|
||||
{
|
||||
return Piwik_getOSLabel($this->details['config_os']);
|
||||
}
|
||||
|
||||
function getOperatingSystemShortName()
|
||||
{
|
||||
return Piwik_getOSShortLabel($this->details['config_os']);
|
||||
}
|
||||
|
||||
function getOperatingSystemIcon()
|
||||
{
|
||||
return Piwik_getOSLogo($this->details['config_os']);
|
||||
}
|
||||
|
||||
function getBrowserFamilyDescription()
|
||||
{
|
||||
return Piwik_getBrowserTypeLabel($this->getBrowserFamily());
|
||||
}
|
||||
|
||||
function getBrowserFamily()
|
||||
{
|
||||
return Piwik_getBrowserFamily($this->details['config_browser_name']);
|
||||
}
|
||||
|
||||
function getBrowser()
|
||||
{
|
||||
return Piwik_getBrowserLabel($this->details['config_browser_name'] . ";" . $this->details['config_browser_version']);
|
||||
}
|
||||
|
||||
function getBrowserIcon()
|
||||
{
|
||||
return Piwik_getBrowsersLogo($this->details['config_browser_name'] . ";" . $this->details['config_browser_version']);
|
||||
}
|
||||
|
||||
function getScreenType()
|
||||
{
|
||||
return Piwik_getScreenTypeFromResolution($this->details['config_resolution']);
|
||||
}
|
||||
|
||||
function getResolution()
|
||||
{
|
||||
return $this->details['config_resolution'];
|
||||
}
|
||||
|
||||
function getScreenTypeIcon()
|
||||
{
|
||||
return Piwik_getScreensLogo($this->getScreenType());
|
||||
}
|
||||
|
||||
function getProvider()
|
||||
{
|
||||
return Piwik_getHostnameName($this->details['location_provider']);
|
||||
}
|
||||
|
||||
function getProviderUrl()
|
||||
{
|
||||
return Piwik_getHostnameUrl($this->details['location_provider']);
|
||||
}
|
||||
|
||||
function getDateTimeLastAction()
|
||||
{
|
||||
return date('Y-m-d H:i:s', strtotime($this->details['visit_last_action_time']));
|
||||
}
|
||||
|
||||
function isVisitorGoalConverted()
|
||||
{
|
||||
return $this->details['visit_goal_converted'];
|
||||
}
|
||||
|
||||
function getGoalType()
|
||||
{
|
||||
if(isset($this->details['match_attribute'])){
|
||||
return $this->details['match_attribute'];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getGoalIcon()
|
||||
{
|
||||
if(isset($this->details['match_attribute'])){
|
||||
$goalicon = "";
|
||||
switch ($this->details['match_attribute']) {
|
||||
case "url":
|
||||
$goalicon = "plugins/Live/templates/images/goal.png";
|
||||
break;
|
||||
case "file":
|
||||
$goalicon = "plugins/Live/templates/images/download.png";
|
||||
break;
|
||||
case "external_website":
|
||||
$goalicon = "plugins/Live/templates/images/outboundlink.png";
|
||||
break;
|
||||
}
|
||||
return $goalicon;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 734 B |
|
After Width: | Height: | Size: 535 B |
|
After Width: | Height: | Size: 683 B |
|
After Width: | Height: | Size: 632 B |
|
After Width: | Height: | Size: 661 B |
|
After Width: | Height: | Size: 596 B |
|
After Width: | Height: | Size: 653 B |
|
After Width: | Height: | Size: 654 B |
|
After Width: | Height: | Size: 637 B |
|
After Width: | Height: | Size: 574 B |
|
After Width: | Height: | Size: 566 B |
|
After Width: | Height: | Size: 672 B |
|
After Width: | Height: | Size: 799 B |
|
After Width: | Height: | Size: 669 B |
|
After Width: | Height: | Size: 619 B |
|
After Width: | Height: | Size: 666 B |
|
After Width: | Height: | Size: 407 B |
|
After Width: | Height: | Size: 995 B |
@@ -0,0 +1,183 @@
|
||||
{literal}
|
||||
<script type="text/javascript" src="plugins/Live/templates/scripts/spy.js"></script>
|
||||
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
|
||||
$(document).ready(function() {
|
||||
if($('#_spyTmp').size() == 0) {
|
||||
$('#visitsLive > div:gt(2)').fadeEachDown(); // initial fade
|
||||
$('#visitsLive').spy({
|
||||
limit: 10,
|
||||
ajax: 'index.php?module=Live&idSite={/literal}{$idSite}{literal}&action=getLastVisitsStart',
|
||||
fadeLast: 2,
|
||||
isDupe: check_for_dupe,
|
||||
timeout: 8000,
|
||||
customParameterName: 'minIdVisit',
|
||||
customParameterValueCallback: lastIdVisit,
|
||||
fadeInSpeed: 600
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// first I'm ensuring that 'last' has been initialised (with last.constructor == Object),
|
||||
// then prev.html() == last.html() will return true if the HTML is the same, or false,
|
||||
// if I have a different entry.
|
||||
function check_for_dupe(prev, last)
|
||||
{
|
||||
if (last.constructor == Object) {
|
||||
return (prev.html() == last.html());
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
function lastIdVisit()
|
||||
{
|
||||
updateTotalVisits();
|
||||
updateVisitBox();
|
||||
return $('#visitsLive > div:lt(2) .idvisit').html();
|
||||
}
|
||||
|
||||
var pauseImage = "plugins/Live/templates/images/pause.gif";
|
||||
var pauseDisabledImage = "plugins/Live/templates/images/pause_disabled.gif";
|
||||
var playImage = "plugins/Live/templates/images/play.gif";
|
||||
var playDisabledImage = "plugins/Live/templates/images/play_disabled.gif";
|
||||
|
||||
function onClickPause()
|
||||
{
|
||||
$('#pauseImage').attr('src', pauseImage);
|
||||
$('#playImage').attr('src', playDisabledImage);
|
||||
return pauseSpy();
|
||||
}
|
||||
function onClickPlay()
|
||||
{
|
||||
$('#playImage').attr('src', playImage);
|
||||
$('#pauseImage').attr('src', pauseDisabledImage);
|
||||
return playSpy();
|
||||
}
|
||||
|
||||
// updates the numbers of total visits in startbox
|
||||
function updateTotalVisits()
|
||||
{
|
||||
$("#visitsTotal").load("index.php?module=Live&idSite={/literal}{$idSite}{literal}&action=ajaxTotalVisitors");
|
||||
}
|
||||
|
||||
// updates the visit table, to refresh the already presented visotors pages
|
||||
function updateVisitBox()
|
||||
{
|
||||
$("#visitsLive").load("index.php?module=Live&idSite={/literal}{$idSite}{literal}&action=getLastVisitsStart");
|
||||
}
|
||||
|
||||
/* TOOLTIP */
|
||||
$('#visitsLive label').tooltip({
|
||||
track: true,
|
||||
delay: 0,
|
||||
showURL: false,
|
||||
showBody: " - ",
|
||||
fade: 250
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
#visitsLive {
|
||||
text-align:left;
|
||||
font-size:90%;
|
||||
}
|
||||
#visitsLive .datetime, #visitsLive .country, #visitsLive .referer, #visitsLive .settings, #visitsLive .returning , #visitsLive .countActions{
|
||||
border-bottom:1px solid #C1DAD7;
|
||||
border-right:1px solid #C1DAD7;
|
||||
padding:5px 5px 5px 12px;
|
||||
}
|
||||
|
||||
#visitsLive .datetime {
|
||||
background:#D4E3ED url(plugins/CoreHome/templates/images/bg_header.jpg) repeat-x scroll 0 0;
|
||||
border-top:1px solid #C1DAD7;
|
||||
color:#6D929B;
|
||||
margin:0;
|
||||
text-align:left;
|
||||
}
|
||||
|
||||
#visitsLive .country {
|
||||
color:#4F6B72;
|
||||
background:#FFFFFF url(plugins/CoreHome/templates/images/bullet1.gif) no-repeat scroll 0 0;
|
||||
}
|
||||
|
||||
#visitsLive .referer {
|
||||
background:#F9FAFA none repeat scroll 0 0;
|
||||
color:#797268;
|
||||
}
|
||||
|
||||
#visitsLive .pagesTitle {
|
||||
display:block;
|
||||
float:left;
|
||||
padding-top: 3px;
|
||||
}
|
||||
|
||||
#visitsLive .countActions {
|
||||
background:#FFFFFF none repeat scroll 0 0;
|
||||
color:#4F6B72;
|
||||
}
|
||||
|
||||
#visitsLive .settings {
|
||||
background:#FFFFFF none repeat scroll 0 0;
|
||||
color:#4F6B72;
|
||||
}
|
||||
|
||||
#visitsLive .returning {
|
||||
background:#F9FAFA none repeat scroll 0 0;
|
||||
color:#797268;
|
||||
}
|
||||
|
||||
#visitsLive .visit {
|
||||
}
|
||||
|
||||
#visitsLive .alt {
|
||||
}
|
||||
|
||||
#visitsLive .actions {
|
||||
background:#F9FAFA none repeat scroll 0 0;
|
||||
color:#797268;
|
||||
padding:0px 5px 0px 12px;
|
||||
}
|
||||
|
||||
</style>
|
||||
{/literal}
|
||||
|
||||
<div id="visitsTotal">
|
||||
<table class="dataTable" cellspacing="0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th id="label" class="sortable label" style="cursor: auto;">
|
||||
<div id="thDIV">Period<div></th>
|
||||
<th id="label" class="sortable label" style="cursor: auto;">
|
||||
<div id="thDIV">Visits<div></th>
|
||||
<th id="label" class="sortable label" style="cursor: auto;">
|
||||
<div id="thDIV">PageViews<div></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<tr class="">
|
||||
<td class="columnodd">Today</td>
|
||||
<td class="columnodd">{$visitorsCountToday}</td>
|
||||
<td class="columnodd">{$pisToday}</td>
|
||||
</tr>
|
||||
<tr class="">
|
||||
<td class="columnodd">Last 30 minutes</td>
|
||||
<td class="columnodd">{$visitorsCountHalfHour}</td>
|
||||
<td class="columnodd">{$pisHalfhour}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id='visitsLive'>
|
||||
{$visitors}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<a href="javascript:void(0);" onclick="onClickPause();"><img id="pauseImage" border="0" src="plugins/Live/templates/images/pause_disabled.gif" /></a>
|
||||
<a href="javascript:void(0);" onclick="onClickPlay();"><img id="playImage" border="0" src="plugins/Live/templates/images/play.gif" /></a>
|
||||
</div>
|
||||
@@ -0,0 +1,35 @@
|
||||
{foreach from=$visitors item=visitor}
|
||||
<div id="{$visitor.idVisit}" class="visit{if $visitor.idVisit % 2} alt{/if}">
|
||||
<div style="display:none" class="idvisit">{$visitor.idVisit}</div>
|
||||
<div class="datetime">
|
||||
{$visitor.serverDatePretty} - {$visitor.serverTimePretty}
|
||||
<img src="{$visitor.countryFlag}" title="{$visitor.country}, Provider {$visitor.provider}" />
|
||||
<img src="{$visitor.browserIcon}" title="{$visitor.browser} with plugins {$visitor.plugins} enabled" />
|
||||
<img src="{$visitor.operatingSystemIcon}" title="{$visitor.operatingSystem}, {$visitor.resolution}" />
|
||||
{if $visitor.isVisitorGoalConverted}<img src="{$visitor.goalIcon}" title="{$visitor.goalType}" />{/if}
|
||||
{if $visitor.isVisitorReturning} <img src="plugins/Live/templates/images/returningVisitor.gif" title="Returning Visitor" />{/if}
|
||||
<label id="" title="IP: {$visitor.ip} - Duration: {$visitor.visitLengthPretty}">more...</label>
|
||||
</div>
|
||||
<!--<div class="settings"></div>-->
|
||||
<div class="referer">
|
||||
{if $visitor.refererType != 'directEntry'}from <a href="{$visitor.refererUrl}" target="_blank">{if !empty($visitor.searchEngineIcon)}<img src="{$visitor.searchEngineIcon}" /> {/if}{$visitor.refererName}</a>
|
||||
{if !empty($visitor.keywords)}"{$visitor.keywords}"{/if}
|
||||
{/if}
|
||||
{if $visitor.refererType == 'directEntry'}Direct entry{/if}
|
||||
</div>
|
||||
<div id="{$visitor.idVisit}_actions" class="settings">
|
||||
<span class="pagesTitle">Pages:</span>
|
||||
{php} $col = 0; {/php}
|
||||
{foreach from=$visitor.actionDetails item=action}
|
||||
{php}
|
||||
$col++;
|
||||
if ($col>=9)
|
||||
{
|
||||
$col=0;
|
||||
}
|
||||
{/php}
|
||||
<a href="{$action.pageUrl}" target="_blank"><img align="middle" src="plugins/Live/templates/images/file{php} echo $col; {/php}.png" title="{$action.pageUrl}" /></a>
|
||||
{/foreach}
|
||||
</div>
|
||||
</div>
|
||||
{/foreach}
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
jQuery Plugin spy (leftlogic.com/info/articles/jquery_spy2)
|
||||
(c) 2006 Remy Sharp (leftlogic.com)
|
||||
$Id: spy.js 1868 2010-02-23 22:47:29Z vipsoft $
|
||||
*/
|
||||
var spyRunning = 1;
|
||||
|
||||
$.fn.spy = function(settings) {
|
||||
var spy = this;
|
||||
spy.epoch = new Date(1970, 0, 1);
|
||||
spy.last = '';
|
||||
spy.parsing = 0;
|
||||
spy.waitTimer = 0;
|
||||
spy.json = null;
|
||||
|
||||
if (!settings.ajax) {
|
||||
alert("An AJAX/AJAH URL must be set for the spy to work.");
|
||||
return;
|
||||
}
|
||||
|
||||
spy.attachHolder = function() {
|
||||
// not mad on this, but the only way to parse HTML collections
|
||||
if (o.method == 'html')
|
||||
$('body').append('<div style="display: none!important;" id="_spyTmp"></div>');
|
||||
}
|
||||
|
||||
// returns true for 'no dupe', and false for 'dupe found'
|
||||
// latest = is latest ajax return value (raw)
|
||||
// last = is previous ajax return value (raw)
|
||||
// note that comparing latest and last if they're JSON objects
|
||||
// always returns false, so you need to implement it manually.
|
||||
spy.isDupe = function(latest, last) {
|
||||
if ((last.constructor == Object) && (o.method == 'html'))
|
||||
return (latest.html() == last.html());
|
||||
else if (last.constructor == String)
|
||||
return (latest == last);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
spy.parse = function(e, r) {
|
||||
spy.parsing = 1; // flag to stop pull via ajax
|
||||
if (o.method == 'html') {
|
||||
$('div#_spyTmp').html(r); // add contents to hidden div
|
||||
} else if (o.method == 'json') {
|
||||
eval('spy.json = ' + r); // convert text to json
|
||||
}
|
||||
|
||||
if ((o.method == 'json' && spy.json.constructor == Array) || o.method == 'html') {
|
||||
if (spy.parseItem(e)) {
|
||||
spy.waitTimer = window.setInterval(function() {
|
||||
if (spyRunning) {
|
||||
if (!spy.parseItem(e)) {
|
||||
spy.parsing = 0;
|
||||
clearInterval(spy.waitTimer);
|
||||
}
|
||||
}
|
||||
}, o.pushTimeout);
|
||||
} else {
|
||||
spy.parsing = 0;
|
||||
}
|
||||
} else if (o.method == 'json') { // we just have 1
|
||||
eval('spy.json = ' + r)
|
||||
spy.addItem(e, spy.json);
|
||||
spy.parsing = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// returns true if there's more to parse
|
||||
spy.parseItem = function(e) {
|
||||
if (o.method == 'html') {
|
||||
// note: pre jq-1.0 doesn't return the object
|
||||
var i = $('div#_spyTmp').find('div:first').remove();
|
||||
if (i.size() > 0) {
|
||||
i.hide();
|
||||
spy.addItem(e, i);
|
||||
}
|
||||
return ($('div#_spyTmp').find('div').size() != 0);
|
||||
} else {
|
||||
if (spy.json.length) {
|
||||
var i = spy.json.shift();
|
||||
spy.addItem(e, i);
|
||||
}
|
||||
|
||||
return (spy.json.length != 0);
|
||||
}
|
||||
}
|
||||
|
||||
spy.addItem = function(e, i) {
|
||||
if (! o.isDupe.call(this, i, spy.last)) {
|
||||
spy.last = i; // note i is a pointer - so when it gets modified, so does spy.last
|
||||
$('#' + e.id + ' > div:gt(' + (o.limit - 2) + ')').remove();
|
||||
$('#' + e.id + ' > div:gt(' + (o.limit - o.fadeLast - 2) + ')').fadeEachDown();
|
||||
o.push.call(e, i);
|
||||
$('#' + e.id + ' > div:first').fadeIn(o.fadeInSpeed);
|
||||
}
|
||||
}
|
||||
|
||||
spy.push = function(r) {
|
||||
$('#' + this.id).prepend(r);
|
||||
}
|
||||
|
||||
var o = {
|
||||
limit: (settings.limit || 10),
|
||||
ajax: settings.ajax,
|
||||
timeout: (settings.timeout || 3000),
|
||||
pushTimeout: (settings.pushTimeout || settings.timeout || 3000),
|
||||
method: (settings.method || 'html').toLowerCase(),
|
||||
push: (settings.push || spy.push),
|
||||
fadeInSpeed: (settings.fadeInSpeed || 'slow'), // 1400 = crawl
|
||||
customParameterName: settings.customParameterName,
|
||||
customParameterValueCallback: settings.customParameterValueCallback,
|
||||
isDupe: (settings.isDupe || spy.isDupe)
|
||||
};
|
||||
|
||||
spy.attachHolder();
|
||||
|
||||
return this.each(function() {
|
||||
var e = this;
|
||||
var lr = ''; // last ajax return
|
||||
var parameters = {};
|
||||
spy.ajaxTimer = window.setInterval(function() {
|
||||
if (spyRunning && (!spy.parsing)) {
|
||||
var customParameterValue = o.customParameterValueCallback.call();
|
||||
parameters[o.customParameterName] = customParameterValue;
|
||||
$.get(o.ajax, parameters, function(r) {
|
||||
spy.parse(e, r);
|
||||
});
|
||||
}
|
||||
}, o.timeout);
|
||||
});
|
||||
};
|
||||
|
||||
$.fn.fadeEachDown = function() {
|
||||
var s = this.size()+5;
|
||||
return this.each(function(i) {
|
||||
var o = 1 - (s == 1 ? 0.5 : 0.85/s*(i+1));
|
||||
var e = this.style;
|
||||
if (window.ActiveXObject)
|
||||
e.filter = "alpha(opacity=" + o*100 + ")";
|
||||
e.opacity = o;
|
||||
});
|
||||
};
|
||||
|
||||
function pauseSpy() {
|
||||
spyRunning = 0; return false;
|
||||
}
|
||||
|
||||
function playSpy() {
|
||||
spyRunning = 1; return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
<div id="visitsTotal">
|
||||
<table class="dataTable" cellspacing="0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th id="label" class="sortable label" style="cursor: auto;">
|
||||
<div id="thDIV">{'Live_Date'|translate}</div></th>
|
||||
<th id="label" class="sortable label" style="cursor: auto;">
|
||||
<div id="thDIV">{'General_ColumnNbVisits'|translate}</div></th>
|
||||
<th id="label" class="sortable label" style="cursor: auto;">
|
||||
<div id="thDIV">{'General_ColumnPageviews'|translate}</div></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="">
|
||||
<td class="columnodd">{'General_Today'|translate}</td>
|
||||
<td class="columnodd">{$visitorsCountToday}</td>
|
||||
<td class="columnodd">{$pisToday}</td>
|
||||
</tr>
|
||||
<tr class="">
|
||||
<td class="columnodd">{'Live_Last30Minutes'|translate}</td>
|
||||
<td class="columnodd">{$visitorsCountHalfHour}</td>
|
||||
<td class="columnodd">{$pisHalfhour}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
|
||||
* @version $Id: Auth.php 2265 2010-06-03 17:46:05Z vipsoft $
|
||||
*
|
||||
* @category Piwik_Plugins
|
||||
* @package Piwik_Login
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @package Piwik_Login
|
||||
*/
|
||||
class Piwik_Login_Auth implements Piwik_Auth
|
||||
{
|
||||
protected $login = null;
|
||||
protected $token_auth = null;
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return 'Login';
|
||||
}
|
||||
|
||||
public function authenticate()
|
||||
{
|
||||
$rootLogin = Zend_Registry::get('config')->superuser->login;
|
||||
$rootPassword = Zend_Registry::get('config')->superuser->password;
|
||||
$rootToken = Piwik_UsersManager_API::getInstance()->getTokenAuth($rootLogin, $rootPassword);
|
||||
|
||||
if($this->login == $rootLogin
|
||||
&& $this->token_auth == $rootToken)
|
||||
{
|
||||
return new Piwik_Auth_Result(Piwik_Auth_Result::SUCCESS_SUPERUSER_AUTH_CODE, $this->login, $this->token_auth );
|
||||
}
|
||||
|
||||
if($this->token_auth === $rootToken)
|
||||
{
|
||||
return new Piwik_Auth_Result(Piwik_Auth_Result::SUCCESS_SUPERUSER_AUTH_CODE, $rootLogin, $rootToken );
|
||||
}
|
||||
|
||||
$login = Piwik_FetchOne(
|
||||
'SELECT login FROM '.Piwik_Common::prefixTable('user').' WHERE token_auth = ?',
|
||||
array($this->token_auth)
|
||||
);
|
||||
if($login !== false)
|
||||
{
|
||||
if(is_null($this->login)
|
||||
|| $this->login == $login)
|
||||
{
|
||||
return new Piwik_Auth_Result(Piwik_Auth_Result::SUCCESS, $login, $this->token_auth );
|
||||
}
|
||||
}
|
||||
return new Piwik_Auth_Result( Piwik_Auth_Result::FAILURE, $this->login, $this->token_auth );
|
||||
}
|
||||
|
||||
public function setLogin($login)
|
||||
{
|
||||
$this->login = $login;
|
||||
}
|
||||
|
||||
public function setTokenAuth($token_auth)
|
||||
{
|
||||
$this->token_auth = $token_auth;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,415 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
|
||||
* @version $Id: Controller.php 2258 2010-06-02 14:50:18Z vipsoft $
|
||||
*
|
||||
* @category Piwik_Plugins
|
||||
* @package Piwik_Login
|
||||
*/
|
||||
|
||||
/**
|
||||
* Login controller
|
||||
*
|
||||
* @package Piwik_Login
|
||||
*/
|
||||
class Piwik_Login_Controller extends Piwik_Controller
|
||||
{
|
||||
/**
|
||||
* Get referer to redirect to upon successful login.
|
||||
* Remembers referer URL even if navigation is: login form -> reset password -> login form
|
||||
*
|
||||
* @returns string
|
||||
*/
|
||||
static public function getRefererToRedirect()
|
||||
{
|
||||
// retrieve any previously saved referer
|
||||
$ns = new Zend_Session_Namespace('Piwik_Login.referer');
|
||||
$referer = $ns->referer;
|
||||
if(empty($referer))
|
||||
{
|
||||
// if the referer contains module=Login, Installation, or CoreUpdater, we instead redirect to the doc root
|
||||
$referer = Piwik_Url::getLocalReferer();
|
||||
if(empty($referer) || preg_match('/module=(Login|Installation|CoreUpdater)/', $referer))
|
||||
{
|
||||
$referer = 'index.php';
|
||||
}
|
||||
$ns->referer = $referer;
|
||||
$ns->setExpirationSeconds(300, 'referer');
|
||||
}
|
||||
else if(!Piwik_Url::isLocalUrl($referer))
|
||||
{
|
||||
$referer = 'index.php';
|
||||
}
|
||||
|
||||
return $referer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default action
|
||||
*
|
||||
* @param none
|
||||
* @return void
|
||||
*/
|
||||
function index()
|
||||
{
|
||||
$this->login();
|
||||
}
|
||||
|
||||
/**
|
||||
* Login form
|
||||
*
|
||||
* @param string $messageNoAccess Access error message
|
||||
* @param string $currentUrl Current URL
|
||||
* @return void
|
||||
*/
|
||||
function login($messageNoAccess = null)
|
||||
{
|
||||
$urlToRedirect = self::getRefererToRedirect();
|
||||
|
||||
$form = new Piwik_Login_Form();
|
||||
if($form->validate())
|
||||
{
|
||||
$nonce = $form->getSubmitValue('form_nonce');
|
||||
if(Piwik_Nonce::verifyNonce('Piwik_Login.login', $nonce))
|
||||
{
|
||||
$login = $form->getSubmitValue('form_login');
|
||||
$password = $form->getSubmitValue('form_password');
|
||||
$md5Password = md5($password);
|
||||
try {
|
||||
$this->authenticateAndRedirect($login, $md5Password, $urlToRedirect);
|
||||
} catch(Exception $e) {
|
||||
$messageNoAccess = $e->getMessage();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$messageNoAccess = Piwik_Translate('Login_InvalidNonceOrReferer');
|
||||
}
|
||||
}
|
||||
|
||||
$view = Piwik_View::factory('login');
|
||||
$view->AccessErrorString = $messageNoAccess;
|
||||
$view->nonce = Piwik_Nonce::getNonce('Piwik_Login.login');
|
||||
$view->linkTitle = Piwik::getRandomTitle();
|
||||
$view->addForm( $form );
|
||||
$view->subTemplate = 'genericForm.tpl';
|
||||
echo $view->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Form-less login
|
||||
*
|
||||
* @param none
|
||||
* @return void
|
||||
*/
|
||||
function logme()
|
||||
{
|
||||
$password = Piwik_Common::getRequestVar('password', null, 'string');
|
||||
if(strlen($password) != 32)
|
||||
{
|
||||
throw new Exception(Piwik_TranslateException('Login_ExceptionPasswordMD5HashExpected'));
|
||||
}
|
||||
|
||||
$login = Piwik_Common::getRequestVar('login', null, 'string');
|
||||
if($login == Zend_Registry::get('config')->superuser->login)
|
||||
{
|
||||
throw new Exception(Piwik_TranslateException('Login_ExceptionInvalidSuperUserAuthenticationMethod', array("logme")));
|
||||
}
|
||||
|
||||
$currentUrl = 'index.php';
|
||||
$urlToRedirect = Piwik_Common::getRequestVar('url', $currentUrl, 'string');
|
||||
$urlToRedirect = htmlspecialchars_decode($urlToRedirect);
|
||||
|
||||
$this->authenticateAndRedirect($login, $password, $urlToRedirect);
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate user and password. Redirect if successful.
|
||||
*
|
||||
* @param string $login (user name)
|
||||
* @param string $md5Password (md5 hash of password)
|
||||
* @param string $urlToRedirect (URL to redirect to, if successfully authenticated)
|
||||
* @return string (failure message if unable to authenticate)
|
||||
*/
|
||||
protected function authenticateAndRedirect($login, $md5Password, $urlToRedirect)
|
||||
{
|
||||
$info = array( 'login' => $login,
|
||||
'md5Password' => $md5Password,
|
||||
);
|
||||
Piwik_PostEvent('Login.initSession', $info);
|
||||
Piwik_Url::redirectToUrl($urlToRedirect);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lost password form. Email password reset information.
|
||||
*
|
||||
* @param none
|
||||
* @return void
|
||||
*/
|
||||
function lostPassword()
|
||||
{
|
||||
$messageNoAccess = null;
|
||||
$urlToRedirect = self::getRefererToRedirect();
|
||||
|
||||
$form = new Piwik_Login_PasswordForm();
|
||||
if($form->validate())
|
||||
{
|
||||
$loginMail = $form->getSubmitValue('form_login');
|
||||
$messageNoAccess = $this->lostPasswordFormValidated($loginMail);
|
||||
}
|
||||
|
||||
$view = Piwik_View::factory('lostPassword');
|
||||
$view->AccessErrorString = $messageNoAccess;
|
||||
$view->linkTitle = Piwik::getRandomTitle();
|
||||
$view->addForm( $form );
|
||||
$view->subTemplate = 'genericForm.tpl';
|
||||
echo $view->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate user (by username or email address).
|
||||
*
|
||||
* @param string $loginMail (user name or email address)
|
||||
* @param string $urlToRedirect (URL to redirect to, if successfully validated)
|
||||
* @return string (failure message if unable to validate)
|
||||
*/
|
||||
protected function lostPasswordFormValidated($loginMail)
|
||||
{
|
||||
$user = self::getUserInformation($loginMail);
|
||||
if( $user === null )
|
||||
{
|
||||
return Piwik_Translate('Login_InvalidUsernameEmail');
|
||||
}
|
||||
|
||||
$view = Piwik_View::factory('passwordsent');
|
||||
|
||||
$login = $user['login'];
|
||||
$email = $user['email'];
|
||||
|
||||
// construct a password reset token from user information
|
||||
$resetToken = self::generatePasswordResetToken($user);
|
||||
|
||||
$ip = Piwik_Common::getIpString();
|
||||
$url = Piwik_Url::getCurrentUrlWithoutQueryString() . "?module=Login&action=resetPassword&token=$resetToken";
|
||||
|
||||
// send email with new password
|
||||
try
|
||||
{
|
||||
$mail = new Piwik_Mail();
|
||||
$mail->addTo($email, $login);
|
||||
$mail->setSubject(Piwik_Translate('Login_MailTopicPasswordRecovery'));
|
||||
$mail->setBodyText(
|
||||
str_replace(
|
||||
'\n',
|
||||
"\n",
|
||||
sprintf(Piwik_Translate('Login_MailPasswordRecoveryBody'), $login, $ip, $url, $resetToken)
|
||||
) . "\n"
|
||||
);
|
||||
|
||||
$piwikHost = $_SERVER['HTTP_HOST'];
|
||||
if(strlen($piwikHost) == 0)
|
||||
{
|
||||
$piwikHost = 'piwik.org';
|
||||
}
|
||||
|
||||
$fromEmailName = Zend_Registry::get('config')->General->login_password_recovery_email_name;
|
||||
$fromEmailAddress = Zend_Registry::get('config')->General->login_password_recovery_email_address;
|
||||
$fromEmailAddress = str_replace('{DOMAIN}', $piwikHost, $fromEmailAddress);
|
||||
$mail->setFrom($fromEmailAddress, $fromEmailName);
|
||||
@$mail->send();
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
$view->ErrorString = $e->getMessage();
|
||||
}
|
||||
|
||||
$view->linkTitle = Piwik::getRandomTitle();
|
||||
echo $view->render();
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset password form. Enter new password here.
|
||||
*
|
||||
* @param none
|
||||
* @return void
|
||||
*/
|
||||
function resetPassword()
|
||||
{
|
||||
$messageNoAccess = null;
|
||||
$urlToRedirect = self::getRefererToRedirect();
|
||||
|
||||
$form = new Piwik_Login_ResetPasswordForm();
|
||||
if($form->validate())
|
||||
{
|
||||
$loginMail = $form->getSubmitValue('form_login');
|
||||
$token = $form->getSubmitValue('form_token');
|
||||
$password = $form->getSubmitValue('form_password');
|
||||
$messageNoAccess = $this->resetPasswordFormValidated($loginMail, $token, $password);
|
||||
}
|
||||
|
||||
$view = Piwik_View::factory('resetPassword');
|
||||
$view->AccessErrorString = $messageNoAccess;
|
||||
$view->linkTitle = Piwik::getRandomTitle();
|
||||
$view->addForm( $form );
|
||||
$view->subTemplate = 'genericForm.tpl';
|
||||
echo $view->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate password reset request. If successful, set new password and redirect.
|
||||
*
|
||||
* @param string $loginMail (user name or email address)
|
||||
* @param string $token (password reset token)
|
||||
* @param array of string $newPassword (new password)
|
||||
* @param string $urlToRedirect (URL to redirect to, if successfully validated)
|
||||
* @return string (failure message)
|
||||
*/
|
||||
protected function resetPasswordFormValidated($loginMail, $token, $password)
|
||||
{
|
||||
$user = self::getUserInformation($loginMail);
|
||||
if( $user === null )
|
||||
{
|
||||
return Piwik_Translate('Login_InvalidUsernameEmail');
|
||||
}
|
||||
|
||||
if(!self::isValidToken($token, $user))
|
||||
{
|
||||
return Piwik_Translate('Login_InvalidOrExpiredToken');
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if( $user['email'] == Zend_Registry::get('config')->superuser->email )
|
||||
{
|
||||
$user['password'] = md5($password);
|
||||
Zend_Registry::get('config')->superuser = $user;
|
||||
}
|
||||
else
|
||||
{
|
||||
Piwik_UsersManager_API::getInstance()->updateUser($user['login'], $password);
|
||||
}
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
$view->ErrorString = $e->getMessage();
|
||||
}
|
||||
|
||||
$view = Piwik_View::factory('passwordchanged');
|
||||
$view->linkTitle = Piwik::getRandomTitle();
|
||||
echo $view->render();
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user information
|
||||
*
|
||||
* @param string $loginMail (user login or email address)
|
||||
* @return array ("login" => '...', "email" => '...', "password" => '...') or null, if user not found
|
||||
*/
|
||||
protected function getUserInformation($loginMail)
|
||||
{
|
||||
Piwik::setUserIsSuperUser();
|
||||
|
||||
$user = null;
|
||||
if( $loginMail == Zend_Registry::get('config')->superuser->email
|
||||
|| $loginMail == Zend_Registry::get('config')->superuser->login )
|
||||
{
|
||||
$user = array(
|
||||
'login' => Zend_Registry::get('config')->superuser->login,
|
||||
'email' => Zend_Registry::get('config')->superuser->email,
|
||||
'password' => Zend_Registry::get('config')->superuser->password,
|
||||
);
|
||||
}
|
||||
else if( Piwik_UsersManager_API::getInstance()->userExists($loginMail) )
|
||||
{
|
||||
$user = Piwik_UsersManager_API::getInstance()->getUser($loginMail);
|
||||
}
|
||||
else if( Piwik_UsersManager_API::getInstance()->userEmailExists($loginMail) )
|
||||
{
|
||||
$user = Piwik_UsersManager_API::getInstance()->getUserByEmail($loginMail);
|
||||
}
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a password reset token. Expires in (roughly) 24 hours.
|
||||
*
|
||||
* @param array (user information)
|
||||
* @param int $timestamp (Unix timestamp)
|
||||
* @return string (generated token)
|
||||
*/
|
||||
protected function generatePasswordResetToken($user, $timestamp = null)
|
||||
{
|
||||
/*
|
||||
* Piwik does not stored the generated password reset token.
|
||||
* This avoids a database schema change and SQL queries to store, retrieve, and purge (expired) tokens.
|
||||
*/
|
||||
if(!$timestamp)
|
||||
{
|
||||
$timestamp = time() + 24*60*60; /* +24 hrs */
|
||||
}
|
||||
|
||||
$expiry = strftime('%Y%m%d%H', $timestamp);
|
||||
$token = md5($expiry . $user['login'] . $user['email'] . $user['password']);
|
||||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate token.
|
||||
*
|
||||
* @param string $token
|
||||
* @param array $user (user information)
|
||||
* @return bool (true if valid, false otherwise)
|
||||
*/
|
||||
protected function isValidToken($token, $user)
|
||||
{
|
||||
$now = time();
|
||||
|
||||
// token valid for 24 hrs (give or take, due to the coarse granularity in our strftime format string)
|
||||
for($i = 0; $i <= 24; $i++)
|
||||
{
|
||||
$generatedToken = self::generatePasswordResetToken($user, $now + $i*60*60);
|
||||
if($generatedToken == $token)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// fails if token is invalid, expired, password already changed, other user information has changed, ...
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear session information
|
||||
*
|
||||
* @param none
|
||||
* @return void
|
||||
*/
|
||||
static public function clearSession()
|
||||
{
|
||||
$authCookieName = Zend_Registry::get('config')->General->login_cookie_name;
|
||||
$cookie = new Piwik_Cookie($authCookieName);
|
||||
$cookie->delete();
|
||||
|
||||
Zend_Session::expireSessionCookie();
|
||||
}
|
||||
|
||||
/**
|
||||
* Logout current user
|
||||
*
|
||||
* @param none
|
||||
* @return void
|
||||
*/
|
||||
public function logout()
|
||||
{
|
||||
self::clearSession();
|
||||
Piwik::redirectToModule('CoreHome');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
|
||||
* @version $Id: Form.php 2036 2010-04-01 21:08:24Z matt $
|
||||
*
|
||||
* @category Piwik_Plugins
|
||||
* @package Piwik_Login
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @package Piwik_Login
|
||||
*/
|
||||
class Piwik_Login_Form extends Piwik_Form
|
||||
{
|
||||
function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
// reset
|
||||
$this->updateAttributes('id="loginform" name="loginform"');
|
||||
}
|
||||
|
||||
function init()
|
||||
{
|
||||
$formElements = array(
|
||||
array('text', 'form_login'),
|
||||
array('password', 'form_password'),
|
||||
array('hidden', 'form_nonce'),
|
||||
);
|
||||
$this->addElements( $formElements );
|
||||
|
||||
$formRules = array(
|
||||
array('form_login', sprintf(Piwik_Translate('General_Required'), Piwik_Translate('General_Username')), 'required'),
|
||||
array('form_password', sprintf(Piwik_Translate('General_Required'), Piwik_Translate('Login_Password')), 'required'),
|
||||
);
|
||||
$this->addRules( $formRules );
|
||||
|
||||
$this->addElement('submit', 'submit');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
|
||||
* @version $Id: Login.php 2264 2010-06-03 16:53:43Z vipsoft $
|
||||
*
|
||||
* @category Piwik_Plugins
|
||||
* @package Piwik_Login
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @package Piwik_Login
|
||||
*/
|
||||
class Piwik_Login extends Piwik_Plugin
|
||||
{
|
||||
public function getInformation()
|
||||
{
|
||||
$info = array(
|
||||
'description' => Piwik_Translate('Login_PluginDescription'),
|
||||
'author' => 'Piwik',
|
||||
'author_homepage' => 'http://piwik.org/',
|
||||
'version' => Piwik_Version::VERSION,
|
||||
);
|
||||
return $info;
|
||||
}
|
||||
|
||||
function getListHooksRegistered()
|
||||
{
|
||||
$hooks = array(
|
||||
'FrontController.initAuthenticationObject' => 'initAuthenticationObject',
|
||||
'FrontController.NoAccessException' => 'noAccess',
|
||||
'API.Request.authenticate' => 'ApiRequestAuthenticate',
|
||||
'Login.initSession' => 'initSession',
|
||||
);
|
||||
return $hooks;
|
||||
}
|
||||
|
||||
function noAccess( $notification )
|
||||
{
|
||||
$exception = $notification->getNotificationObject();
|
||||
$exceptionMessage = $exception->getMessage();
|
||||
|
||||
$controller = new Piwik_Login_Controller();
|
||||
$controller->login($exceptionMessage);
|
||||
}
|
||||
|
||||
function ApiRequestAuthenticate($notification)
|
||||
{
|
||||
$tokenAuth = $notification->getNotificationObject();
|
||||
Zend_Registry::get('auth')->setLogin($login = null);
|
||||
Zend_Registry::get('auth')->setTokenAuth($tokenAuth);
|
||||
}
|
||||
|
||||
function initAuthenticationObject($notification)
|
||||
{
|
||||
$auth = new Piwik_Login_Auth();
|
||||
Zend_Registry::set('auth', $auth);
|
||||
|
||||
$action = Piwik::getAction();
|
||||
if(Piwik::getModule() === 'API'
|
||||
&& (empty($action) || $action == 'index'))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
$authCookieName = Zend_Registry::get('config')->General->login_cookie_name;
|
||||
$authCookieExpiry = time() + Zend_Registry::get('config')->General->login_cookie_expire;
|
||||
$authCookiePath = Zend_Registry::get('config')->General->login_cookie_path;
|
||||
$authCookie = new Piwik_Cookie($authCookieName, $authCookieExpiry, $authCookiePath);
|
||||
$defaultLogin = 'anonymous';
|
||||
$defaultTokenAuth = 'anonymous';
|
||||
if($authCookie->isCookieFound())
|
||||
{
|
||||
$defaultLogin = $authCookie->get('login');
|
||||
$defaultTokenAuth = $authCookie->get('token_auth');
|
||||
}
|
||||
$auth->setLogin($defaultLogin);
|
||||
$auth->setTokenAuth($defaultTokenAuth);
|
||||
}
|
||||
|
||||
function initSession($notification)
|
||||
{
|
||||
$info = $notification->getNotificationObject();
|
||||
$login = $info['login'];
|
||||
$md5Password = $info['md5Password'];
|
||||
|
||||
$tokenAuth = Piwik_UsersManager_API::getInstance()->getTokenAuth($login, $md5Password);
|
||||
|
||||
$auth = Zend_Registry::get('auth');
|
||||
$auth->setLogin($login);
|
||||
$auth->setTokenAuth($tokenAuth);
|
||||
|
||||
$authResult = $auth->authenticate();
|
||||
if(!$authResult->isValid())
|
||||
{
|
||||
throw new Exception(Piwik_Translate('Login_LoginPasswordNotCorrect'));
|
||||
}
|
||||
|
||||
$ns = new Zend_Session_Namespace('Piwik_Login.referer');
|
||||
unset($ns->referer);
|
||||
|
||||
$authCookieName = Zend_Registry::get('config')->General->login_cookie_name;
|
||||
$authCookieExpiry = time() + Zend_Registry::get('config')->General->login_cookie_expire;
|
||||
$authCookiePath = Zend_Registry::get('config')->General->login_cookie_path;
|
||||
$cookie = new Piwik_Cookie($authCookieName, $authCookieExpiry, $authCookiePath);
|
||||
$cookie->set('login', $login);
|
||||
$cookie->set('token_auth', $authResult->getTokenAuth());
|
||||
$cookie->save();
|
||||
|
||||
Zend_Session::regenerateId();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
|
||||
* @version $Id: PasswordForm.php 1736 2009-12-26 21:48:30Z vipsoft $
|
||||
*
|
||||
* @category Piwik_Plugins
|
||||
* @package Piwik_Login
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @package Piwik_Login
|
||||
*/
|
||||
class Piwik_Login_PasswordForm extends Piwik_Form
|
||||
{
|
||||
function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
// reset
|
||||
$this->updateAttributes('id="lostpasswordform" name="lostpasswordform"');
|
||||
}
|
||||
|
||||
function init()
|
||||
{
|
||||
$formElements = array(
|
||||
array('text', 'form_login'),
|
||||
);
|
||||
$this->addElements( $formElements );
|
||||
|
||||
$formRules = array(
|
||||
array('form_login', sprintf(Piwik_Translate('General_Required'), Piwik_Translate('Login_LoginOrEmail')), 'required'),
|
||||
);
|
||||
$this->addRules( $formRules );
|
||||
|
||||
$this->addElement('submit', 'submit');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
|
||||
* @version $Id: ResetPasswordForm.php 2036 2010-04-01 21:08:24Z matt $
|
||||
*
|
||||
* @category Piwik_Plugins
|
||||
* @package Piwik_Login
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @package Piwik_Login
|
||||
*/
|
||||
class Piwik_Login_ResetPasswordForm extends Piwik_Form
|
||||
{
|
||||
function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
// reset
|
||||
$this->updateAttributes('id="resetpasswordform" name="resetpasswordform"');
|
||||
}
|
||||
|
||||
function init()
|
||||
{
|
||||
$resetToken = Piwik_Common::getRequestVar('token', '', 'string');
|
||||
|
||||
$formElements = array(
|
||||
array('text', 'form_login'),
|
||||
array('password', 'form_password'),
|
||||
array('password', 'form_password_bis'),
|
||||
array('text', 'form_token'),
|
||||
);
|
||||
$this->addElements( $formElements );
|
||||
|
||||
$defaults = array(
|
||||
'form_token' => $resetToken,
|
||||
);
|
||||
$this->setDefaults($defaults);
|
||||
|
||||
$formRules = array(
|
||||
array('form_login', sprintf(Piwik_Translate('General_Required'), Piwik_Translate('General_Username')), 'required'),
|
||||
array('form_password', sprintf(Piwik_Translate('General_Required'), Piwik_Translate('Login_Password')), 'required'),
|
||||
array('form_password_bis', sprintf(Piwik_Translate('General_Required'), Piwik_Translate('Login_PasswordRepeat')), 'required'),
|
||||
array('form_token', sprintf(Piwik_Translate('General_Required'), Piwik_Translate('Login_PasswordResetToken')), 'required'),
|
||||
array('form_password', Piwik_Translate( 'Login_PasswordsDoNotMatch'), 'fieldHaveSameValue', 'form_password_bis'),
|
||||
);
|
||||
$this->addRules( $formRules );
|
||||
|
||||
$this->addElement('submit', 'submit');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr">
|
||||
<head>
|
||||
<title>Piwik › {'Login_LogIn'|translate}</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<link rel="shortcut icon" href="plugins/CoreHome/templates/images/favicon.ico" />
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="plugins/Login/templates/login.css" media="screen" />
|
||||
{postEvent name="template_css_import"}
|
||||
|
||||
{literal}
|
||||
<script type="text/javascript">
|
||||
function focusit() {
|
||||
var formLogin = document.getElementById('form_login');
|
||||
if(formLogin)
|
||||
{
|
||||
formLogin.focus();
|
||||
}
|
||||
}
|
||||
window.onload = focusit;
|
||||
</script>
|
||||
{/literal}
|
||||
<script type="text/javascript" src="libs/jquery/jquery.js"></script>
|
||||
{postEvent name="template_js_import"}
|
||||
</head>
|
||||
|
||||
<body class="login">
|
||||
<!-- shamelessly taken from wordpress 2.5 - thank you guys!!! -->
|
||||
|
||||
<div id="logo">
|
||||
<a href="http://piwik.org" title="{$linkTitle}"><span class="h1"><span style="color: rgb(245, 223, 114);">P</span><span style="color: rgb(241, 175, 108);">i</span><span style="color: rgb(241, 117, 117);">w</span><span style="color: rgb(155, 106, 58);">i</span><span style="color: rgb(107, 50, 11);">k</span> <span class="description"># {'General_OpenSourceWebAnalytics'|translate}</span></span></a>
|
||||
</div>
|
||||
@@ -0,0 +1,151 @@
|
||||
/* shamelessly taken from wordpress 2.5 - thank you guys!!! */
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
font: 12px "Lucida Grande", "Lucida Sans Unicode", Tahoma, Verdana,
|
||||
sans-serif;
|
||||
}
|
||||
|
||||
form {
|
||||
margin-left: 8px;
|
||||
padding: 16px 16px 40px 16px;
|
||||
font-weight: bold;
|
||||
-moz-border-radius: 5px;
|
||||
-webkit-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
form .forgetmenot {
|
||||
font-weight: normal;
|
||||
float: left;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
#login form .submit input {
|
||||
font-family: "Lucida Grande", "Lucida Sans Unicode", Tahoma, Verdana,
|
||||
sans-serif;
|
||||
padding: 3px 5px;
|
||||
border: none;
|
||||
font-size: 13px;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
cursor: default;
|
||||
text-decoration: none;
|
||||
margin-top: -6px;
|
||||
}
|
||||
|
||||
form .submit {
|
||||
float: right;
|
||||
}
|
||||
|
||||
form p {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.updated,.login #login_error,.login .message {
|
||||
background-color: #ffffe0;
|
||||
border-color: #e6db55;
|
||||
}
|
||||
|
||||
#login {
|
||||
width: 292px;
|
||||
margin: 7em auto;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
#login_error,.message {
|
||||
margin: 0 0 16px 8px;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
#nav {
|
||||
margin: 0 0 0 8px;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
#form_password,#form_login,#user_email,#form_token {
|
||||
font-size: 20px;
|
||||
width: 97%;
|
||||
padding: 3px;
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
#login form input {
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.login form {
|
||||
background-color: #eaf3fa;
|
||||
}
|
||||
|
||||
#login form .submit input {
|
||||
background-color: #cee1ef !important;
|
||||
}
|
||||
|
||||
#login #login_error {
|
||||
background-color: #ffebe8;
|
||||
border-color: #c00;
|
||||
}
|
||||
|
||||
#login form .submit input {
|
||||
background-color: #e5e5e5;
|
||||
color: #246;
|
||||
border-color: #80b5d0;
|
||||
}
|
||||
|
||||
#login form .submit input:hover {
|
||||
color: #d54e21;
|
||||
}
|
||||
|
||||
#login form .submit input:hover {
|
||||
border-color: #328ab2;
|
||||
}
|
||||
|
||||
.login #login_error {
|
||||
background-color: #ffffe0;
|
||||
border-color: #e6db55;
|
||||
}
|
||||
|
||||
.login #nav a {
|
||||
color: #777;
|
||||
}
|
||||
|
||||
body.login {
|
||||
border-top-color: #464646;
|
||||
}
|
||||
|
||||
#login form input {
|
||||
color: #555;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#logo {
|
||||
margin-left: 38%;
|
||||
margin-top: 100px;
|
||||
}
|
||||
|
||||
#logo .h1 {
|
||||
font-family: Georgia, "Times New Roman", Times, serif;
|
||||
font-weight: normal;
|
||||
color: #136F8B;
|
||||
font-size: 45pt;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
#logo .description {
|
||||
font-family: Georgia, "Times New Roman", Times, serif;
|
||||
font-weight: normal;
|
||||
color: #879dbd;
|
||||
font-size: 19pt;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
{include file="Login/templates/header.tpl"}
|
||||
|
||||
<div id="login">
|
||||
|
||||
{if $form_data.errors}
|
||||
<div id="login_error">
|
||||
{foreach from=$form_data.errors item=data}
|
||||
<strong>{'General_Error'|translate}</strong>: {$data}<br />
|
||||
{/foreach}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{if $AccessErrorString}
|
||||
<div id="login_error"><strong>{'General_Error'|translate}</strong>: {$AccessErrorString}<br /></div>
|
||||
{/if}
|
||||
|
||||
<form {$form_data.attributes}>
|
||||
<p>
|
||||
<label>{'General_Username'|translate}:<br />
|
||||
<input type="text" name="form_login" id="form_login" class="input" value="" size="20" tabindex="10" />
|
||||
<input type="hidden" name="form_nonce" id="form_nonce" value="{$nonce}" /></label>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label>{'Login_Password'|translate}:<br />
|
||||
<input type="password" name="form_password" id="form_password" class="input" value="" size="20" tabindex="20" /></label>
|
||||
</p>
|
||||
{*
|
||||
<p class="forgetmenot"><label><input name="rememberme" type="checkbox" id="rememberme" value="forever" tabindex="90" /> Remember Me</label></p>
|
||||
*}
|
||||
<p class="submit">
|
||||
<input type="submit" value="{'Login_LogIn'|translate}" tabindex="100" />
|
||||
</p>
|
||||
</form>
|
||||
|
||||
<p id="nav">
|
||||
<a href="index.php?module=Login&action=lostPassword" title="{'Login_LostYourPassword'|translate}">{'Login_LostYourPassword'|translate}</a>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,38 @@
|
||||
{include file="Login/templates/header.tpl"}
|
||||
|
||||
<div id="login">
|
||||
|
||||
{if $form_data.errors}
|
||||
<div id="login_error">
|
||||
{foreach from=$form_data.errors item=data}
|
||||
<strong>{'General_Error'|translate}</strong>: {$data}<br />
|
||||
{/foreach}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{if $AccessErrorString}
|
||||
<div id="login_error"><strong>{'General_Error'|translate}</strong>: {$AccessErrorString}<br /></div>
|
||||
{/if}
|
||||
|
||||
<p class="message">
|
||||
{'Login_PasswordReminder'|translate}
|
||||
</p>
|
||||
|
||||
<form {$form_data.attributes}>
|
||||
<p>
|
||||
<label>{'Login_LoginOrEmail'|translate}:<br />
|
||||
<input type="text" name="form_login" id="form_login" class="input" value="" size="20" tabindex="10" /></label>
|
||||
</p>
|
||||
<p class="submit">
|
||||
<input type="submit" value="{'Login_RemindPassword'|translate}" tabindex="100" />
|
||||
</p>
|
||||
</form>
|
||||
|
||||
<p id="nav">
|
||||
<a href="index.php?module=Login" title="{'Login_LogIn'|translate}">{'Login_LogIn'|translate}</a>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,22 @@
|
||||
{include file="Login/templates/header.tpl"}
|
||||
|
||||
<div id="login">
|
||||
|
||||
{if isset($ErrorString)}
|
||||
<div id="login_error"><strong>{'General_Error'|translate}</strong>: {$ErrorString}<br />
|
||||
{'Login_ContactAdmin'|translate}
|
||||
</div>
|
||||
{else}
|
||||
<p class="message">
|
||||
{'Login_PasswordSuccessfullyChanged'|translate}
|
||||
</p>
|
||||
{/if}
|
||||
|
||||
<p id="nav">
|
||||
<a href="index.php?module=Login" title="{'Login_LogIn'|translate}">{'Login_LogIn'|translate}</a>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,22 @@
|
||||
{include file="Login/templates/header.tpl"}
|
||||
|
||||
<div id="login">
|
||||
|
||||
{if isset($ErrorString)}
|
||||
<div id="login_error"><strong>{'General_Error'|translate}</strong>: {$ErrorString}<br />
|
||||
{'Login_ContactAdmin'|translate}
|
||||
</div>
|
||||
{else}
|
||||
<p class="message">
|
||||
{'Login_PasswordSent'|translate}
|
||||
</p>
|
||||
{/if}
|
||||
|
||||
<p id="nav">
|
||||
<a href="index.php?module=Login" title="{'Login_LogIn'|translate}">{'Login_LogIn'|translate}</a>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,50 @@
|
||||
{include file="Login/templates/header.tpl"}
|
||||
|
||||
<div id="login">
|
||||
|
||||
{if $form_data.errors}
|
||||
<div id="login_error">
|
||||
{foreach from=$form_data.errors item=data}
|
||||
<strong>{'General_Error'|translate}</strong>: {$data}<br />
|
||||
{/foreach}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{if $AccessErrorString}
|
||||
<div id="login_error"><strong>{'General_Error'|translate}</strong>: {$AccessErrorString}<br /></div>
|
||||
{/if}
|
||||
|
||||
<form {$form_data.attributes}>
|
||||
<p>
|
||||
<label>{'Login_LoginOrEmail'|translate}:<br />
|
||||
<input type="text" name="form_login" id="form_login" class="input" value="" size="20" tabindex="10" /></label>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label>{'Login_Password'|translate}:<br />
|
||||
<input type="password" name="form_password" id="form_password" class="input" value="" size="20" tabindex="20" /></label>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label>{'Login_PasswordRepeat'|translate}:<br />
|
||||
<input type="password" name="form_password_bis" id="form_password" class="input" value="" size="20" tabindex="30" /></label>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label>{'Login_PasswordResetToken'|translate}:<br />
|
||||
<input type="text" name="form_token" id="form_token" class="input" value="{$form_data.form_token.value}" size="20" tabindex="40" /></label>
|
||||
</p>
|
||||
|
||||
<p class="submit">
|
||||
<input type="submit" value="{'Login_ChangePassword'|translate}" tabindex="100" />
|
||||
</p>
|
||||
</form>
|
||||
|
||||
<p id="nav">
|
||||
<a href="index.php?module=Login&action=lostPassword" title="{'Login_LostYourPassword'|translate}">{'Login_LostYourPassword'|translate}</a>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||