mirror of
https://github.com/processwire/processwire.git
synced 2025-08-13 18:24:57 +02:00
Add support for custom fields in file/image fields. Details and instructions coming on Friday, but if you want to preview, create a template with name "field-images" where the "images" part is the name of your file/image field. Add the fields to it that you want to represent your custom fields, and it's ready to use. Supports most core Fieldtypes (including multi-language) with the following exceptions that are not supported as custom fields in an File/Image field: CKEditor, Repeaters, PageTable, Files (nested), Images (nested), Comments, Cache, Selector.
This commit is contained in:
@@ -12,7 +12,7 @@
|
||||
* Pagefile objects are contained by a `Pagefiles` object.
|
||||
* #pw-body
|
||||
*
|
||||
* ProcessWire 3.x, Copyright 2018 by Ryan Cramer
|
||||
* ProcessWire 3.x, Copyright 2019 by Ryan Cramer
|
||||
* https://processwire.com
|
||||
*
|
||||
* @property-read string $url URL to the file on the server.
|
||||
@@ -23,6 +23,7 @@
|
||||
* @property-read string $name Returns the filename without the path, same as the "basename" property.
|
||||
* @property-read string $hash Get a unique hash (for the page) representing this Pagefile.
|
||||
* @property-read array $tagsArray Get file tags as an array. #pw-group-tags @since 3.0.17
|
||||
* @property-read array $fieldValues Custom field values. #pw-internal @since 3.0.142
|
||||
* @property int $sort Sort order in database. #pw-group-other
|
||||
* @property string $basename Returns the filename without the path.
|
||||
* @property string $description Value of the file’s description field (string), if enabled. Note you can also set this property directly.
|
||||
@@ -77,6 +78,17 @@ class Pagefile extends WireData {
|
||||
*/
|
||||
protected $filedata = array();
|
||||
|
||||
/**
|
||||
* Custom field values indexed by field name, loaded on request
|
||||
*
|
||||
* Values here have been run through wakeupValue and sanitizeValue already.
|
||||
* Prior to that they are stored in $filedata (above).
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
*/
|
||||
protected $fieldValues = array();
|
||||
|
||||
/**
|
||||
* Construct a new Pagefile
|
||||
*
|
||||
@@ -227,6 +239,8 @@ class Pagefile extends WireData {
|
||||
$language = $languages->get((int) $matches[1]);
|
||||
if($language && $language->id) return $this->setDescription($value, $language);
|
||||
}
|
||||
} else if($this->setFieldValue($key, $value)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
return parent::set($key, $value);
|
||||
@@ -237,7 +251,6 @@ class Pagefile extends WireData {
|
||||
*
|
||||
* Filedata is any additional data that you want to store with the file’s 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.
|
||||
@@ -558,11 +571,120 @@ class Pagefile extends WireData {
|
||||
$value = filemtime($this->filename());
|
||||
if(strpos($key, 'Str')) $value = wireDate($this->wire('config')->dateFormat, $value);
|
||||
break;
|
||||
case 'fieldValues':
|
||||
return $this->fieldValues;
|
||||
break;
|
||||
default:
|
||||
$value = $this->getFieldValue($key);
|
||||
|
||||
}
|
||||
if(is_null($value)) return parent::get($key);
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a custom field value
|
||||
*
|
||||
* #pw-internal Most non-core cases should just use get() or direct access rather than this method
|
||||
*
|
||||
* @param string $name
|
||||
* @param bool|null Get as formatted value? true=yes, false=no, null=use page output formatting setting (default=null)
|
||||
* @return mixed|null Returns value or null if not present
|
||||
* @since 3.0.142
|
||||
*
|
||||
*/
|
||||
public function getFieldValue($name, $formatted = null) {
|
||||
|
||||
$field = $this->wire('fields')->get($name);
|
||||
if(!$field) return null;
|
||||
|
||||
$template = $this->pagefiles->getFieldsTemplate();
|
||||
if(!$template) return null;
|
||||
|
||||
$fieldgroup = $template->fieldgroup;
|
||||
if(!$fieldgroup->hasField($field)) return null;
|
||||
|
||||
$field = $fieldgroup->getFieldContext($field); // get in context
|
||||
$fieldtype = $field->type; /** @var Fieldtype $fieldtype */
|
||||
$fileField = $this->pagefiles->getField(); /** @var Field $fileField */
|
||||
$fileFieldtype = $fileField->type; /** @var FieldtypeFile|FieldtypeImage $fileFieldtype */
|
||||
$page = $fileFieldtype->getFieldsPage($fileField);
|
||||
|
||||
if(array_key_exists($name, $this->fieldValues)) {
|
||||
$value = $this->fieldValues[$name];
|
||||
} else {
|
||||
$idKey = "_$field->id";
|
||||
$value = $this->filedata($idKey);
|
||||
if($value !== null) {
|
||||
$value = $fieldtype->wakeupValue($page, $field, $value);
|
||||
$value = $fieldtype->sanitizeValue($page, $field, $value);
|
||||
}
|
||||
$this->fieldValues[$name] = $value;
|
||||
unset($this->filedata[$idKey]); // avoid storing double copies
|
||||
}
|
||||
|
||||
if($value === null) {
|
||||
$value = $fieldtype->getBlankValue($page, $field);
|
||||
$value = $fieldtype->sanitizeValue($page, $field, $value);
|
||||
$this->fieldValues[$name] = $value;
|
||||
}
|
||||
|
||||
if($formatted === null) $formatted = $this->page->of();
|
||||
if($formatted) $value = $fieldtype->formatValue($page, $field, $value);
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a custom field value
|
||||
*
|
||||
* #pw-internal Most non-core cases should use set() instead
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $value
|
||||
* @param bool|null $changed Specify true to force track change, false to force no change, or null to auto-detect (default=null)
|
||||
* @return bool Returns true if value set, or false if not (like if there’s no template defined for the purpose)
|
||||
* @since 3.0.142
|
||||
*
|
||||
*
|
||||
*/
|
||||
public function setFieldValue($name, $value, $changed = null) {
|
||||
|
||||
$template = $this->pagefiles->getFieldsTemplate();
|
||||
if(!$template) return false;
|
||||
|
||||
$fieldgroup = $template->fieldgroup;
|
||||
if(!$fieldgroup) return false;
|
||||
|
||||
$field = $fieldgroup->getFieldContext($name);
|
||||
if(!$field) return false;
|
||||
|
||||
$page = $this->pagefiles->getFieldsPage();
|
||||
|
||||
/** @var Fieldtype $fieldtype */
|
||||
$fieldtype = $field->type;
|
||||
$value = $fieldtype->sanitizeValue($page, $field, $value);
|
||||
|
||||
if($changed === null && $this->page->trackChanges()) {
|
||||
// detect if a change has taken place
|
||||
$oldValue = $this->getFieldValue($field->name, false);
|
||||
if(is_object($oldValue) && $oldValue instanceof Wire && $oldValue === $value) {
|
||||
// $oldValue and new $value are the same object instance, so ask it if anything has changed
|
||||
$changed = $oldValue->isChanged();
|
||||
if($changed) $this->trackChange($field->name);
|
||||
} else if($oldValue != $value) {
|
||||
// $oldValue and new $value differ, record change
|
||||
$this->trackChange($field->name, $oldValue, $value);
|
||||
}
|
||||
} else if($changed === true) {
|
||||
$this->trackChange($field->name);
|
||||
}
|
||||
|
||||
$this->fieldValues[$field->name] = $value;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hookable no-cache URL
|
||||
*
|
||||
|
@@ -108,6 +108,12 @@ class Pagefiles extends WireArray implements PageFieldValueInterface {
|
||||
*
|
||||
*/
|
||||
protected $formatted = false;
|
||||
|
||||
/**
|
||||
* @var Template|null
|
||||
*
|
||||
*/
|
||||
protected $fieldsTemplate = null;
|
||||
|
||||
/**
|
||||
* Construct a Pagefiles object
|
||||
@@ -117,6 +123,7 @@ class Pagefiles extends WireArray implements PageFieldValueInterface {
|
||||
*/
|
||||
public function __construct(Page $page) {
|
||||
$this->setPage($page);
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -917,6 +924,44 @@ class Pagefiles extends WireArray implements PageFieldValueInterface {
|
||||
return $this->formatted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Template object used for Pagefile custom fields, if available (false if not)
|
||||
*
|
||||
* #pw-internal
|
||||
*
|
||||
* @return bool|Template
|
||||
* @since 3.0.142
|
||||
*
|
||||
*/
|
||||
public function getFieldsTemplate() {
|
||||
if($this->fieldsTemplate === null) {
|
||||
/** @var Field $field */
|
||||
$field = $this->getField();
|
||||
if($field) {
|
||||
$this->fieldsTemplate = false;
|
||||
/** @var FieldtypeFile $fieldtype */
|
||||
$fieldtype = $field->type;
|
||||
$template = $fieldtype ? $fieldtype->getFieldsTemplate($field) : null;
|
||||
if($template) $this->fieldsTemplate = $template;
|
||||
}
|
||||
}
|
||||
return $this->fieldsTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get mock/placeholder Page object used for Pagefile custom fields
|
||||
*
|
||||
* @return Page
|
||||
* @since 3.0.142
|
||||
*
|
||||
*/
|
||||
public function getFieldsPage() {
|
||||
$field = $this->getField();
|
||||
/** @var FieldtypeFile $fieldtype */
|
||||
$fieldtype = $field->type;
|
||||
return $fieldtype->getFieldsPage($field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Debug info
|
||||
*
|
||||
|
Reference in New Issue
Block a user