CRM-21563: Cannot search child tags on 'Manage Tag' page
authordeb.monish <monish.deb@jmaconsulting.biz>
Fri, 15 Dec 2017 08:19:27 +0000 (13:49 +0530)
committerdeb.monish <monish.deb@jmaconsulting.biz>
Fri, 15 Dec 2017 08:22:42 +0000 (13:52 +0530)
CRM/Admin/Page/AJAX.php
CRM/Core/BAO/Tag.php
templates/CRM/Tag/Page/Tag.tpl
tests/phpunit/CRM/Contact/Page/AjaxTest.php

index 1aa2d5c0ad23961dfd62689a7eef81320b024c69..6a326c59046db5dab667a5d4bbb4494ba1c0294a 100644 (file)
@@ -302,51 +302,71 @@ class CRM_Admin_Page_AJAX {
    */
   public static function getTagTree() {
     $parent = CRM_Utils_Type::escape(CRM_Utils_Array::value('parent_id', $_GET, 0), 'Integer');
+    $substring = CRM_Utils_Type::escape(CRM_Utils_Array::value('str', $_GET), 'String');
     $result = array();
 
-    $parentClause = $parent ? "AND parent_id = $parent" : 'AND parent_id IS NULL';
-    $sql = "SELECT *
-      FROM civicrm_tag
-      WHERE is_tagset <> 1 $parentClause
-      GROUP BY id
-      ORDER BY name";
+    $whereClauses = array(
+      'is_tagset <> 1',
+      $parent ? "parent_id = $parent" : 'parent_id IS NULL',
+    );
 
     // fetch all child tags in Array('parent_tag' => array('child_tag_1', 'child_tag_2', ...)) format
-    $childTagIDs = CRM_Core_BAO_Tag::getChildTags();
+    $childTagIDs = CRM_Core_BAO_Tag::getChildTags($substring);
+    $parentIDs = array_keys($childTagIDs);
+
+    if ($substring) {
+      $whereClauses['substring'] = " name LIKE '%$substring%' ";
+      if (!empty($parentIDs)) {
+        $whereClauses['substring'] = sprintf("( %s OR id IN (%s) )", $whereClauses['substring'], implode(',', $parentIDs));
+      }
+    }
+
+    $dao = CRM_Utils_SQL_Select::from('civicrm_tag')
+            ->where($whereClauses)
+            ->groupBy('id')
+            ->orderBy('name')
+            ->execute();
 
-    $dao = CRM_Core_DAO::executeQuery($sql);
     while ($dao->fetch()) {
-      $style = '';
-      if ($dao->color) {
-        $style = "background-color: {$dao->color}; color: " . CRM_Utils_Color::getContrast($dao->color);
+      if (!empty($substring)) {
+        $result[] = $dao->id;
+        if (!empty($childTagIDs[$dao->id])) {
+          $result = array_merge($result, $childTagIDs[$dao->id]);
+        }
+      }
+      else {
+        $style = '';
+        if ($dao->color) {
+          $style = "background-color: {$dao->color}; color: " . CRM_Utils_Color::getContrast($dao->color);
+        }
+        $hasChildTags = empty($childTagIDs[$dao->id]) ? FALSE : TRUE;
+        $usedFor = (array) explode(',', $dao->used_for);
+        $result[] = array(
+          'id' => $dao->id,
+          'text' => $dao->name,
+          'icon' => FALSE,
+          'li_attr' => array(
+            'title' => ((string) $dao->description) . ($dao->is_reserved ? ' (*' . ts('Reserved') . ')' : ''),
+            'class' => $dao->is_reserved ? 'is-reserved' : '',
+          ),
+          'a_attr' => array(
+            'style' => $style,
+            'class' => 'crm-tag-item',
+          ),
+          'children' => $hasChildTags,
+          'data' => array(
+            'description' => (string) $dao->description,
+            'is_selectable' => (bool) $dao->is_selectable,
+            'is_reserved' => (bool) $dao->is_reserved,
+            'used_for' => $usedFor,
+            'color' => $dao->color ? $dao->color : '#ffffff',
+            'usages' => civicrm_api3('EntityTag', 'getcount', array(
+              'entity_table' => array('IN' => $usedFor),
+              'tag_id' => $dao->id,
+            )),
+          ),
+        );
       }
-      $hasChildTags = empty($childTagIDs[$dao->id]) ? FALSE : TRUE;
-      $usedFor = (array) explode(',', $dao->used_for);
-      $result[] = array(
-        'id' => $dao->id,
-        'text' => $dao->name,
-        'icon' => FALSE,
-        'li_attr' => array(
-          'title' => ((string) $dao->description) . ($dao->is_reserved ? ' (*' . ts('Reserved') . ')' : ''),
-          'class' => $dao->is_reserved ? 'is-reserved' : '',
-        ),
-        'a_attr' => array(
-          'style' => $style,
-          'class' => 'crm-tag-item',
-        ),
-        'children' => $hasChildTags,
-        'data' => array(
-          'description' => (string) $dao->description,
-          'is_selectable' => (bool) $dao->is_selectable,
-          'is_reserved' => (bool) $dao->is_reserved,
-          'used_for' => $usedFor,
-          'color' => $dao->color ? $dao->color : '#ffffff',
-          'usages' => civicrm_api3('EntityTag', 'getcount', array(
-            'entity_table' => array('IN' => $usedFor),
-            'tag_id' => $dao->id,
-          )),
-        ),
-      );
     }
 
     if (!empty($_REQUEST['is_unit_test'])) {
index 51ab59370f7072bd61ead72955b3f0e41a99a941..8303bc91359efe60399a77c675d06fbb0b7e8a75 100644 (file)
@@ -551,20 +551,26 @@ class CRM_Core_BAO_Tag extends CRM_Core_DAO_Tag {
   /**
    * Get child tags IDs
    *
+   * @param string $searchString
+   *
    * @return array $childTagIDs
    *   associated array of child tags in Array('Parent Tag ID' => Array('Child Tag 1', ...)) format
    */
-  public static function getChildTags() {
+  public static function getChildTags($searchString = NULL) {
     $childTagIDs = array();
 
+    $whereClauses = array('parent.is_tagset <> 1');
+    if ($searchString) {
+      $whereClauses[] = " child.name LIKE '%$searchString%' ";
+    }
+
     // only fetch those tags which has child tags
-    $getChildGroupSQL = "SELECT parent.id as parent_id, GROUP_CONCAT(child.id) as child_id
-        FROM civicrm_tag parent,
-        civicrm_tag child
-        WHERE parent.is_tagset <> 1 AND child.parent_id = parent.id
-        GROUP BY parent.id
-    ";
-    $dao = CRM_Core_DAO::executeQuery($getChildGroupSQL);
+    $dao = CRM_Utils_SQL_Select::from('civicrm_tag parent')
+              ->join('child', 'INNER JOIN civicrm_tag child ON child.parent_id = parent.id ')
+              ->select('parent.id as parent_id, GROUP_CONCAT(child.id) as child_id')
+              ->where($whereClauses)
+              ->groupBy('parent.id')
+              ->execute();
     while ($dao->fetch()) {
       $childTagIDs[$dao->parent_id] = (array) explode(',', $dao->child_id);
     }
index ed4b5e41bc37b16dc2e5767a48ee8f9fa6bb7149..58ff255bc964126e0f40aa577ba3e67e02e8daf3 100644 (file)
           .on('click', '.used-for-toggle', function() {
             $(this).attr('style', 'display: none !important;').next().show();
           })
+          .on('click', 'a.crm-clear-link', function() {
+            $('.tag-tree', $panel).jstree(true).refresh();
+          })
           .on('crmPopupFormSuccess crmFormSuccess', function(e, cts, data) {
             if ($(e.target).hasClass('tagset-action-delete')) {
               deleteTagset();
               check_callback: true
             },
             'search': {
-              'case_insensitive' : true,
+              'ajax' : {
+                url : CRM.url('civicrm/ajax/tagTree')
+              },
               'show_only_matches': true
             },
             plugins: plugins,
           });
 
         $('input[name=filter_tag_tree]', $panel).on('keyup change', function() {
-          $(".tag-tree", $panel).jstree("search", $(this).val());
+          if ($(this).val() == null) {
+            $('.tag-tree', $panel).jstree(true).refresh();
+          }
+          else {
+            $(".tag-tree", $panel).jstree("search", $(this).val());
+          }
         });
       }
 
index acc0eb8cfee4ea0a627c75d492bd775afda7dce1..488fed60c3530b2c5567fb202988a79585e265b7 100644 (file)
@@ -284,6 +284,21 @@ class CRM_Contact_Page_AjaxTest extends CiviUnitTestCase {
     $childTagTree = CRM_Admin_Page_AJAX::getTagTree();
     $this->assertEquals(1, $childTagTree[0]['data']['usages']);
 
+    // CASE 3 : check the tag IDs returned on searching with 'Level'
+    //  which needs to array('parent tag id', 'level 1 child tag id', 'level 2 child tag id')
+    unset($_GET['parent_id']);
+    $_GET['str'] = 'Level';
+    $tagIDs = CRM_Admin_Page_AJAX::getTagTree();
+    $expectedTagIDs = array($parentTag['id'], $childTag1['id'], $childTag2['id']);
+    $this->checkArrayEquals($tagIDs, $expectedTagIDs);
+
+    // CASE 4 : check the tag IDs returned on searching with 'Level 1'
+    //  which needs to array('parent tag id', 'level 1 child tag id')
+    $_GET['str'] = 'Level 1';
+    $tagIDs = CRM_Admin_Page_AJAX::getTagTree();
+    $expectedTagIDs = array($parentTag['id'], $childTag1['id']);
+    $this->checkArrayEquals($tagIDs, $expectedTagIDs);
+
     //cleanup
     foreach ($contacts as $id) {
       $this->callAPISuccess('Contact', 'delete', array('id' => $id));