Daimona Eaytoy has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/391065 )

Change subject: Add contains_all function
......................................................................

Add contains_all function

Added the contains_all function, with basically the same role as
contains_any but using logic AND instead of OR. Co-authored with Valerio
Bozzolan.

Bug: T21176
Change-Id: Ib0a8b783db6ce0d5db64771c8e0c70f0f8d13d36
---
M i18n/en.json
M i18n/qqq.json
M includes/AbuseFilter.class.php
M includes/parser/AbuseFilterParser.php
4 files changed, 47 insertions(+), 16 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/AbuseFilter 
refs/changes/65/391065/1

diff --git a/i18n/en.json b/i18n/en.json
index 1a6ccf5..98c1773 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -235,7 +235,8 @@
        "abusefilter-edit-builder-funcs-rmwhitespace": "Remove whitespace 
(rmwhitespace)",
        "abusefilter-edit-builder-funcs-rmspecials": "Remove special characters 
(rmspecials)",
        "abusefilter-edit-builder-funcs-ip_in_range": "Is IP in range? 
(ip_in_range)",
-       "abusefilter-edit-builder-funcs-contains-any": "Search string for 
multiple substrings (contains_any)",
+       "abusefilter-edit-builder-funcs-contains-any": "Search string for 
multiple substrings in OR mode. (contains_any)",
+       "abusefilter-edit-builder-funcs-contains-all": "Search string for 
multiple substrings in AND mode. (contains_all)",
        "abusefilter-edit-builder-funcs-substr": "Substring (substr)",
        "abusefilter-edit-builder-funcs-strpos": "Position of substring in 
string (strpos)",
        "abusefilter-edit-builder-funcs-str_replace": "Replace substring with 
string (str_replace)",
diff --git a/i18n/qqq.json b/i18n/qqq.json
index 522cc1b..9302446 100644
--- a/i18n/qqq.json
+++ b/i18n/qqq.json
@@ -267,6 +267,7 @@
        "abusefilter-edit-builder-funcs-rmspecials": "{{doc-important|Do not 
translate \"'''rmspecials'''\".}} Abuse filter syntax option in a dropdown from 
the group {{msg-mw|abusefilter-edit-builder-group-funcs}}.",
        "abusefilter-edit-builder-funcs-ip_in_range": "{{doc-important|Do not 
translate \"'''ip_in_range'''\".}} Abuse filter syntax option in a dropdown 
from the group {{msg-mw|abusefilter-edit-builder-group-funcs}}.",
        "abusefilter-edit-builder-funcs-contains-any": "{{doc-important|Do not 
translate \"'''contains_any'''\".}} Abuse filter syntax option in a dropdown 
from the group {{msg-mw|abusefilter-edit-builder-group-funcs}}.",
+       "abusefilter-edit-builder-funcs-contains-all": "{{doc-important|Do not 
translate \"'''contains_all'''\".}} Abuse filter syntax option in a dropdown 
from the group {{msg-mw|abusefilter-edit-builder-group-funcs}}.",
        "abusefilter-edit-builder-funcs-substr": "{{doc-important|Do not 
translate \"'''substr'''\".}} Abuse filter syntax option in a dropdown from the 
group {{msg-mw|abusefilter-edit-builder-group-funcs}}.",
        "abusefilter-edit-builder-funcs-strpos": "{{doc-important|Do not 
translate \"'''strpos'''\".}} Abuse filter syntax option in a dropdown from the 
group {{msg-mw|abusefilter-edit-builder-group-funcs}}.",
        "abusefilter-edit-builder-funcs-str_replace": "{{doc-important|Do not 
translate \"'''str_replace'''\".}} Abuse filter syntax option in a dropdown 
from the group {{msg-mw|abusefilter-edit-builder-group-funcs}}.",
diff --git a/includes/AbuseFilter.class.php b/includes/AbuseFilter.class.php
index f58a46a..270666a 100644
--- a/includes/AbuseFilter.class.php
+++ b/includes/AbuseFilter.class.php
@@ -81,6 +81,7 @@
                        'rmspecials(text)' => 'rmspecials',
                        'ip_in_range(ip, range)' => 'ip_in_range',
                        'contains_any(haystack,needle1,needle2,...)' => 
'contains-any',
+                       'contains_all(haystack,needle1,needle2,...)' => 
'contains-all',
                        'substr(subject, offset, length)' => 'substr',
                        'strpos(haystack, needle)' => 'strpos',
                        'str_replace(subject, search, replace)' => 
'str_replace',
diff --git a/includes/parser/AbuseFilterParser.php 
b/includes/parser/AbuseFilterParser.php
index 89f5a62..fbbf424 100644
--- a/includes/parser/AbuseFilterParser.php
+++ b/includes/parser/AbuseFilterParser.php
@@ -31,6 +31,7 @@
                'get_matches' => 'funcGetMatches',
                'ip_in_range' => 'funcIPInRange',
                'contains_any' => 'funcContainsAny',
+               'contains_all' => 'funcContainsAll',
                'substr' => 'funcSubstr',
                'strlen' => 'funcLen',
                'strpos' => 'funcStrPos',
@@ -1137,9 +1138,28 @@
 
                $s = array_shift( $args );
 
-               return new AFPData( AFPData::DBOOL, self::containsAny( $s, 
$args ) );
+               return new AFPData( AFPData::DBOOL, self::contains( 'ANY', $s, 
$args ) );
        }
 
+       /**
+        * @param array $args
+        * @return AFPData
+        * @throws AFPUserVisibleException
+        */
+       protected function funcContainsAll( $args ) {
+               if ( count( $args ) < 2 ) {
+                       throw new AFPUserVisibleException(
+                               'notenoughargs',
+                               $this->mCur->pos,
+                               [ 'contains_all', 2, count( $args ) ]
+                       );
+               }
+
+               $s = array_shift( $args );
+
+               return new AFPData( AFPData::DBOOL, self::contains( 'ALL', $s, 
$args, false ) );
+       }
+       
        /**
         * Normalize and search a string for multiple substrings
         *
@@ -1158,24 +1178,28 @@
 
                $s = array_shift( $args );
 
-               return new AFPData( AFPData::DBOOL, self::containsAny( $s, 
$args, true ) );
+               return new AFPData( AFPData::DBOOL, self::contains( 'ANY', $s, 
$args, true ) );
        }
 
        /**
         * Search for substrings in a string
         *
+        * Use logic to determine wether to use logic AND (ALL) or OR (ANY).
+        *
         * Use normalize = true to make use of ccnorm and
         * normalize both sides of the search.
         *
+        * @param string $logic Must be 'ANY' or 'ALL'
         * @param AFData $string
         * @param AFData[] $values
         * @param bool $normalize
         *
         * @return bool
         */
-       protected static function containsAny( $string, $values, $normalize = 
false ) {
-               $string = $string->toString();
+       protected static function contains( $logic = 'ANY', $string, $values, 
$normalize = false ) {
+               $is_any = 'ANY' === $logic;
 
+               $string = $string->toString();
                if ( $string == '' ) {
                        return false;
                }
@@ -1184,23 +1208,27 @@
                        $string = self::ccnorm( $string );
                }
 
-               $values = array_map( function ( $val ) use ( $normalize ) {
-                       $str = $val->toString();
+               foreach ( $values as $needle ) {
+                       $needle = $needle->toString();
                        if ( $normalize ) {
-                               $str = AbuseFilterParser::ccnorm( $str );
+                               $needle = AbuseFilterParser::ccnorm( $needle );
+                       }
+                       if( $needle === '' ) {
+                               // Bug #62203: Keep empty parameters from 
causing PHP warnings
+                               continue;
                        }
 
-                       return $str;
-               }, $values );
-
-               foreach ( $values as $needle ) {
-                       // Bug #60203: Keep empty parameters from causing PHP 
warnings
-                       if ( $needle !== '' && strpos( $string, $needle ) !== 
false ) {
-                               return true;
+                       $is_found = strpos( $string, $needle ) !== false;
+                       if( $is_found === $is_any ) {
+                               // If I'm here and it's ANY it means that 
something is    found. Just enough!     Found!
+                               // If I'm here and it's ALL it means that 
something isn't found. Just enough! Not found!
+                               return $is_found;
                        }
                }
 
-               return false;
+               // If I'm here and it's ANY it means that nothing    was  
found: return false (because $is_any is true)
+               // If I'm here and it's ALL it means that everything were 
found: return true  (because $is_any is false)
+               return ! $is_any;
        }
 
        /**

-- 
To view, visit https://gerrit.wikimedia.org/r/391065
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ib0a8b783db6ce0d5db64771c8e0c70f0f8d13d36
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/AbuseFilter
Gerrit-Branch: master
Gerrit-Owner: Daimona Eaytoy <daimona.w...@gmail.com>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to