wire('fields') as $field) { if(!in_array($field->name, $exportFields)) continue; $a = $field->getExportData(); $data[$field->name] = $a; } return $data; } /** * Execute export * * @return InputfieldForm * */ public function ___buildExport() { /** @var InputfieldForm $form */ $form = $this->wire('modules')->get('InputfieldForm'); $form->action = './'; $form->method = 'post'; $exportFields = $this->wire('input')->post('export_fields'); if(empty($exportFields)) { $f = $this->wire('modules')->get('InputfieldSelectMultiple'); $f->attr('id+name', 'export_fields'); $f->label = $this->_('Select the fields that you want to export'); $f->icon = 'copy'; $maxName = 0; $maxLabel = 0; $numFields = 0; foreach($this->wire('fields') as $field) { if(strlen($field->name) > $maxName) $maxName = strlen($field->name); $label = $field->getLabel(); if(strlen($label) > $maxLabel) $maxLabel = strlen($label); $numFields++; } $fieldName = $this->_('NAME'); $fieldLabel = $this->_('LABEL'); $fieldType = $this->_('TYPE'); $label = $fieldName . ' ' . str_repeat('.', $maxName - strlen($fieldName) + 3) . ' ' . $fieldLabel . str_repeat('.', $maxLabel - strlen($fieldLabel) + 3) . ' ' . $fieldType; $f->addOption(0, $label, array('disabled' => 'disabled')); foreach($this->wire('fields') as $field) { $fieldLabel = $field->getLabel(); $label = $field->name . ' ' . str_repeat('.', $maxName - strlen($field->name) + 3) . ' ' . $fieldLabel . str_repeat('.', $maxLabel - strlen($fieldLabel) + 3) . ' ' . str_replace('Fieldtype', '', $field->type); $f->addOption($field->name, $label); } $f->notes = $this->_('Shift+Click to select multiple in sequence. Ctrl+Click (or Cmd+Click) to select multiple individually. Ctrl+A (or Cmd+A) to select all.'); $f->attr('size', $numFields+1); $form->add($f); $f = $this->wire('modules')->get('InputfieldSubmit'); $f->attr('name', 'submit_export'); $f->attr('value', $this->_x('Export', 'button')); $form->add($f); } else { $form = $this->wire('modules')->get('InputfieldForm'); $f = $this->wire('modules')->get('InputfieldTextarea'); $f->attr('id+name', 'export_data'); $f->label = $this->_('Export Data'); $f->description = $this->_('Copy and paste this data into the "Import" box of another installation.'); $f->notes = $this->_('Click anywhere in the box to select all export data. Once selected, copy the data with CTRL-C or CMD-C.'); $f->attr('value', wireEncodeJSON($this->getExportData($exportFields), true, true)); $form->add($f); $f = $this->wire('modules')->get('InputfieldButton'); $f->href = './'; $f->value = $this->_x('Ok', 'button'); $form->add($f); } return $form; } /** * Build Textarea input form to pass JSON data into * * @return InputfieldForm * */ protected function ___buildInputDataForm() { /** @var InputfieldForm $form */ $form = $this->modules->get('InputfieldForm'); $form->action = './'; $form->method = 'post'; $form->attr('id', 'import_form'); /** @var InputfieldTextarea $f */ $f = $this->modules->get('InputfieldTextarea'); $f->attr('name', 'import_data'); $f->label = $this->_x('Import', 'button'); $f->icon = 'paste'; $f->description = $this->_('Paste in the data from an export.'); $f->description .= "\n**Experimental/beta feature: database backup recommended for safety.**"; $f->notes = $this->_('Copy the export data from another installation and then paste into the box above with CTRL-V or CMD-V.'); $form->add($f); /** @var InputfieldSubmit $f */ $f = $this->wire('modules')->get('InputfieldSubmit') ; $f->attr('name', 'submit_import'); $f->attr('value', $this->_('Preview')); $form->add($f); return $form; } /** * Execute import * * @return InputfieldForm * @throws WireException if given invalid import data * */ public function ___buildImport() { /** @var InputfieldForm $form */ $form = $this->modules->get('InputfieldForm'); $form->action = './'; $form->method = 'post'; $form->attr('id', 'import_form'); if($form->isSubmitted('submit_commit')) { $this->processImport(); return $form; } $verify = (int) $this->input->get('verify'); if($verify) { $json = $this->session->get('FieldImportData'); } else { $json = $this->input->post('import_data'); } if(!$json) return $this->buildInputDataForm(); $data = is_array($json) ? $json : wireDecodeJSON($json); if(!$data) throw new WireException("Invalid import data"); $numChangesTotal = 0; $numErrors = 0; $numExistingFields = 0; $numNewFields = 0; $notices = $this->wire('notices'); if(!$verify) $notices->removeAll(); // iterate through data for each field foreach($data as $name => $fieldData) { unset($fieldData['id']); $new = false; $name = $this->wire('sanitizer')->fieldName($name); $field = $this->wire('fields')->get($name); $numChangesField = 0; /** @var InputfieldFieldset $fieldset */ $fieldset = $this->modules->get('InputfieldFieldset'); $fieldset->label = $name; $form->add($fieldset); if(!$field) { $new = true; $field = new Field(); $this->wire($field); $field->name = $name; $fieldset->icon = 'sun-o'; $fieldset->label .= " [" . $this->_('new') . "]"; } else { $fieldset->icon = 'moon-o'; } /** @var InputfieldMarkup $markup */ $markup = $this->modules->get('InputfieldMarkup'); $markup->addClass('InputfieldCheckboxes'); $markup->value = ""; $fieldset->add($markup); $savedFieldData = $field->getExportData(); try { $changes = $field->setImportData($fieldData); } catch(\Exception $e) { $this->error($e->getMessage()); $changes = array(); } $field->setImportData($savedFieldData); // restore /** @var InputfieldCheckboxes $f */ $f = $this->wire('modules')->get('InputfieldCheckboxes'); $f->attr('name', "field_$name"); $f->label = $this->_('Changes'); $f->table = true; $f->thead = $this->_('Property') . '|'; if(!$new) $f->thead .= $this->_('Old Value') . '|'; $f->thead .= $this->_('New Value'); foreach($changes as $property => $info) { if(!$new && $property == 'type') { $this->error(sprintf($this->_('We recommend changing the type of this field to "%s" manually, then coming back here to apply additional changes.'), $info['new'])); } $oldValue = str_replace('|', ' ', $info['old']); $newValue = str_replace('|', ' ', $info['new']); $numChangesField++; $numChangesTotal++; if($info['error']) { $this->error("$name.$property: $info[error]"); $attr = array(); } else { $attr = array('checked' => 'checked'); } if($new) $optionValue = "$property|$newValue"; else $optionValue = "$property|$oldValue|$newValue"; $f->addOption($property, $optionValue, $attr); } $errors = array(); foreach($notices as $notice) { if(!$notice instanceof NoticeError) continue; $errors[] = $this->wire('sanitizer')->entities1($notice->text); } if(count($errors)) { $icon = ""; $markup->value .= "
$importLabel " . "" . "" . ($no && $numChangesField ? "(" . $this->_('click yes to show changes') . ")" : "") . "
"; $f->renderReady(); $markup->value .= $f->render(); $data[$name] = $fieldData; } if($numChangesTotal) { if($verify) { $form->description = $this->_('Sometimes it may take two commits before all changes are applied. Please review any pending changes below and commit them as needed.'); } else { $form->description = $this->_('Please review the changes below and commit them when ready. If there are any changes that you do not want applied, uncheck the boxes where appropriate.'); } /** @var InputfieldSubmit $f */ $f = $this->modules->get('InputfieldSubmit'); $f->attr('name', 'submit_commit'); $f->attr('value', $this->_('Commit Changes')); $f->showInHeader(); $form->add($f); } else { if($verify) { $form->description = $this->_('Your changes have been applied!'); } else { $form->description = $this->_('No changes were found'); } $f = $this->modules->get('InputfieldButton'); $f->href = './'; $f->value = $this->_x('Ok', 'button'); $form->add($f); } $this->session->set('FieldImportData', $data); if($numErrors) $this->error(sprintf($this->_n('Errors were found in %d field', 'Errors were found in %d fields', $numErrors), $numErrors)); if($numNewFields) $this->message(sprintf($this->_n('Found %d new field to add', 'Found %d new fields to add', $numNewFields), $numNewFields)); if($numExistingFields) $this->message(sprintf($this->_n('Found %d existing field to update', 'Found %d existing fields to update', $numExistingFields), $numExistingFields)); return $form; } /** * Commit changed field data * */ protected function ___processImport() { $data = $this->session->get('FieldImportData'); if(!$data) throw new WireException("Invalid import data"); $numChangedFields = 0; $numAddedFields = 0; $skipFieldNames = array(); // iterate through data for each field foreach($data as $name => $fieldData) { $name = $this->wire('sanitizer')->fieldName($name); if(!$this->input->post("import_field_$name")) { $skipFieldNames[] = $name; unset($data[$name]); continue; } $field = $this->wire('fields')->get($name); if(!$field) { $new = true; $field = new Field(); $field->name = $name; } else { $new = false; } unset($fieldData['id']); foreach($fieldData as $property => $value) { if(!in_array($property, $this->input->post("field_$name"))) { unset($fieldData[$property]); } } try { $changes = $field->setImportData($fieldData); foreach($changes as $key => $info) $this->message($this->_('Saved:') . " $name.$key => $info[new]"); $field->save(); if($new) { $numAddedFields++; $this->message($this->_('Added field') . ' - ' . $name); } else { $numChangedFields++; $this->message($this->_('Modified field') . ' - ' . $name); } } catch(\Exception $e) { $this->error($e->getMessage()); } $data[$name] = $fieldData; } $this->session->set('FieldImportSkipNames', $skipFieldNames); $this->session->set('FieldImportData', $data); $numSkippedFields = count($skipFieldNames); if($numAddedFields) $this->message(sprintf($this->_n('Added %d field', 'Added %d fields', $numAddedFields), $numAddedFields)); if($numChangedFields) $this->message(sprintf($this->_n('Modified %d field', 'Modified %d fields', $numChangedFields), $numChangedFields)); if($numSkippedFields) $this->message(sprintf($this->_n('Skipped %d field', 'Skipped %d fields', $numSkippedFields), $numSkippedFields)); $this->session->redirect("./?verify=1"); } }