From 57aae75cfc426935fa4d764d2f35a205f2555024 Mon Sep 17 00:00:00 2001 From: BeezyT Date: Wed, 3 Oct 2012 08:18:12 +0000 Subject: refs #3332 Transitions * support for page titles * language strings for error messages are loaded if not present * some core extensions git-svn-id: http://dev.piwik.org/svn/trunk@7091 59fd770c-687e-43c8-a1e3-f5a4ff64c105 --- plugins/Transitions/API.php | 105 ++++++++++++++---- plugins/Transitions/Controller.php | 17 ++- plugins/Transitions/Transitions.php | 142 ++++++++++++++++++------ plugins/Transitions/templates/transitions.js | 149 +++++++++++++++++++------- plugins/Transitions/templates/transitions.tpl | 4 +- 5 files changed, 317 insertions(+), 100 deletions(-) (limited to 'plugins/Transitions') diff --git a/plugins/Transitions/API.php b/plugins/Transitions/API.php index 0eae1e8b80..bb855bdb4c 100644 --- a/plugins/Transitions/API.php +++ b/plugins/Transitions/API.php @@ -27,18 +27,40 @@ class Piwik_Transitions_API return self::$instance; } + public function getTransitionsForPageTitle($pageTitle, $idSite, $period, $date, $segment = false, $limitBeforeGrouping = false) + { + return $this->getTransitionsForAction($pageTitle, 'title', $idSite, $period, $date, $segment = false, $limitBeforeGrouping = false); + } + + public function getTransitionsForPageUrl($pageUrl, $idSite, $period, $date, $segment = false, $limitBeforeGrouping = false) + { + return $this->getTransitionsForAction($pageUrl, 'url', $idSite, $period, $date, $segment = false, $limitBeforeGrouping = false); + } + /** - * This method returns a complete report. - * It is used in the Transitions API to load all data at once. + * General method to get transitions for an action + * + * @param $actionName + * @param $actionType "url"|"title" + * @param $idSite + * @param $period + * @param $date + * @param bool $segment + * @param bool $limitBeforeGrouping + * @return array + * @throws Exception */ - public function getFullReport($pageUrl, $idSite, $period, $date, $segment = false, $limitBeforeGrouping = false) + public function getTransitionsForAction($actionName, $actionType, + $idSite, $period, $date, $segment = false, $limitBeforeGrouping = false) { Piwik::checkUserHasViewAccess($idSite); - // get idaction of page url - $actionsPlugin = new Piwik_Actions; - $pageUrl = Piwik_Common::unsanitizeInputValue($pageUrl); - $idaction = $actionsPlugin->getIdActionFromSegment($pageUrl, 'idaction'); + // get idaction of the requested action + $idaction = $this->deriveIdAction($actionName, $actionType); + if ($idaction < 0) + { + throw new Exception('NoDataForAction'); + } // prepare archive processing that can be used by the archiving code $archiveProcessing = new Piwik_ArchiveProcessing_Day(); @@ -54,9 +76,9 @@ class Piwik_Transitions_API // add data to the report $transitionsArchiving = new Piwik_Transitions; - $this->addInternalReferrers($transitionsArchiving, $archiveProcessing, $report, $idaction, $limitBeforeGrouping); - $this->addFollowingActions($transitionsArchiving, $archiveProcessing, $report, $idaction, $limitBeforeGrouping); - $this->addExternalReferrers($transitionsArchiving, $archiveProcessing, $report, $idaction, $limitBeforeGrouping); + $this->addInternalReferrers($transitionsArchiving, $archiveProcessing, $report, $idaction, $actionType, $limitBeforeGrouping); + $this->addFollowingActions($transitionsArchiving, $archiveProcessing, $report, $idaction, $actionType, $limitBeforeGrouping); + $this->addExternalReferrers($transitionsArchiving, $archiveProcessing, $report, $idaction, $actionType, $limitBeforeGrouping); // derive the number of exits from the other metrics $report['pageMetrics']['exits'] = $report['pageMetrics']['pageviews'] @@ -80,26 +102,61 @@ class Piwik_Transitions_API return $report; } + /** + * Derive the action ID from the request action name and type. + */ + private function deriveIdAction($actionName, $actionType) + { + $actionsPlugin = new Piwik_Actions; + + switch ($actionType) + { + case 'url': + $actionName = Piwik_Common::unsanitizeInputValue($actionName); + return $actionsPlugin->getIdActionFromSegment($actionName, 'idaction_url'); + + case 'title': + $id = $actionsPlugin->getIdActionFromSegment($actionName, 'idaction_name'); + + if ($id < 0) + { + $unkown = Piwik_Actions_ArchivingHelper::getUnknownActionName( + Piwik_Tracker_Action::TYPE_ACTION_NAME); + + if (trim($actionName) == trim($unkown)) + { + $id = $actionsPlugin->getIdActionFromSegment('', 'idaction_name'); + } + } + + return $id; + + default: + throw new Exception('Unknown action type'); + } + } + /** * Add the internal referrers to the report: * previous pages * - * @param $transitionsArchiving Piwik_Transitions + * @param Piwik_Transitions $transitionsArchiving * @param $archiveProcessing * @param $report * @param $idaction + * @param string $actionType * @param $limitBeforeGrouping * @throws Exception */ private function addInternalReferrers($transitionsArchiving, $archiveProcessing, &$report, - $idaction, $limitBeforeGrouping) { + $idaction, $actionType, $limitBeforeGrouping) { $data = $transitionsArchiving->queryInternalReferrers( - $idaction, $archiveProcessing, $limitBeforeGrouping); + $idaction, $actionType, $archiveProcessing, $limitBeforeGrouping); if ($data['pageviews'] == 0) { - throw new Exception('NoDataForUrl'); + throw new Exception('NoDataForAction'); } $report['previousPages'] = &$data['previousPages']; @@ -111,17 +168,18 @@ class Piwik_Transitions_API * Add the following actions to the report: * following pages, downloads, outlinks * - * @param $transitionsArchiving Piwik_Transitions + * @param Piwik_Transitions $transitionsArchiving * @param $archiveProcessing * @param $report * @param $idaction + * @param string $actionType * @param $limitBeforeGrouping */ private function addFollowingActions($transitionsArchiving, $archiveProcessing, &$report, - $idaction, $limitBeforeGrouping) { + $idaction, $actionType, $limitBeforeGrouping) { $data = $transitionsArchiving->queryFollowingActions( - $idaction, $archiveProcessing, $limitBeforeGrouping); + $idaction, $actionType, $archiveProcessing, $limitBeforeGrouping); foreach ($data as $tableName => $table) { @@ -133,18 +191,18 @@ class Piwik_Transitions_API * Add the external referrers to the report: * direct entries, websites, campaigns, search engines * - * @param $transitionsArchiving + * @param Piwik_Transitions $transitionsArchiving * @param $archiveProcessing * @param $report * @param $idaction + * @param string $actionType * @param $limitBeforeGrouping */ private function addExternalReferrers($transitionsArchiving, $archiveProcessing, &$report, - $idaction, $limitBeforeGrouping) { + $idaction, $actionType, $limitBeforeGrouping) { - /** @var $transitionsArchiving Piwik_Transitions */ $data = $transitionsArchiving->queryExternalReferrers( - $idaction, $archiveProcessing, $limitBeforeGrouping); + $idaction, $actionType, $archiveProcessing, $limitBeforeGrouping); $report['pageMetrics']['entries'] = 0; $report['referrers'] = array(); @@ -206,4 +264,9 @@ class Piwik_Transitions_API } } + public function getTranslations() { + $controller = new Piwik_Transitions_Controller(); + return $controller->getTranslations(); + } + } \ No newline at end of file diff --git a/plugins/Transitions/Controller.php b/plugins/Transitions/Controller.php index f30b019db1..1a6977447e 100644 --- a/plugins/Transitions/Controller.php +++ b/plugins/Transitions/Controller.php @@ -53,9 +53,9 @@ class Piwik_Transitions_Controller extends Piwik_Controller private static $jsTranslations = array( 'XOfY' => 'Transitions_XOutOfYVisits', 'XOfAllPageviews' => 'Transitions_XOfAllPageviews', - 'NoDataForUrl' => 'Transitions_NoDataForUrl', - 'NoDataForUrlDetails' => 'Transitions_NoDataForUrlDetails', - 'NoDataForUrlBack' => 'Transitions_ErrorBack', + 'NoDataForAction' => 'Transitions_NoDataForAction', + 'NoDataForActionDetails' => 'Transitions_NoDataForActionDetails', + 'NoDataForActionBack' => 'Transitions_ErrorBack', 'ShareOfAllPageviews' => 'Transitions_ShareOfAllPageviews', 'DateRange' => 'General_DateRange' ); @@ -72,8 +72,17 @@ class Piwik_Transitions_Controller extends Piwik_Controller public function renderPopover() { $view = Piwik_View::factory('transitions'); - $view->translations = self::$metricTranslations + self::$jsTranslations; + $view->translations = $this->getTranslations(); echo $view->render(); } + public function getTranslations() + { + $translations = self::$metricTranslations + self::$jsTranslations; + foreach ($translations as &$message) { + $message = Piwik_Translate($message); + } + return $translations; + } + } diff --git a/plugins/Transitions/Transitions.php b/plugins/Transitions/Transitions.php index 8e1ceec496..f51fbd0139 100644 --- a/plugins/Transitions/Transitions.php +++ b/plugins/Transitions/Transitions.php @@ -53,10 +53,12 @@ class Piwik_Transitions extends Piwik_Plugin * Get information about external referrers (i.e. search engines, websites & campaigns) * * @param $idaction + * @param $actionType * @param Piwik_ArchiveProcessing_Day $archiveProcessing + * @param $limitBeforeGrouping * @return Piwik_DataTable */ - public function queryExternalReferrers($idaction, Piwik_ArchiveProcessing_Day $archiveProcessing, + public function queryExternalReferrers($idaction, $actionType, $archiveProcessing, $limitBeforeGrouping = false) { $rankingQuery = new Piwik_RankingQuery($limitBeforeGrouping ? $limitBeforeGrouping : $this->limitBeforeGrouping); @@ -87,7 +89,9 @@ class Piwik_Transitions extends Piwik_Plugin )); $orderBy = '`'.Piwik_Archive::INDEX_NB_VISITS.'` DESC'; - $where = 'visit_entry_idaction_url = '.intval($idaction); + + $type = $this->getColumnTypeSuffix($actionType); + $where = 'visit_entry_idaction_'.$type.' = '.intval($idaction); $metrics = array(Piwik_Archive::INDEX_NB_VISITS); $data = $archiveProcessing->queryVisitsByDimension($dimension, $where, $metrics, $orderBy, @@ -130,26 +134,36 @@ class Piwik_Transitions extends Piwik_Plugin * Get information about internal referrers (previous pages & loops, i.e. page refreshes) * * @param $idaction + * @param $actionType * @param Piwik_ArchiveProcessing_Day $archiveProcessing + * @param $limitBeforeGrouping * @return array(previousPages:Piwik_DataTable, loops:integer) */ - public function queryInternalReferrers($idaction, Piwik_ArchiveProcessing_Day $archiveProcessing, + public function queryInternalReferrers($idaction, $actionType, $archiveProcessing, $limitBeforeGrouping = false) { - $dimension = 'idaction_url_ref'; - $rankingQuery = new Piwik_RankingQuery($limitBeforeGrouping ? $limitBeforeGrouping : $this->limitBeforeGrouping); $rankingQuery->addLabelColumn(array('name', 'url_prefix')); $rankingQuery->setColumnToMarkExcludedRows('is_self'); - $rankingQuery->partitionResultIntoMultipleGroups('is_page', array(0, 1)); + $rankingQuery->partitionResultIntoMultipleGroups('only_show_this', array(0, 1)); + + $type = $this->getColumnTypeSuffix($actionType); + $onlyShowType = Piwik_Tracker_Action::TYPE_ACTION_URL; + $dimension = 'idaction_url_ref'; + $isTitle = $actionType == 'title'; + if ($isTitle) + { + $onlyShowType = Piwik_Tracker_Action::TYPE_ACTION_NAME; + $dimension = 'idaction_name_ref'; + } $addSelect = ' log_action.name, log_action.url_prefix, - CASE WHEN log_link_visit_action.idaction_url_ref = '.intval($idaction).' THEN 1 ELSE 0 END AS is_self, - CASE WHEN log_action.type = '.Piwik_Tracker_Action::TYPE_ACTION_URL.' THEN 1 ELSE 0 END AS is_page'; + CASE WHEN log_link_visit_action.idaction_'.$type.'_ref = '.intval($idaction).' THEN 1 ELSE 0 END AS is_self, + CASE WHEN log_action.type = '.$onlyShowType.' THEN 1 ELSE 0 END AS only_show_this'; $where = ' - log_link_visit_action.idaction_url = '.intval($idaction); + log_link_visit_action.idaction_'.$type.' = '.intval($idaction); $orderBy = '`'.Piwik_Archive::INDEX_NB_ACTIONS.'` DESC'; @@ -157,15 +171,17 @@ class Piwik_Transitions extends Piwik_Plugin $data = $archiveProcessing->queryActionsByDimension(array($dimension), $where, $metrics, $orderBy, $rankingQuery, $dimension, $addSelect); + $loops = 0; $nbPageviews = 0; $previousPagesDataTable = new Piwik_DataTable; - if (isset($data['result'][1])) { + if (isset($data['result'][1])) + { foreach ($data['result'][1] as &$page) { $nbActions = intval($page[Piwik_Archive::INDEX_NB_ACTIONS]); $previousPagesDataTable->addRow(new Piwik_DataTable_Row(array( Piwik_DataTable_Row::COLUMNS => array( - 'label' => Piwik_Tracker_Action::reconstructNormalizedUrl($page['name'], $page['url_prefix']), + 'label' => $this->getPageLabel($page, $isTitle), Piwik_Archive::INDEX_NB_ACTIONS => $nbActions ) ))); @@ -173,17 +189,17 @@ class Piwik_Transitions extends Piwik_Plugin } } - if (isset($data['result'][0])) { + if (isset($data['result'][0])) + { foreach ($data['result'][0] as &$referrer) { $nbPageviews += intval($referrer[Piwik_Archive::INDEX_NB_ACTIONS]); } } - $loops = 0; if (count($data['excludedFromLimit'])) { - $loops = intval($data['excludedFromLimit'][0][Piwik_Archive::INDEX_NB_ACTIONS]); + $loops += intval($data['excludedFromLimit'][0][Piwik_Archive::INDEX_NB_ACTIONS]); $nbPageviews += $loops; } @@ -194,39 +210,96 @@ class Piwik_Transitions extends Piwik_Plugin ); } + private function getPageLabel(&$pageRecord, $isTitle) { + if ($isTitle) + { + $label = $pageRecord['name']; + if (empty($label)) + { + $label = Piwik_Actions_ArchivingHelper::getUnknownActionName( + Piwik_Tracker_Action::TYPE_ACTION_NAME); + } + } + else + { + $label = Piwik_Tracker_Action::reconstructNormalizedUrl( + $pageRecord['name'], $pageRecord['url_prefix']); + } + return $label; + } + /** * Get information about the following actions (following pages, outlinks, downloads) * * @param $idaction + * @param $actionType * @param Piwik_ArchiveProcessing_Day $archiveProcessing + * @param $limitBeforeGrouping * @return array(followingPages:Piwik_DataTable, outlinks:Piwik_DataTable, downloads:Piwik_DataTable) */ - public function queryFollowingActions($idaction, Piwik_ArchiveProcessing_Day $archiveProcessing, + public function queryFollowingActions($idaction, $actionType, Piwik_ArchiveProcessing_Day $archiveProcessing, $limitBeforeGrouping = false) - { - static $types = array( - Piwik_Tracker_Action::TYPE_ACTION_URL => 'followingPages', - Piwik_Tracker_Action::TYPE_OUTLINK => 'outlinks', - Piwik_Tracker_Action::TYPE_DOWNLOAD => 'downloads' - ); + { + $types = array(); + + $isTitle = ($actionType == 'title'); + if (!$isTitle) { + // specific setup for page urls + $types[Piwik_Tracker_Action::TYPE_ACTION_URL] = 'followingPages'; + $dimension = array('idaction_url'); + $joinLogActionColumn = 'idaction_url'; + $addSelect = 'log_action.name, log_action.url_prefix, log_action.type'; + } else { + // specific setup for page titles: + $types[Piwik_Tracker_Action::TYPE_ACTION_NAME] = 'followingPages'; + // join log_action on name and url and pick depending on url type + // the table joined on url is log_action1 + $joinLogActionColumn = array('idaction_url', 'idaction_name'); + $dimension = ' + CASE log_action1.type + WHEN 1 THEN log_action2.idaction + ELSE log_action1.idaction + END + '; + $addSelect = ' + CASE log_action1.type + WHEN 1 THEN log_action2.name + ELSE log_action1.name + END AS name, + CASE log_action1.type + WHEN 1 THEN log_action2.type + ELSE log_action1.type + END AS type, + NULL AS url_prefix + '; + } + + // these types are available for both titles and urls + $types[Piwik_Tracker_Action::TYPE_OUTLINK] = 'outlinks'; + $types[Piwik_Tracker_Action::TYPE_DOWNLOAD] = 'downloads'; - $dimension = 'idaction_url'; $rankingQuery = new Piwik_RankingQuery($limitBeforeGrouping ? $limitBeforeGrouping : $this->limitBeforeGrouping); $rankingQuery->addLabelColumn(array('name', 'url_prefix')); $rankingQuery->partitionResultIntoMultipleGroups('type', array_keys($types)); - $addSelect = 'log_action.name, log_action.url_prefix, log_action.type'; - - $where = ' - log_link_visit_action.idaction_url_ref = '.intval($idaction).' AND - log_link_visit_action.idaction_url != '.intval($idaction); + $type = $this->getColumnTypeSuffix($actionType); + $where = 'log_link_visit_action.idaction_'.$type.'_ref = '.intval($idaction).' AND '; + if ($isTitle) + { + $where .= '(log_link_visit_action.idaction_'.$type.' IS NULL OR ' + . 'log_link_visit_action.idaction_'.$type.' != '.intval($idaction).')'; + } + else + { + $where .= 'log_link_visit_action.idaction_'.$type.' != '.intval($idaction); + } $orderBy = '`'.Piwik_Archive::INDEX_NB_ACTIONS.'` DESC'; $metrics = array(Piwik_Archive::INDEX_NB_ACTIONS); - $data = $archiveProcessing->queryActionsByDimension(array($dimension), $where, $metrics, $orderBy, - $rankingQuery, $dimension, $addSelect); + $data = $archiveProcessing->queryActionsByDimension($dimension, $where, $metrics, $orderBy, + $rankingQuery, $joinLogActionColumn, $addSelect); $this->totalTransitionsToFollowingActions = 0; $dataTables = array(); @@ -240,9 +313,7 @@ class Piwik_Transitions extends Piwik_Plugin $actions = intval($record[Piwik_Archive::INDEX_NB_ACTIONS]); $dataTable->addRow(new Piwik_DataTable_Row(array( Piwik_DataTable_Row::COLUMNS => array( - 'label' => $type == Piwik_Tracker_Action::TYPE_ACTION_URL ? - Piwik_Tracker_Action::reconstructNormalizedUrl($record['name'], $record['url_prefix']) : - $record['name'], + 'label' => $this->getPageLabel($record, $isTitle), Piwik_Archive::INDEX_NB_ACTIONS => $actions ) ))); @@ -263,4 +334,11 @@ class Piwik_Transitions extends Piwik_Plugin return $this->totalTransitionsToFollowingActions; } + private function getColumnTypeSuffix($actionType) { + if ($actionType == 'title') { + return 'name'; + } + return 'url'; + } + } \ No newline at end of file diff --git a/plugins/Transitions/templates/transitions.js b/plugins/Transitions/templates/transitions.js index 3e29ddf347..11dc60bc5d 100644 --- a/plugins/Transitions/templates/transitions.js +++ b/plugins/Transitions/templates/transitions.js @@ -17,18 +17,48 @@ function DataTable_RowActions_Transitions(dataTable) { DataTable_RowActions_Transitions.prototype = new DataTable_RowAction; -// override trigger method directly because we don't need the label +DataTable_RowActions_Transitions.isPageUrlReport = function(module, action) { + return module == 'Actions' && + (action == 'getPageUrls' || action == 'getEntryPageUrls' || action == 'getExitPageUrls'); +}; + +DataTable_RowActions_Transitions.isPageTitleReport = function(module, action) { + return module == 'Actions' && action == 'getPageTitles'; +} + DataTable_RowActions_Transitions.prototype.trigger = function(tr, e, subTableLabel) { var link = tr.find('> td:first > a').attr('href'); link = $('