1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-10 00:37:02 +02:00

Add support for custom configuration of what Fieldtype/Inputfield settings may be overridden for field/template context. Appears only in $config->advanced mode. You can see it when editing a field (ProcessField) on the "Overrides" tab. Related to processwire/processwire-requests#145

This commit is contained in:
Ryan Cramer
2017-12-22 11:11:02 -05:00
parent 63229872a0
commit f573473066
2 changed files with 148 additions and 42 deletions

View File

@@ -31,6 +31,7 @@
* @property array $viewRoles Role IDs with view access, applicable only if access control is enabled. #pw-group-access
* @property array|null $orderByCols Columns that WireArray values are sorted by (default=null), Example: "sort" or "-created". #pw-internal
* @property int|null $paginationLimit Used by paginated WireArray values to indicate limit to use during load. #pw-internal
* @property array $allowContexts Names of settings that are custom configured to be allowed for context. #pw-group-properties
*
* Common Inputfield properties that Field objects store:
* @property int|bool|null $required Whether or not this field is required during input #pw-group-properties
@@ -341,16 +342,17 @@ class Field extends WireData implements Saveable, Exportable {
*/
public function get($key) {
if($key == 'viewRoles') return $this->viewRoles;
else if($key == 'editRoles') return $this->editRoles;
else if($key == 'table') return $this->getTable();
else if($key == 'prevTable') return $this->prevTable;
else if($key == 'prevFieldtype') return $this->prevFieldtype;
else if(isset($this->settings[$key])) return $this->settings[$key];
else if($key == 'icon') return $this->getIcon(true);
else if($key == 'useRoles') return ($this->settings['flags'] & self::flagAccess) ? true : false;
else if($key == 'flags') return $this->settings['flags'];
else if($key == 'editRoles') return $this->editRoles;
else if($key == 'table') return $this->getTable();
else if($key == 'prevTable') return $this->prevTable;
else if($key == 'prevFieldtype') return $this->prevFieldtype;
else if(isset($this->settings[$key])) return $this->settings[$key];
else if($key == 'icon') return $this->getIcon(true);
else if($key == 'useRoles') return ($this->settings['flags'] & self::flagAccess) ? true : false;
else if($key == 'flags') return $this->settings['flags'];
$value = parent::get($key);
if($key === 'allowContexts' && !is_array($value)) $value = array();
if(is_array($this->trackGets)) $this->trackGets($key);
return $value;
}
@@ -916,6 +918,7 @@ class Field extends WireData implements Saveable, Exportable {
if($fieldgroupContext) {
$allowContext = $this->type->getConfigAllowContext($this);
if(!is_array($allowContext)) $allowContext = array();
$allowContext = array_merge($allowContext, $this->allowContexts);
} else {
$allowContext = array();
}
@@ -926,6 +929,8 @@ class Field extends WireData implements Saveable, Exportable {
if(!$fieldgroupContext) $inputfields->head = $this->_('Field type details');
$inputfields->attr('title', $this->_('Details'));
$inputfields->attr('id+name', 'fieldtypeConfig');
$remainingNames = array();
foreach($allowContext as $name) $remainingNames[$name] = $name;
try {
$fieldtypeInputfields = $this->type->getConfigInputfields($this);
@@ -940,7 +945,19 @@ class Field extends WireData implements Saveable, Exportable {
foreach($fieldtypeInputfields as $inputfield) {
if($fieldgroupContext && !in_array($inputfield->name, $allowContext)) continue;
$inputfields->append($inputfield);
unset($remainingNames[$inputfield->name]);
}
// now capture those that may have been stuck in a fieldset
if($fieldgroupContext) {
foreach($remainingNames as $name) {
if($inputfields->getChildByName($name)) continue;
$inputfield = $fieldtypeInputfields->getChildByName($name);
if(!$inputfield) continue;
$inputfields->append($inputfield);
unset($remainingNames[$inputfield->name]);
}
}
} catch(\Exception $e) {
$this->trackException($e, false, true);
}
@@ -955,11 +972,15 @@ class Field extends WireData implements Saveable, Exportable {
if($inputfield) {
if($fieldgroupContext) {
$allowContext = array('visibility', 'collapsed', 'columnWidth', 'required', 'requiredIf', 'showIf');
$allowContext = array_merge($allowContext, $inputfield->getConfigAllowContext($this));
$allowContext = array_merge($allowContext, $this->allowContexts, $inputfield->getConfigAllowContext($this));
} else {
$allowContext = array();
$inputfields->head = $this->_('Input field settings');
}
$remainingNames = array();
foreach($allowContext as $name) {
$remainingNames[$name] = $name;
}
$inputfields->attr('title', $this->_('Input'));
$inputfields->attr('id+name', 'inputfieldConfig');
$inputfieldInputfields = $inputfield->getConfigInputfields();
@@ -974,6 +995,16 @@ class Field extends WireData implements Saveable, Exportable {
foreach($inputfieldInputfields as $i) {
if($fieldgroupContext && !in_array($i->name, $allowContext)) continue;
$inputfields->append($i);
unset($remainingNames[$i->name]);
}
if($fieldgroupContext) {
foreach($remainingNames as $name) {
if($inputfields->getChildByName($name)) continue;
$inputfield = $inputfieldInputfields->getChildByName($name);
if(!$inputfield) continue;
$inputfields->append($inputfield);
unset($remainingNames[$inputfield->name]);
}
}
}

View File

@@ -911,7 +911,8 @@ class ProcessField extends Process implements ConfigurableModule {
if(!$fieldgroup->hasFieldContext($field->name, $this->contextNamespace)) continue;
$allChanges[$fieldgroup->name] = $this->getContextChanges($form, $field, $fieldgroup);
}
if(!count($allChanges)) return;
if(!count($allChanges) && !$this->wire('config')->advanced) return;
$tab = $this->wire(new InputfieldWrapper());
$tab->attr('title', $this->_('Overrides'));
@@ -932,43 +933,117 @@ class ProcessField extends Process implements ConfigurableModule {
$f->notes = $this->_('To edit an override setting or override other settings, edit any template and click the field name in the fields list.');
}
$tab->add($f);
if(count($allChanges)) {
/** @var MarkupAdminDataTable $table */
$table = $this->wire('modules')->get('MarkupAdminDataTable');
$table->setEncodeEntities(false);
$table->setSortable(false);
$header = array();
if(!$this->fieldgroup) $header[] = $this->_x('Template', 'context-thead');
$header[] = $this->_x('Setting', 'context-thead');
$header[] = $this->_x('Original', 'context-thead');
$header[] = $this->_x('Override', 'context-thead');
$header[] = "<i class='fa fa-fw fa-lg fa-trash override-select-all'></i>";
$table->headerRow($header);
$sanitizer = $this->wire('sanitizer');
$lastFieldgroupName = '';
$this->wire('modules')->get('JqueryUI')->use('modal');
foreach($allChanges as $fieldgroupName => $changes) {
$fieldgroup = $this->wire('fieldgroups')->get($fieldgroupName);
foreach($changes as $key => $change) {
$a = $fieldgroupName;
// $a = "<a class='pw-modal' data-buttons='#Inputfield_submit_save_field' data-autoclose='1' " .
// "href='./edit?id={$this->field->id}&fieldgroup_id=$fieldgroup->id'>$fieldgroupName</a>";
$fieldgroupLabel = $fieldgroupName == $lastFieldgroupName ? '' : $a;
$row = array();
if(!$this->fieldgroup) $row[] = $fieldgroupLabel;
$row[] = $sanitizer->entities($change['label']);
$row[] = "<del>" . $sanitizer->entities($change['originalValue']) . "</del>";
$row[] = $sanitizer->entities($change['value']);
$row[] = "<input type='checkbox' name='_remove_context[]' value='$fieldgroup->id:$key' />";
$options = $fieldgroupLabel ? array('separator' => true) : array();
$table->row($row, $options);
$lastFieldgroupName = $fieldgroupName;
}
}
$f->value = $table->render();
} else {
$f->value = '<p>' . $this->_('There are currently no settings being overridden by template.') . '</p>';
$f->collapsed = Inputfield::collapsedYes;
}
/** @var MarkupAdminDataTable $table */
$table = $this->wire('modules')->get('MarkupAdminDataTable');
$table->setEncodeEntities(false);
$table->setSortable(false);
$header = array();
if(!$this->fieldgroup) $header[] = $this->_x('Template', 'context-thead');
$header[] = $this->_x('Setting', 'context-thead');
$header[] = $this->_x('Original', 'context-thead');
$header[] = $this->_x('Override', 'context-thead');
$header[] = "<i class='fa fa-trash-o override-select-all'></i>";
$table->headerRow($header);
// allow the following configuration only for advanced mode
if(!$this->wire('config')->advanced) return;
$sanitizer = $this->wire('sanitizer');
$lastFieldgroupName = '';
$this->wire('modules')->get('JqueryUI')->use('modal');
foreach($allChanges as $fieldgroupName => $changes) {
$fieldgroup = $this->wire('fieldgroups')->get($fieldgroupName);
foreach($changes as $key => $change) {
$a = $fieldgroupName;
// $a = "<a class='pw-modal' data-buttons='#Inputfield_submit_save_field' data-autoclose='1' " .
// "href='./edit?id={$this->field->id}&fieldgroup_id=$fieldgroup->id'>$fieldgroupName</a>";
$fieldgroupLabel = $fieldgroupName == $lastFieldgroupName ? '' : $a;
$row = array();
if(!$this->fieldgroup) $row[] = $fieldgroupLabel;
$row[] = $sanitizer->entities($change['label']);
$row[] = "<del>" . $sanitizer->entities($change['originalValue']) . "</del>";
$row[] = $sanitizer->entities($change['value']);
$row[] = "<input type='checkbox' name='_remove_context[]' value='$fieldgroup->id:$key' />";
$options = $fieldgroupLabel ? array('separator' => true) : array();
$table->row($row, $options);
$lastFieldgroupName = $fieldgroupName;
/** @var InputfieldCheckboxes $field */
$field = $this->modules->get('InputfieldCheckboxes');
$field->attr('name', 'allowContexts');
$field->label = $this->_('Allowed overrides');
$field->icon = 'sliders';
$field->description =
$this->_('Checked settings will appear as configuration options when editing this field within the context of a particular template.') . ' ' .
$this->_('**Warning:** doing this for settings beyond those specified by the module author may not always work, or may cause problems.');
$field->table = true;
$field->thead =
$this->_('Label') . '|' .
$this->_('Name') . '|' .
$this->_('Type');
$tabNames = array(
'fieldtypeConfig' => $this->_('Details:'),
'inputfieldConfig' => $this->_('Input:')
);
$exclusions = array(
'collapsed',
'showIf',
'required',
'requiredIf',
'columnWidth',
'visibility',
'themeOffset',
'themeBorder',
'themeColor',
);
$fieldtypeNames = $this->field->type->getConfigAllowContext($this->field);
if(!is_array($fieldtypeNames)) $fieldtypeNames = array();
$dummyPage = $this->wire('pages')->get("/"); // only using this to satisfy param requirement
$inputfieldNames = $this->field->getInputfield($dummyPage)->getConfigAllowContext($this->field);
if(!is_array($inputfieldNames)) $inputfieldNames = array();
$alwaysSelected = array_merge($fieldtypeNames, $inputfieldNames);
$allowContexts = $this->field->get('allowContexts');
$alwaysSelected = array_diff($alwaysSelected, $allowContexts);
$qty = 0;
foreach($tabNames as $tabName => $tabLabel) {
/** @var InputfieldWrapper $tabInputfield */
$tabInputfield = $form->getChildByName($tabName);
if(!$tabInputfield) continue;
foreach($tabInputfield->getAll() as $f) {
$name = $f->name;
if(strpos($name, '_') === 0) continue;
if(in_array($name, $exclusions)) continue;
if($f instanceof InputfieldWrapper || $f instanceof InputfieldMarkup || $f instanceof InputfieldHidden) continue;
$typeName = str_replace('Inputfield', '', $f->className());
$label = str_replace('|', ' ', "$tabLabel $f->label") .
"| [span.detail] $name [/span] " .
"| [span.detail] $typeName [/span]";
if(in_array($name, $alwaysSelected)) {
$field->addOption($name, $label, array('checked' => 'checked', 'disabled' => 'disabled'));
$allowContexts[] = $name;
} else {
$field->addOption($name, $label);
$qty++;
}
}
}
$f->value = $table->render();
$field->attr('value', $allowContexts);
if($qty) $tab->append($field);
}
/*