Remove parenthesis from method names
This commit is contained in:
parent
9aaa67cfc9
commit
235ea50d32
10 changed files with 13 additions and 13 deletions
2
02.txt
2
02.txt
|
@ -74,7 +74,7 @@ The repository, which will be used for many examples throughout the book, can be
|
|||
|
||||
## Running the migration
|
||||
|
||||
Let's use Drush to run the migrations with the commands provided by [Migrate Run](). Open a terminal, switch directories to Drupal's webroot, and execute the following commands.
|
||||
Let's use Drush to run the migrations with the commands provided by [Migrate Run](https://www.drupal.org/project/migrate_run). Open a terminal, switch directories to Drupal's webroot, and execute the following commands.
|
||||
|
||||
```yaml
|
||||
- $ drush pm:enable -y migrate migrate_run ud_migrations_first
|
||||
|
|
4
03.txt
4
03.txt
|
@ -116,8 +116,8 @@ destination: ...
|
|||
|
||||
The [callback](https://api.drupal.org/api/drupal/core%21modules%21migrate%21src%21Plugin%21migrate%21process%21Callback.php/class/Callback) process plugin pass a value to a PHP function and returns its result. The function to call is specified in the `callable` configuration option. Note that this plugin expects a `source` option containing a column from the source or value of the process pipeline. That value is sent as the first argument to the function. Because we are using the `callback` plugin as part of a chain, the source is assumed to be the last output of the previous plugin. Hence, there is no need to define a `source`. So, we concatenate the columns, make them all lowercase, and then capitalize each word.
|
||||
|
||||
Relying on direct PHP function calls should be a last resort. Better alternatives include writing your own process plugins which encapsulates your business logic separate of the migration definition. The `callback` plugin comes with its own **limitation**. For example, you cannot pass extra parameters to the `callable` function. It will receive the specified value as its first argument and nothing else. In the above example, we could combine the calls to mb_strtolower() and ucwords() into a single call to mb_convert_case(\$source, MB_CASE_TITLE) if passing extra parameters were allowed.
|
||||
Relying on direct PHP function calls should be a last resort. Better alternatives include writing your own process plugins which encapsulates your business logic separate of the migration definition. The `callback` plugin comes with its own **limitation**. For example, you cannot pass extra parameters to the `callable` function. It will receive the specified value as its first argument and nothing else. In the above example, we could combine the calls to `mb_strtolower` and ucwords into a single call to mb_convert_case(\$source, MB_CASE_TITLE) if passing extra parameters were allowed.
|
||||
|
||||
_Tip_: You should have a good understanding of your source and destination formats. In this example, one of the values to want to transform is `MELANÇON`. Because of the cedilla (**ç**) using strtolower() is not adequate in this case since it would leave that character uppercase (`melanÇon`). [Multibyte string functions](https://www.php.net/manual/en/ref.mbstring.php) (mb\_\*) are required for proper transformation. ucwords() is not one of them and would present similar issues if the first letter of the words are special characters. Attention should be given to the character encoding of the tables in your destination database.
|
||||
_Tip_: You should have a good understanding of your source and destination formats. In this example, one of the values to want to transform is `MELANÇON`. Because of the cedilla (**ç**) using `strtolower` is not adequate in this case since it would leave that character uppercase (`melanÇon`). [Multibyte string functions](https://www.php.net/manual/en/ref.mbstring.php) (mb\_\*) are required for proper transformation. `ucwords` is not one of them and would present similar issues if the first letter of the words are special characters. Attention should be given to the character encoding of the tables in your destination database.
|
||||
|
||||
_Technical note_: `mb_strtolower` is a function provided by the [mbstring](https://www.php.net/manual/en/mbstring.installation.php) PHP extension. It does not come enabled by default or you might not have it installed altogether. In those cases, the function would not be available when Drupal tries to call it. The following error is produced when trying to call a function that is not available: `The "callable" must be a valid function or method`. For Drupal and this particular function that error would never be triggered, even if the extension is missing. That is because Drupal core depends on some Symfony packages which in turn depend on the `symfony/polyfill-mbstring` package. The latter provides a polyfill for mb\_\* functions that has been leveraged since version 8.6.x of Drupal.
|
||||
|
|
2
05.txt
2
05.txt
|
@ -68,7 +68,7 @@ process:
|
|||
|
||||
In the above example, `my_pseudofield_1` is set to the result of a `concat` process transformation that joins a constant and a column from the source section. The result value is later used as part of a `urlencode` process transformation. Note that to use the value from `my_pseudofield_1` you have to enclose it in _quotes_ (**'**) and prepend an _at sign_ (**@**) to the name. The `pseudo_` prefix in the name is not required. In this case it is used to make it easier to distinguish among pseudofields and regular property or field names. The new value obtained from URL encode operation is stored in `my_pseudofield_2`. This last pseudofield is used to set the value of the `uri` subfield for `field_link`. The example could be simplified, for example, by using a single pseudofield and chaining process plugins. It is presented that way to demonstrate that a pseudofield could be used as direct assignments or as part of process plugin configuration values.
|
||||
|
||||
_Technical note_: If the name of the subfield can be arbitrary, how can you prevent name clashes with destination property names and field names? You might have to look at the source for the entity and the configuration of the bundle. In the case of a node migration, look at the `baseFieldDefinitions()` method of the `Node` class for a list of property names. Be mindful of class inheritance and method overriding. For a list of fields and their machine names, look at the "Manage fields" section of the content type you are migrating into. The [Field API](https://api.drupal.org/api/drupal/core!modules!field!field.module/group/field/8.8.x) prefixes any field created via the administration interface with the string `field_`. This reduces the likelihood of name clashes. Other than these two name restrictions, _anything else can be used_. In this case, the Migrate API will eventually perform an entity save operation which will discard the pseudofields.
|
||||
_Technical note_: If the name of the subfield can be arbitrary, how can you prevent name clashes with destination property names and field names? You might have to look at the source for the entity and the configuration of the bundle. In the case of a node migration, look at the `baseFieldDefinitions` method of the `Node` class for a list of property names. Be mindful of class inheritance and method overriding. For a list of fields and their machine names, look at the "Manage fields" section of the content type you are migrating into. The [Field API](https://api.drupal.org/api/drupal/core!modules!field!field.module/group/field/8.8.x) prefixes any field created via the administration interface with the string `field_`. This reduces the likelihood of name clashes. Other than these two name restrictions, _anything else can be used_. In this case, the Migrate API will eventually perform an entity save operation which will discard the pseudofields.
|
||||
|
||||
## Understanding Drupal Migrate API process pipeline
|
||||
|
||||
|
|
2
07.txt
2
07.txt
|
@ -125,4 +125,4 @@ In addition to downloading the image and place it inside Drupal’s file system,
|
|||
|
||||
One important thing to note is an image’s alternative text, title, width, and height are not associated with the **file entity**. That information is actually stored in a **field of type image**. This will be illustrated in the next chapter. To reiterate, the same approach to migrate images can be used to migrate any file type.
|
||||
|
||||
_Technical note_: The file entity contains other properties you can write to. For a list of available options check the `baseFieldDefinitions()` method of the `File` class defining the entity. Note that more properties can be available up in the class hierarchy. Also, this entity does not have multiple bundles like the node entity does.
|
||||
_Technical note_: The file entity contains other properties you can write to. For a list of available options check the `baseFieldDefinitions` method of the `File` class defining the entity. Note that more properties can be available up in the class hierarchy. Also, this entity does not have multiple bundles like the node entity does.
|
||||
|
|
2
09.txt
2
09.txt
|
@ -48,7 +48,7 @@ process:
|
|||
source: fruit_parent
|
||||
```
|
||||
|
||||
_Technical note_: The _taxonomy term_ entity contains other properties you can write to. For a list of available options check the `baseFieldDefinitions()` method of the `Term` class defining the entity. Note that more properties can be available up in the class hierarchy.
|
||||
_Technical note_: The _taxonomy term_ entity contains other properties you can write to. For a list of available options check the `baseFieldDefinitions` method of the `Term` class defining the entity. Note that more properties can be available up in the class hierarchy.
|
||||
|
||||
## Migrating multivalue taxonomy terms fields
|
||||
|
||||
|
|
2
11.txt
2
11.txt
|
@ -78,7 +78,7 @@ user_picture/target_id:
|
|||
|
||||
*Image* fields are *entity references*. Their `target_id` property needs to be an integer number containing the **file id** (`fid`) of the image. This can be obtained using the [migration_lookup](https://api.drupal.org/api/drupal/core%21modules%21migrate%21src%21Plugin%21migrate%21process%21MigrationLookup.php/class/MigrationLookup) plugin. Details on how to configure it can be found in this [article](https://understanddrupal.com/articles/introduction-migration-dependencies-drupal). You could simply use `user_picture` as your field mapping because `target_id` is the [default subfield](https://understanddrupal.com/articles/migrating-data-drupal-subfields) and could be omitted. Also, note that the `alt` subfield is not mapped. If present, its value will be used for the alternative text of the image. But if it is not specified, like in this example, Drupal will automatically [generate an alternative text](https://git.drupalcode.org/project/drupal/blob/8.8.x/core/modules/user/user.module#L411) out of the username. An example value would be: `Profile picture for user michele`.
|
||||
|
||||
*Technical note*: The user entity contains other properties you can write to. For a list of available options, check the [baseFieldDefinitions](https://git.drupalcode.org/project/drupal/blob/8.8.x/core/modules/user/src/Entity/User.php#L447)() method of the [User](https://git.drupalcode.org/project/drupal/blob/8.8.x/core/modules/user/src/Entity/User.php) class defining the entity. Note that more properties can be available up in the class hierarchy.
|
||||
*Technical note*: The user entity contains other properties you can write to. For a list of available options, check the [baseFieldDefinitions](https://git.drupalcode.org/project/drupal/blob/8.8.x/core/modules/user/src/Entity/User.php#L447) method of the [User](https://git.drupalcode.org/project/drupal/blob/8.8.x/core/modules/user/src/Entity/User.php) class defining the entity. Note that more properties can be available up in the class hierarchy.
|
||||
|
||||
And with that, we wrap up the *user* migration example. We covered how to migrate a user's mail, timezone, username, password, status, creation date, roles, and profile picture. Along the way, we presented various process plugins that had not been used previously in the series. We showed a couple of examples of process plugin chaining to make sure the migrated data is valid and in the format expected by Drupal.
|
||||
|
||||
|
|
6
13.txt
6
13.txt
|
@ -1,6 +1,6 @@
|
|||
# Migrating addresses into Drupal
|
||||
|
||||
Today we will learn how to migrate **addresses** into Drupal. We are going to use the field provided by the [Address module](https://www.drupal.org/project/address) which depends on the third-party library [commerceguys/addressing](https://github.com/commerceguys/addressing). When migrating addresses you need to be careful with the data that Drupal expects. The address components can change per country. The way to store those components also varies per country. These and other important consideration will be explained. Let's get started.
|
||||
Today we will learn how to migrate **addresses** into Drupal. We are going to use the field provided by the [Address module](https://www.drupal.org/project/address) which depends on the third-party library `[commerceguys/addressing](https://github.com/commerceguys/addressing). When migrating addresses you need to be careful with the data that Drupal expects. The address components can change per country. The way to store those components also varies per country. These and other important consideration will be explained. Let's get started.
|
||||
|
||||
## Getting the code
|
||||
|
||||
|
@ -54,7 +54,7 @@ Note that not every address component is set for all addresses. For example, the
|
|||
|
||||
## Available subfields
|
||||
|
||||
The Address field has 13 [subfields](https://understanddrupal.com/articles/migrating-data-drupal-subfields) available. They can be found in the [schema](https://git.drupalcode.org/project/address/blob/8.x-1.x/src/Plugin/Field/FieldType/AddressItem.php#L36)() method of the [AddresItem](https://git.drupalcode.org/project/address/blob/8.x-1.x/src/Plugin/Field/FieldType/AddressItem.php) class. Fields are not required to have a one-to-one mapping between their schema and the form widgets used for entering content. This is particularly true for addresses because input elements, labels, and validations change dynamically based on the selected country. The following is a reference list of all subfields for addresses:
|
||||
The Address field has 13 [subfields](https://understanddrupal.com/articles/migrating-data-drupal-subfields) available. They can be found in the [schema](https://git.drupalcode.org/project/address/blob/8.x-1.x/src/Plugin/Field/FieldType/AddressItem.php#L36) method of the [AddresItem](https://git.drupalcode.org/project/address/blob/8.x-1.x/src/Plugin/Field/FieldType/AddressItem.php) class. Fields are not required to have a one-to-one mapping between their schema and the form widgets used for entering content. This is particularly true for addresses because input elements, labels, and validations change dynamically based on the selected country. The following is a reference list of all subfields for addresses:
|
||||
|
||||
1. `langcode` for language code.
|
||||
2. `country_code` for country.
|
||||
|
@ -118,7 +118,7 @@ If you know a better way, please share it in the comments.
|
|||
|
||||
With version 8 came many changes in the way Drupal is developed. Now there is an intentional effort to integrate with the greater PHP ecosystem. This involves using already existing libraries and frameworks, like [Symfony](https://symfony.com/). But also, making code written for Drupal available as external libraries that could be used by other projects. `commerceguys\addressing` is one example of a library that was made available as an external library. That being said, the Address module also makes use of it.
|
||||
|
||||
Explaining how the library works or where its fetches its database is beyond the scope of this article. Refer to the [library documentation](https://github.com/commerceguys/addressing) for more details on the topic. We are only going to point out some things that are relevant for the migration. For example, the *ZIP code* validation happens at the [validatePostalCode](https://github.com/commerceguys/addressing/blob/50fe323ddc7faaab897759f31d4b29c1a793e5c2/src/Validator/Constraints/AddressFormatConstraintValidator.php#L140)() method of the [AddressFormatConstraintValidator](https://github.com/commerceguys/addressing/blob/50fe323ddc7faaab897759f31d4b29c1a793e5c2/src/Validator/Constraints/AddressFormatConstraintValidator.php) class. There is no need to know this for a migration project. But the key thing to remember is that the migration can be affected by third-party libraries outside of Drupal core or contributed modules. Another example, is the value for the *state* subfield. Address module expects a `subdivision` code as listed in one of the files in the `resources/subdivision` directory.
|
||||
Explaining how the library works or where its fetches its database is beyond the scope of this article. Refer to the [library documentation](https://github.com/commerceguys/addressing) for more details on the topic. We are only going to point out some things that are relevant for the migration. For example, the *ZIP code* validation happens at the [validatePostalCode](https://github.com/commerceguys/addressing/blob/50fe323ddc7faaab897759f31d4b29c1a793e5c2/src/Validator/Constraints/AddressFormatConstraintValidator.php#L140) method of the [AddressFormatConstraintValidator](https://github.com/commerceguys/addressing/blob/50fe323ddc7faaab897759f31d4b29c1a793e5c2/src/Validator/Constraints/AddressFormatConstraintValidator.php) class. There is no need to know this for a migration project. But the key thing to remember is that the migration can be affected by third-party libraries outside of Drupal core or contributed modules. Another example, is the value for the *state* subfield. Address module expects a `subdivision` code as listed in one of the files in the `resources/subdivision` directory.
|
||||
|
||||
Does the validation really affect the migration? We have already [mentioned](https://understanddrupal.com/articles/migrating-data-drupal-subfields) that the Migrate API bypasses [Form API](https://api.drupal.org/api/drupal/elements/8.8.x) validations. And that is true for address fields as well. You can migrate a USA address with state `Florida` and ZIP code `55111`. Both are invalid because you need to use the two-letter *state* code `FL` and use a valid *ZIP code* within the state. Notwithstanding, the migration will not fail in this case. In fact, if you visit the migrated node you will see that Drupal happily shows the address with the data that you entered. The problems arrives when you need to **use the address**. If you try to edit the node you will see that the *state* will not be preselected. And if you try to save the node after selecting `Florida` you will get the validation error for the *ZIP code*.
|
||||
|
||||
|
|
2
14.txt
2
14.txt
|
@ -171,7 +171,7 @@ And that is *one way* to map paragraph reference fields. In the end, all you hav
|
|||
|
||||
Paragraphs migrations are affected by a particular behavior of *revisioned entities*. If the host entity is deleted, and the paragraphs do not have translations, the whole paragraph gets deleted. That means that deleting a node will make the referenced paragraphs' data to be removed. How does this affect your [migration workflow](https://understanddrupal.com/articles/tips-writing-drupal-migrations-and-understanding-their-workflow)? If the migration of the host entity is rollback, then the paragraphs will be removed, the migrate API will not know about it. In this example, if you run a migrate status command after rolling back the *node* migration, you will see that the *paragraph* migration indicated that there are no pending elements to process. The *file* migration for the images will report the same, but in that case, the images will remain on the system.
|
||||
|
||||
In any migration project, it is common that you do rollback operations to test new field mappings or fix errors. Thus, chances are very high that you will stumble upon this behavior. Thanks to [Damien McKenna](https://www.drupal.org/u/damienmckenna) for helping me understand this behavior and tracking it to the [rollback](https://git.drupalcode.org/project/entity_reference_revisions/blob/8.x-1.x/src/Plugin/migrate/destination/EntityReferenceRevisions.php#L150)() method of the [EntityReferenceRevisions](https://git.drupalcode.org/project/entity_reference_revisions/blob/8.x-1.x/src/Plugin/migrate/destination/EntityReferenceRevisions.php) destination plugin. So, what do you do to recover the deleted paragraphs? You have to rollback *both* migrations: *node* and *paragraph*. And then, you have to import the two again. The following snippet shows how to do it:
|
||||
In any migration project, it is common that you do rollback operations to test new field mappings or fix errors. Thus, chances are very high that you will stumble upon this behavior. Thanks to [Damien McKenna](https://www.drupal.org/u/damienmckenna) for helping me understand this behavior and tracking it to the [rollback](https://git.drupalcode.org/project/entity_reference_revisions/blob/8.x-1.x/src/Plugin/migrate/destination/EntityReferenceRevisions.php#L150) method of the [EntityReferenceRevisions](https://git.drupalcode.org/project/entity_reference_revisions/blob/8.x-1.x/src/Plugin/migrate/destination/EntityReferenceRevisions.php) destination plugin. So, what do you do to recover the deleted paragraphs? You have to rollback *both* migrations: *node* and *paragraph*. And then, you have to import the two again. The following snippet shows how to do it:
|
||||
|
||||
```console
|
||||
# 1) Rollback both migrations.
|
||||
|
|
2
24.txt
2
24.txt
|
@ -82,7 +82,7 @@ migration_dependencies: ...
|
|||
|
||||
The group configuration declares two tags: `UD Config Group (JSON Source)` and `UD Example`. The migration configuration overrides the tags to a single value `UD Lorem Ipsum`. What would you expect the final value for the `migration_tags` key be? Is it a combination of the three tags? Is it only the one key defined in the migration configuration?
|
||||
|
||||
The answer in this case is not very intuitive. The final migration will have two tags: `UD Lorem Ipsum` and `UD Example`. This has to do with how Migrate Plus merges the configuration from the group into the individual migrations. It uses the `array_replace_recursive()` PHP function which performs the merge operation based on array keys. In this example, `UD Config Group (JSON Source)` and `UD Lorem Ipsum` have the same index in the `migration_tags` array. Therefore, only one value is preserved in the final result.
|
||||
The answer in this case is not very intuitive. The final migration will have two tags: `UD Lorem Ipsum` and `UD Example`. This has to do with how Migrate Plus merges the configuration from the group into the individual migrations. It uses the `array_replace_recursive` PHP function which performs the merge operation based on array keys. In this example, `UD Config Group (JSON Source)` and `UD Lorem Ipsum` have the same index in the `migration_tags` array. Therefore, only one value is preserved in the final result.
|
||||
|
||||
The examples uses the `migration_tags` key as it is the subject of this article, but the same applies to any nested structure. Some configurations are more critical to a migration than a tag or group. Debugging a problem like this can be tricky. But the same applies to any configuration that has a nested structure. If the end result might be ambiguous, it is preferred to avoid the situation in the first place. In general, nested structures should only be set in either the group or the migration definition file, but not both. Additionally, all the recommendations for writing migrations presented in [this article](https://understanddrupal.com/articles/tips-writing-drupal-migrations-and-understanding-their-workflow) also apply here.
|
||||
|
||||
|
|
2
28.txt
2
28.txt
|
@ -115,7 +115,7 @@ Called from +56 /var/www/drupalvm/drupal/web/modules/contrib/migrate_devel/src/E
|
|||
|
||||
The Migrate Devel module also provides a new process plugin called [debug](https://git.drupalcode.org/project/migrate_devel/blob/8.x-1.x/src/Plugin/migrate/process/Debug.php). The plugin works by printing the value it receives to the terminal. As [Benji Fisher](https://www.drupal.org/u/benjifisher) explains in [this issue](https://www.drupal.org/node/3021648), the `debug` plugin offers the following advantages over the `log` plugin provided by the core Migrate API:
|
||||
|
||||
- The use of [print_r](https://www.php.net/manual/en/function.print-r.php)() handles both arrays and scalar values gracefully.
|
||||
- The use of [print_r](https://www.php.net/manual/en/function.print-r.php) handles both arrays and scalar values gracefully.
|
||||
- It is easy to differentiate debugging code that should be removed from logging plugin configuration that should stay.
|
||||
- It saves time as there is no need to run the `migrate:messages` command to read the logged values.
|
||||
|
||||
|
|
Loading…
Reference in a new issue