Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormatt <matt@59fd770c-687e-43c8-a1e3-f5a4ff64c105>2008-12-26 17:37:46 +0300
committermatt <matt@59fd770c-687e-43c8-a1e3-f5a4ff64c105>2008-12-26 17:37:46 +0300
commitd389561c0ccb76536d18239c9b7f81cce3d02fc1 (patch)
tree2bac760977afe8e7f3ae7890d7cd286e37109d88 /plugins
parent47f4495a2adba4cbce5d1c3d3510ce26f8650f69 (diff)
parentb86d75c79c557a7c89899939055ee7306f40d28a (diff)
Diffstat (limited to 'plugins')
-rw-r--r--plugins/API/Controller.php31
-rw-r--r--plugins/Actions/API.php2
-rw-r--r--plugins/Actions/Actions.php607
-rw-r--r--plugins/Actions/Controller.php16
-rw-r--r--plugins/CoreAdminHome/templates/header.tpl1
-rw-r--r--plugins/CoreAdminHome/templates/styles.css10
-rw-r--r--plugins/CoreHome/Controller.php115
-rw-r--r--plugins/CoreHome/templates/calendar.js2
-rw-r--r--plugins/CoreHome/templates/cloud.tpl2
-rw-r--r--plugins/CoreHome/templates/datatable.css14
-rw-r--r--plugins/CoreHome/templates/datatable.js49
-rw-r--r--plugins/CoreHome/templates/datatable.tpl10
-rw-r--r--plugins/CoreHome/templates/datatable_actions.tpl2
-rw-r--r--plugins/CoreHome/templates/datatable_actions_js.tpl6
-rw-r--r--plugins/CoreHome/templates/datatable_actions_recursive.tpl2
-rw-r--r--plugins/CoreHome/templates/datatable_actions_subdatable.tpl2
-rw-r--r--plugins/CoreHome/templates/datatable_footer.tpl16
-rw-r--r--plugins/CoreHome/templates/datatable_js.tpl6
-rw-r--r--plugins/CoreHome/templates/graph.tpl2
-rw-r--r--plugins/DBStats/API.php48
-rw-r--r--plugins/DBStats/templates/DBStats.tpl6
-rw-r--r--plugins/ExampleAPI/API.php3
-rw-r--r--plugins/ExamplePlugin/ExamplePlugin.php18
-rw-r--r--plugins/Goals/API.php227
-rw-r--r--plugins/Goals/Controller.php150
-rw-r--r--plugins/Goals/Goals.php206
-rw-r--r--plugins/Goals/templates/GoalForm.js124
-rw-r--r--plugins/Goals/templates/add_edit_goal.tpl49
-rw-r--r--plugins/Goals/templates/add_new_goal.tpl8
-rw-r--r--plugins/Goals/templates/form_add_goal.tpl67
-rw-r--r--plugins/Goals/templates/list_goal_edit.tpl22
-rw-r--r--plugins/Goals/templates/list_top_segment.tpl5
-rw-r--r--plugins/Goals/templates/overview.tpl27
-rw-r--r--plugins/Goals/templates/release_notes.tpl20
-rw-r--r--plugins/Goals/templates/single_goal.tpl37
-rw-r--r--plugins/Goals/templates/title_and_evolution_graph.tpl20
-rw-r--r--plugins/Installation/Controller.php952
-rw-r--r--plugins/Installation/templates/firstWebsiteSetup.tpl3
-rw-r--r--plugins/LanguagesManager/API.php2
-rw-r--r--plugins/Live/API.php143
-rw-r--r--plugins/Live/Controller.php37
-rw-r--r--plugins/Live/Live.php14
-rw-r--r--plugins/Live/Visitor.php262
-rw-r--r--plugins/Live/templates/images/pause.gifbin0 -> 669 bytes
-rw-r--r--plugins/Live/templates/images/pause_disabled.gifbin0 -> 619 bytes
-rw-r--r--plugins/Live/templates/images/play.gifbin0 -> 666 bytes
-rw-r--r--plugins/Live/templates/images/play_disabled.gifbin0 -> 407 bytes
-rw-r--r--plugins/Live/templates/images/returningVisitor.gifbin0 -> 995 bytes
-rw-r--r--plugins/Live/templates/index.tpl83
-rw-r--r--plugins/Live/templates/lastVisits.tpl15
-rw-r--r--plugins/Live/templates/scripts/spy.js139
-rw-r--r--plugins/Login/Controller.php129
-rw-r--r--plugins/Login/templates/login.tpl2
-rw-r--r--plugins/Provider/API.php15
-rw-r--r--plugins/Provider/Controller.php6
-rw-r--r--plugins/Provider/Provider.php3
-rw-r--r--plugins/Referers/API.php6
-rw-r--r--plugins/Referers/Controller.php72
-rw-r--r--plugins/Referers/Referers.php238
-rw-r--r--plugins/Referers/functions.php3
-rw-r--r--plugins/Referers/templates/index.tpl (renamed from plugins/Referers/index.tpl)0
-rw-r--r--plugins/Referers/templates/searchEngines_Keywords.tpl (renamed from plugins/Referers/searchEngines_Keywords.tpl)0
-rwxr-xr-xplugins/SitesManager/API.php4
-rw-r--r--plugins/SitesManager/templates/SitesManager.js16
-rw-r--r--plugins/UserCountry/API.php2
-rw-r--r--plugins/UserCountry/Controller.php28
-rw-r--r--plugins/UserCountry/UserCountry.php43
-rw-r--r--plugins/UserSettings/API.php2
-rw-r--r--plugins/UserSettings/UserSettings.php16
-rwxr-xr-xplugins/UsersManager/API.php4
-rw-r--r--plugins/UsersManager/templates/UsersManager.js2
-rw-r--r--plugins/VisitFrequency/API.php8
-rw-r--r--plugins/VisitFrequency/Controller.php3
-rw-r--r--plugins/VisitFrequency/VisitFrequency.php5
-rw-r--r--plugins/VisitTime/API.php2
-rw-r--r--plugins/VisitTime/Controller.php1
-rw-r--r--plugins/VisitTime/VisitTime.php47
-rw-r--r--plugins/VisitorInterest/API.php2
-rw-r--r--plugins/VisitsSummary/API.php8
79 files changed, 3013 insertions, 1236 deletions
diff --git a/plugins/API/Controller.php b/plugins/API/Controller.php
index 60602f585e..8eb442cca1 100644
--- a/plugins/API/Controller.php
+++ b/plugins/API/Controller.php
@@ -10,7 +10,7 @@
*/
require_once "API/Request.php";
-
+require_once "API/DocumentationGenerator.php";
/**
*
@@ -26,36 +26,19 @@ class Piwik_API_Controller extends Piwik_Controller
public function listAllMethods()
{
- $this->init();
- echo Piwik_API_Proxy::getInstance()->getAllInterfaceString( $outputExampleUrls = true, $prefixUrls = Piwik_Common::getRequestVar('prefixUrl', '') );
+ $ApiDocumentation = new Piwik_API_DocumentationGenerator();
+ echo $ApiDocumentation->getAllInterfaceString( $outputExampleUrls = true, $prefixUrls = Piwik_Common::getRequestVar('prefixUrl', '') );
}
public function listAllAPI()
{
$view = new Piwik_View("API/templates/listAllAPI.tpl");
$this->setGeneralVariablesView($view);
- $view->countLoadedAPI = $this->init();
- $view->list_api_methods_with_links = Piwik_API_Proxy::getInstance()->getAllInterfaceString();
- echo $view->render();
- }
-
- protected function init()
- {
- $plugins = Piwik_PluginsManager::getInstance()->getLoadedPluginsName();
- $loaded = 0;
- foreach( $plugins as $plugin )
- {
- $plugin = Piwik::unprefixClass($plugin);
-
- try {
- Piwik_API_Proxy::getInstance()->registerClass($plugin);
- $loaded++;
- }
- catch(Exception $e){
- }
- }
- return $loaded;
+ $ApiDocumentation = new Piwik_API_DocumentationGenerator();
+ $view->countLoadedAPI = Piwik_API_Proxy::getInstance()->getCountRegisteredClasses();
+ $view->list_api_methods_with_links = $ApiDocumentation->getAllInterfaceString();
+ echo $view->render();
}
}
diff --git a/plugins/Actions/API.php b/plugins/Actions/API.php
index 42996b7a53..57c3afa6fe 100644
--- a/plugins/Actions/API.php
+++ b/plugins/Actions/API.php
@@ -18,7 +18,7 @@ require_once "Actions.php";
*
* @package Piwik_Actions
*/
-class Piwik_Actions_API extends Piwik_Apiable
+class Piwik_Actions_API
{
static private $instance = null;
diff --git a/plugins/Actions/Actions.php b/plugins/Actions/Actions.php
index 40e167bd38..50e1d04345 100644
--- a/plugins/Actions/Actions.php
+++ b/plugins/Actions/Actions.php
@@ -1,21 +1,21 @@
-<?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$
- *
- * @package Piwik_Actions
- */
-
-/**
- *
- * @package Piwik_Actions
- */
-class Piwik_Actions extends Piwik_Plugin
-{
- static protected $actionCategoryDelimiter = null;
+<?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$
+ *
+ * @package Piwik_Actions
+ */
+
+/**
+ *
+ * @package Piwik_Actions
+ */
+class Piwik_Actions extends Piwik_Plugin
+{
+ static protected $actionCategoryDelimiter = null;
static protected $limitLevelSubCategory = 10;
public function getInformation()
@@ -41,309 +41,310 @@ class Piwik_Actions extends Piwik_Plugin
);
return $hooks;
}
-
- public function __construct()
+
+ public function __construct()
+ {
+ $this->setCategoryDelimiter( Zend_Registry::get('config')->General->action_category_delimiter);
+ }
+
+ public function setCategoryDelimiter($delimiter)
{
- $this->setCategoryDelimiter( Zend_Registry::get('config')->General->action_category_delimiter);
- }
-
- public function setCategoryDelimiter($delimiter)
- {
- self::$actionCategoryDelimiter = $delimiter;
- }
-
+ self::$actionCategoryDelimiter = $delimiter;
+ }
+
function addWidgets()
{
Piwik_AddWidget( 'Actions', 'getActions', Piwik_Translate('Actions_SubmenuPages'));
Piwik_AddWidget( 'Actions', 'getDownloads', Piwik_Translate('Actions_SubmenuDownloads'));
Piwik_AddWidget( 'Actions', 'getOutlinks', Piwik_Translate('Actions_SubmenuOutlinks'));
}
-
- function addMenus()
- {
- Piwik_AddMenu('Actions_Actions', 'Actions_SubmenuPages', array('module' => 'Actions', 'action' => 'getActions'));
- Piwik_AddMenu('Actions_Actions', 'Actions_SubmenuOutlinks', array('module' => 'Actions', 'action' => 'getOutlinks'));
- Piwik_AddMenu('Actions_Actions', 'Actions_SubmenuDownloads', array('module' => 'Actions', 'action' => 'getDownloads'));
- }
-
- function archivePeriod( $notification )
- {
- $archiveProcessing = $notification->getNotificationObject();
-
- $dataTableToSum = array(
- 'Actions_actions',
- 'Actions_downloads',
- 'Actions_outlink',
- );
+
+ function addMenus()
+ {
+ Piwik_AddMenu('Actions_Actions', 'Actions_SubmenuPages', array('module' => 'Actions', 'action' => 'getActions'));
+ Piwik_AddMenu('Actions_Actions', 'Actions_SubmenuOutlinks', array('module' => 'Actions', 'action' => 'getOutlinks'));
+ Piwik_AddMenu('Actions_Actions', 'Actions_SubmenuDownloads', array('module' => 'Actions', 'action' => 'getDownloads'));
+ }
+
+ function archivePeriod( $notification )
+ {
+ $archiveProcessing = $notification->getNotificationObject();
+
+ $dataTableToSum = array(
+ 'Actions_actions',
+ 'Actions_downloads',
+ 'Actions_outlink',
+ );
$maximumRowsInDataTableLevelZero = 200;
- $maximumRowsInSubDataTable = 50;
- $archiveProcessing->archiveDataTable($dataTableToSum, $maximumRowsInDataTableLevelZero, $maximumRowsInSubDataTable);
- }
-
- /**
- * Compute all the actions along with their hierarchies.
- *
- * For each action we process the "interest statistics" :
- * visits, unique visitors, bouce count, sum visit length.
- *
- *
- */
- public function archiveDay( $notification )
- {
- $archiveProcessing = $notification->getNotificationObject();
-
- require_once "Tracker/Action.php";
-
- $this->actionsTablesByType = array(
- Piwik_Tracker_Action::TYPE_ACTION => array(),
- Piwik_Tracker_Action::TYPE_DOWNLOAD => array(),
- Piwik_Tracker_Action::TYPE_OUTLINK => array(),
- );
-
- // This row is used in the case where an action is know as an exit_action
- // but this action was not properly recorded when it was hit in the first place
- // so we add this fake row information to make sure there is a nb_hits, etc. column for every action
- $this->defaultRow = new Piwik_DataTable_Row(array(
- Piwik_DataTable_Row::COLUMNS => array(
- 'nb_visits' => 1,
- 'nb_uniq_visitors' => 1,
- 'nb_hits' => 1,
- )));
-
- /*
- * Actions global information
- */
- $query = "SELECT name,
- type,
- count(distinct t1.idvisit) as nb_visits,
- count(distinct visitor_idcookie) as nb_uniq_visitors,
- count(*) as nb_hits
- FROM (".$archiveProcessing->logTable." as t1
- LEFT JOIN ".$archiveProcessing->logVisitActionTable." as t2 USING (idvisit))
- LEFT JOIN ".$archiveProcessing->logActionTable." as t3 USING (idaction)
- WHERE visit_server_date = ?
- AND idsite = ?
+ $maximumRowsInSubDataTable = 50;
+ $archiveProcessing->archiveDataTable($dataTableToSum, $maximumRowsInDataTableLevelZero, $maximumRowsInSubDataTable);
+ }
+
+ /**
+ * Compute all the actions along with their hierarchies.
+ *
+ * For each action we process the "interest statistics" :
+ * visits, unique visitors, bouce count, sum visit length.
+ *
+ *
+ */
+ public function archiveDay( $notification )
+ {
+ $archiveProcessing = $notification->getNotificationObject();
+
+ require_once "Tracker/Action.php";
+
+ $this->actionsTablesByType = array(
+ Piwik_Tracker_Action::TYPE_ACTION => array(),
+ Piwik_Tracker_Action::TYPE_DOWNLOAD => array(),
+ Piwik_Tracker_Action::TYPE_OUTLINK => array(),
+ );
+
+ // This row is used in the case where an action is know as an exit_action
+ // but this action was not properly recorded when it was hit in the first place
+ // so we add this fake row information to make sure there is a nb_hits, etc. column for every action
+ $this->defaultRow = new Piwik_DataTable_Row(array(
+ Piwik_DataTable_Row::COLUMNS => array(
+ 'nb_visits' => 1,
+ 'nb_uniq_visitors' => 1,
+ 'nb_hits' => 1,
+ )));
+
+ /*
+ * Actions global information
+ */
+ $query = "SELECT name,
+ type,
+ count(distinct t1.idvisit) as nb_visits,
+ count(distinct visitor_idcookie) as nb_uniq_visitors,
+ count(*) as nb_hits
+ FROM (".$archiveProcessing->logTable." as t1
+ LEFT JOIN ".$archiveProcessing->logVisitActionTable." as t2 USING (idvisit))
+ LEFT JOIN ".$archiveProcessing->logActionTable." as t3 USING (idaction)
+ WHERE visit_server_date = ?
+ AND idsite = ?
GROUP BY t3.idaction
- ORDER BY nb_hits DESC";
- $query = $archiveProcessing->db->query($query, array( $archiveProcessing->strDateStart, $archiveProcessing->idsite ));
-
- $modified = $this->updateActionsTableWithRowQuery($query);
-
-
- /*
- * Entry actions
- */
- $query = "SELECT name,
- type,
- count(distinct visitor_idcookie) as entry_nb_unique_visitor,
- count(*) as entry_nb_visits,
- sum(visit_total_actions) as entry_nb_actions,
- sum(visit_total_time) as entry_sum_visit_length,
- sum(case visit_total_actions when 1 then 1 else 0 end) as entry_bounce_count
- FROM ".$archiveProcessing->logTable."
- JOIN ".$archiveProcessing->logActionTable." ON (visit_entry_idaction = idaction)
- WHERE visit_server_date = ?
- AND idsite = ?
+ ORDER BY nb_hits DESC";
+ $query = $archiveProcessing->db->query($query, array( $archiveProcessing->strDateStart, $archiveProcessing->idsite ));
+ $modified = $this->updateActionsTableWithRowQuery($query);
+
+
+ /*
+ * Entry actions
+ */
+ $query = "SELECT name,
+ type,
+ count(distinct visitor_idcookie) as entry_nb_unique_visitor,
+ count(*) as entry_nb_visits,
+ sum(visit_total_actions) as entry_nb_actions,
+ sum(visit_total_time) as entry_sum_visit_length,
+ sum(case visit_total_actions when 1 then 1 else 0 end) as entry_bounce_count
+ FROM ".$archiveProcessing->logTable."
+ JOIN ".$archiveProcessing->logActionTable." ON (visit_entry_idaction = idaction)
+ WHERE visit_server_date = ?
+ AND idsite = ?
GROUP BY visit_entry_idaction
- ";
- $query = $archiveProcessing->db->query($query, array( $archiveProcessing->strDateStart, $archiveProcessing->idsite ));
-
- $modified = $this->updateActionsTableWithRowQuery($query);
-
-
- /*
- * Exit actions
- */
- $query = "SELECT name,
- type,
- count(distinct visitor_idcookie) as exit_nb_unique_visitor,
- count(*) as exit_nb_visits,
- sum(case visit_total_actions when 1 then 1 else 0 end) as exit_bounce_count
-
- FROM ".$archiveProcessing->logTable."
- JOIN ".$archiveProcessing->logActionTable." ON (visit_exit_idaction = idaction)
- WHERE visit_server_date = ?
- AND idsite = ?
+ ";
+ $query = $archiveProcessing->db->query($query, array( $archiveProcessing->strDateStart, $archiveProcessing->idsite ));
+ $modified = $this->updateActionsTableWithRowQuery($query);
+
+
+ /*
+ * Exit actions
+ */
+ $query = "SELECT name,
+ type,
+ count(distinct visitor_idcookie) as exit_nb_unique_visitor,
+ count(*) as exit_nb_visits,
+ sum(case visit_total_actions when 1 then 1 else 0 end) as exit_bounce_count
+
+ FROM ".$archiveProcessing->logTable."
+ JOIN ".$archiveProcessing->logActionTable." ON (visit_exit_idaction = idaction)
+ WHERE visit_server_date = ?
+ AND idsite = ?
GROUP BY visit_exit_idaction
- ";
- $query = $archiveProcessing->db->query($query, array( $archiveProcessing->strDateStart, $archiveProcessing->idsite ));
-
- $modified = $this->updateActionsTableWithRowQuery($query);
-
- /*
- * Time per action
- */
- $query = "SELECT name,
- type,
- sum(time_spent_ref_action) as sum_time_spent
- FROM (".$archiveProcessing->logTable." log_visit
- JOIN ".$archiveProcessing->logVisitActionTable." log_link_visit_action USING (idvisit))
- JOIN ".$archiveProcessing->logActionTable." log_action ON (log_action.idaction = log_link_visit_action.idaction_ref)
- WHERE visit_server_date = ?
- AND idsite = ?
- GROUP BY idaction_ref
- ";
- $query = $archiveProcessing->db->query($query, array( $archiveProcessing->strDateStart, $archiveProcessing->idsite ));
-
- $modified = $this->updateActionsTableWithRowQuery($query);
+ ";
+ $query = $archiveProcessing->db->query($query, array( $archiveProcessing->strDateStart, $archiveProcessing->idsite ));
+ $modified = $this->updateActionsTableWithRowQuery($query);
- $maximumRowsInDataTableLevelZero = 200;
- $maximumRowsInSubDataTable = 50;
-
- $dataTable = Piwik_ArchiveProcessing_Day::generateDataTable($this->actionsTablesByType[Piwik_Tracker_Action::TYPE_ACTION]);
- $s = $dataTable->getSerialized( $maximumRowsInDataTableLevelZero, $maximumRowsInSubDataTable );
- $record = new Piwik_ArchiveProcessing_Record_BlobArray('Actions_actions', $s);
-
- $dataTable = Piwik_ArchiveProcessing_Day::generateDataTable($this->actionsTablesByType[Piwik_Tracker_Action::TYPE_DOWNLOAD]);
- $s = $dataTable->getSerialized( $maximumRowsInDataTableLevelZero, $maximumRowsInSubDataTable );
- $record = new Piwik_ArchiveProcessing_Record_BlobArray('Actions_downloads', $s);
-
- $dataTable = Piwik_ArchiveProcessing_Day::generateDataTable($this->actionsTablesByType[Piwik_Tracker_Action::TYPE_OUTLINK]);
- $s = $dataTable->getSerialized( $maximumRowsInDataTableLevelZero, $maximumRowsInSubDataTable );
- $record = new Piwik_ArchiveProcessing_Record_BlobArray('Actions_outlink', $s);
+ /*
+ * Time per action
+ */
+ $query = "SELECT name,
+ type,
+ sum(time_spent_ref_action) as sum_time_spent
+ FROM (".$archiveProcessing->logTable." log_visit
+ JOIN ".$archiveProcessing->logVisitActionTable." log_link_visit_action USING (idvisit))
+ JOIN ".$archiveProcessing->logActionTable." log_action ON (log_action.idaction = log_link_visit_action.idaction_ref)
+ WHERE visit_server_date = ?
+ AND idsite = ?
+ GROUP BY idaction_ref
+ ";
+ $query = $archiveProcessing->db->query($query, array( $archiveProcessing->strDateStart, $archiveProcessing->idsite ));
+ $modified = $this->updateActionsTableWithRowQuery($query);
+
+ $this->archiveDayRecordInDatabase();
+ }
+
+ protected function archiveDayRecordInDatabase()
+ {
+ $maximumRowsInDataTableLevelZero = 1000;
+ $maximumRowsInSubDataTable = 200;
+
+ $dataTable = Piwik_ArchiveProcessing_Day::generateDataTable($this->actionsTablesByType[Piwik_Tracker_Action::TYPE_ACTION]);
+ $s = $dataTable->getSerialized( $maximumRowsInDataTableLevelZero, $maximumRowsInSubDataTable );
+ $record = new Piwik_ArchiveProcessing_Record_BlobArray('Actions_actions', $s);
+
+ $dataTable = Piwik_ArchiveProcessing_Day::generateDataTable($this->actionsTablesByType[Piwik_Tracker_Action::TYPE_DOWNLOAD]);
+ $s = $dataTable->getSerialized($maximumRowsInDataTableLevelZero, $maximumRowsInSubDataTable );
+ $record = new Piwik_ArchiveProcessing_Record_BlobArray('Actions_downloads', $s);
- unset($this->actionsTablesByType);
- }
-
- static public function splitUrl($url)
- {
- $matches = $split_arr = array();
- $n = preg_match("#://[^/]+(/)#",$url, $matches, PREG_OFFSET_CAPTURE);
- if( $n )
- {
- $host = substr($url, 0, $matches[1][1]);
- $split_arr = array($host, $url);
- }
- else
- {
- $split_arr = array($url);
- }
- return $split_arr;
- }
-
- static public function getActionCategoryFromName($name)
- {
- $isUrl = false;
- // case the name is an URL we dont clean the name the same way
- if(Piwik_Common::isLookLikeUrl($name)
- || preg_match('#^mailto:#',$name))
- {
- $split = self::splitUrl($name);
- $isUrl = true;
- }
- else
+ $dataTable = Piwik_ArchiveProcessing_Day::generateDataTable($this->actionsTablesByType[Piwik_Tracker_Action::TYPE_OUTLINK]);
+ $s = $dataTable->getSerialized( $maximumRowsInDataTableLevelZero, $maximumRowsInSubDataTable );
+ $record = new Piwik_ArchiveProcessing_Record_BlobArray('Actions_outlink', $s);
+
+ unset($this->actionsTablesByType);
+ }
+
+ static public function splitUrl($url)
+ {
+ $matches = $split_arr = array();
+ $n = preg_match("#://[^/]+(/)#",$url, $matches, PREG_OFFSET_CAPTURE);
+ if( $n )
+ {
+ $host = substr($url, 0, $matches[1][1]);
+ $split_arr = array($host, $url);
+ }
+ else
+ {
+ $split_arr = array($url);
+ }
+ return $split_arr;
+ }
+
+ static public function getActionCategoryFromName($name)
+ {
+ $isUrl = false;
+ // case the name is an URL we dont clean the name the same way
+ if(Piwik_Common::isLookLikeUrl($name)
+ || preg_match('#^mailto:#',$name))
+ {
+ $split = self::splitUrl($name);
+ $isUrl = true;
+ }
+ else
{
if(empty(self::$actionCategoryDelimiter))
{
$split = array($name);
}
else
- {
+ {
$split = explode(self::$actionCategoryDelimiter, $name, self::$limitLevelSubCategory);
- }
- }
- return array( $isUrl, $split);
- }
-
-
- protected function updateActionsTableWithRowQuery($query)
- {
- $rowsProcessed = 0;
-
- while( $row = $query->fetch() )
- {
- // split the actions by category
- $returned = $this->getActionCategoryFromName($row['name']);
- $aActions = $returned[1];
- $isUrl = $returned[0];
-
- // we work on the root table of the given TYPE (either ACTION or DOWNLOAD or OUTLINK etc.)
- $currentTable =& $this->actionsTablesByType[$row['type']];
-
- // go to the level of the subcategory
- $end = count($aActions)-1;
- for($level = 0 ; $level < $end; $level++)
- {
- $actionCategory = $aActions[$level];
- $currentTable =& $currentTable[$actionCategory];
- }
- $actionName = $aActions[$end];
-
- // create a new element in the array for the page
- // we are careful to prefix the pageName with some value so that if a page has the same name
- // as a category we don't overwrite or do other silly things
-
- // if the page name is not a URL we add a / before
- if( !$isUrl )
- {
- // we know that the concatenation of a space and the name of the action
- // will always be unique as all the action names have been trimmed before reaching this point
- $actionName = '/' . $actionName;
- }
- else
- {
- $actionName = ' ' . $actionName;
- }
-
- // currentTable is now the array element corresponding the the action
- // at this point we may be for example at the 4th level of depth in the hierarchy
- $currentTable =& $currentTable[$actionName];
-
- // add the row to the matching sub category subtable
- if(!($currentTable instanceof Piwik_DataTable_Row))
- {
- $currentTable = new Piwik_DataTable_Row(
- array( Piwik_DataTable_Row::COLUMNS =>
- array( 'label' => (string)$actionName,
- 'full_url' => (string)$row['name'],
- )
- )
- );
- }
-
- foreach($row as $name => $value)
- {
- // we don't add this information as itnot pertinent
- // name is already set as the label // and it has been cleaned from the categories and extracted from the initial string
- // type is used to partition the different actions type in different table. Adding the info to the row would be a duplicate.
- if($name != 'name' && $name != 'type')
- {
- // in some very rare case, we actually have twice the same action name with 2 different idaction
- // this happens when 2 visitors visit the same new page at the same time, there is a SELECT and an INSERT for each new page,
- // and in between the two the other visitor comes.
- // here we handle the case where there is already a row for this action name, if this is the case we add the value
- if(($alreadyValue = $currentTable->getColumn($name)) !== false)
- {
- $currentTable->setColumn($name, $alreadyValue+$value);
- }
- else
- {
- $currentTable->addColumn($name, $value);
- }
- }
- }
-
- // if the exit_action was not recorded properly in the log_link_visit_action
- // there would be an error message when getting the nb_hits column
- // we must fake the record and add the columns
- if($currentTable->getColumn('nb_hits') === false)
- {
- // to test this code: delete the entries in log_link_action_visit for
- // a given exit_idaction
- foreach($this->defaultRow->getColumns() as $name => $value)
- {
- $currentTable->addColumn($name, $value);
- }
- }
- // simple count
- $rowsProcessed++;
- }
-
- // just to make sure php copies the last $currentTable in the $parentTable array
- $currentTable =& $this->actionsTablesByType;
-
- return $rowsProcessed;
- }
-}
-
+ }
+ }
+ return array( $isUrl, $split);
+ }
+
+
+ protected function updateActionsTableWithRowQuery($query)
+ {
+ $rowsProcessed = 0;
+
+ while( $row = $query->fetch() )
+ {
+ // split the actions by category
+ $returned = $this->getActionCategoryFromName($row['name']);
+ $aActions = $returned[1];
+ $isUrl = $returned[0];
+
+ // we work on the root table of the given TYPE (either ACTION or DOWNLOAD or OUTLINK etc.)
+ $currentTable =& $this->actionsTablesByType[$row['type']];
+
+ // go to the level of the subcategory
+ $end = count($aActions)-1;
+ for($level = 0 ; $level < $end; $level++)
+ {
+ $actionCategory = $aActions[$level];
+ $currentTable =& $currentTable[$actionCategory];
+ }
+ $actionName = $aActions[$end];
+
+ // create a new element in the array for the page
+ // we are careful to prefix the pageName with some value so that if a page has the same name
+ // as a category we don't overwrite or do other silly things
+
+ // if the page name is not a URL we add a / before
+ if( !$isUrl )
+ {
+ // we know that the concatenation of a space and the name of the action
+ // will always be unique as all the action names have been trimmed before reaching this point
+ $actionName = '/' . $actionName;
+ }
+ else
+ {
+ $actionName = ' ' . $actionName;
+ }
+
+ // currentTable is now the array element corresponding the the action
+ // at this point we may be for example at the 4th level of depth in the hierarchy
+ $currentTable =& $currentTable[$actionName];
+
+ // add the row to the matching sub category subtable
+ if(!($currentTable instanceof Piwik_DataTable_Row))
+ {
+ $currentTable = new Piwik_DataTable_Row(
+ array( Piwik_DataTable_Row::COLUMNS =>
+ array( 'label' => (string)$actionName,
+ 'full_url' => (string)$row['name'],
+ )
+ )
+ );
+ }
+
+ foreach($row as $name => $value)
+ {
+ // we don't add this information as itnot pertinent
+ // name is already set as the label // and it has been cleaned from the categories and extracted from the initial string
+ // type is used to partition the different actions type in different table. Adding the info to the row would be a duplicate.
+ if($name != 'name' && $name != 'type')
+ {
+ // in some very rare case, we actually have twice the same action name with 2 different idaction
+ // this happens when 2 visitors visit the same new page at the same time, there is a SELECT and an INSERT for each new page,
+ // and in between the two the other visitor comes.
+ // here we handle the case where there is already a row for this action name, if this is the case we add the value
+ if(($alreadyValue = $currentTable->getColumn($name)) !== false)
+ {
+ $currentTable->setColumn($name, $alreadyValue+$value);
+ }
+ else
+ {
+ $currentTable->addColumn($name, $value);
+ }
+ }
+ }
+
+ // if the exit_action was not recorded properly in the log_link_visit_action
+ // there would be an error message when getting the nb_hits column
+ // we must fake the record and add the columns
+ if($currentTable->getColumn('nb_hits') === false)
+ {
+ // to test this code: delete the entries in log_link_action_visit for
+ // a given exit_idaction
+ foreach($this->defaultRow->getColumns() as $name => $value)
+ {
+ $currentTable->addColumn($name, $value);
+ }
+ }
+ // simple count
+ $rowsProcessed++;
+ }
+
+ // just to make sure php copies the last $currentTable in the $parentTable array
+ $currentTable =& $this->actionsTablesByType;
+
+ return $rowsProcessed;
+ }
+}
+
diff --git a/plugins/Actions/Controller.php b/plugins/Actions/Controller.php
index 4957756f3c..20e160f927 100644
--- a/plugins/Actions/Controller.php
+++ b/plugins/Actions/Controller.php
@@ -45,7 +45,6 @@ class Piwik_Actions_Controller extends Piwik_Controller
__FUNCTION__,
'Actions.getActions',
'getActionsSubDataTable' );
-
return $this->renderView($view, $fetch);
}
@@ -117,8 +116,6 @@ class Piwik_Actions_Controller extends Piwik_Controller
$currentMethod,
$methodToCall,
$subMethod );
- $view->setColumnTranslation('nb_hits', Piwik_Translate('General_ColumnPageviews'));
- $view->setColumnTranslation('nb_uniq_visitors', Piwik_Translate('General_ColumnUniquePageviews'));
$view->setTemplate('CoreHome/templates/datatable_actions.tpl');
if(Piwik_Common::getRequestVar('idSubtable', -1) != -1)
@@ -132,25 +129,24 @@ class Piwik_Actions_Controller extends Piwik_Controller
$view->setTemplate('CoreHome/templates/datatable_actions_recursive.tpl');
}
$view->disableSort();
-
- $view->setSortedColumn( 'nb_hits', 'desc' );
-
$view->disableOffsetInformation();
+ $view->setLimit( 100 );
$view->setColumnsToDisplay( array('label','nb_uniq_visitors','nb_hits') );
- $view->setLimit( 100 );
+ $view->setSortedColumn( 'nb_uniq_visitors', 'desc' );
+ $view->setColumnTranslation('nb_hits', Piwik_Translate('General_ColumnPageviews'));
+ $view->setColumnTranslation('nb_uniq_visitors', Piwik_Translate('General_ColumnUniquePageviews'));
+
// computing minimum value to exclude
require_once "VisitsSummary/Controller.php";
$visitsInfo = Piwik_VisitsSummary_Controller::getVisitsSummary();
$nbActions = $visitsInfo->getColumn('nb_actions');
$nbActionsLowPopulationThreshold = floor(0.02 * $nbActions); // 2 percent of the total number of actions
-
// we remove 1 to make sure some actions/downloads are displayed in the case we have a very few of them
// and each of them has 1 or 2 hits...
$nbActionsLowPopulationThreshold = min($visitsInfo->getColumn('max_actions')-1, $nbActionsLowPopulationThreshold-1);
- $view->setExcludeLowPopulation( $nbActionsLowPopulationThreshold, 'nb_hits' );
-
+ $view->setExcludeLowPopulation( 'nb_hits', $nbActionsLowPopulationThreshold );
$view->main();
// we need to rewrite the phpArray so it contains all the recursive arrays
diff --git a/plugins/CoreAdminHome/templates/header.tpl b/plugins/CoreAdminHome/templates/header.tpl
index 8ed9472766..55762dccb3 100644
--- a/plugins/CoreAdminHome/templates/header.tpl
+++ b/plugins/CoreAdminHome/templates/header.tpl
@@ -18,6 +18,7 @@
<link rel="stylesheet" type="text/css" href="themes/default/common.css" />
<link rel="stylesheet" type="text/css" href="plugins/CoreAdminHome/templates/styles.css" />
+<link rel="stylesheet" type="text/css" href="libs/jquery/jquery-calendar.css" />
<link rel="shortcut icon" href="plugins/CoreHome/templates/images/favicon.ico">
diff --git a/plugins/CoreAdminHome/templates/styles.css b/plugins/CoreAdminHome/templates/styles.css
index 6bf24d65b4..758e61f7b8 100644
--- a/plugins/CoreAdminHome/templates/styles.css
+++ b/plugins/CoreAdminHome/templates/styles.css
@@ -14,16 +14,6 @@ a {
color: black;
}
-#ajaxError {
- color: red;
- text-align: center;
- font-weight: bold;
- width: 550px;
- border: 3px solid red;
- margin: 10px;
- padding: 10px;
-}
-
table.admin {
font-size: 0.9em;
font-family: Arial, Helvetica, verdana sans-serif;
diff --git a/plugins/CoreHome/Controller.php b/plugins/CoreHome/Controller.php
index 713bba8e19..185cdfb2c2 100644
--- a/plugins/CoreHome/Controller.php
+++ b/plugins/CoreHome/Controller.php
@@ -1,56 +1,67 @@
-<?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 561 2008-07-21 00:00:35Z matt $
- *
- * @package Piwik_CoreHome
- *
- */
-
-require_once "API/Request.php";
-require_once "ViewDataTable.php";
-
-/**
- * @package Piwik_CoreHome
- */
-class Piwik_CoreHome_Controller extends Piwik_Controller
-{
- function getDefaultAction()
- {
- return 'redirectToIndex';
- }
+<?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 561 2008-07-21 00:00:35Z matt $
+ *
+ * @package Piwik_CoreHome
+ *
+ */
+
+require_once "API/Request.php";
+require_once "ViewDataTable.php";
+
+/**
+ * @package Piwik_CoreHome
+ */
+class Piwik_CoreHome_Controller extends Piwik_Controller
+{
+ function getDefaultAction()
+ {
+ return 'redirectToIndex';
+ }
+
+ function redirectToIndex()
+ {
+ // redirect to Login only for anonymous user
+ if((bool)Zend_Registry::get('config')->General->default_module_login == true
+ && Piwik::getCurrentUserLogin() == 'anonymous')
+ {
+ return Piwik_FrontController::dispatch('Login', false);
+ }
+ parent::redirectToIndex('CoreHome', 'index');
+ }
- protected function setGeneralVariablesView($view)
- {
- parent::setGeneralVariablesView($view);
- $view->menu = Piwik_GetMenu();
- }
+ protected function setGeneralVariablesView($view)
+ {
+ parent::setGeneralVariablesView($view);
+ $view->menu = Piwik_GetMenu();
+ }
- public function showInContext()
- {
- $controllerName = Piwik_Common::getRequestVar('moduleToLoad');
- $actionName = Piwik_Common::getRequestVar('actionToLoad', 'index');
-
- $view = $this->getDefaultIndexView();
- $view->basicHtmlView = true;
- $view->content = Piwik_FrontController::getInstance()->fetchDispatch( $controllerName, $actionName );
- echo $view->render();
- }
-
- protected function getDefaultIndexView()
- {
- $view = new Piwik_View('CoreHome/templates/index.tpl');
- $this->setGeneralVariablesView($view);
+ public function showInContext()
+ {
+ $controllerName = Piwik_Common::getRequestVar('moduleToLoad');
+ $actionName = Piwik_Common::getRequestVar('actionToLoad', 'index');
+
+ $view = $this->getDefaultIndexView();
+ $view->basicHtmlView = true;
+ $view->content = Piwik_FrontController::getInstance()->fetchDispatch( $controllerName, $actionName );
+ echo $view->render();
+ }
+
+ protected function getDefaultIndexView()
+ {
+ $view = new Piwik_View('CoreHome/templates/index.tpl');
+ $this->setGeneralVariablesView($view);
$view->content = '';
- return $view;
+ return $view;
+ }
+
+ public function index()
+ {
+ $view = $this->getDefaultIndexView();
+ echo $view->render();
}
-
- public function index()
- {
- $view = $this->getDefaultIndexView();
- echo $view->render();
- }
-}
+}
diff --git a/plugins/CoreHome/templates/calendar.js b/plugins/CoreHome/templates/calendar.js
index 8a5b20ef1b..db71c42fe8 100644
--- a/plugins/CoreHome/templates/calendar.js
+++ b/plugins/CoreHome/templates/calendar.js
@@ -166,7 +166,7 @@ $(document).ready(function(){
_pk_translate('CoreHome_MonthSeptember'),
_pk_translate('CoreHome_MonthOctober'),
_pk_translate('CoreHome_MonthNovember'),
- _pk_translate('CoreHome_MonthDecemeber')]
+ _pk_translate('CoreHome_MonthDecember')]
},
currentDate);
diff --git a/plugins/CoreHome/templates/cloud.tpl b/plugins/CoreHome/templates/cloud.tpl
index 8989e48a85..b3c208ccc0 100644
--- a/plugins/CoreHome/templates/cloud.tpl
+++ b/plugins/CoreHome/templates/cloud.tpl
@@ -1,4 +1,4 @@
-<div id="{$id}">
+<div id="{$properties.uniqueId}">
{literal}
<style>
diff --git a/plugins/CoreHome/templates/datatable.css b/plugins/CoreHome/templates/datatable.css
index 364e24cd69..5a3c3577a7 100644
--- a/plugins/CoreHome/templates/datatable.css
+++ b/plugins/CoreHome/templates/datatable.css
@@ -303,20 +303,6 @@ table thead div {
padding: 0.5em;
}
-#tooltip h3 {
- margin:0;
- padding:0;
-}
-#tooltip {
- position: absolute;
- z-index: 3000;
- border: 1px solid #111;
- background-color: #eee;
- opacity: 0.85;
- font-size: 0.7em;
- padding:7px;
-}
-
/* Actions table */
table.dataTableActions tr td.labelodd {
background-image: none;
diff --git a/plugins/CoreHome/templates/datatable.js b/plugins/CoreHome/templates/datatable.js
index c8b7c26079..b24a8f1254 100644
--- a/plugins/CoreHome/templates/datatable.js
+++ b/plugins/CoreHome/templates/datatable.js
@@ -1,5 +1,5 @@
//-----------------------------------------------------------------------------
-// Data Table
+// DataTable
//-----------------------------------------------------------------------------
//A list of all our DataTables
//Test if the object have already been initialized (multiple includes)
@@ -63,8 +63,7 @@ dataTable.prototype =
'filter_pattern',
'filter_column_recursive',
'filter_pattern_recursive',
- 'filter_excludelowpop',
- 'filter_excludelowpop_value',
+ 'enable_filter_excludelowpop',
'filter_offset',
'filter_limit',
'filter_sort_column',
@@ -216,7 +215,6 @@ dataTable.prototype =
handleSort: function(domElem)
{
var self = this;
-
if( self.param.enable_sort )
{
$('.sortable', domElem).click(
@@ -255,19 +253,19 @@ dataTable.prototype =
.each(
function()
{
- if(typeof self.param.filter_excludelowpop == 'undefined')
+ if(typeof self.param.enable_filter_excludelowpop == 'undefined')
{
- self.param.filter_excludelowpop = 0;
+ self.param.enable_filter_excludelowpop = 0;
}
- if(Number(self.param.filter_excludelowpop) != 0)
+ if(Number(self.param.enable_filter_excludelowpop) != 0)
{
string = _pk_translate('CoreHome_IncludeAllPopulation');
- self.param.filter_excludelowpop = 1;
+ self.param.enable_filter_excludelowpop = 1;
}
else
{
string = _pk_translate('CoreHome_ExcludeLowPopulation');
- self.param.filter_excludelowpop = 0;
+ self.param.enable_filter_excludelowpop = 0;
}
$(this).html(string);
}
@@ -276,7 +274,7 @@ dataTable.prototype =
.click(
function()
{
- self.param.filter_excludelowpop = 1 - self.param.filter_excludelowpop;
+ self.param.enable_filter_excludelowpop = 1 - self.param.enable_filter_excludelowpop;
self.param.filter_offset = 0;
self.reloadAjaxDataTable(true, callbackSuccess);
}
@@ -484,6 +482,19 @@ dataTable.prototype =
}
);
+ $('#tableGoals', domElem)
+ .show()
+ .click(
+ function(){
+ // we only reset the limit filter, in case switch to table view from cloud view where limit is custom set to 30
+ // this value is stored in config file General->dataTable_default_limit but this is more an edge case so ok to set it to 10
+ delete self.param.filter_limit;
+ delete self.param.enable_filter_excludelowpop;
+ self.param.viewDataTable = 'tableGoals';
+ self.reloadAjaxDataTable();
+ }
+ );
+
$('#tableAllColumnsSwitch', domElem)
.show()
.click(
@@ -492,6 +503,11 @@ dataTable.prototype =
// this value is stored in config file General->dataTable_default_limit but this is more an edge case so ok to set it to 10
delete self.param.filter_limit;
self.param.viewDataTable = self.param.viewDataTable == 'table' ? 'tableAllColumns' : 'table';
+ // when switching to display simple table, do not exclude low pop by default
+ if(self.param.viewDataTable == 'table')
+ {
+ self.param.enable_filter_excludelowpop = 0;
+ }
self.reloadAjaxDataTable();
}
);
@@ -505,12 +521,17 @@ dataTable.prototype =
var method = $(this).attr('methodToCall');
var filter_limit = $(this).attr('filter_limit');
+ var param_date = self.param.date;
+ var date = $(this).attr('date');
+ if(typeof date != 'undefined') {
+ param_date = date;
+ }
var str = '?module=API'
+'&method='+method
+'&format='+format
+'&idSite='+self.param.idSite
+'&period='+self.param.period
- +'&date='+self.param.date
+ +'&date='+param_date
+'&token_auth='+piwik.token_auth;
if( filter_limit )
{
@@ -580,7 +601,7 @@ dataTable.prototype =
var urlToLink = $(urlLinkDom).html();
$(urlLinkDom).remove();
- var truncationOffsetBecauseImageIsPrepend = -2;
+ var truncationOffsetBecauseImageIsPrepend = -2; //website subtable needs -9.
self.truncate( $(this), truncationOffsetBecauseImageIsPrepend );
if( urlToLink.match("javascript:") )
@@ -649,7 +670,7 @@ dataTable.prototype =
var filtersToRestore = self.resetAllFilters();
self.param.idSubtable = idSubTable;
- self.param.action = self.param.actionToLoadTheSubTable;
+ self.param.action = self.param.controllerActionCalledWhenRequestSubTable;
self.reloadAjaxDataTable(false);
self.param.action = savedActionVariable;
@@ -862,7 +883,7 @@ actionDataTable.prototype =
delete self.param.filter_pattern;
self.param.idSubtable = idSubTable;
- self.param.action = self.param.actionToLoadTheSubTable;
+ self.param.action = self.param.controllerActionCalledWhenRequestSubTable;
self.reloadAjaxDataTable(false, function(resp){self.actionsSubDataTableLoaded(resp)});
self.param.action = savedActionVariable;
diff --git a/plugins/CoreHome/templates/datatable.tpl b/plugins/CoreHome/templates/datatable.tpl
index 49e233f82e..55291ee9ea 100644
--- a/plugins/CoreHome/templates/datatable.tpl
+++ b/plugins/CoreHome/templates/datatable.tpl
@@ -1,12 +1,12 @@
-<div id="{$id}">
- <div class="{if isset($javascriptVariablesToSet.idSubtable)&& $javascriptVariablesToSet.idSubtable!=0}sub{/if}{if $javascriptVariablesToSet.viewDataTable=='tableAllColumns'}dataTableAllColumnsWrapper{else}dataTableWrapper{/if}">
+<div id="{$properties.uniqueId}">
+ <div class="{if isset($javascriptVariablesToSet.idSubtable)&& $javascriptVariablesToSet.idSubtable!=0}sub{/if}{if $javascriptVariablesToSet.viewDataTable=='tableAllColumns'}dataTableAllColumnsWrapper{elseif $javascriptVariablesToSet.viewDataTable=='tableGoals'}dataTableAllColumnsWrapper{else}dataTableWrapper{/if}">
{if isset($arrayDataTable.result) and $arrayDataTable.result == 'error'}
{$arrayDataTable.message}
{else}
{if count($arrayDataTable) == 0}
<div id="emptyDatatable">{'CoreHome_TableNoData'|translate}</div>
{else}
- <a name="{$id}"></a>
+ <a name="{$properties.uniqueId}"></a>
<table cellspacing="0" class="dataTable">
<thead>
<tr>
@@ -18,11 +18,11 @@
<tbody>
{foreach from=$arrayDataTable item=row}
- <tr {if $row.idsubdatatable}class="subDataTable" id="{$row.idsubdatatable}"{/if}>
+ <tr {if $row.idsubdatatable && $javascriptVariablesToSet.controllerActionCalledWhenRequestSubTable != null}class="subDataTable" id="{$row.idsubdatatable}"{/if}>
{foreach from=$dataTableColumns item=column}
<td>
{if !$row.idsubdatatable && $column.name=='label' && isset($row.metadata.url)}<span id="urlLink">{$row.metadata.url}</span>{/if}
-{if $column.name=='label' && isset($row.metadata.logo)}<img {if isset($row.metadata.logoWidth)}width="{$row.metadata.logoWidth}"{/if} {if isset($row.metadata.logoHeight)}height="{$row.metadata.logoHeight}"{/if} src="{$row.metadata.logo}" />{/if}
+{if $column.name=='label'}{logoHtml metadata=$row.metadata alt=$row.columns.label}{/if}
{* sometimes all columns are not set in the datatable, we assume the value 0 *}
{if isset($row.columns[$column.name])}{$row.columns[$column.name]}{else}0{/if}
</td>
diff --git a/plugins/CoreHome/templates/datatable_actions.tpl b/plugins/CoreHome/templates/datatable_actions.tpl
index 94341cddff..c2dbe1868f 100644
--- a/plugins/CoreHome/templates/datatable_actions.tpl
+++ b/plugins/CoreHome/templates/datatable_actions.tpl
@@ -1,4 +1,4 @@
-<div id="{$id}">
+<div id="{$properties.uniqueId}">
<div class="dataTableActionsWrapper">
{if isset($arrayDataTable.result) and $arrayDataTable.result == 'error'}
{$arrayDataTable.message}
diff --git a/plugins/CoreHome/templates/datatable_actions_js.tpl b/plugins/CoreHome/templates/datatable_actions_js.tpl
index 5bf5ed2bca..568fe83d7b 100644
--- a/plugins/CoreHome/templates/datatable_actions_js.tpl
+++ b/plugins/CoreHome/templates/datatable_actions_js.tpl
@@ -1,12 +1,12 @@
<script type="text/javascript" defer="defer">
$(document).ready(function(){literal}{{/literal}
- actionDataTables['{$id}'] = new actionDataTable();
- actionDataTables['{$id}'].param = {literal}{{/literal}
+ actionDataTables['{$properties.uniqueId}'] = new actionDataTable();
+ actionDataTables['{$properties.uniqueId}'].param = {literal}{{/literal}
{foreach from=$javascriptVariablesToSet key=name item=value name=loop}
{$name}: '{$value}'{if !$smarty.foreach.loop.last},{/if}
{/foreach}
{literal}};{/literal}
- actionDataTables['{$id}'].init('{$id}');
+ actionDataTables['{$properties.uniqueId}'].init('{$properties.uniqueId}');
{literal}}{/literal});
</script>
diff --git a/plugins/CoreHome/templates/datatable_actions_recursive.tpl b/plugins/CoreHome/templates/datatable_actions_recursive.tpl
index bcec62eb2c..01a22255ed 100644
--- a/plugins/CoreHome/templates/datatable_actions_recursive.tpl
+++ b/plugins/CoreHome/templates/datatable_actions_recursive.tpl
@@ -1,4 +1,4 @@
-<div id="{$id}">
+<div id="{$properties.uniqueId}">
<div class="dataTableActionsWrapper">
{if isset($arrayDataTable.result) and $arrayDataTable.result == 'error'}
{$arrayDataTable.message}
diff --git a/plugins/CoreHome/templates/datatable_actions_subdatable.tpl b/plugins/CoreHome/templates/datatable_actions_subdatable.tpl
index 39e103f691..1cfe58edc9 100644
--- a/plugins/CoreHome/templates/datatable_actions_subdatable.tpl
+++ b/plugins/CoreHome/templates/datatable_actions_subdatable.tpl
@@ -1,4 +1,4 @@
-<tr id="{$id}"></tr>
+<tr id="{$properties.uniqueId}"></tr>
{if isset($arrayDataTable.result) and $arrayDataTable.result == 'error'}
{$arrayDataTable.message}
{else}
diff --git a/plugins/CoreHome/templates/datatable_footer.tpl b/plugins/CoreHome/templates/datatable_footer.tpl
index 355fbe2a3e..1d92fbcad5 100644
--- a/plugins/CoreHome/templates/datatable_footer.tpl
+++ b/plugins/CoreHome/templates/datatable_footer.tpl
@@ -23,10 +23,11 @@
<span id="exportToFormat" style="display:none;padding-left:4px;">
<img width="16" height="16" src="{$piwikUrl}themes/default/images/export.png" title="{'General_Export'|translate}" />
<span id="linksExportToFormat" style="display:none;">
- <a target="_blank" class="exportToFormat" methodToCall="{$method}" format="CSV" filter_limit="100">CSV</a> |
- <a target="_blank" class="exportToFormat" methodToCall="{$method}" format="XML" filter_limit="100">XML</a> |
- <a target="_blank" class="exportToFormat" methodToCall="{$method}" format="JSON" filter_limit="100">Json</a> |
- <a target="_blank" class="exportToFormat" methodToCall="{$method}" format="PHP" filter_limit="100">Php</a>
+ <a target="_blank" class="exportToFormat" methodToCall="{$properties.apiMethodToRequestDataTable}" format="CSV" filter_limit="100">CSV</a> |
+ <a target="_blank" class="exportToFormat" methodToCall="{$properties.apiMethodToRequestDataTable}" format="XML" filter_limit="100">XML</a> |
+ <a target="_blank" class="exportToFormat" methodToCall="{$properties.apiMethodToRequestDataTable}" format="JSON" filter_limit="100">Json</a> |
+ <a target="_blank" class="exportToFormat" methodToCall="{$properties.apiMethodToRequestDataTable}" format="PHP" filter_limit="100">Php</a> |
+ <a target="_blank" class="exportToFormat" methodToCall="{$properties.apiMethodToRequestDataTable}" format="RSS" filter_limit="100" date="last10"><img border="0" src="{$piwikUrl}themes/default/images/feed.png"></a>
</span>
<a class="viewDataTable" format="cloud"><img width="16" height="16" src="{$piwikUrl}themes/default/images/tagcloud.png" title="{'General_TagCloud'|translate}" /></a>
<a class="viewDataTable" format="graphVerticalBar"><img width="16" height="16" src="{$piwikUrl}themes/default/images/chart_bar.png" title="{'General_VBarGraph'|translate}" /></a>
@@ -44,6 +45,13 @@
{/if}
</span>
{/if}
+ {if $properties.show_goals}
+ <span id="tableGoals" style="display:none;float:right;padding-right:4px;">
+ {if $javascriptVariablesToSet.viewDataTable != 'tableGoals'}
+ <img title="View Goals" src="{$piwikUrl}themes/default/images/goal.png" />
+ {/if}
+ </span>
+ {/if}
</span>
</div>
{/if}
diff --git a/plugins/CoreHome/templates/datatable_js.tpl b/plugins/CoreHome/templates/datatable_js.tpl
index c3e5c9e5c3..acae875cf4 100644
--- a/plugins/CoreHome/templates/datatable_js.tpl
+++ b/plugins/CoreHome/templates/datatable_js.tpl
@@ -1,13 +1,13 @@
<script type="text/javascript" defer="defer">
$(document).ready(function(){literal}{{/literal}
- dataTables['{$id}'] = new dataTable();
- dataTables['{$id}'].param = {literal}{{/literal}
+ dataTables['{$properties.uniqueId}'] = new dataTable();
+ dataTables['{$properties.uniqueId}'].param = {literal}{{/literal}
{foreach from=$javascriptVariablesToSet key=name item=value name=loop}
{$name}: '{$value}'{if !$smarty.foreach.loop.last},{/if}
{/foreach}
{literal}};{/literal}
- dataTables['{$id}'].init('{$id}');
+ dataTables['{$properties.uniqueId}'].init('{$properties.uniqueId}');
{literal}}{/literal});
</script>
diff --git a/plugins/CoreHome/templates/graph.tpl b/plugins/CoreHome/templates/graph.tpl
index 74e6df6e1f..4e2bd9cda4 100644
--- a/plugins/CoreHome/templates/graph.tpl
+++ b/plugins/CoreHome/templates/graph.tpl
@@ -1,4 +1,4 @@
-<div id="{$id}">
+<div id="{$properties.uniqueId}">
<div class="{if $graphType=='evolution'}dataTableGraphEvolutionWrapper{else}dataTableGraphWrapper{/if}">
{$jsInvocationTag}
diff --git a/plugins/DBStats/API.php b/plugins/DBStats/API.php
index b041b9a227..5c26a6700e 100644
--- a/plugins/DBStats/API.php
+++ b/plugins/DBStats/API.php
@@ -13,7 +13,7 @@
*
* @package Piwik_DBStats_API
*/
-class Piwik_DBStats_API extends Piwik_Apiable
+class Piwik_DBStats_API
{
static private $instance = null;
static public function getInstance()
@@ -44,23 +44,6 @@ class Piwik_DBStats_API extends Piwik_Apiable
return $status;
}
- static private function get_size($size)
- {
- $bytes = array('','K','M','G','T');
- foreach($bytes as $val)
- {
- if($size > 1024)
- {
- $size = $size / 1024;
- }
- else
- {
- break;
- }
- }
- return round($size, 1)." ".$val;
- }
-
static public function getTableStatus($table, $field = '')
{
Piwik::checkUserIsSuperUser();
@@ -80,30 +63,31 @@ class Piwik_DBStats_API extends Piwik_Apiable
static public function getAllTablesStatus()
{
- Piwik::isUserIsSuperUser();
+ Piwik::checkUserIsSuperUser();
$db = Zend_Registry::get('db');
// http://dev.mysql.com/doc/refman/5.1/en/show-table-status.html
$tablesPiwik = Piwik::getTablesInstalled();
$total = array('Name' => 'Total', 'Data_length' => 0, 'Index_length' => 0, 'Rows' => 0);
- foreach($tablesPiwik as $table)
+ $table = array();
+ foreach($tablesPiwik as $tableName)
{
- $t = self::getTableStatus($table);
+ $t = self::getTableStatus($tableName);
$total['Data_length'] += $t['Data_length'];
$total['Index_length'] += $t['Index_length'];
$total['Rows'] += $t['Rows'];
- $t['Total_length'] = self::get_size($t['Index_length']+$t['Data_length']);
- $t['Data_length'] = self::get_size($t['Data_length']);
- $t['Index_length'] = self::get_size($t['Index_length']);
- $t['Rows'] = self::get_size($t['Rows']);
- $tables[] = $t;
+ $t['Total_length'] = Piwik::getPrettySizeFromBytes($t['Index_length']+$t['Data_length']);
+ $t['Data_length'] = Piwik::getPrettySizeFromBytes($t['Data_length']);
+ $t['Index_length'] = Piwik::getPrettySizeFromBytes($t['Index_length']);
+ $t['Rows'] = Piwik::getPrettySizeFromBytes($t['Rows']);
+ $table[] = $t;
}
- $total['Total_length'] = self::get_size($total['Data_length']+$total['Index_length']);
- $total['Data_length'] = self::get_size($total['Data_length']);
- $total['Index_length'] = self::get_size($total['Index_length']);
- $total['TotalRows'] = self::get_size($total['Rows']);
- $tables['Total'] = $total;
+ $total['Total_length'] = Piwik::getPrettySizeFromBytes($total['Data_length']+$total['Index_length']);
+ $total['Data_length'] = Piwik::getPrettySizeFromBytes($total['Data_length']);
+ $total['Index_length'] = Piwik::getPrettySizeFromBytes($total['Index_length']);
+ $total['TotalRows'] = Piwik::getPrettySizeFromBytes($total['Rows']);
+ $table['Total'] = $total;
- return $tables;
+ return $table;
}
}
diff --git a/plugins/DBStats/templates/DBStats.tpl b/plugins/DBStats/templates/DBStats.tpl
index 27f0769dcd..e82e095683 100644
--- a/plugins/DBStats/templates/DBStats.tpl
+++ b/plugins/DBStats/templates/DBStats.tpl
@@ -13,10 +13,11 @@
<th>{'DBStats_RowNumber'|translate}</th>
<th>{'DBStats_DataSize'|translate}</th>
<th>{'DBStats_IndexSize'|translate}</th>
+ <th>{'DBStats_TotalSize'|translate}</th>
</thead>
<tbody id="tables">
{foreach from=$tablesStatus key=index item=table}
- <tr {if $table.Name == 'Total'}class="active"{/if}>
+ <tr {if $table.Name == 'Total'}class="active" style="font-weight:bold;"{/if}>
<td>
{$table.Name}
</td>
@@ -29,6 +30,9 @@
<td>
{$table.Index_length}b
</td>
+ <td>
+ {$table.Total_length}b
+ </td>
</tr>
{/foreach}
</tbody>
diff --git a/plugins/ExampleAPI/API.php b/plugins/ExampleAPI/API.php
index 8a6d19af96..ca052d42aa 100644
--- a/plugins/ExampleAPI/API.php
+++ b/plugins/ExampleAPI/API.php
@@ -20,7 +20,7 @@
*
* @package Piwik_ExamplePlugin
*/
-class Piwik_ExampleAPI_API extends Piwik_Apiable
+class Piwik_ExampleAPI_API
{
static private $instance = null;
static public function getInstance()
@@ -35,6 +35,7 @@ class Piwik_ExampleAPI_API extends Piwik_Apiable
public function getPiwikVersion()
{
+ Piwik::checkUserHasSomeViewAccess();
return Piwik_Version::VERSION;
}
diff --git a/plugins/ExamplePlugin/ExamplePlugin.php b/plugins/ExamplePlugin/ExamplePlugin.php
index 106a6cdbb8..a2cc37bf15 100644
--- a/plugins/ExamplePlugin/ExamplePlugin.php
+++ b/plugins/ExamplePlugin/ExamplePlugin.php
@@ -21,6 +21,24 @@ class Piwik_ExamplePlugin extends Piwik_Plugin
'version' => '0.1',
);
}
+
+ public function getListHooksRegistered()
+ {
+ return array(
+// 'Controller.renderView' => 'addUniqueVisitorsColumnToGivenReport',
+ );
+ }
+
+ function addUniqueVisitorsColumnToGivenReport($notification)
+ {
+ $view = $notification->getNotificationInfo();
+ $view = $view['view'];
+ if($view->getCurrentControllerName() == 'Referers'
+ && $view->getCurrentControllerAction() == 'getWebsites')
+ {
+ $view->addColumnToDisplay('nb_uniq_visitors');
+ }
+ }
}
// we register the widgets so they appear in the "Add a new widget" window in the dashboard
diff --git a/plugins/Goals/API.php b/plugins/Goals/API.php
new file mode 100644
index 0000000000..5b1b849f01
--- /dev/null
+++ b/plugins/Goals/API.php
@@ -0,0 +1,227 @@
+<?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$
+ *
+ * @package Piwik_VisitsSummary
+ */
+
+/**
+ * @package Piwik_Goals
+ */
+class Piwik_Goals_API
+{
+ static private $instance = null;
+ static public function getInstance()
+ {
+ if (self::$instance == null)
+ {
+ $c = __CLASS__;
+ self::$instance = new $c();
+ }
+ return self::$instance;
+ }
+
+ static public function getGoals( $idSite )
+ {
+ $goals = Zend_Registry::get('db')->fetchAll("SELECT *
+ FROM ".Piwik_Common::prefixTable('goal')."
+ WHERE idsite = ?
+ AND deleted = 0", $idSite);
+ $cleanedGoals = array();
+ foreach($goals as &$goal)
+ {
+ unset($goal['idsite']);
+ $cleanedGoals[$goal['idgoal']] = $goal;
+ }
+ return $cleanedGoals;
+ }
+
+ public function addGoal( $idSite, $name, $matchAttribute, $pattern, $patternType, $caseSensitive, $revenue )
+ {
+ Piwik::checkUserHasAdminAccess($idSite);
+ // save in db
+ $db = Zend_Registry::get('db');
+ $idGoal = $db->fetchOne("SELECT max(idgoal) + 1
+ FROM ".Piwik::prefixTable('goal')."
+ WHERE idsite = ?", $idSite);
+ if($idGoal == false)
+ {
+ $idGoal = 1;
+ }
+ self::checkPatternIsValid($patternType, $pattern);
+ $name = self::checkName($name);
+ $pattern = self::checkPattern($pattern);
+ $db->insert(Piwik::prefixTable('goal'),
+ array(
+ 'idsite' => $idSite,
+ 'idgoal' => $idGoal,
+ 'name' => $name,
+ 'match_attribute' => $matchAttribute,
+ 'pattern' => $pattern,
+ 'pattern_type' => $patternType,
+ 'case_sensitive' => $caseSensitive,
+ 'revenue' => $revenue,
+ 'deleted' => 0,
+ ));
+ Piwik_Common::regenerateCacheWebsiteAttributes($idSite);
+ return $idGoal;
+ }
+
+ public function updateGoal( $idSite, $idGoal, $name, $matchAttribute, $pattern, $patternType, $caseSensitive, $revenue )
+ {
+ Piwik::checkUserHasAdminAccess($idSite);
+ $name = self::checkName($name);
+ $pattern = self::checkPattern($pattern);
+ self::checkPatternIsValid($patternType, $pattern);
+ Zend_Registry::get('db')->update( Piwik::prefixTable('goal'),
+ array(
+ 'name' => $name,
+ 'match_attribute' => $matchAttribute,
+ 'pattern' => $pattern,
+ 'pattern_type' => $patternType,
+ 'case_sensitive' => $caseSensitive,
+ 'revenue' => $revenue,
+ ),
+ "idsite = '$idSite' AND idgoal = '$idGoal'"
+ );
+ Piwik_Common::regenerateCacheWebsiteAttributes($idSite);
+ }
+
+ private function checkPatternIsValid($patternType, $pattern)
+ {
+ if($patternType == 'exact'
+ && substr($pattern, 0, 4) != 'http')
+ {
+ throw new Exception("If you choose 'exact match', the matching string must be a
+ URL starting with http:// or https://. For example, 'http://www.yourwebsite.com/newsletter/subscribed.html'.");
+ }
+ }
+
+ private function checkName($name)
+ {
+ return urldecode($name);
+ }
+
+ private function checkPattern($pattern)
+ {
+ return urldecode($pattern);
+ }
+
+ public function deleteGoal( $idSite, $idGoal )
+ {
+ Piwik::checkUserHasAdminAccess($idSite);
+ Zend_Registry::get('db')->query("UPDATE ".Piwik::prefixTable('goal')."
+ SET deleted = 1
+ WHERE idsite = ?
+ AND idgoal = ?",
+ array($idSite, $idGoal));
+ $db->query("DELETE FROM ".Piwik::prefixTable("log_conversion")." WHERE idgoal = ?", $idGoal);
+ Piwik_Common::regenerateCacheWebsiteAttributes($idSite);
+ }
+
+// public function getConversionsReturningVisitors( $idSite, $period, $date, $idGoal = false )
+// {
+//
+// }
+//
+// public function getConversionsNewVisitors( $idSite, $period, $date, $idGoal = false )
+// {
+//
+// }
+
+ // TODO
+ public function getConversionRateReturningVisitors( $idSite, $period, $date, $idGoal = false )
+ {
+ // visits converted for returning for all goals = call Frequency API
+ if($idGoal === false)
+ {
+ $request = new Piwik_API_Request("method=VisitFrequency.getConvertedVisitsReturning&idSite=$idSite&period=$period&date=$date&format=original");
+ $nbVisitsConvertedReturningVisitors = $request->process();
+ }
+ // visits converted for returning = nb conversion for this goal
+ else
+ {
+ $nbVisitsConvertedReturningVisitors = $this->getNumeric($idSite, $period, $date, Piwik_Goals::getRecordName('nb_conversions', $idGoal, 1));
+ }
+ // all returning visits
+ $request = new Piwik_API_Request("method=VisitFrequency.getVisitsReturning&idSite=$idSite&period=$period&date=$date&format=original");
+ $nbVisitsReturning = $request->process();
+// echo $nbVisitsConvertedReturningVisitors;
+// echo "<br>". $nbVisitsReturning;exit;
+ return $this->getPercentage($nbVisitsConvertedReturningVisitors, $nbVisitsReturning);
+ }
+
+ public function getConversionRateNewVisitors( $idSite, $period, $date, $idGoal = false )
+ {
+ // new visits converted for all goals = nb visits converted - nb visits converted for returning
+ if($idGoal == false)
+ {
+ $request = new Piwik_API_Request("method=VisitsSummary.getVisitsConverted&idSite=$idSite&period=$period&date=$date&format=original");
+ $convertedVisits = $request->process();
+ $request = new Piwik_API_Request("method=VisitFrequency.getConvertedVisitsReturning&idSite=$idSite&period=$period&date=$date&format=original");
+ $convertedReturningVisits = $request->process();
+ $convertedNewVisits = $convertedVisits - $convertedReturningVisits;
+ }
+ // new visits converted for a given goal = nb conversion for this goal for new visits
+ else
+ {
+ $convertedNewVisits = $this->getNumeric($idSite, $period, $date, Piwik_Goals::getRecordName('nb_conversions', $idGoal, 0));
+ }
+ // all new visits = all visits - all returning visits
+ $request = new Piwik_API_Request("method=VisitFrequency.getVisitsReturning&idSite=$idSite&period=$period&date=$date&format=original");
+ $nbVisitsReturning = $request->process();
+ $request = new Piwik_API_Request("method=VisitsSummary.getVisits&idSite=$idSite&period=$period&date=$date&format=original");
+ $nbVisits = $request->process();
+ $newVisits = $nbVisits - $nbVisitsReturning;
+ return $this->getPercentage($convertedNewVisits, $newVisits);
+ }
+
+ protected function getPercentage($a, $b)
+ {
+ if($b == 0)
+ {
+ return 0;
+ }
+ return round(100 * $a / $b, Piwik_Goals::ROUNDING_PRECISION);
+ }
+
+ public function get( $idSite, $period, $date, $idGoal = false )
+ {
+ Piwik::checkUserHasViewAccess( $idSite );
+ $archive = Piwik_Archive::build($idSite, $period, $date );
+ $toFetch = array( Piwik_Goals::getRecordName('nb_conversions', $idGoal),
+ Piwik_Goals::getRecordName('conversion_rate', $idGoal),
+ Piwik_Goals::getRecordName('revenue', $idGoal),
+ );
+ $dataTable = $archive->getDataTableFromNumeric($toFetch);
+ return $dataTable;
+ }
+
+ protected static function getNumeric( $idSite, $period, $date, $toFetch )
+ {
+ Piwik::checkUserHasViewAccess( $idSite );
+ $archive = Piwik_Archive::build($idSite, $period, $date );
+ $dataTable = $archive->getNumeric($toFetch);
+ return $dataTable;
+ }
+
+ public function getConversions( $idSite, $period, $date, $idGoal = false )
+ {
+ return self::getNumeric( $idSite, $period, $date, Piwik_Goals::getRecordName('nb_conversions', $idGoal));
+ }
+
+ public function getConversionRate( $idSite, $period, $date, $idGoal = false )
+ {
+ return self::getNumeric( $idSite, $period, $date, Piwik_Goals::getRecordName('conversion_rate', $idGoal));
+ }
+
+ public function getRevenue( $idSite, $period, $date, $idGoal = false )
+ {
+ return self::getNumeric( $idSite, $period, $date, Piwik_Goals::getRecordName('revenue', $idGoal));
+ }
+
+}
diff --git a/plugins/Goals/Controller.php b/plugins/Goals/Controller.php
new file mode 100644
index 0000000000..935d616258
--- /dev/null
+++ b/plugins/Goals/Controller.php
@@ -0,0 +1,150 @@
+<?php
+require_once "Goals/API.php";
+
+class Piwik_Goals_Controller extends Piwik_Controller
+{
+ const CONVERSION_RATE_PRECISION = 1;
+ function goalReport()
+ {
+ $idGoal = Piwik_Common::getRequestVar('idGoal', null, 'int');
+ $idSite = Piwik_Common::getRequestVar('idSite');
+ $goals = Piwik_Goals_API::getGoals($idSite);
+ if(!isset($goals[$idGoal]))
+ {
+ throw new Exception("idgoal $idGoal not valid.");
+ }
+ $goalDefinition = $goals[$idGoal];
+
+ $view = new Piwik_View('Goals/templates/single_goal.tpl');
+ $view->currency = Piwik::getCurrency();
+ $goal = $this->getMetricsForGoal($idGoal);
+ foreach($goal as $name => $value)
+ {
+ $view->$name = $value;
+ }
+ $view->name = $goalDefinition['name'];
+ $view->title = $goalDefinition['name'] . ' - Conversions';
+ $view->graphEvolution = $this->getLastNbConversionsGraph(true);
+ $view->nameGraphEvolution = 'GoalsgetLastNbConversionsGraph'; // must be the function name used above
+
+ $columnNbConversions = 'goal_'.$idGoal.'_nb_conversions';
+ $columnConversionRate = 'goal_'.$idGoal.'_conversion_rate';
+
+ $topSegmentsToLoad = array(
+ 'country' => 'UserCountry.getCountry',
+ 'keyword' => 'Referers.getKeywords',
+ 'website' => 'Referers.getWebsites',
+ );
+
+ $topSegments = array();
+ foreach($topSegmentsToLoad as $segmentName => $apiMethod)
+ {
+ $request = new Piwik_API_Request("method=$apiMethod
+ &format=original
+ &filter_update_columns_when_show_all_goals=1
+ &filter_sort_order=desc
+ &filter_sort_column=$columnNbConversions
+ &filter_limit=3");
+ $datatable = $request->process();
+ $topSegment = array();
+ foreach($datatable->getRows() as $row)
+ {
+ $topSegment[] = array (
+ 'name' => $row->getColumn('label'),
+ 'nb_conversions' => $row->getColumn($columnNbConversions),
+ 'conversion_rate' => $row->getColumn($columnConversionRate),
+ 'metadata' => $row->getMetadata(),
+ );
+ }
+ $topSegments[$segmentName] = $topSegment;
+// echo $datatable;
+ }
+
+ $request = new Piwik_API_Request("method=Goals.getConversionRateReturningVisitors&format=original");
+ $view->conversion_rate_returning = round( $request->process(), self::CONVERSION_RATE_PRECISION );
+ $request = new Piwik_API_Request("method=Goals.getConversionRateNewVisitors&format=original");
+ $view->conversion_rate_new = round( $request->process(), self::CONVERSION_RATE_PRECISION );
+
+ $view->topSegments = $topSegments;
+ echo $view->render();
+ //todo next: nice legends for graphs
+ }
+
+ protected function getMetricsForGoal($goalId)
+ {
+ $request = new Piwik_API_Request("method=Goals.get&format=original&idGoal=$goalId");
+ $datatable = $request->process();
+ return array (
+ 'id' => $goalId,
+ 'nb_conversions' => $datatable->getRowFromLabel(Piwik_Goals::getRecordName('nb_conversions', $goalId))->getColumn('value'),
+ 'conversion_rate' => round($datatable->getRowFromLabel(Piwik_Goals::getRecordName('conversion_rate', $goalId))->getColumn('value'), 1),
+ 'revenue' => $datatable->getRowFromLabel(Piwik_Goals::getRecordName('revenue', $goalId))->getColumn('value'),
+ 'urlSparklineConversions' => $this->getUrlSparkline('getLastNbConversionsGraph', $goalId) . "&idGoal=".$goalId,
+ 'urlSparklineConversionRate' => $this->getUrlSparkline('getLastConversionRateGraph', $goalId) . "&idGoal=".$goalId,
+ 'urlSparklineRevenue' => $this->getUrlSparkline('getLastRevenueGraph', $goalId) . "&idGoal=".$goalId,
+ );
+ }
+
+ function index()
+ {
+ $view = new Piwik_View('Goals/templates/overview.tpl');
+ $view->currency = Piwik::getCurrency();
+
+ $view->title = 'All goals - evolution';
+ $view->graphEvolution = $this->getLastNbConversionsGraph(true);
+ $view->nameGraphEvolution = 'GoalsgetLastNbConversionsGraph'; // must be the function name used above
+
+ // sparkline for the historical data of the above values
+ $view->urlSparklineConversions = $this->getUrlSparkline('getLastNbConversionsGraph');
+ $view->urlSparklineConversionRate = $this->getUrlSparkline('getLastConversionRateGraph');
+ $view->urlSparklineRevenue = $this->getUrlSparkline('getLastRevenueGraph');
+
+ $request = new Piwik_API_Request("method=Goals.get&format=original");
+ $datatable = $request->process();
+ $view->nb_conversions = $datatable->getRowFromLabel('Goal_nb_conversions')->getColumn('value');
+ $view->conversion_rate = $datatable->getRowFromLabel('Goal_conversion_rate')->getColumn('value');
+ $view->revenue = $datatable->getRowFromLabel('Goal_revenue')->getColumn('value');
+
+ $goalMetrics = array();
+
+ $idSite = Piwik_Common::getRequestVar('idSite');
+ $goals = Piwik_Goals_API::getGoals($idSite);
+ foreach($goals as $idGoal => $goal)
+ {
+ $goalMetrics[$idGoal] = $this->getMetricsForGoal($idGoal);
+ $goalMetrics[$idGoal]['name'] = $goal['name'];
+ }
+
+ $view->goalMetrics = $goalMetrics;
+ $view->goals = $goals;
+ $view->goalsJSON = json_encode($goals);
+ $view->userCanEditGoals = Piwik::isUserHasAdminAccess($idSite);
+ echo $view->render();
+ }
+
+ function addNewGoal()
+ {
+ $view = new Piwik_View('Goals/templates/add_new_goal.tpl');
+ $idSite = Piwik_Common::getRequestVar('idSite');
+ $view->userCanEditGoals = Piwik::isUserHasAdminAccess($idSite);
+ $view->currency = Piwik::getCurrency();
+ $view->onlyShowAddNewGoal = true;
+ echo $view->render();
+ }
+
+ function getLastNbConversionsGraph( $fetch = false )
+ {
+ $view = $this->getLastUnitGraph($this->pluginName, __FUNCTION__, 'Goals.getConversions');
+ return $this->renderView($view, $fetch);
+ }
+ function getLastConversionRateGraph( $fetch = false )
+ {
+ $view = $this->getLastUnitGraph($this->pluginName, __FUNCTION__, 'Goals.getConversionRate');
+ return $this->renderView($view, $fetch);
+ }
+ function getLastRevenueGraph( $fetch = false )
+ {
+ $view = $this->getLastUnitGraph($this->pluginName, __FUNCTION__, 'Goals.getRevenue');
+ return $this->renderView($view, $fetch);
+ }
+}
diff --git a/plugins/Goals/Goals.php b/plugins/Goals/Goals.php
new file mode 100644
index 0000000000..550f0e7288
--- /dev/null
+++ b/plugins/Goals/Goals.php
@@ -0,0 +1,206 @@
+<?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$
+ *
+ * @package Piwik_Referers
+ */
+
+require_once "core/Tracker/GoalManager.php";
+
+/**
+ * @package Piwik_Referers
+ */
+class Piwik_Goals extends Piwik_Plugin
+{
+ const ROUNDING_PRECISION = 2;
+
+ public function getInformation()
+ {
+ $info = array(
+ 'name' => '(ALPHA) Goal Tracking',
+ 'description' => 'Create Goals and see reports about your goal conversions: evolution over time, revenue per visit, conversions per referer, per keyword, etc.',
+ 'author' => 'Piwik',
+ 'homepage' => 'http://piwik.org/',
+ 'version' => '0.1',
+ 'TrackerPlugin' => true
+ );
+
+ return $info;
+ }
+
+ function getListHooksRegistered()
+ {
+ $hooks = array(
+ 'Common.fetchWebsiteAttributes' => 'fetchGoalsFromDb',
+ 'ArchiveProcessing_Day.compute' => 'archiveDay',
+ 'ArchiveProcessing_Period.compute' => 'archivePeriod',
+ 'WidgetsList.add' => 'addWidgets',
+ 'Menu.add' => 'addMenus',
+ );
+ return $hooks;
+ }
+
+ function fetchGoalsFromDb($notification)
+ {
+ require_once "Goals/API.php";
+ $info = $notification->getNotificationInfo();
+ $idsite = $info['idsite'];
+
+ // add the 'goal' entry in the website array
+ $array =& $notification->getNotificationObject();
+ $array['goals'] = Piwik_Goals_API::getGoals($idsite);
+ }
+
+ function addWidgets()
+ {
+// Piwik_AddWidget( 'Referers', 'getKeywords', Piwik_Translate('Referers_WidgetKeywords'));
+ }
+
+ function addMenus()
+ {
+ $goals = Piwik_Tracker_GoalManager::getGoalDefinitions(Piwik_Common::getRequestVar('idSite'));
+ if(count($goals)==0)
+ {
+ Piwik_AddMenu('Goals', 'Add a new Goal', array('module' => 'Goals', 'action' => 'addNewGoal'));
+ }
+ else
+ {
+ Piwik_AddMenu('Goals', 'Overview', array('module' => 'Goals'));
+ foreach($goals as $goal)
+ {
+ Piwik_AddMenu('Goals', str_replace('%', '%%', $goal['name']), array('module' => 'Goals', 'action' => 'goalReport', 'idGoal' => $goal['idgoal']));
+ }
+ }
+ }
+
+ /**
+ * @param string $recordName 'nb_conversions'
+ * @param int $idGoal idGoal to return the metrics for, or false to return overall
+ * @param int $visitorReturning 0 for new visitors, 1 for returning visitors, false for all
+ * @return unknown
+ */
+ static public function getRecordName($recordName, $idGoal = false, $visitorReturning = false)
+ {
+ $idGoalStr = $returningStr = '';
+ if($idGoal !== false)
+ {
+ $idGoalStr = $idGoal . "_";
+ }
+ if($visitorReturning !== false)
+ {
+ $returningStr = 'visitor_returning_' . $visitorReturning . '_';
+ }
+ return 'Goal_' . $returningStr . $idGoalStr . $recordName;
+ }
+
+ function archivePeriod($notification )
+ {
+ /**
+ * @var Piwik_ArchiveProcessing_Period
+ */
+ $archiveProcessing = $notification->getNotificationObject();
+
+ $metricsToSum = array( 'nb_conversions', 'revenue');
+ $goalIdsToSum = Piwik_Tracker_GoalManager::getGoalIds($archiveProcessing->idsite);
+
+ $fieldsToSum = array();
+ foreach($metricsToSum as $metricName)
+ {
+ foreach($goalIdsToSum as $goalId)
+ {
+ $fieldsToSum[] = self::getRecordName($metricName, $goalId);
+ $fieldsToSum[] = self::getRecordName($metricName, $goalId, 0);
+ $fieldsToSum[] = self::getRecordName($metricName, $goalId, 1);
+ }
+ $fieldsToSum[] = self::getRecordName($metricName);
+ }
+ $records = $archiveProcessing->archiveNumericValuesSum($fieldsToSum);
+
+ // also recording conversion_rate for each goal
+ foreach($goalIdsToSum as $goalId)
+ {
+ $nb_conversions = $records[self::getRecordName('nb_conversions', $goalId)]->value;
+ $conversion_rate = $this->getConversionRate($nb_conversions, $archiveProcessing);
+ $record = new Piwik_ArchiveProcessing_Record_Numeric(self::getRecordName('conversion_rate', $goalId), $conversion_rate);
+ }
+
+ // global conversion rate
+ $nb_conversions = $records[self::getRecordName('nb_conversions')]->value;
+ $conversion_rate = $this->getConversionRate($nb_conversions, $archiveProcessing);
+ $record = new Piwik_ArchiveProcessing_Record_Numeric(self::getRecordName('conversion_rate'), $conversion_rate);
+
+ }
+
+ function archiveDay( $notification )
+ {
+ /**
+ * @var Piwik_ArchiveProcessing_Day
+ */
+ $archiveProcessing = $notification->getNotificationObject();
+
+ // by processing visitor_returning segment, we can also simply sum and get stats for all goals.
+ $query = $archiveProcessing->queryConversionsBySegment('visitor_returning');
+
+ $nb_conversions = $revenue = 0;
+ $goals = $goalsByVisitorReturning = array();
+ while($row = $query->fetch() )
+ {
+ $goalsByVisitorReturning[$row['idgoal']][$row['visitor_returning']] = $archiveProcessing->getGoalRowFromQueryRow($row);
+
+ if(!isset($goals[$row['idgoal']])) $goals[$row['idgoal']] = $archiveProcessing->getNewGoalRow();
+ $archiveProcessing->updateGoalStats($row, $goals[$row['idgoal']]);
+
+ $revenue += $row['revenue'];
+ $nb_conversions += $row['nb_conversions'];
+ }
+
+ // Stats by goal, for all visitors
+ foreach($goals as $idgoal => $values)
+ {
+ foreach($values as $metricId => $value)
+ {
+ $metricName = Piwik_Archive::$mappingFromIdToNameGoal[$metricId];
+ $recordName = self::getRecordName($metricName, $idgoal);
+ $record = new Piwik_ArchiveProcessing_Record_Numeric($recordName, $value);
+ }
+ $conversion_rate = $this->getConversionRate($values[Piwik_Archive::INDEX_GOAL_NB_CONVERSIONS], $archiveProcessing);
+ $recordName = self::getRecordName('conversion_rate', $idgoal);
+ $record = new Piwik_ArchiveProcessing_Record_Numeric($recordName, $conversion_rate);
+ }
+
+ // Stats by goal, for visitor returning / non returning
+ foreach($goalsByVisitorReturning as $idgoal => $values)
+ {
+ foreach($values as $visitor_returning => $goalValues)
+ {
+ foreach($goalValues as $metricId => $value)
+ {
+ $metricName = Piwik_Archive::$mappingFromIdToNameGoal[$metricId];
+ $recordName = self::getRecordName($metricName, $idgoal, $visitor_returning);
+ $record = new Piwik_ArchiveProcessing_Record_Numeric($recordName, $value);
+// echo $record . "<br>";
+ }
+ }
+ }
+
+ // Stats for all goals
+ $totalAllGoals = array(
+ self::getRecordName('conversion_rate') => round(100 * $archiveProcessing->getNumberOfVisitsConverted() / $archiveProcessing->getNumberOfVisits(), self::ROUNDING_PRECISION),
+ self::getRecordName('nb_conversions') => $nb_conversions,
+ self::getRecordName('revenue') => $revenue,
+ );
+ foreach($totalAllGoals as $recordName => $value)
+ {
+ $record = new Piwik_ArchiveProcessing_Record_Numeric($recordName, $value);
+ }
+ }
+
+ function getConversionRate($count, $archiveProcessing)
+ {
+ return round(100 * $count / $archiveProcessing->getNumberOfVisits(), self::ROUNDING_PRECISION);
+ }
+}
diff --git a/plugins/Goals/templates/GoalForm.js b/plugins/Goals/templates/GoalForm.js
new file mode 100644
index 0000000000..4345bc8958
--- /dev/null
+++ b/plugins/Goals/templates/GoalForm.js
@@ -0,0 +1,124 @@
+
+function showAddNewGoal()
+{
+ $("#GoalForm").show();
+ $("#EditGoals").hide();
+ $.scrollTo("#AddEditGoals", 400);
+ return false;
+}
+
+function showEditGoals()
+{
+ $("#EditGoals").show();
+ $("#GoalForm").hide();
+ $.scrollTo("#AddEditGoals", 400);
+ return false;
+}
+
+// init the goal form with existing goal value, if any
+function initGoalForm(goalMethodAPI, submitText, goalName, matchAttribute, pattern, patternType, caseSensitive, revenue, goalId)
+{
+ $('#goal_name').val(goalName);
+ $('input[@name=match_attribute][value='+matchAttribute+']').attr('checked', true);
+ $('#match_attribute_name').html(mappingMatchTypeName[matchAttribute]);
+ $('#examples_pattern').html(mappingMatchTypeExamples[matchAttribute]);
+ $('option[value='+patternType+']').attr('selected', true);
+ $('input[name=pattern]').val(pattern);
+ $('#case_sensitive').attr('checked', caseSensitive);
+ $('input[name=revenue]').val(revenue);
+ $('input[name=methodGoalAPI]').val(goalMethodAPI);
+ $('#goal_submit').val(submitText);
+ if(goalId != undefined) {
+ $('input[name=goalIdUpdate]').val(goalId);
+ }
+}
+
+function initAndShowAddGoalForm()
+{
+ initGoalForm('Goals.addGoal', 'Add Goal', '', 'url', '', 'contains', false, '0');
+ return showAddNewGoal();
+}
+function bindGoalForm()
+{
+ $('input[@name=match_attribute]').click( function() {
+ var matchTypeId = $(this).attr('value');
+ $('#match_attribute_name').html(mappingMatchTypeName[matchTypeId]);
+ $('#examples_pattern').html(mappingMatchTypeExamples[matchTypeId]);
+ });
+
+ $('#goal_submit').click( function() {
+ // prepare ajax query to API to add goal
+ ajaxRequestAddGoal = getAjaxAddGoal();
+ $.ajax( ajaxRequestAddGoal );
+ return false;
+ });
+
+ $('a[name=linkAddNewGoal]').click( function(){
+ initAndShowAddGoalForm();
+ } );
+}
+
+function bindListGoalEdit()
+{
+ $('a[name=linkEditGoal]').click( function() {
+ var goalId = $(this).attr('id');
+ var goal = piwik.goals[goalId];
+ initGoalForm("Goals.updateGoal", "Update Goal", goal.name, goal.match_attribute, goal.pattern, goal.pattern_type, (goal.case_sensitive=='0' ? false : true), goal.revenue, goalId);
+ showAddNewGoal();
+ return false;
+ });
+
+ $('a[name=linkDeleteGoal]').click( function() {
+ var goalId = $(this).attr('id');
+ var goalName = 'test goal';//piwik.goals[goalId][name]
+ if(confirm(sprintf('Are you sure you want to delete the Goal %s?','"'+goalName+'"')))
+ {
+ $.ajax( getAjaxDeleteGoal( goalId ) );
+ return false;
+ }
+ });
+
+ $('a[name=linkEditGoals]').click( function(){
+ return showEditGoals();
+ } );
+}
+function getAjaxDeleteGoal(idGoal)
+{
+ var ajaxRequest = getStandardAjaxConf();
+ toggleAjaxLoading();
+
+ var parameters = new Object;
+ parameters.idSite = piwik.idSite;
+ parameters.idGoal = idGoal;
+ parameters.method = 'Goals.deleteGoal';
+ parameters.module = 'API';
+ parameters.format = 'json';
+ parameters.token_auth = piwik.token_auth;
+ ajaxRequest.data = parameters;
+ return ajaxRequest;
+}
+
+function getAjaxAddGoal()
+{
+ var ajaxRequest = getStandardAjaxConf();
+ toggleAjaxLoading();
+
+ var parameters = new Object;
+
+ parameters.idSite = piwik.idSite;
+ parameters.name = encodeURIComponent( $('#goal_name').val() );
+ parameters.matchAttribute = $('input[name=match_attribute][checked]').val();
+ parameters.patternType = $('[name=pattern_type]').val();
+ parameters.pattern = encodeURIComponent( $('input[name=pattern]').val() );
+ parameters.caseSensitive = $('#case_sensitive').attr('checked') == true ? 1: 0;
+ parameters.revenue = $('input[name=revenue]').val();
+
+ parameters.idGoal = $('input[name=goalIdUpdate]').val();
+ parameters.method = $('input[name=methodGoalAPI]').val();
+ parameters.module = 'API';
+ parameters.format = 'json';
+ parameters.token_auth = piwik.token_auth;
+
+ ajaxRequest.data = parameters;
+ return ajaxRequest;
+} \ No newline at end of file
diff --git a/plugins/Goals/templates/add_edit_goal.tpl b/plugins/Goals/templates/add_edit_goal.tpl
new file mode 100644
index 0000000000..2ca55ca102
--- /dev/null
+++ b/plugins/Goals/templates/add_edit_goal.tpl
@@ -0,0 +1,49 @@
+
+<div id="AddEditGoals">
+{if isset($onlyShowAddNewGoal)}
+ <h2>Add a new Goal</h2>
+{else}
+ <h2><a onclick='' name="linkAddNewGoal">+ Add a new Goal</a>
+ or <a onclick='' name="linkEditGoals">Edit</a> existing Goals</h2>
+{/if}
+
+ <div>
+ <div id="ajaxError" style="display:none"></div>
+ <div id="ajaxLoading" style="display:none"><div id="loadingPiwik"><img src="themes/default/images/loading-blue.gif" alt="" /> {'General_LoadingData'|translate}</div></div>
+ </div>
+
+{if !isset($onlyShowAddNewGoal)}
+ {include file="Goals/templates/list_goal_edit.tpl"}
+{/if}
+ {include file="Goals/templates/form_add_goal.tpl"}
+
+ <a id='bottom'></a>
+</div>
+
+{literal}
+<script type="text/javascript" src="plugins/Goals/templates/GoalForm.js"></script>
+<script language="javascript">
+
+var mappingMatchTypeName = {
+ "url": "URL",
+ "file": "filename",
+ "external_website": "external website URL"
+};
+var mappingMatchTypeExamples = {
+ "url": "eg. contains 'checkout/confirmation'<br>eg. is exactly 'http://example.com/thank-you.html'<br>eg. matches the expression '[.*]\\\/demo\\\/[.*]'",
+ "file": "eg. contains 'files/brochure.pdf'<br>eg. is exactly 'http://example.com/files/brochure.pdf'<br>eg. matches the expression '[.*]\\\.zip'",
+ "external_website": "eg. contains 'amazon.com'<br>eg. is exactly 'http://mypartner.com/landing.html'<br>eg. matches the expression 'http://www.amazon.com\\\/[.*]\\\/yourAffiliateId'"
+};
+
+bindGoalForm();
+
+{/literal}
+
+{if !isset($onlyShowAddNewGoal)}
+piwik.goals = {$goalsJSON};
+bindListGoalEdit();
+{else}
+initAndShowAddGoalForm();
+{/if}
+
+</script>
diff --git a/plugins/Goals/templates/add_new_goal.tpl b/plugins/Goals/templates/add_new_goal.tpl
new file mode 100644
index 0000000000..05a7f66e8d
--- /dev/null
+++ b/plugins/Goals/templates/add_new_goal.tpl
@@ -0,0 +1,8 @@
+
+{if $userCanEditGoals}
+ {include file=Goals/templates/add_edit_goal.tpl}
+{else}
+Only an Administrator or the Super User can add Goals for a given website.
+Please ask your Piwik administrator to set up a Goal for your website.
+<br>Tracking Goals are a great tool to help you maximize your website performance!
+{/if}
diff --git a/plugins/Goals/templates/form_add_goal.tpl b/plugins/Goals/templates/form_add_goal.tpl
new file mode 100644
index 0000000000..95c4f6d3d9
--- /dev/null
+++ b/plugins/Goals/templates/form_add_goal.tpl
@@ -0,0 +1,67 @@
+{literal}
+<style>
+.goalInlineHelp{
+color:#9B9B9B;
+}
+</style>
+{/literal}
+<span id='GoalForm' style="display:none;">
+<form>
+ <table class="tableForm">
+ <tr>
+ <td>Goal Name </td>
+ <td><input type="text" name="name" value="" id="goal_name" /></td>
+ </tr>
+ <tr>
+ <td>Goal is triggered when visitors:</td>
+ <td>
+ <input type="radio" id="match_attribute_url" value="url" name="match_attribute"/>
+ <label for="match_attribute_url">Visit a given URL (page or group of pages)</label>
+ <br>
+ <input type="radio" id="match_attribute_file" value="file" name="match_attribute"/>
+ <label for="match_attribute_file">Download a file</label>
+ <br>
+ <input type="radio" id="match_attribute_external_website" value="external_website" name="match_attribute"/>
+ <label for="match_attribute_external_website">Click on a Link to an external website </label>
+ </td>
+ </tr>
+ <tr>
+ <td>where the <span id="match_attribute_name"></span></td>
+ <td>
+ <select name="pattern_type">
+ <option value="contains">contains</option>
+ <option value="exact">is exactly</option>
+ <option value="regex">matches the expression</option>
+ </select>
+
+ <input type="text" name="pattern" value=""/>
+ <br>
+ <div id="examples_pattern" class="goalInlineHelp"></div>
+ <br>
+ <span style="float:right">
+ (optional) <input type="checkbox" id="case_sensitive"/>
+ <label for="case_sensitive">Case sensitive match</label>
+ </span>
+ </td>
+ </tr>
+ <tr>
+ <td>(optional) Goal default value is </td>
+ <td>{$currency} <input type="text" name="revenue" size="1" value="0"/>
+ <div class="goalInlineHelp">
+ For example, a Contact Form submitted by a visitor <br>
+ may be worth $10 on average. Piwik will help you understand <br>
+ how well your visitors segments are performing.</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" style="border:0">
+ <div class="submit">
+ <input type="hidden" name="methodGoalAPI" value="">
+ <input type="hidden" name="goalIdUpdate" value="">
+ <input type="submit" value="Add Goal" name="submit" id="goal_submit" class="submit" />
+ </div>
+ </td>
+ </tr>
+ </table>
+</form>
+</span> \ No newline at end of file
diff --git a/plugins/Goals/templates/list_goal_edit.tpl b/plugins/Goals/templates/list_goal_edit.tpl
new file mode 100644
index 0000000000..081497cade
--- /dev/null
+++ b/plugins/Goals/templates/list_goal_edit.tpl
@@ -0,0 +1,22 @@
+<span id='EditGoals' style="display:none;">
+ <table class="tableForm">
+ <thead style="font-weight:bold">
+ <td>Id</td>
+ <td>Goal Name</td>
+ <td>Goal is Triggered when</td>
+ <td>Revenue</td>
+ <td>Edit</td>
+ <td>Delete</td>
+ </thead>
+ {foreach from=$goals item=goal}
+ <tr>
+ <td>{$goal.idgoal}</td>
+ <td>{$goal.name}</td>
+ <td>{$goal.match_attribute} <br>Pattern {$goal.pattern_type}: {$goal.pattern}</b></td>
+ <td>{if $goal.revenue==0}-{else}{$currency}{$goal.revenue}{/if}</td>
+ <td><a href='#' name="linkEditGoal" id="{$goal.idgoal}"><img src='plugins/UsersManager/images/edit.png' border=0> Edit</a></td>
+ <td><a href='#' name="linkDeleteGoal" id="{$goal.idgoal}"><img src='plugins/UsersManager/images/remove.png' border=0> Delete</a></td>
+ </tr>
+ {/foreach}
+ </table>
+</span> \ No newline at end of file
diff --git a/plugins/Goals/templates/list_top_segment.tpl b/plugins/Goals/templates/list_top_segment.tpl
new file mode 100644
index 0000000000..6dbe69813f
--- /dev/null
+++ b/plugins/Goals/templates/list_top_segment.tpl
@@ -0,0 +1,5 @@
+
+{foreach from=$topSegment item=element name=topGoalElements}
+<span class='goalTopElement' title='<b>{$element.nb_conversions}</b> conversions, <b>{$element.conversion_rate}%</b> conversion rate'>
+{$element.name}</span>{logoHtml metadata=$element.metadata alt=$element.name}{if $smarty.foreach.topGoalElements.iteration == $smarty.foreach.topGoalElements.total-1} and {elseif $smarty.foreach.topGoalElements.iteration < $smarty.foreach.topGoalElements.total-1}, {else}{/if}
+{/foreach} {* (<a href=''>more</a>) *}
diff --git a/plugins/Goals/templates/overview.tpl b/plugins/Goals/templates/overview.tpl
new file mode 100644
index 0000000000..04bf1af90d
--- /dev/null
+++ b/plugins/Goals/templates/overview.tpl
@@ -0,0 +1,27 @@
+
+{include file="Goals/templates/title_and_evolution_graph.tpl"}
+
+{foreach from=$goalMetrics item=goal}
+{assign var=nb_conversions value=$goal.nb_conversions}
+{assign var=conversion_rate value=$goal.conversion_rate}
+<h2 style="padding-top: 30px;">{$goal.name} (goal)</h3>
+<table width=700px>
+ <tr><td>
+ <p>{sparkline src=$goal.urlSparklineConversions}<span>
+ {'%s conversions'|translate:"<strong>$nb_conversions</strong>"}</span></p>
+ </td><td>
+ <p>{sparkline src=$goal.urlSparklineConversionRate}<span>
+ {'%s conversion rate'|translate:"<strong>$conversion_rate%</strong>"}</span></p>
+ </td><td>
+ {* (<a href=''>more</a>) *}
+ </td></tr>
+</table>
+
+{/foreach}
+
+{if $userCanEditGoals}
+ <hr style="margin:30px 0px">
+ {include file=Goals/templates/add_edit_goal.tpl}
+{/if}
+
+{include file="Goals/templates/release_notes.tpl} \ No newline at end of file
diff --git a/plugins/Goals/templates/release_notes.tpl b/plugins/Goals/templates/release_notes.tpl
new file mode 100644
index 0000000000..dce9ec63b2
--- /dev/null
+++ b/plugins/Goals/templates/release_notes.tpl
@@ -0,0 +1,20 @@
+<hr>
+<b>About the Goal Tracking Plugin</b><br>
+<pre>
+The Goal Tracking Plugin is in alpha release. There is more coming soon!
+- The Goal Report page will display conversion table by search engines, country, keyword, campaign, etc.
+- The Goal Overview page will link to a Goal Report page with a "(more)" link that will ajax reload the page
+- Goals could be triggered using javascript event, with custom revenue
+- internationalization of all strings
+- provide documentation, screenshots, blog post + add screenshot and inline help in "Add a New Goal"
+- provide widgets for the dashboard, general goal overview, and one widget for each goal. With: graph evolution, sparklines. Widget with top segments for each goal.
+
+Known bugs
+- The Goal total nb conversions should be sum of all goal conversions (wrong number when deleting a Goal)
+- After adding goal, the window should refresh to the goal report page, and not to the dashboard
+- Outlink trailing slash is automatically deleted from the URL, there would be a problem when trying to exact match a URL with trailing slash
+- All graph labelling are not correct (always printing nb_uniq_visitors even when showing conversion or conversion_rate) see <a href='http://dev.piwik.org/trac/ticket/322'>#322</a>
+
+Give us Feedback!
+If you find any other bug, or if you have suggestions, please send us a message using the "Give us feedback" link at the top of the Piwik pages.
+</pre> \ No newline at end of file
diff --git a/plugins/Goals/templates/single_goal.tpl b/plugins/Goals/templates/single_goal.tpl
new file mode 100644
index 0000000000..b605c17490
--- /dev/null
+++ b/plugins/Goals/templates/single_goal.tpl
@@ -0,0 +1,37 @@
+{include file="Goals/templates/title_and_evolution_graph.tpl"}
+
+{if $nb_conversions > 0}
+ <h2>Conversions Overview</h2>
+ <ul class="ulGoalTopElements">
+ <li>Your best converting countries are: {include file='Goals/templates/list_top_segment.tpl' topSegment=$topSegments.country}</li>
+ {if count($topSegments.keyword)>0}<li>Your top converting keywords are: {include file='Goals/templates/list_top_segment.tpl' topSegment=$topSegments.keyword}</li>{/if}
+ {if count($topSegments.website)>0}<li>Your best converting websites referers are: {include file='Goals/templates/list_top_segment.tpl' topSegment=$topSegments.website}</li>{/if}
+ <li>Returning visitors conversion rate is <b>{$conversion_rate_returning}%</b>, New Visitors conversion rate is <b>{$conversion_rate_new}%</b></li>
+ </ul>
+{/if}
+
+
+{literal}
+<style>
+ul.ulGoalTopElements {
+ list-style-type:circle;
+ margin-left:30px;
+}
+.ulGoalTopElements a {
+ text-decoration:none;
+ color:#0033CC;
+ border-bottom:1px dotted #0033CC;
+ line-height:2em;
+}
+.goalTopElement {
+ border-bottom:1px dotted;
+}
+</style>
+<script>
+$(document).ready( function() {
+ $('.goalTopElement')
+ .Tooltip()
+ ;
+ });
+</script>
+{/literal} \ No newline at end of file
diff --git a/plugins/Goals/templates/title_and_evolution_graph.tpl b/plugins/Goals/templates/title_and_evolution_graph.tpl
new file mode 100644
index 0000000000..0b1b8d2c7b
--- /dev/null
+++ b/plugins/Goals/templates/title_and_evolution_graph.tpl
@@ -0,0 +1,20 @@
+<script type="text/javascript" src="plugins/CoreHome/templates/sparkline.js"></script>
+
+<a name="evolutionGraph" graphId="{$nameGraphEvolution}"></a>
+<h2>{$title}</h2>
+{$graphEvolution}
+
+<table>
+ <tr><td>
+ <p>{sparkline src=$urlSparklineConversions}<span>
+ {'%s conversions'|translate:"<strong>$nb_conversions</strong>"}</span></p>
+ {if $revenue != 0 }
+ <p>{sparkline src=$urlSparklineRevenue}<span>
+ {'%s overall revenue'|translate:"<strong>$currency$revenue</strong>"}</span></p>
+ {/if}
+ </td><td valign="top">
+ <p>{sparkline src=$urlSparklineConversionRate}<span>
+ {'%s overall conversion rate (visits with a completed goal)'|translate:"<strong>$conversion_rate%</strong>"}</span></p>
+ </td></tr>
+</table>
+
diff --git a/plugins/Installation/Controller.php b/plugins/Installation/Controller.php
index f843263eb9..1bee5cdbbf 100644
--- a/plugins/Installation/Controller.php
+++ b/plugins/Installation/Controller.php
@@ -1,135 +1,135 @@
-<?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$
- *
- * @package Piwik_Installation
- */
-
-require_once "Installation/View.php";
-
-/**
- *
- * @package Piwik_Installation
- */
-class Piwik_Installation_Controller extends Piwik_Controller
-{
- // public so plugins can add/delete installation steps
- public $steps = array(
- 'welcome',
- 'systemCheck',
- 'databaseSetup',
- 'tablesCreation',
- 'generalSetup',
- 'firstWebsiteSetup',
- 'displayJavascriptCode',
- 'finished'
- );
-
- protected $pathView = 'Installation/templates/';
-
- public function __construct()
- {
- if(!isset($_SESSION['currentStepDone']))
- {
- $_SESSION['currentStepDone'] = '';
- }
-
- Piwik_PostEvent('InstallationController.construct', $this);
- }
-
- public function getInstallationSteps()
- {
- return $this->steps;
- }
-
- function getDefaultAction()
- {
- return $this->steps[0];
- }
-
- function welcome()
+<?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$
+ *
+ * @package Piwik_Installation
+ */
+
+require_once "Installation/View.php";
+
+/**
+ *
+ * @package Piwik_Installation
+ */
+class Piwik_Installation_Controller extends Piwik_Controller
+{
+ // public so plugins can add/delete installation steps
+ public $steps = array(
+ 'welcome',
+ 'systemCheck',
+ 'databaseSetup',
+ 'tablesCreation',
+ 'generalSetup',
+ 'firstWebsiteSetup',
+ 'displayJavascriptCode',
+ 'finished'
+ );
+
+ protected $pathView = 'Installation/templates/';
+
+ public function __construct()
+ {
+ if(!isset($_SESSION['currentStepDone']))
+ {
+ $_SESSION['currentStepDone'] = '';
+ }
+
+ Piwik_PostEvent('InstallationController.construct', $this);
+ }
+
+ public function getInstallationSteps()
+ {
+ return $this->steps;
+ }
+
+ function getDefaultAction()
+ {
+ return $this->steps[0];
+ }
+
+ function welcome()
{
require_once "Login/Controller.php";
Piwik_Login_Controller::clearSession();
-
- $view = new Piwik_Install_View(
- $this->pathView . 'welcome.tpl',
- $this->getInstallationSteps(),
- __FUNCTION__
- );
- $this->skipThisStep( __FUNCTION__ );
- $view->showNextStep = true;
-
- $_SESSION['currentStepDone'] = __FUNCTION__;
- echo $view->render();
- }
-
- function systemCheck()
- {
- $view = new Piwik_Install_View(
- $this->pathView . 'systemCheck.tpl',
- $this->getInstallationSteps(),
- __FUNCTION__
- );
- $this->checkPreviousStepIsValid( __FUNCTION__ );
- $this->skipThisStep( __FUNCTION__ );
-
- $view->infos = $this->getSystemInformation();
- $view->problemWithSomeDirectories = (false !== array_search(false, $view->infos['directories']));
-
- $view->showNextStep = !$view->problemWithSomeDirectories
- && $view->infos['phpVersion_ok']
- && $view->infos['pdo_ok']
- && $view->infos['pdo_mysql_ok']
-
- ;
- $_SESSION['currentStepDone'] = __FUNCTION__;
-
- echo $view->render();
- }
-
-
- function databaseSetup()
- {
- // case the user hits the back button
- $_SESSION['skipThisStep']['firstWebsiteSetup'] = false;
- $_SESSION['skipThisStep']['displayJavascriptCode'] = false;
-
- $view = new Piwik_Install_View(
- $this->pathView . 'databaseSetup.tpl',
- $this->getInstallationSteps(),
- __FUNCTION__
- );
- $this->checkPreviousStepIsValid( __FUNCTION__ );
- $this->skipThisStep( __FUNCTION__ );
-
- $view->showNextStep = false;
- require_once "FormDatabaseSetup.php";
- $form = new Piwik_Installation_FormDatabaseSetup;
-
- if($form->validate())
- {
- $dbInfos = array(
- 'host' => $form->getSubmitValue('host'),
- 'username' => $form->getSubmitValue('username'),
- 'password' => $form->getSubmitValue('password'),
- 'dbname' => $form->getSubmitValue('dbname'),
- 'tables_prefix' => $form->getSubmitValue('tables_prefix'),
- 'adapter' => Zend_Registry::get('config')->database->adapter,
- 'port' => Zend_Registry::get('config')->database->port,
- );
-
- $dbInfos['password'] = '"'.htmlspecialchars($form->getSubmitValue('password')).'"';
-
- if(($portIndex = strpos($dbInfos['host'],':')) !== false)
- {
- $dbInfos['port'] = substr($dbInfos['host'], $portIndex + 1 );
- $dbInfos['host'] = substr($dbInfos['host'], 0, $portIndex);
- }
+
+ $view = new Piwik_Install_View(
+ $this->pathView . 'welcome.tpl',
+ $this->getInstallationSteps(),
+ __FUNCTION__
+ );
+ $this->skipThisStep( __FUNCTION__ );
+ $view->showNextStep = true;
+
+ $_SESSION['currentStepDone'] = __FUNCTION__;
+ echo $view->render();
+ }
+
+ function systemCheck()
+ {
+ $view = new Piwik_Install_View(
+ $this->pathView . 'systemCheck.tpl',
+ $this->getInstallationSteps(),
+ __FUNCTION__
+ );
+ $this->checkPreviousStepIsValid( __FUNCTION__ );
+ $this->skipThisStep( __FUNCTION__ );
+
+ $view->infos = $this->getSystemInformation();
+ $view->problemWithSomeDirectories = (false !== array_search(false, $view->infos['directories']));
+
+ $view->showNextStep = !$view->problemWithSomeDirectories
+ && $view->infos['phpVersion_ok']
+ && $view->infos['pdo_ok']
+ && $view->infos['pdo_mysql_ok']
+
+ ;
+ $_SESSION['currentStepDone'] = __FUNCTION__;
+
+ echo $view->render();
+ }
+
+
+ function databaseSetup()
+ {
+ // case the user hits the back button
+ $_SESSION['skipThisStep']['firstWebsiteSetup'] = false;
+ $_SESSION['skipThisStep']['displayJavascriptCode'] = false;
+
+ $view = new Piwik_Install_View(
+ $this->pathView . 'databaseSetup.tpl',
+ $this->getInstallationSteps(),
+ __FUNCTION__
+ );
+ $this->checkPreviousStepIsValid( __FUNCTION__ );
+ $this->skipThisStep( __FUNCTION__ );
+
+ $view->showNextStep = false;
+ require_once "FormDatabaseSetup.php";
+ $form = new Piwik_Installation_FormDatabaseSetup;
+
+ if($form->validate())
+ {
+ $dbInfos = array(
+ 'host' => $form->getSubmitValue('host'),
+ 'username' => $form->getSubmitValue('username'),
+ 'password' => $form->getSubmitValue('password'),
+ 'dbname' => $form->getSubmitValue('dbname'),
+ 'tables_prefix' => $form->getSubmitValue('tables_prefix'),
+ 'adapter' => Zend_Registry::get('config')->database->adapter,
+ 'port' => Zend_Registry::get('config')->database->port,
+ );
+
+ $dbInfos['password'] = '"'.htmlspecialchars($form->getSubmitValue('password')).'"';
+
+ if(($portIndex = strpos($dbInfos['host'],':')) !== false)
+ {
+ $dbInfos['port'] = substr($dbInfos['host'], $portIndex + 1 );
+ $dbInfos['host'] = substr($dbInfos['host'], 0, $portIndex);
+ }
try{
try {
@@ -152,64 +152,64 @@ class Piwik_Installation_Controller extends Piwik_Controller
{
throw new Exception(vsprintf("Your MySQL version is %s but Piwik requires at least %s.", array($mysqlVersion, $minimumMysqlVersion)));
}
-
+
$_SESSION['db_infos'] = $dbInfos;
- $this->redirectToNextStep( __FUNCTION__ );
- } catch(Exception $e) {
- $view->errorMessage = $e->getMessage();
- }
- }
- $view->addForm($form);
-
- $view->infos = $this->getSystemInformation();
-
- echo $view->render();
- }
-
- function tablesCreation()
- {
- $view = new Piwik_Install_View(
- $this->pathView . 'tablesCreation.tpl',
- $this->getInstallationSteps(),
- __FUNCTION__
- );
- $this->checkPreviousStepIsValid( __FUNCTION__ );
- $this->skipThisStep( __FUNCTION__ );
- $this->createDbFromSessionInformation();
-
- if(Piwik_Common::getRequestVar('deleteTables', 0, 'int') == 1)
- {
- Piwik::dropTables();
- $view->existingTablesDeleted = true;
-
- // when the user decides to drop the tables then we dont skip the next steps anymore
- $_SESSION['skipThisStep']['firstWebsiteSetup'] = false;
- $_SESSION['skipThisStep']['displayJavascriptCode'] = false;
- }
-
- $tablesInstalled = Piwik::getTablesInstalled();
- $tablesToInstall = Piwik::getTablesNames();
-
- if(count($tablesInstalled) > 0)
- {
- $view->someTablesInstalled = true;
- $view->tablesInstalled = implode(", ", $tablesInstalled);
-
- // when the user reuses the same tables we skip the website creation step
- $_SESSION['skipThisStep']['firstWebsiteSetup'] = true;
- $_SESSION['skipThisStep']['displayJavascriptCode'] = true;
- }
- else
- {
- Piwik::createTables();
- Piwik::createAnonymousUser();
+ $this->redirectToNextStep( __FUNCTION__ );
+ } catch(Exception $e) {
+ $view->errorMessage = $e->getMessage();
+ }
+ }
+ $view->addForm($form);
+
+ $view->infos = $this->getSystemInformation();
+
+ echo $view->render();
+ }
+
+ function tablesCreation()
+ {
+ $view = new Piwik_Install_View(
+ $this->pathView . 'tablesCreation.tpl',
+ $this->getInstallationSteps(),
+ __FUNCTION__
+ );
+ $this->checkPreviousStepIsValid( __FUNCTION__ );
+ $this->skipThisStep( __FUNCTION__ );
+ $this->createDbFromSessionInformation();
+
+ if(Piwik_Common::getRequestVar('deleteTables', 0, 'int') == 1)
+ {
+ Piwik::dropTables();
+ $view->existingTablesDeleted = true;
+
+ // when the user decides to drop the tables then we dont skip the next steps anymore
+ $_SESSION['skipThisStep']['firstWebsiteSetup'] = false;
+ $_SESSION['skipThisStep']['displayJavascriptCode'] = false;
+ }
+
+ $tablesInstalled = Piwik::getTablesInstalled();
+ $tablesToInstall = Piwik::getTablesNames();
+
+ if(count($tablesInstalled) > 0)
+ {
+ $view->someTablesInstalled = true;
+ $view->tablesInstalled = implode(", ", $tablesInstalled);
+
+ // when the user reuses the same tables we skip the website creation step
+ $_SESSION['skipThisStep']['firstWebsiteSetup'] = true;
+ $_SESSION['skipThisStep']['displayJavascriptCode'] = true;
+ }
+ else
+ {
+ Piwik::createTables();
+ Piwik::createAnonymousUser();
require_once "Version.php";
- require_once "Updater.php";
+ require_once "Updater.php";
$updater = new Piwik_Updater();
- $updater->recordComponentSuccessfullyUpdated('core', Piwik_Version::VERSION);
- $view->tablesCreated = true;
- $view->showNextStep = true;
- }
+ $updater->recordComponentSuccessfullyUpdated('core', Piwik_Version::VERSION);
+ $view->tablesCreated = true;
+ $view->showNextStep = true;
+ }
if(isset($_SESSION['databaseCreated'])
&& $_SESSION['databaseCreated'] === true)
@@ -218,294 +218,294 @@ class Piwik_Installation_Controller extends Piwik_Controller
$view->databaseCreated = true;
$_SESSION['databaseCreated'] = null;
}
-
- $_SESSION['currentStepDone'] = __FUNCTION__;
- echo $view->render();
- }
-
- function generalSetup()
- {
- $view = new Piwik_Install_View(
- $this->pathView . 'generalSetup.tpl',
- $this->getInstallationSteps(),
- __FUNCTION__
- );
- $this->checkPreviousStepIsValid( __FUNCTION__ );
- $this->skipThisStep( __FUNCTION__ );
-
- require_once "FormGeneralSetup.php";
- $form = new Piwik_Installation_FormGeneralSetup;
-
- if($form->validate())
- {
- $superUserInfos = array(
- 'login' => $form->getSubmitValue('login'),
- 'password' => md5( $form->getSubmitValue('password') ),
- 'email' => $form->getSubmitValue('email'),
- );
-
- $_SESSION['superuser_infos'] = $superUserInfos;
- $this->redirectToNextStep( __FUNCTION__ );
- }
- $view->addForm($form);
-
- echo $view->render();
- }
-
- public function firstWebsiteSetup()
- {
-
- $view = new Piwik_Install_View(
- $this->pathView . 'firstWebsiteSetup.tpl',
- $this->getInstallationSteps(),
- __FUNCTION__
- );
- $this->checkPreviousStepIsValid( __FUNCTION__ );
- $this->skipThisStep( __FUNCTION__ );
-
- require_once "FormFirstWebsiteSetup.php";
- $form = new Piwik_Installation_FormFirstWebsiteSetup;
-
- if( !isset($_SESSION['generalSetupSuccessMessage']))
- {
- $view->displayGeneralSetupSuccess = true;
- $_SESSION['generalSetupSuccessMessage'] = true;
- }
-
- if($form->validate())
- {
- // we setup the superuser login & password in the config that will be checked by the
- // API authentication process
- Zend_Registry::get('config')->superuser = $_SESSION['superuser_infos'];
-
- $name = urlencode($form->getSubmitValue('siteName'));
- $url = urlencode($form->getSubmitValue('url'));
-
- $this->initObjectsToCallAPI();
-
- require_once "API/Request.php";
- $request = new Piwik_API_Request("
- method=SitesManager.addSite
- &siteName=$name
- &urls=$url
- &format=original
- ");
-
- try {
- $result = $request->process();
- $_SESSION['site_idSite'] = $result;
- $_SESSION['site_name'] = $name;
- $_SESSION['site_url'] = $url;
-
- $this->redirectToNextStep( __FUNCTION__ );
- } catch(Exception $e) {
- $view->errorMessage = $e->getMessage();
- }
-
- }
- $view->addForm($form);
- echo $view->render();
+
+ $_SESSION['currentStepDone'] = __FUNCTION__;
+ echo $view->render();
+ }
+
+ function generalSetup()
+ {
+ $view = new Piwik_Install_View(
+ $this->pathView . 'generalSetup.tpl',
+ $this->getInstallationSteps(),
+ __FUNCTION__
+ );
+ $this->checkPreviousStepIsValid( __FUNCTION__ );
+ $this->skipThisStep( __FUNCTION__ );
+
+ require_once "FormGeneralSetup.php";
+ $form = new Piwik_Installation_FormGeneralSetup;
+
+ if($form->validate())
+ {
+ $superUserInfos = array(
+ 'login' => $form->getSubmitValue('login'),
+ 'password' => md5( $form->getSubmitValue('password') ),
+ 'email' => $form->getSubmitValue('email'),
+ );
+
+ $_SESSION['superuser_infos'] = $superUserInfos;
+ $this->redirectToNextStep( __FUNCTION__ );
+ }
+ $view->addForm($form);
+
+ echo $view->render();
}
-
- public function displayJavascriptCode()
- {
- $view = new Piwik_Install_View(
- $this->pathView . 'displayJavascriptCode.tpl',
- $this->getInstallationSteps(),
- __FUNCTION__
- );
- $this->checkPreviousStepIsValid( __FUNCTION__ );
- $this->skipThisStep( __FUNCTION__ );
-
- if( !isset($_SESSION['firstWebsiteSetupSuccessMessage']))
- {
- $view->displayfirstWebsiteSetupSuccess = true;
- $_SESSION['firstWebsiteSetupSuccessMessage'] = true;
- }
-
-
- $view->websiteName = urldecode($_SESSION['site_name']);
-
- $jsTag = Piwik::getJavascriptCode($_SESSION['site_idSite'], Piwik_Url::getCurrentUrlWithoutFileName());
-
- $view->javascriptTag = $jsTag;
- $view->showNextStep = true;
-
- $_SESSION['currentStepDone'] = __FUNCTION__;
- echo $view->render();
- }
-
- public function finished()
- {
- $view = new Piwik_Install_View(
- $this->pathView . 'finished.tpl',
- $this->getInstallationSteps(),
- __FUNCTION__
- );
- $this->checkPreviousStepIsValid( __FUNCTION__ );
- $this->skipThisStep( __FUNCTION__ );
- $this->writeConfigFileFromSession();
-
- $_SESSION['currentStepDone'] = __FUNCTION__;
- $view->showNextStep = false;
-
- setcookie(session_name(), session_id(), 1, '/');
- @session_destroy();
- echo $view->render();
- }
-
- protected function initObjectsToCallAPI()
- {
- // connect to the database using the DB infos currently in the session
- $this->createDbFromSessionInformation();
-
- // create the fake access to grant super user privilege
- Zend_Registry::set('access', new Piwik_FakeAccess_SetSuperUser);
-
- // we need to create the logs otherwise the API request throws an exception
- Piwik::createLogObject();
- }
-
- protected function writeConfigFileFromSession()
+
+ public function firstWebsiteSetup()
+ {
+
+ $view = new Piwik_Install_View(
+ $this->pathView . 'firstWebsiteSetup.tpl',
+ $this->getInstallationSteps(),
+ __FUNCTION__
+ );
+ $this->checkPreviousStepIsValid( __FUNCTION__ );
+ $this->skipThisStep( __FUNCTION__ );
+
+ require_once "FormFirstWebsiteSetup.php";
+ $form = new Piwik_Installation_FormFirstWebsiteSetup;
+
+ if( !isset($_SESSION['generalSetupSuccessMessage']))
+ {
+ $view->displayGeneralSetupSuccess = true;
+ $_SESSION['generalSetupSuccessMessage'] = true;
+ }
+
+ if($form->validate())
+ {
+ // we setup the superuser login & password in the config that will be checked by the
+ // API authentication process
+ Zend_Registry::get('config')->superuser = $_SESSION['superuser_infos'];
+
+ $name = urlencode($form->getSubmitValue('siteName'));
+ $url = urlencode($form->getSubmitValue('url'));
+
+ $this->initObjectsToCallAPI();
+
+ require_once "API/Request.php";
+ $request = new Piwik_API_Request("
+ method=SitesManager.addSite
+ &siteName=$name
+ &urls=$url
+ &format=original
+ ");
+
+ try {
+ $result = $request->process();
+ $_SESSION['site_idSite'] = $result;
+ $_SESSION['site_name'] = $name;
+ $_SESSION['site_url'] = $url;
+
+ $this->redirectToNextStep( __FUNCTION__ );
+ } catch(Exception $e) {
+ $view->errorMessage = $e->getMessage();
+ }
+
+ }
+ $view->addForm($form);
+ echo $view->render();
+ }
+
+ public function displayJavascriptCode()
+ {
+ $view = new Piwik_Install_View(
+ $this->pathView . 'displayJavascriptCode.tpl',
+ $this->getInstallationSteps(),
+ __FUNCTION__
+ );
+ $this->checkPreviousStepIsValid( __FUNCTION__ );
+ $this->skipThisStep( __FUNCTION__ );
+
+ if( !isset($_SESSION['firstWebsiteSetupSuccessMessage']))
+ {
+ $view->displayfirstWebsiteSetupSuccess = true;
+ $_SESSION['firstWebsiteSetupSuccessMessage'] = true;
+ }
+
+
+ $view->websiteName = urldecode($_SESSION['site_name']);
+
+ $jsTag = Piwik::getJavascriptCode($_SESSION['site_idSite'], Piwik_Url::getCurrentUrlWithoutFileName());
+
+ $view->javascriptTag = $jsTag;
+ $view->showNextStep = true;
+
+ $_SESSION['currentStepDone'] = __FUNCTION__;
+ echo $view->render();
+ }
+
+ public function finished()
+ {
+ $view = new Piwik_Install_View(
+ $this->pathView . 'finished.tpl',
+ $this->getInstallationSteps(),
+ __FUNCTION__
+ );
+ $this->checkPreviousStepIsValid( __FUNCTION__ );
+ $this->skipThisStep( __FUNCTION__ );
+ $this->writeConfigFileFromSession();
+
+ $_SESSION['currentStepDone'] = __FUNCTION__;
+ $view->showNextStep = false;
+
+ setcookie(session_name(), session_id(), 1, '/');
+ @session_destroy();
+ echo $view->render();
+ }
+
+ protected function initObjectsToCallAPI()
+ {
+ // connect to the database using the DB infos currently in the session
+ $this->createDbFromSessionInformation();
+
+ // create the fake access to grant super user privilege
+ Zend_Registry::set('access', new Piwik_FakeAccess_SetSuperUser);
+
+ // we need to create the logs otherwise the API request throws an exception
+ Piwik::createLogObject();
+ }
+
+ protected function writeConfigFileFromSession()
{
if(!isset($_SESSION['superuser_infos'])
|| !isset($_SESSION['db_infos']))
{
return;
- }
- $configFile = "; <?php exit; ?> DO NOT REMOVE THIS LINE\n";
- $configFile .= "; file automatically generated during the piwik installation process\n";
-
- // super user information
- $configFile .= "[superuser]\n";
- foreach( $_SESSION['superuser_infos'] as $key => $value)
- {
- $configFile .= "$key = $value\n";
- }
- $configFile .= "\n";
-
- // database information
- $configFile .= "[database]\n";
- foreach($_SESSION['db_infos'] as $key => $value)
- {
- $configFile .= "$key = $value\n";
- }
-
- file_put_contents(Piwik_Config::getDefaultUserConfigPath(), $configFile);
- }
- /**
- * The previous step is valid if it is either
- * - any step before (OK to go back)
- * - the current step (case when validating a form)
- */
- function checkPreviousStepIsValid( $currentStep )
+ }
+ $configFile = "; <?php exit; ?> DO NOT REMOVE THIS LINE\n";
+ $configFile .= "; file automatically generated during the piwik installation process\n";
+
+ // super user information
+ $configFile .= "[superuser]\n";
+ foreach( $_SESSION['superuser_infos'] as $key => $value)
+ {
+ $configFile .= "$key = $value\n";
+ }
+ $configFile .= "\n";
+
+ // database information
+ $configFile .= "[database]\n";
+ foreach($_SESSION['db_infos'] as $key => $value)
+ {
+ $configFile .= "$key = $value\n";
+ }
+
+ file_put_contents(Piwik_Config::getDefaultUserConfigPath(), $configFile);
+ }
+ /**
+ * The previous step is valid if it is either
+ * - any step before (OK to go back)
+ * - the current step (case when validating a form)
+ */
+ function checkPreviousStepIsValid( $currentStep )
{
if(empty($_SESSION['currentStepDone']))
{
return;
- }
- // the currentStep
- $currentStepId = array_search($currentStep, $this->steps);
-
- // the step before
- $previousStepId = array_search($_SESSION['currentStepDone'], $this->steps);
+ }
+ // the currentStep
+ $currentStepId = array_search($currentStep, $this->steps);
+
+ // the step before
+ $previousStepId = array_search($_SESSION['currentStepDone'], $this->steps);
- // not OK if currentStepId > previous+1
- if( $currentStepId > $previousStepId + 1 )
- {
- $message = "Error: it seems you try to skip a step of the Installation process,
- or your cookies are disabled.
- <br /><b>Make sure your cookies are enabled</b> and go back
- <a href='".Piwik_Url::getCurrentUrlWithoutFileName()."'>
- to the first page of the installation</a>.";
- Piwik::exitWithErrorMessage( $message );
- }
- }
-
- protected function redirectToNextStep($currentStep)
- {
- $_SESSION['currentStepDone'] = $currentStep;
- $nextStep = $this->steps[1 + array_search($currentStep, $this->steps)];
- Piwik::redirectToModule('Installation' , $nextStep);
- }
-
- protected function createDbFromSessionInformation()
- {
- $dbInfos = $_SESSION['db_infos'];
-
- Zend_Registry::get('config')->database = $dbInfos;
- Piwik::createDatabaseObject($dbInfos);
- }
-
- protected function getSystemInformation()
- {
- $minimumPhpVersion = Zend_Registry::get('config')->General->minimum_php_version;
- $minimumMemoryLimit = Zend_Registry::get('config')->General->minimum_memory_limit;
-
- $infos = array();
-
- $infos['directories'] = Piwik::checkDirectoriesWritable();
- $infos['phpVersion_minimum'] = $minimumPhpVersion;
- $infos['phpVersion'] = phpversion();
- $infos['phpVersion_ok'] = version_compare( $minimumPhpVersion, $infos['phpVersion']) === -1;
-
- $extensions = @get_loaded_extensions();
-
- $infos['pdo_ok'] = false;
- if (in_array('PDO', $extensions))
- {
- $infos['pdo_ok'] = true;
- }
-
- $infos['pdo_mysql_ok'] = false;
- if (in_array('pdo_mysql', $extensions))
- {
- $infos['pdo_mysql_ok'] = true;
- }
-
- $infos['gd_ok'] = false;
- if (in_array('gd', $extensions))
- {
- $gdInfo = gd_info();
- $infos['gd_version'] = $gdInfo['GD Version'];
- ereg ("([0-9]{1})", $gdInfo['GD Version'], $gdVersion);
- if($gdVersion[0] >= 2)
- {
- $infos['gd_ok'] = true;
- }
- }
-
- $infos['serverVersion'] = addslashes($_SERVER['SERVER_SOFTWARE']);
- $infos['serverOs'] = @php_uname();
- $infos['serverTime'] = date('H:i:s');
-
- $infos['setTimeLimit_ok'] = false;
- if(function_exists( 'set_time_limit'))
- {
- $infos['setTimeLimit_ok'] = true;
- }
-
- $infos['mail_ok'] = false;
- if(function_exists('mail'))
- {
- $infos['mail_ok'] = true;
- }
-
- $infos['registerGlobals_ok'] = ini_get('register_globals') == 0;
- $infos['memoryMinimum'] = $minimumMemoryLimit;
-
- $infos['memory_ok'] = true;
- // on windows the ini_get is not working?
- $infos['memoryCurrent'] = '?M';
-
- $raised = Piwik::raiseMemoryLimitIfNecessary();
- if( $memoryValue = Piwik::getMemoryLimitValue() )
- {
- $infos['memoryCurrent'] = $memoryValue."M";
- $infos['memory_ok'] = $memoryValue >= $minimumMemoryLimit;
- }
-
- return $infos;
+ // not OK if currentStepId > previous+1
+ if( $currentStepId > $previousStepId + 1 )
+ {
+ $message = "Error: it seems you try to skip a step of the Installation process,
+ or your cookies are disabled.
+ <br /><b>Make sure your cookies are enabled</b> and go back
+ <a href='".Piwik_Url::getCurrentUrlWithoutFileName()."'>
+ to the first page of the installation</a>.";
+ Piwik::exitWithErrorMessage( $message );
+ }
+ }
+
+ protected function redirectToNextStep($currentStep)
+ {
+ $_SESSION['currentStepDone'] = $currentStep;
+ $nextStep = $this->steps[1 + array_search($currentStep, $this->steps)];
+ Piwik::redirectToModule('Installation' , $nextStep);
+ }
+
+ protected function createDbFromSessionInformation()
+ {
+ $dbInfos = $_SESSION['db_infos'];
+
+ Zend_Registry::get('config')->database = $dbInfos;
+ Piwik::createDatabaseObject($dbInfos);
+ }
+
+ protected function getSystemInformation()
+ {
+ $minimumPhpVersion = Zend_Registry::get('config')->General->minimum_php_version;
+ $minimumMemoryLimit = Zend_Registry::get('config')->General->minimum_memory_limit;
+
+ $infos = array();
+
+ $infos['directories'] = Piwik::checkDirectoriesWritable();
+ $infos['phpVersion_minimum'] = $minimumPhpVersion;
+ $infos['phpVersion'] = phpversion();
+ $infos['phpVersion_ok'] = version_compare( $minimumPhpVersion, $infos['phpVersion']) === -1;
+
+ $extensions = @get_loaded_extensions();
+
+ $infos['pdo_ok'] = false;
+ if (in_array('PDO', $extensions))
+ {
+ $infos['pdo_ok'] = true;
+ }
+
+ $infos['pdo_mysql_ok'] = false;
+ if (in_array('pdo_mysql', $extensions))
+ {
+ $infos['pdo_mysql_ok'] = true;
+ }
+
+ $infos['gd_ok'] = false;
+ if (in_array('gd', $extensions))
+ {
+ $gdInfo = gd_info();
+ $infos['gd_version'] = $gdInfo['GD Version'];
+ ereg ("([0-9]{1})", $gdInfo['GD Version'], $gdVersion);
+ if($gdVersion[0] >= 2)
+ {
+ $infos['gd_ok'] = true;
+ }
+ }
+
+ $infos['serverVersion'] = addslashes($_SERVER['SERVER_SOFTWARE']);
+ $infos['serverOs'] = @php_uname();
+ $infos['serverTime'] = date('H:i:s');
+
+ $infos['setTimeLimit_ok'] = false;
+ if(function_exists( 'set_time_limit'))
+ {
+ $infos['setTimeLimit_ok'] = true;
+ }
+
+ $infos['mail_ok'] = false;
+ if(function_exists('mail'))
+ {
+ $infos['mail_ok'] = true;
+ }
+
+ $infos['registerGlobals_ok'] = ini_get('register_globals') == 0;
+ $infos['memoryMinimum'] = $minimumMemoryLimit;
+
+ $infos['memory_ok'] = true;
+ // on windows the ini_get is not working?
+ $infos['memoryCurrent'] = '?M';
+
+ $raised = Piwik::raiseMemoryLimitIfNecessary();
+ if( $memoryValue = Piwik::getMemoryLimitValue() )
+ {
+ $infos['memoryCurrent'] = $memoryValue."M";
+ $infos['memory_ok'] = $memoryValue >= $minimumMemoryLimit;
+ }
+
+ return $infos;
}
@@ -516,18 +516,18 @@ class Piwik_Installation_Controller extends Piwik_Controller
{
$this->redirectToNextStep($step);
}
- }
-}
-
-
-/**
- *
- * @package Piwik_Installation
- */
-class Piwik_FakeAccess_SetSuperUser {
- function checkUserIsSuperUser()
- {
- return true;
- }
- function loadAccess() {}
-}
+ }
+}
+
+
+/**
+ *
+ * @package Piwik_Installation
+ */
+class Piwik_FakeAccess_SetSuperUser {
+ function checkUserIsSuperUser()
+ {
+ return true;
+ }
+ function loadAccess() {}
+}
diff --git a/plugins/Installation/templates/firstWebsiteSetup.tpl b/plugins/Installation/templates/firstWebsiteSetup.tpl
index ca83f4ccd8..3c0446bc3c 100644
--- a/plugins/Installation/templates/firstWebsiteSetup.tpl
+++ b/plugins/Installation/templates/firstWebsiteSetup.tpl
@@ -9,8 +9,6 @@
<h1>{'Installation_SetupWebsite'|translate}</h1>
-
-
{if isset($errorMessage)}
<div class="error">
<img src="themes/default/images/error_medium.png">
@@ -20,7 +18,6 @@
</div>
{/if}
-
{if isset($form_data)}
{include file=default/genericForm.tpl}
{/if}
diff --git a/plugins/LanguagesManager/API.php b/plugins/LanguagesManager/API.php
index 20411a7021..edb5d1aa7b 100644
--- a/plugins/LanguagesManager/API.php
+++ b/plugins/LanguagesManager/API.php
@@ -2,7 +2,7 @@
/**
* @package Piwik_LanguagesManager
*/
-class Piwik_LanguagesManager_API extends Piwik_Apiable
+class Piwik_LanguagesManager_API
{
static private $instance = null;
static public function getInstance()
diff --git a/plugins/Live/API.php b/plugins/Live/API.php
new file mode 100644
index 0000000000..3ff93c223a
--- /dev/null
+++ b/plugins/Live/API.php
@@ -0,0 +1,143 @@
+<?php
+require_once "Live/Visitor.php";
+
+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;
+ }
+
+ /*
+ * @return Piwik_DataTable
+ */
+ public function getLastVisitForVisitor( $visitorId, $idSite = null )
+ {
+ return $this->getLastVisitsForVisitor($visitorId, $idSite, 1);
+ }
+
+ /*
+ * @return Piwik_DataTable
+ */
+ public function getLastVisitsForVisitor( $visitorId, $idSite, $limit = 10 )
+ {
+ if(is_null($idSite))
+ {
+ Piwik::checkUserIsSuperUser();
+ }
+ else
+ {
+ Piwik::checkUserHasViewAccess($idSite);
+ }
+ $visitorDetails = self::loadLastVisitorDetailsFromDatabase($visitorId, $idSite, $limit);
+ $table = self::getCleanedVisitorsFromDetails($visitorDetails);
+ return $table;
+ }
+
+ /*
+ * @return Piwik_DataTable
+ */
+ public function getLastVisits( $idSite = false, $limit = 10, $minIdVisit = false )
+ {
+ if(is_null($idSite))
+ {
+ Piwik::checkUserIsSuperUser();
+ }
+ else
+ {
+ Piwik::checkUserHasViewAccess($idSite);
+ }
+ $visitorDetails = self::loadLastVisitorDetailsFromDatabase(null, $idSite, $limit, $minIdVisit);
+ $table = self::getCleanedVisitorsFromDetails($visitorDetails);
+ return $table;
+ }
+
+ /*
+ * @return Piwik_DataTable
+ */
+ static private function getCleanedVisitorsFromDetails($visitorDetails)
+ {
+ $table = new Piwik_DataTable();
+ foreach($visitorDetails as $visitorDetail)
+ {
+ self::cleanVisitorDetails($visitorDetail);
+ $visitor = new Piwik_Live_Visitor($visitorDetail);
+ $visitorDetailsArray = $visitor->getAllVisitorDetails();
+ $dateTimeVisit = Piwik_Date::factory($visitorDetailsArray['firstActionTimestamp']);
+ $visitorDetailsArray['serverDatePretty'] = $dateTimeVisit->getLocalized('%a %d %b');
+ $visitorDetailsArray['serverTimePretty'] = $dateTimeVisit->getLocalized('%X');
+ $table->addRowFromArray( array(Piwik_DataTable_Row::COLUMNS => $visitorDetailsArray));
+ }
+ return $table;
+ }
+
+ /*
+ * @return array
+ */
+ private function loadLastVisitorDetailsFromDatabase($visitorId = null, $idSite = null, $limit = null, $minIdVisit = false )
+ {
+ $where = $whereBind = array();
+
+ if(!is_null($idSite))
+ {
+ $where[] = " idsite = ? ";
+ $whereBind[] = $idSite;
+ }
+
+ if(!is_null($visitorId))
+ {
+ $where[] = " visitor_idcookie = ? ";
+ $whereBind[] = $visitorId;
+ }
+
+ if(!$minIdVisit)
+ {
+ $where[] = " idvisit > ? ";
+ $whereBind[] = $minIdVisit;
+ }
+
+ $sqlWhere = "";
+ if(count($where) > 0)
+ {
+ $sqlWhere = " WHERE " . join(' AND ', $where);
+ }
+
+ $sql = "SELECT *
+ FROM " . Piwik::prefixTable('log_visit') . "
+ $sqlWhere
+ ORDER BY idvisit DESC
+ LIMIT $limit";
+
+ return Piwik_FetchAll($sql, $whereBind);
+ }
+
+ /*
+ * @return void
+ */
+ static 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]);
+ }
+ }
+ }
+}
diff --git a/plugins/Live/Controller.php b/plugins/Live/Controller.php
new file mode 100644
index 0000000000..aeb13829d9
--- /dev/null
+++ b/plugins/Live/Controller.php
@@ -0,0 +1,37 @@
+<?php
+require_once 'Live/API.php';
+
+Piwik_AddWidget('Live', 'widget', 'Live Visitors!');
+
+class Piwik_Live_Controller extends Piwik_Controller
+{
+ function widget()
+ {
+ echo "Live Visitors!";
+ }
+
+ function getLastVisits($fetch = false)
+ {
+ $idSite = Piwik_Common::getRequestVar('idSite', null, 'int');
+ $limit = 10;
+ $api = new Piwik_API_Request("method=Live.getLastVisits&idSite=$idSite&limit=$limit&format=php&serialize=0&disable_generic_filters=1");
+
+ $view = new Piwik_View('Live/templates/lastVisits.tpl');
+ $view->visitors = $api->process();
+ $rendered = $view->render($fetch);
+
+ if($fetch)
+ {
+ return $rendered;
+ }
+ echo $rendered;
+ }
+
+ function index()
+ {
+ $view = new Piwik_View('Live/templates/index.tpl');
+ $this->setGeneralVariablesView($view);
+ $view->visitors = $this->getLastVisits($fetch = true);
+ echo $view->render();
+ }
+}
diff --git a/plugins/Live/Live.php b/plugins/Live/Live.php
new file mode 100644
index 0000000000..d6432bf447
--- /dev/null
+++ b/plugins/Live/Live.php
@@ -0,0 +1,14 @@
+<?php
+class Piwik_Live extends Piwik_Plugin
+{
+ public function getInformation()
+ {
+ return array(
+ 'name' => 'Live Visitors',
+ 'description' => 'Live Visitors!',
+ 'author' => 'Piwik',
+ 'homepage' => 'http://piwik.org/',
+ 'version' => '0.1',
+ );
+ }
+}
diff --git a/plugins/Live/Visitor.php b/plugins/Live/Visitor.php
new file mode 100644
index 0000000000..0145641a69
--- /dev/null
+++ b/plugins/Live/Visitor.php
@@ -0,0 +1,262 @@
+<?php
+//TODO add api to get actions name/count/first/last/etc
+require_once "Referers/functions.php";
+require_once "UserCountry/functions.php";
+require_once "UserSettings/functions.php";
+require_once "Provider/functions.php";
+
+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(),
+ );
+ }
+
+ function getServerDate()
+ {
+ return $this->details['visit_server_date'];
+ }
+
+ 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()
+ {
+ $searchEngine = $this->getSearchEngineUrl();
+ if( !is_null($searchEngine) )
+ {
+ return Piwik_getSearchEngineLogoFromName($searchEngine);
+ }
+ return null;
+ }
+
+ function getPlugins()
+ {
+ $plugins = array(
+ 'config_pdf',
+ 'config_flash',
+ 'config_java',
+ 'config_director',
+ 'config_quicktime',
+ 'config_realplayer',
+ 'config_windowsmedia'
+ );
+ $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']);
+ }
+}
diff --git a/plugins/Live/templates/images/pause.gif b/plugins/Live/templates/images/pause.gif
new file mode 100644
index 0000000000..5954f9f545
--- /dev/null
+++ b/plugins/Live/templates/images/pause.gif
Binary files differ
diff --git a/plugins/Live/templates/images/pause_disabled.gif b/plugins/Live/templates/images/pause_disabled.gif
new file mode 100644
index 0000000000..98b79f7402
--- /dev/null
+++ b/plugins/Live/templates/images/pause_disabled.gif
Binary files differ
diff --git a/plugins/Live/templates/images/play.gif b/plugins/Live/templates/images/play.gif
new file mode 100644
index 0000000000..87eded433b
--- /dev/null
+++ b/plugins/Live/templates/images/play.gif
Binary files differ
diff --git a/plugins/Live/templates/images/play_disabled.gif b/plugins/Live/templates/images/play_disabled.gif
new file mode 100644
index 0000000000..ef69513d69
--- /dev/null
+++ b/plugins/Live/templates/images/play_disabled.gif
Binary files differ
diff --git a/plugins/Live/templates/images/returningVisitor.gif b/plugins/Live/templates/images/returningVisitor.gif
new file mode 100644
index 0000000000..bc71867e55
--- /dev/null
+++ b/plugins/Live/templates/images/returningVisitor.gif
Binary files differ
diff --git a/plugins/Live/templates/index.tpl b/plugins/Live/templates/index.tpl
new file mode 100644
index 0000000000..a30eef0739
--- /dev/null
+++ b/plugins/Live/templates/index.tpl
@@ -0,0 +1,83 @@
+{assign var=showSitesSelection value=true}
+{assign var=showPeriodSelection value=false}
+{include file="CoreAdminHome/templates/header.tpl"}
+
+<h1> Plugin Development version </h1>
+
+{literal}
+<script type="text/javascript" src="plugins/Live/templates/scripts/spy.js"></script>
+
+<script type="text/javascript" charset="utf-8">
+ $(document).ready(function() {
+ $('#visits').spy({ limit: 10, 'fadeInSpeed': '1400', ajax: 'index.php?module=Live&idSite=1&action=getLastVisits', timeout: 5000, customParameterName: 'minIdVisit', customParameterValueCallback: lastIdVisit, fadeInSpeed: 1400 });
+ });
+
+ function lastIdVisit()
+ {
+ return $('#visits > 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();
+ }
+
+</script>
+
+<style>
+#visits {
+ text-align:left;
+}
+#visits .datetime, #visits .country, #visits .referer, #visits .settings, #visits .returning {
+ float:left;
+ margin-right:10px;
+ overflow:hidden;
+ padding-left:1px;
+ max-width:700px;
+}
+#visits .datetime {
+ width:110px;
+}
+#visits .country {
+ width:30px;
+}
+#visits .referer {
+ width:200px;
+}
+#visits .settings {
+ width:100px;
+}
+#visits .returning {
+ width:30px;
+}
+#visits .visit {
+ border-bottom:1px solid #C1DAD7;
+ background-color:#F9FAFA;
+ padding:10px;
+ line-height:24px;
+ height:40px;
+}
+#visits .alt {
+ background-color:#FFFFFF;
+}
+</style>
+{/literal}
+
+{$visitors}
+
+<div>
+ <a href="#?" onclick="onClickPause();"><img id="pauseImage" border="0" src="plugins/Live/templates/images/pause_disabled.gif"></a>
+ <a href="#?" onclick="onClickPlay();"><img id="playImage" border="0" src="plugins/Live/templates/images/play.gif"></a>
+</div>
diff --git a/plugins/Live/templates/lastVisits.tpl b/plugins/Live/templates/lastVisits.tpl
new file mode 100644
index 0000000000..ac515f2d63
--- /dev/null
+++ b/plugins/Live/templates/lastVisits.tpl
@@ -0,0 +1,15 @@
+<div id="visits">
+{foreach from=$visitors item=visitor}
+ <div class="visit{if $visitor.idVisit % 2} alt{/if}">
+ <div style="display:none" class="idvisit">{$visitor.idVisit}</div>
+ <div class="datetime">{$visitor.serverDatePretty}<br/>{$visitor.serverTimePretty}</div>
+ <div class="country"><img src="{$visitor.countryFlag}" title="{$visitor.country}, Provider {$visitor.provider}"></div>
+ <div class="referer">{if $visitor.refererType != 'directEntry'}from <a href="{$visitor.refererUrl}">{$visitor.refererName}</a> {if !empty($visitor.keywords)}"{$visitor.keywords}"{/if}{/if}</div>
+ <div class="settings">
+ <img src="{$visitor.browserIcon}" title="{$visitor.browser} with plugins {$visitor.plugins} enabled">
+ <img src="{$visitor.operatingSystemIcon}" title="{$visitor.operatingSystem}, {$visitor.resolution}">
+ </div>
+ <div class="returning">{if $visitor.isVisitorReturning}<img src="plugins/Live/templates/images/returningVisitor.gif" title="Returning Visitor">{/if}</div>
+ </div>
+{/foreach}
+</div>
diff --git a/plugins/Live/templates/scripts/spy.js b/plugins/Live/templates/scripts/spy.js
new file mode 100644
index 0000000000..ac296ab02f
--- /dev/null
+++ b/plugins/Live/templates/scripts/spy.js
@@ -0,0 +1,139 @@
+/*
+ jQuery Plugin spy (leftlogic.com/info/articles/jquery_spy2)
+ (c) 2006 Remy Sharp (leftlogic.com)
+ $Id$
+*/
+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 - 1) + ')').remove();
+ 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 = new Object;
+ 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);
+ });
+};
+
+function pauseSpy() {
+ spyRunning = 0; return false;
+}
+
+function playSpy() {
+ spyRunning = 1; return false;
+}
diff --git a/plugins/Login/Controller.php b/plugins/Login/Controller.php
index fbee6a38e0..54557e9563 100644
--- a/plugins/Login/Controller.php
+++ b/plugins/Login/Controller.php
@@ -100,70 +100,97 @@ class Piwik_Login_Controller extends Piwik_Controller
if($form->validate())
{
$loginMail = $form->getSubmitValue('form_login');
- Piwik::setUserIsSuperUser();
-
- $user = null;
-
- if( Piwik_UsersManager_API::userExists($loginMail) )
- {
- $user = Piwik_UsersManager_API::getUser($loginMail);
- }
- else if( Piwik_UsersManager_API::userEmailExists($loginMail) )
- {
- $user = Piwik_UsersManager_API::getUserByEmail($loginMail);
- }
+ $this->lostPasswordFormValidated($loginMail, $urlToRedirect);
+ return;
+ }
+ $view = new Piwik_View('Login/templates/lostPassword.tpl');
+ $view->AccessErrorString = $messageNoAccess;
+ // make navigation login form -> reset password -> login form remember your first url
+ $view->urlToRedirect = $urlToRedirect;
+ $view->linkTitle = Piwik::getRandomTitle();
+ $view->addForm( $form );
+ $view->subTemplate = 'genericForm.tpl';
+ echo $view->render();
+ }
+
+ protected function lostPasswordFormValidated($loginMail, $urlToRedirect)
+ {
+ Piwik::setUserIsSuperUser();
+ $user = null;
+ $isSuperUser = false;
+
+ if( $loginMail == Zend_Registry::get('config')->superuser->email
+ || $loginMail == Zend_Registry::get('config')->superuser->login )
+ {
+ $isSuperUser = true;
+ $user = array(
+ 'login' => Zend_Registry::get('config')->superuser->login,
+ 'email' => Zend_Registry::get('config')->superuser->email);
+ }
+ else if( Piwik_UsersManager_API::userExists($loginMail) )
+ {
+ $user = Piwik_UsersManager_API::getUser($loginMail);
+ }
+ else if( Piwik_UsersManager_API::userEmailExists($loginMail) )
+ {
+ $user = Piwik_UsersManager_API::getUserByEmail($loginMail);
+ }
- if( $user === null )
+ if( $user === null )
+ {
+ $messageNoAccess = Piwik_Translate('Login_InvalidUsernameEmail');
+ }
+ else
+ {
+ $view = new Piwik_View('Login/templates/passwordsent.tpl');
+
+ $login = $user['login'];
+ $email = $user['email'];
+ $randomPassword = Piwik_Common::getRandomString(8);
+
+ if($isSuperUser)
{
- $messageNoAccess = Piwik_Translate('Login_InvalidUsernameEmail');
+ $user['password'] = md5($randomPassword);
+ Zend_Registry::get('config')->superuser = $user;
}
else
{
- $view = new Piwik_View('Login/templates/passwordsent.tpl');
-
- $login = $user['login'];
- $email = $user['email'];
- $randomPassword = Piwik_Common::getRandomString(8);
Piwik_UsersManager_API::updateUser($login, $randomPassword);
+ }
- // send email with new password
- try
- {
- $mail = new Piwik_Mail();
- $mail->addTo($email, $login);
- $mail->setSubject(Piwik_Translate('Login_MailTopicPasswordRecovery'));
- $mail->setBodyText(sprintf(Piwik_Translate('Login_MailPasswordRecoveryBody'),
- $login, $randomPassword, Piwik_Url::getCurrentUrlWithoutQueryString()));
+ // 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, $randomPassword, Piwik_Url::getCurrentUrlWithoutQueryString())
+ )
+ );
- $host = $_SERVER['HTTP_HOST'];
- if(strlen($host) == 0)
- {
- $host = 'piwik.org';
- }
- $mail->setFrom('password-recovery@'.$host, 'Piwik');
- @$mail->send();
- }
- catch(Exception $e)
+ $host = $_SERVER['HTTP_HOST'];
+ if(strlen($host) == 0)
{
- $view->ErrorString = $e->getMessage();
+ $host = 'piwik.org';
}
-
- $view->linkTitle = Piwik::getRandomTitle();
- $view->urlToRedirect = $urlToRedirect;
- echo $view->render();
- return;
+ $mail->setFrom('password-recovery@'.$host, 'Piwik');
+ @$mail->send();
+ }
+ catch(Exception $e)
+ {
+ $view->ErrorString = $e->getMessage();
}
+
+ $view->linkTitle = Piwik::getRandomTitle();
+ $view->urlToRedirect = $urlToRedirect;
+ echo $view->render();
}
- $view = new Piwik_View('Login/templates/lostPassword.tpl');
- $view->AccessErrorString = $messageNoAccess;
- // make navigation login form -> reset password -> login form remember your first url
- $view->urlToRedirect = $urlToRedirect;
- $view->linkTitle = Piwik::getRandomTitle();
- $view->addForm( $form );
- $view->subTemplate = 'genericForm.tpl';
- echo $view->render();
}
-
+
static public function clearSession()
{
$authCookieName = 'piwik-auth';
diff --git a/plugins/Login/templates/login.tpl b/plugins/Login/templates/login.tpl
index 4b3ef37de9..0484425181 100644
--- a/plugins/Login/templates/login.tpl
+++ b/plugins/Login/templates/login.tpl
@@ -35,7 +35,7 @@
<p id="nav">
-<a href="?module=Login&amp;action=lostPassword&amp;form_url={$urlToRedirect}" title="{'Login_LostYourPassword'|translate}">{'Login_LostYourPassword'|translate}</a>
+<a href="?module=Login&amp;action=lostPassword&amp;form_url={$urlToRedirect|escape:url}" title="{'Login_LostYourPassword'|translate}">{'Login_LostYourPassword'|translate}</a>
</p>
</div>
diff --git a/plugins/Provider/API.php b/plugins/Provider/API.php
index 7f7c83f569..074ca64994 100644
--- a/plugins/Provider/API.php
+++ b/plugins/Provider/API.php
@@ -14,7 +14,7 @@ require_once "Provider/functions.php";
*
* @package Piwik_Provider
*/
-class Piwik_Provider_API extends Piwik_Apiable
+class Piwik_Provider_API
{
static private $instance = null;
@@ -38,18 +38,5 @@ class Piwik_Provider_API extends Piwik_Apiable
$dataTable->queueFilter('Piwik_DataTable_Filter_ReplaceColumnNames');
return $dataTable;
}
-
- /**
- * Example of getting a RAW BLOB
- *
- * @return blob
- */
- public function getProviderBlob( $idSite, $period, $date )
- {
- Piwik::checkUserHasViewAccess( $idSite );
- $archive = Piwik_Archive::build($idSite, $period, $date );
- $dataTable = $archive->getBlob('Provider_hostnameExt');
- return $dataTable;
- }
}
diff --git a/plugins/Provider/Controller.php b/plugins/Provider/Controller.php
index cc08f0b3e9..90d9674cc3 100644
--- a/plugins/Provider/Controller.php
+++ b/plugins/Provider/Controller.php
@@ -1,6 +1,4 @@
<?php
-require_once "ViewDataTable.php";
-
class Piwik_Provider_Controller extends Piwik_Controller
{
/**
@@ -9,12 +7,10 @@ class Piwik_Provider_Controller extends Piwik_Controller
function getProvider($fetch = false)
{
$view = Piwik_ViewDataTable::factory();
- $view->init( 'Provider', __FUNCTION__, "Provider.getProvider" );
-
+ $view->init( $this->pluginName, __FUNCTION__, "Provider.getProvider" );
$view->setColumnsToDisplay( array('label','nb_uniq_visitors') );
$view->setSortedColumn( 1 );
$view->setLimit( 5 );
-
return $this->renderView($view, $fetch);
}
diff --git a/plugins/Provider/Provider.php b/plugins/Provider/Provider.php
index a819797c31..0de4d5b8f8 100644
--- a/plugins/Provider/Provider.php
+++ b/plugins/Provider/Provider.php
@@ -97,7 +97,8 @@ class Piwik_Provider extends Piwik_Plugin
$recordName = 'Provider_hostnameExt';
$labelSQL = "location_provider";
- $tableProvider = $archiveProcessing->getDataTableInterestForLabel($labelSQL);
+ $interestByProvider = $archiveProcessing->getArrayInterestForLabel($labelSQL);
+ $tableProvider = $archiveProcessing->getDataTableFromArray($interestByProvider);
$record = new Piwik_ArchiveProcessing_Record_BlobArray($recordName, $tableProvider->getSerialized());
}
diff --git a/plugins/Referers/API.php b/plugins/Referers/API.php
index 8a5b8b5bca..ab60cc8c83 100644
--- a/plugins/Referers/API.php
+++ b/plugins/Referers/API.php
@@ -15,7 +15,7 @@ require_once "Referers/functions.php";
*
* @package Piwik_Referers
*/
-class Piwik_Referers_API extends Piwik_Apiable
+class Piwik_Referers_API
{
static private $instance = null;
static public function getInstance()
@@ -56,10 +56,10 @@ class Piwik_Referers_API extends Piwik_Apiable
$dataTable->queueFilter('Piwik_DataTable_Filter_ColumnCallbackReplace', array('label', 'Piwik_getRefererTypeLabel'));
return $dataTable;
}
-
+
function getKeywords($idSite, $period, $date, $expanded = false)
{
- $dataTable = $this->getDataTable('Referers_searchEngineByKeyword',$idSite, $period, $date, $expanded);
+ $dataTable = $this->getDataTable('Referers_searchEngineByKeyword', $idSite, $period, $date, $expanded);
return $dataTable;
}
diff --git a/plugins/Referers/Controller.php b/plugins/Referers/Controller.php
index c76d596b19..c064e8b83e 100644
--- a/plugins/Referers/Controller.php
+++ b/plugins/Referers/Controller.php
@@ -1,10 +1,9 @@
<?php
-require_once "ViewDataTable.php";
class Piwik_Referers_Controller extends Piwik_Controller
{
function index()
{
- $view = new Piwik_View('Referers/index.tpl');
+ $view = new Piwik_View('Referers/templates/index.tpl');
$view->graphEvolutionReferers = $this->getLastDirectEntryGraph(true);
$view->nameGraphEvolutionReferers = 'ReferersgetLastDirectEntryGraph'; // must be the function name used above
@@ -40,25 +39,24 @@ class Piwik_Referers_Controller extends Piwik_Controller
function getSearchEnginesAndKeywords()
{
- $view = new Piwik_View('Referers/searchEngines_Keywords.tpl');
+ $view = new Piwik_View('Referers/templates/searchEngines_Keywords.tpl');
$view->searchEngines = $this->getSearchEngines(true) ;
$view->keywords = $this->getKeywords(true);
echo $view->render();
}
- /**
- * Referers
- */
+
function getRefererType( $fetch = false)
{
$view = Piwik_ViewDataTable::factory('cloud');
$view->init( $this->pluginName,
- 'getRefererType',
+ __FUNCTION__,
'Referers.getRefererType'
);
$view->disableSearchBox();
$view->disableOffsetInformation();
$view->disableExcludeLowPopulation();
$view->doNotShowFooter();
+ $view->enableShowGoals();
$view->setColumnsToDisplay( array('label','nb_uniq_visitors', 'nb_visits') );
@@ -68,21 +66,21 @@ class Piwik_Referers_Controller extends Piwik_Controller
function getKeywords( $fetch = false)
{
$view = Piwik_ViewDataTable::factory();
-
- $view->init( $this->pluginName, 'getKeywords',
+ $view->init( $this->pluginName, __FUNCTION__,
'Referers.getKeywords',
'getSearchEnginesFromKeywordId'
);
$view->disableExcludeLowPopulation();
$view->setColumnsToDisplay( array('label','nb_visits') );
-
+ $view->enableShowGoals();
+ $view->disableSubTableWhenShowGoals();
return $this->renderView($view, $fetch);
}
function getSearchEnginesFromKeywordId( $fetch = false )
{
$view = Piwik_ViewDataTable::factory();
- $view->init( $this->pluginName, 'getSearchEnginesFromKeywordId',
+ $view->init( $this->pluginName, __FUNCTION__,
'Referers.getSearchEnginesFromKeywordId'
);
$view->disableSearchBox();
@@ -96,34 +94,36 @@ class Piwik_Referers_Controller extends Piwik_Controller
function getSearchEngines( $fetch = false)
{
$view = Piwik_ViewDataTable::factory();
- $view->init( $this->pluginName, 'getSearchEngines',
+ $view->init( $this->pluginName, __FUNCTION__,
'Referers.getSearchEngines',
'getKeywordsFromSearchEngineId'
);
$view->disableSearchBox();
$view->disableExcludeLowPopulation();
+ $view->enableShowGoals();
+ $view->disableSubTableWhenShowGoals();
$view->setColumnsToDisplay( array('label','nb_visits') );
return $this->renderView($view, $fetch);
}
- public function getSearchEnginesEvolution($fetch = false)
- {
- $view = Piwik_ViewDataTable::factory('graphEvolution');
- $view->init( 'Referers', __FUNCTION__, 'Referers.getSearchEngines' );
-
- $view->setColumnsToDisplay( 'nb_uniq_visitors' );
- $view->setExactPattern( array('Google','Yahoo!'), 'label');
- //$view->setExactPattern( array('Google'), 'label');
-
- return $this->renderView($view, $fetch);
- }
+ public function getSearchEnginesEvolution($fetch = false)
+ {
+ $view = Piwik_ViewDataTable::factory('graphEvolution');
+ $view->init( $this->pluginName, __FUNCTION__, 'Referers.getSearchEngines' );
+
+ $view->setColumnsToDisplay( 'nb_uniq_visitors' );
+ $view->setExactPattern( array('Google','Yahoo!'), 'label');
+ //$view->setExactPattern( array('Google'), 'label');
+
+ return $this->renderView($view, $fetch);
+ }
function getKeywordsFromSearchEngineId( $fetch = false )
{
$view = Piwik_ViewDataTable::factory();
- $view->init( $this->pluginName, 'getKeywordsFromSearchEngineId',
+ $view->init( $this->pluginName, __FUNCTION__,
'Referers.getKeywordsFromSearchEngineId'
);
$view->disableSearchBox();
@@ -136,20 +136,23 @@ class Piwik_Referers_Controller extends Piwik_Controller
function getWebsites( $fetch = false)
{
$view = Piwik_ViewDataTable::factory();
- $view->init( $this->pluginName, 'getWebsites',
+ $view->init( $this->pluginName, __FUNCTION__,
'Referers.getWebsites',
'getUrlsFromWebsiteId'
);
$view->disableExcludeLowPopulation();
$view->setColumnsToDisplay( array('label','nb_visits') );
$view->setLimit(10);
+ $view->enableShowGoals();
+ $view->disableSubTableWhenShowGoals();
+
return $this->renderView($view, $fetch);
}
function getCampaigns( $fetch = false)
{
$view = Piwik_ViewDataTable::factory();
- $view->init( $this->pluginName, 'getCampaigns',
+ $view->init( $this->pluginName, __FUNCTION__,
'Referers.getCampaigns',
'getKeywordsFromCampaignId'
);
@@ -157,16 +160,15 @@ class Piwik_Referers_Controller extends Piwik_Controller
$view->disableSearchBox();
$view->disableExcludeLowPopulation();
$view->setLimit( 5 );
-
+ $view->enableShowGoals();
$view->setColumnsToDisplay( array('label','nb_visits') );
-
return $this->renderView($view, $fetch);
}
function getKeywordsFromCampaignId( $fetch = false)
{
$view = Piwik_ViewDataTable::factory();
- $view->init( $this->pluginName, 'getKeywordsFromCampaignId',
+ $view->init( $this->pluginName, __FUNCTION__,
'Referers.getKeywordsFromCampaignId'
);
@@ -180,7 +182,7 @@ class Piwik_Referers_Controller extends Piwik_Controller
function getUrlsFromWebsiteId( $fetch = false)
{
$view = Piwik_ViewDataTable::factory();
- $view->init( $this->pluginName, 'getUrlsFromWebsiteId',
+ $view->init( $this->pluginName, __FUNCTION__,
'Referers.getUrlsFromWebsiteId'
);
$view->disableSearchBox();
@@ -189,7 +191,7 @@ class Piwik_Referers_Controller extends Piwik_Controller
return $this->renderView($view, $fetch);
}
- function getReferersType()
+ protected function getReferersVisitorsByType()
{
// we disable the queued filters because here we want to get the visits coming from search engines
// if the filters were applied we would have to look up for a label looking like "Search Engines"
@@ -198,13 +200,7 @@ class Piwik_Referers_Controller extends Piwik_Controller
&format=original
&disable_queued_filters=1";
$request = new Piwik_API_Request($requestString);
- return $request->process();
- }
-
- protected function getReferersVisitorsByType()
- {
- // this is raw data (no filters applied, on purpose) so we select the data using the magic integers ID
- $dataTableReferersType = $this->getReferersType(true);
+ $dataTableReferersType = $request->process();
$nameToColumnId = array(
'visitorsFromSearchEngines' => Piwik_Common::REFERER_TYPE_SEARCH_ENGINE,
diff --git a/plugins/Referers/Referers.php b/plugins/Referers/Referers.php
index fe23422512..339a75f73f 100644
--- a/plugins/Referers/Referers.php
+++ b/plugins/Referers/Referers.php
@@ -122,10 +122,22 @@ class Piwik_Referers extends Piwik_Plugin
);
}
}
-
+
+
public function archiveDay( $notification )
{
+ /**
+ * @var Piwik_ArchiveProcessing_Day
+ */
$archiveProcessing = $notification->getNotificationObject();
+
+ $this->archiveDayAggregateVisits($archiveProcessing);
+ $this->archiveDayAggregateGoals($archiveProcessing);
+ $this->archiveDayRecordInDatabase($archiveProcessing);
+ }
+
+ protected function archiveDayAggregateVisits($archiveProcessing)
+ {
$query = "SELECT referer_type,
referer_name,
referer_keyword,
@@ -135,7 +147,8 @@ class Piwik_Referers extends Piwik_Plugin
sum(visit_total_actions) as nb_actions,
max(visit_total_actions) as max_actions,
sum(visit_total_time) as sum_visit_length,
- sum(case visit_total_actions when 1 then 1 else 0 end) as bounce_count
+ sum(case visit_total_actions when 1 then 1 else 0 end) as bounce_count,
+ sum(case visit_goal_converted when 1 then 1 else 0 end) as nb_visits_converted
FROM ".$archiveProcessing->logTable."
WHERE visit_server_date = ?
AND idsite = ?
@@ -143,111 +156,164 @@ class Piwik_Referers extends Piwik_Plugin
ORDER BY nb_visits DESC";
$query = $archiveProcessing->db->query($query, array( $archiveProcessing->strDateStart, $archiveProcessing->idsite ));
- $interestBySearchEngine =
- $interestByKeyword =
- $keywordBySearchEngine =
- $searchEngineByKeyword =
- $interestByWebsite[Piwik_Common::REFERER_TYPE_WEBSITE] =
- $urlByWebsite[Piwik_Common::REFERER_TYPE_WEBSITE] =
- $keywordByCampaign =
- $interestByCampaign =
- $interestByType =
- $distinctUrls[Piwik_Common::REFERER_TYPE_WEBSITE] = array();
+ $this->interestBySearchEngine =
+ $this->interestByKeyword =
+ $this->interestBySearchEngineAndKeyword =
+ $this->interestByKeywordAndSearchEngine =
+ $this->interestByWebsite =
+ $this->interestByWebsiteAndUrl =
+ $this->interestByCampaignAndKeyword =
+ $this->interestByCampaign =
+ $this->interestByType =
+ $this->distinctUrls = array();
- while($rowBefore = $query->fetch() )
+ while($row = $query->fetch() )
{
- $row = array(
- Piwik_Archive::INDEX_NB_UNIQ_VISITORS => $rowBefore['nb_uniq_visitors'],
- Piwik_Archive::INDEX_NB_VISITS => $rowBefore['nb_visits'],
- Piwik_Archive::INDEX_NB_ACTIONS => $rowBefore['nb_actions'],
- Piwik_Archive::INDEX_MAX_ACTIONS => $rowBefore['max_actions'],
- Piwik_Archive::INDEX_SUM_VISIT_LENGTH => $rowBefore['sum_visit_length'],
- Piwik_Archive::INDEX_BOUNCE_COUNT => $rowBefore['bounce_count'],
- 'referer_type' => $rowBefore['referer_type'],
- 'referer_name' => $rowBefore['referer_name'],
- 'referer_keyword' => $rowBefore['referer_keyword'],
- 'referer_url' => $rowBefore['referer_url'],
- );
-
- switch($row['referer_type'])
+ if(empty($row['referer_type']))
{
- case Piwik_Common::REFERER_TYPE_SEARCH_ENGINE:
-
- if(!isset($interestBySearchEngine[$row['referer_name']])) $interestBySearchEngine[$row['referer_name']]= $archiveProcessing->getNewInterestRow();
- if(!isset($interestByKeyword[$row['referer_keyword']])) $interestByKeyword[$row['referer_keyword']]= $archiveProcessing->getNewInterestRow();
- if(!isset($keywordBySearchEngine[$row['referer_name']][$row['referer_keyword']])) $keywordBySearchEngine[$row['referer_name']][$row['referer_keyword']]= $archiveProcessing->getNewInterestRow();
- if(!isset($searchEngineByKeyword[$row['referer_keyword']][$row['referer_name']])) $searchEngineByKeyword[$row['referer_keyword']][$row['referer_name']]= $archiveProcessing->getNewInterestRow();
-
- $archiveProcessing->updateInterestStats( $row, $interestBySearchEngine[$row['referer_name']]);
- $archiveProcessing->updateInterestStats( $row, $interestByKeyword[$row['referer_keyword']]);
- $archiveProcessing->updateInterestStats( $row, $keywordBySearchEngine[$row['referer_name']][$row['referer_keyword']]);
- $archiveProcessing->updateInterestStats( $row, $searchEngineByKeyword[$row['referer_keyword']][$row['referer_name']]);
- break;
-
- case Piwik_Common::REFERER_TYPE_WEBSITE:
+ $row['referer_type'] = Piwik_Common::REFERER_TYPE_DIRECT_ENTRY;
+ }
+ else
+ {
+ switch($row['referer_type'])
+ {
+ case Piwik_Common::REFERER_TYPE_SEARCH_ENGINE:
- if(!isset($interestByWebsite[$row['referer_type']][$row['referer_name']])) $interestByWebsite[$row['referer_type']][$row['referer_name']]= $archiveProcessing->getNewInterestRow();
- $archiveProcessing->updateInterestStats( $row, $interestByWebsite[$row['referer_type']][$row['referer_name']]);
+ if(!isset($this->interestBySearchEngine[$row['referer_name']])) $this->interestBySearchEngine[$row['referer_name']]= $archiveProcessing->getNewInterestRow();
+ if(!isset($this->interestByKeyword[$row['referer_keyword']])) $this->interestByKeyword[$row['referer_keyword']]= $archiveProcessing->getNewInterestRow();
+ if(!isset($this->interestBySearchEngineAndKeyword[$row['referer_name']][$row['referer_keyword']])) $this->interestBySearchEngineAndKeyword[$row['referer_name']][$row['referer_keyword']]= $archiveProcessing->getNewInterestRow();
+ if(!isset($this->interestByKeywordAndSearchEngine[$row['referer_keyword']][$row['referer_name']])) $this->interestByKeywordAndSearchEngine[$row['referer_keyword']][$row['referer_name']]= $archiveProcessing->getNewInterestRow();
- if(!isset($urlByWebsite[$row['referer_type']][$row['referer_name']][$row['referer_url']])) $urlByWebsite[$row['referer_type']][$row['referer_name']][$row['referer_url']]= $archiveProcessing->getNewInterestRow();
- $archiveProcessing->updateInterestStats( $row, $urlByWebsite[$row['referer_type']][$row['referer_name']][$row['referer_url']]);
-
- if(!isset($distinctUrls[$row['referer_type']][$row['referer_url']]))
- {
- $distinctUrls[$row['referer_type']][$row['referer_url']] = true;
- }
+ $archiveProcessing->updateInterestStats( $row, $this->interestBySearchEngine[$row['referer_name']]);
+ $archiveProcessing->updateInterestStats( $row, $this->interestByKeyword[$row['referer_keyword']]);
+ $archiveProcessing->updateInterestStats( $row, $this->interestBySearchEngineAndKeyword[$row['referer_name']][$row['referer_keyword']]);
+ $archiveProcessing->updateInterestStats( $row, $this->interestByKeywordAndSearchEngine[$row['referer_keyword']][$row['referer_name']]);
+ break;
+
+ case Piwik_Common::REFERER_TYPE_WEBSITE:
+
+ if(!isset($this->interestByWebsite[$row['referer_name']])) $this->interestByWebsite[$row['referer_name']]= $archiveProcessing->getNewInterestRow();
+ $archiveProcessing->updateInterestStats( $row, $this->interestByWebsite[$row['referer_name']]);
+
+ if(!isset($this->interestByWebsiteAndUrl[$row['referer_name']][$row['referer_url']])) $this->interestByWebsiteAndUrl[$row['referer_name']][$row['referer_url']]= $archiveProcessing->getNewInterestRow();
+ $archiveProcessing->updateInterestStats( $row, $this->interestByWebsiteAndUrl[$row['referer_name']][$row['referer_url']]);
- break;
+ if(!isset($this->distinctUrls[$row['referer_url']]))
+ {
+ $this->distinctUrls[$row['referer_url']] = true;
+ }
+
+ break;
+
+ case Piwik_Common::REFERER_TYPE_CAMPAIGN:
+ if(!empty($row['referer_keyword']))
+ {
+ if(!isset($this->interestByCampaignAndKeyword[$row['referer_name']][$row['referer_keyword']])) $this->interestByCampaignAndKeyword[$row['referer_name']][$row['referer_keyword']]= $archiveProcessing->getNewInterestRow();
+ $archiveProcessing->updateInterestStats( $row, $this->interestByCampaignAndKeyword[$row['referer_name']][$row['referer_keyword']]);
+ }
+ if(!isset($this->interestByCampaign[$row['referer_name']])) $this->interestByCampaign[$row['referer_name']]= $archiveProcessing->getNewInterestRow();
+ $archiveProcessing->updateInterestStats( $row, $this->interestByCampaign[$row['referer_name']]);
+ break;
+
+ case Piwik_Common::REFERER_TYPE_DIRECT_ENTRY:
+ // direct entry are aggregated below in $this->interestByType array
+ break;
+
+ default:
+ throw new Exception("Non expected referer_type = " . $row['referer_type']);
+ break;
+ }
+ }
+ if(!isset($this->interestByType[$row['referer_type']] )) $this->interestByType[$row['referer_type']] = $archiveProcessing->getNewInterestRow();
+ $archiveProcessing->updateInterestStats($row, $this->interestByType[$row['referer_type']]);
+ }
+ }
+
+ protected function archiveDayAggregateGoals($archiveProcessing)
+ {
+ $query = $archiveProcessing->queryConversionsBySegment("referer_type,referer_name,referer_keyword");
+ while($row = $query->fetch() )
+ {
+ if(empty($row['referer_type']))
+ {
+ $row['referer_type'] = Piwik_Common::REFERER_TYPE_DIRECT_ENTRY;
+ }
+ else
+ {
+ switch($row['referer_type'])
+ {
+ case Piwik_Common::REFERER_TYPE_SEARCH_ENGINE:
+ if(!isset($this->interestBySearchEngine[$row['referer_name']][Piwik_Archive::INDEX_GOALS][$row['idgoal']])) $this->interestBySearchEngine[$row['referer_name']][Piwik_Archive::INDEX_GOALS][$row['idgoal']] = $archiveProcessing->getNewGoalRow();
+ if(!isset($this->interestByKeyword[$row['referer_keyword']][Piwik_Archive::INDEX_GOALS][$row['idgoal']])) $this->interestByKeyword[$row['referer_keyword']][Piwik_Archive::INDEX_GOALS][$row['idgoal']] = $archiveProcessing->getNewGoalRow();
+
+ $archiveProcessing->updateGoalStats( $row, $this->interestBySearchEngine[$row['referer_name']][Piwik_Archive::INDEX_GOALS][$row['idgoal']]);
+ $archiveProcessing->updateGoalStats( $row, $this->interestByKeyword[$row['referer_keyword']][Piwik_Archive::INDEX_GOALS][$row['idgoal']]);
+ break;
+
+ case Piwik_Common::REFERER_TYPE_WEBSITE:
+ if(!isset($this->interestByWebsite[$row['referer_name']][Piwik_Archive::INDEX_GOALS][$row['idgoal']])) $this->interestByWebsite[$row['referer_name']][Piwik_Archive::INDEX_GOALS][$row['idgoal']] = $archiveProcessing->getNewGoalRow();
+ $archiveProcessing->updateGoalStats( $row, $this->interestByWebsite[$row['referer_name']][Piwik_Archive::INDEX_GOALS][$row['idgoal']]);
+ break;
+
+ case Piwik_Common::REFERER_TYPE_CAMPAIGN:
+ if(!empty($row['referer_keyword']))
+ {
+ if(!isset($this->interestByCampaignAndKeyword[$row['referer_name']][$row['referer_keyword']][Piwik_Archive::INDEX_GOALS][$row['idgoal']])) $this->interestByCampaignAndKeyword[$row['referer_name']][$row['referer_keyword']][Piwik_Archive::INDEX_GOALS][$row['idgoal']] = $archiveProcessing->getNewGoalRow();
+ $archiveProcessing->updateGoalStats( $row, $this->interestByCampaignAndKeyword[$row['referer_name']][$row['referer_keyword']][Piwik_Archive::INDEX_GOALS][$row['idgoal']]);
+ }
+ if(!isset($this->interestByCampaign[$row['referer_name']][Piwik_Archive::INDEX_GOALS][$row['idgoal']])) $this->interestByCampaign[$row['referer_name']][Piwik_Archive::INDEX_GOALS][$row['idgoal']] = $archiveProcessing->getNewGoalRow();
+ $archiveProcessing->updateGoalStats( $row, $this->interestByCampaign[$row['referer_name']][Piwik_Archive::INDEX_GOALS][$row['idgoal']]);
+ break;
- case Piwik_Common::REFERER_TYPE_CAMPAIGN:
- if(!empty($row['referer_keyword']))
- {
- if(!isset($keywordByCampaign[$row['referer_name']][$row['referer_keyword']])) $keywordByCampaign[$row['referer_name']][$row['referer_keyword']]= $archiveProcessing->getNewInterestRow();
- $archiveProcessing->updateInterestStats( $row, $keywordByCampaign[$row['referer_name']][$row['referer_keyword']]);
- }
- if(!isset($interestByCampaign[$row['referer_name']])) $interestByCampaign[$row['referer_name']]= $archiveProcessing->getNewInterestRow();
- $archiveProcessing->updateInterestStats( $row, $interestByCampaign[$row['referer_name']]);
- break;
+ default:
+ throw new Exception("Non expected referer_type = " . $row['referer_type']);
+ break;
+ }
}
- if(!isset($interestByType[$row['referer_type']] )) $interestByType[$row['referer_type']] = $archiveProcessing->getNewInterestRow();
- $archiveProcessing->updateInterestStats($row, $interestByType[$row['referer_type']]);
+ if(!isset($this->interestByType[$row['referer_type']][Piwik_Archive::INDEX_GOALS][$row['idgoal']] )) $this->interestByType[$row['referer_type']][Piwik_Archive::INDEX_GOALS][$row['idgoal']] = $archiveProcessing->getNewGoalRow();
+ $archiveProcessing->updateGoalStats($row, $this->interestByType[$row['referer_type']][Piwik_Archive::INDEX_GOALS][$row['idgoal']]);
}
-
- $numberOfDistinctSearchEngines = count($keywordBySearchEngine);
- $numberOfDistinctKeywords = count($searchEngineByKeyword);
-
- $numberOfDistinctCampaigns = count($interestByCampaign);
- $numberOfDistinctWebsites = count($interestByWebsite[Piwik_Common::REFERER_TYPE_WEBSITE]);
- $numberOfDistinctWebsitesUrls = count($distinctUrls[Piwik_Common::REFERER_TYPE_WEBSITE]);
-
+
+ $archiveProcessing->enrichConversionsByLabelArray($this->interestByType);
+ $archiveProcessing->enrichConversionsByLabelArray($this->interestBySearchEngine);
+ $archiveProcessing->enrichConversionsByLabelArray($this->interestByKeyword);
+ $archiveProcessing->enrichConversionsByLabelArray($this->interestByWebsite);
+ $archiveProcessing->enrichConversionsByLabelArray($this->interestByCampaign);
+ $archiveProcessing->enrichConversionsByLabelArrayHasTwoLevels($this->interestByCampaignAndKeyword);
+ }
+
+ protected function archiveDayRecordInDatabase($archiveProcessing)
+ {
$numericRecords = array(
- 'Referers_distinctSearchEngines' => $numberOfDistinctSearchEngines,
- 'Referers_distinctKeywords' => $numberOfDistinctKeywords,
- 'Referers_distinctCampaigns' => $numberOfDistinctCampaigns,
- 'Referers_distinctWebsites' => $numberOfDistinctWebsites,
- 'Referers_distinctWebsitesUrls' => $numberOfDistinctWebsitesUrls,
+ 'Referers_distinctSearchEngines' => count($this->interestBySearchEngineAndKeyword),
+ 'Referers_distinctKeywords' => count($this->interestByKeywordAndSearchEngine),
+ 'Referers_distinctCampaigns' => count($this->interestByCampaign),
+ 'Referers_distinctWebsites' => count($this->interestByWebsite),
+ 'Referers_distinctWebsitesUrls' => count($this->distinctUrls),
);
+
foreach($numericRecords as $name => $value)
{
$record = new Piwik_ArchiveProcessing_Record_Numeric($name, $value);
}
- $data = $archiveProcessing->getDataTableSerialized($interestByType);
+ $data = $archiveProcessing->getDataTableSerialized($this->interestByType);
$record = new Piwik_ArchiveProcessing_Record_BlobArray('Referers_type', $data);
$maximumRowsInDataTableLevelZero = 500;
$maximumRowsInSubDataTable = 50;
- $data = $archiveProcessing->getDataTablesSerialized($keywordBySearchEngine, $interestBySearchEngine, $maximumRowsInDataTableLevelZero, $maximumRowsInSubDataTable);
- $record = new Piwik_ArchiveProcessing_Record_BlobArray('Referers_keywordBySearchEngine', $data);
-
- $data = $archiveProcessing->getDataTablesSerialized($searchEngineByKeyword, $interestByKeyword, $maximumRowsInDataTableLevelZero, $maximumRowsInSubDataTable);
- $record = new Piwik_ArchiveProcessing_Record_BlobArray('Referers_searchEngineByKeyword', $data);
-
- $data = $archiveProcessing->getDataTablesSerialized($keywordByCampaign, $interestByCampaign, $maximumRowsInDataTableLevelZero, $maximumRowsInSubDataTable);
- $record = new Piwik_ArchiveProcessing_Record_BlobArray('Referers_keywordByCampaign', $data);
+ $blobRecords = array(
+ 'Referers_keywordBySearchEngine' => $archiveProcessing->getDataTableWithSubtablesFromArraysIndexedByLabel($this->interestBySearchEngineAndKeyword, $this->interestBySearchEngine),
+ 'Referers_searchEngineByKeyword' => $archiveProcessing->getDataTableWithSubtablesFromArraysIndexedByLabel($this->interestByKeywordAndSearchEngine, $this->interestByKeyword),
+ 'Referers_keywordByCampaign' => $archiveProcessing->getDataTableWithSubtablesFromArraysIndexedByLabel($this->interestByCampaignAndKeyword, $this->interestByCampaign),
+ 'Referers_urlByWebsite' => $archiveProcessing->getDataTableWithSubtablesFromArraysIndexedByLabel($this->interestByWebsiteAndUrl, $this->interestByWebsite),
+ );
- $data = $archiveProcessing->getDataTablesSerialized($urlByWebsite[Piwik_Common::REFERER_TYPE_WEBSITE], $interestByWebsite[Piwik_Common::REFERER_TYPE_WEBSITE], $maximumRowsInDataTableLevelZero, $maximumRowsInSubDataTable);
- $record = new Piwik_ArchiveProcessing_Record_BlobArray('Referers_urlByWebsite', $data);
+ foreach($blobRecords as $recordName => $table )
+ {
+ $dataToRecord = $table->getSerialized($maximumRowsInDataTableLevelZero, $maximumRowsInSubDataTable);
+ $record = new Piwik_ArchiveProcessing_Record_BlobArray($recordName, $dataToRecord);
+ }
}
}
diff --git a/plugins/Referers/functions.php b/plugins/Referers/functions.php
index 9df808e0b1..735e7865e1 100644
--- a/plugins/Referers/functions.php
+++ b/plugins/Referers/functions.php
@@ -63,4 +63,5 @@ function Piwik_getRefererTypeLabel($label)
break;
}
return Piwik_Translate($indexTranslation);
-} \ No newline at end of file
+}
+
diff --git a/plugins/Referers/index.tpl b/plugins/Referers/templates/index.tpl
index df1995c81e..df1995c81e 100644
--- a/plugins/Referers/index.tpl
+++ b/plugins/Referers/templates/index.tpl
diff --git a/plugins/Referers/searchEngines_Keywords.tpl b/plugins/Referers/templates/searchEngines_Keywords.tpl
index a664aefb50..a664aefb50 100644
--- a/plugins/Referers/searchEngines_Keywords.tpl
+++ b/plugins/Referers/templates/searchEngines_Keywords.tpl
diff --git a/plugins/SitesManager/API.php b/plugins/SitesManager/API.php
index cfd4e8b0c7..6ff1ff9a8b 100755
--- a/plugins/SitesManager/API.php
+++ b/plugins/SitesManager/API.php
@@ -13,7 +13,7 @@
*
* @package Piwik_SitesManager
*/
-class Piwik_SitesManager_API extends Piwik_Apiable
+class Piwik_SitesManager_API
{
static private $instance = null;
static public function getInstance()
@@ -26,8 +26,6 @@ class Piwik_SitesManager_API extends Piwik_Apiable
return self::$instance;
}
- static public $methodsNotToPublish = array();
-
/**
* Returns the javascript tag for the given idSite.
* This tag must be included on every page to be tracked by Piwik
diff --git a/plugins/SitesManager/templates/SitesManager.js b/plugins/SitesManager/templates/SitesManager.js
index df6b3ed9f1..8ebfedd3b3 100644
--- a/plugins/SitesManager/templates/SitesManager.js
+++ b/plugins/SitesManager/templates/SitesManager.js
@@ -1,15 +1,3 @@
-
-function getEncoded(siteName)
-{
- // compatible with old browsers but wouldnt work for UTF8 strings
- if (encodeURIComponent) {
- siteName = encodeURIComponent(siteName);
- } else {
- siteName = escape(siteName);
- }
- return siteName;
-}
-
function getDeleteSiteAJAX( idSite )
{
var ajaxRequest = getStandardAjaxConf();
@@ -41,7 +29,7 @@ function getAddSiteAJAX( row )
request += '&module=API';
request += '&format=json';
request += '&method=SitesManager.addSite';
- siteName = getEncoded(siteName);
+ siteName = encodeURIComponent(siteName);
request += '&siteName='+siteName;
$.each(urls, function (key,value){ request+= '&urls[]='+escape(value);} );
request += '&token_auth=' + piwik.token_auth;
@@ -64,7 +52,7 @@ function getUpdateSiteAJAX( row )
request += '&module=API';
request += '&format=json';
request += '&method=SitesManager.updateSite';
- siteName = getEncoded(siteName);
+ siteName = encodeURIComponent(siteName);
request += '&siteName='+siteName;
request += '&idSite='+idSite;
$.each(urls, function (key,value){ if(value.length>1) request+= '&urls[]='+value;} );
diff --git a/plugins/UserCountry/API.php b/plugins/UserCountry/API.php
index 404dc0cbc4..6c6f00c857 100644
--- a/plugins/UserCountry/API.php
+++ b/plugins/UserCountry/API.php
@@ -15,7 +15,7 @@ require_once "UserCountry/functions.php";
*
* @package Piwik_UserCountry
*/
-class Piwik_UserCountry_API extends Piwik_Apiable
+class Piwik_UserCountry_API
{
static private $instance = null;
static public function getInstance()
diff --git a/plugins/UserCountry/Controller.php b/plugins/UserCountry/Controller.php
index 29e7f56b07..a2395620f8 100644
--- a/plugins/UserCountry/Controller.php
+++ b/plugins/UserCountry/Controller.php
@@ -19,39 +19,41 @@ class Piwik_UserCountry_Controller extends Piwik_Controller
function getCountry( $fetch = false)
{
$view = Piwik_ViewDataTable::factory();
- $view->init( 'UserCountry', __FUNCTION__, "UserCountry.getCountry" );
+ $view->init( $this->pluginName, __FUNCTION__, "UserCountry.getCountry" );
$view->disableExcludeLowPopulation();
$view->setColumnsToDisplay( array('label','nb_uniq_visitors') );
$view->setSortedColumn( 1 );
$view->disableSearchBox();
$view->setLimit( 5 );
+ $view->enableShowGoals();
return $this->renderView($view, $fetch);
}
- function getNumberOfDistinctCountries( $fetch = false)
- {
- return $this->getNumericValue('UserCountry.getNumberOfDistinctCountries');
- }
-
- function getLastDistinctCountriesGraph( $fetch = false )
- {
- $view = $this->getLastUnitGraph('UserCountry',__FUNCTION__, "UserCountry.getNumberOfDistinctCountries");
- return $this->renderView($view, $fetch);
- }
-
function getContinent( $fetch = false)
{
$view = Piwik_ViewDataTable::factory( 'graphVerticalBar' );
- $view->init( 'UserCountry', __FUNCTION__, "UserCountry.getContinent" );
+ $view->init( $this->pluginName, __FUNCTION__, "UserCountry.getContinent" );
$view->disableExcludeLowPopulation();
$view->disableSearchBox();
$view->disableOffsetInformation();
$view->disableSort();
$view->setColumnsToDisplay( array('label','nb_uniq_visitors') );
$view->setSortedColumn( 1 );
+ $view->enableShowGoals();
return $this->renderView($view, $fetch);
}
+
+ function getNumberOfDistinctCountries( $fetch = false)
+ {
+ return $this->getNumericValue('UserCountry.getNumberOfDistinctCountries');
+ }
+
+ function getLastDistinctCountriesGraph( $fetch = false )
+ {
+ $view = $this->getLastUnitGraph('UserCountry',__FUNCTION__, "UserCountry.getNumberOfDistinctCountries");
+ return $this->renderView($view, $fetch);
+ }
}
diff --git a/plugins/UserCountry/UserCountry.php b/plugins/UserCountry/UserCountry.php
index bd69f64067..93a052ca1e 100644
--- a/plugins/UserCountry/UserCountry.php
+++ b/plugins/UserCountry/UserCountry.php
@@ -68,17 +68,42 @@ class Piwik_UserCountry extends Piwik_Plugin
function archiveDay($notification)
{
$archiveProcessing = $notification->getNotificationObject();
-
- $recordName = 'UserCountry_country';
+ $this->archiveDayAggregateVisits($archiveProcessing);
+ $this->archiveDayAggregateGoals($archiveProcessing);
+ $this->archiveDayRecordInDatabase($archiveProcessing);
+ }
+
+ protected function archiveDayAggregateVisits($archiveProcessing)
+ {
$labelSQL = "location_country";
- $tableCountry = $archiveProcessing->getDataTableInterestForLabel($labelSQL);
- $record = new Piwik_ArchiveProcessing_Record_Numeric('UserCountry_distinctCountries', $tableCountry->getRowsCount());
- $record = new Piwik_ArchiveProcessing_Record_BlobArray($recordName, $tableCountry->getSerialized());
-
- $recordName = 'UserCountry_continent';
+ $this->interestByCountry = $archiveProcessing->getArrayInterestForLabel($labelSQL);
+
$labelSQL = "location_continent";
- $tableContinent = $archiveProcessing->getDataTableInterestForLabel($labelSQL);
- $record = new Piwik_ArchiveProcessing_Record_BlobArray($recordName, $tableContinent->getSerialized());
+ $this->interestByContinent = $archiveProcessing->getArrayInterestForLabel($labelSQL);
+ }
+
+ protected function archiveDayAggregateGoals($archiveProcessing)
+ {
+ $query = $archiveProcessing->queryConversionsBySegment("location_continent,location_country");
+ while($row = $query->fetch() )
+ {
+ if(!isset($this->interestByCountry[$row['location_country']][Piwik_Archive::INDEX_GOALS][$row['idgoal']])) $this->interestByCountry[$row['location_country']][Piwik_Archive::INDEX_GOALS][$row['idgoal']] = $archiveProcessing->getNewGoalRow();
+ if(!isset($this->interestByContinent[$row['location_continent']][Piwik_Archive::INDEX_GOALS][$row['idgoal']])) $this->interestByContinent[$row['location_continent']][Piwik_Archive::INDEX_GOALS][$row['idgoal']] = $archiveProcessing->getNewGoalRow();
+ $archiveProcessing->updateGoalStats($row, $this->interestByCountry[$row['location_country']][Piwik_Archive::INDEX_GOALS][$row['idgoal']]);
+ $archiveProcessing->updateGoalStats($row, $this->interestByContinent[$row['location_continent']][Piwik_Archive::INDEX_GOALS][$row['idgoal']]);
+ }
+ $archiveProcessing->enrichConversionsByLabelArray($this->interestByCountry);
+ $archiveProcessing->enrichConversionsByLabelArray($this->interestByContinent);
+ }
+
+ protected function archiveDayRecordInDatabase($archiveProcessing)
+ {
+ $tableCountry = $archiveProcessing->getDataTableFromArray($this->interestByCountry);
+ $record = new Piwik_ArchiveProcessing_Record_BlobArray('UserCountry_country', $tableCountry->getSerialized());
+ $record = new Piwik_ArchiveProcessing_Record_Numeric('UserCountry_distinctCountries', $tableCountry->getRowsCount());
+
+ $tableContinent = $archiveProcessing->getDataTableFromArray($this->interestByContinent);
+ $record = new Piwik_ArchiveProcessing_Record_BlobArray('UserCountry_continent', $tableContinent->getSerialized());
}
}
diff --git a/plugins/UserSettings/API.php b/plugins/UserSettings/API.php
index c31f941ced..d283c83870 100644
--- a/plugins/UserSettings/API.php
+++ b/plugins/UserSettings/API.php
@@ -16,7 +16,7 @@ require_once "UserSettings/functions.php";
/**
* @package Piwik_UserSettings
*/
-class Piwik_UserSettings_API extends Piwik_Apiable
+class Piwik_UserSettings_API
{
static private $instance = null;
static public function getInstance()
diff --git a/plugins/UserSettings/UserSettings.php b/plugins/UserSettings/UserSettings.php
index 6b0895145f..b56ed2d8b2 100644
--- a/plugins/UserSettings/UserSettings.php
+++ b/plugins/UserSettings/UserSettings.php
@@ -30,8 +30,8 @@ class Piwik_UserSettings extends Piwik_Plugin
// source: http://en.wikipedia.org/wiki/List_of_web_browsers
static public $browserType = array(
"ie" => array("IE"),
- "gecko" => array("NS", "PX", "FF", "FB", "CA", "CH", "GA", "KM", "MO", "SM"),
- "khtml" => array("SF", "KO", "OW"),
+ "gecko" => array("NS", "PX", "FF", "FB", "CA", "GA", "KM", "MO", "SM"),
+ "khtml" => array("SF", "KO", "OW", "CH"),
"opera" => array("OP")
);
@@ -78,17 +78,20 @@ class Piwik_UserSettings extends Piwik_Plugin
$recordName = 'UserSettings_configuration';
$labelSQL = "CONCAT(config_os, ';', config_browser_name, ';', config_resolution)";
- $tableConfiguration = $archiveProcessing->getDataTableInterestForLabel($labelSQL);
+ $interestByConfiguration = $archiveProcessing->getArrayInterestForLabel($labelSQL);
+ $tableConfiguration = $archiveProcessing->getDataTableFromArray($interestByConfiguration);
$record = new Piwik_ArchiveProcessing_Record_BlobArray($recordName, $tableConfiguration->getSerialized());
$recordName = 'UserSettings_os';
$labelSQL = "config_os";
- $tableOs = $archiveProcessing->getDataTableInterestForLabel($labelSQL);
+ $interestByOs = $archiveProcessing->getArrayInterestForLabel($labelSQL);
+ $tableOs = $archiveProcessing->getDataTableFromArray($interestByOs);
$record = new Piwik_ArchiveProcessing_Record_BlobArray($recordName, $tableOs->getSerialized());
$recordName = 'UserSettings_browser';
$labelSQL = "CONCAT(config_browser_name, ';', config_browser_version)";
- $tableBrowser = $archiveProcessing->getDataTableInterestForLabel($labelSQL);
+ $interestByBrowser = $archiveProcessing->getArrayInterestForLabel($labelSQL);
+ $tableBrowser = $archiveProcessing->getDataTableFromArray($interestByBrowser);
$record = new Piwik_ArchiveProcessing_Record_BlobArray($recordName, $tableBrowser->getSerialized());
$recordName = 'UserSettings_browserType';
@@ -97,7 +100,8 @@ class Piwik_UserSettings extends Piwik_Plugin
$recordName = 'UserSettings_resolution';
$labelSQL = "config_resolution";
- $tableResolution = $archiveProcessing->getDataTableInterestForLabel($labelSQL);
+ $interestByResolution = $archiveProcessing->getArrayInterestForLabel($labelSQL);
+ $tableResolution = $archiveProcessing->getDataTableFromArray($interestByResolution);
$filter = new Piwik_DataTable_Filter_ColumnCallbackDeleteRow($tableResolution, 'label', 'Piwik_UserSettings_keepStrlenGreater');
$record = new Piwik_ArchiveProcessing_Record_BlobArray($recordName, $tableResolution->getSerialized());
diff --git a/plugins/UsersManager/API.php b/plugins/UsersManager/API.php
index 46024d1295..235562c11c 100755
--- a/plugins/UsersManager/API.php
+++ b/plugins/UsersManager/API.php
@@ -13,7 +13,7 @@
*
* @package Piwik_UsersManager
*/
-class Piwik_UsersManager_API extends Piwik_Apiable
+class Piwik_UsersManager_API
{
static private $instance = null;
static public function getInstance()
@@ -26,8 +26,6 @@ class Piwik_UsersManager_API extends Piwik_Apiable
return self::$instance;
}
- static public $methodsNotToPublish = array();
-
/**
* Returns the list of all the users
*
diff --git a/plugins/UsersManager/templates/UsersManager.js b/plugins/UsersManager/templates/UsersManager.js
index a4e772ab97..966ea73ea5 100644
--- a/plugins/UsersManager/templates/UsersManager.js
+++ b/plugins/UsersManager/templates/UsersManager.js
@@ -185,7 +185,7 @@ $(document).ready( function() {
.toggle()
.parent()
.prepend( $('<img src="plugins/UsersManager/images/ok.png" class="updateuser">')
- .click( function(){ $.ajax( getUpdateUserAJAX( $('tr#'+idRow) ) ); } )
+ .click( function(){ $.ajax( getUpdateUserAJAX( $('tr#'+idRow) ) ); } )
);
});
diff --git a/plugins/VisitFrequency/API.php b/plugins/VisitFrequency/API.php
index c1e92bcc01..70e6010a02 100644
--- a/plugins/VisitFrequency/API.php
+++ b/plugins/VisitFrequency/API.php
@@ -13,7 +13,7 @@
*
* @package Piwik_VisitFrequency
*/
-class Piwik_VisitFrequency_API extends Piwik_Apiable
+class Piwik_VisitFrequency_API
{
static private $instance = null;
static public function getInstance()
@@ -36,6 +36,7 @@ class Piwik_VisitFrequency_API extends Piwik_Apiable
'max_actions_returning',
'sum_visit_length_returning',
'bounce_count_returning',
+ 'nb_visits_converted_returning',
);
$dataTable = $archive->getDataTableFromNumeric($toFetch);
return $dataTable;
@@ -73,4 +74,9 @@ class Piwik_VisitFrequency_API extends Piwik_Apiable
{
return $this->getNumeric( $idSite, $period, $date, 'bounce_count_returning');
}
+
+ public function getConvertedVisitsReturning( $idSite, $period, $date )
+ {
+ return $this->getNumeric( $idSite, $period, $date, 'nb_visits_converted_returning');
+ }
}
diff --git a/plugins/VisitFrequency/Controller.php b/plugins/VisitFrequency/Controller.php
index c3ce1a01bb..366ed17ab4 100644
--- a/plugins/VisitFrequency/Controller.php
+++ b/plugins/VisitFrequency/Controller.php
@@ -37,8 +37,7 @@ class Piwik_VisitFrequency_Controller extends Piwik_Controller
protected function getSummary()
{
- $requestString = "method=VisitFrequency.getSummary
- &format=original";
+ $requestString = "method=VisitFrequency.getSummary&format=original";
$request = new Piwik_API_Request($requestString);
return $request->process();
}
diff --git a/plugins/VisitFrequency/VisitFrequency.php b/plugins/VisitFrequency/VisitFrequency.php
index 94aa1329d9..68bb7fb02a 100644
--- a/plugins/VisitFrequency/VisitFrequency.php
+++ b/plugins/VisitFrequency/VisitFrequency.php
@@ -58,6 +58,7 @@ class Piwik_VisitFrequency extends Piwik_Plugin
'nb_actions_returning',
'sum_visit_length_returning',
'bounce_count_returning',
+ 'nb_visits_converted_returning',
);
$archiveProcessing->archiveNumericValuesSum($numericToSum);
$archiveProcessing->archiveNumericValuesMax('max_actions_returning');
@@ -72,7 +73,8 @@ class Piwik_VisitFrequency extends Piwik_Plugin
sum(visit_total_actions) as nb_actions_returning,
max(visit_total_actions) as max_actions_returning,
sum(visit_total_time) as sum_visit_length_returning,
- sum(case visit_total_actions when 1 then 1 else 0 end) as bounce_count_returning
+ sum(case visit_total_actions when 1 then 1 else 0 end) as bounce_count_returning,
+ sum(case visit_goal_converted when 1 then 1 else 0 end) as nb_visits_converted_returning
FROM ".$archiveProcessing->logTable."
WHERE visit_server_date = ?
AND idsite = ?
@@ -87,6 +89,7 @@ class Piwik_VisitFrequency extends Piwik_Plugin
$row['max_actions_returning'] = 0;
$row['sum_visit_length_returning'] = 0;
$row['bounce_count_returning'] = 0;
+ $row['nb_visits_converted_returning'] = 0;
}
foreach($row as $name => $value)
diff --git a/plugins/VisitTime/API.php b/plugins/VisitTime/API.php
index 86fe3d6224..47dc678216 100644
--- a/plugins/VisitTime/API.php
+++ b/plugins/VisitTime/API.php
@@ -14,7 +14,7 @@
*
* @package Piwik_VisitTime
*/
-class Piwik_VisitTime_API extends Piwik_Apiable
+class Piwik_VisitTime_API
{
static private $instance = null;
static public function getInstance()
diff --git a/plugins/VisitTime/Controller.php b/plugins/VisitTime/Controller.php
index d08458a706..923c406a1e 100644
--- a/plugins/VisitTime/Controller.php
+++ b/plugins/VisitTime/Controller.php
@@ -23,6 +23,7 @@ class Piwik_VisitTime_Controller extends Piwik_Controller
$view->disableSearchBox();
$view->disableExcludeLowPopulation();
$view->disableOffsetInformation();
+ $view->enableShowGoals();
return $this->renderView($view, $fetch);
}
diff --git a/plugins/VisitTime/VisitTime.php b/plugins/VisitTime/VisitTime.php
index 0160b838c4..9ee7f006d9 100644
--- a/plugins/VisitTime/VisitTime.php
+++ b/plugins/VisitTime/VisitTime.php
@@ -52,41 +52,58 @@ class Piwik_VisitTime extends Piwik_Plugin
function archivePeriod( $notification )
{
$archiveProcessing = $notification->getNotificationObject();
-
$dataTableToSum = array(
'VisitTime_localTime',
'VisitTime_serverTime',
);
-
$archiveProcessing->archiveDataTable($dataTableToSum);
}
public function archiveDay( $notification )
{
$archiveProcessing = $notification->getNotificationObject();
-
- $this->archiveProcessing = $archiveProcessing;
-
- $recordName = 'VisitTime_localTime';
+ $this->archiveDayAggregateVisits($archiveProcessing);
+ $this->archiveDayAggregateGoals($archiveProcessing);
+ $this->archiveDayRecordInDatabase($archiveProcessing);
+ }
+
+ protected function archiveDayAggregateVisits($archiveProcessing)
+ {
$labelSQL = "HOUR(visitor_localtime)";
- $tableLocalTime = $archiveProcessing->getDataTableInterestForLabel($labelSQL);
- $this->makeSureAllHoursAreSet($tableLocalTime);
- $record = new Piwik_ArchiveProcessing_Record_BlobArray($recordName, $tableLocalTime->getSerialized());
+ $this->interestByLocalTime = $archiveProcessing->getArrayInterestForLabel($labelSQL);
- $recordName = 'VisitTime_serverTime';
$labelSQL = "HOUR(visit_first_action_time)";
- $tableServerTime = $archiveProcessing->getDataTableInterestForLabel($labelSQL);
- $this->makeSureAllHoursAreSet($tableServerTime);
- $record = new Piwik_ArchiveProcessing_Record_BlobArray($recordName, $tableServerTime->getSerialized());
+ $this->interestByServerTime = $archiveProcessing->getArrayInterestForLabel($labelSQL);
+ }
+
+ protected function archiveDayAggregateGoals($archiveProcessing)
+ {
+ $query = $archiveProcessing->queryConversionsBySingleSegment("HOUR(server_time)");
+ while($row = $query->fetch())
+ {
+ $this->interestByServerTime[$row['label']][Piwik_Archive::INDEX_GOALS][$row['idgoal']] = $archiveProcessing->getGoalRowFromQueryRow($row);
+ }
+ $archiveProcessing->enrichConversionsByLabelArray($this->interestByServerTime);
}
- private function makeSureAllHoursAreSet($table)
+ protected function archiveDayRecordInDatabase($archiveProcessing)
+ {
+ $tableLocalTime = $archiveProcessing->getDataTableFromArray($this->interestByLocalTime);
+ $this->makeSureAllHoursAreSet($tableLocalTime, $archiveProcessing);
+ $record = new Piwik_ArchiveProcessing_Record_BlobArray('VisitTime_localTime', $tableLocalTime->getSerialized());
+
+ $tableServerTime = $archiveProcessing->getDataTableFromArray($this->interestByServerTime);
+ $this->makeSureAllHoursAreSet($tableServerTime, $archiveProcessing);
+ $record = new Piwik_ArchiveProcessing_Record_BlobArray('VisitTime_serverTime', $tableServerTime->getSerialized());
+ }
+
+ private function makeSureAllHoursAreSet($table, $archiveProcessing)
{
for($i=0;$i<=23;$i++)
{
if($table->getRowFromLabel($i) === false)
{
- $row = $this->archiveProcessing->getNewInterestRowLabeled($i);
+ $row = $archiveProcessing->getNewInterestRowLabeled($i);
$table->addRow( $row );
}
}
diff --git a/plugins/VisitorInterest/API.php b/plugins/VisitorInterest/API.php
index fc2af110ff..2903c3eabf 100644
--- a/plugins/VisitorInterest/API.php
+++ b/plugins/VisitorInterest/API.php
@@ -14,7 +14,7 @@
*
* @package Piwik_VisitorInterest
*/
-class Piwik_VisitorInterest_API extends Piwik_Apiable
+class Piwik_VisitorInterest_API
{
static private $instance = null;
static public function getInstance()
diff --git a/plugins/VisitsSummary/API.php b/plugins/VisitsSummary/API.php
index 72df24bfbf..ed9a75df7c 100644
--- a/plugins/VisitsSummary/API.php
+++ b/plugins/VisitsSummary/API.php
@@ -12,7 +12,7 @@
/**
* @package Piwik_VisitsSummary
*/
-class Piwik_VisitsSummary_API extends Piwik_Apiable
+class Piwik_VisitsSummary_API
{
static private $instance = null;
static public function getInstance()
@@ -36,6 +36,7 @@ class Piwik_VisitsSummary_API extends Piwik_Apiable
'nb_actions',
'sum_visit_length',
'bounce_count',
+ 'nb_visits_converted',
);
$dataTable = $archive->getDataTableFromNumeric($toFetch);
return $dataTable;
@@ -83,4 +84,9 @@ class Piwik_VisitsSummary_API extends Piwik_Apiable
{
return self::getNumeric( $idSite, $period, $date, 'bounce_count');
}
+
+ public function getVisitsConverted( $idSite, $period, $date )
+ {
+ return self::getNumeric( $idSite, $period, $date, 'nb_visits_converted');
+ }
}