|
1 <?php |
|
2 |
|
3 /** |
|
4 * @file |
|
5 * Install, update and uninstall functions for the field module. |
|
6 */ |
|
7 |
|
8 /** |
|
9 * Implements hook_schema(). |
|
10 */ |
|
11 function field_schema() { |
|
12 // Static (meta) tables. |
|
13 $schema['field_config'] = array( |
|
14 'fields' => array( |
|
15 'id' => array( |
|
16 'type' => 'serial', |
|
17 'not null' => TRUE, |
|
18 'description' => 'The primary identifier for a field', |
|
19 ), |
|
20 'field_name' => array( |
|
21 'type' => 'varchar', |
|
22 'length' => 32, |
|
23 'not null' => TRUE, |
|
24 'description' => 'The name of this field. Non-deleted field names are unique, but multiple deleted fields can have the same name.', |
|
25 ), |
|
26 'type' => array( |
|
27 'type' => 'varchar', |
|
28 'length' => 128, |
|
29 'not null' => TRUE, |
|
30 'description' => 'The type of this field.', |
|
31 ), |
|
32 'module' => array( |
|
33 'type' => 'varchar', |
|
34 'length' => 128, |
|
35 'not null' => TRUE, |
|
36 'default' => '', |
|
37 'description' => 'The module that implements the field type.', |
|
38 ), |
|
39 'active' => array( |
|
40 'type' => 'int', |
|
41 'size' => 'tiny', |
|
42 'not null' => TRUE, |
|
43 'default' => 0, |
|
44 'description' => 'Boolean indicating whether the module that implements the field type is enabled.', |
|
45 ), |
|
46 'storage_type' => array( |
|
47 'type' => 'varchar', |
|
48 'length' => 128, |
|
49 'not null' => TRUE, |
|
50 'description' => 'The storage backend for the field.', |
|
51 ), |
|
52 'storage_module' => array( |
|
53 'type' => 'varchar', |
|
54 'length' => 128, |
|
55 'not null' => TRUE, |
|
56 'default' => '', |
|
57 'description' => 'The module that implements the storage backend.', |
|
58 ), |
|
59 'storage_active' => array( |
|
60 'type' => 'int', |
|
61 'size' => 'tiny', |
|
62 'not null' => TRUE, |
|
63 'default' => 0, |
|
64 'description' => 'Boolean indicating whether the module that implements the storage backend is enabled.', |
|
65 ), |
|
66 'locked' => array( |
|
67 'type' => 'int', |
|
68 'size' => 'tiny', |
|
69 'not null' => TRUE, |
|
70 'default' => 0, |
|
71 'description' => '@TODO', |
|
72 ), |
|
73 'data' => array( |
|
74 'type' => 'blob', |
|
75 'size' => 'big', |
|
76 'not null' => TRUE, |
|
77 'serialize' => TRUE, |
|
78 'description' => 'Serialized data containing the field properties that do not warrant a dedicated column.', |
|
79 ), |
|
80 'cardinality' => array( |
|
81 'type' => 'int', |
|
82 'size' => 'tiny', |
|
83 'not null' => TRUE, |
|
84 'default' => 0, |
|
85 ), |
|
86 'translatable' => array( |
|
87 'type' => 'int', |
|
88 'size' => 'tiny', |
|
89 'not null' => TRUE, |
|
90 'default' => 0, |
|
91 ), |
|
92 'deleted' => array( |
|
93 'type' => 'int', |
|
94 'size' => 'tiny', |
|
95 'not null' => TRUE, |
|
96 'default' => 0, |
|
97 ), |
|
98 ), |
|
99 'primary key' => array('id'), |
|
100 'indexes' => array( |
|
101 'field_name' => array('field_name'), |
|
102 // Used by field_sync_field_status(). |
|
103 'active' => array('active'), |
|
104 'storage_active' => array('storage_active'), |
|
105 'deleted' => array('deleted'), |
|
106 // Used by field_modules_disabled(). |
|
107 'module' => array('module'), |
|
108 'storage_module' => array('storage_module'), |
|
109 'type' => array('type'), |
|
110 'storage_type' => array('storage_type'), |
|
111 ), |
|
112 ); |
|
113 $schema['field_config_instance'] = array( |
|
114 'fields' => array( |
|
115 'id' => array( |
|
116 'type' => 'serial', |
|
117 'not null' => TRUE, |
|
118 'description' => 'The primary identifier for a field instance', |
|
119 ), |
|
120 'field_id' => array( |
|
121 'type' => 'int', |
|
122 'not null' => TRUE, |
|
123 'description' => 'The identifier of the field attached by this instance', |
|
124 ), |
|
125 'field_name' => array( |
|
126 'type' => 'varchar', |
|
127 'length' => 32, |
|
128 'not null' => TRUE, |
|
129 'default' => '' |
|
130 ), |
|
131 'entity_type' => array( |
|
132 'type' => 'varchar', |
|
133 'length' => 32, |
|
134 'not null' => TRUE, |
|
135 'default' => '' |
|
136 ), |
|
137 'bundle' => array( |
|
138 'type' => 'varchar', |
|
139 'length' => 128, |
|
140 'not null' => TRUE, |
|
141 'default' => '' |
|
142 ), |
|
143 'data' => array( |
|
144 'type' => 'blob', |
|
145 'size' => 'big', |
|
146 'not null' => TRUE, |
|
147 'serialize' => TRUE, |
|
148 ), |
|
149 'deleted' => array( |
|
150 'type' => 'int', |
|
151 'size' => 'tiny', |
|
152 'not null' => TRUE, |
|
153 'default' => 0, |
|
154 ), |
|
155 ), |
|
156 'primary key' => array('id'), |
|
157 'indexes' => array( |
|
158 // Used by field_delete_instance(). |
|
159 'field_name_bundle' => array('field_name', 'entity_type', 'bundle'), |
|
160 // Used by field_read_instances(). |
|
161 'deleted' => array('deleted'), |
|
162 ), |
|
163 ); |
|
164 $schema['cache_field'] = drupal_get_schema_unprocessed('system', 'cache'); |
|
165 $schema['cache_field']['description'] = 'Cache table for the Field module to store already built field information.'; |
|
166 |
|
167 return $schema; |
|
168 } |
|
169 |
|
170 /** |
|
171 * Utility function: create a field by writing directly to the database. |
|
172 * |
|
173 * This function can be used for databases whose schema is at field module |
|
174 * version 7000 or higher. |
|
175 * |
|
176 * @ingroup update_api |
|
177 */ |
|
178 function _update_7000_field_create_field(&$field) { |
|
179 // Merge in default values.` |
|
180 $field += array( |
|
181 'entity_types' => array(), |
|
182 'cardinality' => 1, |
|
183 'translatable' => FALSE, |
|
184 'locked' => FALSE, |
|
185 'settings' => array(), |
|
186 'indexes' => array(), |
|
187 'deleted' => 0, |
|
188 'active' => 1, |
|
189 ); |
|
190 |
|
191 // Set storage. |
|
192 $field['storage'] = array( |
|
193 'type' => 'field_sql_storage', |
|
194 'settings' => array(), |
|
195 'module' => 'field_sql_storage', |
|
196 'active' => 1, |
|
197 ); |
|
198 |
|
199 // Fetch the field schema to initialize columns and indexes. The field module |
|
200 // is not guaranteed to be loaded at this point. |
|
201 module_load_install($field['module']); |
|
202 $schema = (array) module_invoke($field['module'], 'field_schema', $field); |
|
203 $schema += array('columns' => array(), 'indexes' => array()); |
|
204 // 'columns' are hardcoded in the field type. |
|
205 $field['columns'] = $schema['columns']; |
|
206 // 'indexes' can be both hardcoded in the field type, and specified in the |
|
207 // incoming $field definition. |
|
208 $field['indexes'] += $schema['indexes']; |
|
209 |
|
210 // The serialized 'data' column contains everything from $field that does not |
|
211 // have its own column and is not automatically populated when the field is |
|
212 // read. |
|
213 $data = $field; |
|
214 unset($data['columns'], $data['field_name'], $data['type'], $data['active'], $data['module'], $data['storage_type'], $data['storage_active'], $data['storage_module'], $data['locked'], $data['cardinality'], $data['deleted']); |
|
215 // Additionally, do not save the 'bundles' property populated by |
|
216 // field_info_field(). |
|
217 unset($data['bundles']); |
|
218 |
|
219 // Write the field to the database. |
|
220 $record = array( |
|
221 'field_name' => $field['field_name'], |
|
222 'type' => $field['type'], |
|
223 'module' => $field['module'], |
|
224 'active' => (int) $field['active'], |
|
225 'storage_type' => $field['storage']['type'], |
|
226 'storage_module' => $field['storage']['module'], |
|
227 'storage_active' => (int) $field['storage']['active'], |
|
228 'locked' => (int) $field['locked'], |
|
229 'data' => serialize($data), |
|
230 'cardinality' => $field['cardinality'], |
|
231 'translatable' => (int) $field['translatable'], |
|
232 'deleted' => (int) $field['deleted'], |
|
233 ); |
|
234 // We don't use drupal_write_record() here because it depends on the schema. |
|
235 $field['id'] = db_insert('field_config') |
|
236 ->fields($record) |
|
237 ->execute(); |
|
238 |
|
239 // Create storage for the field. |
|
240 field_sql_storage_field_storage_create_field($field); |
|
241 } |
|
242 |
|
243 /** |
|
244 * Utility function: delete a field stored in SQL storage directly from the database. |
|
245 * |
|
246 * To protect user data, this function can only be used to delete fields once |
|
247 * all information it stored is gone. Delete all data from the |
|
248 * field_data_$field_name table before calling by either manually issuing |
|
249 * delete queries against it or using _update_7000_field_delete_instance(). |
|
250 * |
|
251 * This function can be used for databases whose schema is at field module |
|
252 * version 7000 or higher. |
|
253 * |
|
254 * @param $field_name |
|
255 * The field name to delete. |
|
256 * |
|
257 * @ingroup update_api |
|
258 */ |
|
259 function _update_7000_field_delete_field($field_name) { |
|
260 $table_name = 'field_data_' . $field_name; |
|
261 if (db_select($table_name)->range(0, 1)->countQuery()->execute()->fetchField()) { |
|
262 $t = get_t(); |
|
263 throw new Exception($t('This function can only be used to delete fields without data')); |
|
264 } |
|
265 // Delete all instances. |
|
266 db_delete('field_config_instance') |
|
267 ->condition('field_name', $field_name) |
|
268 ->execute(); |
|
269 |
|
270 // Nuke field data and revision tables. |
|
271 db_drop_table($table_name); |
|
272 db_drop_table('field_revision_' . $field_name); |
|
273 |
|
274 // Delete the field. |
|
275 db_delete('field_config') |
|
276 ->condition('field_name', $field_name) |
|
277 ->execute(); |
|
278 } |
|
279 |
|
280 |
|
281 /** |
|
282 * Utility function: delete an instance and all its data of a field stored in SQL Storage. |
|
283 * |
|
284 * BEWARE: this function deletes user data from the field storage tables. |
|
285 * |
|
286 * This function is valid for a database schema version 7000. |
|
287 * |
|
288 * @ingroup update_api |
|
289 */ |
|
290 function _update_7000_field_delete_instance($field_name, $entity_type, $bundle) { |
|
291 // Delete field instance configuration data. |
|
292 db_delete('field_config_instance') |
|
293 ->condition('field_name', $field_name) |
|
294 ->condition('entity_type', $entity_type) |
|
295 ->condition('bundle', $bundle) |
|
296 ->execute(); |
|
297 |
|
298 // Nuke data. |
|
299 db_delete('field_data_' . $field_name) |
|
300 ->condition('entity_type', $entity_type) |
|
301 ->condition('bundle', $bundle) |
|
302 ->execute(); |
|
303 db_delete('field_revision_' . $field_name) |
|
304 ->condition('entity_type', $entity_type) |
|
305 ->condition('bundle', $bundle) |
|
306 ->execute(); |
|
307 } |
|
308 |
|
309 /** |
|
310 * Utility function: fetch all the field definitions from the database. |
|
311 * |
|
312 * Warning: unlike the field_read_fields() API function, this function returns |
|
313 * all fields by default, including deleted and inactive fields, unless |
|
314 * specified otherwise in the $conditions parameter. |
|
315 * |
|
316 * @param $conditions |
|
317 * An array of conditions to limit the select query to. |
|
318 * @param $key |
|
319 * The name of the field property the return array is indexed by. Using |
|
320 * anything else than 'id' might cause incomplete results if the $conditions |
|
321 * do not filter out deleted fields. |
|
322 * |
|
323 * @return |
|
324 * An array of fields matching $conditions, keyed by the property specified |
|
325 * by the $key parameter. |
|
326 * |
|
327 * @ingroup update_api |
|
328 */ |
|
329 function _update_7000_field_read_fields(array $conditions = array(), $key = 'id') { |
|
330 $fields = array(); |
|
331 $query = db_select('field_config', 'fc', array('fetch' => PDO::FETCH_ASSOC)) |
|
332 ->fields('fc'); |
|
333 foreach ($conditions as $column => $value) { |
|
334 $query->condition($column, $value); |
|
335 } |
|
336 foreach ($query->execute() as $record) { |
|
337 $field = unserialize($record['data']); |
|
338 $field['id'] = $record['id']; |
|
339 $field['field_name'] = $record['field_name']; |
|
340 $field['type'] = $record['type']; |
|
341 $field['module'] = $record['module']; |
|
342 $field['active'] = $record['active']; |
|
343 $field['storage']['type'] = $record['storage_type']; |
|
344 $field['storage']['module'] = $record['storage_module']; |
|
345 $field['storage']['active'] = $record['storage_active']; |
|
346 $field['locked'] = $record['locked']; |
|
347 $field['cardinality'] = $record['cardinality']; |
|
348 $field['translatable'] = $record['translatable']; |
|
349 $field['deleted'] = $record['deleted']; |
|
350 |
|
351 $fields[$field[$key]] = $field; |
|
352 } |
|
353 return $fields; |
|
354 } |
|
355 |
|
356 /** |
|
357 * Utility function: write a field instance directly to the database. |
|
358 * |
|
359 * This function can be used for databases whose schema is at field module |
|
360 * version 7000 or higher. |
|
361 * |
|
362 * @ingroup update_api |
|
363 */ |
|
364 function _update_7000_field_create_instance($field, &$instance) { |
|
365 // Merge in defaults. |
|
366 $instance += array( |
|
367 'field_id' => $field['id'], |
|
368 'field_name' => $field['field_name'], |
|
369 'deleted' => 0, |
|
370 ); |
|
371 |
|
372 // The serialized 'data' column contains everything from $instance that does |
|
373 // not have its own column and is not automatically populated when the |
|
374 // instance is read. |
|
375 $data = $instance; |
|
376 unset($data['id'], $data['field_id'], $data['field_name'], $data['entity_type'], $data['bundle'], $data['deleted']); |
|
377 |
|
378 $record = array( |
|
379 'field_id' => $instance['field_id'], |
|
380 'field_name' => $instance['field_name'], |
|
381 'entity_type' => $instance['entity_type'], |
|
382 'bundle' => $instance['bundle'], |
|
383 'data' => serialize($data), |
|
384 'deleted' => (int) $instance['deleted'], |
|
385 ); |
|
386 $instance['id'] = db_insert('field_config_instance') |
|
387 ->fields($record) |
|
388 ->execute(); |
|
389 } |
|
390 |
|
391 /** |
|
392 * @addtogroup updates-6.x-to-7.x |
|
393 * @{ |
|
394 */ |
|
395 |
|
396 /** |
|
397 * Field update version placeholder. |
|
398 */ |
|
399 function field_update_7000() { |
|
400 // Some update helper functions (such as _update_7000_field_create_field()) |
|
401 // modify the database directly. They can be used safely only if the database |
|
402 // schema matches the field module schema established for Drupal 7.0 (i.e. |
|
403 // version 7000). This function exists solely to set the schema version to |
|
404 // 7000, so that update functions calling those helpers can do so safely |
|
405 // by declaring a dependency on field_update_7000(). |
|
406 } |
|
407 |
|
408 /** |
|
409 * Fix fields definitions created during the d6 to d7 upgrade path. |
|
410 */ |
|
411 function field_update_7001() { |
|
412 $fields = _update_7000_field_read_fields(); |
|
413 foreach ($fields as $field) { |
|
414 // _update_7000_field_create_field() was broken in d7 RC2, and the fields |
|
415 // created during a d6 to d7 upgrade do not correcly store the 'index' |
|
416 // entry. See http://drupal.org/node/996160. |
|
417 |
|
418 module_load_install($field['module']); |
|
419 $schema = (array) module_invoke($field['module'], 'field_schema', $field); |
|
420 $schema += array('indexes' => array()); |
|
421 // 'indexes' can be both hardcoded in the field type, and specified in the |
|
422 // incoming $field definition. |
|
423 $field['indexes'] += $schema['indexes']; |
|
424 |
|
425 // Place the updated entries in the existing serialized 'data' column. |
|
426 $data = db_query("SELECT data FROM {field_config} WHERE id = :id", array(':id' => $field['id']))->fetchField(); |
|
427 $data = unserialize($data); |
|
428 $data['columns'] = $field['columns']; |
|
429 $data['indexes'] = $field['indexes']; |
|
430 |
|
431 // Save the new data. |
|
432 $query = db_update('field_config') |
|
433 ->condition('id', $field['id']) |
|
434 ->fields(array('data' => serialize($data))) |
|
435 ->execute(); |
|
436 } |
|
437 } |
|
438 |
|
439 /** |
|
440 * @} End of "addtogroup updates-6.x-to-7.x". |
|
441 */ |
|
442 |
|
443 /** |
|
444 * @addtogroup updates-7.x-extra |
|
445 * @{ |
|
446 */ |
|
447 |
|
448 /** |
|
449 * Split the all-inclusive field_bundle_settings variable per bundle. |
|
450 */ |
|
451 function field_update_7002() { |
|
452 $settings = variable_get('field_bundle_settings', array()); |
|
453 if ($settings) { |
|
454 foreach ($settings as $entity_type => $entity_type_settings) { |
|
455 foreach ($entity_type_settings as $bundle => $bundle_settings) { |
|
456 variable_set('field_bundle_settings_' . $entity_type . '__' . $bundle, $bundle_settings); |
|
457 } |
|
458 } |
|
459 variable_del('field_bundle_settings'); |
|
460 } |
|
461 } |
|
462 |
|
463 /** |
|
464 * Add the FieldInfo class to the class registry. |
|
465 */ |
|
466 function field_update_7003() { |
|
467 // Empty update to force a rebuild of the registry. |
|
468 } |
|
469 |
|
470 /** |
|
471 * Grant the new "administer fields" permission to trusted users. |
|
472 */ |
|
473 function field_update_7004() { |
|
474 // Assign the permission to anyone that already has a trusted core permission |
|
475 // that would have previously let them administer fields on an entity type. |
|
476 $rids = array(); |
|
477 $permissions = array( |
|
478 'administer site configuration', |
|
479 'administer content types', |
|
480 'administer users', |
|
481 ); |
|
482 foreach ($permissions as $permission) { |
|
483 $rids = array_merge($rids, array_keys(user_roles(FALSE, $permission))); |
|
484 } |
|
485 $rids = array_unique($rids); |
|
486 foreach ($rids as $rid) { |
|
487 _update_7000_user_role_grant_permissions($rid, array('administer fields'), 'field'); |
|
488 } |
|
489 } |
|
490 |
|
491 /** |
|
492 * @} End of "addtogroup updates-7.x-extra". |
|
493 */ |