0009772: allow or filter in sieve rules
authorAlexander Stintzing <a.stintzing@metaways.de>
Fri, 21 Mar 2014 13:44:42 +0000 (14:44 +0100)
committerPhilipp Schüle <p.schuele@metaways.de>
Wed, 26 Mar 2014 21:29:03 +0000 (22:29 +0100)
allow or filter in sieve rules
https://forge.tine20.org/mantisbt/view.php?id=9772

Change-Id: I544acfdeb65540e4ddf9d96a04554b3b8e042878
Reviewed-on: http://gerrit.tine20.com/customers/464
Tested-by: Jenkins CI (http://ci.tine20.com/)
Reviewed-by: Philipp Schüle <p.schuele@metaways.de>
Tested-by: Philipp Schüle <p.schuele@metaways.de>
14 files changed:
tests/tine20/Felamimail/JsonTest.php
tests/tine20/Felamimail/Sieve/Backend/ScriptTest.php
tine20/Felamimail/Model/Sieve/Rule.php
tine20/Felamimail/Setup/Update/Release8.php
tine20/Felamimail/Setup/setup.xml
tine20/Felamimail/Sieve/Rule.php
tine20/Felamimail/css/Felamimail.css
tine20/Felamimail/js/Model.js
tine20/Felamimail/js/sieve/RuleEditDialog.js
tine20/Felamimail/translations/de.po
tine20/Felamimail/translations/template.pot
tine20/Tinebase/js/widgets/grid/FilterToolbar.js
tine20/Tinebase/translations/de.po
tine20/Tinebase/translations/template.pot

index bea839e..bb1c947 100644 (file)
@@ -1195,6 +1195,7 @@ class Felamimail_JsonTest extends PHPUnit_Framework_TestCase
             'id'            => 1,
             'action_type'   => Felamimail_Sieve_Rule_Action::FILEINTO, 
             'action_argument' => $this->_testFolderName,
+            'conjunction'  => 'allof',
             'conditions'    => array(array(
                 'test'          => Felamimail_Sieve_Rule_Condition::TEST_ADDRESS,
                 'comperator'    => Felamimail_Sieve_Rule_Condition::COMPERATOR_CONTAINS,
@@ -1206,6 +1207,7 @@ class Felamimail_JsonTest extends PHPUnit_Framework_TestCase
             'id'            => 2,
             'action_type'   => Felamimail_Sieve_Rule_Action::FILEINTO, 
             'action_argument' => $this->_testFolderName,
+            'conjunction'  => 'allof',
             'conditions'    => array(array(
                 'test'          => Felamimail_Sieve_Rule_Condition::TEST_ADDRESS,
                 'comperator'    => Felamimail_Sieve_Rule_Condition::COMPERATOR_CONTAINS,
@@ -1217,6 +1219,7 @@ class Felamimail_JsonTest extends PHPUnit_Framework_TestCase
             'id'            => 3,
             'action_type'   => Felamimail_Sieve_Rule_Action::FILEINTO, 
             'action_argument' => $this->_testFolderName,
+            'conjunction'  => 'allof',
             'conditions'    => array(array(
                 'test'          => Felamimail_Sieve_Rule_Condition::TEST_HEADER,
                 'comperator'    => Felamimail_Sieve_Rule_Condition::COMPERATOR_REGEX,
@@ -1237,6 +1240,7 @@ class Felamimail_JsonTest extends PHPUnit_Framework_TestCase
             'id'            => 1,
             'action_type'   => Felamimail_Sieve_Rule_Action::REDIRECT, 
             'action_argument' => $this->_account->email,
+            'conjunction'     => 'allof',
             'conditions'    => array(array(
                 'test'          => Felamimail_Sieve_Rule_Condition::TEST_ADDRESS,
                 'comperator'    => Felamimail_Sieve_Rule_Condition::COMPERATOR_CONTAINS,
index cc2f166..e535c4c 100644 (file)
@@ -97,7 +97,7 @@ class Felamimail_Sieve_Backend_ScriptTest extends PHPUnit_Framework_TestCase
     }
 
     /**
-     * test enabled rule
+     * test enabled rule, also test correct parsing of anyof conjunction
      */
     public function testEnabledRule()
     {
@@ -117,13 +117,14 @@ class Felamimail_Sieve_Backend_ScriptTest extends PHPUnit_Framework_TestCase
         $rule->setEnabled(true)
             ->setId(12)
             ->setAction($action)
+            ->setSieveConjunction('anyof')
             ->addCondition($condition);
         
         $script->addRule($rule);
         
         $sieveScript = $script->getSieve();
         #echo $sieveScript;
-        $this->assertContains('if allof (address :contains "From" "info@example.com")', $sieveScript);
+        $this->assertContains('if anyof (address :contains "From" "info@example.com")', $sieveScript);
         $this->assertContains('fileinto "INBOX/UNITTEST";', $sieveScript);
         $this->assertContains('Felamimail_Sieve_Rule', $sieveScript);
     }
index 2873fe7..f2bacc3 100644 (file)
@@ -48,6 +48,7 @@ class Felamimail_Model_Sieve_Rule extends Tinebase_Record_Abstract
         'account_id'            => array(Zend_Filter_Input::ALLOW_EMPTY => true),
         'action_type'           => array(Zend_Filter_Input::ALLOW_EMPTY => true),
         'action_argument'       => array(Zend_Filter_Input::ALLOW_EMPTY => true),
+        'conjunction'           => array(Zend_Filter_Input::ALLOW_EMPTY => true, Zend_Filter_Input::DEFAULT_VALUE => 'allof'),
         'conditions'            => array(Zend_Filter_Input::ALLOW_EMPTY => true, Zend_Filter_Input::DEFAULT_VALUE => array()),
         'enabled'               => array(Zend_Filter_Input::ALLOW_EMPTY => true, Zend_Filter_Input::DEFAULT_VALUE => 0),
     );
@@ -71,7 +72,8 @@ class Felamimail_Model_Sieve_Rule extends Tinebase_Record_Abstract
     {
         $fsr = new Felamimail_Sieve_Rule();
         $fsr->setEnabled($this->enabled)
-            ->setId($this->id);
+            ->setId($this->id)
+            ->setSieveConjunction($this->conjunction);
 
         $fsra = new Felamimail_Sieve_Rule_Action();
         $fsra->setType($this->action_type)
index 9867daf..a764719 100644 (file)
@@ -39,4 +39,24 @@ class Felamimail_Setup_Update_Release8 extends Setup_Update_Abstract
         
         $this->setApplicationVersion('Felamimail', '8.1');
     }
+    
+    /**
+     * add conjunction field to sieve rule to allow "anyof"-conjunction
+     */
+    public function update_1()
+    {
+        $declaration = new Setup_Backend_Schema_Field_Xml('<field>
+            <name>conjunction</name>
+            <type>text</type>
+            <length>40</length>
+            <notnull>true</notnull>
+            <default>allof</default>
+        </field>');
+        
+        $this->_backend->addCol('felamimail_sieve_rule', $declaration);
+        
+        $this->setTableVersion('felamimail_sieve_rule', 3);
+        
+        $this->setApplicationVersion('Felamimail', '8.2');
+    }
 }
index ea80ca1..ca6c70e 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <application>
     <name>Felamimail</name>
-    <version>8.1</version>
+    <version>8.2</version>
     <order>30</order>
     <status>enabled</status>
     <tables>
         </table>
         <table>
             <name>felamimail_sieve_rule</name>
-            <version>2</version>
+            <version>3</version>
             <declaration>
                 <field>
                     <name>id</name>
                     <notnull>true</notnull>
                 </field>
                 <field>
+                    <name>conjunction</name>
+                    <type>text</type>
+                    <length>40</length>
+                    <notnull>true</notnull>
+                    <default>allof</default>
+                </field>
+                <field>
                     <name>action_type</name>
                     <type>text</type>
                     <length>256</length>
index 282ab50..68d9029 100644 (file)
@@ -40,6 +40,13 @@ class Felamimail_Sieve_Rule
     protected $_action = NULL;
     
     /**
+     * how to conjunct the filters
+     * 
+     * @var string
+     */
+    protected $_conjunction = 'allof';
+    
+    /**
      * status of rule (enabled or disabled)
      * 
      * @var boolean
@@ -160,6 +167,29 @@ class Felamimail_Sieve_Rule
     }
     
     /**
+     * returns the current conjunction
+     * 
+     * @return string
+     */
+    public function getSieveConjunction()
+    {
+        return $this->_conjunction;
+    }
+    
+    /**
+     * sets the current sieve conjunction
+     * 
+     * @param string $conjunction
+     * @return Felamimail_Sieve_Rule
+     */
+    public function setSieveConjunction($conjunction)
+    {
+        $this->_conjunction = $conjunction;
+        
+        return $this;
+    }
+    
+    /**
      * return the rule Sieve code
      * 
      * @return string
@@ -167,7 +197,7 @@ class Felamimail_Sieve_Rule
     public function __toString() 
     {
         $rule = sprintf("%s (%s) {\r\n%s\r\n}\r\n",
-            'allof',
+            $this->getSieveConjunction(),
             $this->_getSieveConditions(),
             $this->_getSieveAction()
         );
@@ -193,6 +223,7 @@ class Felamimail_Sieve_Rule
             'conditions'            => $conditions,
             'action_type'           => $action['type'],
             'action_argument'       => $action['argument'],
+            'conjunction'           => $this->_conjunction,
             'enabled'               => (integer) $this->_enabled,
             'id'                    => $this->_id,
         );
index 9ae4937..5a30c64 100644 (file)
     color: #aaaaaa;
 }
 
+.felamimail-sieverule-conjunction {
+    color: #15428b;
+    font: bold 11px tahoma,arial,verdana,sans-serif;
+}
+
index c60ebc2..61c2d50 100644 (file)
@@ -694,6 +694,7 @@ Tine.Felamimail.Model.Rule = Tine.Tinebase.data.Record.create(Tine.Tinebase.Mode
     },
     { name: 'action_type' },
     { name: 'action_argument' },
+    { name: 'conjunction' },
     { name: 'enabled', type: 'boolean'},
     { name: 'conditions' },
     { name: 'account_id' }
@@ -724,6 +725,7 @@ Tine.Felamimail.Model.Rule.getDefaultData = function() {
             comperator: 'contains',
             key: ''
         }],
+        conjunction: 'allof',
         action_type: 'fileinto',
         action_argument: ''
     };
index bbc86a6..46467d6 100644 (file)
@@ -44,6 +44,7 @@ Tine.Felamimail.sieve.RuleEditDialog = Ext.extend(Tine.widgets.dialog.EditDialog
     loadRecord: true,
     tbarItems: [],
     evalGrants: false,
+    conjunctionCombo: null,
     
     /**
      * overwrite update toolbars function (we don't have record grants yet)
@@ -98,6 +99,8 @@ Tine.Felamimail.sieve.RuleEditDialog = Ext.extend(Tine.widgets.dialog.EditDialog
         
         this.getForm().loadRecord(this.record);
         
+        this.onConjunctionChange();
+        
         this.loadMask.hide();
     },
     
@@ -211,6 +214,14 @@ Tine.Felamimail.sieve.RuleEditDialog = Ext.extend(Tine.widgets.dialog.EditDialog
     },
     
     /**
+     * sets the conjunction operator of the filtertoolbar to show the correct text for anyof or allof
+     */
+    onConjunctionChange: function() {
+        this.conditionsPanel.conjunctionOperator = this.conjunctionCombo.getValue() == 'anyof' ? 'or' : 'and';
+        this.conditionsPanel.onFilterRowsChange();
+    },
+    
+    /**
      * returns dialog
      * 
      * NOTE: when this method gets called, all initalisation is done.
@@ -243,6 +254,24 @@ Tine.Felamimail.sieve.RuleEditDialog = Ext.extend(Tine.widgets.dialog.EditDialog
             }
         });
         
+        this.conjunctionCombo = new Ext.form.ComboBox({
+            hideLabel  : false,
+            width: 250,
+            fieldLabel : '<span class="felamimail-sieverule-conjunction">' + this.app.i18n._('Apply filter if') + '</span>',
+            labelSeparator: '',
+            name       : 'conjunction',
+            store      : [
+                ['allof', this.app.i18n._('all conditions met')],
+                ['anyof', this.app.i18n._('any condition mets')]
+            ],
+            value      : 'allof',
+            listeners: {
+                scope: this,
+                change: this.onConjunctionChange,
+                select: this.onConjunctionChange
+            }
+        });
+        
         this.idPrefix = Ext.id();
         
         return [{
@@ -251,12 +280,20 @@ Tine.Felamimail.sieve.RuleEditDialog = Ext.extend(Tine.widgets.dialog.EditDialog
             autoScroll: true,
             items: [
             {
-                title: this.app.i18n._('If all of the following conditions are met:'),
                 region: 'north',
                 border: false,
                 autoScroll: true,
-                items: [
-                    this.conditionsPanel
+                items: [{
+                    layout: 'form',
+                    labelWidth: 200,
+                    frame: true,
+                    region: 'center',
+                    autoScroll: true,
+                    border: false,
+                    items: [
+                        this.conjunctionCombo
+                    ]
+                }, this.conditionsPanel
                 ],
                 xtype: 'panel',
                 listeners: {
@@ -264,7 +301,7 @@ Tine.Felamimail.sieve.RuleEditDialog = Ext.extend(Tine.widgets.dialog.EditDialog
                     afterlayout: function(ct, layout) {
                         ct.suspendEvents();
                         if (this.conditionsPanel.getHeight() < 170) {
-                            ct.setHeight(this.conditionsPanel.getHeight() + 30);
+                            ct.setHeight(this.conditionsPanel.getHeight() + 35);
                         }
                         ct.ownerCt.layout.layout();
                         ct.resumeEvents();
index 605e81d..6c7fa20 100644 (file)
@@ -1087,3 +1087,12 @@ msgstr "An (E-Mail CC)"
 
 msgid "To (Email BCC)"
 msgstr "An (E-Mail BCC)"
+
+msgid "Apply filter if"
+msgstr "Wende Filter an, wenn"
+
+msgid "any condition mets"
+msgstr "mindestens eine Bedingung erfüllt ist"
+
+msgid "all conditions met"
+msgstr "alle Bedingungen erfüllt sind"
index 3414fd7..cdf96d6 100644 (file)
@@ -1397,3 +1397,12 @@ msgstr ""
 #: Controller/Sieve.php:338
 msgid "Out of Office reply from %1$s"
 msgstr ""
+
+msgid "Apply filter if"
+msgstr ""
+
+msgid "any condition mets"
+msgstr ""
+
+msgid "all conditions met"
+msgstr ""
index aca8159..ddab613 100644 (file)
@@ -98,6 +98,13 @@ Ext.extend(Tine.widgets.grid.FilterToolbar, Ext.Panel, {
      */
     isActive: true,
     
+    /**
+     * does any of all of the filters match (or/and)
+     * 
+     * @type String
+     */
+    conjunctionOperator: 'and',
+    
     header: false,
     border: false,
     monitorResize: true,
@@ -429,7 +436,7 @@ Ext.extend(Tine.widgets.grid.FilterToolbar, Ext.Panel, {
             var tr = this.bwrap.child('tr[id='+ this.frowIdPrefix + filter.id + ']');
             
             if (tr) {
-                tr.child('td[class=tw-ftb-frow-prefix]').dom.innerHTML = _('and');
+                tr.child('td[class=tw-ftb-frow-prefix]').dom.innerHTML = '<span style="width: 25px; display: inline-block">' + _(this.conjunctionOperator) + '<span>';
             }
             
             if (filter.id == lastId) {
index 2756fbe..2c9624e 100644 (file)
@@ -2934,3 +2934,6 @@ msgid ""
 "You are not allowed to delete this Container. Please define another "
 "container as the default addressbook for internal contacts!"
 msgstr "Es ist nicht erlaubt diesen Ordner zu löschen. Bitte definieren sie zuvor einen anderen Ordner für interne Kontakte!"
+
+msgid "or"
+msgstr "oder"
\ No newline at end of file
index e030809..f727eac 100644 (file)
@@ -3205,3 +3205,6 @@ msgid ""
 "You are not allowed to delete this Container. Please define another "
 "container as the default addressbook for internal contacts!"
 msgstr ""
+
+msgid "or"
+msgstr ""