public function insert($entity, array $options = [])
{
if (is_object($entity)) {
$entityName = get_class($entity);
$this->entity($entityName);
} elseif (is_array($entity)) {
$entityName = $this->entity();
$entity = $this->get()->data($entity);
} else {
throw new Exception(__METHOD__ . " Accepts either an entity object or entity data array");
}
// Run beforeSave and beforeInsert to know whether or not we can continue
if (false === $this->eventEmitter()->emit('beforeSave', [$entity, $this]) || false === $this->eventEmitter()->emit('beforeInsert', [$entity, $this])) {
return false;
}
// Run validation unless disabled via options
if (!isset($options['validate']) || isset($options['validate']) && $options['validate'] !== false) {
if (!$this->validate($entity, $options)) {
return false;
}
}
// Ensure there is actually data to update
$data = $entity->data(null, true, false);
if (count($data) > 0) {
if (isset($options['relations']) && $options['relations'] === true) {
$this->saveBelongsToRelations($entity, $options);
$data = $entity->data(null, true, false);
}
$pkField = $this->primaryKeyField();
$pkFieldInfo = $this->fieldInfo($pkField);
// Save only known, defined fields
$entityFields = $this->fields();
$extraData = array_diff_key($data, $entityFields);
$data = array_intersect_key($data, $entityFields);
// If there are extra fields here, throw an error
if (!isset($options['strict']) || isset($options['strict']) && $options['strict'] === true) {
if (count($extraData) > 0) {
throw new Exception("Insert error: Unknown fields provided for " . $entityName . ": '" . implode("', '", array_keys($extraData)) . "'");
}
}
// Do type conversion
$data = $this->convertToDatabaseValues($entityName, $data);
// Don't pass NULL for "serial" columns (causes issues with PostgreSQL + others)
if (array_key_exists($pkField, $data) && empty($data[$pkField])) {
unset($data[$pkField]);
}
// Send to adapter via named connection
$table = $this->table();
$result = $this->resolver()->create($table, $data);
if ($result) {
$connection = $this->connection();
if (array_key_exists($pkField, $data)) {
// PK value was given on insert, just return it
$result = $data[$pkField];
} else {
// Get PK from database
if ($pkFieldInfo && $pkFieldInfo['autoincrement'] === true) {
if ($this->connectionIs('pgsql')) {
// Allow custom sequence name
$fieldAliasMappings = $this->entityManager()->fieldAliasMappings();
$sequenceField = isset($fieldAliasMappings[$pkField]) ? $fieldAliasMappings[$pkField] : $pkField;
$sequenceName = $this->resolver()->escapeIdentifier($table . '_' . $sequenceField . '_seq');
if (isset($pkFieldInfo['sequence_name'])) {
$sequenceName = $pkFieldInfo['sequence_name'];
}
$result = $connection->lastInsertId($sequenceName);
} else {
$result = $connection->lastInsertId();
}
}
}
}
// Update primary key on entity object
$entity->{$pkField} = $result;
$entity->isNew(false);
$entity->data($entity->data(null, true, false), false);
if (isset($options['relations']) && $options['relations'] === true) {
$this->saveHasRelations($entity, $options);
}
if ($result) {
$this->prepareEntity($entity);
}
// Run afterSave and afterInsert
if (false === $this->eventEmitter()->emit('afterSave', [$entity, $this, &$result]) || false === $this->eventEmitter()->emit('afterInsert', [$entity, $this, &$result])) {
$result = false;
}
} else {
$result = false;
}
return $result;
}