mirror of
https://github.com/processwire/processwire.git
synced 2025-08-09 16:26:59 +02:00
Add Setup>Fields>Export/Import support for Repeater fields. processwire/processwire-issues#416
This commit is contained in:
@@ -177,7 +177,7 @@ class Fieldgroup extends WireArray implements Saveable, Exportable, HasLookupIte
|
||||
* #pw-internal
|
||||
*
|
||||
* @param Field $field
|
||||
* @return Fieldgroup $this
|
||||
* @return Fieldgroup|WireArray $this
|
||||
*
|
||||
*/
|
||||
public function finishRemove(Field $field) {
|
||||
@@ -194,7 +194,7 @@ class Fieldgroup extends WireArray implements Saveable, Exportable, HasLookupIte
|
||||
* #pw-group-manipulation
|
||||
*
|
||||
* @param Field|string|int $field Field object, name or id.
|
||||
* @return Fieldgroup $this
|
||||
* @return bool|Fieldgroup|WireArray
|
||||
*
|
||||
*/
|
||||
public function softRemove($field) {
|
||||
@@ -379,7 +379,7 @@ class Fieldgroup extends WireArray implements Saveable, Exportable, HasLookupIte
|
||||
*
|
||||
* @param string $key Name of property to set
|
||||
* @param string|int|object $value Value of property
|
||||
* @return Fieldgroup $this
|
||||
* @return Fieldgroup|WireArray $this
|
||||
* @throws WireException if passed invalid data
|
||||
*
|
||||
*/
|
||||
@@ -448,7 +448,9 @@ class Fieldgroup extends WireArray implements Saveable, Exportable, HasLookupIte
|
||||
*
|
||||
*/
|
||||
public function getExportData() {
|
||||
return $this->wire('fieldgroups')->getExportData($this);
|
||||
/** @var Fieldgroups $fieldgroups */
|
||||
$fieldgroups = $this->wire('fieldgroups');
|
||||
return $fieldgroups->getExportData($this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -469,7 +471,9 @@ class Fieldgroup extends WireArray implements Saveable, Exportable, HasLookupIte
|
||||
*
|
||||
*/
|
||||
public function setImportData(array $data) {
|
||||
return $this->wire('fieldgroups')->setImportData($this, $data);
|
||||
/** @var Fieldgroups $fieldgroups */
|
||||
$fieldgroups = $this->wire('fieldgroups');
|
||||
return $fieldgroups->setImportData($this, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -640,7 +644,9 @@ class Fieldgroup extends WireArray implements Saveable, Exportable, HasLookupIte
|
||||
*
|
||||
*/
|
||||
public function getTemplates() {
|
||||
return $this->wire('fieldgroups')->getTemplates($this);
|
||||
/** @var Fieldgroups $fieldgroups */
|
||||
$fieldgroups = $this->wire('fieldgroups');
|
||||
return $fieldgroups->getTemplates($this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -147,20 +147,11 @@ class Fieldgroups extends WireSaveableItemsLookup {
|
||||
if($item->id && $item->removedFields) {
|
||||
|
||||
foreach($this->wire('templates') as $template) {
|
||||
|
||||
if($template->fieldgroup->id !== $item->id) continue;
|
||||
|
||||
foreach($item->removedFields as $field) {
|
||||
|
||||
// make sure the field is valid to delete from this template
|
||||
if(($field->flags & Field::flagGlobal) && !$template->noGlobal) {
|
||||
throw new WireException("Field '$field' may not be removed from fieldgroup '{$item->name}' because it is globally required (Field::flagGlobal)");
|
||||
}
|
||||
|
||||
if($field->flags & Field::flagPermanent) {
|
||||
throw new WireException("Field '$field' may not be removed from fieldgroup '{$item->name}' because it is permanent.");
|
||||
}
|
||||
|
||||
$error = $this->isFieldNotRemoveable($field, $item, $template);
|
||||
if($error !== false) throw new WireException("$error Save of fieldgroup changes aborted.");
|
||||
if($field->type) $field->type->deleteTemplateField($template, $field);
|
||||
$item->finishRemove($field);
|
||||
}
|
||||
@@ -206,7 +197,7 @@ class Fieldgroups extends WireSaveableItemsLookup {
|
||||
* Also deletes the references in fieldgroups_fields table
|
||||
*
|
||||
* @param Saveable|Fieldgroup $item
|
||||
* @return Fieldgroups $this
|
||||
* @return bool
|
||||
* @throws WireException
|
||||
*
|
||||
*/
|
||||
@@ -218,7 +209,10 @@ class Fieldgroups extends WireSaveableItemsLookup {
|
||||
}
|
||||
|
||||
if(count($templates)) {
|
||||
throw new WireException("Can't delete fieldgroup '{$item->name}' because it is in use by template(s): " . implode(', ', $templates));
|
||||
throw new WireException(
|
||||
"Can't delete fieldgroup '{$item->name}' because it is in use by template(s): " .
|
||||
implode(', ', $templates)
|
||||
);
|
||||
}
|
||||
|
||||
return parent::___delete($item);
|
||||
@@ -272,7 +266,8 @@ class Fieldgroups extends WireSaveableItemsLookup {
|
||||
$contexts = $fieldgroup->getFieldContextArray();
|
||||
$numSaved = 0;
|
||||
foreach($contexts as $fieldID => $context) {
|
||||
$field = $fieldgroup->getFieldContext($fieldID);
|
||||
$field = $fieldgroup->getFieldContext((int) $fieldID);
|
||||
if(!$field) continue;
|
||||
if($this->wire('fields')->saveFieldgroupContext($field, $fieldgroup)) $numSaved++;
|
||||
}
|
||||
return $numSaved;
|
||||
@@ -454,5 +449,35 @@ class Fieldgroups extends WireSaveableItemsLookup {
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the given Field not allowed to be removed from given Template?
|
||||
*
|
||||
* #pw-internal
|
||||
*
|
||||
* @param Field $field
|
||||
* @param Template $template
|
||||
* @param Fieldgroup $fieldgroup
|
||||
* @return bool|string Returns error message string if not removeable or boolean false if it is removeable
|
||||
*
|
||||
*/
|
||||
public function isFieldNotRemoveable(Field $field, Fieldgroup $fieldgroup, Template $template = null) {
|
||||
|
||||
if(is_null($template)) $template = $this->wire('templates')->get($fieldgroup->name);
|
||||
|
||||
if(($field->flags & Field::flagGlobal) && (!$template || !$template->noGlobal)) {
|
||||
return
|
||||
"Field '$field' may not be removed from fieldgroup '{$this->name}' " .
|
||||
"because it is globally required (Field::flagGlobal).";
|
||||
}
|
||||
|
||||
if($field->flags & Field::flagPermanent) {
|
||||
return
|
||||
"Field '$field' may not be removed from fieldgroup '{$this->name}' " .
|
||||
"because it is permanent (Field::flagPermanent).";
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@@ -1718,6 +1718,113 @@ class FieldtypeRepeater extends Fieldtype implements ConfigurableModule {
|
||||
return $field;
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Export configuration values for external consumption
|
||||
*
|
||||
* Use this method to externalize any config values when necessary.
|
||||
* For example, internal IDs should be converted to GUIDs where possible.
|
||||
* Most Fieldtype modules can use the default implementation already provided here.
|
||||
*
|
||||
* #pw-group-configuration
|
||||
*
|
||||
* @param Field $field
|
||||
* @param array $data
|
||||
* @return array
|
||||
*
|
||||
*/
|
||||
public function ___exportConfigData(Field $field, array $data) {
|
||||
|
||||
$data = parent::___exportConfigData($field, $data);
|
||||
|
||||
$template = $this->wire('templates')->get((int) $data['template_id']);
|
||||
|
||||
$data['template_id'] = 0;
|
||||
$data['parent_id'] = 0;
|
||||
$data['repeaterFields'] = array();
|
||||
$data['fieldContexts'] = array();
|
||||
|
||||
foreach($field->get('repeaterFields') as $fid) {
|
||||
$f = $this->wire('fields')->get((int) $fid);
|
||||
if(!$f) continue;
|
||||
$data['repeaterFields'][] = $f->name;
|
||||
$data['fieldContexts'][$f->name] = $template->fieldgroup->getFieldContextArray($f->id);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an array of exported data to a format that will be understood internally
|
||||
*
|
||||
* This is the opposite of the exportConfigData() method.
|
||||
* Most modules can use the default implementation provided here.
|
||||
*
|
||||
* #pw-group-configuration
|
||||
*
|
||||
* @param Field $field
|
||||
* @param array $data
|
||||
* @return array Data as given and modified as needed. Also included is $data[errors], an associative array
|
||||
* indexed by property name containing errors that occurred during import of config data.
|
||||
*
|
||||
*/
|
||||
public function ___importConfigData(Field $field, array $data) {
|
||||
|
||||
if(!$field->type instanceof FieldtypeRepeater) return $data;
|
||||
|
||||
$errors = array();
|
||||
$repeaterFields = array();
|
||||
$saveFieldgroup = false;
|
||||
$saveFieldgroupContext = false;
|
||||
$template = $field->id ? $this->getRepeaterTemplate($field) : null;
|
||||
|
||||
if(!empty($data['repeaterFields'])) {
|
||||
foreach($data['repeaterFields'] as $name) {
|
||||
$f = $this->wire('fields')->get($name);
|
||||
if(!$f || !$f instanceof Field) {
|
||||
$errors[] = "Unable to locate field to add to repeater: $name";
|
||||
continue;
|
||||
}
|
||||
$repeaterFields[] = $f->id;
|
||||
}
|
||||
$data['repeaterFields'] = $repeaterFields;
|
||||
}
|
||||
|
||||
if($template && !empty($data['fieldContexts'])) {
|
||||
foreach($data['fieldContexts'] as $name => $contextData) {
|
||||
$f = $this->wire('fields')->get($name);
|
||||
if(!$f || !$f instanceof Field) continue;
|
||||
if($template->fieldgroup->hasField($f)) {
|
||||
$f = $template->fieldgroup->getFieldContext($f->name);
|
||||
}
|
||||
$template->fieldgroup->add($f);
|
||||
$saveFieldgroup = true;
|
||||
if(!empty($contextData)) {
|
||||
$template->fieldgroup->setFieldContextArray($f->id, $contextData);
|
||||
$saveFieldgroupContext = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($template) {
|
||||
if($saveFieldgroupContext) {
|
||||
$template->fieldgroup->saveContext();
|
||||
}
|
||||
if($saveFieldgroup) {
|
||||
$template->fieldgroup->save();
|
||||
}
|
||||
}
|
||||
|
||||
unset($data['fieldContexts']);
|
||||
|
||||
$data = parent::___importConfigData($field, $data);
|
||||
|
||||
if(count($errors)) {
|
||||
$data['errors'] = array_merge($data['errors'], array('repeaterFields' => $errors));
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return configuration fields definable for each FieldtypePage
|
||||
|
@@ -777,6 +777,7 @@ class InputfieldRepeater extends Inputfield implements InputfieldItemList {
|
||||
$depthName = "depth_repeater{$page->id}";
|
||||
|
||||
if($input->$deleteName == $page->id) {
|
||||
// @todo add check to Fieldgroups::isFieldNotRemoveable() before attempting remove
|
||||
$value->remove($page);
|
||||
$numChanges++;
|
||||
continue;
|
||||
|
Reference in New Issue
Block a user