Ed Hoo has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/260951

Change subject: Fix HOLDS operator parsing and adds corresponding NOT 
functionality
......................................................................

Fix HOLDS operator parsing and adds corresponding NOT functionality

The expanded functionality enables HOLDS to be used as follows:
    Author HOLDS "John Smith"
    Author HOLDS NOT "Jane Smith"
    Author HOLDS LIKE "% Smith"
    Author HOLDS NOT LIKE "% Johnson"
    Book.Author HOLDS "John Smith"
    Book.Author HOLDS NOT "Jane Smith"
    Book.Author HOLDS LIKE "% Smith"
    Book.Author HOLDS NOT LIKE "% Johnson"

Change-Id: I46f3e052901420f0c6d68c6291b16b52299d43f5
---
M CargoSQLQuery.php
1 file changed, 62 insertions(+), 41 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Cargo 
refs/changes/51/260951/1

diff --git a/CargoSQLQuery.php b/CargoSQLQuery.php
index 23722ee..c892f2e 100644
--- a/CargoSQLQuery.php
+++ b/CargoSQLQuery.php
@@ -558,6 +558,22 @@
                return false;
        }
 
+       /*
+        * Provides HOLDS functionality to WHERE clause by replacing $pattern
+        * in $subject with $replacement and setting $found to true if
+        * successful (leaves it untouched otehrwise). Includes modifying
+        * the regex beginning from a non-valid identifier character to word
+        * boundary.
+        */
+       function substVirtualFieldName( &$subject, $pattern, $replacement, 
&$found ) {
+               if ( preg_match( $pattern, $subject ) ) {
+                       $pattern = str_replace( '([^\w$]|^)', '\b', $pattern);
+                       $pattern = str_replace( '([^\w$.]|^)', '\b', $pattern);
+                       $subject = preg_replace( $pattern, $replacement, 
$subject );
+                       $found = true;
+               }
+       }
+
        function handleVirtualFields() {
                // The array-field alias can be found in a number of different
                // clauses. Handling depends on which clause it is:
@@ -592,38 +608,57 @@
                foreach ( $virtualFields as $virtualField ) {
                        $fieldName = $virtualField['fieldName'];
                        $tableName = $virtualField['tableName'];
-                       $foundLikeMatch1 = $foundMatch1 = $foundLikeMatch2 = 
$foundMatch2 = false;
-                       $likePattern1 = $likePattern2 = '';
-                       $patternSuffix = '\s+(HOLDS)\s+(LIKE)?/i';
+                       $fieldTableName = $tableName . '__' . $fieldName;
+                       $replacementFieldName = $fieldTableName . '._value';
+                       $patternSuffix = '\b\s*/i';
+                       $fieldReplaced = false;
                        $throwException = false;
 
-                       $simplePattern1 = 
CargoUtils::getSQLTableAndFieldPattern( $tableName, $fieldName );
-                       if ( preg_match( $simplePattern1, $this->mWhereStr ) ) {
-                               $likePattern1 = 
CargoUtils::getSQLTableAndFieldPattern( $tableName, $fieldName, false ).
-                                               $patternSuffix;
-                               if ( preg_match( $likePattern1, 
$this->mWhereStr, $matches ) ) {
-                                       $foundMatch1 = count( $matches ) == 3;
-                                       $foundLikeMatch1 = count( $matches ) == 
4;
+                       $patternSimple = array(
+                               CargoUtils::getSQLTableAndFieldPattern( 
$tableName, $fieldName ),
+                               CargoUtils::getSQLFieldPattern( $fieldName )
+                               );
+                       $patternRoot = array(
+                               CargoUtils::getSQLTableAndFieldPattern( 
$tableName, $fieldName, false ) . '\s+',
+                               CargoUtils::getSQLFieldPattern( $fieldName, 
false ) . '\s+'
+                               );
+
+                       for ( $i = 0 ; $i < 2 ; $i++ ) {
+                               if ( preg_match( $patternSimple[$i], 
$this->mWhereStr ) ) {
+
+                                       $this->substVirtualFieldName(
+                                               $this->mWhereStr,
+                                               $patternRoot[$i] . 
'HOLDS\s+NOT\s+LIKE' . $patternSuffix,
+                                               "$replacementFieldName NOT LIKE 
",
+                                               $fieldReplaced);
+
+                                       $this->substVirtualFieldName(
+                                               $this->mWhereStr,
+                                               $patternRoot[$i] . 
'HOLDS\s+LIKE' . $patternSuffix,
+                                               "$replacementFieldName LIKE ",
+                                               $fieldReplaced);
+
+                                       $this->substVirtualFieldName(
+                                               $this->mWhereStr,
+                                               $patternRoot[$i] . 
'HOLDS\s+NOT' . $patternSuffix,
+                                               "$replacementFieldName!=",
+                                               $fieldReplaced);
+
+                                       $this->substVirtualFieldName(
+                                               $this->mWhereStr,
+                                               $patternRoot[$i] . 'HOLDS' . 
$patternSuffix,
+                                               "$replacementFieldName=",
+                                               $fieldReplaced);
+
+                                       if ( preg_match( $patternSimple[$i], 
$this->mWhereStr ) ) {
+                                               throw new MWException( "Error: 
operator for the virtual field '" .
+                                                       "$tableName.$fieldName' 
must be 'HOLDS', 'HOLDS NOT', '" .
+                                                       "HOLDS LIKE' or 'HOLDS 
NOT LIKE'." );
+                                       }
                                }
-                               $throwException = $throwException || (! 
$foundMatch1 && ! $foundLikeMatch1);
-                       }
-                       $simplePattern2 = CargoUtils::getSQLFieldPattern( 
$fieldName );
-                       if ( preg_match( $simplePattern2, $this->mWhereStr ) ) {
-                               $likePattern2 = CargoUtils::getSQLFieldPattern( 
$fieldName, false ).
-                                               $patternSuffix;
-                               if ( preg_match( $likePattern2, 
$this->mWhereStr, $matches ) ) {
-                                       $foundMatch2 = count( $matches ) == 3;
-                                       $foundLikeMatch2 = count( $matches ) == 
4;
-                               }
-                               $throwException = $throwException || (! 
$foundMatch2 && ! $foundLikeMatch2);
-                       }
-                       if ( $throwException ) {
-                               throw new MWException( "Error: operator for the 
virtual field '" .
-                                       "$tableName.$fieldName' must be 'HOLDS' 
or 'HOLDS LIKE'." );
                        }
 
-                       if ( $foundLikeMatch1 || $foundLikeMatch2 || 
$foundMatch1 || $foundMatch2 ) {
-                               $fieldTableName = $tableName . '__' . 
$fieldName;
+                       if ( $fieldReplaced ) {
                                $this->addFieldTableToTableNames( 
$fieldTableName, $tableName );
                                $this->mCargoJoinConds[] = array(
                                        'joinType' => 'LEFT OUTER JOIN',
@@ -632,20 +667,6 @@
                                        'table2' => $fieldTableName,
                                        'field2' => '_rowID'
                                );
-                               $likePattern1 = str_replace( '([^\w$.]|^)', 
'\b', $likePattern1);
-                               $likePattern2 = str_replace( '([^\w$.]|^)', 
'\b', $likePattern2);
-
-                               if ( $foundLikeMatch1 ) {
-                                       $this->mWhereStr = preg_replace( 
$likePattern1, "$fieldTableName._value LIKE ",
-                                               $this->mWhereStr );
-                               } elseif ( $foundLikeMatch2 ) {
-                                       $this->mWhereStr = preg_replace( 
$likePattern2, "$fieldTableName._value LIKE ",
-                                               $this->mWhereStr );
-                               } elseif ( $foundMatch1 ) {
-                                       $this->mWhereStr = preg_replace( 
$likePattern1, "$fieldTableName._value=", $this->mWhereStr );
-                               } elseif ( $foundMatch2 ) {
-                                       $this->mWhereStr = preg_replace( 
$likePattern2, "$fieldTableName._value=", $this->mWhereStr );
-                               }
                        }
                }
 

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I46f3e052901420f0c6d68c6291b16b52299d43f5
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Cargo
Gerrit-Branch: master
Gerrit-Owner: Ed Hoo <edward....@gmail.com>

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

Reply via email to