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

Some additional updates and fixes for pages export/import

This commit is contained in:
Ryan Cramer
2017-08-25 10:18:09 -04:00
parent fc2b7944a2
commit e96d740586
5 changed files with 70 additions and 15 deletions

View File

@@ -133,7 +133,7 @@ class Fieldgroup extends WireArray implements Saveable, Exportable, HasLookupIte
/**
* Remove a field from this fieldgroup
*
* Note that this must be followed up with a `$field->save()` before it does anything destructive.
* Note that this must be followed up with a `$fieldgroup->save()` before it does anything destructive.
* This method does nothing more than queue the removal.
*
* _Technical Details_

View File

@@ -555,7 +555,21 @@ abstract class Fieldtype extends WireData implements Module {
/**
* Get associative array of options and info (name => value) that Fieldtype supports for importValue
*
* - `test` (bool): indicates Fieldtype supports testing import before committing.
* Current recognized options include the following:
*
* - `importable` (bool): Is the field importable (and exportable)? (default=auto-detect)
*
* - `test` (bool): Indicates Fieldtype supports testing import before committing & populates notices to
* returned Wire object. (default=false)
*
* - `returnsPageValue` (bool): True if it returns the value that should set back to Page? False if return
* value should not be set to Page. When false, it indicates the Fieldtype::importValue() handles the
* actual commit to DB of import data. (default=true)
*
* - `requiresExportValue` (bool): Indicates Fieldtype::importValue() requires an 'exportValue' of the
* current value from Page in $options. (default=false)
*
* - `restoreOnException` (bool): Restore previous value if Exception thrown during import (default=false).
*
* #pw-internal
*
@@ -564,8 +578,15 @@ abstract class Fieldtype extends WireData implements Module {
*
*/
public function getImportValueOptions(Field $field) {
if($field) {} // ignore
return array();
$schema = $this->getDatabaseSchema($field);
$options = array(
'importable' => (!isset($schema['xtra']['all']) || $schema['xtra']['all'] !== true) ? false : true,
'test' => false,
'returnsPageValue' => true,
'requiresExportValue' => false,
'restoreOnException' => false,
);
return $options;
}
/**

View File

@@ -882,9 +882,20 @@ class PagesExportImport extends Wire {
}
}
$fieldtypeSupportsOptions = $field->type->getImportValueOptions($field);
$fieldtypeImportDefaults = array(
// supports testing before commit (populates notices to returned Wire).
'test' => false,
// returns the value that should set back to Page? (false=return value for notices only).
// when false, it also indicates the Fieldtype::importValue() handles the actual commit to DB of import data.
'returnsPageValue' => true,
// indicates Fieldtype::importValue() would like an 'exportValue' of the current value from Page in $options
'requiresExportValue' => false,
);
$fieldtypeImportOptions = array_merge($fieldtypeImportDefaults, $field->type->getImportValueOptions($field));
$o = array(
'importType' => $page->get('_importType'),
'system' => true,
'caller' => $this,
'commit' => $options['commit'],
@@ -892,7 +903,7 @@ class PagesExportImport extends Wire {
);
// fake-commit for more verbose testing of certain fieldtypes
$fakeCommit = $options['commit'] || !empty($fieldtypeSupportsOptions['test']);
$fakeCommit = $options['commit'] || !empty($fieldtypeImportOptions['test']);
if($page->get('_importType') == 'create' && !$options['commit'] && !$fakeCommit) {
// test import on a new page, so value will always be used
@@ -910,17 +921,36 @@ class PagesExportImport extends Wire {
// use '===' for all other value comparisons
if($exportValue === $importValue) return;
}
// at this point, values appear to be different
if($fieldtypeImportOptions['requiresExportValue']) $o['exportValue'] = $exportValue;
if($options['commit'] || $fakeCommit) {
$pageValue = $field->type->importValue($page, $field, $importValue, $o);
if($pageValue !== null) $page->set($field->name, $pageValue);
$commitException = false;
try {
$pageValue = $field->type->importValue($page, $field, $importValue, $o);
} catch(\Exception $e) {
if($options['commit'] && $fieldtypeImportOptions['restoreOnException']) {
$commitException = true;
$pageValue = $field->type->importValue($page, $field, $exportValue, $o);
$page->warning("$field: " . $e->getMessage());
$page->warning("$field: Attempted to restore previous value");
}
}
if(!$commitException) {
if($pageValue !== null && $fieldtypeImportOptions['returnsPageValue']) {
$page->set($field->name, $pageValue);
} else if(!$fieldtypeImportOptions['returnsPageValue']) {
$page->trackChange("{$field->name}__");
}
}
if(is_object($pageValue) && $pageValue instanceof Wire) {
// movie notices from the pageValue to the page
$this->wire('notices')->move($pageValue, $page);
}
} else {
// test import on existing page, avoids actually setting value to the page
$page->trackChange($field->name); // values appear to be different
$page->trackChange($field->name);
}
if($options['debug']) {
@@ -1327,19 +1357,19 @@ class PagesExportImport extends Wire {
} else {
// test to see if exportable
try {
$schema = $fieldtype->getDatabaseSchema($field);
$importInfo = $fieldtype->getImportValueOptions($field);
} catch(\Exception $e) {
$exportable = false;
$reason = $e->getMessage();
}
if($exportable && (!isset($schema['xtra']['all']) || $schema['xtra']['all'] !== true)) {
if($exportable && !$importInfo['importable']) {
// this fieldtype is storing data outside of the DB or in other unknown tables
// there's a good chance we won't be able to export/import this into an array
// @todo check if fieldtype implements its own exportValue/importValue, and if
// it does then allow the value to be exported
$exportable = false;
$reason = "Field '$field' cannot be used because $field->type uses data outside table '$field->table'";
$reason = "Field '$field' cannot be used because $field->type indicates imports are not supported";
}
}

View File

@@ -810,9 +810,9 @@ class PagesLoader extends Wire {
// if page is already loaded and cache allowed, then get the path from it
if($options['useCache'] && $page = $this->pages->getCache($id)) {
/** @var Page $page */
if($languages) $languages->setLanguage($language);
if($languageID) $languages->setLanguage($language);
$path = $page->path();
if($languages) $languages->unsetLanguage();
if($languageID) $languages->unsetLanguage();
return $path;
} else if($id == $homepageID && $languages && !$languageID) {

View File

@@ -183,7 +183,7 @@ class ProcessPagesExportImport extends Process {
$submitCommit = $input->post('submit_commit_import') ? true : false;
$submitTest = $input->post('submit_test_import') ? true : false;
$submitZIP = !empty($_FILES['import_zip']);
$submitZIP = !empty($_FILES['import_zip']) && !empty($_FILES['import_zip']['name'][0]);
$fileField = null;
$filesPath = $this->wire('session')->getFor($this, 'filesPath');
$jsonFile = '';
@@ -815,6 +815,10 @@ class ProcessPagesExportImport extends Process {
}
if($numChanges) {
foreach($changes as $key => $change) {
// i.e. 'field_name__' as disguised change
if(substr($change, -2) == '__') $changes[$key] = substr($change, 0, -2);
}
if($languages) {
// indicate language in name and status changes
foreach($changes as $key => $change) {