1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-11 09:14:58 +02:00

Implement new getFieldSetups() method in these Fieldtypes: Datetime, File, Image, Options, Page, and Textarea.

This commit is contained in:
Ryan Cramer
2023-02-24 10:19:32 -05:00
parent b3913a8791
commit 5855c8c8b6
8 changed files with 291 additions and 67 deletions

View File

@@ -121,6 +121,45 @@ class FieldtypeDatetime extends Fieldtype {
return $inputfield;
}
/**
* Get predefined setups for newly created fields of this type
*
* #pw-internal
* #pw-hooker
*
* @return array
* @since 3.0.213
*
*/
public function ___getFieldSetups() {
return array(
'datetime' => array(
'title' => $this->_x('Date and Time', 'datetime-setup'), // label for datetime field setup
'dateOutputFormat' => $this->_x('j F Y g:i a', 'datetime-setup'), // default date/time output format for datetime (PHP dateformat)
'dateInputFormat' => $this->_x('Y-m-d', 'datetime-setup'), // default date input format for datetime (PHP dateformat)
'timeInputFormat' => $this->_x('g:i a', 'datetime-setup'), // default time input format for datetime (PHP dateformat)
'inputType' => $this->_x('html', 'datetime-setup'), // default input type to use for datetime - one of: html, text, select
'htmlType' => 'datetime',
),
'date' => array(
'title' => $this->_x('Date', 'date-setup'), // label for date-only fields setup
'dateOutputFormat' => $this->_x('j F Y', 'date-setup'), // default output format for date (PHP dateformat)
'dateInputFormat' => $this->_x('Y-m-d', 'date-setup'), // default input format for date (PHP dateformat)
'timeInputFormat' => '',
'inputType' => $this->_x('html', 'date-setup'), // default input type to use for date - one of: html, text, select
'htmlType' => 'date',
),
'time' => array(
'title' => $this->_x('Time', 'time-setup'), // label for time-only field setup
'dateOutputFormat' => $this->_x('g:i a', 'time-setup'), // default output format for time (PHP dateformat)
'dateInputFormat' => '',
'timeInputFormat' => $this->_x('g:i a', 'time-setup'), // default input format for time (PHP dateformat)
'inputType' => $this->_x('html', 'time-setup'), // default input type to use for time - one of: html, text, select
'htmlType' => 'time',
),
);
}
/**
* Sanitize value, per Fieldtype interface
*

View File

@@ -187,6 +187,28 @@ class FieldtypeFile extends FieldtypeMulti implements ConfigurableModule, Fieldt
return $inputfield;
}
/**
* Get setup options and setup functions for new fields
*
* @return array
* @since 3.0.213
*
*/
public function ___getFieldSetups() {
$setups = parent::___getFieldSetups();
$setups['single'] = array(
'title' => $this->_('Single file'),
'maxFiles' => 1,
'textformatters' => 'TextformatterEntities',
);
$setups['multiple'] = array(
'title' => $this->_('Multiple files'),
'maxFiles' => 0,
'textformatters' => 'TextformatterEntities',
);
return $setups;
}
/**
* Get compatible Fieldtypes
*

View File

@@ -281,6 +281,20 @@ class FieldtypeImage extends FieldtypeFile implements FieldtypeHasFiles, Fieldty
if($value instanceof Pageimage) $pageimages->add($value);
return $pageimages;
}
/**
* Get setup options and setup functions for new fields
*
* @return array
* @since 3.0.213
*
*/
public function ___getFieldSetups() {
$setups = parent::___getFieldSetups();
$setups['single']['title'] = $this->_('Single image');
$setups['multiple']['title'] = $this->_('Multiple images');
return $setups;
}
/**
* Get Inputfields to configure fields using this Fieldtype

View File

@@ -3,7 +3,7 @@
/**
* ProcessWire Select Options Fieldtype
*
* ProcessWire 3.x, Copyright 2022 by Ryan Cramer
* ProcessWire 3.x, Copyright 2023 by Ryan Cramer
* https://processwire.com
*
* @property SelectableOptionManager $manager
@@ -125,6 +125,20 @@ class FieldtypeOptions extends FieldtypeMulti implements Module {
return $inputfield;
}
/**
* Get setup options and setup functions for new fields
*
* @return array
* @since 3.0.213
*
*/
public function ___getFieldSetups() {
$setups = parent::___getFieldSetups();
$setups = array_merge($setups, $this->getInputfieldClassOptions(true));
return $setups;
}
/**
* Get Fieldtypes that are known compatible with this one
*
@@ -598,6 +612,50 @@ class FieldtypeOptions extends FieldtypeMulti implements Module {
return $inputfields;
}
/**
* Get Inputfield options
*
* #pw-internal
*
* @param bool $getFieldSetups
* @return array
* @since 3.0.213
*
*/
public function getInputfieldClassOptions($getFieldSetups = false) {
$options = array();
$modules = $this->wire()->modules;
$labelSingle = $this->_('Single option:');
$labelMulti = $this->_('Multiple options:');
$labelSortable = $this->_('Multiple sortable options:');
foreach($modules->findByPrefix('Inputfield') as $moduleName) {
$module = $modules->getModule($moduleName, array('noInit' => true));
if(!$module instanceof InputfieldHasSelectableOptions) continue;
$title = str_replace('Inputfield', '', $moduleName);
if($module instanceof InputfieldHasSortableValue) {
$title = "$labelSortable $title";
} else if($module instanceof InputfieldSelectMultiple) {
$title = "$labelMulti $title";
} else {
$title = "$labelSingle $title";
}
if($getFieldSetups) {
$name = str_replace('Inputfield', '', $moduleName);
$options[$name] = array(
'title' => $title,
'inputfieldClass' => $moduleName,
);
} else {
$options[$moduleName] = $title;
}
}
asort($options);
return $options;
}
/**
* Given a FieldtypeOptions field id, name or object, return the object
* @param $field

View File

@@ -3,7 +3,7 @@
/**
* Inputfields and processing for Select Options Fieldtype
*
* ProcessWire 3.x, Copyright 2020 by Ryan Cramer
* ProcessWire 3.x, Copyright 2023 by Ryan Cramer
* https://processwire.com
*
*/
@@ -42,6 +42,7 @@ class SelectableOptionConfig extends Wire {
*
*/
public function __construct(Field $field, InputfieldWrapper $inputfields) {
parent::__construct();
$this->field = $field;
$fieldtype = $field->type; /** @var FieldtypeOptions $fieldtype */
$this->fieldtype = $fieldtype;
@@ -59,25 +60,30 @@ class SelectableOptionConfig extends Wire {
*
*/
protected function process(Inputfield $inputfield) {
$modules = $this->wire()->modules;
$input = $this->wire()->input;
$user = $this->wire()->user;
$process = $this->wire()->process;
$languages = $this->wire()->languages;
$session = $this->wire()->session;
$value = $this->wire('input')->post('_options');
$user = $this->wire('user'); /** @var User $user */
$process = $this->wire('process'); /** @var Process @process */
$value = $input->post('_options');
if($process != 'ProcessField' || (!$user->isSuperuser() && !$user->hasPermission('field-admin'))) return;
$ns = "$this$this->field"; // namespace for session
if(!is_null($value)) {
// _options has been posted
if($this->manager->useLanguages() && $inputfield->getSetting('useLanguages')) {
if($this->manager->useLanguages() && $inputfield->getSetting('useLanguages') && $languages) {
// multi-language
$valuesPerLanguage = array();
$changed = false;
foreach($this->wire('languages') as $language) {
foreach($languages as $language) {
$key = $language->isDefault() ? "_options" : "_options__$language";
$valuesPerLanguage[$language->id] = $this->wire('input')->post($key);
$valuesPerLanguage[$language->id] = $input->post($key);
$key = $language->isDefault() ? "value" : "value$language";
if($inputfield->$key != $valuesPerLanguage[$language->id]) $changed = true;
}
@@ -97,11 +103,11 @@ class SelectableOptionConfig extends Wire {
$removedOptionIDs = $this->manager->getRemovedOptionIDs(); // identified for removal
if(count($removedOptionIDs)) {
// stuff in session for next request
$this->wire('session')->set($ns, 'removedOptionIDs', $removedOptionIDs);
$session->set($ns, 'removedOptionIDs', $removedOptionIDs);
}
$deleteOptionIDs = $this->wire('input')->post('_delete_options');
$deleteConfirm = (int) $this->wire('input')->post('_delete_confirm');
$deleteOptionIDs = $input->post('_delete_options');
$deleteConfirm = (int) $input->post('_delete_confirm');
if($deleteOptionIDs && $deleteConfirm) {
// confirmed deleted
if(!ctype_digit(str_replace(',', '', $deleteOptionIDs))) throw new WireException("Invalid deleteOptionIDs");
@@ -113,16 +119,17 @@ class SelectableOptionConfig extends Wire {
} else {
// options not posted, check if there are any pending session activities
$removedOptionIDs = $this->wire('session')->get($ns, 'removedOptionIDs');
$removedOptionIDs = $session->get($ns, 'removedOptionIDs');
if(wireCount($removedOptionIDs)) {
$f = $this->wire('modules')->get('InputfieldHidden');
/** @var InputfieldHidden $f */
$f = $modules->get('InputfieldHidden');
$f->attr('name', '_delete_options');
$f->attr('value', implode(',', $removedOptionIDs));
$this->inputfields->prepend($f);
// setup for confirmation
$f = $this->wire('modules')->get('InputfieldCheckbox');
/** @var InputfieldCheckbox $f */
$f = $modules->get('InputfieldCheckbox');
$f->attr('name', '_delete_confirm');
$f->label = $this->_('Please confirm that you want to delete options');
$f->label2 = $this->_n('Delete this option', 'Delete these options', count($removedOptionIDs));
@@ -131,11 +138,14 @@ class SelectableOptionConfig extends Wire {
$delimiter = $this->_('DELETE:') . ' ';
$f->description .= $delimiter . $removeOptions->implode("\n$delimiter", 'title');
// collapse other inputfields since we prefer them to focus on this one only for now
foreach($this->inputfields as $i) $i->collapsed = Inputfield::collapsedYes;
foreach($this->inputfields as $i) {
/** @var Inputfield $i */
$i->collapsed = Inputfield::collapsedYes;
}
// add our confirmation field
$this->inputfields->prepend($f);
// was stuffed in session from previous request, unset it now since this is a one time thing
$this->wire('session')->remove($ns, 'removedOptionIDs');
$session->remove($ns, 'removedOptionIDs');
}
}
}
@@ -154,37 +164,18 @@ class SelectableOptionConfig extends Wire {
$options = $this->manager->getOptions($field);
$modules = $this->wire('modules');
$labelSingle = $this->_('Single value');
$labelMulti = $this->_('Multiple values');
$labelSortable = $this->_('Multiple sortable values');
/** @var InputfieldSelect $f */
$f = $modules->get('InputfieldSelect');
$f->attr('name', 'inputfieldClass');
$f->label = $this->_('What should be used for input?');
$f->description = $this->_('Depending on what input type you choose, the user will be able to select either a single option or multiple options. Some input types (like AsmSelect) also support user-sortable selections. Some input types also provide more settings on the *Input* tab (visible after you save).');
foreach($modules as $module) {
if(strpos($module->className(), 'Inputfield') !== 0) continue;
if($module instanceof ModulePlaceholder) {
$module = $modules->getModule($module->className(), array('noInit' => true));
}
if($module instanceof InputfieldSelect || $module instanceof InputfieldHasSelectableOptions) {
$name = str_replace('Inputfield', '', $module->className());
if($module instanceof InputfieldHasSortableValue) {
$name .= " ($labelSortable)";
} else if($module instanceof InputfieldSelectMultiple) {
$name .= " ($labelMulti)";
} else {
$name .= " ($labelSingle)";
}
$f->addOption($module->className(), $name);
}
}
$f->addOptions($this->fieldtype->getInputfieldClassOptions());
$value = $field->get('inputfieldClass');
if(!$value) $value = 'InputfieldSelect';
$f->attr('value', $value);
$inputfields->add($f);
/** @var InputfieldTextarea $f */
$f = $modules->get('InputfieldTextarea');
$f->attr('name', '_options');
$f->label = $this->_('What are the selectable options?');
@@ -206,6 +197,7 @@ class SelectableOptionConfig extends Wire {
$inputfieldClass = $field->get('inputfieldClass');
if($options->count() && $inputfieldClass && $f = $modules->get($inputfieldClass)) {
/** @var InputfieldSelect $f */
$f->attr('name', 'initValue');
$f->label = $this->_('What options do you want pre-selected? (if any)');
$f->collapsed = Inputfield::collapsedBlank;

View File

@@ -133,6 +133,20 @@ class FieldtypePage extends FieldtypeMulti implements Module, ConfigurableModule
return $inputfield;
}
/**
* Get setup options and setup functions for new fields
*
* @return array
* @since 3.0.213
*
*/
public function ___getFieldSetups() {
$setups = parent::___getFieldSetups();
/** @var InputfieldPage $f */
$f = $this->wire()->modules->getModule('InputfieldPage', array('noInit' => true));
return array_merge($setups, $f->getFieldSetups());
}
/**
* Per the Fieldtype interface, Save the given Field from the given Page to the database
*

View File

@@ -292,6 +292,34 @@ class FieldtypeTextarea extends FieldtypeText {
$inputfield->class = $this->className();
return $inputfield;
}
/**
* Get setup options and setup functions for new fields
*
* @return array
* @since 3.0.213
*
*/
public function ___getFieldSetups() {
$class = $this->className();
$setups = parent::___getFieldSetups();
if($class !== 'FieldtypeTextarea' && $class !== 'FieldtypeTextareaLanguage') {
// limit setups options to the base types
return $setups;
}
$setups['default'] = array('title' => 'Textarea');
$modules = $this->wire()->modules;
$editors = array('CKEditor', 'TinyMCE');
foreach($editors as $name) {
if($modules->isInstalled("Inputfield$name")) $setups[$name] = array(
'title' => $name,
'inputfieldClass' => "Inputfield$name",
'contentType' => self::contentTypeHTML,
'textformatters' => array()
);
}
return $setups;
}
/**
* Get database schema used by the Field

View File

@@ -1375,36 +1375,14 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
$field->required = true;
$field->icon = 'plug';
$inputfieldSelection = $field;
$options = $this->getInputfieldOptions();
$pageListTypes = $options['pageListTypes'];
$singles = array();
$multiples = array();
$sortables = array();
$pageListTypes = array();
$inputfieldClasses = $this->inputfieldClasses;
if($this->hasFieldtype) $inputfieldClasses = array_merge(self::$defaultInputfieldClasses, $inputfieldClasses);
foreach($inputfieldClasses as $class) {
$module = $modules->getModule($class, array('noInit' => true));
$info = $modules->getModuleInfo($module);
$label = ucfirst((string) $info['title']);
if($module instanceof InputfieldPageListSelection) {
$pageListTypes[] = $class;
}
if($module instanceof InputfieldHasSortableValue) {
$sortables[$class] = $label;
} else if($module instanceof InputfieldHasArrayValue || $module instanceof InputfieldSupportsArrayValue) {
$multiples[$class] = $label;
} else {
$singles[$class] = $label;
}
if($class == 'InputfieldPageAutocomplete') $singles["_$class"] = $label;
}
$multiLabel = $this->_('Multiple page selection');
$field->addOption($this->_('Single page selection'), $singles);
$field->addOption($multiLabel, $multiples);
$field->addOption($multiLabel . ' (' . $this->_('sortable') . ')', $sortables);
$field->addOption($this->_('Single page selection'), $options['singles']);
$field->addOption($multiLabel, $options['multiples']);
$field->addOption($multiLabel . ' (' . $this->_('sortable') . ')', $options['sortables']);
$inputfields->insertBefore($field, $selectablePagesFieldset);
if($this->hasFieldtype === false) {
@@ -1501,6 +1479,85 @@ class InputfieldPage extends Inputfield implements ConfigurableModule {
return $inputfields;
}
/**
* Get options available for page selection Inputfields
*
* @return array
* @since 3.0.213
*
*/
public function getInputfieldOptions() {
$modules = $this->wire()->modules;
$singles = array();
$multiples = array();
$sortables = array();
$pageListTypes = array();
$inputfieldClasses = $this->inputfieldClasses;
if($this->hasFieldtype) $inputfieldClasses = array_merge(self::$defaultInputfieldClasses, $inputfieldClasses);
foreach($inputfieldClasses as $class) {
$module = $modules->getModule($class, array('noInit' => true));
$info = $modules->getModuleInfo($module);
$label = ucfirst((string) $info['title']);
if($module instanceof InputfieldPageListSelection) {
$pageListTypes[] = $class;
}
if($module instanceof InputfieldHasSortableValue) {
$sortables[$class] = $label;
} else if($module instanceof InputfieldHasArrayValue || $module instanceof InputfieldSupportsArrayValue) {
$multiples[$class] = $label;
} else {
$singles[$class] = $label;
}
if($class == 'InputfieldPageAutocomplete') $singles["_$class"] = $label;
}
return array(
'singles' => $singles,
'multiples' => $multiples,
'sortables' => $sortables,
'pageListTypes' => $pageListTypes,
);
}
/**
* Get recommended setups for FieldtypePage/InputfieldPage
*
* @return array
* @since 3.0.213
*
*/
public function getFieldSetups() {
$setups = array();
$options = $this->getInputfieldOptions();
$singleLabel = $this->_('Single page:');
$multiLabel = $this->_('Multiple pages:');
$sortLabel = $this->_('Multiple sortable pages:');
foreach($options['singles'] as $class => $label) {
$name = str_replace('Inputfield', '', $class);
$setups[$name] = array(
'title' => "$singleLabel $label",
'derefAsPage' => FieldtypePage::derefAsPageOrNullPage,
'inputfield' => $class,
);
}
foreach(array_merge($options['multiples'], $options['sortables']) as $class => $label) {
$name = str_replace('Inputfield', '', $class);
$label = isset($options['sortables'][$class]) ? "$sortLabel $label" : "$multiLabel $label";
$setups[$name] = array(
'title' => $label,
'derefAsPage' => FieldtypePage::derefAsPageArray,
'inputfield' => $class,
);
}
return $setups;
}
/**
* Get module configuration Inputfields
*