return NULL;
}
+ /**
+ * Create or update a record from supplied params.
+ *
+ * If 'id' is supplied, an existing record will be updated
+ * Otherwise a new record will be created.
+ *
+ * @param array $record
+ * @return CRM_Core_DAO
+ * @throws CRM_Core_Exception
+ */
+ public static function writeRecord(array $record) {
+ $hook = empty($record['id']) ? 'create' : 'edit';
+ $className = CRM_Core_DAO_AllCoreTables::getCanonicalClassName(static::class);
+ if ($className === 'CRM_Core_DAO') {
+ throw new CRM_Core_Exception('Function writeRecord must be called on a subclass of CRM_Core_DAO');
+ }
+ $entityName = CRM_Core_DAO_AllCoreTables::getBriefName($className);
+
+ \CRM_Utils_Hook::pre($hook, $entityName, $record['id'] ?? NULL, $record);
+ $instance = new $className();
+ $instance->copyValues($record);
+ $instance->save();
+ \CRM_Utils_Hook::post($hook, $entityName, $instance->id, $instance);
+
+ return $instance;
+ }
+
+ /**
+ * Delete a record from supplied params.
+ *
+ * @param array $record
+ * 'id' is required.
+ * @return CRM_Core_DAO
+ * @throws CRM_Core_Exception
+ */
+ public static function deleteRecord(array $record) {
+ $className = CRM_Core_DAO_AllCoreTables::getCanonicalClassName(static::class);
+ if ($className === 'CRM_Core_DAO') {
+ throw new CRM_Core_Exception('Function deleteRecord must be called on a subclass of CRM_Core_DAO');
+ }
+ $entityName = CRM_Core_DAO_AllCoreTables::getBriefName($className);
+ if (empty($record['id'])) {
+ throw new CRM_Core_Exception("Cannot delete {$entityName} with no id.");
+ }
+
+ CRM_Utils_Hook::pre('delete', $entityName, $record['id'], $record);
+ $instance = new $className();
+ $instance->id = $record['id'];
+ if (!$instance->delete()) {
+ throw new CRM_Core_Exception("Could not delete {$entityName} id {$record['id']}");
+ }
+ CRM_Utils_Hook::post('delete', $entityName, $record['id'], $instance);
+
+ return $instance;
+ }
+
/**
* Check if there is a record with the same name in the db.
*
$baoName = $this->getBaoName();
if ($this->getCheckPermissions()) {
- foreach ($items as $item) {
- $this->checkContactPermissions($baoName, $item);
+ foreach (array_keys($items) as $key) {
+ $items[$key]['check_permissions'] = TRUE;
+ $this->checkContactPermissions($baoName, $items[$key]);
}
}
}
else {
foreach ($items as $item) {
- $bao = new $baoName();
- $bao->id = $item['id'];
- // delete it
- $action_result = $bao->delete();
- if ($action_result) {
- $ids[] = ['id' => $item['id']];
- }
- else {
- throw new \API_Exception("Could not delete {$this->getEntityName()} id {$item['id']}");
- }
+ $baoName::deleteRecord($item);
+ $ids[] = ['id' => $item['id']];
}
}
return $ids;
$createResult = $baoName::$method($item);
}
else {
- $createResult = $this->genericCreateMethod($item);
+ $createResult = $baoName::writeRecord($item);
}
if (!$createResult) {
return $result;
}
- /**
- * Fallback when a BAO does not contain create or add functions
- *
- * @param $params
- * @return mixed
- */
- private function genericCreateMethod($params) {
- $baoName = $this->getBaoName();
- $hook = empty($params['id']) ? 'create' : 'edit';
-
- \CRM_Utils_Hook::pre($hook, $this->getEntityName(), $params['id'] ?? NULL, $params);
- /** @var \CRM_Core_DAO $instance */
- $instance = new $baoName();
- $instance->copyValues($params);
- $instance->save();
- \CRM_Utils_Hook::post($hook, $this->getEntityName(), $instance->id, $instance);
-
- return $instance;
- }
-
/**
* @param array $params
* @param int $entityId
else {
// Fixme: decouple from v3
require_once 'api/v3/utils.php';
- _civicrm_api3_check_edit_permissions($baoName, ['check_permissions' => 1] + $item);
+ _civicrm_api3_check_edit_permissions($baoName, $item);
}
}
/**
* For BAO's which don't have a create() or add() functions, use this fallback implementation.
*
- * @fixme There's an intuitive sense that this behavior should be defined somehow in the BAO/DAO class
- * structure. In practice, that requires a fair amount of refactoring and/or kludgery.
- *
- * @param string $bao_name
+ * @param string|CRM_Core_DAO $bao_name
* @param array $params
*
* @throws API_Exception
* @return CRM_Core_DAO|NULL
* An instance of the BAO
*/
-function _civicrm_api3_basic_create_fallback($bao_name, &$params) {
- $dao_name = get_parent_class($bao_name);
- if ($dao_name === 'CRM_Core_DAO' || !$dao_name) {
- $dao_name = $bao_name;
- }
- $entityName = CRM_Core_DAO_AllCoreTables::getBriefName($dao_name);
- if (empty($entityName)) {
- throw new API_Exception("Class \"$bao_name\" does not map to an entity name", "unmapped_class_to_entity", [
- 'class_name' => $bao_name,
- ]);
- }
- $hook = empty($params['id']) ? 'create' : 'edit';
-
- CRM_Utils_Hook::pre($hook, $entityName, CRM_Utils_Array::value('id', $params), $params);
- $instance = new $dao_name();
- $instance->copyValues($params);
- $instance->save();
- CRM_Utils_Hook::post($hook, $entityName, $instance->id, $instance);
-
- return $instance;
+function _civicrm_api3_basic_create_fallback($bao_name, $params) {
+ return $bao_name::writeRecord($params);
}
/**