Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dev/core#866, dev/core#1318 Fix failure to import checkboxes for activities #19111

Merged
merged 1 commit into from
Jan 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 0 additions & 29 deletions CRM/Activity/Import/Parser/Activity.php
Original file line number Diff line number Diff line change
Expand Up @@ -278,11 +278,6 @@ public function import($onDuplicate, &$values) {
return CRM_Import_Parser::ERROR;
}

$params['custom'] = CRM_Core_BAO_CustomField::postProcess($params,
NULL,
'Activity'
);

if ($this->_contactIdIndex < 0) {

// Retrieve contact id using contact dedupe rule.
Expand Down Expand Up @@ -393,36 +388,12 @@ protected function deprecated_activity_formatted_param(&$params, &$values, $crea
$fields = CRM_Activity_DAO_Activity::fields();
_civicrm_api3_store_values($fields, $params, $values);

require_once 'CRM/Core/OptionGroup.php';
$customFields = CRM_Core_BAO_CustomField::getFields('Activity');

foreach ($params as $key => $value) {
// ignore empty values or empty arrays etc
if (CRM_Utils_System::isNull($value)) {
continue;
}

//Handling Custom Data
if ($customFieldID = CRM_Core_BAO_CustomField::getKeyID($key)) {
$values[$key] = $value;
$type = $customFields[$customFieldID]['html_type'];
if (CRM_Core_BAO_CustomField::isSerialized($customFields[$customFieldID])) {
$values[$key] = CRM_Import_Parser::unserializeCustomValue($customFieldID, $value, $type);
}
elseif ($type == 'Select' || $type == 'Radio') {
$customOption = CRM_Core_BAO_CustomOption::getCustomOption($customFieldID, TRUE);
foreach ($customOption as $customFldID => $customValue) {
$val = $customValue['value'] ?? NULL;
$label = $customValue['label'] ?? NULL;
$label = strtolower($label);
$value = strtolower(trim($value));
if (($value == $label) || ($value == strtolower($val))) {
$values[$key] = $val;
}
}
}
}

if ($key == 'target_contact_id') {
if (!CRM_Utils_Rule::integer($value)) {
return civicrm_api3_create_error("contact_id not valid: $value");
Expand Down
4 changes: 2 additions & 2 deletions CRM/Core/Session.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ class CRM_Core_Session {
* We only need one instance of this object. So we use the singleton
* pattern and cache the instance in this variable
*
* @var object
* @var \CRM_Core_Session
*/
static private $_singleton = NULL;
static private $_singleton;

/**
* Constructor.
Expand Down
3 changes: 3 additions & 0 deletions api/v3/CustomField.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ function civicrm_api3_custom_field_create($params) {
* Flush static caches in functions that might have stored available custom fields.
*/
function _civicrm_api3_custom_field_flush_static_caches() {
if (isset(\Civi::$statics['CRM_Core_BAO_OptionGroup']['titles_by_name'])) {
unset(\Civi::$statics['CRM_Core_BAO_OptionGroup']['titles_by_name']);
}
civicrm_api('CustomField', 'getfields', ['version' => 3, 'cache_clear' => 1]);
CRM_Core_BAO_UFField::getAvailableFieldsFlat(TRUE);
}
Expand Down
108 changes: 108 additions & 0 deletions tests/phpunit/CRM/Activity/Import/Parser/ActivityTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<?php

/**
* File for the TestActivityType class
*
* (PHP 5)
*
* @package CiviCRM
*
* This file is part of CiviCRM
*
* CiviCRM is free software; you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation; either version 3 of
* the License, or (at your option) any later version.
*
* CiviCRM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*/

/**
* Test CRM/Member/BAO Membership Log add , delete functions
*
* @package CiviCRM
* @group headless
*/
class CRM_Activity_Import_Parser_ActivityTest extends CiviUnitTestCase {
use CRMTraits_Custom_CustomDataTrait;

/**
* Prepare for tests.
*/
public function setUp():void {
parent::setUp();
$this->createLoggedInUser();
}

/**
* Clean up after test.
*
* @throws \CRM_Core_Exception
*/
public function tearDown():void {
$this->quickCleanup(['civicrm_contact', 'civicrm_activity'], TRUE);
parent::tearDown();
}

/**
* Test Import.
*
* So far this is just testing the class constructor & preparing for more
* tests.
*
* @throws \API_Exception
* @throws \CRM_Core_Exception
* @throws \CiviCRM_API3_Exception
*/
public function testImport(): void {
$this->createCustomGroupWithFieldOfType(['extends' => 'Activity'], 'checkbox');
$values = [
'activity_detail' => 'fascinating',
'activity_type_id' => 1,
'activity_date_time' => '2010-01-06',
'target_contact_id' => $this->individualCreate(),
'subject' => 'riveting stuff',
$this->getCustomFieldName('checkbox') => 'L',
];
$this->importValues($values);
$this->callAPISuccessGetSingle('Activity', [$this->getCustomFieldName('checkbox') => 'L']);
}

/**
* Create an import object.
*
* @param array $fields
*
* @return \CRM_Activity_Import_Parser_Activity
*/
protected function createImportObject(array $fields): \CRM_Activity_Import_Parser_Activity {
$fieldMapper = [];
foreach ($fields as $index => $field) {
$fieldMapper[] = $field;
}
$importer = new CRM_Activity_Import_Parser_Activity($fieldMapper);
$importer->init();
return $importer;
}

/**
* Run the importer.
*
* @param array $values
* @param int $expectedOutcome
*/
protected function importValues(array $values, $expectedOutcome = 1): void {
$importer = $this->createImportObject(array_keys($values));
$params = array_values($values);
CRM_Core_Session::singleton()->set('dateTypes', 1);
$this->assertEquals($expectedOutcome, $importer->import(NULL, $params));
}

}
40 changes: 39 additions & 1 deletion tests/phpunit/CRM/Core/BAO/CustomFieldTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,7 @@ public function testGetFieldsForImport() {
'extends_entity_column_id' => NULL,
'is_view' => '0',
'is_multiple' => '0',
'option_group_id' => $this->callAPISuccessGetValue('CustomField', ['id' => $this->getCustomFieldID('select_string'), 'return' => 'option_group_id']),
'option_group_id' => $this->getOptionGroupID('select_string'),
'date_format' => NULL,
'time_format' => NULL,
'is_required' => 0,
Expand Down Expand Up @@ -877,6 +877,44 @@ public function testGetFieldsForImport() {
'callback' => 'CRM_Core_SelectValues::boolean',
],
],
$this->getCustomFieldName('checkbox') => [
'name' => $this->getCustomFieldName('checkbox'),
'custom_field_id' => $this->getCustomFieldID('checkbox'),
'id' => $this->getCustomFieldID('checkbox'),
'groupTitle' => 'Custom Group',
'default_value' => NULL,
'option_group_id' => $this->getOptionGroupID('checkbox'),
'custom_group_id' => $customGroupID,
'extends' => 'Contact',
'extends_entity_column_value' => NULL,
'extends_entity_column_id' => NULL,
'is_view' => '0',
'is_multiple' => '0',
'date_format' => NULL,
'time_format' => NULL,
'is_required' => 0,
'table_name' => 'civicrm_value_custom_group_' . $customGroupID,
'column_name' => $this->getCustomFieldColumnName('checkbox'),
'where' => 'civicrm_value_custom_group_' . $customGroupID . '.' . $this->getCustomFieldColumnName('checkbox'),
'extends_table' => 'civicrm_contact',
'search_table' => 'contact_a',
'import' => 1,
'label' => 'Pick Shade',
'headerPattern' => '//',
'title' => 'Pick Shade',
'data_type' => 'String',
'type' => 2,
'html_type' => 'CheckBox',
'text_length' => NULL,
'options_per_line' => NULL,
'is_search_range' => '0',
'serialize' => '1',
'pseudoconstant' => [
'optionGroupName' => $this->getOptionGroupName('checkbox'),
'optionEditPath' => 'civicrm/admin/options/' . $this->getOptionGroupName('checkbox'),

],
],
];
$this->assertEquals($expected, CRM_Core_BAO_CustomField::getFieldsForImport());
}
Expand Down
70 changes: 60 additions & 10 deletions tests/phpunit/CRMTraits/Custom/CustomDataTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,9 @@ protected function getCustomFieldColumnName($key) {
*
* @throws \API_Exception
* @throws \CRM_Core_Exception
* @throws \Civi\API\Exception\UnauthorizedException
*/
public function createCustomGroupWithFieldOfType($groupParams = [], $customFieldType = 'text', $identifier = NULL, $fieldParams = []) {
$supported = ['text', 'select', 'date', 'int', 'contact_reference', 'radio', 'multi_country'];
public function createCustomGroupWithFieldOfType($groupParams = [], $customFieldType = 'text', $identifier = NULL, $fieldParams = []): void {
$supported = ['text', 'select', 'date', 'checkbox', 'int', 'contact_reference', 'radio', 'multi_country'];
if (!in_array($customFieldType, $supported, TRUE)) {
throw new CRM_Core_Exception('we have not yet extracted other custom field types from createCustomFieldsOfAllTypes, Use consistent syntax when you do');
}
Expand All @@ -113,6 +112,10 @@ public function createCustomGroupWithFieldOfType($groupParams = [], $customField
$reference = $this->createSelectCustomField($fieldParams)['id'];
return;

case 'checkbox':
$reference = $this->createStringCheckboxCustomField($fieldParams)['id'];
return;

case 'int':
$reference = $this->createIntCustomField($fieldParams)['id'];
return;
Expand Down Expand Up @@ -154,6 +157,7 @@ public function createCustomFieldsOfAllTypes() {
$ids['state'] = (int) $this->createStateCustomField(['custom_group_id' => $customGroupID])['id'];
$ids['multi_state'] = (int) $this->createMultiStateCustomField(['custom_group_id' => $customGroupID])['id'];
$ids['boolean'] = (int) $this->createBooleanCustomField(['custom_group_id' => $customGroupID])['id'];
$ids['checkbox'] = (int) $this->createStringCheckboxCustomField(['custom_group_id' => $customGroupID])['id'];
return $ids;
}

Expand Down Expand Up @@ -206,6 +210,34 @@ protected function getCustomFieldID($key) {
return $this->ids['CustomField'][$key];
}

/**
* Get the option group id of the created field.
*
* @param string $key
*
* @return string
*/
protected function getOptionGroupID(string $key): string {
return (string) $this->callAPISuccessGetValue('CustomField', [
'id' => $this->getCustomFieldID($key),
'return' => 'option_group_id',
]);
}

/**
* Get the option group id of the created field.
*
* @param string $key
*
* @return string
*/
protected function getOptionGroupName(string $key): string {
return (string) $this->callAPISuccessGetValue('CustomField', [
'id' => $this->getCustomFieldID($key),
'return' => 'option_group_id.name',
]);
}

/**
* Create a custom text fields.
*
Expand Down Expand Up @@ -374,6 +406,18 @@ protected function createDateCustomField($params): array {
return $this->callAPISuccess('custom_field', 'create', $params)['values'][0];
}

/**
* Create a custom field of type radio with integer values.
*
* @param array $params
*
* @return array
*/
protected function createStringCheckboxCustomField(array $params): array {
$params = array_merge($this->getFieldsValuesByType('String', 'CheckBox'), $params);
return $this->callAPISuccess('custom_field', 'create', $params)['values'][0];
}

/**
* Create a custom field of type radio with integer values.
*
Expand Down Expand Up @@ -480,30 +524,36 @@ protected function getAvailableFieldCombinations() {
],
],
'CheckBox' => [
'label' => 'Pick Color',
'label' => 'Pick Shade',
'html_type' => 'CheckBox',
'data_type' => 'String',
'text_length' => '',
'default_value' => '',
'option_values' => [
[
'label' => 'Red',
'value' => 'R',
'label' => 'Lilac',
'value' => 'L',
'weight' => 1,
'is_active' => 1,
],
[
'label' => 'Yellow',
'value' => 'Y',
'label' => 'Purple',
'value' => 'P',
'weight' => 2,
'is_active' => 1,
],
[
'label' => 'Green',
'value' => 'G',
'label' => 'Mauve',
'value' => 'M',
'weight' => 3,
'is_active' => 1,
],
[
'label' => 'Violet',
'value' => 'V',
'weight' => 4,
'is_active' => 1,
],
],
],
'Multi-Select' => [
Expand Down