// Text was translated with `%1` placeholders preserved so it could be cached
// Now we'll replace `%1` placeholders with the entityTitle, unless FALSE
$entityTitle = $this->entityTitle === TRUE ? CoreUtil::getInfoItem($this->getEntityName(), 'title') : $this->entityTitle;
- foreach ($links as &$link) {
+ foreach ($links as $index => &$link) {
// Swap placeholders with $entityTitle (TRUE means use default title)
if ($entityTitle !== FALSE && !empty($link['text'])) {
$link['text'] = str_replace('%1', $entityTitle, $link['text']);
if (isset($value)) {
$link['path'] = str_replace($token['token'], $value, $link['path']);
}
+ // If $values was supplied, treat all tokens as mandatory and remove links with null values
+ // This hides invalid links from SearchKit e.g. `civicrm/group/edit?id=null`
+ else {
+ unset($links[$index]);
+ break;
+ }
}
}
}
$this->assertCount(2, $count);
}
+ public function testDefaultDisplayLinks(): void {
+ $group1 = $this->createTestRecord('Group', ['title' => uniqid('a')])['id'];
+ $group2 = $this->createTestRecord('Group', ['title' => uniqid('b')])['id'];
+ $contact1 = $this->createTestRecord('Individual', ['last_name' => 'b', 'first_name' => 'b'])['id'];
+ $contact2 = $this->createTestRecord('Individual', ['last_name' => 'a', 'first_name' => 'a'])['id'];
+ // Add both contacts to group2
+ $this->saveTestRecords('GroupContact', [
+ 'records' => [
+ ['contact_id' => $contact1, 'group_id' => $group2],
+ ['contact_id' => $contact2, 'group_id' => $group2],
+ ],
+ ]);
+
+ $params = [
+ 'checkPermissions' => FALSE,
+ 'return' => 'page:1',
+ 'savedSearch' => [
+ 'api_entity' => 'Group',
+ 'api_params' => [
+ 'version' => 4,
+ 'select' => [
+ 'title',
+ 'Group_GroupContact_Contact_01.sort_name',
+ ],
+ 'join' => [
+ [
+ 'Contact AS Group_GroupContact_Contact_01',
+ 'LEFT',
+ 'GroupContact',
+ ['id', '=', 'Group_GroupContact_Contact_01.group_id'],
+ ['Group_GroupContact_Contact_01.status:name', '=', '"Added"'],
+ ],
+ ],
+ 'where' => [],
+ ],
+ ],
+ 'display' => NULL,
+ 'sort' => [
+ ['title', 'ASC'],
+ ['Group_GroupContact_Contact_01.sort_name', 'ASC'],
+ ],
+ 'filters' => ['id' => [$group1, $group2]],
+ ];
+
+ $result = civicrm_api4('SearchDisplay', 'run', $params);
+ $this->assertCount(1, $result[0]['columns'][0]['links']);
+ $this->assertNull($result[0]['columns'][1]['val']);
+ $this->assertArrayNotHasKey('links', $result[0]['columns'][1]);
+ $this->assertCount(1, $result[1]['columns'][0]['links']);
+ $this->assertCount(1, $result[1]['columns'][1]['links']);
+ $this->assertCount(1, $result[2]['columns'][0]['links']);
+ $this->assertCount(1, $result[2]['columns'][1]['links']);
+ // No contact links in 1st row since the group is empty
+ $this->assertNotContains('View Contact', array_column($result[0]['columns'][2]['links'], 'text'));
+ $this->assertNotContains('Delete Contact', array_column($result[0]['columns'][2]['links'], 'text'));
+ $this->assertContains('View Contact', array_column($result[1]['columns'][2]['links'], 'text'));
+ $this->assertContains('Delete Contact', array_column($result[1]['columns'][2]['links'], 'text'));
+ $this->assertContains('View Contact', array_column($result[2]['columns'][2]['links'], 'text'));
+ $this->assertContains('Delete Contact', array_column($result[2]['columns'][2]['links'], 'text'));
+ }
+
/**
* Test return values are augmented by tokens.
*/