$parent = CRM_Utils_Type::escape(CRM_Utils_Array::value('parent_id', $_GET, 0), 'Integer');
$result = array();
- $parentClause = $parent ? "AND tag.parent_id = $parent" : 'AND tag.parent_id IS NULL';
- $sql = "SELECT tag.*, child.id AS child, COUNT(et.id) as usages
- FROM civicrm_tag tag
- LEFT JOIN civicrm_entity_tag et ON et.tag_id = tag.id
- LEFT JOIN civicrm_tag child ON child.parent_id = tag.id
- WHERE tag.is_tagset <> 1 $parentClause
- GROUP BY tag.id
- ORDER BY tag.name";
+ $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";
+
+ // fetch all child tags in Array('parent_tag' => array('child_tag_1', 'child_tag_2', ...)) format
+ $childTagIDs = CRM_Core_BAO_Tag::getChildTags();
+
$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);
}
+ $hasChildTags = empty($childTagIDs[$dao->id]) ? FALSE : TRUE;
+ // get tag IDs includeing its child tags, later used to fetch usage count
+ $tagIDs = array($dao->id);
+ if ($hasChildTags) {
+ $tagIDs = array_merge($tagIDs, $childTagIDs[$dao->id]);
+ }
+ $usedFor = (array) explode(',', $dao->used_for);
$result[] = array(
'id' => $dao->id,
'text' => $dao->name,
'style' => $style,
'class' => 'crm-tag-item',
),
- 'children' => (bool) $dao->child,
+ 'children' => $hasChildTags,
'data' => array(
'description' => (string) $dao->description,
'is_selectable' => (bool) $dao->is_selectable,
'is_reserved' => (bool) $dao->is_reserved,
- 'used_for' => $dao->used_for ? explode(',', $dao->used_for) : array(),
+ 'used_for' => $usedFor,
'color' => $dao->color ? $dao->color : '#ffffff',
- 'usages' => (int) $dao->usages,
+ 'usages' => civicrm_api3('EntityTag', 'getcount', array(
+ 'entity_table' => array('IN' => $usedFor),
+ 'tag_id' => array('IN' => $tagIDs),
+ )),
),
);
}
+ if (!empty($_REQUEST['is_unit_test'])) {
+ return $result;
+ }
+
CRM_Utils_JSON::output($result);
}
return $tags;
}
+ /**
+ * Get child tags IDs
+ *
+ * @return array $childTagIDs
+ * associated array of child tags in Array('Parent Tag ID' => Array('Child Tag 1', ...)) format
+ */
+ public static function getChildTags() {
+ $childTagIDs = array();
+
+ // 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);
+ while ($dao->fetch()) {
+ $childTagIDs[$dao->parent_id] = (array) explode(',', $dao->child_id);
+ }
+
+ // check if child tag has any childs, if found then include those child tags inside parent tag
+ // i.e. format Array('parent_tag' => array('child_tag_1', ...), 'child_tag_1' => array(child_tag_1_1, ..), ..)
+ // to Array('parent_tag' => array('child_tag_1', 'child_tag_1_1'...), ..)
+ foreach ($childTagIDs as $parentTagID => $childTags) {
+ foreach ($childTags as $childTag) {
+ // if $childTag has any child tag of its own
+ if (array_key_exists($childTag, $childTagIDs)) {
+ $childTagIDs[$parentTagID] = array_merge($childTagIDs[$parentTagID], $childTagIDs[$childTag]);
+ }
+ }
+ }
+
+ return $childTagIDs;
+ }
+
}
$this->assertEquals(array('data' => array(), 'recordsTotal' => 0, 'recordsFiltered' => 0), $result);
}
+ /**
+ * CRM-20621 : Test to check usage count of Tag tree
+ */
+ public function testGetTagTree() {
+ $contacts = array();
+ // create three contacts
+ for ($i = 0; $i < 3; $i++) {
+ $contacts[] = $this->individualCreate();
+ }
+
+ // Create Tag called as 'Parent Tag'
+ $parentTag = $this->tagCreate(array(
+ 'name' => 'Parent Tag',
+ 'used_for' => 'civicrm_contact',
+ ));
+ //assign first contact to parent tag
+ $params = array(
+ 'entity_id' => $contacts[0],
+ 'entity_table' => 'civicrm_contact',
+ 'tag_id' => $parentTag['id'],
+ );
+ // TODO: EntityTag.create API is not working
+ CRM_Core_BAO_EntityTag::add($params);
+
+ // Create child Tag of $parentTag
+ $childTag1 = $this->tagCreate(array(
+ 'name' => 'Child Tag Level 1',
+ 'parent_id' => $parentTag['id'],
+ 'used_for' => 'civicrm_contact',
+ ));
+ //assign contact to this level 1 child tag
+ $params = array(
+ 'entity_id' => $contacts[1],
+ 'entity_table' => 'civicrm_contact',
+ 'tag_id' => $childTag1['id'],
+ );
+ CRM_Core_BAO_EntityTag::add($params);
+
+ // Create child Tag of $childTag1
+ $childTag2 = $this->tagCreate(array(
+ 'name' => 'Child Tag Level 2',
+ 'parent_id' => $childTag1['id'],
+ 'used_for' => 'civicrm_contact',
+ ));
+ //assign contact to this level 2 child tag
+ $params = array(
+ 'entity_id' => $contacts[2],
+ 'entity_table' => 'civicrm_contact',
+ 'tag_id' => $childTag2['id'],
+ );
+ CRM_Core_BAO_EntityTag::add($params);
+
+ // CASE I : check the usage count of parent tag which need to be 3
+ // as it should also include the count of child tags
+ $_REQUEST['is_unit_test'] = TRUE;
+ $parentTagTreeResult = CRM_Admin_Page_AJAX::getTagTree();
+ foreach ($parentTagTreeResult as $result) {
+ if ($result['id'] == $parentTag['id']) {
+ $this->assertEquals(3, $result['data']['usages']);
+ }
+ }
+
+ // CASE 2 : check the usage count of level 1 child tag, which needs to be 2
+ // as it should also include the count of its child tag
+ $_GET['parent_id'] = $parentTag['id'];
+ $childTagTree = CRM_Admin_Page_AJAX::getTagTree();
+ $this->assertEquals(2, $childTagTree[0]['data']['usages']);
+
+ // CASE 2 : check the usage count of child tag at level 2
+ //which needs to be 1 as it has no child tag
+ $_GET['parent_id'] = $childTag1['id'];
+ $childTagTree = CRM_Admin_Page_AJAX::getTagTree();
+ $this->assertEquals(1, $childTagTree[0]['data']['usages']);
+
+ //cleanup
+ foreach ($contacts as $id) {
+ $this->callAPISuccess('Contact', 'delete', array('id' => $id));
+ }
+ $this->callAPISuccess('Tag', 'delete', array('id' => $childTag2['id']));
+ $this->callAPISuccess('Tag', 'delete', array('id' => $childTag1['id']));
+ $this->callAPISuccess('Tag', 'delete', array('id' => $parentTag['id']));
+ }
+
/**
* Test to check contact reference field
*/