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 +--------------------------------------------------------------------+
31 * @copyright CiviCRM LLC (c) 2004-2014
37 * form to process actions on the set aspect of Custom Data
39 class CRM_Custom_Form_Group
extends CRM_Core_Form
{
42 * The set id saved to the session for an update
55 protected $_isGroupEmpty = TRUE;
58 * Array of existing subtypes set for a custom set
63 protected $_subtypes = array();
66 * Array of default params
71 protected $_defaults = array();
74 * Set variables up before form is built
81 public function preProcess() {
83 $this->_id
= $this->get('id');
85 if ($this->_id
&& $isReserved = CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_CustomGroup', $this->_id
, 'is_reserved', 'id')) {
86 CRM_Core_Error
::fatal("You cannot edit the settings of a reserved custom field-set.");
88 // setting title for html page
89 if ($this->_action
== CRM_Core_Action
::UPDATE
) {
90 $title = CRM_Core_BAO_CustomGroup
::getTitle($this->_id
);
91 CRM_Utils_System
::setTitle(ts('Edit %1', array(1 => $title)));
93 elseif ($this->_action
== CRM_Core_Action
::VIEW
) {
94 $title = CRM_Core_BAO_CustomGroup
::getTitle($this->_id
);
95 CRM_Utils_System
::setTitle(ts('Preview %1', array(1 => $title)));
98 CRM_Utils_System
::setTitle(ts('New Custom Field Set'));
101 if (isset($this->_id
)) {
102 $params = array('id' => $this->_id
);
103 CRM_Core_BAO_CustomGroup
::retrieve($params, $this->_defaults
);
105 $subExtends = CRM_Utils_Array
::value('extends_entity_column_value', $this->_defaults
);
106 if (!empty($subExtends)) {
107 $this->_subtypes
= explode(CRM_Core_DAO
::VALUE_SEPARATOR
, substr($subExtends, 1, -1));
115 * @param array $fields the input form values
116 * @param array $files the uploaded files if any
120 * @return true if no errors, else array of errors
124 static function formRule($fields, $files, $self) {
127 //validate group title as well as name.
128 $title = $fields['title'];
129 $name = CRM_Utils_String
::munge($title, '_', 64);
130 $query = 'select count(*) from civicrm_custom_group where ( name like %1 OR title like %2 ) and id != %3';
131 $grpCnt = CRM_Core_DAO
::singleValueQuery($query, array(1 => array($name, 'String'),
132 2 => array($title, 'String'),
133 3 => array((int)$self->_id
, 'Integer'),
136 $errors['title'] = ts('Custom group \'%1\' already exists in Database.', array(1 => $title));
139 if (!empty($fields['extends'][1])) {
140 if (in_array('', $fields['extends'][1]) && count($fields['extends'][1]) > 1) {
141 $errors['extends'] = ts("Cannot combine other option with 'Any'.");
145 if (empty($fields['extends'][0])) {
146 $errors['extends'] = ts("You need to select the type of record that this set of custom fields is applicable for.");
149 $extends = array('Activity', 'Relationship', 'Group', 'Contribution', 'Membership', 'Event', 'Participant');
150 if (in_array($fields['extends'][0], $extends) && $fields['style'] == 'Tab') {
151 $errors['style'] = ts("Display Style should be Inline for this Class");
152 $self->assign('showStyle', TRUE);
155 if (!empty($fields['is_multiple'])) {
156 $self->assign('showMultiple', TRUE);
159 if (empty($fields['is_multiple']) && $fields['style'] == 'Tab with table') {
160 $errors['style'] = ts("Display Style 'Tab with table' is only supported for multiple-record custom field sets.");
163 //checks the given custom set doesnot start with digit
164 $title = $fields['title'];
165 if (!empty($title)) {
166 // gives the ascii value
167 $asciiValue = ord($title{0});
168 if ($asciiValue >= 48 && $asciiValue <= 57) {
169 $errors['title'] = ts("Name cannot not start with a digit");
173 return empty($errors) ?
TRUE : $errors;
177 * This function is used to add the rules (mainly global rules) for form.
178 * All local rules are added near the element
186 function addRules() {
187 $this->addFormRule(array('CRM_Custom_Form_Group', 'formRule'), $this);
191 * Build the form object
198 public function buildQuickForm() {
199 $this->applyFilter('__ALL__', 'trim');
201 $attributes = CRM_Core_DAO
::getAttribute('CRM_Core_DAO_CustomGroup');
204 $this->add('text', 'title', ts('Set Name'), $attributes['title'], TRUE);
206 //Fix for code alignment, CRM-3058
207 $contactTypes = array('Contact', 'Individual', 'Household', 'Organization');
208 $this->assign('contactTypes', json_encode($contactTypes));
210 $sel1 = array("" => "- select -") + CRM_Core_SelectValues
::customGroupExtends();
212 $activityType = CRM_Core_PseudoConstant
::activityType(FALSE, TRUE, FALSE, 'label', TRUE);
214 $eventType = CRM_Core_OptionGroup
::values('event_type');
215 $grantType = CRM_Core_OptionGroup
::values('grant_type');
216 $campaignTypes = CRM_Campaign_PseudoConstant
::campaignType();
217 $membershipType = CRM_Member_BAO_MembershipType
::getMembershipTypes(FALSE);
218 $participantRole = CRM_Core_OptionGroup
::values('participant_role');
219 $relTypeInd = CRM_Contact_BAO_Relationship
::getContactRelationshipType(NULL, 'null', NULL, 'Individual');
220 $relTypeOrg = CRM_Contact_BAO_Relationship
::getContactRelationshipType(NULL, 'null', NULL, 'Organization');
221 $relTypeHou = CRM_Contact_BAO_Relationship
::getContactRelationshipType(NULL, 'null', NULL, 'Household');
224 asort($activityType);
227 asort($membershipType);
228 asort($participantRole);
229 $allRelationshipType = array();
230 $allRelationshipType = array_merge($relTypeInd, $relTypeOrg);
231 $allRelationshipType = array_merge($allRelationshipType, $relTypeHou);
233 //adding subtype specific relationships CRM-5256
234 $subTypes = CRM_Contact_BAO_ContactType
::subTypeInfo();
236 foreach ($subTypes as $subType => $val) {
237 $subTypeRelationshipTypes = CRM_Contact_BAO_Relationship
::getContactRelationshipType(NULL, NULL, NULL, $val['parent'],
238 FALSE, 'label', TRUE, $subType
240 $allRelationshipType = array_merge($allRelationshipType, $subTypeRelationshipTypes);
243 $sel2['Event'] = $eventType;
244 $sel2['Grant'] = $grantType;
245 $sel2['Activity'] = $activityType;
246 $sel2['Campaign'] = $campaignTypes;
247 $sel2['Membership'] = $membershipType;
248 $sel2['ParticipantRole'] = $participantRole;
249 $sel2['ParticipantEventName'] = CRM_Event_PseudoConstant
::event(NULL, FALSE, "( is_template IS NULL OR is_template != 1 )");
250 $sel2['ParticipantEventType'] = $eventType;
251 $sel2['Contribution'] = CRM_Contribute_PseudoConstant
::financialType();
252 $sel2['Relationship'] = $allRelationshipType;
254 $sel2['Individual'] = CRM_Contact_BAO_ContactType
::subTypePairs('Individual', FALSE, NULL);
255 $sel2['Household'] = CRM_Contact_BAO_ContactType
::subTypePairs('Household', FALSE, NULL);
256 $sel2['Organization'] = CRM_Contact_BAO_ContactType
::subTypePairs('Organization', FALSE, NULL);
258 CRM_Core_BAO_CustomGroup
::getExtendedObjectTypes($sel2);
260 foreach ($sel2 as $main => $sub) {
261 if (!empty($sel2[$main])) {
262 if ($main == 'Relationship') {
263 $relName = self
::getFormattedList($sel2[$main]);
264 $sel2[$main] = array(
265 '' => ts("- Any -")) +
$relName;
268 $sel2[$main] = array(
269 '' => ts("- Any -")) +
$sel2[$main];
274 $cSubTypes = CRM_Core_Component
::contactSubTypes();
276 if (!empty($cSubTypes)) {
277 $contactSubTypes = array();
278 foreach ($cSubTypes as $key => $value) {
279 $contactSubTypes[$key] = $key;
281 $sel2['Contact'] = array(
282 "" => "-- Any --") +
$contactSubTypes;
285 if (!isset($this->_id
)) {
286 $formName = 'document.forms.' . $this->_name
;
288 $js = "<script type='text/javascript'>\n";
289 $js .= "{$formName}['extends_1'].style.display = 'none';\n";
291 $this->assign('initHideBlocks', $js);
295 $sel = &$this->add('hierselect',
299 'name' => 'extends[0]',
300 'style' => 'vertical-align: top;'
304 $sel->setOptions(array($sel1, $sel2));
305 if (is_a($sel->_elements
[1], 'HTML_QuickForm_select')) {
306 // make second selector a multi-select -
307 $sel->_elements
[1]->setMultiple(TRUE);
308 $sel->_elements
[1]->setSize(5);
310 if ($this->_action
== CRM_Core_Action
::UPDATE
) {
311 $subName = CRM_Utils_Array
::value('extends_entity_column_id', $this->_defaults
);
312 if ($this->_defaults
['extends'] == 'Participant') {
314 $this->_defaults
['extends'] = 'ParticipantRole';
316 elseif ($subName == 2) {
317 $this->_defaults
['extends'] = 'ParticipantEventName';
319 elseif ($subName == 3) {
320 $this->_defaults
['extends'] = 'ParticipantEventType';
324 //allow to edit settings if custom set is empty CRM-5258
325 $this->_isGroupEmpty
= CRM_Core_BAO_CustomGroup
::isGroupEmpty($this->_id
);
326 if (!$this->_isGroupEmpty
) {
327 if (!empty($this->_subtypes
)) {
328 // we want to allow adding / updating subtypes for this case,
329 // and therefore freeze the first selector only.
330 $sel->_elements
[0]->freeze();
333 // freeze both the selectors
337 $this->assign('isCustomGroupEmpty', $this->_isGroupEmpty
);
338 $this->assign('gid', $this->_id
);
340 $this->assign('defaultSubtypes', json_encode($this->_subtypes
));
343 $this->addWysiwyg('help_pre', ts('Pre-form Help'), $attributes['help_pre']);
344 $this->addWysiwyg('help_post', ts('Post-form Help'), $attributes['help_post']);
347 $this->add('text', 'weight', ts('Order'), $attributes['weight'], TRUE);
348 $this->addRule('weight', ts('is a numeric field'), 'numeric');
351 $this->add('select', 'style', ts('Display Style'), CRM_Core_SelectValues
::customGroupStyle());
353 // is this set collapsed or expanded ?
354 $this->addElement('checkbox', 'collapse_display', ts('Collapse this set on initial display'));
356 // is this set collapsed or expanded ? in advanced search
357 $this->addElement('checkbox', 'collapse_adv_display', ts('Collapse this set in Advanced Search'));
359 // is this set active ?
360 $this->addElement('checkbox', 'is_active', ts('Is this Custom Data Set active?'));
362 // does this set have multiple record?
363 $multiple = $this->addElement('checkbox', 'is_multiple',
364 ts('Does this Custom Field Set allow multiple records?'), NULL);
366 // $min_multiple = $this->add('text', 'min_multiple', ts('Minimum number of multiple records'), $attributes['min_multiple'] );
367 // $this->addRule('min_multiple', ts('is a numeric field') , 'numeric');
369 $max_multiple = $this->add('text', 'max_multiple', ts('Maximum number of multiple records'), $attributes['max_multiple']);
370 $this->addRule('max_multiple', ts('is a numeric field'), 'numeric');
372 //allow to edit settings if custom set is empty CRM-5258
373 $this->assign('isGroupEmpty', $this->_isGroupEmpty
);
374 if (!$this->_isGroupEmpty
) {
376 //$min_multiple->freeze();
377 $max_multiple->freeze();
380 $this->assign('showStyle', FALSE);
381 $this->assign('showMultiple', FALSE);
385 'name' => ts('Save'),
386 'spacing' => ' ',
391 'name' => ts('Cancel'),
394 if (!$this->_isGroupEmpty
&& !empty($this->_subtypes
)) {
395 $buttons[0]['js'] = array('onclick' => "return warnDataLoss()");
397 $this->addButtons($buttons);
399 // views are implemented as frozen form
400 if ($this->_action
& CRM_Core_Action
::VIEW
) {
402 $this->addElement('button', 'done', ts('Done'), array('onclick' => "location.href='civicrm/admin/custom/group?reset=1&action=browse'"));
407 * Set default values for the form. Note that in edit/view mode
408 * the default values are retrieved from the database
412 * @return array array of default values
415 function setDefaultValues() {
416 $defaults = &$this->_defaults
;
417 $this->assign('showMaxMultiple', TRUE);
418 if ($this->_action
== CRM_Core_Action
::ADD
) {
419 $defaults['weight'] = CRM_Utils_Weight
::getDefaultWeight('CRM_Core_DAO_CustomGroup');
421 $defaults['is_multiple'] = $defaults['min_multiple'] = 0;
422 $defaults['is_active'] = $defaults['collapse_display'] = 1;
423 $defaults['style'] = 'Inline';
425 elseif (empty($defaults['max_multiple']) && !$this->_isGroupEmpty
) {
426 $this->assign('showMaxMultiple', FALSE);
429 if (($this->_action
& CRM_Core_Action
::UPDATE
) && !empty($defaults['is_multiple'])) {
430 $defaults['collapse_display'] = 0;
433 if (isset($defaults['extends'])) {
434 $extends = $defaults['extends'];
435 unset($defaults['extends']);
437 $defaults['extends'][0] = $extends;
439 if (!empty($this->_subtypes
)) {
440 $defaults['extends'][1] = $this->_subtypes
;
443 $defaults['extends'][1] = array(0 => '');
446 if ($extends == 'Relationship' && !empty($this->_subtypes
)) {
447 $relationshipDefaults = array();
448 foreach ($defaults['extends'][1] as $donCare => $rel_type_id) {
449 $relationshipDefaults[] = $rel_type_id;
452 $defaults['extends'][1] = $relationshipDefaults;
467 public function postProcess() {
468 // get the submitted form values.
469 $params = $this->controller
->exportValues('Group');
470 $params['overrideFKConstraint'] = 0;
471 if ($this->_action
& CRM_Core_Action
::UPDATE
) {
472 $params['id'] = $this->_id
;
473 if ($this->_defaults
['extends'][0] != $params['extends'][0]) {
474 $params['overrideFKConstraint'] = 1;
477 if (!empty($this->_subtypes
)) {
478 $subtypesToBeRemoved = array_diff($this->_subtypes
, array_intersect($this->_subtypes
, $params['extends'][1]));
479 CRM_Contact_BAO_ContactType
::deleteCustomRowsOfSubtype($this->_id
, $subtypesToBeRemoved);
482 elseif ($this->_action
& CRM_Core_Action
::ADD
) {
483 //new custom set , so lets set the created_id
484 $session = CRM_Core_Session
::singleton();
485 $params['created_id'] = $session->get('userID');
486 $params['created_date'] = date('YmdHis');
489 $group = CRM_Core_BAO_CustomGroup
::create($params);
492 CRM_Core_BAO_Cache
::deleteGroup('contact fields');
494 if ($this->_action
& CRM_Core_Action
::UPDATE
) {
495 CRM_Core_Session
::setStatus(ts('Your custom field set \'%1 \' has been saved.', array(1 => $group->title
)), ts('Saved'), 'success');
498 // Jump directly to adding a field if popups are disabled
499 $action = CRM_Core_Resources
::singleton()->ajaxPopupsEnabled ?
'' : '/add';
500 $url = CRM_Utils_System
::url("civicrm/admin/custom/group/field$action", 'reset=1&new=1&gid=' . $group->id
. '&action=' . ($action ?
'add' : 'browse'));
501 CRM_Core_Session
::setStatus(ts("Your custom field set '%1' has been added. You can add custom fields now.",
502 array(1 => $group->title
)
503 ), ts('Saved'), 'success');
504 $session = CRM_Core_Session
::singleton();
505 $session->replaceUserContext($url);
508 // prompt Drupal Views users to update $db_prefix in settings.php, if necessary
510 $config = CRM_Core_Config
::singleton();
511 if (is_array($db_prefix) && $config->userSystem
->is_drupal
&& module_exists('views')) {
512 // get table_name for each custom group
514 $sql = "SELECT table_name FROM civicrm_custom_group WHERE is_active = 1";
515 $result = CRM_Core_DAO
::executeQuery($sql);
516 while ($result->fetch()) {
517 $tables[$result->table_name
] = $result->table_name
;
520 // find out which tables are missing from the $db_prefix array
521 $missingTableNames = array_diff_key($tables, $db_prefix);
523 if (!empty($missingTableNames)) {
524 CRM_Core_Session
::setStatus(ts("To ensure that all of your custom data groups are available to Views, you may need to add the following key(s) to the db_prefix array in your settings.php file: '%1'.",
525 array(1 => implode(', ', $missingTableNames))
526 ), ts('Note'), 'info');
532 * Return a formatted list of relationship name.
534 * @param array $list array of relationship name.
536 * @return array of relationship name.
538 static function getFormattedList(&$list) {
541 foreach ($list as $listItemKey => $itemValue) {
542 // Extract the relationship ID.
543 $key = substr($listItemKey, 0, strpos($listItemKey, '_'));
544 if (isset($list["{$key}_b_a"])) {
545 $relName["$key"] = $list["{$key}_a_b"];
546 // Are the two labels different?
547 if ($list["{$key}_a_b"] != $list["{$key}_b_a"]) {
548 $relName["$key"] = $list["{$key}_a_b"] . ' / ' . $list["{$key}_b_a"];
550 unset($list["{$key}_b_a"]);
551 unset($list["{$key}_a_b"]);
554 // If no '_b_a' label exists save the '_a_b' one and unset it from the list
555 $relName["{$key}"] = $list["{$key}_a_b"];
556 unset($list["{$key}_a_b"]);