From ada836d750a74ddfda03b48baf2fa1c1173e39ff Mon Sep 17 00:00:00 2001
From: Thomas Steur <thomas.steur@gmail.com>
Date: Thu, 19 Nov 2015 04:12:24 +0000
Subject: [PATCH] make new operators available in the UI, moved check to
 segment data class

---
 core/Plugin/Segment.php                           | 15 +++++++++++++++
 lang/en.json                                      |  2 ++
 plugins/API/API.php                               |  8 --------
 plugins/SegmentEditor/SegmentSelectorControl.php  |  2 ++
 plugins/SegmentEditor/javascripts/Segmentation.js |  4 +++-
 .../SegmentEditor/templates/_segmentSelector.twig |  2 ++
 6 files changed, 24 insertions(+), 9 deletions(-)

diff --git a/core/Plugin/Segment.php b/core/Plugin/Segment.php
index 3d6914fe5c..2a20208ea2 100644
--- a/core/Plugin/Segment.php
+++ b/core/Plugin/Segment.php
@@ -7,6 +7,7 @@
  *
  */
 namespace Piwik\Plugin;
+use Exception;
 
 /**
  * Creates a new segment that can be used for instance within the {@link \Piwik\Columns\Dimension::configureSegment()}
@@ -123,6 +124,7 @@ class Segment
     public function setSegment($segment)
     {
         $this->segment = $segment;
+        $this->check();
     }
 
     /**
@@ -166,6 +168,7 @@ class Segment
     public function setSqlSegment($sqlSegment)
     {
         $this->sqlSegment = $sqlSegment;
+        $this->check();
     }
 
     /**
@@ -178,6 +181,7 @@ class Segment
     public function setUnionOfSegments($segments)
     {
         $this->unionOfSegments = $segments;
+        $this->check();
     }
 
     /**
@@ -323,4 +327,15 @@ class Segment
     {
         $this->requiresAtLeastViewAccess = $requiresAtLeastViewAccess;
     }
+
+    private function check()
+    {
+        if ($this->sqlSegment && $this->unionOfSegments) {
+            throw new Exception(sprintf('Union of segments and SQL segment is set for segment "%s", use only one of them', $this->name));
+        }
+
+        if ($this->segment && $this->unionOfSegments && in_array($this->segment, $this->unionOfSegments, true)) {
+            throw new Exception(sprintf('The segment %s contains a union segment to itself', $this->name));
+        }
+    }
 }
diff --git a/lang/en.json b/lang/en.json
index 615ad706c0..c5a32ed0d8 100644
--- a/lang/en.json
+++ b/lang/en.json
@@ -264,6 +264,8 @@
         "OperationIsNot": "Is not",
         "OperationLessThan": "Less than",
         "OperationNotEquals": "Not Equals",
+        "OperationStartsWith": "Starts with",
+        "OperationEndsWith": "Ends with",
         "OptionalSmtpPort": "Optional. Defaults to 25 for unencrypted and TLS SMTP, and 465 for SSL SMTP.",
         "Options": "Options",
         "OrCancel": "or %s Cancel %s",
diff --git a/plugins/API/API.php b/plugins/API/API.php
index 09e4719824..e5d9fbcd2a 100644
--- a/plugins/API/API.php
+++ b/plugins/API/API.php
@@ -129,14 +129,6 @@ class API extends \Piwik\Plugin\API
                     $segment->setPermission($isAuthenticatedWithViewAccess);
                 }
 
-                if ($segment->getSqlSegment() && $segment->getUnionOfSegments()) {
-                    throw new \Exception(sprintf('Union of segments and SQL segment is set for segment "%s", use only one of them', $segment->getName()));
-                }
-
-                if ($segment->getUnionOfSegments() && in_array($segment->getSegment(), $segment->getUnionOfSegments(), true)) {
-                    throw new \Exception(sprintf('The segment %s contains a union segment to itself', $segment->getName()));
-                }
-
                 $segments[] = $segment->toArray();
             }
         }
diff --git a/plugins/SegmentEditor/SegmentSelectorControl.php b/plugins/SegmentEditor/SegmentSelectorControl.php
index e37354e1cd..9dc2659660 100644
--- a/plugins/SegmentEditor/SegmentSelectorControl.php
+++ b/plugins/SegmentEditor/SegmentSelectorControl.php
@@ -115,6 +115,8 @@ class SegmentSelectorControl extends UIControl
             'General_OperationGreaterThan',
             'General_OperationContains',
             'General_OperationDoesNotContain',
+            'General_OperationStartsWith',
+            'General_OperationEndsWith',
             'General_OperationIs',
             'General_OperationIsNot',
             'General_OperationContains',
diff --git a/plugins/SegmentEditor/javascripts/Segmentation.js b/plugins/SegmentEditor/javascripts/Segmentation.js
index 0e47bd7d19..ec1e8f23b8 100644
--- a/plugins/SegmentEditor/javascripts/Segmentation.js
+++ b/plugins/SegmentEditor/javascripts/Segmentation.js
@@ -49,6 +49,8 @@ Segmentation = (function($) {
         self.availableMatches["dimension"]["!="] = self.translations['General_OperationIsNot'];
         self.availableMatches["dimension"]["=@"] = self.translations['General_OperationContains'];
         self.availableMatches["dimension"]["!@"] = self.translations['General_OperationDoesNotContain'];
+        self.availableMatches["dimension"]["=^"] = self.translations['General_OperationStartsWith'];
+        self.availableMatches["dimension"]["=$"] = self.translations['General_OperationEndsWith'];
 
         segmentation.prototype.setAvailableSegments = function (segments) {
             this.availableSegments = segments;
@@ -264,7 +266,7 @@ Segmentation = (function($) {
         };
 
         var findAndExplodeByMatch = function(metric){
-            var matches = ["==" , "!=" , "<=", ">=", "=@" , "!@","<",">"];
+            var matches = ["==" , "!=" , "<=", ">=", "=@" , "!@","<",">", "=^", "=$"];
             var newMetric = {};
             var minPos = metric.length;
             var match, index;
diff --git a/plugins/SegmentEditor/templates/_segmentSelector.twig b/plugins/SegmentEditor/templates/_segmentSelector.twig
index 1ffb4b3d47..f2d53b60c7 100644
--- a/plugins/SegmentEditor/templates/_segmentSelector.twig
+++ b/plugins/SegmentEditor/templates/_segmentSelector.twig
@@ -61,6 +61,8 @@
                 <option value=">">{{ 'General_OperationGreaterThan'|translate }}</option>
                 <option value="=@">{{ 'General_OperationContains'|translate }}</option>
                 <option value="!@">{{ 'General_OperationDoesNotContain'|translate }}</option>
+                <option value="=^">{{ 'General_OperationStartsWith'|translate }}</option>
+                <option value="=$">{{ 'General_OperationEndsWith'|translate }}</option>
             </select>
         </div>
         <div class="segment-input metricValueBlock">
-- 
GitLab