Merge pull request #4686 from lcdservices/CRM-15698-b
[civicrm-core.git] / CRM / Core / Form / Tag.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2014 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
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. |
13 | |
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. |
18 | |
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 +--------------------------------------------------------------------+
26 */
27
28 /**
29 *
30 * @package CRM
31 * @copyright CiviCRM LLC (c) 2004-2014
32 * $Id$
33 *
34 */
35
36 /**
37 * This class generates form element for free tag widget
38 *
39 */
40 class CRM_Core_Form_Tag {
41 public $_entityTagValues;
42
43 /**
44 * Build tag widget if correct parent is passed
45 *
46 * @param CRM_Core_Form $form form object
47 * @param string $parentNames parent name ( tag name)
48 * @param string $entityTable entitytable 'eg: civicrm_contact'
49 * @param int $entityId entityid 'eg: contact id'
50 * @param boolean $skipTagCreate true if tag need be created using ajax
51 * @param boolean $skipEntityAction true if need to add entry in entry table via ajax
52 * @param string $tagsetElementName if you need to create tagsetlist with specific name
53 *
54 * @return void
55 * @access public
56 * @static
57 */
58 static function buildQuickForm(&$form, $parentNames, $entityTable, $entityId = NULL, $skipTagCreate = FALSE,
59 $skipEntityAction = FALSE, $tagsetElementName = NULL ) {
60 $tagset = $form->_entityTagValues = array();
61 $form->assign("isTagset", FALSE);
62 $mode = NULL;
63
64 foreach ($parentNames as &$parentNameItem) {
65 // get the parent id for tag list input for keyword
66 $parentId = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_Tag', $parentNameItem, 'id', 'name');
67
68 // check if parent exists
69 if ($parentId) {
70 $tagsetItem = $tagsetElementName . 'parentId_' . $parentId;
71 $tagset[$tagsetItem]['parentID'] = $parentId;
72
73 list(, $mode) = explode('_', $entityTable);
74 if (!$tagsetElementName) {
75 $tagsetElementName = $mode . "_taglist";
76 }
77 $tagset[$tagsetItem]['tagsetElementName'] = $tagsetElementName;
78
79 $form->addEntityRef("{$tagsetElementName}[{$parentId}]", $parentNameItem, array(
80 'entity' => 'tag',
81 'multiple' => TRUE,
82 'create' => !$skipTagCreate,
83 'api' => array('params' => array('parent_id' => $parentId)),
84 'data-entity_table' => $entityTable,
85 'data-entity_id' => $entityId,
86 'class' => "crm-$mode-tagset",
87 ));
88
89 if ($entityId) {
90 $tagset[$tagsetItem]['entityId'] = $entityId;
91 $entityTags = CRM_Core_BAO_EntityTag::getChildEntityTags($parentId, $entityId, $entityTable);
92 if ($entityTags) {
93 $form->setDefaults(array("{$tagsetElementName}[{$parentId}]" => implode(',', array_keys($entityTags))));
94 }
95 }
96 else {
97 $skipEntityAction = TRUE;
98 }
99 $tagset[$tagsetItem]['skipEntityAction'] = $skipEntityAction;
100 }
101 }
102
103 if (!empty($tagset)) {
104 // assign current tagsets which is used in postProcess
105 $form->_tagsetInfo = $tagset;
106 $form->assign("tagsetType", $mode);
107 // Merge this tagset info with possibly existing info in the template
108 $tagsetInfo = (array) $form->get_template_vars("tagsetInfo");
109 if (empty($tagsetInfo[$mode])) {
110 $tagsetInfo[$mode] = array();
111 }
112 $tagsetInfo[$mode] = array_merge($tagsetInfo[$mode], $tagset);
113 $form->assign("tagsetInfo", $tagsetInfo);
114 $form->assign("isTagset", TRUE);
115 }
116 }
117
118 /**
119 * Save entity tags when it is not save used AJAX
120 *
121 * @param array $params associated array
122 * @param int $entityId entity id, eg: contact id, activity id, case id, file id
123 * @param string $entityTable entity table
124 * @param CRM_Core_Form $form form object
125 *
126 * @return void
127 * @access public
128 * @static
129 */
130 static function postProcess(&$params, $entityId, $entityTable = 'civicrm_contact', &$form) {
131 if ($form && !empty($form->_entityTagValues)) {
132 $existingTags = $form->_entityTagValues;
133 }
134 else {
135 $existingTags = CRM_Core_BAO_EntityTag::getTag($entityId, $entityTable);
136 }
137
138 if ($form) {
139 // if the key is missing from the form response then all the tags were deleted / cleared
140 // in that case we create empty tagset params so that below logic works and tagset are
141 // deleted correctly
142 foreach ($form->_tagsetInfo as $tagsetName => $tagsetInfo) {
143 $tagsetId = explode('parentId_', $tagsetName);
144 $tagsetId = $tagsetId[1];
145 if (empty($params[$tagsetId])) {
146 $params[$tagsetId] = '';
147 }
148 }
149 }
150
151 // when form is submitted with tagset values below logic will work and in the case when all tags in a tagset
152 // are deleted we will have to set $params[tagset id] = '' which is done by above logic
153 foreach ($params as $parentId => $value) {
154 $newTagIds = array();
155 $tagIds = array();
156
157 if ($value) {
158 $tagIds = explode(',', $value);
159 foreach ($tagIds as $tagId) {
160 if ($form && $form->_action != CRM_Core_Action::UPDATE || !array_key_exists($tagId, $existingTags)) {
161 $newTagIds[] = $tagId;
162 }
163 }
164 }
165
166 // Any existing entity tags from this tagset missing from the $params should be deleted
167 $deleteSQL = "DELETE FROM civicrm_entity_tag
168 USING civicrm_entity_tag, civicrm_tag
169 WHERE civicrm_tag.id=civicrm_entity_tag.tag_id
170 AND civicrm_entity_tag.entity_table='{$entityTable}'
171 AND entity_id={$entityId} AND parent_id={$parentId}";
172 if (!empty($tagIds)) {
173 $deleteSQL .= " AND tag_id NOT IN (" . implode(', ', $tagIds) . ");";
174 }
175
176 CRM_Core_DAO::executeQuery($deleteSQL);
177
178 if (!empty($newTagIds)) {
179 // New tag ids can be inserted directly into the db table.
180 $insertValues = array();
181 foreach ($newTagIds as $tagId) {
182 $insertValues[] = "( {$tagId}, {$entityId}, '{$entityTable}' ) ";
183 }
184 $insertSQL = 'INSERT INTO civicrm_entity_tag ( tag_id, entity_id, entity_table )
185 VALUES ' . implode(', ', $insertValues) . ';';
186 CRM_Core_DAO::executeQuery($insertSQL);
187 }
188 }
189 }
190 }
191