3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2014 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
29 * This class contains functions for managing Tag(tag) for a contact
32 * @copyright CiviCRM LLC (c) 2004-2014
36 class CRM_Core_BAO_EntityTag
extends CRM_Core_DAO_EntityTag
{
40 * Given a contact id, it returns an array of tag id's the
43 * @param int $entityID id of the entity usually the contactID.
44 * @param string $entityTable name of the entity table usually 'civicrm_contact'
47 ) reference $tag array of category id's the contact belongs to.
52 static function &getTag($entityID, $entityTable = 'civicrm_contact') {
55 $entityTag = new CRM_Core_BAO_EntityTag();
56 $entityTag->entity_id
= $entityID;
57 $entityTag->entity_table
= $entityTable;
60 while ($entityTag->fetch()) {
61 $tags[$entityTag->tag_id
] = $entityTag->tag_id
;
67 * takes an associative array and creates a entityTag object
69 * the function extract all the params it needs to initialize the create a
70 * group object. the params array could contain additional unused name/value
73 * @param array $params (reference ) an assoc array of name/value pairs
75 * @return object CRM_Core_BAO_EntityTag object
79 static function add(&$params) {
80 $dataExists = self
::dataExists($params);
85 $entityTag = new CRM_Core_BAO_EntityTag();
86 $entityTag->copyValues($params);
88 // dont save the object if it already exists, CRM-1276
89 if (!$entityTag->find(TRUE)) {
92 //invoke post hook on entityTag
93 // we are using this format to keep things consistent between the single and bulk operations
94 // so a bit different from other post hooks
95 $object = array(0 => array(0 => $params['entity_id']), 1 => $params['entity_table']);
96 CRM_Utils_Hook
::post('create', 'EntityTag', $params['tag_id'], $object);
102 * Check if there is data to create the object
104 * @params array $params (reference ) an assoc array of name/value pairs
112 static function dataExists(&$params) {
113 return ($params['tag_id'] == 0) ?
FALSE : TRUE;
117 * Function to delete the tag for a contact
119 * @param array $params (reference ) an assoc array of name/value pairs
121 * @return object CRM_Core_BAO_EntityTag object
126 static function del(&$params) {
127 $entityTag = new CRM_Core_BAO_EntityTag();
128 $entityTag->copyValues($params);
129 $entityTag->delete();
131 //invoke post hook on entityTag
132 $object = array(0 => array(0 => $params['entity_id']), 1 => $params['entity_table']);
133 CRM_Utils_Hook
::post('delete', 'EntityTag', $params['tag_id'], $object);
137 * Given an array of entity ids and entity table, add all the entity to the tags
139 * @param array $entityIds (reference ) the array of entity ids to be added
140 * @param int $tagId the id of the tag
141 * @param string $entityTable
142 * @params string $entityTable name of entity table default:civicrm_contact
144 * @return array (total, added, notAdded) count of enities added to tag
148 static function addEntitiesToTag(&$entityIds, $tagId, $entityTable = 'civicrm_contact') {
149 $numEntitiesAdded = 0;
150 $numEntitiesNotAdded = 0;
151 $entityIdsAdded = array();
153 foreach ($entityIds as $entityId) {
154 $tag = new CRM_Core_DAO_EntityTag();
156 $tag->entity_id
= $entityId;
157 $tag->tag_id
= $tagId;
158 $tag->entity_table
= $entityTable;
161 $entityIdsAdded[] = $entityId;
165 $numEntitiesNotAdded++
;
169 //invoke post hook on entityTag
170 $object = array($entityIdsAdded, $entityTable);
171 CRM_Utils_Hook
::post('create', 'EntityTag', $tagId, $object);
173 // reset the group contact cache for all groups
174 // if tags are being used in a smart group
175 CRM_Contact_BAO_GroupContactCache
::remove();
177 return array(count($entityIds), $numEntitiesAdded, $numEntitiesNotAdded);
181 * Given an array of entity ids and entity table, remove entity(s) tags
183 * @param array $entityIds (reference ) the array of entity ids to be removed
184 * @param int $tagId the id of the tag
185 * @param string $entityTable
186 * @params string $entityTable name of entity table default:civicrm_contact
188 * @return array (total, removed, notRemoved) count of entities removed from tags
192 static function removeEntitiesFromTag(&$entityIds, $tagId, $entityTable = 'civicrm_contact') {
193 $numEntitiesRemoved = 0;
194 $numEntitiesNotRemoved = 0;
195 $entityIdsRemoved = array();
197 foreach ($entityIds as $entityId) {
198 $tag = new CRM_Core_DAO_EntityTag();
200 $tag->entity_id
= $entityId;
201 $tag->tag_id
= $tagId;
202 $tag->entity_table
= $entityTable;
205 $entityIdsRemoved[] = $entityId;
206 $numEntitiesRemoved++
;
209 $numEntitiesNotRemoved++
;
213 //invoke post hook on entityTag
214 $object = array($entityIdsRemoved, $entityTable);
215 CRM_Utils_Hook
::post('delete', 'EntityTag', $tagId, $object);
217 // reset the group contact cache for all groups
218 // if tags are being used in a smart group
219 CRM_Contact_BAO_GroupContactCache
::remove();
221 return array(count($entityIds), $numEntitiesRemoved, $numEntitiesNotRemoved);
225 * takes an associative array and creates tag entity record for all tag entities
227 * @param array $params (reference ) an assoc array of name/value pairs
228 * @param $entityTable
231 * @internal param array $contactId contact id
237 static function create(&$params, $entityTable, $entityID) {
238 // get categories for the entity id
239 $entityTag = CRM_Core_BAO_EntityTag
::getTag($entityID, $entityTable);
241 // get the list of all the categories
242 $allTag = CRM_Core_BAO_Tag
::getTags($entityTable);
244 // this fix is done to prevent warning generated by array_key_exits incase of empty array is given as input
245 if (!is_array($params)) {
249 // this fix is done to prevent warning generated by array_key_exits incase of empty array is given as input
250 if (!is_array($entityTag)) {
251 $entityTag = array();
254 // check which values has to be inserted/deleted for contact
255 foreach ($allTag as $key => $varValue) {
256 $tagParams['entity_table'] = $entityTable;
257 $tagParams['entity_id'] = $entityID;
258 $tagParams['tag_id'] = $key;
260 if (array_key_exists($key, $params) && !array_key_exists($key, $entityTag)) {
261 // insert a new record
262 CRM_Core_BAO_EntityTag
::add($tagParams);
264 elseif (!array_key_exists($key, $params) && array_key_exists($key, $entityTag)) {
265 // delete a record for existing contact
266 CRM_Core_BAO_EntityTag
::del($tagParams);
272 * This function returns all entities assigned to a specific tag
274 * @param object $tag an object of a tag.
276 * @return array $entityIds array of entity ids
279 function getEntitiesByTag($tag) {
280 $entityIds = array();
281 $entityTagDAO = new CRM_Core_DAO_EntityTag();
282 $entityTagDAO->tag_id
= $tag->id
;
283 $entityTagDAO->find();
284 while ($entityTagDAO->fetch()) {
285 $entityIds[] = $entityTagDAO->entity_id
;
291 * Function to get contact tags
293 static function getContactTags($contactID, $count = FALSE) {
294 $contactTags = array();
296 $select = "SELECT name ";
299 $select = "SELECT count(*) as cnt";
304 INNER JOIN civicrm_entity_tag et ON ( ct.id = et.tag_id AND
305 et.entity_id = {$contactID} AND
306 et.entity_table = 'civicrm_contact' AND
309 $dao = CRM_Core_DAO
::executeQuery($query);
316 while ($dao->fetch()) {
317 $contactTags[] = $dao->name
;
324 * Function to get child contact tags given parentId
326 static function getChildEntityTags($parentId, $entityId, $entityTable = 'civicrm_contact') {
327 $entityTags = array();
328 $query = "SELECT ct.id as tag_id, name FROM civicrm_tag ct
329 INNER JOIN civicrm_entity_tag et ON ( et.entity_id = {$entityId} AND
330 et.entity_table = '{$entityTable}' AND et.tag_id = ct.id)
331 WHERE ct.parent_id = {$parentId}";
333 $dao = CRM_Core_DAO
::executeQuery($query);
335 while ($dao->fetch()) {
336 $entityTags[$dao->tag_id
] = array(
337 'id' => $dao->tag_id
,
338 'name' => $dao->name
,
346 * Function to merge two tags: tag B into tag A.
348 function mergeTags($tagAId, $tagBId) {
349 $queryParams = array(1 => array($tagBId, 'Integer'),
350 2 => array($tagAId, 'Integer'),
353 // re-compute used_for field
354 $query = "SELECT id, name, used_for FROM civicrm_tag WHERE id IN (%1, %2)";
355 $dao = CRM_Core_DAO
::executeQuery($query, $queryParams);
357 while ($dao->fetch()) {
358 $label = ($dao->id
== $tagAId) ?
'tagA' : 'tagB';
359 $tags[$label] = $dao->name
;
360 $tags["{$label}_used_for"] = $dao->used_for ?
explode(",", $dao->used_for
) : array();
362 $usedFor = array_merge($tags["tagA_used_for"], $tags["tagB_used_for"]);
363 $usedFor = implode(',', array_unique($usedFor));
364 $tags["tagB_used_for"] = explode(",", $usedFor);
366 // get all merge queries together
368 // 1. update entity tag entries
369 "UPDATE IGNORE civicrm_entity_tag SET tag_id = %1 WHERE tag_id = %2",
370 // 2. update used_for info for tag B
371 "UPDATE civicrm_tag SET used_for = '{$usedFor}' WHERE id = %1",
372 // 3. remove tag A, if tag A is getting merged into B
373 "DELETE FROM civicrm_tag WHERE id = %2",
374 // 4. remove duplicate entity tag records
375 "DELETE et2.* from civicrm_entity_tag et1 INNER JOIN civicrm_entity_tag et2 ON et1.entity_table = et2.entity_table AND et1.entity_id = et2.entity_id AND et1.tag_id = et2.tag_id WHERE et1.id < et2.id",
376 // 5. remove orphaned entity_tags
377 "DELETE FROM civicrm_entity_tag WHERE tag_id = %2",
379 $tables = array('civicrm_entity_tag', 'civicrm_tag');
381 // Allow hook_civicrm_merge() to add SQL statements for the merge operation AND / OR
382 // perform any other actions like logging
383 CRM_Utils_Hook
::merge('sqls', $sqls, $tagAId, $tagBId, $tables);
385 // call the SQL queries in one transaction
386 $transaction = new CRM_Core_Transaction();
387 foreach ($sqls as $sql) {
388 CRM_Core_DAO
::executeQuery($sql, $queryParams, TRUE, NULL, TRUE);
390 $transaction->commit();
392 $tags['status'] = TRUE;