3c92c0bcc95718f7ff5375a319aac36c1c2672a4
[civicrm-core.git] / CRM / Admin / Form / Options.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.6 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2015 |
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-2015
32 * $Id$
33 *
34 */
35
36 /**
37 * This class generates form components for Options
38 *
39 */
40 class CRM_Admin_Form_Options extends CRM_Admin_Form {
41
42 /**
43 * The option group name.
44 *
45 * @var array
46 */
47 protected $_gName;
48
49 /**
50 * The option group name in display format (capitalized, without underscores...etc)
51 *
52 * @var array
53 */
54 protected $_gLabel;
55
56 /**
57 * Pre-process
58 *
59 * @return void
60 */
61 public function preProcess() {
62 parent::preProcess();
63 $session = CRM_Core_Session::singleton();
64 if (!$this->_gName && !empty($this->urlPath[3])) {
65 $this->_gName = $this->urlPath[3];
66 }
67 if (!$this->_gName && !empty($_GET['gid'])) {
68 $this->_gName = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionGroup', (int) $_GET['gid'], 'name');
69 }
70 if ($this->_gName) {
71 $this->set('gName', $this->_gName);
72 }
73 else {
74 $this->_gName = $this->get('gName');
75 }
76 $this->_gid = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionGroup',
77 $this->_gName,
78 'id',
79 'name'
80 );
81 $this->_gLabel = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionGroup', $this->_gid, 'title');
82 $url = "civicrm/admin/options/{$this->_gName}";
83 $params = "reset=1";
84
85 if (($this->_action & CRM_Core_Action::DELETE) &&
86 in_array($this->_gName, array('email_greeting', 'postal_greeting', 'addressee'))
87 ) {
88 // Don't allow delete if the option value belongs to addressee, postal or email greetings and is in use.
89 $findValue = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionValue', $this->_id, 'value');
90 $queryParam = array(1 => array($findValue, 'Integer'));
91 $columnName = $this->_gName . "_id";
92 $sql = "SELECT count(id) FROM civicrm_contact WHERE " . $columnName . " = %1";
93 $isInUse = CRM_Core_DAO::singleValueQuery($sql, $queryParam);
94 if ($isInUse) {
95 $scriptURL = "<a href='" . CRM_Utils_System::docURL2('Update Greetings and Address Data for Contacts', TRUE, NULL, NULL, NULL, "wiki") . "'>" . ts('Learn more about a script that can automatically update contact addressee and greeting options.') . "</a>";
96 CRM_Core_Session::setStatus(ts('The selected %1 option has <strong>not been deleted</strong> because it is currently in use. Please update these contacts to use a different format before deleting this option. %2', array(
97 1 => $this->_gLabel,
98 2 => $scriptURL,
99 )), ts('Sorry'), 'error');
100 $redirect = CRM_Utils_System::url($url, $params);
101 CRM_Utils_System::redirect($redirect);
102 }
103 }
104
105 $session->pushUserContext(CRM_Utils_System::url($url, $params));
106 $this->assign('id', $this->_id);
107
108 if ($this->_id && in_array($this->_gName, CRM_Core_OptionGroup::$_domainIDGroups)) {
109 $domainID = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionValue', $this->_id, 'domain_id', 'id');
110 if (CRM_Core_Config::domainID() != $domainID) {
111 CRM_Core_Error::fatal(ts('You do not have permission to access this page.'));
112 }
113 }
114 }
115
116 /**
117 * Set default values for the form.
118 *
119 * @return void
120 */
121 public function setDefaultValues() {
122 $defaults = parent::setDefaultValues();
123
124 // Default weight & value
125 $fieldValues = array('option_group_id' => $this->_gid);
126 foreach (array('weight', 'value') as $field) {
127 if (empty($defaults[$field])) {
128 $defaults[$field] = CRM_Utils_Weight::getDefaultWeight('CRM_Core_DAO_OptionValue', $fieldValues, $field);
129 }
130 }
131
132 //setDefault of contact types for email greeting, postal greeting, addressee, CRM-4575
133 if (in_array($this->_gName, array(
134 'email_greeting',
135 'postal_greeting',
136 'addressee',
137 ))) {
138 $defaults['contactOptions'] = (CRM_Utils_Array::value('filter', $defaults)) ? $defaults['filter'] : NULL;
139 }
140 // CRM-11516
141 if ($this->_gName == 'payment_instrument' && $this->_id) {
142 $defaults['financial_account_id'] = CRM_Financial_BAO_FinancialTypeAccount::getFinancialAccount($this->_id, 'civicrm_option_value', 'financial_account_id');
143 }
144 return $defaults;
145 }
146
147 /**
148 * Build the form object.
149 *
150 * @return void
151 */
152 public function buildQuickForm() {
153 parent::buildQuickForm();
154 $this->setPageTitle(ts('%1 Option', array(1 => $this->_gLabel)));
155
156 if ($this->_action & CRM_Core_Action::DELETE) {
157 return;
158 }
159
160 $this->applyFilter('__ALL__', 'trim');
161
162 $isReserved = FALSE;
163 if ($this->_id) {
164 $isReserved = (bool) CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionValue', $this->_id, 'is_reserved');
165 }
166
167 $this->add('text',
168 'label',
169 ts('Label'),
170 CRM_Core_DAO::getAttribute('CRM_Core_DAO_OptionValue', 'label'),
171 TRUE
172 );
173
174 $this->add('text',
175 'value',
176 ts('Value'),
177 CRM_Core_DAO::getAttribute('CRM_Core_DAO_OptionValue', 'value'),
178 TRUE
179 );
180
181 if (!in_array($this->_gName, array(
182 'email_greeting',
183 'postal_greeting',
184 'addressee',
185 )) && !$isReserved
186 ) {
187 $this->addRule('label',
188 ts('This Label already exists in the database for this option group. Please select a different Value.'),
189 'optionExists',
190 array('CRM_Core_DAO_OptionValue', $this->_id, $this->_gid, 'label')
191 );
192 }
193
194 if ($this->_gName == 'case_status') {
195 $classes = array(
196 'Opened' => ts('Opened'),
197 'Closed' => ts('Closed'),
198 );
199
200 $grouping = $this->add('select',
201 'grouping',
202 ts('Status Class'),
203 $classes
204 );
205 if ($isReserved) {
206 $grouping->freeze();
207 }
208 }
209 // CRM-11516
210 if ($this->_gName == 'payment_instrument') {
211 $accountType = CRM_Core_PseudoConstant::accountOptionValues('financial_account_type', NULL, " AND v.name = 'Asset' ");
212 $financialAccount = CRM_Contribute_PseudoConstant::financialAccount(NULL, key($accountType));
213
214 $this->add('select', 'financial_account_id', ts('Financial Account'),
215 array('' => ts('- select -')) + $financialAccount,
216 TRUE
217 );
218 }
219
220 $required = FALSE;
221 if ($this->_gName == 'custom_search') {
222 $required = TRUE;
223 }
224 elseif ($this->_gName == 'redaction_rule' || $this->_gName == 'engagement_index') {
225 if ($this->_gName == 'redaction_rule') {
226 $this->add('checkbox',
227 'filter',
228 ts('Regular Expression?')
229 );
230 }
231 }
232 if ($this->_gName == 'participant_listing') {
233 $this->add('text',
234 'description',
235 ts('Description'),
236 CRM_Core_DAO::getAttribute('CRM_Core_DAO_OptionValue', 'description')
237 );
238 }
239 else {
240 // Hard-coding attributes here since description is still stored as varchar and not text in the schema. dgg
241 $this->addWysiwyg('description',
242 ts('Description'),
243 array('rows' => 4, 'cols' => 80),
244 $required
245 );
246 }
247
248 if ($this->_gName == 'event_badge') {
249 $this->add('text',
250 'name',
251 ts('Class Name'),
252 CRM_Core_DAO::getAttribute('CRM_Core_DAO_OptionValue', 'name')
253 );
254 }
255
256 $this->add('text',
257 'weight',
258 ts('Order'),
259 CRM_Core_DAO::getAttribute('CRM_Core_DAO_OptionValue', 'weight'),
260 TRUE
261 );
262 $this->addRule('weight', ts('is a numeric field'), 'numeric');
263
264 // If CiviCase enabled AND "Add" mode OR "edit" mode for non-reserved activities, only allow user to pick Core or CiviCase component.
265 // FIXME: Each component should define whether adding new activity types is allowed.
266 $config = CRM_Core_Config::singleton();
267 if ($this->_gName == 'activity_type' && in_array("CiviCase", $config->enableComponents) &&
268 (($this->_action & CRM_Core_Action::ADD) || !$isReserved)
269 ) {
270 $caseID = CRM_Core_Component::getComponentID('CiviCase');
271 $components = array('' => ts('Contacts AND Cases'), $caseID => ts('Cases Only'));
272 $this->add('select',
273 'component_id',
274 ts('Component'),
275 $components, FALSE
276 );
277 }
278
279 $enabled = $this->add('checkbox', 'is_active', ts('Enabled?'));
280
281 if ($isReserved) {
282 $enabled->freeze();
283 }
284
285 //fix for CRM-3552, CRM-4575
286 $showIsDefaultGroups = array(
287 'email_greeting',
288 'postal_greeting',
289 'addressee',
290 'from_email_address',
291 'case_status',
292 'encounter_medium',
293 'case_type',
294 'payment_instrument',
295 'communication_style',
296 'soft_credit_type',
297 'website_type',
298 );
299
300 if (in_array($this->_gName, $showIsDefaultGroups)) {
301 $this->assign('showDefault', TRUE);
302 $this->add('checkbox', 'is_default', ts('Default Option?'));
303 }
304
305 //get contact type for which user want to create a new greeting/addressee type, CRM-4575
306 if (in_array($this->_gName, array(
307 'email_greeting',
308 'postal_greeting',
309 'addressee',
310 )) && !$isReserved
311 ) {
312 $values = array(
313 1 => ts('Individual'),
314 2 => ts('Household'),
315 3 => ts('Organization'),
316 4 => ts('Multiple Contact Merge'),
317 );
318 $this->add('select', 'contactOptions', ts('Contact Type'), array('' => '-select-') + $values, TRUE);
319 $this->assign('showContactFilter', TRUE);
320 }
321
322 if ($this->_gName == 'participant_status') {
323 // For Participant Status options, expose the 'filter' field to track which statuses are "Counted", and the Visibility field
324 $element = $this->add('checkbox', 'filter', ts('Counted?'));
325 $this->add('select', 'visibility_id', ts('Visibility'), CRM_Core_PseudoConstant::visibility());
326 }
327 if ($this->_gName == 'participant_role') {
328 // For Participant Role options, expose the 'filter' field to track which statuses are "Counted"
329 $this->add('checkbox', 'filter', ts('Counted?'));
330 }
331
332 $this->addFormRule(array('CRM_Admin_Form_Options', 'formRule'), $this);
333 }
334
335 /**
336 * Global form rule.
337 *
338 * @param array $fields
339 * The input form values.
340 * @param array $files
341 * The uploaded files if any.
342 * @param array $self
343 * Current form object.
344 *
345 * @return array
346 * array of errors / empty array.
347 */
348 public static function formRule($fields, $files, $self) {
349 $errors = array();
350 if ($self->_gName == 'case_status' && empty($fields['grouping'])) {
351 $errors['grouping'] = ts('Status class is a required field');
352 }
353
354 if (in_array($self->_gName, array(
355 'email_greeting',
356 'postal_greeting',
357 'addressee',
358 )) && empty($self->_defaultValues['is_reserved'])
359 ) {
360 $label = $fields['label'];
361 $condition = " AND v.label = '{$label}' ";
362 $values = CRM_Core_OptionGroup::values($self->_gName, FALSE, FALSE, FALSE, $condition, 'filter');
363 $checkContactOptions = TRUE;
364
365 if ($self->_id && ($self->_defaultValues['contactOptions'] == $fields['contactOptions'])) {
366 $checkContactOptions = FALSE;
367 }
368
369 if ($checkContactOptions && in_array($fields['contactOptions'], $values)) {
370 $errors['label'] = ts('This Label already exists in the database for the selected contact type.');
371 }
372 }
373
374 if ($self->_gName == 'from_email_address') {
375 $formEmail = CRM_Utils_Mail::pluckEmailFromHeader($fields['label']);
376 if (!CRM_Utils_Rule::email($formEmail)) {
377 $errors['label'] = ts('Please enter a valid email address.');
378 }
379
380 $formName = explode('"', $fields['label']);
381 if (empty($formName[1]) || count($formName) != 3) {
382 $errors['label'] = ts('Please follow the proper format for From Email Address');
383 }
384 }
385
386 return $errors;
387 }
388
389 /**
390 * Process the form submission.
391 *
392 *
393 * @return void
394 */
395 public function postProcess() {
396 if ($this->_action & CRM_Core_Action::DELETE) {
397 $fieldValues = array('option_group_id' => $this->_gid);
398 $wt = CRM_Utils_Weight::delWeight('CRM_Core_DAO_OptionValue', $this->_id, $fieldValues);
399
400 if (CRM_Core_BAO_OptionValue::del($this->_id)) {
401 if ($this->_gName == 'phone_type') {
402 CRM_Core_BAO_Phone::setOptionToNull(CRM_Utils_Array::value('value', $this->_defaultValues));
403 }
404
405 CRM_Core_Session::setStatus(ts('Selected %1 type has been deleted.', array(1 => $this->_gLabel)), ts('Record Deleted'), 'success');
406 }
407 else {
408 CRM_Core_Session::setStatus(ts('Selected %1 type has not been deleted.', array(1 => $this->_gLabel)), ts('Sorry'), 'error');
409 CRM_Utils_Weight::correctDuplicateWeights('CRM_Core_DAO_OptionValue', $fieldValues);
410 }
411 }
412 else {
413 $params = $ids = array();
414 $params = $this->exportValues();
415
416 // allow multiple defaults within group.
417 $allowMultiDefaults = array('email_greeting', 'postal_greeting', 'addressee', 'from_email_address');
418 if (in_array($this->_gName, $allowMultiDefaults)) {
419 if ($this->_gName == 'from_email_address') {
420 $params['reset_default_for'] = array('domain_id' => CRM_Core_Config::domainID());
421 }
422 elseif ($filter = CRM_Utils_Array::value('contactOptions', $params)) {
423 $params['filter'] = $filter;
424 $params['reset_default_for'] = array('filter' => "0, " . $params['filter']);
425 }
426
427 //make sure we should has to have space, CRM-6977
428 if ($this->_gName == 'from_email_address') {
429 $params['label'] = str_replace('"<', '" <', $params['label']);
430 }
431 }
432
433 // set value of filter if not present in params
434 if ($this->_id && !array_key_exists('filter', $params)) {
435 if ($this->_gName == 'participant_role') {
436 $params['filter'] = 0;
437 }
438 else {
439 $params['filter'] = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionValue', $this->_id, 'filter', 'id');
440 }
441 }
442
443 $groupParams = array('name' => ($this->_gName));
444 $optionValue = CRM_Core_OptionValue::addOptionValue($params, $groupParams, $this->_action, $this->_id);
445
446 // CRM-11516
447 if (!empty($params['financial_account_id'])) {
448 $relationTypeId = key(CRM_Core_PseudoConstant::accountOptionValues('account_relationship', NULL, " AND v.name LIKE 'Asset Account is' "));
449 $params = array(
450 'entity_table' => 'civicrm_option_value',
451 'entity_id' => $optionValue->id,
452 'account_relationship' => $relationTypeId,
453 'financial_account_id' => $params['financial_account_id'],
454 );
455 CRM_Financial_BAO_FinancialTypeAccount::add($params);
456 }
457
458 CRM_Core_Session::setStatus(ts('The %1 \'%2\' has been saved.', array(
459 1 => $this->_gLabel,
460 2 => $optionValue->label,
461 )), ts('Saved'), 'success');
462 }
463 }
464
465 }