update Piwik to version 2.16 (fixes #91)
This commit is contained in:
parent
296343bf3b
commit
d885a4baa9
5833 changed files with 418860 additions and 226988 deletions
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -12,6 +12,8 @@ namespace Piwik\Tracker;
|
|||
use Exception;
|
||||
use Piwik\Common;
|
||||
use Piwik\Piwik;
|
||||
use Piwik\Plugin\Dimension\ActionDimension;
|
||||
use Piwik\Plugin\Manager;
|
||||
use Piwik\Tracker;
|
||||
|
||||
/**
|
||||
|
|
@ -20,70 +22,132 @@ use Piwik\Tracker;
|
|||
*/
|
||||
abstract class Action
|
||||
{
|
||||
const TYPE_PAGE_URL = 1;
|
||||
const TYPE_OUTLINK = 2;
|
||||
const TYPE_DOWNLOAD = 3;
|
||||
const TYPE_PAGE_URL = 1;
|
||||
const TYPE_OUTLINK = 2;
|
||||
const TYPE_DOWNLOAD = 3;
|
||||
const TYPE_PAGE_TITLE = 4;
|
||||
const TYPE_ECOMMERCE_ITEM_SKU = 5;
|
||||
const TYPE_ECOMMERCE_ITEM_SKU = 5;
|
||||
const TYPE_ECOMMERCE_ITEM_NAME = 6;
|
||||
const TYPE_ECOMMERCE_ITEM_CATEGORY = 7;
|
||||
const TYPE_SITE_SEARCH = 8;
|
||||
|
||||
const TYPE_EVENT = 10; // Alias TYPE_EVENT_CATEGORY
|
||||
const TYPE_EVENT = 10; // Alias TYPE_EVENT_CATEGORY
|
||||
const TYPE_EVENT_CATEGORY = 10;
|
||||
const TYPE_EVENT_ACTION = 11;
|
||||
const TYPE_EVENT_NAME = 12;
|
||||
const TYPE_EVENT_ACTION = 11;
|
||||
const TYPE_EVENT_NAME = 12;
|
||||
|
||||
const TYPE_CONTENT = 13; // Alias TYPE_CONTENT_NAME
|
||||
const TYPE_CONTENT_NAME = 13;
|
||||
const TYPE_CONTENT_PIECE = 14;
|
||||
const TYPE_CONTENT_TARGET = 15;
|
||||
const TYPE_CONTENT_INTERACTION = 16;
|
||||
|
||||
const DB_COLUMN_CUSTOM_FLOAT = 'custom_float';
|
||||
|
||||
private static $factoryPriority = array(
|
||||
self::TYPE_PAGE_URL,
|
||||
self::TYPE_CONTENT,
|
||||
self::TYPE_SITE_SEARCH,
|
||||
self::TYPE_EVENT,
|
||||
self::TYPE_OUTLINK,
|
||||
self::TYPE_DOWNLOAD
|
||||
);
|
||||
|
||||
/**
|
||||
* Public so that events listener can access it
|
||||
*
|
||||
* @var Request
|
||||
*/
|
||||
public $request;
|
||||
|
||||
private $idLinkVisitAction;
|
||||
private $actionIdsCached = array();
|
||||
private $customFields = array();
|
||||
private $actionName;
|
||||
private $actionType;
|
||||
|
||||
/**
|
||||
* URL with excluded Query parameters
|
||||
*/
|
||||
private $actionUrl;
|
||||
|
||||
/**
|
||||
* Raw URL (will contain excluded URL query parameters)
|
||||
*/
|
||||
private $rawActionUrl;
|
||||
|
||||
/**
|
||||
* Makes the correct Action object based on the request.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return ActionClickUrl|ActionPageview|ActionSiteSearch
|
||||
* @return Action
|
||||
*/
|
||||
static public function factory(Request $request)
|
||||
public static function factory(Request $request)
|
||||
{
|
||||
$downloadUrl = $request->getParam('download');
|
||||
if (!empty($downloadUrl)) {
|
||||
return new ActionClickUrl(self::TYPE_DOWNLOAD, $downloadUrl, $request);
|
||||
/** @var Action[] $actions */
|
||||
$actions = self::getAllActions($request);
|
||||
|
||||
foreach ($actions as $actionType) {
|
||||
if (empty($action)) {
|
||||
$action = $actionType;
|
||||
continue;
|
||||
}
|
||||
|
||||
$posPrevious = self::getPriority($action);
|
||||
$posCurrent = self::getPriority($actionType);
|
||||
|
||||
if ($posCurrent > $posPrevious) {
|
||||
$action = $actionType;
|
||||
}
|
||||
}
|
||||
|
||||
$outlinkUrl = $request->getParam('link');
|
||||
if (!empty($outlinkUrl)) {
|
||||
return new ActionClickUrl(self::TYPE_OUTLINK, $outlinkUrl, $request);
|
||||
}
|
||||
|
||||
$url = $request->getParam('url');
|
||||
|
||||
$eventCategory = $request->getParam('e_c');
|
||||
$eventAction = $request->getParam('e_a');
|
||||
if(strlen($eventCategory) > 0 && strlen($eventAction) > 0 ) {
|
||||
return new ActionEvent($eventCategory, $eventAction, $url, $request);
|
||||
}
|
||||
|
||||
$action = new ActionSiteSearch($url, $request);
|
||||
if ($action->isSearchDetected()) {
|
||||
if (!empty($action)) {
|
||||
return $action;
|
||||
}
|
||||
return new ActionPageview($url, $request);
|
||||
|
||||
return new ActionPageview($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @var Request
|
||||
*/
|
||||
protected $request;
|
||||
private static function getPriority(Action $actionType)
|
||||
{
|
||||
$key = array_search($actionType->getActionType(), self::$factoryPriority);
|
||||
|
||||
private $idLinkVisitAction;
|
||||
private $actionIdsCached = array();
|
||||
private $actionName;
|
||||
private $actionType;
|
||||
private $actionUrl;
|
||||
if (false === $key) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return $key;
|
||||
}
|
||||
|
||||
public static function shouldHandle(Request $request)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
private static function getAllActions(Request $request)
|
||||
{
|
||||
static $actions;
|
||||
|
||||
if (is_null($actions)) {
|
||||
$actions = Manager::getInstance()->findMultipleComponents('Actions', '\\Piwik\\Tracker\\Action');
|
||||
}
|
||||
|
||||
$instances = array();
|
||||
|
||||
foreach ($actions as $action) {
|
||||
/** @var \Piwik\Tracker\Action $action */
|
||||
if ($action::shouldHandle($request)) {
|
||||
$instances[] = new $action($request);
|
||||
}
|
||||
}
|
||||
|
||||
return $instances;
|
||||
}
|
||||
|
||||
public function __construct($type, Request $request)
|
||||
{
|
||||
$this->actionType = $type;
|
||||
$this->request = $request;
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -96,6 +160,14 @@ abstract class Action
|
|||
return $this->actionUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns URL of page being tracked, including all original Query parameters
|
||||
*/
|
||||
public function getActionUrlRaw()
|
||||
{
|
||||
return $this->rawActionUrl;
|
||||
}
|
||||
|
||||
public function getActionName()
|
||||
{
|
||||
return $this->actionName;
|
||||
|
|
@ -108,8 +180,7 @@ abstract class Action
|
|||
|
||||
public function getCustomVariables()
|
||||
{
|
||||
$customVariables = $this->request->getCustomVariables($scope = 'page');
|
||||
return $customVariables;
|
||||
return $this->request->getCustomVariables($scope = 'page');
|
||||
}
|
||||
|
||||
// custom_float column
|
||||
|
|
@ -118,24 +189,28 @@ abstract class Action
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
protected function setActionName($name)
|
||||
{
|
||||
$name = PageUrl::cleanupString((string)$name);
|
||||
$this->actionName = $name;
|
||||
$this->actionName = PageUrl::cleanupString((string)$name);
|
||||
}
|
||||
|
||||
protected function setActionUrl($url)
|
||||
{
|
||||
$urlBefore = $url;
|
||||
$this->rawActionUrl = PageUrl::getUrlIfLookValid($url);
|
||||
$url = PageUrl::excludeQueryParametersFromUrl($url, $this->request->getIdSite());
|
||||
|
||||
if ($url != $urlBefore) {
|
||||
Common::printDebug(' Before was "' . $urlBefore . '"');
|
||||
$this->actionUrl = PageUrl::getUrlIfLookValid($url);
|
||||
|
||||
if ($url != $this->rawActionUrl) {
|
||||
Common::printDebug(' Before was "' . $this->rawActionUrl . '"');
|
||||
Common::printDebug(' After is "' . $url . '"');
|
||||
}
|
||||
}
|
||||
|
||||
protected function setActionUrlWithoutExcludingParameters($url)
|
||||
{
|
||||
$url = PageUrl::getUrlIfLookValid($url);
|
||||
$this->rawActionUrl = $url;
|
||||
$this->actionUrl = $url;
|
||||
}
|
||||
|
||||
|
|
@ -144,14 +219,26 @@ abstract class Action
|
|||
protected function getUrlAndType()
|
||||
{
|
||||
$url = $this->getActionUrl();
|
||||
|
||||
if (!empty($url)) {
|
||||
// normalize urls by stripping protocol and www
|
||||
$url = PageUrl::normalizeUrl($url);
|
||||
return array($url['url'], Tracker\Action::TYPE_PAGE_URL, $url['prefixId']);
|
||||
return array($url['url'], self::TYPE_PAGE_URL, $url['prefixId']);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function setCustomField($field, $value)
|
||||
{
|
||||
$this->customFields[$field] = $value;
|
||||
}
|
||||
|
||||
public function getCustomFields()
|
||||
{
|
||||
return $this->customFields;
|
||||
}
|
||||
|
||||
public function getIdActionUrl()
|
||||
{
|
||||
$idUrl = $this->actionIdsCached['idaction_url'];
|
||||
|
|
@ -159,7 +246,6 @@ abstract class Action
|
|||
return (int)$idUrl;
|
||||
}
|
||||
|
||||
|
||||
public function getIdActionUrlForEntryAndExitIds()
|
||||
{
|
||||
return $this->getIdActionUrl();
|
||||
|
|
@ -172,9 +258,10 @@ abstract class Action
|
|||
|
||||
public function getIdActionName()
|
||||
{
|
||||
if(!isset($this->actionIdsCached['idaction_name'])) {
|
||||
if (!isset($this->actionIdsCached['idaction_name'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->actionIdsCached['idaction_name'];
|
||||
}
|
||||
|
||||
|
|
@ -188,24 +275,17 @@ abstract class Action
|
|||
return $this->idLinkVisitAction;
|
||||
}
|
||||
|
||||
public function writeDebugInfo()
|
||||
{
|
||||
$type = self::getTypeAsString($this->getActionType());
|
||||
Common::printDebug("Action is a $type,
|
||||
Action name = " . $this->getActionName() . ",
|
||||
Action URL = " . $this->getActionUrl());
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function getTypeAsString($type)
|
||||
{
|
||||
$class = new \ReflectionClass("\\Piwik\\Tracker\\Action");
|
||||
$class = new \ReflectionClass("\\Piwik\\Tracker\\Action");
|
||||
$constants = $class->getConstants();
|
||||
|
||||
$typeId = array_search($type, $constants);
|
||||
if($typeId === false) {
|
||||
|
||||
if (false === $typeId) {
|
||||
throw new Exception("Unexpected action type " . $type);
|
||||
}
|
||||
|
||||
return str_replace('TYPE_', '', $typeId);
|
||||
}
|
||||
|
||||
|
|
@ -220,13 +300,38 @@ abstract class Action
|
|||
*/
|
||||
public function loadIdsFromLogActionTable()
|
||||
{
|
||||
if(!empty($this->actionIdsCached)) {
|
||||
if (!empty($this->actionIdsCached)) {
|
||||
return;
|
||||
}
|
||||
$actions = $this->getActionsToLookup();
|
||||
|
||||
/** @var ActionDimension[] $dimensions */
|
||||
$dimensions = ActionDimension::getAllDimensions();
|
||||
$actions = $this->getActionsToLookup();
|
||||
|
||||
foreach ($dimensions as $dimension) {
|
||||
$value = $dimension->onLookupAction($this->request, $this);
|
||||
|
||||
if (false !== $value) {
|
||||
if (is_float($value)) {
|
||||
$value = Common::forceDotAsSeparatorForDecimalPoint($value);
|
||||
}
|
||||
|
||||
$field = $dimension->getColumnName();
|
||||
|
||||
if (empty($field)) {
|
||||
$dimensionClass = get_class($dimension);
|
||||
throw new Exception('Dimension ' . $dimensionClass . ' does not define a field name');
|
||||
}
|
||||
|
||||
$actionId = $dimension->getActionId();
|
||||
$actions[$field] = array($value, $actionId);
|
||||
Common::printDebug("$field = $value");
|
||||
}
|
||||
}
|
||||
|
||||
$actions = array_filter($actions, 'count');
|
||||
|
||||
if(empty($actions)) {
|
||||
if (empty($actions)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -239,72 +344,101 @@ abstract class Action
|
|||
/**
|
||||
* Records in the DB the association between the visit and this action.
|
||||
*
|
||||
* @param int $idVisit is the ID of the current visit in the DB table log_visit
|
||||
* @param $visitorIdCookie
|
||||
* @param int $idReferrerActionUrl is the ID of the last action done by the current visit.
|
||||
* @param $idReferrerActionName
|
||||
* @param int $timeSpentReferrerAction is the number of seconds since the last action was done.
|
||||
* It is directly related to idReferrerActionUrl.
|
||||
* @param Visitor $visitor
|
||||
*/
|
||||
public function record($idVisit, $visitorIdCookie, $idReferrerActionUrl, $idReferrerActionName, $timeSpentReferrerAction)
|
||||
public function record(Visitor $visitor, $idReferrerActionUrl, $idReferrerActionName)
|
||||
{
|
||||
$this->loadIdsFromLogActionTable();
|
||||
|
||||
$idActionName = in_array($this->getActionType(), array(Tracker\Action::TYPE_PAGE_TITLE,
|
||||
Tracker\Action::TYPE_PAGE_URL,
|
||||
Tracker\Action::TYPE_SITE_SEARCH
|
||||
))
|
||||
? (int)$this->getIdActionName()
|
||||
: null;
|
||||
|
||||
$visitAction = array(
|
||||
'idvisit' => $idVisit,
|
||||
'idsite' => $this->request->getIdSite(),
|
||||
'idvisitor' => $visitorIdCookie,
|
||||
'server_time' => Tracker::getDatetimeFromTimestamp($this->request->getCurrentTimestamp()),
|
||||
'idaction_url' => $this->getIdActionUrl(),
|
||||
'idaction_name' => $idActionName,
|
||||
'idaction_url_ref' => $idReferrerActionUrl,
|
||||
'idaction_name_ref' => $idReferrerActionName,
|
||||
'time_spent_ref_action' => $timeSpentReferrerAction
|
||||
'idvisit' => $visitor->getVisitorColumn('idvisit'),
|
||||
'idsite' => $this->request->getIdSite(),
|
||||
'idvisitor' => $visitor->getVisitorColumn('idvisitor'),
|
||||
'idaction_url' => $this->getIdActionUrl(),
|
||||
'idaction_url_ref' => $idReferrerActionUrl,
|
||||
'idaction_name_ref' => $idReferrerActionName
|
||||
);
|
||||
|
||||
foreach($this->actionIdsCached as $field => $idAction) {
|
||||
$visitAction[$field] = $idAction;
|
||||
/** @var ActionDimension[] $dimensions */
|
||||
$dimensions = ActionDimension::getAllDimensions();
|
||||
|
||||
foreach ($dimensions as $dimension) {
|
||||
$value = $dimension->onNewAction($this->request, $visitor, $this);
|
||||
|
||||
if ($value !== false) {
|
||||
if (is_float($value)) {
|
||||
$value = Common::forceDotAsSeparatorForDecimalPoint($value);
|
||||
}
|
||||
|
||||
$visitAction[$dimension->getColumnName()] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
// idaction_name is NULLable. we only set it when applicable
|
||||
if ($this->isActionHasActionName()) {
|
||||
$visitAction['idaction_name'] = (int)$this->getIdActionName();
|
||||
}
|
||||
|
||||
foreach ($this->actionIdsCached as $field => $idAction) {
|
||||
$visitAction[$field] = ($idAction === false) ? 0 : $idAction;
|
||||
}
|
||||
|
||||
$customValue = $this->getCustomFloatValue();
|
||||
if (!empty($customValue)) {
|
||||
$visitAction[self::DB_COLUMN_CUSTOM_FLOAT] = $customValue;
|
||||
$visitAction[self::DB_COLUMN_CUSTOM_FLOAT] = Common::forceDotAsSeparatorForDecimalPoint($customValue);
|
||||
}
|
||||
|
||||
$customVariables = $this->getCustomVariables();
|
||||
if (!empty($customVariables)) {
|
||||
Common::printDebug("Page level Custom Variables: ");
|
||||
Common::printDebug($customVariables);
|
||||
}
|
||||
$visitAction = array_merge($visitAction, $this->customFields);
|
||||
|
||||
$visitAction = array_merge($visitAction, $customVariables);
|
||||
$fields = implode(", ", array_keys($visitAction));
|
||||
$bind = array_values($visitAction);
|
||||
$values = Common::getSqlStringFieldsArray($visitAction);
|
||||
$this->idLinkVisitAction = $this->getModel()->createAction($visitAction);
|
||||
|
||||
$sql = "INSERT INTO " . Common::prefixTable('log_link_visit_action') . " ($fields) VALUES ($values)";
|
||||
Tracker::getDatabase()->query($sql, $bind);
|
||||
|
||||
$this->idLinkVisitAction = Tracker::getDatabase()->lastInsertId();
|
||||
$visitAction['idlink_va'] = $this->idLinkVisitAction;
|
||||
|
||||
Common::printDebug("Inserted new action:");
|
||||
Common::printDebug($visitAction);
|
||||
$visitActionDebug = $visitAction;
|
||||
$visitActionDebug['idvisitor'] = bin2hex($visitActionDebug['idvisitor']);
|
||||
Common::printDebug($visitActionDebug);
|
||||
|
||||
/**
|
||||
* Triggered after successfully persisting a [visit action entity](/guides/persistence-and-the-mysql-backend#visit-actions).
|
||||
*
|
||||
*
|
||||
* This event is deprecated, use [Dimensions](http://developer.piwik.org/guides/dimensions) instead.
|
||||
*
|
||||
* @param Action $tracker Action The Action tracker instance.
|
||||
* @param array $visitAction The visit action entity that was persisted. Read
|
||||
* [this](/guides/persistence-and-the-mysql-backend#visit-actions) to see what it contains.
|
||||
* @deprecated
|
||||
*/
|
||||
Piwik::postEvent('Tracker.recordAction', array($trackerAction = $this, $visitAction));
|
||||
}
|
||||
|
||||
public function writeDebugInfo()
|
||||
{
|
||||
$type = self::getTypeAsString($this->getActionType());
|
||||
$name = $this->getActionName();
|
||||
$url = $this->getActionUrl();
|
||||
|
||||
Common::printDebug("Action is a $type,
|
||||
Action name = " . $name . ",
|
||||
Action URL = " . $url);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function getModel()
|
||||
{
|
||||
return new Model();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
private function isActionHasActionName()
|
||||
{
|
||||
$types = array(self::TYPE_PAGE_TITLE, self::TYPE_PAGE_URL, self::TYPE_SITE_SEARCH);
|
||||
|
||||
return in_array($this->getActionType(), $types);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue