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:
authormattab <matthieu.aubry@gmail.com>2013-05-12 10:09:22 +0400
committermattab <matthieu.aubry@gmail.com>2013-05-12 10:09:22 +0400
commitd89a08b8b27ef9a7293e9f8cf351bedbd838e2cb (patch)
tree0aa6a2e2233d8a3b77deefe97fb3e142592003a4
parent263892f231da5f6e998342aef02f33aa7edf8622 (diff)
Fixes #3932
* you can now write browserCode==ff;referrerKeyword!= to select all visitors using firefox and that have a keyword set * or you can write referrerKeyword==;browserCode==ff to select all visitors using firefox and that did not have any keyword set Also fixes #3933 Refs #2135 * fixing last bugs with segment selector encoding (working on chrome + FF + opera) - I 'hope' it will work on iE...
-rw-r--r--core/API/Proxy.php2
-rw-r--r--core/API/Request.php12
-rw-r--r--core/Segment.php8
-rw-r--r--core/SegmentExpression.php44
-rw-r--r--core/ViewDataTable.php24
-rw-r--r--core/ViewDataTable/GenerateGraphData/ChartEvolution.php2
-rw-r--r--plugins/API/API.php2
-rw-r--r--plugins/CoreHome/DataTableRowAction/RowEvolution.php2
-rw-r--r--plugins/CoreHome/templates/broadcast.js5
-rw-r--r--plugins/CoreHome/templates/datatable.js2
-rw-r--r--plugins/CoreHome/templates/datatable_rowactions.js1
-rw-r--r--plugins/CoreHome/templates/menu.js4
-rw-r--r--plugins/CoreHome/templates/menu.tpl2
-rw-r--r--plugins/Live/Controller.php2
-rw-r--r--plugins/SegmentEditor/templates/Segmentation.js7
-rw-r--r--plugins/UserCountryMap/Controller.php6
-rw-r--r--plugins/VisitsSummary/Controller.php2
-rw-r--r--tests/PHPUnit/Core/SegmentExpressionTest.php13
-rw-r--r--tests/PHPUnit/Core/SegmentTest.php25
-rw-r--r--themes/default/ajaxHelper.js13
20 files changed, 132 insertions, 46 deletions
diff --git a/core/API/Proxy.php b/core/API/Proxy.php
index 2a024afbf5..e7ed698f6e 100644
--- a/core/API/Proxy.php
+++ b/core/API/Proxy.php
@@ -161,6 +161,7 @@ class Piwik_API_Proxy
// Temporarily sets the Request array to this API call context
$saveGET = $_GET;
+ $saveQUERY_STRING = @$_SERVER['QUERY_STRING'];
foreach ($parametersRequest as $param => $value) {
$_GET[$param] = $value;
}
@@ -199,6 +200,7 @@ class Piwik_API_Proxy
// Restore the request
$_GET = $saveGET;
+ $_SERVER['QUERY_STRING'] = $saveQUERY_STRING;
// log the API Call
try {
diff --git a/core/API/Request.php b/core/API/Request.php
index 22d0436b3c..d9ec3f7cff 100644
--- a/core/API/Request.php
+++ b/core/API/Request.php
@@ -48,6 +48,12 @@ class Piwik_API_Request
static public function getRequestArrayFromString($request)
{
$defaultRequest = $_GET + $_POST;
+
+ $requestRaw = self::getRequestParametersGET();
+ if(!empty($requestRaw['segment'])) {
+ $defaultRequest['segment'] = $requestRaw['segment'];
+ }
+
$requestArray = $defaultRequest;
if (!is_null($request)) {
@@ -63,9 +69,8 @@ class Piwik_API_Request
$request = str_replace(array("\n", "\t"), '', $request);
$requestParsed = Piwik_Common::getArrayFromQueryString($request);
-
-// parse_str($request, $requestArray);
$requestArray = $requestParsed + $defaultRequest;
+
}
foreach ($requestArray as &$element) {
@@ -209,6 +214,9 @@ class Piwik_API_Request
*/
public static function getRequestParametersGET()
{
+ if(empty($_SERVER['QUERY_STRING'])) {
+ return array();
+ }
$GET = Piwik_Common::getArrayFromQueryString($_SERVER['QUERY_STRING']);
return $GET;
}
diff --git a/core/Segment.php b/core/Segment.php
index a02581e829..af57fe59a9 100644
--- a/core/Segment.php
+++ b/core/Segment.php
@@ -37,9 +37,9 @@ class Piwik_Segment
// First try with url decoded value. If that fails, try with raw value.
// If that also fails, it will throw the exception
try {
- $this->initializeSegment($string, $idSites);
- } catch(Exception $e) {
$this->initializeSegment( urldecode($string), $idSites);
+ } catch(Exception $e) {
+ $this->initializeSegment($string, $idSites);
}
}
@@ -50,7 +50,6 @@ class Piwik_Segment
*/
protected function initializeSegment($string, $idSites)
{
- $string = Piwik_Common::unsanitizeInputValue($string);
// As a preventive measure, we restrict the filter size to a safe limit
$string = substr($string, 0, self::SEGMENT_TRUNCATE_LIMIT);
@@ -111,7 +110,8 @@ class Piwik_Segment
// apply presentation filter
if (isset($segment['sqlFilter'])
&& !empty($segment['sqlFilter'])
- && $matchType != Piwik_SegmentExpression::MATCH_IS_NOT_NULL
+ && $matchType != Piwik_SegmentExpression::MATCH_IS_NOT_NULL_NOR_EMPTY
+ && $matchType != Piwik_SegmentExpression::MATCH_IS_NULL_OR_EMPTY
) {
$value = call_user_func($segment['sqlFilter'], $value, $segment['sqlSegment'], $matchType, $name);
diff --git a/core/SegmentExpression.php b/core/SegmentExpression.php
index fe178abccf..43aa1294a1 100644
--- a/core/SegmentExpression.php
+++ b/core/SegmentExpression.php
@@ -27,8 +27,11 @@ class Piwik_SegmentExpression
const MATCH_CONTAINS = '=@';
const MATCH_DOES_NOT_CONTAIN = '!@';
- // Note: undocumented for now, only used in API.getSuggestedValuesForSegment
- const MATCH_IS_NOT_NULL = '::';
+ // Note: you can't write this in the API, but access this feature
+ // via field!= <- IS NOT NULL
+ // or via field== <- IS NULL / empty
+ const MATCH_IS_NOT_NULL_NOR_EMPTY = '::NOT_NULL';
+ const MATCH_IS_NULL_OR_EMPTY = '::NULL';
// Special case, since we look up Page URLs/Page titles in a sub SQL query
const MATCH_ACTIONS_CONTAINS = 'IN';
@@ -72,9 +75,8 @@ class Piwik_SegmentExpression
. self::MATCH_LESS_OR_EQUAL . '|'
. self::MATCH_LESS . '|'
. self::MATCH_CONTAINS . '|'
- . self::MATCH_IS_NOT_NULL . '|'
. self::MATCH_DOES_NOT_CONTAIN
- . '){1}(.+)/';
+ . '){1}(.*)/';
$match = preg_match($pattern, $operand, $matches);
if ($match == 0) {
throw new Exception('The segment \'' . $operand . '\' is not valid.');
@@ -83,6 +85,19 @@ class Piwik_SegmentExpression
$leftMember = $matches[1];
$operation = $matches[2];
$valueRightMember = urldecode($matches[3]);
+
+ // is null / is not null
+ if ($valueRightMember === '') {
+ if($operation == self::MATCH_NOT_EQUAL) {
+ $operation = self::MATCH_IS_NOT_NULL_NOR_EMPTY;
+ } elseif($operation == self::MATCH_EQUAL) {
+ $operation = self::MATCH_IS_NULL_OR_EMPTY;
+ } else {
+ throw new Exception('The segment \'' . $operand . '\' has no value specified. You can leave this value empty ' .
+ 'only when you use the operators: ' . self::MATCH_NOT_EQUAL . ' (is not) or ' . self::MATCH_EQUAL . ' (is)');
+ }
+ }
+
$parsedSubExpressions[] = array(
self::INDEX_BOOL_OPERATOR => $operator,
self::INDEX_OPERAND => array(
@@ -158,12 +173,14 @@ class Piwik_SegmentExpression
$matchType = $def[1];
$value = $def[2];
+ $alsoMatchNULLValues = false;
switch ($matchType) {
case self::MATCH_EQUAL:
$sqlMatch = '=';
break;
case self::MATCH_NOT_EQUAL:
$sqlMatch = '<>';
+ $alsoMatchNULLValues = true;
break;
case self::MATCH_GREATER:
$sqlMatch = '>';
@@ -184,13 +201,19 @@ class Piwik_SegmentExpression
case self::MATCH_DOES_NOT_CONTAIN:
$sqlMatch = 'NOT LIKE';
$value = '%' . $this->escapeLikeString($value) . '%';
+ $alsoMatchNULLValues = true;
break;
- case self::MATCH_IS_NOT_NULL:
+ case self::MATCH_IS_NOT_NULL_NOR_EMPTY:
$sqlMatch = 'IS NOT NULL AND ('.$field.' <> \'\' OR '.$field.' = 0)';
$value = null;
break;
+ case self::MATCH_IS_NULL_OR_EMPTY:
+ $sqlMatch = 'IS NULL OR '.$field.' = \'\' ';
+ $value = null;
+ break;
+
case self::MATCH_ACTIONS_CONTAINS:
// this match type is not accessible from the outside
// (it won't be matched in self::parseSubExpressions())
@@ -204,11 +227,18 @@ class Piwik_SegmentExpression
break;
}
+ // We match NULL values when rows are excluded only when we are not doing a
+ $alsoMatchNULLValues = $alsoMatchNULLValues && !empty($value);
+
if ($matchType === self::MATCH_ACTIONS_CONTAINS
|| is_null($value)) {
- $sqlExpression = "$field $sqlMatch";
+ $sqlExpression = "( $field $sqlMatch )";
} else {
- $sqlExpression = "$field $sqlMatch ?";
+ if($alsoMatchNULLValues) {
+ $sqlExpression = "( $field IS NULL OR $field $sqlMatch ? )";
+ } else {
+ $sqlExpression = "$field $sqlMatch ?";
+ }
}
$this->checkFieldIsAvailable($field, $availableTables);
diff --git a/core/ViewDataTable.php b/core/ViewDataTable.php
index 28dc4b23bf..89cc36ff3d 100644
--- a/core/ViewDataTable.php
+++ b/core/ViewDataTable.php
@@ -583,13 +583,26 @@ abstract class Piwik_ViewDataTable
}
}
+ $segment = $this->getRawSegmentFromRequest();
+ if(!empty($segment)) {
+ $requestString .= '&segment=' . $segment;
+ }
+ return $requestString;
+ }
+
+ /**
+ * @return array|bool
+ */
+ static public function getRawSegmentFromRequest()
+ {
// we need the URL encoded segment parameter, we fetch it from _SERVER['QUERY_STRING'] instead of default URL decoded _GET
+ $segmentRaw = false;
$segment = Piwik_Common::getRequestVar('segment', '', 'string');
if (!empty($segment)) {
- $requestRaw = Piwik_API_Request::getRequestParametersGET();
- $requestString .= '&segment=' . $requestRaw['segment'];
+ $request = Piwik_API_Request::getRequestParametersGET();
+ $segmentRaw = $request['segment'];
}
- return $requestString;
+ return $segmentRaw;
}
/**
@@ -768,6 +781,11 @@ abstract class Piwik_ViewDataTable
unset($javascriptVariablesToSet[$name]);
}
}
+
+ $rawSegment = $this->getRawSegmentFromRequest();
+ $javascriptVariablesToSet['segment'] = $rawSegment;
+
+
return $javascriptVariablesToSet;
}
diff --git a/core/ViewDataTable/GenerateGraphData/ChartEvolution.php b/core/ViewDataTable/GenerateGraphData/ChartEvolution.php
index 65d7988216..cbcf93d7be 100644
--- a/core/ViewDataTable/GenerateGraphData/ChartEvolution.php
+++ b/core/ViewDataTable/GenerateGraphData/ChartEvolution.php
@@ -191,7 +191,7 @@ class Piwik_ViewDataTable_GenerateGraphData_ChartEvolution extends Piwik_ViewDat
'idSite' => $idSite,
'period' => $period->getLabel(),
'date' => $dateInUrl->toString(),
- 'segment' => Piwik_Common::unsanitizeInputValue(Piwik_Common::getRequestVar('segment', false))
+ 'segment' => Piwik_ViewDataTable::getRawSegmentFromRequest()
);
$hash = '';
if (!empty($queryStringAsHash)) {
diff --git a/plugins/API/API.php b/plugins/API/API.php
index e9d3511f19..2402b515fd 100644
--- a/plugins/API/API.php
+++ b/plugins/API/API.php
@@ -1659,7 +1659,7 @@ class Piwik_API_API
// Select non empty fields only
// Note: this optimization has only a very minor impact
- $requestLastVisits.= "&segment=$segmentName" . Piwik_SegmentExpression::MATCH_IS_NOT_NULL . "null";
+ $requestLastVisits.= "&segment=$segmentName".urlencode('!=');
// By default Live fetches all actions for all visitors, but we'd rather do this only when required
if($this->doesSegmentNeedActionsData($segmentName)) {
diff --git a/plugins/CoreHome/DataTableRowAction/RowEvolution.php b/plugins/CoreHome/DataTableRowAction/RowEvolution.php
index 5df1ce3e16..ab42ea3452 100644
--- a/plugins/CoreHome/DataTableRowAction/RowEvolution.php
+++ b/plugins/CoreHome/DataTableRowAction/RowEvolution.php
@@ -91,7 +91,7 @@ class Piwik_CoreHome_DataTableRowAction_RowEvolution
list($this->date, $lastN) =
Piwik_ViewDataTable_GenerateGraphHTML_ChartEvolution::getDateRangeAndLastN($this->period, $end);
}
- $this->segment = Piwik_Common::getRequestVar('segment', '', 'string');
+ $this->segment = Piwik_ViewDataTable::getRawSegmentFromRequest();
$this->loadEvolutionReport();
}
diff --git a/plugins/CoreHome/templates/broadcast.js b/plugins/CoreHome/templates/broadcast.js
index 31c3fb6c29..508777c174 100644
--- a/plugins/CoreHome/templates/broadcast.js
+++ b/plugins/CoreHome/templates/broadcast.js
@@ -462,7 +462,10 @@ var broadcast = {
hashStr = url.substring(url.indexOf("#"), url.length);
}
else {
- hashStr = (location.hash);
+ locationSplit = location.href.split('#');
+ if(typeof locationSplit[1] != 'undefined') {
+ hashStr = '#' + locationSplit[1];
+ }
}
return hashStr;
diff --git a/plugins/CoreHome/templates/datatable.js b/plugins/CoreHome/templates/datatable.js
index 1369b11786..a0a9b4afd4 100644
--- a/plugins/CoreHome/templates/datatable.js
+++ b/plugins/CoreHome/templates/datatable.js
@@ -1367,7 +1367,7 @@ dataTable.prototype =
// doing AJAX request
var menuItem = null;
$("#root").find(">ul.nav a").each(function () {
- if ($(this).attr('name') == url) {
+ if ($(this).attr('href') == url) {
menuItem = this;
return false
}
diff --git a/plugins/CoreHome/templates/datatable_rowactions.js b/plugins/CoreHome/templates/datatable_rowactions.js
index afe31cc61b..238c4e7309 100644
--- a/plugins/CoreHome/templates/datatable_rowactions.js
+++ b/plugins/CoreHome/templates/datatable_rowactions.js
@@ -213,6 +213,7 @@ DataTable_RowAction.prototype.getLabelFromTr = function (tr) {
if (!value) {
value = label.text();
}
+ value = value.trim();
return encodeURIComponent(value);
};
diff --git a/plugins/CoreHome/templates/menu.js b/plugins/CoreHome/templates/menu.js
index 3be160b1ca..b2010152be 100644
--- a/plugins/CoreHome/templates/menu.js
+++ b/plugins/CoreHome/templates/menu.js
@@ -29,7 +29,7 @@ menu.prototype =
onItemClick: function (item) {
$('ul.nav').trigger('piwikSwitchPage', item);
- broadcast.propagateAjax($(item).attr('name'));
+ broadcast.propagateAjax( $(item).attr('href').substr(1) );
return false;
},
@@ -45,7 +45,7 @@ menu.prototype =
// for all sub menu we want to have a unique id based on their module and action
// for main menu we want to add just the module as its id.
this.menuNode.find('li').each(function () {
- var url = $(this).find('a').attr('name');
+ var url = $(this).find('a').attr('href').substr(1);
var module = broadcast.getValueFromUrl("module", url);
var action = broadcast.getValueFromUrl("action", url);
var moduleId = broadcast.getValueFromUrl("idGoal", url) || broadcast.getValueFromUrl("idDashboard", url);
diff --git a/plugins/CoreHome/templates/menu.tpl b/plugins/CoreHome/templates/menu.tpl
index e9e2fcd853..476483f745 100644
--- a/plugins/CoreHome/templates/menu.tpl
+++ b/plugins/CoreHome/templates/menu.tpl
@@ -6,7 +6,7 @@
<ul>
{foreach from=$level2 key=name item=urlParameters name=level2}
{if strpos($name, '_') !== 0}
- <li><a name='{$urlParameters._url|@urlRewriteWithParameters}' href='#{$urlParameters._url|@urlRewriteWithParameters|substr:1}'
+ <li><a href='#{$urlParameters._url|@urlRewriteWithParameters|substr:1}'
onclick='return piwikMenu.onItemClick(this);'>{$name|translate|escape:'html'}</a></li>
{/if}
{/foreach}
diff --git a/plugins/Live/Controller.php b/plugins/Live/Controller.php
index 40f2300678..ef703aa743 100644
--- a/plugins/Live/Controller.php
+++ b/plugins/Live/Controller.php
@@ -130,7 +130,7 @@ class Piwik_Live_Controller extends Piwik_Controller
private function setCounters($view)
{
- $segment = Piwik_Common::getRequestVar('segment', false, 'string');
+ $segment = Piwik_ViewDataTable::getRawSegmentFromRequest();
$last30min = Piwik_Live_API::getInstance()->getCounters($this->idSite, $lastMinutes = 30, $segment);
$last30min = $last30min[0];
$today = Piwik_Live_API::getInstance()->getCounters($this->idSite, $lastMinutes = 24 * 60, $segment);
diff --git a/plugins/SegmentEditor/templates/Segmentation.js b/plugins/SegmentEditor/templates/Segmentation.js
index eb8379efe9..0b5ab93147 100644
--- a/plugins/SegmentEditor/templates/Segmentation.js
+++ b/plugins/SegmentEditor/templates/Segmentation.js
@@ -948,12 +948,7 @@ $(document).ready( function(){
var changeSegment = function(segmentDefinition){
$('#segmentEditorPanel a.close').click();
segmentDefinition = cleanupSegmentDefinition(segmentDefinition);
-
-// if($.browser.mozilla ) {
- segmentDefinition = encodeURIComponent(segmentDefinition);
-// }
-// alert('new segment to reload='+segmentDefinition);
-
+ segmentDefinition = encodeURIComponent(segmentDefinition);
return broadcast.propagateNewPage('segment=' + segmentDefinition, true);
};
diff --git a/plugins/UserCountryMap/Controller.php b/plugins/UserCountryMap/Controller.php
index b0ca11de21..5195ec7421 100644
--- a/plugins/UserCountryMap/Controller.php
+++ b/plugins/UserCountryMap/Controller.php
@@ -73,7 +73,7 @@ class Piwik_UserCountryMap_Controller extends Piwik_Controller
'date' => $date,
'token_auth' => $token_auth,
'format' => 'json',
- 'segment' => Piwik_Common::unsanitizeInputValue(Piwik_Common::getRequestVar('segment', '')),
+ 'segment' => Piwik_ViewDataTable::getRawSegmentFromRequest(),
'showRawMetrics' => 1,
'enable_filter_excludelowpop' => 1,
'filter_excludelowpop_value' => -1
@@ -144,7 +144,7 @@ class Piwik_UserCountryMap_Controller extends Piwik_Controller
'date' => self::REAL_TIME_WINDOW,
'token_auth' => $token_auth,
'format' => 'json',
- 'segment' => Piwik_Common::unsanitizeInputValue(Piwik_Common::getRequestVar('segment', '')),
+ 'segment' => Piwik_ViewDataTable::getRawSegmentFromRequest(),
'showRawMetrics' => 1
));
@@ -192,7 +192,7 @@ class Piwik_UserCountryMap_Controller extends Piwik_Controller
. "&period=" . $period
. "&date=" . $date
. "&token_auth=" . $token_auth
- . "&segment=" . Piwik_Common::unsanitizeInputValue(Piwik_Common::getRequestVar('segment', ''))
+ . "&segment=" . Piwik_ViewDataTable::getRawSegmentFromRequest()
. "&enable_filter_excludelowpop=1"
. "&showRawMetrics=1";
diff --git a/plugins/VisitsSummary/Controller.php b/plugins/VisitsSummary/Controller.php
index c93cf11679..fd62d14e38 100644
--- a/plugins/VisitsSummary/Controller.php
+++ b/plugins/VisitsSummary/Controller.php
@@ -129,7 +129,7 @@ class Piwik_VisitsSummary_Controller extends Piwik_Controller
$dataTableVisit = self::getVisitsSummary();
$dataRow = $dataTableVisit->getRowsCount() == 0 ? new Piwik_DataTable_Row() : $dataTableVisit->getFirstRow();
- $dataTableActions = Piwik_Actions_API::getInstance()->get($idSite, Piwik_Common::getRequestVar('period'), Piwik_Common::getRequestVar('date'), Piwik_Common::getRequestVar('segment', false));
+ $dataTableActions = Piwik_Actions_API::getInstance()->get($idSite, Piwik_Common::getRequestVar('period'), Piwik_Common::getRequestVar('date'), Piwik_ViewDataTable::getRawSegmentFromRequest());
$dataActionsRow =
$dataTableActions->getRowsCount() == 0 ? new Piwik_DataTable_Row() : $dataTableActions->getFirstRow();
diff --git a/tests/PHPUnit/Core/SegmentExpressionTest.php b/tests/PHPUnit/Core/SegmentExpressionTest.php
index ea53e5d049..afbfa23854 100644
--- a/tests/PHPUnit/Core/SegmentExpressionTest.php
+++ b/tests/PHPUnit/Core/SegmentExpressionTest.php
@@ -60,10 +60,10 @@ class SegmentExpressionTest extends PHPUnit_Framework_TestCase
return array(
array('A==B%', array('where' => " A = ? ", 'bind' => array('B%'))),
array('ABCDEF====B===', array('where' => " ABCDEF = ? ", 'bind' => array('==B==='))),
- array('A===B;CDEF!=C!=', array('where' => " A = ? AND CDEF <> ? ", 'bind' => array('=B', 'C!='))),
+ array('A===B;CDEF!=C!=', array('where' => " A = ? AND ( CDEF IS NULL OR CDEF <> ? ) ", 'bind' => array('=B', 'C!='))),
array('A==B,C==D', array('where' => " (A = ? OR C = ? )", 'bind' => array('B', 'D'))),
- array('A!=B;C==D', array('where' => " A <> ? AND C = ? ", 'bind' => array('B', 'D'))),
- array('A!=B;C==D,E!=Hello World!=', array('where' => " A <> ? AND (C = ? OR E <> ? )", 'bind' => array('B', 'D', 'Hello World!='))),
+ array('A!=B;C==D', array('where' => " ( A IS NULL OR A <> ? ) AND C = ? ", 'bind' => array('B', 'D'))),
+ array('A!=B;C==D,E!=Hello World!=', array('where' => " ( A IS NULL OR A <> ? ) AND (C = ? OR ( E IS NULL OR E <> ? ) )", 'bind' => array('B', 'D', 'Hello World!='))),
array('A>B', array('where' => " A > ? ", 'bind' => array('B'))),
array('A<B', array('where' => " A < ? ", 'bind' => array('B'))),
@@ -74,7 +74,7 @@ class SegmentExpressionTest extends PHPUnit_Framework_TestCase
array('A>=B;C>=D,E<w_ow great!', array('where' => " A >= ? AND (C >= ? OR E < ? )", 'bind' => array('B', 'D', 'w_ow great!'))),
array('A=@B_', array('where' => " A LIKE ? ", 'bind' => array('%B\_%'))),
- array('A!@B%', array('where' => " A NOT LIKE ? ", 'bind' => array('%B\%%'))),
+ array('A!@B%', array('where' => " ( A IS NULL OR A NOT LIKE ? ) ", 'bind' => array('%B\%%'))),
);
}
@@ -107,8 +107,7 @@ class SegmentExpressionTest extends PHPUnit_Framework_TestCase
array(',;,'),
array(','),
array(',,'),
- array('==='),
- array('!=')
+ array('!='),
);
}
@@ -126,6 +125,6 @@ class SegmentExpressionTest extends PHPUnit_Framework_TestCase
} catch (Exception $e) {
return;
}
- $this->fail('Expected exception not raised');
+ $this->fail('Expected exception not raised for:' . var_export($segment->getSql(), true));
}
}
diff --git a/tests/PHPUnit/Core/SegmentTest.php b/tests/PHPUnit/Core/SegmentTest.php
index 35da2a58a3..c007cc9d20 100644
--- a/tests/PHPUnit/Core/SegmentTest.php
+++ b/tests/PHPUnit/Core/SegmentTest.php
@@ -55,7 +55,7 @@ class SegmentTest extends PHPUnit_Framework_TestCase
// AND, with 2 values rewrites
array('countryCode==a;visitorType!=returning;visitorType==new', array(
- 'where' => ' log_visit.location_country = ? AND log_visit.visitor_returning <> ? AND log_visit.visitor_returning = ? ',
+ 'where' => ' log_visit.location_country = ? AND ( log_visit.visitor_returning IS NULL OR log_visit.visitor_returning <> ? ) AND log_visit.visitor_returning = ? ',
'bind' => array('a', '1', '0'))),
// OR, with 2 value rewrites
@@ -63,6 +63,27 @@ class SegmentTest extends PHPUnit_Framework_TestCase
'where' => ' (log_visit.referer_type = ? OR log_visit.referer_type = ? )',
'bind' => array(Piwik_Common::REFERER_TYPE_SEARCH_ENGINE,
Piwik_Common::REFERER_TYPE_DIRECT_ENTRY))),
+
+ // IS NOT NULL
+ array('browserCode==ff;referrerKeyword!=', array(
+ 'where' => ' log_visit.config_browser_name = ? AND ( log_visit.referer_keyword IS NOT NULL AND (log_visit.referer_keyword <> \'\' OR log_visit.referer_keyword = 0) ) ',
+ 'bind' => array('ff')
+ )),
+ array('referrerKeyword!=,browserCode==ff', array(
+ 'where' => ' (( log_visit.referer_keyword IS NOT NULL AND (log_visit.referer_keyword <> \'\' OR log_visit.referer_keyword = 0) ) OR log_visit.config_browser_name = ? )',
+ 'bind' => array('ff')
+ )),
+
+ // IS NULL
+ array('browserCode==ff;referrerKeyword==', array(
+ 'where' => ' log_visit.config_browser_name = ? AND ( log_visit.referer_keyword IS NULL OR log_visit.referer_keyword = \'\' ) ',
+ 'bind' => array('ff')
+ )),
+ array('referrerKeyword==,browserCode==ff', array(
+ 'where' => ' (( log_visit.referer_keyword IS NULL OR log_visit.referer_keyword = \'\' ) OR log_visit.config_browser_name = ? )',
+ 'bind' => array('ff')
+ )),
+
);
}
@@ -259,7 +280,7 @@ class SegmentTest extends PHPUnit_Framework_TestCase
WHERE
( log_conversion.idvisit = ? )
AND
- ( log_conversion.idgoal <> ? AND log_link_visit_action.custom_var_k1 = ? AND log_conversion.idgoal = ? )",
+ ( ( log_conversion.idgoal IS NULL OR log_conversion.idgoal <> ? ) AND log_link_visit_action.custom_var_k1 = ? AND log_conversion.idgoal = ? )",
"bind" => array(1, 2, 'Test', 1));
$this->assertEquals($this->_filterWhitsSpaces($expected), $this->_filterWhitsSpaces($query));
diff --git a/themes/default/ajaxHelper.js b/themes/default/ajaxHelper.js
index f2e7e12a71..10b9459216 100644
--- a/themes/default/ajaxHelper.js
+++ b/themes/default/ajaxHelper.js
@@ -300,10 +300,19 @@ function ajaxHelper() {
this._buildAjaxCall = function () {
var that = this;
+ var parameters = this._mixinDefaultGetParams(this.getParams);
+
+ var url = 'index.php?';
+ // we took care of encoding &segment properly already, so we don't use $.param for it ($.param URL encodes the values)
+ if(parameters['segment']) {
+ url += 'segment=' + parameters['segment'] + '&';
+ delete parameters['segment'];
+ }
+ url += $.param(parameters);
var ajaxCall = {
type: 'POST',
async: this.async !== false,
- url: 'index.php?' + $.param(this._mixinDefaultGetParams(this.getParams)),
+ url: url,
dataType: this.format || 'json',
error: this.errorCallback,
success: function (response) {
@@ -363,7 +372,7 @@ function ajaxHelper() {
var defaultParams = {
idSite: piwik.idSite || broadcast.getValueFromUrl('idSite'),
period: piwik.period || broadcast.getValueFromUrl('period'),
- segment: broadcast.getValueFromHash('segment', window.location.href)
+ segment: broadcast.getValueFromHash('segment', window.location.href.split('#')[1])
};
// never append token_auth to url