diff --git a/core/lib/Drupal/Core/Field/Plugin/migrate/field/Email.php b/core/lib/Drupal/Core/Field/Plugin/migrate/field/Email.php index 3b490f0f19..1649700f4c 100644 --- a/core/lib/Drupal/Core/Field/Plugin/migrate/field/Email.php +++ b/core/lib/Drupal/Core/Field/Plugin/migrate/field/Email.php @@ -11,7 +11,9 @@ * core = {6,7}, * type_map = { * "email" = "email" - * } + * }, + * source_module = "email", + * destination_module = "core" * ) */ class Email extends FieldPluginBase { diff --git a/core/lib/Drupal/Core/Field/Plugin/migrate/field/d7/EntityReference.php b/core/lib/Drupal/Core/Field/Plugin/migrate/field/d7/EntityReference.php index 2e61589fb5..f45e95d2cc 100644 --- a/core/lib/Drupal/Core/Field/Plugin/migrate/field/d7/EntityReference.php +++ b/core/lib/Drupal/Core/Field/Plugin/migrate/field/d7/EntityReference.php @@ -10,7 +10,9 @@ * type_map = { * "entityreference" = "entity_reference", * }, - * core = {7} + * core = {7}, + * source_module = "entityreference", + * destination_module = "core" * ) */ class EntityReference extends FieldPluginBase {} diff --git a/core/lib/Drupal/Core/Field/Plugin/migrate/field/d7/NumberField.php b/core/lib/Drupal/Core/Field/Plugin/migrate/field/d7/NumberField.php index 90803288e4..cf2f4567a8 100644 --- a/core/lib/Drupal/Core/Field/Plugin/migrate/field/d7/NumberField.php +++ b/core/lib/Drupal/Core/Field/Plugin/migrate/field/d7/NumberField.php @@ -12,7 +12,9 @@ * "number_decimal" = "decimal", * "number_float" = "float", * }, - * core = {7} + * core = {7}, + * source_module = "number", + * destination_module = "core" * ) */ class NumberField extends FieldPluginBase {} diff --git a/core/modules/datetime/src/Plugin/migrate/field/DateField.php b/core/modules/datetime/src/Plugin/migrate/field/DateField.php index 0dd56c9acf..c3e611a4d4 100644 --- a/core/modules/datetime/src/Plugin/migrate/field/DateField.php +++ b/core/modules/datetime/src/Plugin/migrate/field/DateField.php @@ -14,7 +14,9 @@ * "datestamp" = "timestamp", * "datetime" = "datetime", * }, - * core = {6,7} + * core = {6,7}, + * source_module = "date", + * destination_module = "datetime" * ) */ class DateField extends FieldPluginBase { diff --git a/core/modules/datetime/src/Plugin/migrate/field/d6/DateField.php b/core/modules/datetime/src/Plugin/migrate/field/d6/DateField.php index c4e7b4981d..c19d7bdfe9 100644 --- a/core/modules/datetime/src/Plugin/migrate/field/d6/DateField.php +++ b/core/modules/datetime/src/Plugin/migrate/field/d6/DateField.php @@ -16,7 +16,8 @@ * "datestamp" = "timestamp", * "datetime" = "datetime", * }, - * core = {6} + * core = {6}, + * source_module = "date" * ) * * @deprecated in Drupal 8.4.x, to be removed before Drupal 9.0.x. Use diff --git a/core/modules/field/src/Plugin/migrate/source/d7/Field.php b/core/modules/field/src/Plugin/migrate/source/d7/Field.php index 9e92619f8e..da9e037328 100644 --- a/core/modules/field/src/Plugin/migrate/source/d7/Field.php +++ b/core/modules/field/src/Plugin/migrate/source/d7/Field.php @@ -15,7 +15,7 @@ * * @MigrateSource( * id = "d7_field", - * source_module = "field" + * source_module = "field_sql_storage" * ) */ class Field extends DrupalSqlBase { diff --git a/core/modules/file/src/Plugin/migrate/field/d6/FileField.php b/core/modules/file/src/Plugin/migrate/field/d6/FileField.php index 930c13b030..ef512b1578 100644 --- a/core/modules/file/src/Plugin/migrate/field/d6/FileField.php +++ b/core/modules/file/src/Plugin/migrate/field/d6/FileField.php @@ -9,7 +9,9 @@ /** * @MigrateField( * id = "filefield", - * core = {6} + * core = {6}, + * source_module = "file", + * destination_module = "file" * ) */ class FileField extends FieldPluginBase { diff --git a/core/modules/file/src/Plugin/migrate/field/d7/FileField.php b/core/modules/file/src/Plugin/migrate/field/d7/FileField.php index 4243d43c42..2d7e7ba387 100644 --- a/core/modules/file/src/Plugin/migrate/field/d7/FileField.php +++ b/core/modules/file/src/Plugin/migrate/field/d7/FileField.php @@ -8,7 +8,9 @@ /** * @MigrateField( * id = "file", - * core = {7} + * core = {7}, + * source_module = "file", + * destination_module = "file" * ) */ class FileField extends D6FileField { diff --git a/core/modules/file/src/Plugin/migrate/field/d7/ImageField.php b/core/modules/file/src/Plugin/migrate/field/d7/ImageField.php index 7783ae2886..fea19c667b 100644 --- a/core/modules/file/src/Plugin/migrate/field/d7/ImageField.php +++ b/core/modules/file/src/Plugin/migrate/field/d7/ImageField.php @@ -8,7 +8,9 @@ /** * @MigrateField( * id = "image", - * core = {7} + * core = {7}, + * source_module = "image", + * destination_module = "file" * ) */ class ImageField extends FieldPluginBase { diff --git a/core/modules/link/src/Plugin/migrate/field/d6/LinkField.php b/core/modules/link/src/Plugin/migrate/field/d6/LinkField.php index 0d03656ad8..8b7e68d2f7 100644 --- a/core/modules/link/src/Plugin/migrate/field/d6/LinkField.php +++ b/core/modules/link/src/Plugin/migrate/field/d6/LinkField.php @@ -10,7 +10,9 @@ * id = "link", * core = {6}, * type_map = { - * "link_field" = "link" + * "link_field" = "link", + * source_module = "link", + * destination_module = "link" * } * ) */ diff --git a/core/modules/link/src/Plugin/migrate/field/d7/LinkField.php b/core/modules/link/src/Plugin/migrate/field/d7/LinkField.php index bb71418aba..fe7ee8bfa1 100644 --- a/core/modules/link/src/Plugin/migrate/field/d7/LinkField.php +++ b/core/modules/link/src/Plugin/migrate/field/d7/LinkField.php @@ -12,7 +12,9 @@ * type_map = { * "link_field" = "link" * } - * ) + * source_module = "link", + * destination_module = "link" + * ) * * This plugin provides the exact same functionality as the Drupal 6 "link" * plugin with the exception that the plugin ID "link_field" is used in the diff --git a/core/modules/migrate_drupal/src/Annotation/MigrateField.php b/core/modules/migrate_drupal/src/Annotation/MigrateField.php index ad78bc924d..7192749837 100644 --- a/core/modules/migrate_drupal/src/Annotation/MigrateField.php +++ b/core/modules/migrate_drupal/src/Annotation/MigrateField.php @@ -51,4 +51,26 @@ public function __construct($values) { */ public $core = []; + /** + * Identifies the system providing the data the field plugin will read. + * + * The field plugin itself determines how the value is used. For example, + * Migrate Drupal's field plugins expect source_module to be the name of a + * module that must be installed and enabled in the source database. + * + * @var string + */ + public $source_module; + + /** + * Identifies the system handling the data the destination plugin will write. + * + * The destination plugin itself determines how the value is used. For + * example, Migrate Drupal's destination plugins expect destination_module to + * be the name of a module that must be installed on the destination. + * + * @var string + */ + public $destination_module; + } diff --git a/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php b/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php index ffe43136fb..0ed2f3a75c 100644 --- a/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php +++ b/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php @@ -2,6 +2,7 @@ namespace Drupal\migrate_drupal_ui\Form; +use Drupal\Component\Plugin\Exception\PluginNotFoundException; use Drupal\Core\Datetime\DateFormatterInterface; use Drupal\Core\Form\ConfirmFormBase; use Drupal\Core\Form\FormStateInterface; @@ -466,6 +467,32 @@ public function buildConfirmForm(array $form, FormStateInterface $form_state) { ksort($table_data[$source_module]); } + // Now get the field migrations. + $field_types = \Drupal::service('plugin.manager.field.field_type')->getDefinitions(); + /** @var \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManager $field_plugin_manager */ + $field_plugin_manager = \Drupal::service('plugin.manager.migrate.field'); + /** @var \Drupal\Core\Extension\ModuleHandlerInterface $module_handler */ + $module_handler = \Drupal::service('module_handler'); + $field_plugin_ids = []; + $migrated_field_table_data = []; + foreach ($field_types as $field_type => $value) { + try { + $plugin_id = $field_plugin_manager->getPluginIdFromFieldType($field_type, ['core' => $version]); + $field_def = $field_plugin_manager->getDefinition($plugin_id); + $source_module = $field_def['source_module']; + $destination_module = $field_def['destination_module']; + $migration_id = 'field'; + if (($destination_module == 'core') || $module_handler->moduleExists($destination_module)) { + $migrated_field_table_data[$source_module][$destination_module][$migration_id] = $plugin_id . '_field'; + } + $field_plugin_ids[] = $plugin_id; + } + catch (PluginNotFoundException $ex) { + continue; + } + } + $table_data = array_merge($table_data, $migrated_field_table_data); + // Fetch the system data at the first opportunity. $system_data = $form_state->get('system_data'); $unmigrated_source_modules = array_diff_key($system_data['module'], $table_data); @@ -560,7 +587,8 @@ public function submitConfirmForm(array &$form, FormStateInterface $form_state) ], ], 'finished' => [ - MigrateUpgradeImportBatch::class, 'finished', + MigrateUpgradeImportBatch::class, + 'finished', ], ]; batch_set($batch); diff --git a/core/modules/options/src/Plugin/migrate/field/d7/ListField.php b/core/modules/options/src/Plugin/migrate/field/d7/ListField.php index fff29ee177..714c364b8f 100644 --- a/core/modules/options/src/Plugin/migrate/field/d7/ListField.php +++ b/core/modules/options/src/Plugin/migrate/field/d7/ListField.php @@ -12,7 +12,9 @@ * "list_integer" = "list_integer", * "list_text" = "list_string", * }, - * core = {7} + * core = {7}, + * source_module = "list", + * destination_module = "options" * ) */ class ListField extends FieldPluginBase {} diff --git a/core/modules/rest/src/RequestHandler.php b/core/modules/rest/src/RequestHandler.php index 4b7020c128..e5437ccb68 100644 --- a/core/modules/rest/src/RequestHandler.php +++ b/core/modules/rest/src/RequestHandler.php @@ -2,10 +2,8 @@ namespace Drupal\rest; -use Drupal\Component\Utility\ArgumentsResolver; use Drupal\Core\Cache\CacheableResponseInterface; use Drupal\Core\DependencyInjection\ContainerInjectionInterface; -use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Routing\RouteMatchInterface; use Symfony\Component\DependencyInjection\ContainerAwareInterface; @@ -121,17 +119,17 @@ public function handle(RouteMatchInterface $route_match, Request $request) { // Determine the request parameters that should be passed to the resource // plugin. - $argument_resolver = $this->createArgumentResolver($route_match, $unserialized, $request); - try { - $arguments = $argument_resolver->getArguments([$resource, $method]); - } - catch (\RuntimeException $exception) { - @trigger_error('Passing in arguments the legacy way is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Provide the right parameter names in the method, similar to controllers. See https://www.drupal.org/node/2894819', E_USER_DEPRECATED); - $arguments = $this->getLegacyParameters($route_match, $unserialized, $request); + $route_parameters = $route_match->getParameters(); + $parameters = []; + // Filter out all internal parameters starting with "_". + foreach ($route_parameters as $key => $parameter) { + if ($key{0} !== '_') { + $parameters[] = $parameter; + } } // Invoke the operation on the resource plugin. - $response = call_user_func_array([$resource, $method], $arguments); + $response = call_user_func_array([$resource, $method], array_merge($parameters, [$unserialized, $request])); if ($response instanceof CacheableResponseInterface) { // Add rest config's cache tags. @@ -141,100 +139,4 @@ public function handle(RouteMatchInterface $route_match, Request $request) { return $response; } - /** - * Creates an argument resolver, containing all REST parameters. - * - * @param \Drupal\Core\Routing\RouteMatchInterface $route_match - * The route match. - * @param mixed $unserialized - * The unserialized data. - * @param \Symfony\Component\HttpFoundation\Request $request - * The request. - * - * @return \Drupal\Component\Utility\ArgumentsResolver - * An instance of the argument resolver containing information like the - * 'entity' we process and the 'unserialized' content from the request body. - */ - protected function createArgumentResolver(RouteMatchInterface $route_match, $unserialized, Request $request) { - $route = $route_match->getRouteObject(); - - // Defaults for the parameters defined on the route object need to be added - // to the raw arguments. - $raw_route_arguments = $route_match->getRawParameters()->all() + $route->getDefaults(); - - $route_arguments = $route_match->getParameters()->all(); - $upcasted_route_arguments = $route_arguments; - - // For request methods that have request bodies, ResourceInterface plugin - // methods historically receive the unserialized request body as the N+1th - // method argument, where N is the number of route parameters specified on - // the accompanying route. To be able to use the argument resolver, which is - // not based on position but on name and typehint, specify commonly used - // names here. Similarly, those methods receive the original stored object - // as the first method argument. - - $route_arguments_entity = NULL; - // Try to find a parameter which is an entity. - foreach ($route_arguments as $value) { - if ($value instanceof EntityInterface) { - $route_arguments_entity = $value; - break; - } - } - - if (in_array($request->getMethod(), ['PATCH', 'POST'], TRUE)) { - $upcasted_route_arguments['entity'] = $unserialized; - $upcasted_route_arguments['data'] = $unserialized; - $upcasted_route_arguments['unserialized'] = $unserialized; - $upcasted_route_arguments['original_entity'] = $route_arguments_entity; - } - else { - $upcasted_route_arguments['entity'] = $route_arguments_entity; - } - - // Parameters which are not defined on the route object, but still are - // essential for access checking are passed as wildcards to the argument - // resolver. - $wildcard_arguments = [$route, $route_match]; - $wildcard_arguments[] = $request; - if (isset($unserialized)) { - $wildcard_arguments[] = $unserialized; - } - - return new ArgumentsResolver($raw_route_arguments, $upcasted_route_arguments, $wildcard_arguments); - } - - /** - * Provides the parameter usable without an argument resolver. - * - * This creates an list of parameters in a statically defined order. - * - * @param \Drupal\Core\Routing\RouteMatchInterface $route_match - * The route match - * @param mixed $unserialized - * The unserialized data. - * @param \Symfony\Component\HttpFoundation\Request $request - * The request. - * - * @deprecated in Drupal 8.4.0, will be removed before Drupal 9.0.0. Use the - * argument resolver method instead, see ::createArgumentResolver(). - * - * @see https://www.drupal.org/node/2894819 - * - * @return array - * An array of parameters. - */ - protected function getLegacyParameters(RouteMatchInterface $route_match, $unserialized, Request $request) { - $route_parameters = $route_match->getParameters(); - $parameters = []; - // Filter out all internal parameters starting with "_". - foreach ($route_parameters as $key => $parameter) { - if ($key{0} !== '_') { - $parameters[] = $parameter; - } - } - - return array_merge($parameters, [$unserialized, $request]); - } - } diff --git a/core/modules/rest/tests/modules/rest_test/src/Plugin/rest/resource/NoSerializationClassTestResource.php b/core/modules/rest/tests/modules/rest_test/src/Plugin/rest/resource/NoSerializationClassTestResource.php index 2689588481..3e83a4ce74 100644 --- a/core/modules/rest/tests/modules/rest_test/src/Plugin/rest/resource/NoSerializationClassTestResource.php +++ b/core/modules/rest/tests/modules/rest_test/src/Plugin/rest/resource/NoSerializationClassTestResource.php @@ -25,7 +25,7 @@ class NoSerializationClassTestResource extends ResourceBase { * * @return \Drupal\rest\ResourceResponse */ - public function post(array $data) { + public function post(array $data = []) { return new ResourceResponse($data); } diff --git a/core/modules/rest/tests/src/Functional/ResourceTestBase.php b/core/modules/rest/tests/src/Functional/ResourceTestBase.php index 0a0e34c35d..10fa555c1e 100644 --- a/core/modules/rest/tests/src/Functional/ResourceTestBase.php +++ b/core/modules/rest/tests/src/Functional/ResourceTestBase.php @@ -351,7 +351,12 @@ protected function request($method, Url $url, array $request_options) { */ protected function assertResourceResponse($expected_status_code, $expected_body, ResponseInterface $response) { $this->assertSame($expected_status_code, $response->getStatusCode()); - $this->assertSame([static::$mimeType], $response->getHeader('Content-Type')); + if ($expected_status_code < 400) { + $this->assertSame([static::$mimeType], $response->getHeader('Content-Type')); + } + else { + $this->assertSame([static::$mimeType], $response->getHeader('Content-Type')); + } if ($expected_body !== FALSE) { $this->assertSame($expected_body, (string) $response->getBody()); } diff --git a/core/modules/rest/tests/src/Kernel/RequestHandlerTest.php b/core/modules/rest/tests/src/Kernel/RequestHandlerTest.php index 808d434cc0..2b8855917e 100644 --- a/core/modules/rest/tests/src/Kernel/RequestHandlerTest.php +++ b/core/modules/rest/tests/src/Kernel/RequestHandlerTest.php @@ -93,9 +93,9 @@ public function testHandle() { */ class StubRequestHandlerResourcePlugin extends ResourceBase { - public function get($example, Request $request) {} + public function get() {} public function post() {} - public function patch($example_original, Request $request) {} + public function patch() {} public function delete() {} } diff --git a/core/modules/settings_tray/js/off-canvas.es6.js b/core/modules/settings_tray/js/off-canvas.es6.js index 1cb740c3ff..0144c9fb89 100644 --- a/core/modules/settings_tray/js/off-canvas.es6.js +++ b/core/modules/settings_tray/js/off-canvas.es6.js @@ -107,8 +107,10 @@ const eventData = { settings, $element, offCanvasDialog: this }; $element + .on('dialogresize.off-canvas', eventData, debounce(Drupal.offCanvas.bodyPadding, 100)) .on('dialogContentResize.off-canvas', eventData, Drupal.offCanvas.handleDialogResize) - .on('dialogContentResize.off-canvas', eventData, Drupal.offCanvas.bodyPadding); + .on('dialogContentResize.off-canvas', eventData, debounce(Drupal.offCanvas.bodyPadding, 100)) + .trigger('dialogresize.off-canvas'); Drupal.offCanvas.getContainer($element).attr(`data-offset-${Drupal.offCanvas.getEdge()}`, ''); diff --git a/core/modules/settings_tray/js/off-canvas.js b/core/modules/settings_tray/js/off-canvas.js index 800fd8eb11..8d0ae3521f 100644 --- a/core/modules/settings_tray/js/off-canvas.js +++ b/core/modules/settings_tray/js/off-canvas.js @@ -51,7 +51,7 @@ var eventData = { settings: settings, $element: $element, offCanvasDialog: this }; - $element.on('dialogContentResize.off-canvas', eventData, Drupal.offCanvas.handleDialogResize).on('dialogContentResize.off-canvas', eventData, Drupal.offCanvas.bodyPadding); + $element.on('dialogresize.off-canvas', eventData, debounce(Drupal.offCanvas.bodyPadding, 100)).on('dialogContentResize.off-canvas', eventData, Drupal.offCanvas.handleDialogResize).on('dialogContentResize.off-canvas', eventData, debounce(Drupal.offCanvas.bodyPadding, 100)).trigger('dialogresize.off-canvas'); Drupal.offCanvas.getContainer($element).attr('data-offset-' + Drupal.offCanvas.getEdge(), ''); diff --git a/core/modules/telephone/src/Plugin/migrate/field/d7/PhoneField.php b/core/modules/telephone/src/Plugin/migrate/field/d7/PhoneField.php index 3164cecdca..a046c1656b 100644 --- a/core/modules/telephone/src/Plugin/migrate/field/d7/PhoneField.php +++ b/core/modules/telephone/src/Plugin/migrate/field/d7/PhoneField.php @@ -10,7 +10,9 @@ * type_map = { * "phone" = "telephone", * }, - * core = {7} + * core = {7}, + * source_module = "telephone", + * destination_module = "telephone" * ) */ class PhoneField extends FieldPluginBase {} diff --git a/core/modules/text/src/Plugin/migrate/field/d6/TextField.php b/core/modules/text/src/Plugin/migrate/field/d6/TextField.php index 62deeee10c..cd1e2f7b29 100644 --- a/core/modules/text/src/Plugin/migrate/field/d6/TextField.php +++ b/core/modules/text/src/Plugin/migrate/field/d6/TextField.php @@ -14,7 +14,9 @@ * "text_long" = "text_long", * "text_with_summary" = "text_with_summary" * }, - * core = {6} + * core = {6}, + * source_module = "text", + * destination_module = "text", * ) */ class TextField extends FieldPluginBase { diff --git a/core/modules/text/src/Plugin/migrate/field/d7/TextField.php b/core/modules/text/src/Plugin/migrate/field/d7/TextField.php index c3d24c2119..79d8a1e356 100644 --- a/core/modules/text/src/Plugin/migrate/field/d7/TextField.php +++ b/core/modules/text/src/Plugin/migrate/field/d7/TextField.php @@ -14,7 +14,9 @@ * "text_long" = "text_long", * "text_with_summary" = "text_with_summary" * }, - * core = {7} + * core = {7}, + * source_module = "text", + * destination_module = "text", * ) */ class TextField extends FieldPluginBase {