Before: APIv4 would guess which fields to use for grouping when sorting by weight.
this caused a bug when sorting custom fields which also had an option_group_id, which
was incorrectly guessed to be used for grouping.
After: New `@groupWeightsBy` annotation removes the guesswork.
* @see https://docs.civicrm.org/user/en/latest/organising-your-data/creating-custom-fields/
* @searchable secondary
* @orderBy weight
+ * @groupWeightsBy custom_group_id
* @since 5.19
* @package Civi\Api4
*/
'data_type' => 'Array',
'description' => 'When joining entities in the UI, which fields should be presented by default in the ON clause',
],
+ [
+ 'name' => 'group_weights_by',
+ 'data_type' => 'Array',
+ 'description' => 'For sortable entities, what field groupings are used to order by weight',
+ ],
];
}))->setCheckPermissions($checkPermissions);
}
/** @var \CRM_Core_DAO|string $daoName */
$daoName = CoreUtil::getInfoItem($this->getEntityName(), 'dao');
$weightField = CoreUtil::getInfoItem($this->getEntityName(), 'order_by');
+ $grouping = CoreUtil::getInfoItem($this->getEntityName(), 'group_weights_by');
$idField = CoreUtil::getIdFieldName($this->getEntityName());
// If updating an existing record without changing weight, do nothing
if (!isset($record[$weightField]) && !empty($record[$idField])) {
$newWeight = $record[$weightField] ?? NULL;
$oldWeight = empty($record[$idField]) ? NULL : \CRM_Core_DAO::getFieldValue($daoName, $record[$idField], $weightField);
- // FIXME: Need a more metadata-ish approach. For now here's a hardcoded list of the fields sortable entities use for grouping.
- $guesses = ['option_group_id', 'price_set_id', 'price_field_id', 'premiums_id', 'uf_group_id', 'custom_group_id', 'parent_id', 'domain_id'];
$filters = [];
- foreach (array_intersect($guesses, array_keys($daoFields)) as $filter) {
+ foreach ($grouping ?? [] as $filter) {
$filters[$filter] = $record[$filter] ?? (empty($record[$idField]) ? NULL : \CRM_Core_DAO::getFieldValue($daoName, $record[$idField], $filter));
}
// Supply default weight for new record
*
* @searchable secondary
* @orderBy weight
+ * @groupWeightsBy domain_id
* @since 5.27
* @package Civi\Api4
*/
*
* @searchable none
* @orderBy weight
+ * @groupWeightsBy domain_id,parent_id
* @since 5.19
* @package Civi\Api4
*/
* @see \Civi\Api4\OptionGroup
* @searchable secondary
* @orderBy weight
+ * @groupWeightsBy option_group_id
* @since 5.19
* @package Civi\Api4
*/
*
* @searchable secondary
* @orderBy weight
+ * @groupWeightsBy price_set_id
* @since 5.27
* @package Civi\Api4
*/
*
* @searchable secondary
* @orderBy weight
+ * @groupWeightsBy price_field_id
* @since 5.27
* @package Civi\Api4
*/
* @see \Civi\Api4\UFGroup
* @searchable none
* @orderBy weight
+ * @groupWeightsBy uf_group_id
* @since 5.19
* @package Civi\Api4
*/
elseif ($key == 'return') {
$info['return'] = explode('|', $words[0]);
}
- elseif ($key == 'options' || $key == 'ui_join_filters') {
+ elseif ($key == 'options' || $key == 'ui_join_filters' || $key == 'groupWeightsBy') {
$val = str_replace(', ', ',', implode(' ', $words));
$info[$key] = explode(',', $val);
}
->addValue('extends', 'Individual')
->execute()->first();
$sampleData = [
- ['label' => 'One'],
+ ['label' => 'One', 'html_type' => 'Select', 'option_values' => ['a' => 'A', 'b' => 'B']],
['label' => 'Two'],
- ['label' => 'Three'],
+ ['label' => 'Three', 'html_type' => 'Select', 'option_values' => ['c' => 'C', 'd' => 'D']],
['label' => 'Four'],
];
CustomField::save(FALSE)