Skip to content
Permalink
Browse files

Add support for Fieldtypes to specify that a Field should use a custo…

…m class that extends the Field class, rather than always using the "Field" class.
  • Loading branch information
Ryan Cramer
Ryan Cramer committed Nov 12, 2019
1 parent 4e4b3af commit bbddcf1ca0bfd0783461398f3eb7e7863e783282
@@ -616,7 +616,7 @@ public function setFieldtype($type) {
} 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 @@ public function makeBlankItem() {
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 @@ public function ___importValue(Page $page, Field $field, $value, array $options
*
* #pw-internal
*
* @param array Field $field
* @param Field $field
* @return array
*
*/
@@ -813,6 +813,21 @@ public function getDatabaseSchema(Field $field) {
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 @@ protected function preload() {
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 @@ public function get($key) {
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,28 +182,28 @@ protected function getLoadQuery($selectors = null) {
*/
protected function ___load(WireArray $items, $selectors = null) {
/** @var WireDatabasePDO $database */
$database = $this->wire('database');
$sql = $this->getLoadQuery($selectors)->getQuery();
$query = $database->prepare($sql);
$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)
}

0 comments on commit bbddcf1

Please sign in to comment.
You can’t perform that action at this time.