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

Fix issue processwire/processwire-issues#1670 plus minor optimizations to template importing

This commit is contained in:
Ryan Cramer
2023-01-26 09:55:19 -05:00
parent 2ebb0055be
commit 47f1e8a089
3 changed files with 101 additions and 53 deletions

View File

@@ -759,7 +759,7 @@ class Template extends WireData implements Saveable, Exportable {
$fieldgroup = $this->wire()->fieldgroups->get($value); $fieldgroup = $this->wire()->fieldgroups->get($value);
if($fieldgroup) { if($fieldgroup) {
$this->setFieldgroup($fieldgroup); $this->setFieldgroup($fieldgroup);
} else { } else if($this->id) {
$this->error("Unable to load fieldgroup '$value' for template $this->name"); $this->error("Unable to load fieldgroup '$value' for template $this->name");
} }
return; return;

View File

@@ -573,6 +573,7 @@ class Templates extends WireSaveableItems {
if($template->fieldgroup) $fieldgroupData = $template->fieldgroup->getExportData(); if($template->fieldgroup) $fieldgroupData = $template->fieldgroup->getExportData();
$data['fieldgroupFields'] = $fieldgroupData['fields']; $data['fieldgroupFields'] = $fieldgroupData['fields'];
$data['fieldgroupContexts'] = $fieldgroupData['contexts']; $data['fieldgroupContexts'] = $fieldgroupData['contexts'];
unset($data['_lazy'], $data['_exportMode']);
$template->set('_exportMode', false); $template->set('_exportMode', false);
return $data; return $data;

View File

@@ -10,11 +10,15 @@
class ProcessTemplateExportImport extends Wire { class ProcessTemplateExportImport extends Wire {
/** @var Templates $items */ /**
* @var Templates|Template[] $items
*
*/
protected $items; protected $items;
public function __construct() { public function wired() {
$this->items = $this->wire('templates'); parent::wired();
$this->items = $this->wire()->templates;
} }
protected function getItem($name) { protected function getItem($name) {
@@ -35,7 +39,8 @@ class ProcessTemplateExportImport extends Wire {
*/ */
protected function getExportData(array $exportTemplates) { protected function getExportData(array $exportTemplates) {
$data = array(); $data = array();
foreach($this->wire('templates') as $template) { foreach($this->items as $template) {
/** @var Template $template */
if(!in_array($template->name, $exportTemplates)) continue; if(!in_array($template->name, $exportTemplates)) continue;
$a = $template->getExportData(); $a = $template->getExportData();
$data[$template->name] = $a; $data[$template->name] = $a;
@@ -46,30 +51,35 @@ class ProcessTemplateExportImport extends Wire {
/** /**
* Execute export * Execute export
* *
* @return string * @return InputfieldForm
* *
*/ */
public function ___buildExport() { public function ___buildExport() {
$form = $this->wire('modules')->get('InputfieldForm'); $modules = $this->wire()->modules;
$input = $this->wire()->input;
/** @var InputfieldForm $form */
$form = $modules->get('InputfieldForm');
$form->action = './'; $form->action = './';
$form->method = 'post'; $form->method = 'post';
$exportTemplates = $this->wire('input')->post('export_templates'); $exportTemplates = $input->post('export_templates');
if(empty($exportTemplates)) { if(empty($exportTemplates)) {
$f = $this->wire('modules')->get('InputfieldSelectMultiple'); /** @var InputfieldSelectMultiple $f */
$f = $modules->get('InputfieldSelectMultiple');
$f->attr('id+name', 'export_templates'); $f->attr('id+name', 'export_templates');
$f->label = $this->_('Select the templates that you want to export'); $f->label = $this->_('Select the templates that you want to export');
$f->icon = 'copy'; $f->icon = 'copy';
$maxName = 0; $maxName = 0;
$maxLabel = 0; $maxLabel = 0;
$numTemplates = 0; $numTemplates = 0;
foreach($this->wire('templates') as $template) { foreach($this->items as $template) {
/** @var Template $template */
if(strlen($template->name) > $maxName) $maxName = strlen($template->name); if(strlen($template->name) > $maxName) $maxName = strlen($template->name);
$label = $template->getLabel(); $label = $template->getLabel();
if(strlen($label) > $maxLabel) $maxLabel = strlen($label); if(strlen($label) > $maxLabel) $maxLabel = strlen($label);
@@ -86,7 +96,7 @@ class ProcessTemplateExportImport extends Wire {
$modified; $modified;
$f->addOption(0, $label, array('disabled' => 'disabled')); $f->addOption(0, $label, array('disabled' => 'disabled'));
foreach($this->wire('templates') as $template) { foreach($this->items as $template) {
//if(!is_object($template->fieldgroup)) $this->error("Template: $template has no fieldgroup"); //if(!is_object($template->fieldgroup)) $this->error("Template: $template has no fieldgroup");
$templateName = $template->name . ' '; $templateName = $template->name . ' ';
$templateLabel = $template->getLabel() . ' '; $templateLabel = $template->getLabel() . ' ';
@@ -105,15 +115,16 @@ class ProcessTemplateExportImport extends Wire {
$f->attr('size', $numTemplates+1); $f->attr('size', $numTemplates+1);
$form->add($f); $form->add($f);
$f = $this->wire('modules')->get('InputfieldSubmit'); /** @var InputfieldSubmit $f */
$f = $modules->get('InputfieldSubmit');
$f->attr('name', 'submit_export'); $f->attr('name', 'submit_export');
$f->attr('value', $this->_x('Export', 'button')); $f->attr('value', $this->_x('Export', 'button'));
$form->add($f); $form->add($f);
} else { } else {
$form = $this->wire('modules')->get('InputfieldForm'); /** @var InputfieldTextarea $f */
$f = $this->wire('modules')->get('InputfieldTextarea'); $f = $modules->get('InputfieldTextarea');
$f->attr('id+name', 'export_data'); $f->attr('id+name', 'export_data');
$f->label = $this->_('Export Data'); $f->label = $this->_('Export Data');
$f->description = $this->_('Copy and paste this data into the "Import" box of another installation.'); $f->description = $this->_('Copy and paste this data into the "Import" box of another installation.');
@@ -121,7 +132,8 @@ class ProcessTemplateExportImport extends Wire {
$f->attr('value', wireEncodeJSON($this->getExportData($exportTemplates), true, true)); $f->attr('value', wireEncodeJSON($this->getExportData($exportTemplates), true, true));
$form->add($f); $form->add($f);
$f = $this->wire('modules')->get('InputfieldButton'); /** @var InputfieldButton $f */
$f = $modules->get('InputfieldButton');
$f->href = './'; $f->href = './';
$f->value = $this->_x('Ok', 'button'); $f->value = $this->_x('Ok', 'button');
$form->add($f); $form->add($f);
@@ -173,18 +185,24 @@ class ProcessTemplateExportImport extends Wire {
* *
*/ */
public function ___buildImport() { public function ___buildImport() {
$modules = $this->wire()->modules;
$session = $this->wire()->session;
$notices = $this->wire()->notices;
$input = $this->wire()->input;
$sanitizer = $this->wire()->sanitizer;
if($this->input->post('submit_commit')) { if($input->post('submit_commit')) {
$this->processImport(); $this->processImport();
return ''; return '';
} }
$verify = (int) $this->input->get('verify'); $verify = (int) $input->get('verify');
if($verify) { if($verify) {
$json = $this->session->get($this, 'importData'); $json = $session->get($this, 'importData');
} else { } else {
$json = $this->input->post('import_data'); $json = $input->post('import_data');
} }
if(!$json) return $this->buildInputDataForm(); if(!$json) return $this->buildInputDataForm();
@@ -192,7 +210,7 @@ class ProcessTemplateExportImport extends Wire {
if(!$data) throw new WireException("Invalid import data"); if(!$data) throw new WireException("Invalid import data");
/** @var InputfieldForm $form */ /** @var InputfieldForm $form */
$form = $this->modules->get('InputfieldForm'); $form = $modules->get('InputfieldForm');
$form->action = './'; $form->action = './';
$form->method = 'post'; $form->method = 'post';
$form->attr('id', 'import_form'); $form->attr('id', 'import_form');
@@ -214,7 +232,6 @@ class ProcessTemplateExportImport extends Wire {
$numErrors = 0; $numErrors = 0;
$numExistingTemplates = 0; $numExistingTemplates = 0;
$numNewTemplates = 0; $numNewTemplates = 0;
$notices = $this->wire('notices');
if(!$verify) $notices->removeAll(); if(!$verify) $notices->removeAll();
@@ -224,16 +241,17 @@ class ProcessTemplateExportImport extends Wire {
$postName = str_replace('-', '__', $name); $postName = str_replace('-', '__', $name);
unset($templateData['id']); unset($templateData['id']);
$new = false; $new = false;
$name = $this->wire('sanitizer')->name($name); $name = $sanitizer->name($name);
$template = $this->wire('templates')->get($name); $template = $this->items->get($name);
$numChangesTemplate = 0; $numChangesTemplate = 0;
/** @var InputfieldFieldset $fieldset */ /** @var InputfieldFieldset $fieldset */
$fieldset = $this->modules->get('InputfieldFieldset'); $fieldset = $modules->get('InputfieldFieldset');
$fieldset->label = $name; $fieldset->label = $name;
$form->add($fieldset); $form->add($fieldset);
if(!$template) { if(!$template) {
$new = true; $new = true;
/** @var Template $template */
$template = $this->wire(new Template()); $template = $this->wire(new Template());
$template->name = $name; $template->name = $name;
$fieldset->icon = 'sun-o'; $fieldset->icon = 'sun-o';
@@ -243,7 +261,7 @@ class ProcessTemplateExportImport extends Wire {
} }
/** @var InputfieldMarkup $markup */ /** @var InputfieldMarkup $markup */
$markup = $this->modules->get('InputfieldMarkup'); $markup = $modules->get('InputfieldMarkup');
$markup->addClass('InputfieldCheckboxes'); $markup->addClass('InputfieldCheckboxes');
$markup->value = ""; $markup->value = "";
$fieldset->add($markup); $fieldset->add($markup);
@@ -257,7 +275,8 @@ class ProcessTemplateExportImport extends Wire {
$this->error($e->getMessage()); $this->error($e->getMessage());
} }
$f = $this->wire('modules')->get('InputfieldCheckboxes'); /** @var InputfieldCheckboxes $f */
$f = $modules->get('InputfieldCheckboxes');
$f->attr('name', "item_$postName"); $f->attr('name', "item_$postName");
$f->label = $this->_('Changes'); $f->label = $this->_('Changes');
$f->table = true; $f->table = true;
@@ -266,6 +285,7 @@ class ProcessTemplateExportImport extends Wire {
$f->thead .= $this->_('New Value'); $f->thead .= $this->_('New Value');
foreach($changes as $property => $info) { foreach($changes as $property => $info) {
if($property === '_lazy' || $property === '_exportMode') continue;
$oldValue = str_replace('|', ' ', $info['old']); $oldValue = str_replace('|', ' ', $info['old']);
$newValue = str_replace('|', ' ', $info['new']); $newValue = str_replace('|', ' ', $info['new']);
@@ -289,12 +309,12 @@ class ProcessTemplateExportImport extends Wire {
$errors = array(); $errors = array();
foreach($notices as $notice) { foreach($notices as $notice) {
if(!$notice instanceof NoticeError) continue; if(!$notice instanceof NoticeError) continue;
$errors[] = $this->wire('sanitizer')->entities1($notice->text); $errors[] = $sanitizer->entities1($notice->text);
$notices->remove($notice); $notices->remove($notice);
} }
if(count($errors)) { if(count($errors)) {
$icon = "<i class='fa fa-exclamation-triangle'></i>"; $icon = wireIconMarkup('exclamation-triangle');
$markup->value .= "<ul class='ui-state-error-text'><li>$icon " . implode("</li><li>$icon ", $errors) . '</li></ul>'; $markup->value .= "<ul class='ui-state-error-text'><li>$icon " . implode("</li><li>$icon ", $errors) . '</li></ul>';
$fieldset->label .= ' (' . sprintf($this->_n('%d notice', '%d notices', count($errors)), count($errors)) . ')'; $fieldset->label .= ' (' . sprintf($this->_n('%d notice', '%d notices', count($errors)), count($errors)) . ')';
$numErrors++; $numErrors++;
@@ -303,9 +323,15 @@ class ProcessTemplateExportImport extends Wire {
//if(!$verify) $notices->removeAll(); //if(!$verify) $notices->removeAll();
if($numChangesTemplate) { if($numChangesTemplate) {
$fieldset->description = sprintf($this->_n('Found %d property to apply.', 'Found %d properties to apply.', $numChangesTemplate), $numChangesTemplate); $fieldset->description = sprintf(
if($new) $numNewTemplates++; $this->_n('Found %d property to apply.', 'Found %d properties to apply.', $numChangesTemplate),
else $numExistingTemplates++; $numChangesTemplate
);
if($new) {
$numNewTemplates++;
} else {
$numExistingTemplates++;
}
} else { } else {
$fieldset->description = $this->_('No changes pending.'); $fieldset->description = $this->_('No changes pending.');
} }
@@ -342,7 +368,7 @@ class ProcessTemplateExportImport extends Wire {
} }
/** @var InputfieldSubmit $f */ /** @var InputfieldSubmit $f */
$f = $this->modules->get('InputfieldSubmit'); $f = $modules->get('InputfieldSubmit');
$f->attr('name', 'submit_commit'); $f->attr('name', 'submit_commit');
$f->attr('value', $this->_('Commit Changes')); $f->attr('value', $this->_('Commit Changes'));
$f->showInHeader(); $f->showInHeader();
@@ -357,16 +383,31 @@ class ProcessTemplateExportImport extends Wire {
} }
/** @var InputfieldButton $f */ /** @var InputfieldButton $f */
$f = $this->modules->get('InputfieldButton'); $f = $modules->get('InputfieldButton');
$f->href = './'; $f->href = './';
$f->value = $this->_x('Ok', 'button'); $f->value = $this->_x('Ok', 'button');
$form->add($f); $form->add($f);
} }
$this->session->set($this, 'importData', $data); $session->set($this, 'importData', $data);
if($numErrors) $this->error(sprintf($this->_n('Notices in %d template', 'Notices in %d templates', $numErrors), $numErrors)); if($numErrors) {
if($numNewTemplates) $this->message(sprintf($this->_n('Found %d new template to add', 'Found %d new templates to add', $numNewTemplates), $numNewTemplates)); $this->error(sprintf(
if($numExistingTemplates) $this->message(sprintf($this->_n('Found %d existing template to update', 'Found %d existing templates to update', $numExistingTemplates), $numExistingTemplates)); $this->_n('Notices in %d template', 'Notices in %d templates', $numErrors),
$numErrors
));
}
if($numNewTemplates) {
$this->message(sprintf(
$this->_n('Found %d new template to add', 'Found %d new templates to add', $numNewTemplates),
$numNewTemplates
));
}
if($numExistingTemplates) {
$this->message(sprintf(
$this->_n('Found %d existing template to update', 'Found %d existing templates to update', $numExistingTemplates),
$numExistingTemplates
));
}
return $form; return $form;
} }
@@ -376,8 +417,12 @@ class ProcessTemplateExportImport extends Wire {
* *
*/ */
protected function ___processImport() { protected function ___processImport() {
$sanitizer = $this->wire()->sanitizer;
$session = $this->wire()->session;
$input = $this->wire()->input;
$data = $this->session->get($this, 'importData'); $data = $session->get($this, 'importData');
if(!$data) throw new WireException("Invalid import data"); if(!$data) throw new WireException("Invalid import data");
$numChangedItems = 0; $numChangedItems = 0;
@@ -387,10 +432,10 @@ class ProcessTemplateExportImport extends Wire {
// iterate through data for each field // iterate through data for each field
foreach($data as $name => $itemData) { foreach($data as $name => $itemData) {
$name = $this->wire('sanitizer')->name($name); $name = $sanitizer->name($name);
$postName = str_replace('-', '__', $name); $postName = str_replace('-', '__', $name);
if(!$this->input->post("import_item_$postName")) { if(!$input->post("import_item_$postName")) {
$skipNames[] = $name; $skipNames[] = $name;
unset($data[$name]); unset($data[$name]);
continue; continue;
@@ -408,14 +453,16 @@ class ProcessTemplateExportImport extends Wire {
unset($itemData['id']); unset($itemData['id']);
foreach($itemData as $property => $value) { foreach($itemData as $property => $value) {
if(!in_array($property, $this->input->post("item_$postName"))) { if(!in_array($property, $input->post("item_$postName"))) {
unset($itemData[$property]); unset($itemData[$property]);
} }
} }
try { try {
$changes = $item->setImportData($itemData); $changes = $item->setImportData($itemData);
foreach($changes as $key => $info) $this->message($this->_('Saved:') . " $name.$key => $info[new]"); foreach($changes as $key => $info) {
$this->message($this->_('Saved:') . " $name.$key => $info[new]");
}
$this->saveItem($item, $changes); $this->saveItem($item, $changes);
if($new) { if($new) {
$numAddedItems++; $numAddedItems++;
@@ -431,14 +478,14 @@ class ProcessTemplateExportImport extends Wire {
$data[$name] = $itemData; $data[$name] = $itemData;
} }
$this->session->set($this, 'skipNames', $skipNames); $session->set($this, 'skipNames', $skipNames);
$this->session->set($this, 'importData', $data); $session->set($this, 'importData', $data);
$numSkippedItems = count($skipNames); $numSkippedItems = count($skipNames);
if($numAddedItems) $this->message(sprintf($this->_n('Added %d item', 'Added %d items', $numAddedItems), $numAddedItems)); if($numAddedItems) $this->message(sprintf($this->_n('Added %d item', 'Added %d items', $numAddedItems), $numAddedItems));
if($numChangedItems) $this->message(sprintf($this->_n('Modified %d item', 'Modified %d items', $numChangedItems), $numChangedItems)); if($numChangedItems) $this->message(sprintf($this->_n('Modified %d item', 'Modified %d items', $numChangedItems), $numChangedItems));
if($numSkippedItems) $this->message(sprintf($this->_n('Skipped %d item', 'Skipped %d items', $numSkippedItems), $numSkippedItems)); if($numSkippedItems) $this->message(sprintf($this->_n('Skipped %d item', 'Skipped %d items', $numSkippedItems), $numSkippedItems));
$this->session->redirect("./?verify=1"); $session->redirect("./?verify=1");
} }
/** /**
@@ -447,16 +494,16 @@ class ProcessTemplateExportImport extends Wire {
* *
*/ */
public function saveItem($item, array $changes) { public function saveItem($item, array $changes) {
if($changes) {} // ignore
/** @var Fieldgroup $fieldgroup */ /** @var Fieldgroup $fieldgroup */
$fieldgroup = $item->fieldgroup; $fieldgroup = $item->fieldgroup;
if(!$fieldgroup) {
$fieldgroup = new Fieldgroup();
$fieldgroup->name = $item->name;
}
$fieldgroup->save(); $fieldgroup->save();
$fieldgroup->saveContext(); $fieldgroup->saveContext();
$item->setFieldgroup($fieldgroup);
$item->save(); $item->save();
if(!$item->fieldgroup) {
$item->setFieldgroup($fieldgroup);
$item->save();
}
} }
} }