mirror of
https://github.com/processwire/processwire.git
synced 2025-08-13 18:24:57 +02:00
Add support for Fieldtypes to specify that a Field should use a custom class that extends the Field class, rather than always using the "Field" class.
This commit is contained in:
@@ -616,7 +616,7 @@ class Field extends WireData implements Saveable, Exportable {
|
||||
|
||||
} else if(is_string($type)) {
|
||||
$typeStr = $type;
|
||||
$fieldtypes = $this->wire('fieldtypes');
|
||||
$fieldtypes = $this->wire('fieldtypes'); /** @var Fieldtypes $fieldtypes */
|
||||
if(!$type = $fieldtypes->get($type)) {
|
||||
$this->error("Fieldtype '$typeStr' does not exist");
|
||||
return $this;
|
||||
|
@@ -155,6 +155,45 @@ class Fields extends WireSaveableItems {
|
||||
return $this->wire(new Field());
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an item and populate with given data
|
||||
*
|
||||
* @param array $a Associative array of data to populate
|
||||
* @return Saveable|Wire
|
||||
* @throws WireException
|
||||
* @since 3.0.147
|
||||
*
|
||||
*/
|
||||
public function makeItem(array $a = array()) {
|
||||
|
||||
if(empty($a['type'])) return parent::makeItem($a);
|
||||
|
||||
/** @var Fieldtypes $fieldtypes */
|
||||
$fieldtypes = $this->wire('fieldtypes');
|
||||
if(!$fieldtypes) return parent::makeItem($a);
|
||||
|
||||
/** @var Fieldtype $fieldtype */
|
||||
$fieldtype = $fieldtypes->get($a['type']);
|
||||
if(!$fieldtype) return parent::makeItem($a);
|
||||
|
||||
$class = $fieldtype->getFieldClass($a);
|
||||
if(empty($class) || $class === 'Field') return parent::makeItem($a);
|
||||
|
||||
if(strpos($class, "\\") === false) $class = wireClassName($class, true);
|
||||
if(!class_exists($class)) return parent::makeItem($a);
|
||||
|
||||
$field = new $class();
|
||||
$this->wire($field);
|
||||
|
||||
foreach($a as $key => $value) {
|
||||
$field->$key = $value;
|
||||
}
|
||||
|
||||
$field->resetTrackChanges(true);
|
||||
|
||||
return $field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Per WireSaveableItems interface, return all available Field instances
|
||||
*
|
||||
|
@@ -605,7 +605,7 @@ abstract class Fieldtype extends WireData implements Module {
|
||||
*
|
||||
* #pw-internal
|
||||
*
|
||||
* @param array Field $field
|
||||
* @param Field $field
|
||||
* @return array
|
||||
*
|
||||
*/
|
||||
@@ -813,6 +813,21 @@ abstract class Fieldtype extends WireData implements Module {
|
||||
return $schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get class name to use Field objects of this type (must be class that extends Field class)
|
||||
*
|
||||
* Return blank if default class (Field) should be used.
|
||||
*
|
||||
* @param array $a Field data from DB (if needed)
|
||||
* @return string Return class name or blank to use default Field class
|
||||
* @since 3.0.147
|
||||
*
|
||||
*/
|
||||
public function getFieldClass(array $a = array()) {
|
||||
if($a) {} // ignore
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns verbose array of database schema information
|
||||
*
|
||||
|
@@ -49,10 +49,11 @@ class Fieldtypes extends WireArray {
|
||||
if($this->preloaded) return;
|
||||
$debug = $this->isAPI && $this->wire('config')->debug;
|
||||
if($debug) Debug::timer('Fieldtypes.preload');
|
||||
foreach($this->data as $key => $module) {
|
||||
$modules = $this->wire('modules'); /** @var Modules $modules */
|
||||
foreach($this->data as $moduleName => $module) {
|
||||
if($module instanceof ModulePlaceholder) {
|
||||
$fieldtype = $this->wire('modules')->get($module->className());
|
||||
$this->data[$key] = $fieldtype;
|
||||
$fieldtype = $modules->getModule($moduleName);
|
||||
$this->data[$moduleName] = $fieldtype;
|
||||
}
|
||||
}
|
||||
if($debug) Debug::saveTimer('Fieldtypes.preload');
|
||||
@@ -130,11 +131,12 @@ class Fieldtypes extends WireArray {
|
||||
if(strpos($key, 'Fieldtype') !== 0) $key = "Fieldtype" . ucfirst($key);
|
||||
|
||||
if(!$fieldtype = parent::get($key)) {
|
||||
$fieldtype = $this->wire('modules')->get($key);
|
||||
$fieldtype = $this->wire('modules')->getModule($key);
|
||||
if($fieldtype) $this->set($key, $fieldtype);
|
||||
}
|
||||
|
||||
if($fieldtype instanceof ModulePlaceholder) {
|
||||
$fieldtype = $this->wire('modules')->get($fieldtype->className());
|
||||
$fieldtype = $this->wire('modules')->getModule($fieldtype->className());
|
||||
if($fieldtype) $this->set($key, $fieldtype);
|
||||
}
|
||||
|
||||
|
@@ -42,6 +42,25 @@ abstract class WireSaveableItems extends Wire implements \IteratorAggregate {
|
||||
*/
|
||||
abstract public function makeBlankItem();
|
||||
|
||||
/**
|
||||
* Make an item and populate with given data
|
||||
*
|
||||
* @param array $a Associative array of data to populate
|
||||
* @return Saveable|Wire
|
||||
* @throws WireException
|
||||
* @since 3.0.147
|
||||
*
|
||||
*/
|
||||
public function makeItem(array $a = array()) {
|
||||
$item = $this->makeBlankItem();
|
||||
$this->wire($item);
|
||||
foreach($a as $key => $value) {
|
||||
$item->$key = $value;
|
||||
}
|
||||
$item->resetTrackChanges(true);
|
||||
return $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the table that this DAO stores item records in
|
||||
*
|
||||
@@ -163,6 +182,7 @@ abstract class WireSaveableItems extends Wire implements \IteratorAggregate {
|
||||
*/
|
||||
protected function ___load(WireArray $items, $selectors = null) {
|
||||
|
||||
/** @var WireDatabasePDO $database */
|
||||
$database = $this->wire('database');
|
||||
$sql = $this->getLoadQuery($selectors)->getQuery();
|
||||
|
||||
@@ -170,21 +190,20 @@ abstract class WireSaveableItems extends Wire implements \IteratorAggregate {
|
||||
$query->execute();
|
||||
|
||||
while($row = $query->fetch(\PDO::FETCH_ASSOC)) {
|
||||
$item = $this->makeBlankItem();
|
||||
$this->wire($item);
|
||||
foreach($row as $field => $value) {
|
||||
if($field == 'data') {
|
||||
if($value) $value = $this->decodeData($value);
|
||||
else continue;
|
||||
if(isset($row['data'])) {
|
||||
if($row['data']) {
|
||||
$row['data'] = $this->decodeData($row['data']);
|
||||
} else {
|
||||
unset($row['data']);
|
||||
}
|
||||
$item->$field = $value;
|
||||
}
|
||||
$item->setTrackChanges(true);
|
||||
$items->add($item);
|
||||
$item = $this->makeItem($row);
|
||||
if($item) $items->add($item);
|
||||
}
|
||||
|
||||
$query->closeCursor();
|
||||
|
||||
$items->setTrackChanges(true);
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
|
@@ -199,6 +199,21 @@ class FieldtypeRepeater extends Fieldtype implements ConfigurableModule {
|
||||
$initFields[$className] = 1;
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get class name to use Field objects of this type (must be class that extends Field class)
|
||||
*
|
||||
* Return blank if default class (Field) should be used.
|
||||
*
|
||||
* @param array $a Field data from DB (if needed)
|
||||
* @return string Return class name or blank to use default Field class
|
||||
* @since 3.0.147
|
||||
*
|
||||
*/
|
||||
public function getFieldClass(array $a = array()) {
|
||||
require_once(dirname(__FILE__) . '/RepeaterField.php');
|
||||
return 'RepeaterField';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the class used for repeater Page objects
|
||||
|
@@ -0,0 +1,5 @@
|
||||
<?php namespace ProcessWire;
|
||||
|
||||
class RepeaterField extends Field {
|
||||
// example of custom class for Field object (not yet put to use in this case)
|
||||
}
|
Reference in New Issue
Block a user