/**
 * Create an Attachment.
 *
 * @param array $params
 *
 * @return array
 * @throws API_Exception validation errors
 * @see Civi\API\Subscriber\DynamicFKAuthorization
 */
function civicrm_api3_attachment_create($params)
{
    if (empty($params['id'])) {
        // When creating we need either entity_table or field_name
        civicrm_api3_verify_one_mandatory($params, NULL, array('entity_table', 'field_name'));
    }
    $config = CRM_Core_Config::singleton();
    list($id, $file, $entityFile, $name, $content, $moveFile, $isTrusted, $returnContent) = _civicrm_api3_attachment_parse_params($params);
    $fileDao = new CRM_Core_BAO_File();
    $entityFileDao = new CRM_Core_DAO_EntityFile();
    if ($id) {
        $fileDao->id = $id;
        if (!$fileDao->find(TRUE)) {
            throw new API_Exception("Invalid ID");
        }
        $entityFileDao->file_id = $id;
        if (!$entityFileDao->find(TRUE)) {
            throw new API_Exception("Cannot modify orphaned file");
        }
    }
    if (!$id && !is_string($content) && !is_string($moveFile)) {
        throw new API_Exception("Mandatory key(s) missing from params array: 'id' or 'content' or 'options.move-file'");
    }
    if (!$isTrusted && $moveFile) {
        throw new API_Exception("options.move-file is only supported on secure calls");
    }
    if (is_string($content) && is_string($moveFile)) {
        throw new API_Exception("'content' and 'options.move-file' are mutually exclusive");
    }
    if ($id && !$isTrusted && isset($file['upload_date']) && $file['upload_date'] != CRM_Utils_Date::isoToMysql($fileDao->upload_date)) {
        throw new API_Exception("Cannot modify upload_date" . var_export(array($file['upload_date'], $fileDao->upload_date, CRM_Utils_Date::isoToMysql($fileDao->upload_date)), TRUE));
    }
    if ($id && $name && $name != CRM_Utils_File::cleanFileName($fileDao->uri)) {
        throw new API_Exception("Cannot modify name");
    }
    $fileDao->copyValues($file);
    if (!$id) {
        $fileDao->uri = CRM_Utils_File::makeFileName($name);
    }
    $fileDao->save();
    $entityFileDao->copyValues($entityFile);
    $entityFileDao->file_id = $fileDao->id;
    $entityFileDao->save();
    $path = $config->customFileUploadDir . DIRECTORY_SEPARATOR . $fileDao->uri;
    if (is_string($content)) {
        file_put_contents($path, $content);
    } elseif (is_string($moveFile)) {
        // CRM-17432 Do not use rename() since it will break file permissions.
        // Also avoid move_uplaoded_file() because the API can use options.move-file.
        copy($moveFile, $path);
        unlink($moveFile);
    }
    // Save custom field to entity
    if (!$id && empty($params['entity_table']) && isset($params['field_name'])) {
        civicrm_api3('custom_value', 'create', array('entity_id' => $params['entity_id'], $params['field_name'] => $fileDao->id));
    }
    $result = array($fileDao->id => _civicrm_api3_attachment_format_result($fileDao, $entityFileDao, $returnContent, $isTrusted));
    return civicrm_api3_create_success($result, $params, 'Attachment', 'create');
}