-
-
Notifications
You must be signed in to change notification settings - Fork 38
/
Copy pathmigrate_plus.migration.program_data.yml
273 lines (272 loc) · 11.9 KB
/
migrate_plus.migration.program_data.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
# Migration file for creating "program" nodes from CSV.
#
# This file contains much of the information which we
# used to specify in the "Migration" class in Drupal 7.
# But why write code if you can write YAML?
# This is how we declare a Migration the Drupal 8 way.
# Migration ID.
#
# Usually the ID indicates what we are trying to migrate.
# In our case, we are migrating nodes of type "program".
id: program_data
# Human-readable name of the migration for the UI.
label: Academic programs and associated data.
# Migration group.
#
# Migration groups allow us to put related migrations under one
# umbrella so that we can execute or reference them together.
migration_group: c11n
# Migration tags.
#
# Migration tags help us group migrations using tags. In our
# example, we tag all migrations with an "academic program"
# tag. That way, we can run all academic-program-related migrations
# using one command.
migration_tags:
- node
- academic program
# Source.
#
# Under the source, we define the key "plugin" and other
# configurations specific to the plugin.
source:
# We will be importing from a CSV file, so we will require
# the migrate_source_csv module which introduces the CSV
# source plugin with the identifier "csv".
plugin: csv
# Specify the path to the CSV data source.
path: 'public://import/program/program.data.csv'
# Number of rows at the beginning which are not actual data.
header_row_count: 1
# Unique ID.
#
# These are the column names from the CSV file representing the
# unique identifier for each source record. These will be used
# by the Migration API to relate source records to migrated
# entities usually for an updating imported records or for performing
# rollbacks.
keys:
- ID
# Definitions for fields available in the source.
#
# This is an optional configuration but it makes the UI more
# explanatory. It is a set of key-value pairs where the key
# is the property name and the value is a string describing what
# the property is all about.
fields:
ID: Unique identifier for the program as in the data source.
Title: Name of the program.
Body: A description for the program.
Level: Whether the program is for undergraduates or graduates.
Type: Whether it is a full-time or a part-time program.
Image file: Name of the image file associated with the program.
Image alt: Alternate text for the image for accessibilty.
Tags: Comma-separated strings to use as tags.
Fees: We will ignore this field as per requirement.
# Static values for the migration.
#
# We can assign hard-coded values to certain properties using constants.
constants:
bool_0: 0
bool_1: 1
uid_root: 1
restricted_html: restricted_html
# Destination.
destination:
# We want to import data from a CSV file, but how do we save it?
# This plugin will be responsible for storing the records read during
# the migration in to nodes. We can also store them as other entities
# like taxonomy terms, etc. But in this case we want nodes.
plugin: 'entity:node'
# We specify the default node type as "program" because
# we will only be importing nodes of type "program" in this
# migration.
default_bundle: program
# Mapping.
#
# We can create simple mappings without any changes to
# source data or we can pass the source data through one or more
# plugins before the processed value is assigned to the
# destination.
process:
# Here, we make a direct assignment of the "Title" column
# as the node title. Not specifying a plugin name results in
# the usage of the plugin "get" which simply copies the source
# property value to the destination property.
title: Title
# There are certain destination fields which do not have
# corresponding source fields. for these, we defined constants
# in the "source" parameter. We can refer to them here as
# "constants/NAME".
#
# The below segnment makes the imported "program" nodes non-sticky.
sticky: constants/bool_0
# Similarly, we can specify whether we need or do not need the nodes
# to be promoted to the front page. Although nodes are promoted to
# front-page by default, I added the below line for demonstration.
promote: constants/bool_1
# Similarly, we can define a default user for the imported nodes.
uid: constants/uid_root
# Some fields have multiple properties! For example, the "body" field
# can have the actual full text, a summary, etc. Values can be
# assigned to specific properties using the syntax used below. We
# wrap the destination property name in quotes to comply with YAML
# specifications.
#
# Unfortunately, at the time of writing this code, there is no UI or
# drush migrate-fields-destination. Hence, one might have to refer
# to the structure of various field-types for determining the properties
# supported by various fields.
#
# Reference: https://www.drupal.org/node/2630732
'body/value': Body
# We copied the text into the _value_ for the _body_ field, however,
# we did not specify how the text is to be treated. We do that by
# specifying the _format_ property of the _body_ field.
#
# In the line below we tell Drupal to treat the _body_ as full HTML.
# Since this value does not come from the data source, we use a constant
# value defined in "source".
'body/format': constants/restricted_html
# For the "Level" of the program, the source has possible values
# "Graduate" or "Undergraduate". However, in the field definition,
# we accept only the values "gr" for graduate and "ug" for
# undergraduate.
#
# To transform the value, we can pass it through a series of
# plugins to transform the source value to the destination value.
field_program_level:
# The first plugin we will use will be the "callable" plugin.
# It will simply send in the source value "Level" to the "strtolower"
# function to get rid of any upper-case characters in the source.
# We do this because one of the records says "Undergraduate" while
# there is another one says "UnderGraduate", which is weird. So, we
# standardize the values using the "strtolower" function on them.
#
# Unfortunately, the callback plugin does not accept any additional
# arguments for the callback, but in our case we don't need them any way.
-
plugin: callback
callable: strtolower
source: Level
# If you notice the program.data.csv file, one of the programs
# does not have any "Level" value. For programs without any "Level",
# the client wants us to treat it as "graduate".
#
# For cases where we have some values but we need to implement a
# fallback value when a value is not available, we use the
# "default_value" plugin. In this case, I use this plugin before
# the "static_map" so that the "static_map" plugin as a value to
# work with.
-
plugin: default_value
default_value: graduate
# Once transformed to lower-case, we would like to transform the old
# value in to a new one. This switch-case kind of an operation can
# be handled by the plugin "static_map" which helps us map existing
# values to new values (and more).
-
plugin: static_map
map:
graduate: gr
undergraduate: ug
# For the "Type" of the program, could have used a text-list field,
# the client wants us to have a taxonomy term reference field.
#
# Assuming the vocabulary exists and we have the names of the terms
# in the data source (CSV), we would need to convert the terms into
# IDs for use during the migration. But in our data source, we do not
# have ID references - we have term names: "Part-time", "Full-time".
# We would have to create taxonomy terms for each program type and
# then associate the generated terms to the academic program.
#
# Although this can be done in a number of ways, a nice way would
# be to use the entity_generate process plugin which comes with the
# migrate_plus module. We simply specify the type of entity we wish to
# create and the some properties we wish to populate. The plugin would
# automatically lookup entities (create one if needed) and associate
# the same with academic program.
#
# Using the entity_generate plugin the task might seem to be easy,
# however, it is always a better idea to use a separate migration for
# creating the taxonomy terms (like I demonstrated for tags) and then
# use the "migration" plugin to associate them to other entities.
# With a separate migration, rollbacks would delete these dependencies
# as well, unlike while using the entity_generate plugin.
field_program_type:
plugin: entity_generate
source: Type
entity_type: taxonomy_term
bundle_key: vid
bundle: program_types
value_key: name
# For the "Tags" of the program, we need to associate taxonomy terms (tags)
# generated during the migration "term_tags". For this, we import all tags
# using the "term_tags" migration in migrate_plus.migration.term_tags.yml.
field_tags:
# First we convert the multiple tag values into an array of tag names
# using the explode plugin which simply explodes/splits a string by a given
# delimiter. In our case, we split the text by ", " to get rid of the
# spaces after the commas at once.
-
plugin: explode
delimiter: ', '
source: Tags
# Once the tag names are converted to arrays, we pass the term names
# through the "migration" plugin. This easy-to-use plugin does the grand
# task of looking up the terms we imported during the "term_tags"
# migration and utilizes the IDs of those terms during this migration.
#
# To make things better, it can handle multiple values, so each term
# name gets converted into it's relevant ID. Cool!
#
# The migration plugin can be used when the related entities (like tags)
# are available in a separate data source so that they can be imported
# first. If they are not available or cannot be extracted to their own
# data source for the migration, one would have to write their own
# "process" plugin to explode the terms and translate the term names into
# their corresponding term IDs.
-
plugin: migration
migration: program_tags
# For the "Image" of the program, we need to do some real work.
# First, we need to define the "program_image" migration to generate
# entities of type "file" for each of the images we wish to use with
# the programs. Once done, we use the plugin "migration" just like we
# did above for "tags" and associate the file IDs to the "target_id"
# property of the "field_image".
#
# NOTE: It's so cool that the property is no longer "fid" because D8
# associates the files as entity references, thereby standardizing
# things to a great extent.
'field_image/target_id':
plugin: migration
migration: program_image
source: Image file
# Now that we have the images in place, we also copy the alternate text
# for the images to the "alt" property of "field_image". Having "alt"
# would help improve accessibility and SEO.
'field_image/alt': Image alt
# With the migration_dependencies, as the name suggests, we can specify
# if this migration requires some other migrations to be run first.
#
# For example, say we were importing articles and authors. In the migration
# of articles, we would need to refer to the newly migrated author data so
# as to link the author to the article. In that case, the article migration
# would require that the author migration be run first. Thus, we could say
# that the article migration depends on the author migration and we would have
# had to specify a dependency here.
#
# In our case, we need to import tags first so that we can associate them
# to the academic programs.
migration_dependencies:
optional:
- program_tags
- program_image
# We specify that this migration depends on the c11n_migrate module.
# Based on this dependency, this migration will be removed when the
# c11n_migrate module is uninstalled.
dependencies:
enforced:
module:
- c11n_migrate