1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-07 07:16:51 +02:00

Add support for filedata in FieldtypeFile/FieldtypeImage, which provides a way to store other general purpose data with files/images.

This commit is contained in:
Ryan Cramer
2018-01-24 11:31:03 -05:00
parent 6241fd6730
commit 3fb3294f5a
4 changed files with 149 additions and 13 deletions

View File

@@ -54,7 +54,15 @@ class Pagefile extends WireData {
* @var Pagefiles
*
*/
protected $pagefiles;
protected $pagefiles;
/**
* Extra file data
*
* @var array
*
*/
protected $filedata = array();
/**
* Construct a new Pagefile
@@ -173,14 +181,20 @@ class Pagefile extends WireData {
*/
public function set($key, $value) {
if($key == 'basename') $value = $this->pagefiles->cleanBasename($value, false);
if($key == 'description') return $this->setDescription($value);
if($key == 'modified') $value = ctype_digit("$value") ? (int) $value : strtotime($value);
if($key == 'created') $value = ctype_digit("$value") ? (int) $value : strtotime($value);
if($key == 'tags') {
if($key == 'basename') {
$value = $this->pagefiles->cleanBasename($value, false);
} else if($key == 'description') {
return $this->setDescription($value);
} else if($key == 'modified') {
$value = ctype_digit("$value") ? (int) $value : strtotime($value);
} else if($key == 'created') {
$value = ctype_digit("$value") ? (int) $value : strtotime($value);
} else if($key == 'tags') {
$this->tags($value);
return $this;
} else if($key == 'filedata') {
if(is_array($value)) $this->filedata($value);
return $this;
}
if(strpos($key, 'description') === 0 && preg_match('/^description(\d+)$/', $value, $matches)) {
@@ -195,6 +209,59 @@ class Pagefile extends WireData {
return parent::set($key, $value);
}
/**
* Get or set filedata
*
* Filedata is any additional data that you want to store with the files database record.
*
*
* - To get a value, specify just the $key argument. Null is returned if request value is not present.
* - To get all values, omit all arguments. An associative array will be returned.
* - To set a value, specify the $key and the $value to set.
* - To set all values at once, specify an associative array for the $key argument.
* - To unset, specify boolean false (or null) for $key, and the name of the property to unset as $value.
* - To unset, you can also get all values, unset it from the retuned array, and set the array back.
*
* #pw-internal
*
* @param string|array|false|null $key Specify array to set all file data, or key (string) to set or get a property,
* Or specify boolean false to remove key specified by $value argument.
* @param null|string|array|int|float $value Specify a value to set for given property
* @return Pagefile|Pageimage|array|string|int|float|bool|null
*
*/
public function filedata($key = '', $value = null) {
$filedata = $this->filedata;
if($key === false || $key === null) {
// unset property named in $value
if(!empty($value)) {
unset($this->filedata[$value]);
if(isset($filedata[$value])) $this->trackChange('filedata', $filedata, $this->filedata);
}
return $this;
} else if(empty($key)) {
// return all
return $filedata;
} else if(is_array($key)) {
// set all
if($key != $filedata) {
$this->filedata = $key;
$this->trackChange('filedata', $filedata, $this->filedata);
}
return $this;
} else if($value === null) {
// return value for key
return isset($this->filedata[$key]) ? $this->filedata[$key] : null;
} else {
// set value for key
if(!isset($filedata[$key]) || $filedata[$key] != $value) {
$this->filedata[$key] = $value;
$this->trackChange('filedata', $filedata, $this->filedata);
}
return $this;
}
}
/**
* Set a description, optionally parsing JSON language-specific descriptions to separate properties
*
@@ -243,6 +310,7 @@ class Pagefile extends WireData {
foreach($values as $id => $v) {
// first item is always default language. this ensures description will still
// work even if language support is later uninstalled.
$name = 'description';
if($noLang && $n > 0) break;
$n++;
if(ctype_digit("$id")) {
@@ -445,6 +513,10 @@ class Pagefile extends WireData {
parent::set($key, $value);
}
break;
case 'fileData':
case 'filedata':
$value = $this->filedata();
break;
case 'mtime':
$value = filemtime($this->filename());
break;
@@ -875,7 +947,7 @@ class Pagefile extends WireData {
* #pw-internal
*
* @param string $path Path (not including basename)
* @return mixed result of copy() function
* @return bool result of copy() function
*
*/
public function copyToPath($path) {

View File

@@ -107,3 +107,4 @@ foreach($corePreloads as $file) {
/** @noinspection PhpIncludeInspection */
include_once(PROCESSWIRE_CORE_PATH . $file);
}
unset($corePreloads);

View File

@@ -63,6 +63,12 @@ class FieldtypeFile extends FieldtypeMulti {
*/
const fileSchemaDate = 2;
/**
* File schema is configured to support 'filedata' encoded data (flag)
*
*/
const fileSchemaFiledata = 4;
/**
* Flag for useTags: tags off/disabled
*
@@ -207,6 +213,7 @@ class FieldtypeFile extends FieldtypeMulti {
if(isset($v['modified'])) $pagefile->modified = $v['modified'];
if(isset($v['created'])) $pagefile->created = $v['created'];
if(isset($v['tags'])) $pagefile->tags = $v['tags'];
if(!empty($v['filedata'])) $pagefile->filedata = json_decode($v['filedata'], true);
$pagefile->setTrackChanges(true);
$pagefiles->add($pagefile);
}
@@ -245,6 +252,12 @@ class FieldtypeFile extends FieldtypeMulti {
if($fileSchema & self::fileSchemaTags) {
$item['tags'] = $pagefile->tags;
}
if($fileSchema & self::fileSchemaFiledata) {
$item['filedata'] = null;
$filedata = $pagefile->filedata;
if(!empty($filedata)) $item['filedata'] = json_encode($filedata);
}
$sleepValue[] = $item;
}
@@ -516,10 +529,56 @@ class FieldtypeFile extends FieldtypeMulti {
$schema['data'] = "varchar($maxLen) NOT NULL";
$schema['description'] = "text NOT NULL";
$schema['modified'] = "datetime";
$schema['created'] = "datetime";
$schema['keys']['description'] = 'FULLTEXT KEY description (description)';
$schema['created'] = "datetime";
$schema['filedata'] = "mediumtext";
$schema['keys']['description'] = 'FULLTEXT KEY description (description)';
$schema['keys']['filedata'] = 'FULLTEXT KEY filedata (filedata)';
$schema['keys']['modified'] = 'index (modified)';
$schema['keys']['created'] = 'index (created)';
$schema['keys']['created'] = 'index (created)';
if($field->id && !($field->get('fileSchema') & self::fileSchemaFiledata)) {
// permanently add new 'filedata' column to schema
$addFiledata = false;
try {
$query = $database->prepare("SHOW COLUMNS FROM `$table` WHERE Field='filedata'");
$query->execute();
$numRows = (int) $query->rowCount();
$query->closeCursor();
if($numRows) {
$field->set('fileSchema', $field->get('fileSchema') | self::fileSchemaFiledata);
$field->save();
} else {
$addFiledata = true;
}
} catch(\Exception $e) {
// intentionally blank
}
if($addFiledata) try {
$database->exec("ALTER TABLE `{$table}` ADD `filedata` $schema[filedata]");
$database->exec("ALTER TABLE `{$table}` ADD " . $schema['keys']['filedata']);
$field->set('fileSchema', $field->get('fileSchema') | self::fileSchemaFiledata);
$field->save();
$this->message("Added filedata to DB schema for '{$field->name}'", Notice::log);
} catch(\Exception $e) {
$query = $database->prepare("SHOW COLUMNS FROM `$table` WHERE Field='filedata'");
$query->execute();
$numRows = (int) $query->rowCount();
$query->closeCursor();
if($numRows) {
$field->set('fileSchema', $field->get('fileSchema') | self::fileSchemaFiledata);
$field->save();
} else {
$this->error("Error adding created/modified to '{$field->name}' schema", Notice::log);
unset($schema['filedata'], $schema['keys']['filedata']);
}
}
}
if($field->id && !($field->get('fileSchema') & self::fileSchemaDate)) {
// permanently add new 'modified' and 'created' column to file schema

View File

@@ -438,7 +438,7 @@ class InputfieldFile extends Inputfield implements InputfieldItemList, Inputfiel
* @return string
*
*/
protected function getDisplayBasename(Pagefile $pagefile, $maxLength = 25) {
public function getDisplayBasename(Pagefile $pagefile, $maxLength = 25) {
$displayName = $pagefile->basename;
if($this->noShortName) return $displayName;
if(strlen($displayName) > $maxLength) {
@@ -764,7 +764,11 @@ class InputfieldFile extends Inputfield implements InputfieldItemList, Inputfiel
if($val) $item->$key = $val;
}
// items saved in ajax or uploadOnly mode are temporary till saved in non-ajax/non-uploadOnly
if($this->isAjax && !$this->overwrite) $item->isTemp(true);
if($this->isAjax && !$this->overwrite) {
if($this->wire('input')->get('InputfieldFileAjax') !== 'noTemp') {
$item->isTemp(true);
}
}
$this->fileAdded($item);
} catch(\Exception $e) {
$item->unlink();