/**
* Class constructor.
*
- * @return \CRM_Core_DAO
+ * @return static
*/
public function __construct() {
$this->initialize();
* we will build the condition only using the whereAdd's. Default is to
* build the condition only using the object parameters.
*
- * * @return mixed Int (No. of rows affected) on success, false on failure, 0 on no data affected
+ * @return int|false
+ * Int (No. of rows affected) on success, false on failure, 0 on no data affected
*/
public function delete($useWhere = FALSE) {
$preEvent = new \Civi\Core\DAO\Event\PreDelete($this);
* @throws \CRM_Core_Exception
*/
public static function writeRecord(array $record): CRM_Core_DAO {
- $hook = empty($record['id']) ? 'create' : 'edit';
+ $op = 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();
+ \CRM_Utils_Hook::pre($op, $entityName, $record['id'] ?? NULL, $record);
+ $fields = static::getSupportedFields();
+ $instance = new static();
// Ensure fields exist before attempting to write to them
- $values = array_intersect_key($record, self::getSupportedFields());
+ $values = array_intersect_key($record, $fields);
$instance->copyValues($values);
+ if (empty($values['id']) && array_key_exists('name', $fields) && empty($values['name']) && !empty($values['label'])) {
+ $instance->makeNameFromLabel();
+ }
$instance->save();
- \CRM_Utils_Hook::post($hook, $entityName, $instance->id, $instance);
+
+ if (!empty($record['custom']) && is_array($record['custom'])) {
+ CRM_Core_BAO_CustomValueTable::store($record['custom'], static::$_tableName, $instance->id, $op);
+ }
+
+ \CRM_Utils_Hook::post($op, $entityName, $instance->id, $instance);
return $instance;
}
/**
* Find all records which refer to this entity.
*
- * @return array
- * Array of objects referencing this
+ * @return CRM_Core_DAO[]
*/
public function findReferences() {
$links = self::getReferencesToTable(static::getTableName());
return static::$_paths ?? [];
}
+ /**
+ * When creating a record without a supplied name,
+ * create a unique, clean name derived from the label.
+ *
+ * Note: this function does nothing unless a unique index exists for "name" column.
+ */
+ private function makeNameFromLabel() {
+ $indexNameWith = NULL;
+ // Look for a unique index which includes the "name" field
+ if (method_exists($this, 'indices')) {
+ foreach ($this->indices(FALSE) as $index) {
+ if (!empty($index['unique']) && in_array('name', $index['field'], TRUE)) {
+ $indexNameWith = $index['field'];
+ }
+ }
+ }
+ if (!$indexNameWith) {
+ // No unique index on "name", do nothing
+ return;
+ }
+ $name = CRM_Utils_String::munge($this->label, '_', 252);
+
+ // Find existing records with the same name
+ $sql = new CRM_Utils_SQL_Select($this::getTableName());
+ $sql->select(['id', 'name']);
+ $sql->where('name LIKE @name', ['@name' => $name . '%']);
+ // Include all fields that are part of the index
+ foreach (array_diff($indexNameWith, ['name']) as $field) {
+ $sql->where("`$field` = @val", ['@val' => $this->$field]);
+ }
+ $query = $sql->toSQL();
+ $existing = self::executeQuery($query)->fetchMap('id', 'name');
+ $dupes = 0;
+ $suffix = '';
+ while (in_array($name . $suffix, $existing)) {
+ $suffix = '_' . (++$dupes);
+ }
+ $this->name = $name . $suffix;
+ }
+
}