3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
15 * @copyright CiviCRM LLC https://civicrm.org/licensing
19 * This class generates form element for free tag widget.
21 class CRM_Core_Form_Tag
{
22 public $_entityTagValues;
25 * Build tag widget if correct parent is passed
27 * @param CRM_Core_Form $form
29 * @param string $parentNames
30 * Parent name ( tag name).
31 * @param string $entityTable
32 * Entitytable 'eg: civicrm_contact'.
33 * @param int $entityId
34 * Entityid 'eg: contact id'.
35 * @param bool $skipTagCreate
36 * True if tag need be created using ajax.
37 * @param bool $skipEntityAction
38 * True if need to add entry in entry table via ajax.
39 * @param string $tagsetElementName
40 * If you need to create tagsetlist with specific name.
42 public static function buildQuickForm(
43 &$form, $parentNames, $entityTable, $entityId = NULL, $skipTagCreate = FALSE,
44 $skipEntityAction = FALSE, $tagsetElementName = NULL) {
45 $tagset = $form->_entityTagValues
= [];
46 $form->assign("isTagset", FALSE);
49 foreach ($parentNames as &$parentNameItem) {
50 // get the parent id for tag list input for keyword
51 $parentId = CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_Tag', $parentNameItem, 'id', 'name');
53 // check if parent exists
55 $tagsetItem = $tagsetElementName . 'parentId_' . $parentId;
56 $tagset[$tagsetItem]['parentID'] = $parentId;
58 list(, $mode) = explode('_', $entityTable);
59 if (!$tagsetElementName) {
60 $tagsetElementName = $mode . "_taglist";
62 $tagset[$tagsetItem]['tagsetElementName'] = $tagsetElementName;
64 $form->addEntityRef("{$tagsetElementName}[{$parentId}]", $parentNameItem, [
67 'create' => !$skipTagCreate,
68 'api' => ['params' => ['parent_id' => $parentId]],
69 'data-entity_table' => $entityTable,
70 'data-entity_id' => $entityId,
71 'class' => "crm-$mode-tagset",
72 'select' => ['minimumInputLength' => 0],
76 $tagset[$tagsetItem]['entityId'] = $entityId;
77 $entityTags = CRM_Core_BAO_EntityTag
::getChildEntityTags($parentId, $entityId, $entityTable);
79 $form->setDefaults(["{$tagsetElementName}[{$parentId}]" => implode(',', array_keys($entityTags))]);
83 $skipEntityAction = TRUE;
85 $tagset[$tagsetItem]['skipEntityAction'] = $skipEntityAction;
89 if (!empty($tagset)) {
90 // assign current tagsets which is used in postProcess
91 $form->_tagsetInfo
= $tagset;
92 $form->assign("tagsetType", $mode);
93 // Merge this tagset info with possibly existing info in the template
94 $tagsetInfo = (array) $form->get_template_vars("tagsetInfo");
95 if (empty($tagsetInfo[$mode])) {
96 $tagsetInfo[$mode] = [];
98 $tagsetInfo[$mode] = array_merge($tagsetInfo[$mode], $tagset);
99 $form->assign("tagsetInfo", $tagsetInfo);
100 $form->assign("isTagset", TRUE);
105 * Save entity tags when it is not save used AJAX.
107 * @param array $params
108 * @param int $entityId
109 * Entity id, eg: contact id, activity id, case id, file id.
110 * @param string $entityTable
112 * @param CRM_Core_Form $form
115 public static function postProcess(&$params, $entityId, $entityTable = 'civicrm_contact', &$form = NULL) {
116 if ($form && !empty($form->_entityTagValues
)) {
117 $existingTags = $form->_entityTagValues
;
120 $existingTags = CRM_Core_BAO_EntityTag
::getTag($entityId, $entityTable);
124 // if the key is missing from the form response then all the tags were deleted / cleared
125 // in that case we create empty tagset params so that below logic works and tagset are
127 foreach ($form->_tagsetInfo
as $tagsetName => $tagsetInfo) {
128 $tagsetId = explode('parentId_', $tagsetName);
129 $tagsetId = $tagsetId[1];
130 if (empty($params[$tagsetId])) {
131 $params[$tagsetId] = '';
136 // when form is submitted with tagset values below logic will work and in the case when all tags in a tagset
137 // are deleted we will have to set $params[tagset id] = '' which is done by above logic
138 foreach ($params as $parentId => $value) {
143 $tagIds = explode(',', $value);
144 foreach ($tagIds as $tagId) {
145 if ($form && $form->_action
!= CRM_Core_Action
::UPDATE ||
!array_key_exists($tagId, $existingTags)) {
146 $newTagIds[] = $tagId;
151 // Any existing entity tags from this tagset missing from the $params should be deleted
152 $deleteSQL = "DELETE FROM civicrm_entity_tag
153 USING civicrm_entity_tag, civicrm_tag
154 WHERE civicrm_tag.id=civicrm_entity_tag.tag_id
155 AND civicrm_entity_tag.entity_table='{$entityTable}'
156 AND entity_id={$entityId} AND parent_id={$parentId}";
157 if (!empty($tagIds)) {
158 $deleteSQL .= " AND tag_id NOT IN (" . implode(', ', $tagIds) . ");";
161 CRM_Core_DAO
::executeQuery($deleteSQL);
163 if (!empty($newTagIds)) {
164 // New tag ids can be inserted directly into the db table.
166 foreach ($newTagIds as $tagId) {
167 $insertValues[] = "( {$tagId}, {$entityId}, '{$entityTable}' ) ";
169 $insertSQL = 'INSERT INTO civicrm_entity_tag ( tag_id, entity_id, entity_table )
170 VALUES ' . implode(', ', $insertValues) . ';';
171 CRM_Core_DAO
::executeQuery($insertSQL);