Thumbnails (and handling) of uploaded files on new entries that have not yet been saved

This commit is contained in:
nathangray
2017-04-10 10:39:04 -06:00
parent ee62801ace
commit d5c24a2c8e
11 changed files with 158 additions and 24 deletions

View File

@@ -995,6 +995,16 @@ class Contacts extends Contacts\Storage
$contact['uid'] = $to_write['uid'];
$contact['etag'] = $to_write['etag'];
// Clear any files saved with new entries
// They've been dealt with already and they cause errors with linking
foreach(array_keys($this->customfields) as $field)
{
if(is_array($to_write[Storage::CF_PREFIX.$field]))
{
unset($to_write[Storage::CF_PREFIX.$field]);
}
}
// if contact is an account and account-relevant data got updated, handle it like account got updated
if ($contact['account_id'] && $isUpdate &&
($old['email'] != $contact['email'] || $old['n_family'] != $contact['n_family'] || $old['n_given'] != $contact['n_given']))

View File

@@ -1051,7 +1051,7 @@ class Sql extends Api\Storage
* @param array $extra_cols =array() extra-data to be saved
* @return bool false on success, errornumber on failure
*/
function save_customfields($data, array $extra_cols=array())
function save_customfields(&$data, array $extra_cols=array())
{
return parent::save_customfields($data, array('contact_owner' => $data['owner'])+$extra_cols);
}

View File

@@ -399,7 +399,10 @@ class Customfields extends Transformer
$field_name = $this->id[0] == self::$prefix && $customfields[substr($this->id,1)] ? $this->id : self::form_name($form_name != self::GLOBAL_ID ? $form_name : $cname, $field);
$valid =& self::get_array($validated, $field_name, true);
if (is_array($valid)) $valid = implode(',', $valid);
// Arrays are not valid, but leave filemanager alone, we'll catch it
// when saving. This allows files for new entries.
if (is_array($valid) && $field_settings['type'] !== 'filemanager') $valid = implode(',', $valid);
// NULL is valid for most fields, but not custom fields due to backend handling
// See so_sql_cf->save()
if (is_null($valid)) $valid = false;
@@ -414,4 +417,58 @@ class Customfields extends Transformer
//error_log(__METHOD__."() $form_name $field: ".array2string($value).' --> '.array2string($value));
}
}
/**
* Handle any uploaded files that weren't dealt with immediately when uploaded.
* This usually happens for new entries, where we don't have the entry's ID
* to properly file it in the VFS. Files are stored temporarily until we
* have the ID, then here we move the files to their proper location.
*
* @staticvar array $_customfields List of custom field data, kept to avoid
* loading it multiple times if called again.
*
* @param string $app Current application
* @param string $entry_id Application ID of the new entry
* @param Array $values Array of entry data, including custom fields.
* File information from the VFS widget (via self::validate()) will be found &
* dealt with. Successful or not, the value is cleared to avoid trying to insert it into
* the database, which would generate errors.
* @param Array $customfields Pass the custom field list if you have it to avoid loading it again
*/
public static function handle_files($app, $entry_id, &$values, &$customfields = array())
{
if(!is_array($values) || !$entry_id) return;
if(!$customfields)
{
static $_customfields = array();
if(!$_customfields[$app])
{
$_customfields[$app] = Api\Storage\Customfields::get($app);
}
$customfields = $_customfields[$app];
}
foreach ($customfields as $field_name => $field)
{
if($field['type'] == 'filemanager')
{
$value =& $values[static::$prefix.$field_name];
static::handle_file($entry_id, $field, $value);
unset($values[static::$prefix.$field_name]);
}
}
}
protected static function handle_file($entry_id, $field, $value)
{
$path = Vfs::get_vfs_path($field['app'].":$entry_id:".$field['label']);
if($path)
{
foreach($value as $file)
{
$file['tmp_name'] = Api\Vfs::PREFIX.$file['path'];
Vfs::store_file($path, $file);
}
}
}
}

View File

@@ -85,13 +85,13 @@ class File extends Etemplate\Widget
}
foreach($file_list as $file)
{
self::process_uploaded_file($field, $file, $mime, $file_data);
static::process_uploaded_file($field, $file, $mime, $file_data);
}
}
else
{
// Just one file
self::process_uploaded_file($field, $files, $mime, $file_data);
static::process_uploaded_file($field, $files, $mime, $file_data);
}
}

View File

@@ -56,11 +56,15 @@ class Vfs extends File
if(!is_numeric($id))
{
$_id = self::expand_name($id,0,0,0,0,self::$request->content);
if($_id != $id)
if($_id != $id && $_id)
{
$id = $_id;
$form_name = "$app:$id:$relpath";
}
else
{
return;
}
}
$value =& self::get_array(self::$request->content, $form_name, true);
$path = Api\Link::vfs_path($app,$id,'',true);
@@ -113,9 +117,23 @@ class Vfs extends File
public static function ajax_upload()
{
parent::ajax_upload();
foreach($_FILES as $file)
}
/**
* Process one uploaded file. There should only be one per request...
*
* Overriden from the parent to see if we can safely show the thumbnail immediately
*/
protected static function process_uploaded_file($field, Array &$file, $mime, Array &$file_data)
{
parent::process_uploaded_file($field, $file, $mime, $file_data);
$path = self::store_file($_REQUEST['path'] ? $_REQUEST['path'] : $_REQUEST['widget_id'], $file);
if($path)
{
self::store_file($_REQUEST['path'] ? $_REQUEST['path'] : $_REQUEST['widget_id'], $file);
$file_data[basename($file['tmp_name'])]['name'] = $file['name'];
$file_data[basename($file['tmp_name'])]['path'] = $path;
$file_data[basename($file['tmp_name'])]['mime'] = $file['type'];
$file_data[basename($file['tmp_name'])]['mtime'] = time();
}
}
@@ -232,7 +250,7 @@ class Vfs extends File
* When the form is submitted, the information for all files uploaded is available in the returned
* $content array and the application should deal with the file.
*/
public static function store_file($path, $file)
public static function store_file($path, &$file)
{
$name = $_REQUEST['widget_id'];
@@ -242,16 +260,17 @@ class Vfs extends File
$path = self::get_vfs_path($path);
}
$filename = $file['name'];
if (substr($path,-1) != '/')
if ($path && substr($path,-1) != '/')
{
// add extension to path
$parts = explode('.',$filename);
if (($extension = array_pop($parts)) && Api\MimeMagic::ext2mime($extension)) // really an extension --> add it to path
{
$path .= '.'.$extension;
$file['name'] = Api\Vfs::basename($path);
}
}
else // multiple upload with dir given (trailing slash)
else if ($path) // multiple upload with dir given (trailing slash)
{
$path .= Api\Vfs::encodePathComponent($filename);
}
@@ -331,10 +350,15 @@ class Vfs extends File
if(!is_numeric($id))
{
$_id = self::expand_name($id,0,0,0,0,self::$request->content);
if($_id != $id)
if($_id != $id && $_id)
{
$id = $_id;
}
else
{
// ID didn't resolve, try again without it as a 'new record'
return static::get_vfs_path("$app::$relpath");
}
}
$path = Api\Link::vfs_path($app,$id,'',true);
}

View File

@@ -216,14 +216,18 @@ class Storage extends Storage\Base
* @param array $extra_cols =array() extra-data to be saved
* @return bool false on success, errornumber on failure
*/
function save_customfields($data, array $extra_cols=array())
function save_customfields(&$data, array $extra_cols=array())
{
$id = isset($data[$this->autoinc_id]) ? $data[$this->autoinc_id] : $data[$this->db_key_cols[$this->autoinc_id]];
\EGroupware\Api\Etemplate\Widget\Customfields::handle_files($this->app, $id, $data, $this->customfields);
foreach (array_keys((array)$this->customfields) as $name)
{
if (!isset($data[$field = $this->get_cf_field($name)])) continue;
$where = array(
$this->extra_id => isset($data[$this->autoinc_id]) ? $data[$this->autoinc_id] : $data[$this->db_key_cols[$this->autoinc_id]],
$this->extra_id => $id,
$this->extra_key => $name,
);
$is_multiple = $this->is_multiple($name);