crm-12976-fix : using 'strstr' while placeholder replacement mechanism
authorPratik Joshi <pratik.joshi@webaccess.co.in>
Thu, 4 Jul 2013 11:40:21 +0000 (17:10 +0530)
committerPratik Joshi <pratik.joshi@webaccess.co.in>
Thu, 4 Jul 2013 11:40:21 +0000 (17:10 +0530)
CRM/Core/DAO.php
tests/phpunit/CRM/Core/DAOTest.php

index dae921dc1531c8c723c32d1c0d74214b11ca5d58..c03f87f9ee2fb1d2c780af0f8a572de62cb40ba2 100644 (file)
@@ -1004,13 +1004,7 @@ FROM   civicrm_domain
       }
     }
 
-    // CRM-11582
-    foreach($tr as $key => $value) {
-      $key   = preg_quote($key);
-      $value = preg_quote($value);
-      $query = preg_replace("/$key\b/", $value, $query);
-    }
-    return $query;
+    return strtr($query, $tr);
   }
 
   static function freeResult($ids = NULL) {
index 5989a9e42b21a9c8e4b794edee8bbf64fee984fa..fe455c6e3bf755af26e781f00e47e299a20be31f 100644 (file)
@@ -71,4 +71,25 @@ class CRM_Core_DAOTest extends CiviUnitTestCase {
     $actualSql = CRM_Core_DAO::composeQuery($inputSql, $inputParams);
     $this->assertEquals($expectSql, $actualSql);
   }
+
+  // CASE: Two params where the %2 is already present in the query
+  // NOTE: This case should rightly FAIL, as using strstr in the replace mechanism will turn
+  // the query into: SELECT * FROM whatever WHERE name = 'Alice' AND title = 'Bob' AND year LIKE ''Bob'012'
+  // So, to avoid such ERROR, the query should be framed like:
+  // 'SELECT * FROM whatever WHERE name = %1 AND title = %3 AND year LIKE '%2012'
+  // $params[3] = array('Bob', 'String');
+  // i.e. the place holder should be unique and should not contain in any other operational use in query
+  function testComposeQueryFailure() {
+    $cases[] = array(
+      'SELECT * FROM whatever WHERE name = %1 AND title = %2 AND year LIKE \'%2012\' ',
+      array(
+        1 => array('Alice', 'String'),
+        2 => array('Bob', 'String'),
+      ),
+      'SELECT * FROM whatever WHERE name = \'Alice\' AND title = \'Bob\' AND year LIKE \'%2012\' ',
+    );
+    list($inputSql, $inputParams, $expectSql) = $cases[0];
+    $actualSql = CRM_Core_DAO::composeQuery($inputSql, $inputParams);
+    $this->assertFalse(($expectSql == $actualSql));
+  }
 }