1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-22 14:23:05 +02:00

Fix issue processwire/processwire-issues#1082 as well as improve error handling when one places a fieldset closer before its opener

This commit is contained in:
Ryan Cramer
2020-07-27 13:07:40 -04:00
parent b466e4fb99
commit 475ae801d1
2 changed files with 106 additions and 6 deletions

View File

@@ -113,6 +113,60 @@ class FieldtypeFieldsetOpen extends Fieldtype {
return $field->type instanceof FieldtypeFieldsetOpen && !($field->type instanceof FieldtypeFieldsetClose); return $field->type instanceof FieldtypeFieldsetOpen && !($field->type instanceof FieldtypeFieldsetClose);
} }
/**
* Check that Fieldgroup has matching open/close fieldsets and in correct order
*
* @param Fieldgroup $fieldgroup
* @return bool
* @since 3.0.164
*
*/
public function checkFieldgroupFieldsets(Fieldgroup $fieldgroup) {
list($openers, $closers, $isChanged) = array(array(), array(), false);
foreach($fieldgroup as $field) {
/** @var Fieldtype $fieldtype */
if(!$field->type instanceof FieldtypeFieldsetOpen) continue;
if($field->type instanceof FieldtypeFieldsetClose) {
if(!strpos($field->name, self::fieldsetCloseIdentifier)) continue;
$name = substr($field->name, 0, -1 * strlen(self::fieldsetCloseIdentifier));
$closers[$name] = $field;
} else if(!isset($closers[$field->name])) {
// ensure opener comes before closer, otherwise only closer remains
$openers[$field->name] = $field;
}
}
if(count($openers) === count($closers)) return true;
foreach($openers as $name => $opener) {
/** @var Field $opener */
if(isset($closers[$name])) continue;
$closer = $this->getFieldsetCloseField($opener);
if($closer) {
$fieldgroup->insertAfter($closer, $opener);
} else {
$fieldgroup->remove($opener);
}
$isChanged = true;
}
foreach($closers as $name => $closer) {
/** @var Field $closer */
if(isset($openers[$name])) continue;
$opener = $this->getFieldsetOpenField($closer);
if($opener) {
$fieldgroup->insertBefore($opener, $closer);
} else {
$fieldgroup->remove($closer);
}
$isChanged = true;
}
return $isChanged;
}
/** /**
* Get the Field that closes/terminates the given Fieldset field * Get the Field that closes/terminates the given Fieldset field
* *
@@ -123,7 +177,7 @@ class FieldtypeFieldsetOpen extends Fieldtype {
*/ */
public function getFieldsetCloseField(Field $field, $createIfNotExists = false) { public function getFieldsetCloseField(Field $field, $createIfNotExists = false) {
if(!$this->isFieldset($field)) return; if(!$this->isFieldset($field)) return null;
$name = $field->name . self::fieldsetCloseIdentifier; $name = $field->name . self::fieldsetCloseIdentifier;
$closer = $this->wire('fields')->get($name); $closer = $this->wire('fields')->get($name);
@@ -155,6 +209,35 @@ class FieldtypeFieldsetOpen extends Fieldtype {
return $closer; return $closer;
} }
/**
* Get the Field that opens the given FieldsetClose field
*
* @param Field $field
* @return null|Field of type FieldtypeFieldsetOpen, if found
* @since 3.0.164
*
*/
public function getFieldsetOpenField(Field $field) {
if(!$field->type instanceof FieldtypeFieldsetClose) return null;
if(!strpos($field->name, self::fieldsetCloseIdentifier)) return null;
$name = substr($field->name, 0, -1 * strlen(self::fieldsetCloseIdentifier));
$opener = $this->wire()->fields->get($name);
if($opener) return $opener;
foreach($this->wire()->fields as $f) {
if(!$f->type instanceof FieldtypeFieldsetOpen) continue;
$closeFieldID = (int) $f->get('closeFieldID');
if($closeFieldID != $field->id) continue;
$opener = $f;
break;
}
return $opener;
}
/** /**
* Hook executed when field is added via ProcessField * Hook executed when field is added via ProcessField
* *

View File

@@ -2756,9 +2756,14 @@ class ProcessTemplate extends Process {
} }
} }
if(count($badFieldsets)) {
foreach($badFieldsets as $field) { foreach($badFieldsets as $field) {
$this->error(sprintf($this->_('Error with placement of fieldset/tab "%s" - please fix and save again'), $field->name)); $this->error(sprintf($this->_('Error with placement of fieldset/tab "%s" - please fix and save again'), $field->name));
} }
/** @var FieldtypeFieldsetOpen $fieldset */
$fieldset = $this->wire()->fieldtypes->get('FieldtypeFieldsetOpen');
if($fieldset->checkFieldgroupFieldsets($this->template->fieldgroup)) $saveFieldgroup = true;
}
} }
// check if any other fieldgroup should be imported // check if any other fieldgroup should be imported
@@ -2921,6 +2926,7 @@ class ProcessTemplate extends Process {
$removeIds = $this->wire('input')->get('fields'); $removeIds = $this->wire('input')->get('fields');
if(empty($removeIds)) $this->session->redirect('./'); if(empty($removeIds)) $this->session->redirect('./');
$removeIds = explode(',', $removeIds); $removeIds = explode(',', $removeIds);
$removeFields = array();
$fieldgroup = $this->template->fieldgroup; $fieldgroup = $this->template->fieldgroup;
$this->wire('processHeadline', sprintf($this->_('Remove Fields from Template: %s'), $this->template->name)); $this->wire('processHeadline', sprintf($this->_('Remove Fields from Template: %s'), $this->template->name));
@@ -2942,6 +2948,17 @@ class ProcessTemplate extends Process {
foreach($fieldgroup as $field) { foreach($fieldgroup as $field) {
if(!in_array($field->id, $removeIds)) continue; if(!in_array($field->id, $removeIds)) continue;
$removeFields[$field->id] = $field;
if($field->type instanceof FieldtypeFieldsetClose) {
$opener = $field->type->getFieldsetOpenField($field);
if($opener && $fieldgroup->hasField($opener) && !in_array($opener->id, $removeIds)) {
unset($removeFields[$field->id]);
$removeFields[$opener->id] = $opener;
}
}
}
foreach($removeFields as $field) {
$checkboxes->addOption($field->id, sprintf($this->_('Remove field "%1$s" from template "%2$s"'), $field->name, $this->template->name)); $checkboxes->addOption($field->id, sprintf($this->_('Remove field "%1$s" from template "%2$s"'), $field->name, $this->template->name));
} }