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 16:50:57 +0300
committermatt <matt@59fd770c-687e-43c8-a1e3-f5a4ff64c105>2008-12-26 16:50:57 +0300
commit446fd843abd0640403c30a763493a8fb1d821160 (patch)
tree65ebec570ef05ae3f3d84e14a3e4cd7ab6b128ea
parent35d668736cc7596e9f48ac050ce685a45296cbb6 (diff)
- cacheFile is now creating the directory if not already created
- adding log_conversion table, and goal table in 0.2.27 - adding case sensitive/case insensitive matching - when goal plugin is disabled, conversions are not being recorded - adding release notes in the Goal tab to let users know that this is alpha release
-rw-r--r--core/ArchiveProcessing/Day.php1
-rw-r--r--core/CacheFile.php8
-rw-r--r--core/Common.php34
-rw-r--r--core/DataFiles/SearchEngines.php5
-rw-r--r--core/Log.php2
-rw-r--r--core/Piwik.php81
-rw-r--r--core/PluginsManager.php4
-rw-r--r--core/Tracker/GoalManager.php35
-rw-r--r--core/Updates/0.2.27.php18
-rw-r--r--core/Updates/0.2.28.php9
-rw-r--r--core/Version.php2
-rw-r--r--core/ViewDataTable.php5
-rw-r--r--core/ViewDataTable/HtmlTable/AllColumns.php1
-rw-r--r--core/ViewDataTable/HtmlTable/Goals.php1
-rw-r--r--misc/TODO43
-rw-r--r--misc/testJavascriptTracker/index.php2
-rw-r--r--plugins/Goals/API.php54
-rw-r--r--plugins/Goals/Controller.php10
-rw-r--r--plugins/Goals/Goals.php13
-rw-r--r--plugins/Goals/templates/GoalForm.js41
-rw-r--r--plugins/Goals/templates/add_edit_goal.tpl131
-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/overview.tpl7
-rw-r--r--plugins/Goals/templates/release_notes.tpl20
-rw-r--r--plugins/Goals/templates/single_goal.tpl4
-rw-r--r--plugins/Goals/templates/title_and_evolution_graph.tpl1
-rw-r--r--plugins/VisitsSummary/Controller.php1
-rw-r--r--tests/core/ReleaseCheckList.test.php4
-rw-r--r--themes/default/common.css2
31 files changed, 392 insertions, 244 deletions
diff --git a/core/ArchiveProcessing/Day.php b/core/ArchiveProcessing/Day.php
index 300234f3ce..9d0e3fd975 100644
--- a/core/ArchiveProcessing/Day.php
+++ b/core/ArchiveProcessing/Day.php
@@ -358,7 +358,6 @@ class Piwik_ArchiveProcessing_Day extends Piwik_ArchiveProcessing
$oldRowToUpdate[Piwik_Archive::INDEX_NB_VISITS_CONVERTED] += $newRowToAdd['nb_visits_converted'];
}
- //TODO comment
public function queryConversionsBySegment($segments = '')
{
if(!empty($segments))
diff --git a/core/CacheFile.php b/core/CacheFile.php
index 156ef85703..a254788c52 100644
--- a/core/CacheFile.php
+++ b/core/CacheFile.php
@@ -58,12 +58,16 @@ class Piwik_CacheFile
* @return bool True if the entry was succesfully stored
*/
function set($id, $content)
- {
+ {
+ if( !is_dir($this->cachePath))
+ {
+ Piwik_Common::mkdir($this->cachePath);
+ }
if (!is_writable($this->cachePath)) {
return false;
}
- $id = $this->cachePath . $id;
+ $id = $this->cachePath . $id . ".php";
$cache_literal = "<"."?php\n\n";
$cache_literal .= "$"."content = ".var_export($content, true).";\n\n";
diff --git a/core/Common.php b/core/Common.php
index adfd7015b7..194e66a4c8 100644
--- a/core/Common.php
+++ b/core/Common.php
@@ -216,6 +216,40 @@ class Piwik_Common
return $nameToValue;
}
+ static public function mkdir( $path, $mode = 0755, $denyAccess = true )
+ {
+ if(!is_dir($path))
+ {
+ $directoryParent = Piwik_Common::realpath(dirname($path));
+ if( is_writable($directoryParent) )
+ {
+ mkdir($path, $mode, true);
+ }
+ }
+
+ if($denyAccess)
+ {
+ self::createHtAccess($path);
+ }
+ }
+
+ /**
+ * path without trailing slash
+ */
+ static public function createHtAccess( $path )
+ {
+ @file_put_contents($path . "/.htaccess", "Deny from all");
+ }
+
+ static public function realpath($path)
+ {
+ if (file_exists($path))
+ {
+ return realpath($path);
+ }
+ return $path;
+ }
+
/**
* Returns true if the string is a valid filename
* File names that start with a-Z or 0-9 and contain a-Z, 0-9, underscore(_), dash(-), and dot(.) will be accepted.
diff --git a/core/DataFiles/SearchEngines.php b/core/DataFiles/SearchEngines.php
index af8891dca3..1076b56ff7 100644
--- a/core/DataFiles/SearchEngines.php
+++ b/core/DataFiles/SearchEngines.php
@@ -66,8 +66,9 @@ if(!isset($GLOBALS['Piwik_SearchEngines'] ))
//Alice Adsl
"rechercher.aliceadsl.fr" => array("Alice Adsl", "qs"),
- "search.alice.it" => array("Alice (Virgilio)", "qt"),
-
+ "search.alice.it" => array("Alice (powered by Virgilio)", "qt"),
+ "ricerca.alice.it" => array("Alice (powered by Virgilio)", "qs"),
+
//Allesklar
"www.allesklar.de" => array("Allesklar", "words"),
diff --git a/core/Log.php b/core/Log.php
index 3291065e26..59f91c025b 100644
--- a/core/Log.php
+++ b/core/Log.php
@@ -52,7 +52,7 @@ abstract class Piwik_Log extends Zend_Log
function addWriteToFile()
{
$writerFile = new Zend_Log_Writer_Stream($this->logToFileFilename);
- Piwik::mkdir(Zend_Registry::get('config')->path->log);
+ Piwik_Common::mkdir(Zend_Registry::get('config')->path->log);
$writerFile->setFormatter( $this->fileFormatter );
$this->addWriter($writerFile);
}
diff --git a/core/Piwik.php b/core/Piwik.php
index 597d335257..aafe16655a 100644
--- a/core/Piwik.php
+++ b/core/Piwik.php
@@ -34,31 +34,6 @@ class Piwik
);
/**
- * path without trailing slash
- */
- static public function createHtAccess( $path )
- {
- @file_put_contents($path . "/.htaccess", "Deny from all");
- }
-
- static public function mkdir( $path, $mode = 0755, $denyAccess = true )
- {
- if(!is_dir($path))
- {
- $directoryParent = Piwik::realpath(dirname($path));
- if( is_writable($directoryParent) )
- {
- mkdir($path, $mode, true);
- }
- }
-
- if($denyAccess)
- {
- Piwik::createHtAccess($path);
- }
- }
-
- /**
* Checks that the directories Piwik needs write access are actually writable
* Displays a nice error page if permissions are missing on some directories
*
@@ -72,7 +47,7 @@ class Piwik
$directoryList = '';
foreach($resultCheck as $dir => $bool)
{
- $realpath = Piwik::realpath($dir);
+ $realpath = Piwik_Common::realpath($dir);
if(!empty($realpath) && $bool === false)
{
$directoryList .= "<code>chmod 777 $realpath</code><br>";
@@ -117,10 +92,10 @@ class Piwik
if(!file_exists($directoryToCheck))
{
- Piwik::mkdir($directoryToCheck, 0755, false);
+ Piwik_Common::mkdir($directoryToCheck, 0755, false);
}
- $directory = Piwik::realpath($directoryToCheck);
+ $directory = Piwik_Common::realpath($directoryToCheck);
$resultCheck[$directory] = false;
if($directory !== false // realpath() returns FALSE on failure
&& is_writable($directoryToCheck))
@@ -131,15 +106,6 @@ class Piwik
return $resultCheck;
}
- static public function realpath($path)
- {
- if (file_exists($path))
- {
- return realpath($path);
- }
- return $path;
- }
-
/**
* Returns the Javascript code to be inserted on every page to track
*
@@ -547,6 +513,19 @@ class Piwik
)
",
+ 'goal' => " CREATE TABLE `{$prefixTables}goal` (
+ `idsite` int(11) NOT NULL,
+ `idgoal` int(11) NOT NULL,
+ `name` varchar(50) NOT NULL,
+ `match_attribute` varchar(20) NOT NULL,
+ `pattern` varchar(255) NOT NULL,
+ `pattern_type` varchar(10) NOT NULL,
+ `case_sensitive` tinyint(4) NOT NULL,
+ `revenue` float NOT NULL,
+ `deleted` tinyint(4) NOT NULL default '0',
+ PRIMARY KEY (`idsite`,`idgoal`)
+ )
+ ",
'logger_message' => "CREATE TABLE {$prefixTables}logger_message (
idlogger_message INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
@@ -644,6 +623,30 @@ class Piwik
)
",
+ 'log_conversion' => "CREATE TABLE `{$prefixTables}log_conversion` (
+ `idvisit` int(10) unsigned NOT NULL,
+ `idsite` int(10) unsigned NOT NULL,
+ `visitor_idcookie` char(32) NOT NULL,
+ `server_time` datetime NOT NULL,
+ `visit_server_date` date NOT NULL,
+ `idaction` int(11) NOT NULL,
+ `idlink_va` int(11) NOT NULL,
+ `referer_idvisit` int(10) unsigned default NULL,
+ `referer_visit_server_date` date default NULL,
+ `referer_type` int(10) unsigned default NULL,
+ `referer_name` varchar(70) default NULL,
+ `referer_keyword` varchar(255) default NULL,
+ `visitor_returning` tinyint(1) NOT NULL,
+ `location_country` char(3) NOT NULL,
+ `location_continent` char(3) NOT NULL,
+ `url` text NOT NULL,
+ `idgoal` int(10) unsigned NOT NULL,
+ `revenue` float default NULL,
+ PRIMARY KEY (`idvisit`,`idgoal`),
+ KEY `index_idsite_date` (`idsite`,`visit_server_date`)
+ )
+ ",
+
'log_link_visit_action' => "CREATE TABLE {$prefixTables}log_link_visit_action (
idlink_va INTEGER(11) NOT NULL AUTO_INCREMENT,
idvisit INTEGER(10) UNSIGNED NOT NULL,
@@ -1151,8 +1154,8 @@ class Piwik
static public function install()
{
- Piwik::mkdir(Zend_Registry::get('config')->smarty->compile_dir);
- Piwik::mkdir(Zend_Registry::get('config')->smarty->cache_dir);
+ Piwik_Common::mkdir(Zend_Registry::get('config')->smarty->compile_dir);
+ Piwik_Common::mkdir(Zend_Registry::get('config')->smarty->cache_dir);
}
static public function uninstall()
diff --git a/core/PluginsManager.php b/core/PluginsManager.php
index 60c4f42f7a..a27bd2c937 100644
--- a/core/PluginsManager.php
+++ b/core/PluginsManager.php
@@ -401,9 +401,7 @@ class Piwik_PluginsManager
}
/**
- * TODO horrible dirty hack because the Config class is not clean enough. Needs to rewrite the Config
- * __set and __get in a cleaner way, also see the __destruct which writes the configuration file.
- *
+ * TODO horrible dirty hack. Fix config class by merging both config files before reading.
* @return array
*/
public function getInstalledPluginsName()
diff --git a/core/Tracker/GoalManager.php b/core/Tracker/GoalManager.php
index 85ef6ba808..d7f3b38726 100644
--- a/core/Tracker/GoalManager.php
+++ b/core/Tracker/GoalManager.php
@@ -25,8 +25,6 @@ class Piwik_Tracker_GoalManager
$this->cookie = $cookie;
}
- //TODO goalid should be incrementing on a website basis
- // load goal definitions from file
static public function getGoalDefinitions( $idSite )
{
$websiteAttributes = Piwik_Common::getCacheWebsiteAttributes( $idSite );
@@ -61,6 +59,10 @@ class Piwik_Tracker_GoalManager
//TODO does this code work for manually triggered goals, with custom revenue?
function detectGoals($idSite)
{
+ if(!Piwik_PluginsManager::getInstance()->isPluginActivated('Goals'))
+ {
+ return false;
+ }
$url = $this->action->getUrl();
$actionType = $this->action->getActionType();
$goals = $this->getGoalDefinitions($idSite);
@@ -76,25 +78,44 @@ class Piwik_Tracker_GoalManager
continue;
}
- //TODO: outlink trailing slash is automatically deleted, problem when trying to match?
$pattern_type = $goal['pattern_type'];
switch($pattern_type)
{
case 'regex':
- $match = (preg_match('/' . $goal['pattern'] . '/', $url) == 1);
+ $pattern = '/' . $goal['pattern'] . '/';
+ if(!$goal['case_sensitive'])
+ {
+ $pattern .= 'i';
+ }
+ $match = (preg_match($pattern, $url) == 1);
break;
case 'contains':
- $match = (strpos($url, $goal['pattern']) !== false);
+ if($goal['case_sensitive'])
+ {
+ $matched = strpos($url, $goal['pattern']);
+ }
+ else
+ {
+ $matched = stripos($url, $goal['pattern']);
+ }
+ $match = ($matched !== false);
break;
case 'exact':
- $match = ($goal['pattern'] == $url);
+ if($goal['case_sensitive'])
+ {
+ $matched = strcmp($goal['pattern'], $url);
+ }
+ else
+ {
+ $matched = strcasecmp($goal['pattern'], $url);
+ }
+ $match = ($matched == 0);
break;
default:
throw new Exception("Pattern type $pattern_type not valid.");
break;
}
-
if($match)
{
$this->matchedGoals[] = $goal;
diff --git a/core/Updates/0.2.27.php b/core/Updates/0.2.27.php
new file mode 100644
index 0000000000..4e04ee3eb0
--- /dev/null
+++ b/core/Updates/0.2.27.php
@@ -0,0 +1,18 @@
+<?php
+
+Piwik_Query( "ALTER TABLE `".Piwik::prefixTable('log_visit')."`
+ ADD `visit_goal_converted` VARCHAR( 1 ) NOT NULL AFTER `visit_total_time` ;");
+$tables = Piwik::getTablesCreateSql();
+Piwik_Query( $tables['log_conversion'] );
+Piwik_Query( $tables['goal'] );
+
+$allTablesInstalled = Piwik::getTablesInstalled();
+foreach($allTablesInstalled as $tableName)
+{
+ if(preg_match('/archive_/', $tableName) == 1)
+ {
+ Piwik_Query('CREATE INDEX index_all
+ ON '. $tableName . ' (`idsite`,`date1`,`date2`,`name`,`ts_archived`)');
+
+ }
+}
diff --git a/core/Updates/0.2.28.php b/core/Updates/0.2.28.php
deleted file mode 100644
index a64b2b2a72..0000000000
--- a/core/Updates/0.2.28.php
+++ /dev/null
@@ -1,9 +0,0 @@
-<?php
-
-Piwik_Query( "ALTER TABLE `".Piwik::prefixTable('log_visit')."`
- ADD `visit_goal_converted` VARCHAR( 1 ) NOT NULL AFTER `visit_total_time` ;");
-
-//TODO
-// alter all archive_*
-// KEY `index_all` (`idsite`,`date1`,`date2`,`name`,`ts_archived`)
-
diff --git a/core/Version.php b/core/Version.php
index 89ad548c01..ce5455afda 100644
--- a/core/Version.php
+++ b/core/Version.php
@@ -1,5 +1,5 @@
<?php
final class Piwik_Version {
- const VERSION = '0.2.26';
+ const VERSION = '0.2.27';
}
diff --git a/core/ViewDataTable.php b/core/ViewDataTable.php
index cc767a1337..e13f6b3d71 100644
--- a/core/ViewDataTable.php
+++ b/core/ViewDataTable.php
@@ -662,7 +662,10 @@ abstract class Piwik_ViewDataTable
*/
public function enableShowGoals()
{
- $this->viewProperties['show_goals'] = true;
+ if(Piwik_PluginsManager::getInstance()->isPluginActivated('Goals'))
+ {
+ $this->viewProperties['show_goals'] = true;
+ }
}
/**
diff --git a/core/ViewDataTable/HtmlTable/AllColumns.php b/core/ViewDataTable/HtmlTable/AllColumns.php
index bf84ff2ff0..2a83c9ae80 100644
--- a/core/ViewDataTable/HtmlTable/AllColumns.php
+++ b/core/ViewDataTable/HtmlTable/AllColumns.php
@@ -10,7 +10,6 @@ class Piwik_ViewDataTable_HtmlTable_AllColumns extends Piwik_ViewDataTable_HtmlT
public function main()
{
- //TODO should be cached at least statically?
$this->viewProperties['show_exclude_low_population'] = true;
parent::main();
}
diff --git a/core/ViewDataTable/HtmlTable/Goals.php b/core/ViewDataTable/HtmlTable/Goals.php
index f1233fec6a..6711f7602c 100644
--- a/core/ViewDataTable/HtmlTable/Goals.php
+++ b/core/ViewDataTable/HtmlTable/Goals.php
@@ -47,6 +47,7 @@ class Piwik_ViewDataTable_HtmlTable_Goals extends Piwik_ViewDataTable_HtmlTable
if($columnName == 'goal_%s_conversion_rate')
{
require_once "core/Tracker/GoalManager.php";
+ require_once "plugins/Goals/API.php";
$goals = Piwik_Goals_API::getGoals( $this->getIdSite() );
foreach($goals as $goal)
{
diff --git a/misc/TODO b/misc/TODO
index daf18fd044..41ed27986f 100644
--- a/misc/TODO
+++ b/misc/TODO
@@ -1,45 +1,19 @@
Before Alpha
------------
-small
-- no goals: no graph, form opened by default, easy to
-- h3 should not be bold
-- test [.*] pattern
-- clarify that pattern need to be escaped
-- display table by search engines, coutry, kwd, etc.
-- update _visit schema + prepare update files >>
-- test on piwik.org for one day, performance
-
-- test cacheFile code
-- plugify all Goal related code
-
-Goal beta release Todo list
----------------------------
-- click on (more) leads to right sub report (start implementing #state)
-- i18n
-- documentation, screenshots, blog post
-
-
-1h - new translations + updates
3h - small bugs report in robotrock, new search engines, etc.
1h - release
-friday:
-8h of work free to fix
-
-Following up show all columns new UI element
-====
+To fix
+======
+- <idsubdatatable>1</idsubdatatable> shouldnt be in api response
- when used with visitsGenerator, in dowloads export XML, full_url and url is 0
-- add new column "overall visits with conversion"
- post 29 There seems not to be a way to export the pages information widget.
I wanted to download the entry pages to see where my visitors entered my site from,
but there is no option to do so.
- ADD forward of non true show_values to forward when specified from URL to ajax
- disable show icon in some iframes and/or dashboard
-- do proper CSS factoring
- clarify 'false' '0' values etc. //convert all JS datatable footer parameter values to '1' or '0'
-- documentation + Blog post
-- exclude all population doesn't work for actions
- cron should return errors when token doesn't have any website
Bugs
@@ -51,9 +25,12 @@ Bugs
- In Referers-&gt;Evolution page, in addition, I think its melting titles because I read
in spanish &quot;Entrada directa nb_uniq_visitors&quot; for the first graph,
&quot;Paginas web nb_uniq_visitors&quot; for the second and so on.
-
+- exclude all population doesn't work for actions
+
Reports improvements
====================
+- add new column "overall visits with conversion"
+- add visits with conversion sparkline in VisitsSummary overview
- add link under widgets to report (optional display)
- link under goal conversion to full goal reports (optional display)
- think of ways to show entry / exit pages and bounce rate.
@@ -87,10 +64,6 @@ high priority features
- Loyalty (Most people visited: 1 times) and Recency (Most people last visited: X days ago)
http://en.wikipedia.org/wiki/RFM
-Small features
-==============
-- can we find a "binary operator string -> regex" conversion function?
-
User Interface improvements
===========================
- add icon calendar http://developer.yahoo.com/ypatterns/pattern.php?pattern=calendar#Solution
@@ -106,7 +79,7 @@ Code improvements
=================
- plugins should listen to user delete/ site delete and delete their own user/site related data
- why widgetize inherits Piwik_Widgetize_Controller
-- PLUGINS HAVE THEIR OWN TESTS
+- plugins could have their own tests, read automatically from the test suite
Documentation
=============
diff --git a/misc/testJavascriptTracker/index.php b/misc/testJavascriptTracker/index.php
index 8361e50375..1de9ff8de3 100644
--- a/misc/testJavascriptTracker/index.php
+++ b/misc/testJavascriptTracker/index.php
@@ -52,4 +52,4 @@ piwik_log(piwik_action_name, piwik_idsite,piwik_url);
</script><object>
<noscript><p>Web analytics <img src="<?php echo $urlPiwik; ?>/piwik.php" style="border:0" alt="piwik"/></p>
</noscript></object></a>
-<!-- /Piwik --> \ No newline at end of file
+<!-- /Piwik -->
diff --git a/plugins/Goals/API.php b/plugins/Goals/API.php
index 7417bd1988..5b1b849f01 100644
--- a/plugins/Goals/API.php
+++ b/plugins/Goals/API.php
@@ -40,7 +40,7 @@ class Piwik_Goals_API
return $cleanedGoals;
}
- public function addGoal( $idSite, $name, $matchAttribute, $pattern, $patternType, $revenue )
+ public function addGoal( $idSite, $name, $matchAttribute, $pattern, $patternType, $caseSensitive, $revenue )
{
Piwik::checkUserHasAdminAccess($idSite);
// save in db
@@ -52,8 +52,9 @@ class Piwik_Goals_API
{
$idGoal = 1;
}
- $name = urldecode($name);
- $pattern = urldecode($pattern);
+ self::checkPatternIsValid($patternType, $pattern);
+ $name = self::checkName($name);
+ $pattern = self::checkPattern($pattern);
$db->insert(Piwik::prefixTable('goal'),
array(
'idsite' => $idSite,
@@ -62,6 +63,7 @@ class Piwik_Goals_API
'match_attribute' => $matchAttribute,
'pattern' => $pattern,
'pattern_type' => $patternType,
+ 'case_sensitive' => $caseSensitive,
'revenue' => $revenue,
'deleted' => 0,
));
@@ -69,23 +71,45 @@ class Piwik_Goals_API
return $idGoal;
}
- public function updateGoal( $idSite, $idGoal, $name, $matchAttribute, $pattern, $patternType, $revenue )
+ public function updateGoal( $idSite, $idGoal, $name, $matchAttribute, $pattern, $patternType, $caseSensitive, $revenue )
{
Piwik::checkUserHasAdminAccess($idSite);
- $name = urldecode($name);
- $pattern = urldecode($pattern);
+ $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 )
{
@@ -99,15 +123,15 @@ class Piwik_Goals_API
Piwik_Common::regenerateCacheWebsiteAttributes($idSite);
}
- public function getConversionsReturningVisitors( $idSite, $period, $date, $idGoal = false )
- {
-
- }
-
- public function getConversionsNewVisitors( $idSite, $period, $date, $idGoal = false )
- {
-
- }
+// 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 )
diff --git a/plugins/Goals/Controller.php b/plugins/Goals/Controller.php
index 42fa706150..935d616258 100644
--- a/plugins/Goals/Controller.php
+++ b/plugins/Goals/Controller.php
@@ -121,6 +121,16 @@ class Piwik_Goals_Controller extends Piwik_Controller
$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 )
{
diff --git a/plugins/Goals/Goals.php b/plugins/Goals/Goals.php
index ae13724c44..550f0e7288 100644
--- a/plugins/Goals/Goals.php
+++ b/plugins/Goals/Goals.php
@@ -62,11 +62,18 @@ class Piwik_Goals extends Piwik_Plugin
function addMenus()
{
- Piwik_AddMenu('Goals', 'Overview', array('module' => 'Goals'));
$goals = Piwik_Tracker_GoalManager::getGoalDefinitions(Piwik_Common::getRequestVar('idSite'));
- foreach($goals as $goal)
+ if(count($goals)==0)
{
- Piwik_AddMenu('Goals', str_replace('%', '%%', $goal['name']), array('module' => 'Goals', 'action' => 'goalReport', 'idGoal' => $goal['idgoal']));
+ 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']));
+ }
}
}
diff --git a/plugins/Goals/templates/GoalForm.js b/plugins/Goals/templates/GoalForm.js
index 27e250c5ca..4345bc8958 100644
--- a/plugins/Goals/templates/GoalForm.js
+++ b/plugins/Goals/templates/GoalForm.js
@@ -3,7 +3,7 @@ function showAddNewGoal()
{
$("#GoalForm").show();
$("#EditGoals").hide();
- lazyScrollTo("#bottom", 100);
+ $.scrollTo("#AddEditGoals", 400);
return false;
}
@@ -11,12 +11,12 @@ function showEditGoals()
{
$("#EditGoals").show();
$("#GoalForm").hide();
- lazyScrollTo("#bottom", 100);
+ $.scrollTo("#AddEditGoals", 400);
return false;
}
// init the goal form with existing goal value, if any
-function initGoalForm(goalMethodAPI, submitText, goalName, matchAttribute, pattern, patternType, revenue, goalId)
+function initGoalForm(goalMethodAPI, submitText, goalName, matchAttribute, pattern, patternType, caseSensitive, revenue, goalId)
{
$('#goal_name').val(goalName);
$('input[@name=match_attribute][value='+matchAttribute+']').attr('checked', true);
@@ -24,6 +24,7 @@ function initGoalForm(goalMethodAPI, submitText, goalName, matchAttribute, patte
$('#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);
@@ -32,6 +33,11 @@ function initGoalForm(goalMethodAPI, submitText, goalName, matchAttribute, patte
}
}
+function initAndShowAddGoalForm()
+{
+ initGoalForm('Goals.addGoal', 'Add Goal', '', 'url', '', 'contains', false, '0');
+ return showAddNewGoal();
+}
function bindGoalForm()
{
$('input[@name=match_attribute]').click( function() {
@@ -46,8 +52,36 @@ function bindGoalForm()
$.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();
@@ -76,6 +110,7 @@ function getAjaxAddGoal()
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();
diff --git a/plugins/Goals/templates/add_edit_goal.tpl b/plugins/Goals/templates/add_edit_goal.tpl
index 1f0220bcf6..2ca55ca102 100644
--- a/plugins/Goals/templates/add_edit_goal.tpl
+++ b/plugins/Goals/templates/add_edit_goal.tpl
@@ -1,103 +1,29 @@
<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}
- <h2><a href='#' name="linkAddNewGoal">+ Add a new Goal</a>
- or <a href='#' name="linkEditGoals">Edit</a> existing Goals</h2>
-
- <script>
- piwik.goals = {$goalsJSON};
- </script>
-
<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>
- <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>
-
- <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" onclick="" checked="true" 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" onclick="" id="match_attribute_file" value="file" name="match_attribute"/>
- <label for="match_attribute_file">Download a file</label>
- <br>
- <input type="radio" onclick="" 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"></div>
- </td>
- </tr>
- <tr>
- <td>(optional) Goal default value is </td>
- <td>{$currency} <input type="text" name="revenue" size="1" value="0"/></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>
+{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}
-<style>
-#examples_pattern {
- color:#9B9B9B;
-}
-</style>
<script type="text/javascript" src="plugins/Goals/templates/GoalForm.js"></script>
<script language="javascript">
+
var mappingMatchTypeName = {
"url": "URL",
"file": "filename",
@@ -109,34 +35,15 @@ var mappingMatchTypeExamples = {
"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'"
};
-$('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.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;
- }
-});
-
bindGoalForm();
-$('a[name=linkAddNewGoal]').click( function(){
- initGoalForm('Goals.addGoal', 'Add Goal', '', 'url', '', 'contains', '0');
- return showAddNewGoal();
-} );
-$('a[name=linkEditGoals]').click( function(){
- return showEditGoals();
-} );
+{/literal}
-</script>
+{if !isset($onlyShowAddNewGoal)}
+piwik.goals = {$goalsJSON};
+bindListGoalEdit();
+{else}
+initAndShowAddGoalForm();
+{/if}
-{/literal}
+</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/overview.tpl b/plugins/Goals/templates/overview.tpl
index a17611066d..04bf1af90d 100644
--- a/plugins/Goals/templates/overview.tpl
+++ b/plugins/Goals/templates/overview.tpl
@@ -1,12 +1,10 @@
{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}
-<h3 style="text-decoration:underline;padding-top:20px">{$goal.name} (goal)</h3>
+<h2 style="padding-top: 30px;">{$goal.name} (goal)</h3>
<table width=700px>
<tr><td>
<p>{sparkline src=$goal.urlSparklineConversions}<span>
@@ -22,5 +20,8 @@
{/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
index bb04e6f01b..b605c17490 100644
--- a/plugins/Goals/templates/single_goal.tpl
+++ b/plugins/Goals/templates/single_goal.tpl
@@ -4,8 +4,8 @@
<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>
- <li>Your top converting keywords are: {include file='Goals/templates/list_top_segment.tpl' topSegment=$topSegments.keyword}</li>
- <li>Your best converting websites referers are: {include file='Goals/templates/list_top_segment.tpl' topSegment=$topSegments.website}</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}
diff --git a/plugins/Goals/templates/title_and_evolution_graph.tpl b/plugins/Goals/templates/title_and_evolution_graph.tpl
index f5359132d9..0b1b8d2c7b 100644
--- a/plugins/Goals/templates/title_and_evolution_graph.tpl
+++ b/plugins/Goals/templates/title_and_evolution_graph.tpl
@@ -18,4 +18,3 @@
</td></tr>
</table>
-<div style="clear:both"> \ No newline at end of file
diff --git a/plugins/VisitsSummary/Controller.php b/plugins/VisitsSummary/Controller.php
index 953c90a7d9..4b2cc72e56 100644
--- a/plugins/VisitsSummary/Controller.php
+++ b/plugins/VisitsSummary/Controller.php
@@ -29,7 +29,6 @@ class Piwik_VisitsSummary_Controller extends Piwik_Controller
$view->sumVisitLength = $dataTableVisit->getColumn('sum_visit_length');
$view->bounceCount = $dataTableVisit->getColumn('bounce_count');
$view->maxActions = $dataTableVisit->getColumn('max_actions');
- //TODO visits with conversion
}
function getSparklines()
diff --git a/tests/core/ReleaseCheckList.test.php b/tests/core/ReleaseCheckList.test.php
index c308da3975..329a329376 100644
--- a/tests/core/ReleaseCheckList.test.php
+++ b/tests/core/ReleaseCheckList.test.php
@@ -47,7 +47,9 @@ class Test_Piwik_ReleaseCheckList extends UnitTestCase
public function test_checkThatGivenPluginsAreDisabledByDefault()
{
$pluginsShouldBeDisabled = array(
- 'DBStats'
+ 'DBStats',
+ 'Goals',
+ 'Live',
);
foreach($pluginsShouldBeDisabled as $pluginName)
{
diff --git a/themes/default/common.css b/themes/default/common.css
index bbc6505903..d2123e4753 100644
--- a/themes/default/common.css
+++ b/themes/default/common.css
@@ -45,6 +45,8 @@ body {
}
a {
color: #0F1B2E;
+ text-decoration:underline;
+ cursor:pointer;
}
#loadingPiwik {