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

[php8-compact][REF] Fix failing custom group test on php8 by better h… #20616

Merged
merged 3 commits into from
Jun 18, 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
99 changes: 73 additions & 26 deletions CRM/Core/BAO/CustomGroup.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,37 +45,29 @@ public static function create(&$params) {
$group->title = $params['title'];
}

$extends = CRM_Utils_Array::value('extends', $params, []);
$extendsEntity = $extends[0] ?? NULL;

$participantEntities = [
'ParticipantRole',
'ParticipantEventName',
'ParticipantEventType',
];

if (in_array($extendsEntity, $participantEntities)) {
$group->extends = 'Participant';
}
else {
$group->extends = $extendsEntity;
}

$group->extends_entity_column_id = 'null';
if (in_array($extendsEntity, $participantEntities)
) {
$group->extends_entity_column_id = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionValue', $extendsEntity, 'value', 'name');
}

// this is format when form get submit.
$extendsChildType = $extends[1] ?? NULL;
$extendsChildType = NULL;
// lets allow user to pass direct child type value, CRM-6893
if (!empty($params['extends_entity_column_value'])) {
$extendsChildType = $params['extends_entity_column_value'];
}
if (!CRM_Utils_System::isNull($extendsChildType)) {
$b = self::getMungedEntity($params['extends'], $params['extends_entity_column_id'] ?? NULL);
$registeredSubTypes = self::getSubTypes()[$b];
if (is_array($extendsChildType)) {
foreach ($extendsChildType as $childType) {
if (!array_key_exists($childType, $registeredSubTypes) && !in_array($childType, $registeredSubTypes, TRUE)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a bug in this validation. If you try to create a ParticipantRole group with a type through the form it fails because registeredTypes above has a key 'ParticipantRole' but $params['extends'] is 'Participant'

I tested this & it seems to work

--- a/CRM/Core/BAO/CustomGroup.php
+++ b/CRM/Core/BAO/CustomGroup.php
@@ -51,7 +51,9 @@ class CRM_Core_BAO_CustomGroup extends CRM_Core_DAO_CustomGroup {
       $extendsChildType = $params['extends_entity_column_value'];
     }
     if (!CRM_Utils_System::isNull($extendsChildType)) {
-      $registeredSubTypes = self::getSubTypes()[$params['extends']];
+
+      $b = self::getMungedEntity($params['extends'], $params['extends_entity_column_id'] ?? NULL);
+      $registeredSubTypes = self::getSubTypes()[$b];
       if (is_array($extendsChildType)) {
         foreach ($extendsChildType as $childType) {
           if (!array_key_exists($childType, $registeredSubTypes) && !in_array($childType, $registeredSubTypes, TRUE)) {
@@ -224,6 +226,24 @@ class CRM_Core_BAO_CustomGroup extends CRM_Core_DAO_CustomGroup {
     return CRM_Core_DAO::commonRetrieve('CRM_Core_DAO_CustomGroup', $params, $defaults);
   }
 
+  /**
+   * Get the munged entity.
+   *
+   * This is the entity eg. Relationship or the name of the sub entity
+   * e.g ParticipantRole.
+   *
+   * @param string $extends
+   * @param int|null $extendsEntityColumn
+   *
+   * @return string
+   */
+  protected static function getMungedEntity($extends, $extendsEntityColumn = NULL) {
+    if (!$extendsEntityColumn) {
+      return $extends;
+    }
+    return CRM_Core_OptionGroup::values('custom_data_type', FALSE, FALSE, FALSE, NULL, 'name')[$extendsEntityColumn];
+  }

throw new CRM_Core_Exception('Supplied Sub type is not valid for the specified entitiy');
}
}
}
else {
if (!array_key_exists($extendsChildType, $registeredSubTypes) && !in_array($extendsChildType, $registeredSubTypes, TRUE)) {
throw new CRM_Core_Exception('Supplied Sub type is not valid for the specified entitiy');
}
$extendsChildType = [$extendsChildType];
}
$extendsChildType = implode(CRM_Core_DAO::VALUE_SEPARATOR, $extendsChildType);
if (CRM_Utils_Array::value(0, $extends) == 'Relationship') {
if ($params['extends'] == 'Relationship') {
$extendsChildType = str_replace(['_a_b', '_b_a'], [
'',
'',
Expand Down Expand Up @@ -107,6 +99,8 @@ public static function create(&$params) {
'is_active',
'is_multiple',
'icon',
'extends_entity_column_id',
'extends',
];
$current_db_version = CRM_Core_BAO_Domain::version();
$is_public_version = version_compare($current_db_version, '4.7.19', '>=');
Expand Down Expand Up @@ -200,7 +194,7 @@ public static function create(&$params) {
$params['id'],
'table_name'
);
CRM_Core_BAO_SchemaHandler::changeFKConstraint($table, self::mapTableName($extendsEntity));
CRM_Core_BAO_SchemaHandler::changeFKConstraint($table, self::mapTableName($params['extends']));
}
$transaction->commit();

Expand Down Expand Up @@ -2200,4 +2194,57 @@ private static function buildGroupTree($entityType, $toReturn, $subTypes, $query
return [$multipleFieldGroups, $groupTree];
}

public static function getSubTypes(): array {
$sel2 = [];
$activityType = CRM_Core_PseudoConstant::activityType(FALSE, TRUE, FALSE, 'label', TRUE);

$eventType = CRM_Core_OptionGroup::values('event_type');
$grantType = CRM_Core_OptionGroup::values('grant_type');
$campaignTypes = CRM_Campaign_PseudoConstant::campaignType();
$membershipType = CRM_Member_BAO_MembershipType::getMembershipTypes(FALSE);
$participantRole = CRM_Core_OptionGroup::values('participant_role');

asort($activityType);
asort($eventType);
asort($grantType);
asort($membershipType);
asort($participantRole);

$sel2['Event'] = $eventType;
$sel2['Grant'] = $grantType;
$sel2['Activity'] = $activityType;
$sel2['Campaign'] = $campaignTypes;
$sel2['Membership'] = $membershipType;
$sel2['ParticipantRole'] = $participantRole;
$sel2['ParticipantEventName'] = CRM_Event_PseudoConstant::event(NULL, FALSE, "( is_template IS NULL OR is_template != 1 )");
$sel2['ParticipantEventType'] = $eventType;
$sel2['Contribution'] = CRM_Contribute_PseudoConstant::financialType();
$sel2['Relationship'] = CRM_Custom_Form_Group::getRelationshipTypes();

$sel2['Individual'] = CRM_Contact_BAO_ContactType::subTypePairs('Individual', FALSE, NULL);
$sel2['Household'] = CRM_Contact_BAO_ContactType::subTypePairs('Household', FALSE, NULL);
$sel2['Organization'] = CRM_Contact_BAO_ContactType::subTypePairs('Organization', FALSE, NULL);

CRM_Core_BAO_CustomGroup::getExtendedObjectTypes($sel2);
return $sel2;
}

/**
* Get the munged entity.
*
* This is the entity eg. Relationship or the name of the sub entity
* e.g ParticipantRole.
*
* @param string $extends
* @param int|null $extendsEntityColumn
*
* @return string
*/
protected static function getMungedEntity($extends, $extendsEntityColumn = NULL) {
if (!$extendsEntityColumn || $extendsEntityColumn === 'null') {
return $extends;
}
return CRM_Core_OptionGroup::values('custom_data_type', FALSE, FALSE, FALSE, NULL, 'name')[$extendsEntityColumn];
}

}
41 changes: 6 additions & 35 deletions CRM/Custom/Form/Group.php
Original file line number Diff line number Diff line change
Expand Up @@ -176,38 +176,8 @@ public function buildQuickForm() {
$this->assign('contactTypes', json_encode($contactTypes));

$sel1 = ["" => ts("- select -")] + CRM_Core_SelectValues::customGroupExtends();
$sel2 = [];
$activityType = CRM_Core_PseudoConstant::activityType(FALSE, TRUE, FALSE, 'label', TRUE);

$eventType = CRM_Core_OptionGroup::values('event_type');
$grantType = CRM_Core_OptionGroup::values('grant_type');
$campaignTypes = CRM_Campaign_PseudoConstant::campaignType();
$membershipType = CRM_Member_BAO_MembershipType::getMembershipTypes(FALSE);
$participantRole = CRM_Core_OptionGroup::values('participant_role');

ksort($sel1);
asort($activityType);
asort($eventType);
asort($grantType);
asort($membershipType);
asort($participantRole);

$sel2['Event'] = $eventType;
$sel2['Grant'] = $grantType;
$sel2['Activity'] = $activityType;
$sel2['Campaign'] = $campaignTypes;
$sel2['Membership'] = $membershipType;
$sel2['ParticipantRole'] = $participantRole;
$sel2['ParticipantEventName'] = CRM_Event_PseudoConstant::event(NULL, FALSE, "( is_template IS NULL OR is_template != 1 )");
$sel2['ParticipantEventType'] = $eventType;
$sel2['Contribution'] = CRM_Contribute_PseudoConstant::financialType();
$sel2['Relationship'] = self::getRelationshipTypes();

$sel2['Individual'] = CRM_Contact_BAO_ContactType::subTypePairs('Individual', FALSE, NULL);
$sel2['Household'] = CRM_Contact_BAO_ContactType::subTypePairs('Household', FALSE, NULL);
$sel2['Organization'] = CRM_Contact_BAO_ContactType::subTypePairs('Organization', FALSE, NULL);

CRM_Core_BAO_CustomGroup::getExtendedObjectTypes($sel2);
$sel2 = CRM_Core_BAO_CustomGroup::getSubTypes();

foreach ($sel2 as $main => $sub) {
if (!empty($sel2[$main])) {
Expand Down Expand Up @@ -443,22 +413,23 @@ public function postProcess() {
$params['created_date'] = date('YmdHis');
}

$group = CRM_Core_BAO_CustomGroup::create($params);
$result = civicrm_api3('CustomGroup', 'create', $params);
$group = $result['values'][$result['id']];

// reset the cache
Civi::cache('fields')->flush();
// reset ACL and system caches.
CRM_Core_BAO_Cache::resetCaches();

if ($this->_action & CRM_Core_Action::UPDATE) {
CRM_Core_Session::setStatus(ts('Your custom field set \'%1 \' has been saved.', [1 => $group->title]), ts('Saved'), 'success');
CRM_Core_Session::setStatus(ts('Your custom field set \'%1 \' has been saved.', [1 => $group['title']]), ts('Saved'), 'success');
}
else {
// Jump directly to adding a field if popups are disabled
$action = CRM_Core_Resources::singleton()->ajaxPopupsEnabled ? '' : '/add';
$url = CRM_Utils_System::url("civicrm/admin/custom/group/field$action", 'reset=1&new=1&gid=' . $group->id . '&action=' . ($action ? 'add' : 'browse'));
$url = CRM_Utils_System::url("civicrm/admin/custom/group/field$action", 'reset=1&new=1&gid=' . $group['id'] . '&action=' . ($action ? 'add' : 'browse'));
CRM_Core_Session::setStatus(ts("Your custom field set '%1' has been added. You can add custom fields now.",
[1 => $group->title]
[1 => $group['title']]
), ts('Saved'), 'success');
$session = CRM_Core_Session::singleton();
$session->replaceUserContext($url);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,9 @@ class CustomGroupPreCreationSubscriber extends Generic\PreCreationSubscriber {
* @param \Civi\Api4\Generic\DAOCreateAction $request
*/
protected function modify(DAOCreateAction $request) {
$extends = $request->getValue('extends');
$title = $request->getValue('title');
$name = $request->getValue('name');

if (is_string($extends)) {
$request->addValue('extends', [$extends]);
}

if (NULL === $title && $name) {
$request->addValue('title', $name);
}
Expand Down
23 changes: 23 additions & 0 deletions api/v3/CustomGroup.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,29 @@ function civicrm_api3_custom_group_create($params) {

return civicrm_api3_create_error("First item in params['extends'] must be a class name (e.g. 'Contact').");
}
if (!isset($params['extends_entity_column_value']) && isset($params['extends'][1])) {
$extendsEntity = $params['extends'][0] ?? NULL;
$participantEntities = [
'ParticipantRole',
'ParticipantEventName',
'ParticipantEventType',
];
$params['extends_entity_column_id'] = 'null';
if (in_array($extendsEntity, $participantEntities)
) {
$params['extends_entity_column_id'] = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionValue', $extendsEntity, 'value', 'name');
}
$params['extends_entity_column_value'] = $params['extends'][1];
if (in_array($extendsEntity, $participantEntities)) {
$params['extends'] = 'Participant';
}
else {
$params['extends'] = $extendsEntity;
}
}
elseif (isset($params['extends']) && (!isset($params['extends'][1]) || empty($params['extends'][1]))) {
$params['extends'] = $params['extends'][0];
}
if (isset($params['extends_entity_column_value']) && !is_array($params['extends_entity_column_value'])) {
// BAO fails if this is a string, but API getFields says this must be a string, so we'll do a double backflip
$params['extends_entity_column_value'] = CRM_Utils_Array::explodePadded($params['extends_entity_column_value']);
Expand Down
2 changes: 1 addition & 1 deletion tests/phpunit/CRMTraits/Custom/CustomDataTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public function createCustomGroupWithFieldsOfAllTypes($groupParams = []) {
public function createCustomGroup($params = []) {
$params = array_merge([
'title' => 'Custom Group',
'extends' => [$this->entity ?? 'Contact'],
'extends' => $this->entity ?? 'Contact',
'weight' => 5,
'style' => 'Inline',
'max_multiple' => 0,
Expand Down
31 changes: 29 additions & 2 deletions tests/phpunit/api/v3/CustomGroupTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,7 @@ public function testCustomGroupExtendsMultipleCreate() {
'is_active' => 1,
];

$result = $this->callAPIFailure('custom_group', 'create', $params,
'implode(): Invalid arguments passed');
$result = $this->callAPIFailure('custom_group', 'create', $params, 'Supplied Sub type is not valid for the specified entitiy');
}

/**
Expand Down Expand Up @@ -369,4 +368,32 @@ public function testUpdateCustomGroup() {
$this->customGroupDelete($customGroupId);
}

/**
* Test that as per the form that if the extends column is passed as
* - ['ParticipantEventType', [4]] Where 4 = Meeting Event Type that we can create a custom group correctly
*/
public function testParticipantEntityCustomGroup() {
$customGroup = $this->callAPISuccess($this->_entity, 'create', array_merge($this->_params, ['extends' => ['ParticipantEventType', [4]]]));
$result = array_shift($customGroup['values']);
$this->assertEquals(3, $result['extends_entity_column_id']);
$this->assertEquals('Participant', $result['extends']);
$this->customGroupDelete($result['id']);
}

/**
* Test that without any fields we can change the entity type of the custom group and fields are correctly updated
*/
public function testChangeEntityCustomGroup() {
$customGroup = $this->callAPISuccess($this->_entity, 'create', array_merge($this->_params, ['extends' => ['ParticipantEventType', [4]]]));
$result = array_shift($customGroup['values']);
$this->assertEquals(3, $result['extends_entity_column_id']);
$this->assertEquals('Participant', $result['extends']);
$customGroup = $this->callAPISuccess($this->_entity, 'create', ['id' => $customGroup['id'], 'extends' => ['Individual', []]]);
$result = array_shift($customGroup['values']);
$this->assertTrue(empty($result['extends_entity_column_id']));
$this->assertTrue(empty($result['extends_entity_column_value']));
$this->assertEquals('Individual', $result['extends']);
$this->customGroupDelete($result['id']);
}

}