Skip to content

Commit

Permalink
Add upgrade-safe DAO::getSupportedFields method
Browse files Browse the repository at this point in the history
Switches api v3 and v4 to use that method so they are upgrade-safe by default.
  • Loading branch information
colemanw committed Jul 1, 2020
1 parent ec9ef5d commit 35a4d0b
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 7 deletions.
37 changes: 37 additions & 0 deletions CRM/Core/DAO.php
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,43 @@ public static function &fields() {
return $result;
}

/**
* Returns all usable fields, indexed by name.
*
* This function differs from fields() in that it indexes by name rather than unique_name.
*
* It excludes fields not added yet by pending upgrades.
* This avoids problems with trying to SELECT a field that exists in code but has not yet been added to the db.
*
* @param bool $checkPermissions
* Filter by field permissions.
* @return array
*/
public static function getSupportedFields($checkPermissions = FALSE) {
$fields = array_column((array) static::fields(), NULL, 'name');

// Exclude fields yet not added by pending upgrades
$dbVer = \CRM_Core_BAO_Domain::version();
if ($fields && version_compare($dbVer, \CRM_Utils_System::version()) < 0) {
$fields = array_filter($fields, function($field) use ($dbVer) {
$add = $field['add'] ?? '1.0.0';
if (substr_count($add, '.') < 2) {
$add .= '.alpha1';
}
return version_compare($dbVer, $add, '>=');
});
}

// Exclude fields the user does not have permission for
if ($checkPermissions) {
$fields = array_filter($fields, function($field) {
return empty($field['permission']) || CRM_Core_Permission::check($field['permission']);
});
}

return $fields;
}

/**
* Get/set an associative array of table columns
*
Expand Down
2 changes: 1 addition & 1 deletion Civi/Api4/Service/Spec/SpecGatherer.php
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ private function getCustomGroupFields($customGroup, RequestSpec $specification)
private function getDAOFields($entityName) {
$bao = CoreUtil::getBAOFromApiName($entityName);

return $bao::fields();
return $bao::getSupportedFields();
}

}
16 changes: 10 additions & 6 deletions api/v3/utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ function _civicrm_api3_load_DAO($entity) {
* return the DAO name to manipulate this function
* eg. "civicrm_api3_contact_create" or "Contact" will return "CRM_Contact_BAO_Contact"
*
* @return mixed|string
* @return CRM_Core_DAO|string
*/
function _civicrm_api3_get_DAO($name) {
if (strpos($name, 'civicrm_api3') !== FALSE) {
Expand Down Expand Up @@ -1878,15 +1878,19 @@ function _civicrm_api_get_fields($entity, $unique = FALSE, &$params = []) {
if (empty($dao)) {
return [];
}
$d = new $dao();
$fields = $d->fields();
$fields = $dao::fields();
$supportedFields = $dao::getSupportedFields();

foreach ($fields as $name => &$field) {
foreach ($fields as $name => $field) {
// Denote as core field
$field['is_core_field'] = TRUE;
$fields[$name]['is_core_field'] = TRUE;
// Set html attributes for text fields
if (isset($field['html'])) {
$field['html'] += (array) $d::makeAttribute($field);
$fields[$name]['html'] += (array) $dao::makeAttribute($field);
}
// Delete field if not supported by current db schema (prevents errors when there are pending db updates)
if (!isset($supportedFields[$field['name']])) {
unset($fields[$name]);
}
}

Expand Down

0 comments on commit 35a4d0b

Please sign in to comment.