1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-13 18:24:57 +02:00

Update to allow for Combo fields within Repeaters to support file/image fields

This commit is contained in:
Ryan Cramer
2022-08-28 10:43:44 -04:00
parent cbb5133d46
commit 96dae07160
3 changed files with 51 additions and 27 deletions

View File

@@ -179,14 +179,14 @@ class FieldtypeRepeater extends Fieldtype implements ConfigurableModule {
if($inEditor) { if($inEditor) {
// ProcessPageEdit or ProcessProfile // ProcessPageEdit or ProcessProfile
$this->addHookBefore('ProcessPageEdit::ajaxSave', $this, 'hookProcessPageEditAjaxSave'); $this->addHookBefore('ProcessPageEdit::ajaxSave', $this, 'hookProcessPageEditAjaxSave', array('priority' => 99));
} }
if($inEditor && $config->ajax) { if($inEditor && $config->ajax) {
// handle scenario of repeater within repeater field // handle scenario of repeater within repeater field
$fieldName = (string) $input->get('field'); $fieldName = (string) $input->get('field');
$pageID = (int) $input->get('id'); $pageID = (int) $input->get('id');
if($pageID && strpos($fieldName, '_repeater') && preg_match('/^(.+)_repeater\d+$/', $fieldName, $matches)) { if($pageID && strpos($fieldName, '_repeater') && preg_match('/^(.+)_repeater\d+($|\.)/', $fieldName, $matches)) {
$this->initAllFields(); $this->initAllFields();
$editPage = $this->wire()->pages->get($pageID); $editPage = $this->wire()->pages->get($pageID);
if($editPage->id && strpos($editPage->template->name, self::templateNamePrefix) === 0) { if($editPage->id && strpos($editPage->template->name, self::templateNamePrefix) === 0) {
@@ -348,7 +348,6 @@ class FieldtypeRepeater extends Fieldtype implements ConfigurableModule {
$fieldName = $input->get('field'); $fieldName = $input->get('field');
if($fieldName) { if($fieldName) {
$field = null;
$_fieldName = $fieldName; $_fieldName = $fieldName;
$fieldName = $this->wire()->sanitizer->fieldName($fieldName); $fieldName = $this->wire()->sanitizer->fieldName($fieldName);
if($fieldName === $_fieldName) { if($fieldName === $_fieldName) {
@@ -407,7 +406,7 @@ class FieldtypeRepeater extends Fieldtype implements ConfigurableModule {
foreach($allTemplateNames as $templateId => $templateName) { foreach($allTemplateNames as $templateId => $templateName) {
if(strpos($templateName, self::templateNamePrefix) !== 0) continue; if(strpos($templateName, self::templateNamePrefix) !== 0) continue;
$templateIds[$templateName] = $templateId; $templateIds[$templateName] = $templateId;
foreach($fieldgroups->getFieldNames($templateName) as $fieldId => $fieldName) { foreach($fieldgroups->getFieldNames($templateName) as /* $fieldId => */ $fieldName) {
$fieldNames[$fieldName] = $fieldName; $fieldNames[$fieldName] = $fieldName;
} }
} }
@@ -487,9 +486,11 @@ class FieldtypeRepeater extends Fieldtype implements ConfigurableModule {
// if this isn't a repeater field we're dealing with, then abort // if this isn't a repeater field we're dealing with, then abort
if(!isset($_SERVER['HTTP_X_FIELDNAME'])) return; if(!isset($_SERVER['HTTP_X_FIELDNAME'])) return;
if(!preg_match('/^(.+)(_repeater(\d+))$/', $_SERVER['HTTP_X_FIELDNAME'], $matches)) return; if(strpos($_SERVER['HTTP_X_FIELDNAME'], '_repeater') === false) return;
if(!preg_match('/^(.+)(_repeater(\d+))(?:$|\.)/', $_SERVER['HTTP_X_FIELDNAME'], $matches)) return;
$fieldName = $this->wire()->sanitizer->fieldName($matches[1]); $sanitizer = $this->wire()->sanitizer;
$fieldName = $sanitizer->fieldName($matches[1]);
$repeaterPageID = (int) $matches[3]; $repeaterPageID = (int) $matches[3];
if($repeaterPageID < 1) return; if($repeaterPageID < 1) return;
@@ -513,9 +514,20 @@ class FieldtypeRepeater extends Fieldtype implements ConfigurableModule {
$args[0] = $repeaterPage; $args[0] = $repeaterPage;
$event->arguments = $args; $event->arguments = $args;
// repopulate the server header to be the fieldName (sans _repeater\d+) $ajaxFieldName = $_SERVER['HTTP_X_FIELDNAME'];
$this->ajaxFieldName = $this->wire()->sanitizer->fieldName($_SERVER['HTTP_X_FIELDNAME']); if(strpos($ajaxFieldName, '.')) {
$_SERVER['HTTP_X_FIELDNAME'] = $fieldName; // field.subfield combination, i.e. FieldtypeCombo ajax subfield
list($ajaxFieldName, $ajaxSubfieldName) = explode('.', $ajaxFieldName, 2);
$ajaxFieldName = $sanitizer->fieldName($ajaxFieldName);
$ajaxSubfieldName = $sanitizer->name($ajaxSubfieldName);
$this->ajaxFieldName = $ajaxFieldName;
// repopulate the server header to be the fieldName (sans _repeater\d+)
$_SERVER['HTTP_X_FIELDNAME'] = "$fieldName.$ajaxSubfieldName";
} else {
$this->ajaxFieldName = $sanitizer->fieldName($_SERVER['HTTP_X_FIELDNAME']);
// repopulate the server header to be the fieldName (sans _repeater\d+)
$_SERVER['HTTP_X_FIELDNAME'] = $fieldName;
}
// save a copy for comparison in our hookPageEditable function // save a copy for comparison in our hookPageEditable function
$this->ajaxPage = $repeaterPage; $this->ajaxPage = $repeaterPage;
@@ -543,6 +555,7 @@ class FieldtypeRepeater extends Fieldtype implements ConfigurableModule {
$repeaters = array(); $repeaters = array();
foreach($ownerPage->fieldgroup as $f) { foreach($ownerPage->fieldgroup as $f) {
/** @var Field $f */
if(!$f->type instanceof FieldtypeRepeater) continue; if(!$f->type instanceof FieldtypeRepeater) continue;
$repeaters[$f->name] = $f->name; $repeaters[$f->name] = $f->name;
$grandparent = $this->getRepeaterParent($f); $grandparent = $this->getRepeaterParent($f);
@@ -573,7 +586,7 @@ class FieldtypeRepeater extends Fieldtype implements ConfigurableModule {
// for single item value (i.e. FieldtypeFieldsetPage) // for single item value (i.e. FieldtypeFieldsetPage)
$hasField = $this->isRepeaterItemValidOnPage($repeaterItem, $repeaterItems); $hasField = $this->isRepeaterItemValidOnPage($repeaterItem, $repeaterItems);
} else { } else {
continue; // continue;
} }
} }
@@ -832,13 +845,12 @@ class FieldtypeRepeater extends Fieldtype implements ConfigurableModule {
*/ */
public function ___wakeupValue(Page $page, Field $field, $value) { public function ___wakeupValue(Page $page, Field $field, $value) {
$parent_id = null;
$field_parent_id = $field->get('parent_id'); $field_parent_id = $field->get('parent_id');
$template_id = $field->get('template_id'); $template_id = $field->get('template_id');
// $outputFormatting = $page->outputFormatting(); // $outputFormatting = $page->outputFormatting();
// if it's already in the target format, leave it // if it's already in the target format, leave it
if($value instanceof PageArray) return $value; if(!is_array($value) && $value instanceof PageArray) return $value;
// if this field has no parent set, just return a blank pageArray // if this field has no parent set, just return a blank pageArray
if(!$field_parent_id) return $this->getBlankValue($page, $field); if(!$field_parent_id) return $this->getBlankValue($page, $field);
@@ -983,13 +995,15 @@ class FieldtypeRepeater extends Fieldtype implements ConfigurableModule {
if(!empty($options['minimal']) || !empty($options['FieldtypeRepeater']['minimal'])) { if(!empty($options['minimal']) || !empty($options['FieldtypeRepeater']['minimal'])) {
// minimal export option includes only fields data // minimal export option includes only fields data
foreach($value as $k => $p) { foreach($value as $p) {
/** @var Page $p */ /** @var Page $p */
if($p->isUnpublished()) continue; if($p->isUnpublished()) continue;
$v = array(); $v = array();
foreach($p->template->fieldgroup as $f) { foreach($p->template->fieldgroup as $f) {
/** @var Field $f */
if(!$p->hasField($f)) continue; if(!$p->hasField($f)) continue;
$v[$f->name] = $f->type->exportValue($p, $f, $p->getUnformatted($f->name), $options); $fieldtype = $f->type; /** @var Fieldtype $fieldtype */
$v[$f->name] = $fieldtype->exportValue($p, $f, $p->getUnformatted($f->name), $options);
} }
$a[$p->name] = $v; $a[$p->name] = $v;
} }
@@ -1067,7 +1081,7 @@ class FieldtypeRepeater extends Fieldtype implements ConfigurableModule {
if($commit) { if($commit) {
// create new repeater item, ready to be populated // create new repeater item, ready to be populated
/** @var RepeaterPage $readyPage */ /** @var RepeaterPage $p */
$p = $this->wire(new $repeaterPageClass()); $p = $this->wire(new $repeaterPageClass());
if($repeaterParent->id) $p->parent = $repeaterParent; if($repeaterParent->id) $p->parent = $repeaterParent;
$p->template = $repeaterTemplate; $p->template = $repeaterTemplate;
@@ -1296,7 +1310,7 @@ class FieldtypeRepeater extends Fieldtype implements ConfigurableModule {
if($template->name != $name && !$this->wire()->templates->get($name)) { if($template->name != $name && !$this->wire()->templates->get($name)) {
$this->bd("Renamed repeater template from '$template->name' to '$name'", __FUNCTION__); $this->bd("Renamed repeater template from '$template->name' to '$name'", __FUNCTION__);
$flags = $template->flags; $flags = $template->flags;
$template->flags = Template::flagSystemOverride; $template->flags = Template::flagSystemOverride; // required before flags=0
$template->flags = 0; $template->flags = 0;
$template->save(); $template->save();
$template->name = $name; $template->name = $name;
@@ -1441,7 +1455,6 @@ class FieldtypeRepeater extends Fieldtype implements ConfigurableModule {
public function sanitizeValueString(Page $page, Field $field, $value) { public function sanitizeValueString(Page $page, Field $field, $value) {
$pages = $this->wire()->pages; $pages = $this->wire()->pages;
if($page) {} // ignore
$result = false; $result = false;
if(ctype_digit("$value")) { if(ctype_digit("$value")) {
@@ -1452,7 +1465,7 @@ class FieldtypeRepeater extends Fieldtype implements ConfigurableModule {
// csv string of page IDs // csv string of page IDs
$value = explode(',', $value); $value = explode(',', $value);
$result = array(); $result = array();
foreach($value as $k => $v) { foreach($value as $v) {
$v = (int) $v; $v = (int) $v;
if($v) $result[] = $v; if($v) $result[] = $v;
} }
@@ -1536,7 +1549,10 @@ class FieldtypeRepeater extends Fieldtype implements ConfigurableModule {
($operator == '!=' && $value)) { ($operator == '!=' && $value)) {
$templateIDs = array(); $templateIDs = array();
foreach($field->getTemplates() as $template) $templateIDs[] = (int) $template->id; foreach($field->getTemplates() as $template) {
/** @var Template $template */
$templateIDs[] = (int) $template->id;
}
if(count($templateIDs)) { if(count($templateIDs)) {
$templateIDs = implode(',', $templateIDs); $templateIDs = implode(',', $templateIDs);
$sql = $sql =
@@ -1689,7 +1705,7 @@ class FieldtypeRepeater extends Fieldtype implements ConfigurableModule {
// iterate through each page in the pageArray value // iterate through each page in the pageArray value
// and determine which need to be saved // and determine which need to be saved
foreach($value as $key => $p) { foreach($value as $p) {
/** @var Page|RepeaterPage $p */ /** @var Page|RepeaterPage $p */
if($p->template->id != $template_id) { if($p->template->id != $template_id) {
$value->remove($p); $value->remove($p);
@@ -1832,7 +1848,7 @@ class FieldtypeRepeater extends Fieldtype implements ConfigurableModule {
$templateName = $template->name; $templateName = $template->name;
// remove system flag from the template // remove system flag from the template
$template->flags = Template::flagSystemOverride; $template->flags = Template::flagSystemOverride; // required before flags=0
$template->flags = 0; $template->flags = 0;
// delete the template // delete the template
@@ -2264,7 +2280,7 @@ class FieldtypeRepeater extends Fieldtype implements ConfigurableModule {
$template = $this->getRepeaterTemplate($field); $template = $this->getRepeaterTemplate($field);
$parent = $this->getRepeaterParent($field); $parent = $this->getRepeaterParent($field);
if($this->wire()->input->post->repeaterFields) { if($this->wire()->input->post('repeaterFields')) {
$this->saveConfigInputfields($field, $template, $parent); $this->saveConfigInputfields($field, $template, $parent);
} }
@@ -2283,7 +2299,6 @@ class FieldtypeRepeater extends Fieldtype implements ConfigurableModule {
* *
*/ */
protected function ___saveConfigInputfields(Field $field, Template $template, Page $parent) { protected function ___saveConfigInputfields(Field $field, Template $template, Page $parent) {
if($parent) {} // ignore
$this->initAllFields(); $this->initAllFields();
$helper = $this->getRepeaterConfigHelper($field); $helper = $this->getRepeaterConfigHelper($field);
$helper->saveConfigInputfields($template); $helper->saveConfigInputfields($template);

View File

@@ -514,9 +514,18 @@ $(document).ready(function() {
var configName = $inputfield.attr('data-configName'); var configName = $inputfield.attr('data-configName');
var settings = ProcessWire.config[configName]; var settings = ProcessWire.config[configName];
var options = []; var options = [];
for(var n = 0; n < settings['tags'].length; n++) { if(typeof settings === 'undefined') {
var tag = settings['tags'][n]; if(configName.indexOf('_repeater') > -1) {
options[n] = {value: tag}; configName = configName.replace(/_repeater\d+(_?)/, '$1');
settings = ProcessWire.config[configName];
if(typeof settings === 'undefined') settings = null;
}
}
if(settings) {
for(var n = 0; n < settings['tags'].length; n++) {
var tag = settings['tags'][n];
options[n] = {value: tag};
}
} }
$selects.selectize({ $selects.selectize({
plugins: ['remove_button', 'drag_drop'], plugins: ['remove_button', 'drag_drop'],

View File

@@ -43,7 +43,7 @@ class InputfieldFile extends Inputfield implements InputfieldItemList, Inputfiel
return array( return array(
'title' => __('Files', __FILE__), // Module Title 'title' => __('Files', __FILE__), // Module Title
'summary' => __('One or more file uploads (sortable)', __FILE__), // Module Summary 'summary' => __('One or more file uploads (sortable)', __FILE__), // Module Summary
'version' => 127, 'version' => 128,
'permanent' => true, 'permanent' => true,
); );
} }