ran security updates on contrib modules
ctools, video_embed_field, migrate, views_bulk_operations
This commit is contained in:
@@ -1,5 +0,0 @@
|
||||
Conventions to make porting changes between Drupal 6 and Drupal 7 easier:
|
||||
|
||||
Try to always use specific DBTNG functions such as db_select() instead of the
|
||||
more general db_query(), which needs to be renamed to dbtng_query() under
|
||||
Drupal 6.
|
@@ -1,11 +1,31 @@
|
||||
Migrate 2.7
|
||||
Migrate 2.8
|
||||
===========
|
||||
|
||||
Bug fixes
|
||||
- #2415597 - Make batching of SQL sources optional, and force map_joinable FALSE.
|
||||
Features and enhancements
|
||||
- #2379289 - Better handle interaction of --update with highwater marks.
|
||||
- #2403643 - Support an additional level of subfields.
|
||||
- #2472045 - Add language subfields only if field is translatable.
|
||||
- #2474809 - Provide better message for bad dependencies.
|
||||
- #2397791 - Provide detailed field validation errors.
|
||||
- #2309563 - Add support for running migrations via wildcard name.
|
||||
- #2095841 - Abstract mail system disablement for more flexibility.
|
||||
- #2419373 - Provide ability to cache map lookups.
|
||||
- #2141687 - Provide detailed message on file copy error.
|
||||
|
||||
Migrate 2.7 Release Candidate 1
|
||||
===============================
|
||||
Bug fixes
|
||||
Field sanitization added to prevent possibility of XSS - see security advisory
|
||||
https://security.drupal.org/node/155268.
|
||||
- #2447115 - Add xpath handling to the field mapping editor.
|
||||
- #2497015 - Term reference handler would ignore all terms if one was NULL.
|
||||
- #2488560 - MigrateSourceList/MigrateSourceMultiItems iterators prematurely
|
||||
return.
|
||||
- #2446105 - Keep coded DNM source field mappings from overriding UI mappings.
|
||||
- #2415977 - Use temporary:// instead of /tmp for drush logging.
|
||||
- #2475473 - Fix handling of --idlist when map not joined.
|
||||
- #2465387 - Fix handling of --stop option on migrate-import.
|
||||
|
||||
Migrate 2.7
|
||||
===========
|
||||
|
||||
Features and enhancements
|
||||
- #2296911 - Add a source handler for IBM DB2.
|
||||
@@ -14,6 +34,7 @@ Features and enhancements
|
||||
- #1751438 - Add spreadsheet source plugin.
|
||||
|
||||
Bug fixes
|
||||
- #2415597 - Make batching of SQL sources optional, and force map_joinable FALSE.
|
||||
- #2403593 - SQL batching messes up cases with altered queries, such as idlist.
|
||||
- #2298969 - Verify wizard validation function exists.
|
||||
- #2268863 - Fix drush --all option.
|
||||
|
@@ -301,6 +301,11 @@ abstract class MigrationBase {
|
||||
return $this->disableHooks;
|
||||
}
|
||||
|
||||
/**
|
||||
* An array to track 'mail_system' variable if disabled.
|
||||
*/
|
||||
protected $mailSystem = array();
|
||||
|
||||
/**
|
||||
* Have we already warned about obsolete constructor argumentss on this request?
|
||||
*
|
||||
@@ -432,16 +437,11 @@ abstract class MigrationBase {
|
||||
// Record the time limit
|
||||
$this->timeLimit = ini_get('max_execution_time');
|
||||
|
||||
// Prevent any emails from being sent out on migration
|
||||
global $conf;
|
||||
if (!empty($conf['mail_system'])) {
|
||||
foreach ($conf['mail_system'] as $system => $class) {
|
||||
$conf['mail_system'][$system] = 'MigrateMailIgnore';
|
||||
}
|
||||
}
|
||||
else {
|
||||
$conf['mail_system']['default-system'] = 'MigrateMailIgnore';
|
||||
}
|
||||
// Save the current mail system, prior to disabling emails.
|
||||
$this->saveMailSystem();
|
||||
|
||||
// Prevent emails from being sent out during migrations.
|
||||
$this->disableMailSystem();
|
||||
|
||||
// Make sure we clear our semaphores in case of abrupt exit
|
||||
drupal_register_shutdown_function(array($this, 'endProcess'));
|
||||
@@ -1355,6 +1355,39 @@ abstract class MigrationBase {
|
||||
}
|
||||
return $time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the current mail system, or set a system default if there is none.
|
||||
*/
|
||||
protected function saveMailSystem() {
|
||||
global $conf;
|
||||
if (empty($conf['mail_system'])) {
|
||||
$conf['mail_system']['default-system'] = 'MigrateMailIgnore';
|
||||
}
|
||||
else {
|
||||
$this->mailSystem = $conf['mail_system'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables mail system to prevent emails from being sent during migrations.
|
||||
*/
|
||||
public function disableMailSystem() {
|
||||
global $conf;
|
||||
if (!empty($conf['mail_system'])) {
|
||||
foreach ($conf['mail_system'] as $system => $class) {
|
||||
$conf['mail_system'][$system] = 'MigrateMailIgnore';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores the original saved mail system for migrations that require it.
|
||||
*/
|
||||
public function restoreMailSystem() {
|
||||
global $conf;
|
||||
$conf['mail_system'] = $this->mailSystem;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure static members (in particular, $displayFunction) get
|
||||
|
@@ -141,16 +141,26 @@ abstract class Migration extends MigrationBase {
|
||||
// destination field, keep only the last (so the UI can override a source
|
||||
// field DNM that was defined in code).
|
||||
$no_destination = array();
|
||||
// But also remove a mapping of a source field to nothing, if there is
|
||||
// a mapping to something.
|
||||
$mapped_source_fields = array();
|
||||
/** @var MigrateFieldMapping $mapping */
|
||||
foreach ($this->allFieldMappings as $destination_field => $mapping) {
|
||||
$source_field = $mapping->getSourceField();
|
||||
// If the source field is not mapped to a destination field, the
|
||||
// array index is integer.
|
||||
if (is_int($destination_field)) {
|
||||
$source_field = $mapping->getSourceField();
|
||||
if (isset($no_destination[$source_field])) {
|
||||
unset($this->allFieldMappings[$no_destination[$source_field]]);
|
||||
unset($no_destination[$source_field]);
|
||||
}
|
||||
$no_destination[$source_field] = $destination_field;
|
||||
if (isset($mapped_source_fields[$source_field])) {
|
||||
unset($this->allFieldMappings[$destination_field]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$mapped_source_fields[$source_field] = $source_field;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1267,8 +1277,11 @@ abstract class Migration extends MigrationBase {
|
||||
// Are we dealing with the primary value of the destination field, or a
|
||||
// subfield?
|
||||
$destination = explode(':', $destination);
|
||||
// Count how many levels of fields are in the mapping. We'll use the
|
||||
// last one.
|
||||
$destination_count = count($destination);
|
||||
$destination_field = $destination[0];
|
||||
if (isset($destination[1])) {
|
||||
if ($destination_count == 2) {
|
||||
$subfield = $destination[1];
|
||||
// We're processing the subfield before the primary value, initialize it
|
||||
if (!property_exists($this->destinationValues, $destination_field)) {
|
||||
@@ -1282,6 +1295,24 @@ abstract class Migration extends MigrationBase {
|
||||
// Add the subfield value to the arguments array.
|
||||
$this->destinationValues->{$destination_field}['arguments'][$subfield] = $destination_values;
|
||||
}
|
||||
elseif ($destination_count == 3) {
|
||||
$subfield2 = $destination[2];
|
||||
// We're processing the subfield before the primary value, initialize it
|
||||
if (!property_exists($this->destinationValues, $destination_field)) {
|
||||
$this->destinationValues->$destination_field = array();
|
||||
}
|
||||
// We have a value, and need to convert to an array so we can add
|
||||
// arguments.
|
||||
elseif (!is_array($this->destinationValues->$destination_field)) {
|
||||
$this->destinationValues->$destination_field = array($this->destinationValues->$destination_field);
|
||||
}
|
||||
if (!is_array($this->destinationValues->{$destination_field}['arguments'][$destination[1]])) {
|
||||
// Convert first subfield level to an array so we can add to it.
|
||||
$this->destinationValues->{$destination_field}['arguments'][$destination[1]] = array( $this->destinationValues->{$destination_field}['arguments'][$destination[1]] );
|
||||
}
|
||||
// Add the subfield value to the arguments array.
|
||||
$this->destinationValues->{$destination_field}['arguments'][$destination[1]]['arguments'][$subfield2] = $destination_values;
|
||||
}
|
||||
// Just the primary value, the first time through for this field, simply
|
||||
// set it.
|
||||
elseif (!property_exists($this->destinationValues, $destination_field)) {
|
||||
|
@@ -303,9 +303,11 @@ abstract class MigrateSource implements Iterator {
|
||||
// highwaters and map rows).
|
||||
$prepared = FALSE;
|
||||
if (!empty($this->idList)) {
|
||||
// Check first source key.
|
||||
if (!in_array(reset($this->currentKey), $this->idList)) {
|
||||
// If this is a compound source key, check the full key.
|
||||
$compoundKey = implode($this->multikeySeparator, $this->currentKey);
|
||||
if (count($this->currentKey) > 1 && !in_array($compoundKey, $this->idList)) {
|
||||
if (count($this->currentKey) == 1 || !in_array($compoundKey, $this->idList)) {
|
||||
// Could not find the key, skip.
|
||||
continue;
|
||||
}
|
||||
|
@@ -18,6 +18,7 @@ function migrate_drush_command() {
|
||||
'force' => 'Force an operation to run, even if all dependencies are not satisfied',
|
||||
'group' => 'Name of the migration group to run',
|
||||
'notify' => 'Send email notification upon completion of operation',
|
||||
'wildcard' => 'Process migrations that match a certain pattern. For example, Content*.',
|
||||
);
|
||||
$items['migrate-status'] = array(
|
||||
'description' => 'List all migrations with current status.',
|
||||
@@ -161,6 +162,7 @@ function migrate_drush_command() {
|
||||
'migrate-import Article' => 'Import new articles',
|
||||
'migrate-import Article --update' => 'Import new items, and also update previously-imported items',
|
||||
'migrate-import Article --idlist=4,9' => 'Import two specific articles. The ids refer to the value of the primary key in base table',
|
||||
'migrate-import Article --idlist=450:pasta,451' => 'Import two specific articles. A colon can be used to separate parts of compound keys; otherwise, compound keys match by the first key field.',
|
||||
'migrate-import Article --limit="60 seconds" --stop --rollback' =>
|
||||
'Import for up to 60 seconds after stopping and rolling back the Article migration.',
|
||||
'migrate-import Article --limit="100 items"' =>
|
||||
@@ -824,15 +826,6 @@ function drush_migrate_rollback($args = NULL) {
|
||||
// Capture non-informational output for mailing
|
||||
ob_start();
|
||||
ob_implicit_flush(FALSE);
|
||||
// Save original mail setup, which Migrate will disable, so we can
|
||||
// restore it later.
|
||||
global $conf;
|
||||
if (!empty($conf['mail_system'])) {
|
||||
$mail_system = $conf['mail_system'];
|
||||
}
|
||||
else {
|
||||
$mail_system = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
$migrations = drush_migrate_get_migrations($args);
|
||||
@@ -928,12 +921,6 @@ function drush_migrate_rollback($args = NULL) {
|
||||
|
||||
// Notify user
|
||||
if (drush_get_option('notify')) {
|
||||
if (is_null($mail_system)) {
|
||||
unset($conf['mail_system']);
|
||||
}
|
||||
else {
|
||||
$conf['mail_system'] = $mail_system;
|
||||
}
|
||||
_drush_migrate_notify();
|
||||
}
|
||||
}
|
||||
@@ -985,6 +972,14 @@ function drush_migrate_get_migrations($args) {
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif ($wildcard = drush_get_option('wildcard')) {
|
||||
foreach ($migration_objects as $name => $migration) {
|
||||
if (!fnmatch(drupal_strtolower($wildcard), drupal_strtolower($name)) ||
|
||||
!$migration->getEnabled()) {
|
||||
unset($migration_objects[$name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$named_migrations = array();
|
||||
foreach (explode(',', $args) as $name) {
|
||||
@@ -1057,18 +1052,23 @@ function drush_migrate_rollback_validate($args = NULL) {
|
||||
|
||||
function drush_migrate_validate_common($args) {
|
||||
if (drush_get_option('all')) {
|
||||
if (!empty($args) || drush_get_option('group')) {
|
||||
return drush_set_error(NULL, dt('You must specify exactly one of a migration name, --all, or --group'));
|
||||
if (!empty($args) || drush_get_option('group') || drush_get_option('wildcard')) {
|
||||
return drush_set_error(NULL, dt('You must specify exactly one of a migration name, --all, or --group, or --wildcard'));
|
||||
}
|
||||
}
|
||||
elseif (drush_get_option('group')) {
|
||||
if (!empty($args) || drush_get_option('all')) {
|
||||
return drush_set_error(NULL, dt('You must specify exactly one of a migration name, --all, or --group'));
|
||||
if (!empty($args) || drush_get_option('all') || drush_get_option('wildcard')) {
|
||||
return drush_set_error(NULL, dt('You must specify exactly one of a migration name, --all, or --group, or --wildcard'));
|
||||
}
|
||||
}
|
||||
elseif (drush_get_option('wildcard')) {
|
||||
if (!empty($args) || drush_get_option('all') || drush_get_option('group')) {
|
||||
return drush_set_error(NULL, dt('You must specify exactly one of a migration name, --all, or --group, or --wildcard'));
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (empty($args)) {
|
||||
return drush_set_error(NULL, dt('You must specify exactly one of a migration name, --all, or --group'));
|
||||
return drush_set_error(NULL, dt('You must specify exactly one of a migration name, --all, or --group, or --wildcard'));
|
||||
}
|
||||
$machine_names = explode(',', $args);
|
||||
|
||||
@@ -1107,7 +1107,29 @@ function drush_migrate_validate_common($args) {
|
||||
*/
|
||||
function drush_migrate_pre_migrate_import($args = NULL) {
|
||||
if (drush_get_option('stop')) {
|
||||
drush_invoke('migrate-stop', $args);
|
||||
drush_unset_option('stop');
|
||||
try {
|
||||
/** @var Migration[] $migrations */
|
||||
$migrations = drush_migrate_get_migrations($args);
|
||||
foreach ($migrations as $migration) {
|
||||
$status = $migration->getStatus();
|
||||
if ($status == MigrationBase::STATUS_IMPORTING ||
|
||||
$status == MigrationBase::STATUS_ROLLING_BACK) {
|
||||
drush_log(dt("Stopping '!description' migration", array('!description' => $migration->getMachineName())));
|
||||
$migration->stopProcess();
|
||||
// Give the process a chance to stop.
|
||||
$count = 0;
|
||||
while ($migration->getStatus() != MigrationBase::STATUS_IDLE
|
||||
&& $count++ < 5) {
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (MigrateException $e) {
|
||||
drush_print($e->getMessage());
|
||||
exit;
|
||||
}
|
||||
}
|
||||
if (drush_get_option('rollback')) {
|
||||
drush_unset_option('rollback');
|
||||
@@ -1127,15 +1149,6 @@ function drush_migrate_import($args = NULL) {
|
||||
// Capture non-informational output for mailing
|
||||
ob_start();
|
||||
ob_implicit_flush(FALSE);
|
||||
// Save original mail setup, which Migrate will disable, so we can
|
||||
// restore it later.
|
||||
global $conf;
|
||||
if (!empty($conf['mail_system'])) {
|
||||
$mail_system = $conf['mail_system'];
|
||||
}
|
||||
else {
|
||||
$mail_system = NULL;
|
||||
}
|
||||
}
|
||||
$migrations = drush_migrate_get_migrations($args);
|
||||
$options = array();
|
||||
@@ -1294,12 +1307,6 @@ function drush_migrate_import($args = NULL) {
|
||||
|
||||
// Notify user
|
||||
if (drush_get_option('notify')) {
|
||||
if (is_null($mail_system)) {
|
||||
unset($conf['mail_system']);
|
||||
}
|
||||
else {
|
||||
$conf['mail_system'] = $mail_system;
|
||||
}
|
||||
_drush_migrate_notify();
|
||||
}
|
||||
}
|
||||
|
@@ -51,9 +51,9 @@ files[] = tests/plugins/destinations/term.test
|
||||
files[] = tests/plugins/destinations/user.test
|
||||
files[] = tests/plugins/sources/xml.test
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-02-09
|
||||
version = "7.x-2.7"
|
||||
; Information added by Drupal.org packaging script on 2015-07-01
|
||||
version = "7.x-2.8"
|
||||
core = "7.x"
|
||||
project = "migrate"
|
||||
datestamp = "1423521491"
|
||||
datestamp = "1435760949"
|
||||
|
||||
|
@@ -93,11 +93,18 @@ function migrate_migrations($reset = NULL) {
|
||||
$final_migrations[$name] = array();
|
||||
}
|
||||
|
||||
// Fill in the grouped list
|
||||
// Fill in the grouped list.
|
||||
foreach ($migrations as $machine_name => $migration) {
|
||||
$final_migrations[$migration->getGroup()->getName()][$machine_name] = $migration;
|
||||
if (!method_exists($migration, 'getGroup')) {
|
||||
MigrationBase::displayMessage(t('Migration !machine_name is not a valid Migration dependency.', array(
|
||||
'!machine_name' => $machine_name,
|
||||
)));
|
||||
}
|
||||
else {
|
||||
$final_migrations[$migration->getGroup()->getName()][$machine_name] = $migration;
|
||||
}
|
||||
}
|
||||
// Then flatten the list
|
||||
// Flatten the grouped list.
|
||||
$migrations = array();
|
||||
foreach ($final_migrations as $group_name => $group_migrations) {
|
||||
foreach ($group_migrations as $machine_name => $migration) {
|
||||
|
@@ -424,15 +424,13 @@ class BeerNodeMigration extends BasicExampleMigration {
|
||||
// subfields of the same field may be grouped on the same line), and indent
|
||||
// subfields to distinguish them from top-level fields.
|
||||
$this->addUnmigratedDestinations(array(
|
||||
'body:format', 'body:language',
|
||||
'body:format',
|
||||
'changed',
|
||||
'comment',
|
||||
'created',
|
||||
'field_migrate_example_country:language',
|
||||
'field_migrate_example_image:destination_dir',
|
||||
'field_migrate_example_image:destination_file',
|
||||
'field_migrate_example_image:file_replace',
|
||||
'field_migrate_example_image:language',
|
||||
'field_migrate_example_image:preserve_files',
|
||||
'field_migrate_example_image:urlencode',
|
||||
'is_new',
|
||||
@@ -515,7 +513,7 @@ class BeerCommentMigration extends BasicExampleMigration {
|
||||
// Unmapped destination fields
|
||||
$this->addUnmigratedDestinations(array(
|
||||
'changed',
|
||||
'comment_body:format', 'comment_body:language',
|
||||
'comment_body:format',
|
||||
'created',
|
||||
'homepage',
|
||||
'hostname',
|
||||
|
@@ -18,9 +18,9 @@ files[] = wine.inc
|
||||
; For testing table_copy plugin. Since is infrequently used, we comment it out.
|
||||
; files[] = example.table_copy.inc
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-02-09
|
||||
version = "7.x-2.7"
|
||||
; Information added by Drupal.org packaging script on 2015-07-01
|
||||
version = "7.x-2.8"
|
||||
core = "7.x"
|
||||
project = "migrate"
|
||||
datestamp = "1423521491"
|
||||
datestamp = "1435760949"
|
||||
|
||||
|
@@ -11,9 +11,9 @@ name = "Migrate example - Oracle"
|
||||
package = "Migration"
|
||||
project = "migrate_example_oracle"
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-02-09
|
||||
version = "7.x-2.7"
|
||||
; Information added by Drupal.org packaging script on 2015-07-01
|
||||
version = "7.x-2.8"
|
||||
core = "7.x"
|
||||
project = "migrate"
|
||||
datestamp = "1423521491"
|
||||
datestamp = "1435760949"
|
||||
|
||||
|
@@ -449,7 +449,7 @@ class WineProducerMigration extends AdvancedExampleMigration {
|
||||
|
||||
// Unmapped destination fields
|
||||
$this->addUnmigratedDestinations(array(
|
||||
'body:format', 'body:language',
|
||||
'body:format',
|
||||
'changed',
|
||||
'comment',
|
||||
'created',
|
||||
@@ -550,7 +550,7 @@ class WineProducerXMLMigration extends XMLMigration {
|
||||
->xpath('/producer/description');
|
||||
|
||||
$this->addUnmigratedDestinations(array(
|
||||
'body:summary', 'body:format', 'body:language',
|
||||
'body:summary', 'body:format',
|
||||
'changed',
|
||||
'comment',
|
||||
'created',
|
||||
@@ -663,7 +663,7 @@ class WineProducerNamespaceXMLMigration extends XMLMigration {
|
||||
->xpath('/pr:producer/pr:description');
|
||||
|
||||
$this->addUnmigratedDestinations(array(
|
||||
'body:summary', 'body:format', 'body:language',
|
||||
'body:summary', 'body:format',
|
||||
'changed',
|
||||
'comment',
|
||||
'created',
|
||||
@@ -784,7 +784,7 @@ class WineProducerMultiXMLMigration extends XMLMigration {
|
||||
->xpath('description');
|
||||
|
||||
$this->addUnmigratedDestinations(array(
|
||||
'body:summary', 'body:format', 'body:language',
|
||||
'body:summary', 'body:format',
|
||||
'changed',
|
||||
'comment',
|
||||
'created',
|
||||
@@ -907,7 +907,7 @@ class WineProducerMultiNamespaceXMLMigration extends XMLMigration {
|
||||
->xpath('pr:description');
|
||||
|
||||
$this->addUnmigratedDestinations(array(
|
||||
'body:summary', 'body:format', 'body:language',
|
||||
'body:summary', 'body:format',
|
||||
'changed',
|
||||
'comment',
|
||||
'created',
|
||||
@@ -1012,7 +1012,7 @@ class WineProducerXMLPullMigration extends XMLMigration {
|
||||
->xpath('description');
|
||||
|
||||
$this->addUnmigratedDestinations(array(
|
||||
'body:summary', 'body:format', 'body:language',
|
||||
'body:summary', 'body:format',
|
||||
'changed',
|
||||
'comment',
|
||||
'created',
|
||||
@@ -1119,7 +1119,7 @@ class WineProducerNamespaceXMLPullMigration extends XMLMigration {
|
||||
->xpath('pr:description');
|
||||
|
||||
$this->addUnmigratedDestinations(array(
|
||||
'body:summary', 'body:format', 'body:language',
|
||||
'body:summary', 'body:format',
|
||||
'changed',
|
||||
'comment',
|
||||
'created',
|
||||
@@ -1290,12 +1290,11 @@ class WineWineMigration extends AdvancedExampleMigration {
|
||||
|
||||
// Unmapped destination fields
|
||||
$this->addUnmigratedDestinations(array(
|
||||
'body:format', 'body:language',
|
||||
'body:format',
|
||||
'comment',
|
||||
'field_migrate_example_image:destination_dir',
|
||||
'field_migrate_example_image:destination_file',
|
||||
'field_migrate_example_image:file_class',
|
||||
'field_migrate_example_image:language',
|
||||
'field_migrate_example_image:preserve_files',
|
||||
'field_migrate_example_image:source_dir',
|
||||
'field_migrate_example_image:urlencode',
|
||||
@@ -1418,7 +1417,7 @@ class WineCommentMigration extends AdvancedExampleMigration {
|
||||
|
||||
// Unmapped destination fields
|
||||
$this->addUnmigratedDestinations(array(
|
||||
'comment_body:format', 'comment_body:language',
|
||||
'comment_body:format',
|
||||
'language',
|
||||
'thread',
|
||||
));
|
||||
@@ -1551,14 +1550,13 @@ class WineUpdatesMigration extends AdvancedExampleMigration {
|
||||
$this->addFieldMapping('created');
|
||||
$this->addFieldMapping('changed');
|
||||
$this->addUnmigratedDestinations(array(
|
||||
'body:format', 'body:summary', 'body:language',
|
||||
'body:format', 'body:summary',
|
||||
'comment',
|
||||
'field_migrate_example_image:alt',
|
||||
'field_migrate_example_image:destination_dir',
|
||||
'field_migrate_example_image:destination_file',
|
||||
'field_migrate_example_image:file_class',
|
||||
'field_migrate_example_image:file_replace',
|
||||
'field_migrate_example_image:language',
|
||||
'field_migrate_example_image:preserve_files',
|
||||
'field_migrate_example_image:source_dir',
|
||||
'field_migrate_example_image:title',
|
||||
@@ -1623,7 +1621,7 @@ class WineCommentUpdatesMigration extends AdvancedExampleMigration {
|
||||
// Unmapped destination fields
|
||||
$this->addUnmigratedDestinations(array(
|
||||
'changed',
|
||||
'comment_body', 'comment_body:format', 'comment_body:language',
|
||||
'comment_body', 'comment_body:format',
|
||||
'created',
|
||||
'homepage',
|
||||
'hostname',
|
||||
|
@@ -24,9 +24,9 @@ name = "migrate_example_baseball"
|
||||
package = "Migration"
|
||||
php = "5.2.4"
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-02-09
|
||||
version = "7.x-2.7"
|
||||
; Information added by Drupal.org packaging script on 2015-07-01
|
||||
version = "7.x-2.8"
|
||||
core = "7.x"
|
||||
project = "migrate"
|
||||
datestamp = "1423521491"
|
||||
datestamp = "1435760949"
|
||||
|
||||
|
@@ -6,9 +6,9 @@ core = 7.x
|
||||
dependencies[] = migrate
|
||||
files[] = migrate_ui.wizard.inc
|
||||
|
||||
; Information added by Drupal.org packaging script on 2015-02-09
|
||||
version = "7.x-2.7"
|
||||
; Information added by Drupal.org packaging script on 2015-07-01
|
||||
version = "7.x-2.8"
|
||||
core = "7.x"
|
||||
project = "migrate"
|
||||
datestamp = "1423521491"
|
||||
datestamp = "1435760949"
|
||||
|
||||
|
@@ -14,7 +14,7 @@ function migrate_ui_migrate_dashboard($form, &$form_state) {
|
||||
|
||||
$build['overview'] = array(
|
||||
'#prefix' => '<div>',
|
||||
'#markup' => migrate_overview(),
|
||||
'#markup' => filter_xss_admin(migrate_overview()),
|
||||
'#suffix' => '</div>',
|
||||
);
|
||||
|
||||
@@ -100,7 +100,7 @@ function migrate_ui_migrate_dashboard($form, &$form_state) {
|
||||
l($group_row->title, 'admin/content/migrate/groups/' . $group_row->name);
|
||||
$arguments = unserialize($group_row->arguments);
|
||||
if (!empty($arguments['source_system'])) {
|
||||
$row['source_system'] = $arguments['source_system'];
|
||||
$row['source_system'] = filter_xss_admin($arguments['source_system']);
|
||||
}
|
||||
else {
|
||||
$row['source_system'] = '';
|
||||
@@ -212,9 +212,9 @@ function migrate_ui_migrate_group($form, &$form_state, $group_name) {
|
||||
}
|
||||
$row['machinename'] =
|
||||
l($display_name, "admin/content/migrate/groups/$group_name/$machine_name");
|
||||
$row['importrows'] = $total;
|
||||
$row['imported'] = $imported;
|
||||
$row['unprocessed'] = $unprocessed;
|
||||
$row['importrows'] = (int) $total;
|
||||
$row['imported'] = (int) $imported;
|
||||
$row['unprocessed'] = (int) $unprocessed;
|
||||
if (user_access(MIGRATE_ACCESS_ADVANCED)) {
|
||||
if (is_subclass_of($migration, 'Migration')) {
|
||||
$num_messages = $migration->messageCount();
|
||||
@@ -231,13 +231,13 @@ function migrate_ui_migrate_group($form, &$form_state, $group_name) {
|
||||
$row['lastthroughput'] = t('Unknown');
|
||||
}
|
||||
else {
|
||||
$row['lastthroughput'] = t('!rate/min', array('!rate' => $rate));
|
||||
$row['lastthroughput'] = t('@rate/min', array('@rate' => $rate));
|
||||
}
|
||||
}
|
||||
else {
|
||||
$row['lastthroughput'] = t('N/A');
|
||||
}
|
||||
$row['lastimported'] = $migration->getLastImported();
|
||||
$row['lastimported'] = check_plain($migration->getLastImported());
|
||||
}
|
||||
$rows[$machine_name] = $row;
|
||||
}
|
||||
@@ -497,6 +497,19 @@ function migrate_ui_migrate_submit($form, &$form_state) {
|
||||
}
|
||||
elseif (count($drush_arguments) > 0) {
|
||||
$drush_path = trim(variable_get('migrate_drush_path', ''));
|
||||
// Check that $drush_path works. See migrate_ui_configure_form().
|
||||
if (!is_executable($drush_path)) {
|
||||
$message = t('To enable running operations in the background with <a href="@drush">drush</a>, (which is <a href="@recommended">recommended</a>), some configuration must be done on the server. See the <a href="@config">documentation</a> on <a href="@dorg">drupal.org</a>.',
|
||||
array(
|
||||
'@drush' => 'http://drupal.org/project/drush',
|
||||
'@recommended' => 'http://drupal.org/node/1806824',
|
||||
'@config' => 'http://drupal.org/node/1958170',
|
||||
'@dorg' => 'http://drupal.org/',
|
||||
)
|
||||
);
|
||||
drupal_set_message($message);
|
||||
return;
|
||||
}
|
||||
$uri = $GLOBALS['base_url'];
|
||||
$uid = $GLOBALS['user']->uid;
|
||||
if ($operation == 'import_background') {
|
||||
@@ -523,7 +536,7 @@ function migrate_ui_migrate_submit($form, &$form_state) {
|
||||
$limit = $limit['value'] . ' ' . $limit['unit'];
|
||||
$drush_command .= " --limit=\"$limit\"";
|
||||
}
|
||||
$log_file = '/tmp/' . $drush_arguments[0] . $log_suffix;
|
||||
$log_file = drupal_realpath('temporary://' . $drush_arguments[0] . $log_suffix);
|
||||
$drush_command .= " >$log_file 2>&1 &";
|
||||
exec($drush_command, $output, $status);
|
||||
if (variable_get('migrate_drush_mail', 0)) {
|
||||
@@ -674,13 +687,24 @@ function migrate_ui_batch_finish($success, $results, $operations) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a message to be displayed later.
|
||||
*
|
||||
* Ignore the message if $level is set to 'debug'.
|
||||
*
|
||||
* @param string $message
|
||||
* the message to be displayed
|
||||
* @param string $level
|
||||
* the type of the message: 'debug', 'completed', 'failed', or a valid $type
|
||||
* used by drupal_set_message()
|
||||
*/
|
||||
function migrate_ui_capture_message($message, $level) {
|
||||
if ($level != 'debug') {
|
||||
// Store each message as an array with keys 'message' and 'level'.
|
||||
global $_migrate_messages;
|
||||
$_migrate_messages[] = array(
|
||||
'message' => $message,
|
||||
'level' => $level,
|
||||
'message' => filter_xss_admin($message),
|
||||
'level' => check_plain($level),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -738,8 +762,8 @@ function migrate_migration_info($form, $form_state, $group_name, $migration_name
|
||||
foreach ($team as $group => $list) {
|
||||
$form['overview'][$group] = array(
|
||||
'#type' => 'item',
|
||||
'#title' => $group,
|
||||
'#markup' => implode(', ', $list),
|
||||
'#title' => filter_xss_admin($group),
|
||||
'#markup' => filter_xss_admin(implode(', ', $list)),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -747,7 +771,7 @@ function migrate_migration_info($form, $form_state, $group_name, $migration_name
|
||||
if (count($dependencies) > 0) {
|
||||
$form['overview']['dependencies'] = array(
|
||||
'#title' => t('Dependencies') ,
|
||||
'#markup' => implode(', ', $dependencies),
|
||||
'#markup' => filter_xss_admin(implode(', ', $dependencies)),
|
||||
'#type' => 'item',
|
||||
);
|
||||
}
|
||||
@@ -755,14 +779,14 @@ function migrate_migration_info($form, $form_state, $group_name, $migration_name
|
||||
if (count($soft_dependencies) > 0) {
|
||||
$form['overview']['soft_dependencies'] = array(
|
||||
'#title' => t('Soft Dependencies'),
|
||||
'#markup' => implode(', ', $soft_dependencies),
|
||||
'#markup' => filter_xss_admin(implode(', ', $soft_dependencies)),
|
||||
'#type' => 'item',
|
||||
);
|
||||
}
|
||||
|
||||
$form['overview']['group'] = array(
|
||||
'#title' => t('Group:'),
|
||||
'#markup' => $migration->getGroup()->getTitle(),
|
||||
'#markup' => filter_xss_admin($migration->getGroup()->getTitle()),
|
||||
'#type' => 'item',
|
||||
);
|
||||
|
||||
@@ -787,7 +811,7 @@ function migrate_migration_info($form, $form_state, $group_name, $migration_name
|
||||
|
||||
$form['overview']['description'] = array(
|
||||
'#title' => t('Description:'),
|
||||
'#markup' => $migration->getDescription(),
|
||||
'#markup' => filter_xss_admin($migration->getDescription()),
|
||||
'#type' => 'item',
|
||||
);
|
||||
|
||||
@@ -807,7 +831,7 @@ function migrate_migration_info($form, $form_state, $group_name, $migration_name
|
||||
$form['destination']['type'] = array(
|
||||
'#type' => 'item',
|
||||
'#title' => t('Type'),
|
||||
'#markup' => (string)$destination,
|
||||
'#markup' => filter_xss_admin((string) $destination),
|
||||
);
|
||||
$dest_key = $destination->getKeySchema();
|
||||
$header = array(t('Machine name'), t('Description'));
|
||||
@@ -822,7 +846,10 @@ function migrate_migration_info($form, $form_state, $group_name, $migration_name
|
||||
// Add class for mapped/unmapped. Used in summary.
|
||||
$classes[] = !isset($destination_fields[$machine_name]) ? 'migrate-error' : '';
|
||||
}
|
||||
$rows[] = array(array('data' => $machine_name, 'class' => $classes), array('data' => $description, 'class' => $classes));
|
||||
$rows[] = array(
|
||||
array('data' => check_plain($machine_name), 'class' => $classes),
|
||||
array('data' => filter_xss_admin($description), 'class' => $classes),
|
||||
);
|
||||
}
|
||||
$classes = array();
|
||||
|
||||
@@ -848,7 +875,7 @@ function migrate_migration_info($form, $form_state, $group_name, $migration_name
|
||||
$form['source']['query'] = array(
|
||||
'#type' => 'item',
|
||||
'#title' => t('Query'),
|
||||
'#markup' => '<pre>' . $source . '</pre>',
|
||||
'#markup' => '<pre>' . filter_xss_admin($source) . '</pre>',
|
||||
);
|
||||
$source_key = $migration->getMap()->getSourceKey();
|
||||
$header = array(t('Machine name'), t('Description'));
|
||||
@@ -862,7 +889,10 @@ function migrate_migration_info($form, $form_state, $group_name, $migration_name
|
||||
// Add class for mapped/unmapped. Used in summary.
|
||||
$classes = !isset($source_fields[$machine_name]) ? 'migrate-error' : '';
|
||||
}
|
||||
$rows[] = array(array('data' => $machine_name, 'class' => $classes), array('data' => $description, 'class' => $classes));
|
||||
$rows[] = array(
|
||||
array('data' => check_plain($machine_name), 'class' => $classes),
|
||||
array('data' => filter_xss_admin($description), 'class' => $classes),
|
||||
);
|
||||
}
|
||||
$classes = array();
|
||||
|
||||
@@ -887,16 +917,16 @@ function migrate_migration_info($form, $form_state, $group_name, $migration_name
|
||||
if (!is_null($source_field) && !isset($source_fields[$source_field])) {
|
||||
drupal_set_message(t('"!source" was used as source field in the
|
||||
"!destination" mapping but is not in list of source fields', array(
|
||||
'!source' => $source_field,
|
||||
'!destination' => $destination_field
|
||||
'!source' => filter_xss_admin($source_field),
|
||||
'!destination' => filter_xss_admin($destination_field),
|
||||
)),
|
||||
'warning');
|
||||
}
|
||||
if (!is_null($destination_field) && !isset($destination_fields[$destination_field])) {
|
||||
drupal_set_message(t('"!destination" was used as destination field in
|
||||
"!source" mapping but is not in list of destination fields', array(
|
||||
'!source' => $source_field,
|
||||
'!destination' => $destination_field)),
|
||||
'!source' => filter_xss_admin($source_field),
|
||||
'!destination' => filter_xss_admin($destination_field))),
|
||||
'warning');
|
||||
}
|
||||
$descriptions[$mapping->getIssueGroup()][] = $mapping;
|
||||
@@ -906,7 +936,7 @@ function migrate_migration_info($form, $form_state, $group_name, $migration_name
|
||||
foreach ($descriptions as $group => $mappings) {
|
||||
$form[$group] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => t('Mapping: !group', array('!group' => $group)),
|
||||
'#title' => t('Mapping: !group', array('!group' => filter_xss_admin($group))),
|
||||
'#group' => 'detail',
|
||||
'#attributes' => array('class' => array('migrate-mapping')),
|
||||
);
|
||||
@@ -918,7 +948,7 @@ function migrate_migration_info($form, $form_state, $group_name, $migration_name
|
||||
}
|
||||
$issue_priority = $mapping->getIssuePriority();
|
||||
if (!is_null($issue_priority)) {
|
||||
$classes[] = 'migrate-priority-' . $issue_priority;
|
||||
$classes[] = 'migrate-priority-' . drupal_html_class($issue_priority);
|
||||
$priority = MigrateFieldMapping::$priorities[$issue_priority];
|
||||
$issue_pattern = $migration->getIssuePattern();
|
||||
$issue_number = $mapping->getIssueNumber();
|
||||
@@ -942,11 +972,11 @@ function migrate_migration_info($form, $form_state, $group_name, $migration_name
|
||||
$source_field = "<em>$source_field</em>";
|
||||
}
|
||||
$row = array(
|
||||
array('data' => $destination_field, 'class' => $classes),
|
||||
array('data' => $source_field, 'class' => $classes),
|
||||
array('data' => $default, 'class' => $classes),
|
||||
array('data' => $mapping->getDescription(), 'class' => $classes),
|
||||
array('data' => $priority, 'class' => $classes),
|
||||
array('data' => filter_xss_admin($destination_field), 'class' => $classes),
|
||||
array('data' => filter_xss_admin($source_field), 'class' => $classes),
|
||||
array('data' => filter_xss_admin($default), 'class' => $classes),
|
||||
array('data' => filter_xss_admin($mapping->getDescription()), 'class' => $classes),
|
||||
array('data' => filter_xss_admin($priority), 'class' => $classes),
|
||||
);
|
||||
$rows[] = $row;
|
||||
$classes = array();
|
||||
@@ -973,7 +1003,7 @@ function migrate_migration_info($form, $form_state, $group_name, $migration_name
|
||||
*/
|
||||
function migrate_ui_edit_mappings($form, $form_state, $group_name,
|
||||
$migration_name) {
|
||||
drupal_set_title(t('Edit !migration', array('!migration' => $migration_name)));
|
||||
drupal_set_title(t('Edit !migration', array('!migration' => filter_xss_admin($migration_name))));
|
||||
|
||||
$form = array();
|
||||
$form['#tree'] = TRUE;
|
||||
@@ -1014,6 +1044,9 @@ function migrate_ui_edit_mappings($form, $form_state, $group_name,
|
||||
'#suffix' => '</div>',
|
||||
);
|
||||
|
||||
// So the theme function knows whether to include the xpath column.
|
||||
$form['field_mappings']['#is_xml_migration'] = is_a($migration, 'XMLMigration');
|
||||
|
||||
$form['source_fields'] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => t('Source fields'),
|
||||
@@ -1045,10 +1078,14 @@ function migrate_ui_edit_mappings($form, $form_state, $group_name,
|
||||
else {
|
||||
$label_format = '!description';
|
||||
}
|
||||
$label = t($label_format,
|
||||
array('!source_field' => $name, '!description' => $description));
|
||||
$short_label = t($label_format,
|
||||
array('!source_field' => $name, '!description' => $short_description));
|
||||
$label = t($label_format, array(
|
||||
'!source_field' => filter_xss_admin($name),
|
||||
'!description' => filter_xss_admin($description),
|
||||
));
|
||||
$short_label = t($label_format, array(
|
||||
'!source_field' => filter_xss_admin($name),
|
||||
'!description' => filter_xss_admin($short_description),
|
||||
));
|
||||
|
||||
$dnm_value = 0;
|
||||
|
||||
@@ -1171,6 +1208,16 @@ function migrate_ui_edit_mappings($form, $form_state, $group_name,
|
||||
'#options' => $source_migration_options,
|
||||
'#default_value' => $source_migration,
|
||||
);
|
||||
|
||||
if (is_a($mapping, 'MigrateXMLFieldMapping')) {
|
||||
/** @var MigrateXMLFieldMapping $mapping */
|
||||
$form['field_mappings'][$name]['xpath'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#default_value' => $mapping->getXpath(),
|
||||
'#size' => 20,
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1213,7 +1260,7 @@ function migrate_ui_edit_mappings($form, $form_state, $group_name,
|
||||
}
|
||||
$form['dependencies'][$machine_name] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => $machine_name,
|
||||
'#title' => check_plain($machine_name),
|
||||
'#default_value' => $default_value,
|
||||
'#options' => $dependency_options,
|
||||
);
|
||||
@@ -1275,16 +1322,21 @@ function migrate_ui_edit_mappings_submit(&$form, &$form_state) {
|
||||
$field_mappings = array();
|
||||
$default_values = array();
|
||||
$issue_group_values = array();
|
||||
$xpaths = array();
|
||||
|
||||
$migration = Migration::getInstance($machine_name);
|
||||
if (is_a($migration, 'Migration')) {
|
||||
$xml = is_a($migration, 'XMLMigration') ? TRUE : FALSE;
|
||||
$existing_mappings = $migration->getFieldMappings();
|
||||
$coded_mappings = $migration->getCodedFieldMappings();
|
||||
foreach ($form_state['values']['field_mappings'] as $destination_field => $info) {
|
||||
// Treat an empty string for the default value as NULL.
|
||||
// Treat empty strings as NULL.
|
||||
if ($info['default_value'] === '') {
|
||||
$info['default_value'] = NULL;
|
||||
}
|
||||
if ($xml && $info['xpath'] === '') {
|
||||
$info['xpath'] = NULL;
|
||||
}
|
||||
|
||||
// If this mapping matches a coded mapping but not a stored mapping, remove
|
||||
// it entirely (don't store it in the database) so the coded mapping is not
|
||||
@@ -1296,6 +1348,10 @@ function migrate_ui_edit_mappings_submit(&$form, &$form_state) {
|
||||
$coded_mappings[$destination_field]->getDefaultValue();
|
||||
$coded_source_migration =
|
||||
$coded_mappings[$destination_field]->getSourceMigration();
|
||||
if ($xml) {
|
||||
$coded_xpath =
|
||||
$coded_mappings[$destination_field]->getXpath();
|
||||
}
|
||||
if ($info['mapping'] == '-1') {
|
||||
$info['mapping'] = NULL;
|
||||
}
|
||||
@@ -1312,6 +1368,7 @@ function migrate_ui_edit_mappings_submit(&$form, &$form_state) {
|
||||
if ($info['mapping'] == $coded_source_field &&
|
||||
$info['default_value'] == $coded_default_value &&
|
||||
$info['source_migration'] == $coded_source_migration &&
|
||||
(!$xml || ($xml && ($info['xpath'] == $coded_xpath))) &&
|
||||
$dnm_matches) {
|
||||
continue;
|
||||
}
|
||||
@@ -1321,6 +1378,9 @@ function migrate_ui_edit_mappings_submit(&$form, &$form_state) {
|
||||
$default_values[$destination_field] = $info['default_value'];
|
||||
$source_migrations[$destination_field] = $info['source_migration'];
|
||||
$issue_group_values[$destination_field] = $info['issue_group'];
|
||||
if ($xml) {
|
||||
$xpaths[$destination_field] = $info['xpath'];
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($field_mappings as $destination_field => $source_field) {
|
||||
@@ -1342,10 +1402,12 @@ function migrate_ui_edit_mappings_submit(&$form, &$form_state) {
|
||||
$mapping = NULL;
|
||||
if (isset($existing_mappings[$destination_field]) &&
|
||||
$issue_group_values[$destination_field] != 0) {
|
||||
/** @var MigrateFieldMapping $old_mapping */
|
||||
$old_mapping = $existing_mappings[$destination_field];
|
||||
if ($source_field == $old_mapping->getSourceField() &&
|
||||
$default_values[$destination_field] == $old_mapping->getDefaultValue() &&
|
||||
$source_migrations[$destination_field] == $old_mapping->getSourceMigration()) {
|
||||
$source_migrations[$destination_field] == $old_mapping->getSourceMigration() &&
|
||||
(!$xml || ($xml && ($xpaths[$destination_field] == $old_mapping->getXpath())))) {
|
||||
// First, if this mapping matches a previously-stored mapping, we want to
|
||||
// preserve it as it was originally stored.
|
||||
if ($old_mapping->getMappingSource() ==
|
||||
@@ -1362,8 +1424,11 @@ function migrate_ui_edit_mappings_submit(&$form, &$form_state) {
|
||||
// We're not skipping this mapping, or preserving an old one, so create the
|
||||
// new mapping.
|
||||
if (!$mapping) {
|
||||
$mapping = new MigrateFieldMapping($destination_field, $source_field);
|
||||
$mapping = _migrate_ui_get_mapping_object($migration, $destination_field, $source_field);
|
||||
$mapping->defaultValue($default);
|
||||
if ($xml && $xpaths[$destination_field]) {
|
||||
$mapping->xpath($xpaths[$destination_field]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($issue_group_values[$destination_field]) {
|
||||
@@ -1394,7 +1459,7 @@ function migrate_ui_edit_mappings_submit(&$form, &$form_state) {
|
||||
// If it is marked DNM in the UI, but is not ignored in the code,
|
||||
// generate a DNM mapping.
|
||||
if ($value && !$code_ignored) {
|
||||
$mapping = new MigrateFieldMapping(NULL, $source_field);
|
||||
$mapping = _migrate_ui_get_mapping_object($migration, NULL, $source_field);
|
||||
$mapping->issueGroup(t('DNM'));
|
||||
$arguments['field_mappings'][] = $mapping;
|
||||
}
|
||||
@@ -1410,7 +1475,7 @@ function migrate_ui_edit_mappings_submit(&$form, &$form_state) {
|
||||
}
|
||||
}
|
||||
if (!$mapping_found) {
|
||||
$mapping = new MigrateFieldMapping(NULL, $source_field);
|
||||
$mapping = _migrate_ui_get_mapping_object($migration, NULL, $source_field);
|
||||
$arguments['field_mappings'][] = $mapping;
|
||||
}
|
||||
}
|
||||
@@ -1436,6 +1501,22 @@ function migrate_ui_edit_mappings_submit(&$form, &$form_state) {
|
||||
"admin/content/migrate/groups/$group_name/$machine_name";
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a field mapping object of the appropriate class.
|
||||
*
|
||||
* @param $migration
|
||||
*
|
||||
* @return MigrateFieldMapping
|
||||
*/
|
||||
function _migrate_ui_get_mapping_object($migration, $destination, $source) {
|
||||
if (is_a($migration, 'XMLMigration')) {
|
||||
return new MigrateXMLFieldMapping($destination, $source);
|
||||
}
|
||||
else {
|
||||
return new MigrateFieldMapping($destination, $source);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Revert callback for the edit mappings form. Remove any field mappings that
|
||||
* were defined through the UI.
|
||||
@@ -1469,6 +1550,9 @@ function theme_migrate_ui_field_mapping_form($variables) {
|
||||
if (!empty($elements)) {
|
||||
$header = array(t('DNM'), t('Destination field'), t('Source field'),
|
||||
t('Default value'), t('Source migration'));
|
||||
if (!empty($form['#is_xml_migration'])) {
|
||||
$header[] = t('Xpath');
|
||||
}
|
||||
$rows = array();
|
||||
foreach ($elements as $mapping_key) {
|
||||
$row = array();
|
||||
@@ -1479,6 +1563,9 @@ function theme_migrate_ui_field_mapping_form($variables) {
|
||||
$row[] = drupal_render($form[$mapping_key]['mapping']);
|
||||
$row[] = drupal_render($form[$mapping_key]['default_value']);
|
||||
$row[] = drupal_render($form[$mapping_key]['source_migration']);
|
||||
if (!empty($form['#is_xml_migration'])) {
|
||||
$row[] = drupal_render($form[$mapping_key]['xpath']);
|
||||
}
|
||||
$rows[] = $row;
|
||||
}
|
||||
$output .= theme('table', array('header' => $header, 'rows' => $rows));
|
||||
@@ -1536,7 +1623,11 @@ function migrate_ui_messages($group_name, $migration_name) {
|
||||
$header = array();
|
||||
// Add a table header for each source key in the migration's map.
|
||||
foreach ($source_key as $key => $map_info) {
|
||||
$header[] = array('data' => $map_info['description'], 'field' => $source_key_map[$key], 'sort' => 'asc');
|
||||
$header[] = array(
|
||||
'data' => filter_xss_admin($map_info['description']),
|
||||
'field' => $source_key_map[$key],
|
||||
'sort' => 'asc',
|
||||
);
|
||||
}
|
||||
|
||||
$header[] = array('data' => t('Level'), 'field' => 'level');
|
||||
@@ -1558,12 +1649,18 @@ function migrate_ui_messages($group_name, $migration_name) {
|
||||
// Add a table column for each source key.
|
||||
foreach ($source_key_map_flipped as $source_key => $source_field) {
|
||||
$row[] = array(
|
||||
'data' => $message->{$source_key},
|
||||
'data' => filter_xss_admin($message->{$source_key}),
|
||||
'class' => $classes,
|
||||
);
|
||||
}
|
||||
$row[] = array('data' => $migration->getMessageLevelName($message->level), 'class' => $classes);
|
||||
$row[] = array('data' => $message->message, 'class' => $classes);
|
||||
$row[] = array(
|
||||
'data' => filter_xss_admin($migration->getMessageLevelName($message->level)),
|
||||
'class' => $classes,
|
||||
);
|
||||
$row[] = array(
|
||||
'data' => filter_xss_admin($message->message),
|
||||
'class' => $classes,
|
||||
);
|
||||
|
||||
$rows[] = $row;
|
||||
|
||||
@@ -1642,7 +1739,10 @@ function migrate_ui_configure_form($form, &$form_state) {
|
||||
if (!class_exists($row->class_name)) {
|
||||
$migrations[] = $row->machine_name;
|
||||
$migration_list .= '<li>' . t('!migration (class !class)',
|
||||
array('!migration' => $row->machine_name, '!class' => $row->class_name)) . "</li>\n";
|
||||
array(
|
||||
'!migration' => filter_xss_admin($row->machine_name),
|
||||
'!class' => filter_xss_admin($row->class_name),
|
||||
)) . "</li>\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1680,7 +1780,7 @@ function migrate_ui_configure_form($form, &$form_state) {
|
||||
// Configure background imports if the drush command has been set.
|
||||
$drush_path = trim(variable_get('migrate_drush_path', ''));
|
||||
$drush_validated = FALSE;
|
||||
if ($drush_path) {
|
||||
if ($drush_path && is_executable($drush_path)) {
|
||||
// Try running a drush status command to verify it's properly configured.
|
||||
$uri = $GLOBALS['base_url'];
|
||||
$uid = $GLOBALS['user']->uid;
|
||||
@@ -1818,9 +1918,9 @@ function migrate_ui_configure_form($form, &$form_state) {
|
||||
->condition('type', 'class')
|
||||
->execute()
|
||||
->fetchField();
|
||||
$row['module'] = $module;
|
||||
$row['class'] = $class_name;
|
||||
$row['types'] = implode(', ', $handler->getTypesHandled());
|
||||
$row['module'] = check_plain($module);
|
||||
$row['class'] = check_plain($class_name);
|
||||
$row['types'] = filter_xss_admin(implode(', ', $handler->getTypesHandled()));
|
||||
$default_values[$class_name] = !in_array($class_name, $disabled);
|
||||
$rows[$class_name] = $row;
|
||||
}
|
||||
@@ -1855,9 +1955,9 @@ function migrate_ui_configure_form($form, &$form_state) {
|
||||
->condition('type', 'class')
|
||||
->execute()
|
||||
->fetchField();
|
||||
$row['module'] = $module;
|
||||
$row['class'] = $class_name;
|
||||
$row['types'] = implode(', ', $handler->getTypesHandled());
|
||||
$row['module'] = check_plain($module);
|
||||
$row['class'] = check_plain($class_name);
|
||||
$row['types'] = filter_xss_admin(implode(', ', $handler->getTypesHandled()));
|
||||
$default_values[$class_name] = !in_array($class_name, $disabled);
|
||||
$rows[$class_name] = $row;
|
||||
}
|
||||
|
@@ -216,7 +216,7 @@ class MigrateDestinationComment extends MigrateDestinationEntity {
|
||||
}
|
||||
|
||||
// Validate field data prior to saving.
|
||||
field_attach_validate('comment', $comment);
|
||||
MigrateDestinationEntity::fieldAttachValidate('comment', $comment);
|
||||
|
||||
migrate_instrument_start('comment_save');
|
||||
comment_save($comment);
|
||||
|
@@ -176,4 +176,34 @@ abstract class MigrateDestinationEntity extends MigrateDestination {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform field validation against the field data in an entity. Wraps
|
||||
* field_attach_validate to handle exceptions cleanly and provide maximum
|
||||
* information for identifying the cause of validation errors.
|
||||
*
|
||||
* @param $entity_type
|
||||
* The type of $entity; e.g. 'node' or 'user'.
|
||||
* @param $entity
|
||||
* The entity with fields to validate.
|
||||
*/
|
||||
static public function fieldAttachValidate($entity_type, $entity) {
|
||||
try {
|
||||
field_attach_validate($entity_type, $entity);
|
||||
}
|
||||
catch (FieldValidationException $e) {
|
||||
$migration = Migration::currentMigration();
|
||||
foreach ($e->errors as $field_name => $field_errors) {
|
||||
foreach ($field_errors as $langcode => $errors) {
|
||||
foreach ($errors as $delta => $error_list) {
|
||||
foreach ($error_list as $index => $error) {
|
||||
$message = $error['message'];
|
||||
$migration->saveMessage(t('Field validation error for !field_name: !message',
|
||||
array('!field_name' => $field_name, '!message' => $message)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -342,8 +342,11 @@ class MigrateTextFieldHandler extends MigrateFieldHandler {
|
||||
$fields['format'] = t('Subfield: <a href="@doc">Text format for the field</a>',
|
||||
array('@doc' => 'http://drupal.org/node/1224042#format'));
|
||||
}
|
||||
$fields['language'] = t('Subfield: <a href="@doc">Language for the field</a>',
|
||||
array('@doc' => 'http://drupal.org/node/1224042#language'));
|
||||
$field = field_info_field($instance['field_name']);
|
||||
if (field_is_translatable($instance['entity_type'], $field)) {
|
||||
$fields['language'] = t('Subfield: <a href="@doc">Language for the field</a>',
|
||||
array('@doc' => 'http://drupal.org/node/1224042#language'));
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
|
||||
@@ -469,7 +472,7 @@ class MigrateTaxonomyTermReferenceFieldHandler extends MigrateFieldHandler {
|
||||
else {
|
||||
$arguments = array();
|
||||
}
|
||||
if (empty($values[0])) {
|
||||
if (count($values) == 1 && empty($values[0])) {
|
||||
$values = array();
|
||||
}
|
||||
|
||||
@@ -530,7 +533,7 @@ class MigrateTaxonomyTermReferenceFieldHandler extends MigrateFieldHandler {
|
||||
// This term is being created with no fields, but we should still call
|
||||
// field_attach_validate() before saving, as that invokes
|
||||
// hook_field_attach_validate().
|
||||
field_attach_validate('taxonomy_term', $new_term);
|
||||
MigrateDestinationEntity::fieldAttachValidate('taxonomy_term', $new_term);
|
||||
|
||||
taxonomy_term_save($new_term);
|
||||
$tids[] = $new_term->tid;
|
||||
@@ -588,9 +591,13 @@ abstract class MigrateFileFieldBaseHandler extends MigrateFieldHandler {
|
||||
$fields = array(
|
||||
'file_class' => t('Option: <a href="@doc">Implementation of MigrateFile to use</a>',
|
||||
array('@doc' => 'http://drupal.org/node/1540106#file_class')),
|
||||
'language' => t('Subfield: Language for the field'),
|
||||
);
|
||||
|
||||
$field = field_info_field($instance['field_name']);
|
||||
if (field_is_translatable($instance['entity_type'], $field)) {
|
||||
$fields['language'] = t('Subfield: Language for the field');
|
||||
}
|
||||
|
||||
// If we can identify the file class mapped to this field, pick up the
|
||||
// subfields specific to that class.
|
||||
if ($migration) {
|
||||
|
@@ -389,15 +389,16 @@ class MigrateFileUri extends MigrateFile {
|
||||
// Perform the copy operation, with a cleaned-up path.
|
||||
$this->sourcePath = self::urlencode($this->sourcePath);
|
||||
}
|
||||
if (!@copy($this->sourcePath, $destination)) {
|
||||
$migration = Migration::currentMigration();
|
||||
$migration->saveMessage(t('The specified file %file could not be copied to %destination.',
|
||||
array('%file' => $this->sourcePath, '%destination' => $destination)));
|
||||
return FALSE;
|
||||
}
|
||||
else {
|
||||
try {
|
||||
copy($this->sourcePath, $destination);
|
||||
return TRUE;
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$migration = Migration::currentMigration();
|
||||
$migration->saveMessage(t('The specified file %file could not be copied to %destination: "%exception_msg"',
|
||||
array('%file' => $this->sourcePath, '%destination' => $destination, '%exception_msg' => $e->getMessage())));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -263,7 +263,7 @@ class MigrateDestinationNode extends MigrateDestinationEntity {
|
||||
}
|
||||
|
||||
// Validate field data prior to saving.
|
||||
field_attach_validate('node', $node);
|
||||
MigrateDestinationEntity::fieldAttachValidate('node', $node);
|
||||
|
||||
migrate_instrument_start('node_save');
|
||||
node_save($node);
|
||||
|
@@ -258,7 +258,7 @@ class MigrateDestinationTerm extends MigrateDestinationEntity {
|
||||
}
|
||||
|
||||
// Validate field data prior to saving.
|
||||
field_attach_validate('taxonomy_term', $term);
|
||||
MigrateDestinationEntity::fieldAttachValidate('taxonomy_term', $term);
|
||||
|
||||
migrate_instrument_start('taxonomy_term_save');
|
||||
$status = taxonomy_term_save($term);
|
||||
|
@@ -231,7 +231,7 @@ class MigrateDestinationUser extends MigrateDestinationEntity {
|
||||
}
|
||||
|
||||
// Validate field data prior to saving.
|
||||
field_attach_validate('user', $account);
|
||||
MigrateDestinationEntity::fieldAttachValidate('user', $account);
|
||||
|
||||
migrate_instrument_start('user_save');
|
||||
$newaccount = user_save($old_account, (array)$account);
|
||||
|
@@ -198,8 +198,8 @@ class MigrateSourceList extends MigrateSource {
|
||||
list(, $id) = each($ids);
|
||||
$row->$key_name = $id;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return $row;
|
||||
}
|
||||
|
@@ -187,8 +187,8 @@ class MigrateSourceMultiItems extends MigrateSource {
|
||||
$sourceKey = $this->activeMap->getSourceKey();
|
||||
$key_name = key($sourceKey);
|
||||
$row->$key_name = $id;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return $row;
|
||||
}
|
||||
|
@@ -376,14 +376,29 @@ class MigrateSourceSQL extends MigrateSource {
|
||||
// 3. If we are using highwater marks, also include rows above the mark.
|
||||
// But, include all rows if the highwater mark is not set.
|
||||
if (isset($this->highwaterField['name']) && $this->activeMigration->getHighwater() !== '') {
|
||||
if (isset($this->highwaterField['alias'])) {
|
||||
$highwater = $this->highwaterField['alias'] . '.' . $this->highwaterField['name'];
|
||||
// But, if there are any existing items marked as needing update which
|
||||
// fall below the highwater mark, and map_joinable is FALSE, those
|
||||
// items will be skipped. Thus, in that case do not add the highwater
|
||||
// optimization to the query.
|
||||
$add_highwater_condition = TRUE;
|
||||
if (!$this->mapJoinable) {
|
||||
$count_needs_update = db_query('SELECT COUNT(*) FROM {' .
|
||||
$this->activeMap->getQualifiedMapTable() . '} WHERE needs_update = 1')
|
||||
->fetchField();
|
||||
if ($count_needs_update > 0) {
|
||||
$add_highwater_condition = FALSE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$highwater = $this->highwaterField['name'];
|
||||
if ($add_highwater_condition) {
|
||||
if (isset($this->highwaterField['alias'])) {
|
||||
$highwater = $this->highwaterField['alias'] . '.' . $this->highwaterField['name'];
|
||||
}
|
||||
else {
|
||||
$highwater = $this->highwaterField['name'];
|
||||
}
|
||||
$conditions->condition($highwater, $this->activeMigration->getHighwater(), '>');
|
||||
$condition_added = TRUE;
|
||||
}
|
||||
$conditions->condition($highwater, $this->activeMigration->getHighwater(), '>');
|
||||
$condition_added = TRUE;
|
||||
}
|
||||
if ($condition_added) {
|
||||
$this->query->condition($conditions);
|
||||
|
@@ -69,6 +69,11 @@ class MigrateSQLMap extends MigrateMap {
|
||||
*/
|
||||
protected $ensured;
|
||||
|
||||
/**
|
||||
* Provide caching for Source or Desination Map Lookups.
|
||||
*/
|
||||
protected $cacheMapLookups;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
@@ -92,6 +97,13 @@ class MigrateSQLMap extends MigrateMap {
|
||||
$this->trackLastImported = TRUE;
|
||||
}
|
||||
|
||||
if (isset($options['cache_map_lookups'])) {
|
||||
$this->cacheMapLookups = $options['cache_map_lookups'];
|
||||
}
|
||||
else {
|
||||
$this->cacheMapLookups = FALSE;
|
||||
}
|
||||
|
||||
$this->connection = Database::getConnection('default', $connection_key);
|
||||
|
||||
// Default generated table names, limited to 63 characters
|
||||
@@ -302,6 +314,16 @@ class MigrateSQLMap extends MigrateMap {
|
||||
*/
|
||||
public function lookupSourceID(array $destination_id) {
|
||||
migrate_instrument_start('lookupSourceID');
|
||||
// Try a cache lookup if enabled.
|
||||
if ($this->cacheMapLookups) {
|
||||
$cache = &drupal_static($this->mapTable . '_sourceIDCache');
|
||||
$serialized = json_encode($destination_id);
|
||||
if (isset($cache[$serialized])) {
|
||||
migrate_instrument_stop('lookupSourceID');
|
||||
return $cache[$serialized];
|
||||
}
|
||||
}
|
||||
|
||||
$query = $this->connection->select($this->mapTable, 'map')
|
||||
->fields('map', $this->sourceKeyMap);
|
||||
foreach ($this->destinationKeyMap as $key_name) {
|
||||
@@ -309,6 +331,12 @@ class MigrateSQLMap extends MigrateMap {
|
||||
}
|
||||
$result = $query->execute();
|
||||
$source_id = $result->fetchAssoc();
|
||||
|
||||
// Store the id in a cache if enabled.
|
||||
if ($this->cacheMapLookups) {
|
||||
$cache[$serialized] = $destination_id;
|
||||
}
|
||||
|
||||
migrate_instrument_stop('lookupSourceID');
|
||||
return $source_id;
|
||||
}
|
||||
@@ -324,6 +352,16 @@ class MigrateSQLMap extends MigrateMap {
|
||||
*/
|
||||
public function lookupDestinationID(array $source_id) {
|
||||
migrate_instrument_start('lookupDestinationID');
|
||||
// Try a cache lookup if enabled.
|
||||
if ($this->cacheMapLookups) {
|
||||
$cache = &drupal_static($this->mapTable . '_destinationIDCache');
|
||||
$serialized = json_encode($source_id);
|
||||
if (isset($cache[$serialized])) {
|
||||
migrate_instrument_stop('lookupDestinationID');
|
||||
return $cache[$serialized];
|
||||
}
|
||||
}
|
||||
|
||||
$query = $this->connection->select($this->mapTable, 'map')
|
||||
->fields('map', $this->destinationKeyMap);
|
||||
foreach ($this->sourceKeyMap as $key_name) {
|
||||
@@ -331,10 +369,15 @@ class MigrateSQLMap extends MigrateMap {
|
||||
}
|
||||
$result = $query->execute();
|
||||
$destination_id = $result->fetchAssoc();
|
||||
|
||||
// Store the id in a cache if enabled.
|
||||
if ($this->cacheMapLookups) {
|
||||
$cache[$serialized] = $destination_id;
|
||||
}
|
||||
|
||||
migrate_instrument_stop('lookupDestinationID');
|
||||
return $destination_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called upon import of one record, we record a mapping from the source key
|
||||
* to the destination key. Also may be called, setting the third parameter to
|
||||
|
@@ -40,17 +40,13 @@ class MigrateImportOptionsTest extends DrupalWebTestCase {
|
||||
|
||||
$result = $migration->processImport($options);
|
||||
|
||||
$this->verbose(print_r($timers, 1));
|
||||
$successes = $migration->importedCount();
|
||||
$this->verbose("Total successes: {$successes}");
|
||||
$assertion = format_plural($limit, 'The migration successfully processed 1 item.',
|
||||
'The migration successfully processed @count items.');
|
||||
$this->assertEqual($limit, $successes, $assertion);
|
||||
|
||||
$prepare_row_count = $timers['BeerTermMigration prepareRow']['count'];
|
||||
$this->verbose("prepareRow() count: {$prepare_row_count}");
|
||||
$processed = $migration->processedCount();
|
||||
$this->verbose("Total processed count: {$processed}");
|
||||
$assertion = format_plural($processed, 'The migration executed processRow() on 1 item.',
|
||||
'The migration executed processRow() on @count items.');
|
||||
$this->assertEqual($prepare_row_count, $processed, $assertion);
|
||||
|
Reference in New Issue
Block a user