Problem/Motivation
The MigrateSkipProcessException causes the processed value is set to NULL, no more plugins are used and the the value is not migrated.
See \Drupal\migrate\MigrateExecutable::processRow
In some cases, we want to skip the process (it means to escape from the chain of process plugins), but keep the current value and migrate the current value.
Proposed resolution
Create a way for a process plugin to declare itself as final, which will prevent additional process plugins from running for that pipeline. This both solves the original problem, (by allowing a plugin to return the original value and declaring itself final) AND provides us a path towards removing the ugly Exception-As-A-Signal which is MigrateSkipProcessException (by having the plugin return null or void and declaring itself as final)
I extended the MigrateSkipProcessException with a keepValue parameter, which is set to FALSE by default.
In case I need to keep the value, I throw the MigrateSkipProcessException('Message or NULL', TRUE).
The \Drupal\migrate\MigrateExecutable::processRow then tests the option and set the value to NULL only when the keepValue option is set to FALSE.
Example:
-
plugin: entity_lookup
-
plugin: log
-
# All, not null values end here and are migrated.
plugin: continue_if_null
-
# This plugin is processed only if the value from above is NULL.
plugin: migration_lookup
source: alternative_value
class ContinueIfNull extends ProcessPluginBase {
/**
* Continue if the value is NULL.
*
* @throws \Drupal\migrate\MigrateSkipProcessException
*/
public function transform($value, ...) {
if (!is_null($value)) {
throw new MigrateSkipProcessException(NULL, TRUE);
}
return NULL;
}
The alternative way is to use a new exception, like MigrateFinalProcessException, but I chose the way described above.