Révision a1cafe7e
Ajouté par Assos Assos il y a plus de 4 ans
drupal7/sites/all/modules/field_collection/field_collection.module | ||
---|---|---|
184 | 184 |
* Loads a field collection revision. |
185 | 185 |
* |
186 | 186 |
* @param $revision_id |
187 |
* The field collection revision ID. |
|
187 |
* The id of the revision to load. |
|
188 |
* |
|
189 |
* @return |
|
190 |
* The entity object, or FALSE if there is no entity with the given revision |
|
191 |
* id. |
|
188 | 192 |
*/ |
189 | 193 |
function field_collection_item_revision_load($revision_id) { |
190 | 194 |
return entity_revision_load('field_collection_item', $revision_id); |
... | ... | |
193 | 197 |
/** |
194 | 198 |
* Loads field collection items. |
195 | 199 |
* |
200 |
* @param $ids |
|
201 |
* An array of entity IDs, or FALSE to load all entities. |
|
202 |
* @param $conditions |
|
203 |
* (deprecated) An associative array of conditions on the base table, where |
|
204 |
* the keys are the database fields and the values are the values those |
|
205 |
* fields must have. Instead, it is preferable to use EntityFieldQuery to |
|
206 |
* retrieve a list of entity IDs loadable by this function. |
|
207 |
* @param $reset |
|
208 |
* Whether to reset the internal cache for the requested entity type. |
|
209 |
* |
|
196 | 210 |
* @return |
197 | 211 |
* An array of field collection item entities. |
198 | 212 |
*/ |
... | ... | |
220 | 234 |
foreach (field_info_fields() as $field) { |
221 | 235 |
if ($field['type'] == 'field_collection') { |
222 | 236 |
$path = field_collection_field_get_path($field); |
223 |
$count = count(explode('/', $path));
|
|
237 |
$count = substr_count($path, '/') + 1;
|
|
224 | 238 |
|
225 | 239 |
$items[$path . '/%field_collection_item'] = array( |
226 | 240 |
'page callback' => 'field_collection_item_page_view', |
... | ... | |
280 | 294 |
* Implements hook_menu_alter() to fix the field collections admin UI tabs. |
281 | 295 |
*/ |
282 | 296 |
function field_collection_menu_alter(&$items) { |
283 |
if (module_exists('field_ui') && isset($items['admin/structure/field-collections/%field_collection_field_name/fields'])) {
|
|
297 |
if (isset($items['admin/structure/field-collections/%field_collection_field_name/fields']) && module_exists('field_ui')) {
|
|
284 | 298 |
// Make the fields task the default local task. |
285 | 299 |
$items['admin/structure/field-collections/%field_collection_field_name'] = $items['admin/structure/field-collections/%field_collection_field_name/fields']; |
286 | 300 |
$item = &$items['admin/structure/field-collections/%field_collection_field_name']; |
... | ... | |
299 | 313 |
|
300 | 314 |
/** |
301 | 315 |
* Menu title callback. |
316 |
* |
|
317 |
* return string |
|
302 | 318 |
*/ |
303 | 319 |
function field_collection_admin_page_title($field_name) { |
304 | 320 |
return t('Field collection @field_name', array('@field_name' => $field_name)); |
... | ... | |
306 | 322 |
|
307 | 323 |
/** |
308 | 324 |
* Implements hook_admin_paths(). |
325 |
* |
|
326 |
* @return array |
|
309 | 327 |
*/ |
310 | 328 |
function field_collection_admin_paths() { |
311 | 329 |
if (variable_get('node_admin_theme')) { |
... | ... | |
326 | 344 |
'title' => t('Administer field collections'), |
327 | 345 |
'description' => t('Create and delete fields on field collections.'), |
328 | 346 |
), |
347 |
'edit field collections' => array( |
|
348 |
'title' => t('Edit field collections'), |
|
349 |
'description' => t('Edit field collections.'), |
|
350 |
), |
|
329 | 351 |
); |
330 | 352 |
} |
331 | 353 |
|
... | ... | |
339 | 361 |
* items is determined. |
340 | 362 |
* @param $account |
341 | 363 |
* The user to check for. Leave it to NULL to check for the global user. |
364 |
* |
|
342 | 365 |
* @return boolean |
343 | 366 |
* Whether access is allowed or not. |
344 | 367 |
*/ |
... | ... | |
346 | 369 |
// We do not support editing field collection revisions that are not used at |
347 | 370 |
// the hosts default revision as saving the host might result in a new default |
348 | 371 |
// revision. |
349 |
if (isset($item) && !$item->isInUse() && $op != 'view') {
|
|
372 |
if ($op != 'view' && isset($item) && !$item->isInUse()) {
|
|
350 | 373 |
return FALSE; |
351 | 374 |
} |
375 |
if (user_access('edit field collections', $account)) { |
|
376 |
return TRUE; |
|
377 |
} |
|
352 | 378 |
if (user_access('administer field collections', $account)) { |
353 | 379 |
return TRUE; |
354 | 380 |
} |
... | ... | |
356 | 382 |
return FALSE; |
357 | 383 |
} |
358 | 384 |
$op = $op == 'view' ? 'view' : 'edit'; |
385 |
|
|
359 | 386 |
// Access is determined by the entity and field containing the reference. |
360 | 387 |
$field = field_info_field($item->field_name); |
361 |
$entity_access = entity_access($op == 'view' ? 'view' : 'update', $item->hostEntityType(), $item->hostEntity(), $account); |
|
362 |
return $entity_access && field_access($op, $field, $item->hostEntityType(), $item->hostEntity(), $account); |
|
388 |
$hostEntity = $item->hostEntity() !== FALSE ? $item->hostEntity() : NULL; |
|
389 |
$entity_access = entity_access($op == 'view' ? 'view' : 'update', $item->hostEntityType(), $hostEntity, $account); |
|
390 |
|
|
391 |
return $entity_access && field_access($op, $field, $item->hostEntityType(), $hostEntity, $account); |
|
363 | 392 |
} |
364 | 393 |
|
365 | 394 |
/** |
... | ... | |
548 | 577 |
// In case the entity has been changed / created, save it and set the id. |
549 | 578 |
// If the host entity creates a new revision, save new item-revisions as |
550 | 579 |
// well. |
551 |
if (isset($item['entity']) || !empty($host_entity->revision)) {
|
|
580 |
if (!empty($host_entity->revision) || isset($item['entity'])) {
|
|
552 | 581 |
if ($entity = field_collection_field_get_entity($item)) { |
553 | 582 |
// If the host entity is saved as new revision, do the same for the item. |
554 | 583 |
if (!empty($host_entity->revision) || !empty($host_entity->is_new_revision)) { |
... | ... | |
615 | 644 |
$items_to_remove = array_diff($ids, $current_by_id); |
616 | 645 |
// Delete unused field collection items now. |
617 | 646 |
foreach (field_collection_item_load_multiple($items_to_remove) as $un_item) { |
618 |
$un_item->updateHostEntity($host_entity); |
|
647 |
$un_item->updateHostEntity($host_entity, $host_entity_type);
|
|
619 | 648 |
$un_item->deleteRevision(TRUE); |
620 | 649 |
} |
621 | 650 |
} |
... | ... | |
626 | 655 |
* Implements hook_field_delete(). |
627 | 656 |
*/ |
628 | 657 |
function field_collection_field_delete($entity_type, $entity, $field, $instance, $langcode, &$items) { |
658 |
$ids = field_collection_field_item_to_ids($items); |
|
629 | 659 |
// Also delete all embedded entities. |
630 |
if ($ids = field_collection_field_item_to_ids($items)) {
|
|
660 |
if ($ids && field_info_field($field['field_name'])) {
|
|
631 | 661 |
// We filter out entities that are still being referenced by other |
632 | 662 |
// host-entities. This should never be the case, but it might happened e.g. |
633 | 663 |
// when modules cloned a node without knowing about field-collection. |
... | ... | |
665 | 695 |
} |
666 | 696 |
} |
667 | 697 |
|
698 |
/** |
|
699 |
* Implements hook_field_load(). |
|
700 |
* |
|
701 |
* Invokes the load hooks for the fields contained in new, unsaved field |
|
702 |
* collection items. This allows images inside a field collection item to be |
|
703 |
* seen on a node's preview page before it's saved. |
|
704 |
*/ |
|
705 |
function field_collection_field_load($entity_type, $entities, $field, $instances, $langcode, &$items, $age) { |
|
706 |
foreach ($items as &$each_item) { |
|
707 |
foreach ($each_item as &$each_field_collection_item) { |
|
708 |
if (!empty($each_field_collection_item['entity'])) { |
|
709 |
_field_invoke_multiple('load', 'field_collection_item', array(NULL => &$each_field_collection_item['entity'])); |
|
710 |
} |
|
711 |
} |
|
712 |
} |
|
713 |
} |
|
714 |
|
|
668 | 715 |
/** |
669 | 716 |
* Implements hook_field_delete_revision(). |
670 | 717 |
*/ |
671 | 718 |
function field_collection_field_delete_revision($entity_type, $entity, $field, $instance, $langcode, &$items) { |
672 | 719 |
foreach ($items as $item) { |
673 |
if (!empty($item['revision_id'])) { |
|
674 |
if ($entity = field_collection_item_revision_load($item['revision_id'])) { |
|
675 |
$entity->deleteRevision(TRUE); |
|
676 |
} |
|
720 |
if (!empty($item['revision_id']) |
|
721 |
&& $entity = field_collection_item_revision_load($item['revision_id'])) { |
|
722 |
$entity->deleteRevision(TRUE); |
|
677 | 723 |
} |
678 | 724 |
} |
679 | 725 |
} |
... | ... | |
698 | 744 |
if (!empty($item['value'])) { |
699 | 745 |
return FALSE; |
700 | 746 |
} |
701 |
elseif (isset($item['entity'])) { |
|
747 |
|
|
748 |
if (isset($item['entity'])) { |
|
702 | 749 |
return field_collection_item_is_empty($item['entity']); |
703 | 750 |
} |
704 | 751 |
return TRUE; |
... | ... | |
882 | 929 |
return implode('<br>', $output); |
883 | 930 |
} |
884 | 931 |
|
932 |
function field_collection_entity_preload($entities, $langcode, &$items, $fields) { |
|
933 |
static $local_entity_cache = array(); |
|
934 |
|
|
935 |
$fc_ids = array(); |
|
936 |
|
|
937 |
// Collect every possible term attached to any of the fieldable entities. |
|
938 |
foreach ($entities as $id => $entity) { |
|
939 |
foreach ($items[$id] as $delta => $item) { |
|
940 |
|
|
941 |
// Check if this item is in our local entity cache |
|
942 |
if (isset($local_entity_cache[$item['value']])) { |
|
943 |
$items[$id][$delta]['field_collection'] = $local_entity_cache[$item['value']]; |
|
944 |
continue; |
|
945 |
} |
|
946 |
|
|
947 |
// Force the array key to prevent duplicates. |
|
948 |
$fc_ids[$item['value']] = $item['value']; |
|
949 |
} |
|
950 |
} |
|
951 |
|
|
952 |
if ($fc_ids) { |
|
953 |
$new_entities = array(); |
|
954 |
$terms = field_collection_item_load_multiple($fc_ids); |
|
955 |
|
|
956 |
// Iterate through the fieldable entities again to attach the loaded |
|
957 |
// field collection data. |
|
958 |
foreach ($entities as $id => $entity) { |
|
959 |
$rekey = FALSE; |
|
960 |
|
|
961 |
foreach ($items[$id] as $delta => $item) { |
|
962 |
// Check whether the field collection field instance value could be loaded. |
|
963 |
if (isset($terms[$item['value']])) { |
|
964 |
// Replace the instance value with the term data. |
|
965 |
$e = $terms[$item['value']]; |
|
966 |
$local_entity_cache[$item['value']] = $e; |
|
967 |
$items[$id][$delta]['field_collection'] = $e; |
|
968 |
|
|
969 |
foreach ($fields as $field_name => $field) { |
|
970 |
if (isset($e->$field_name)) { |
|
971 |
$field_data = $e->$field_name; |
|
972 |
if (isset($field_data[$langcode])) { |
|
973 |
$new_entities[$e->item_id] = $e->item_id; |
|
974 |
$items[$e->item_id] = $field_data[$langcode]; |
|
975 |
} |
|
976 |
} |
|
977 |
} |
|
978 |
} |
|
979 |
// Otherwise, unset the instance value, since the field colletion entity does not exist. |
|
980 |
else { |
|
981 |
unset($items[$id][$delta]); |
|
982 |
$rekey = TRUE; |
|
983 |
} |
|
984 |
} |
|
985 |
|
|
986 |
if ($rekey) { |
|
987 |
// Rekey the items array. |
|
988 |
$items[$id] = array_values($items[$id]); |
|
989 |
} |
|
990 |
} |
|
991 |
|
|
992 |
field_collection_entity_preload($new_entities, $langcode, $items, $fields); |
|
993 |
} |
|
994 |
} |
|
995 |
|
|
996 |
function field_collection_field_formatter_prepare_view($entity_type, $entities, $field, $instances, $langcode, &$items, $displays) { |
|
997 |
$fields = field_read_fields(array('type' => 'field_collection')); |
|
998 |
field_collection_entity_preload($entities, $langcode, $items, $fields); |
|
999 |
} |
|
1000 |
|
|
885 | 1001 |
/** |
886 | 1002 |
* Implements hook_field_formatter_view(). |
887 | 1003 |
*/ |
... | ... | |
915 | 1031 |
|
916 | 1032 |
$view_mode = !empty($display['settings']['view_mode']) ? $display['settings']['view_mode'] : 'full'; |
917 | 1033 |
foreach ($items as $delta => $item) { |
918 |
if ($field_collection = field_collection_field_get_entity($item)) { |
|
919 |
$element[$delta]['entity'] = $field_collection->view($view_mode, $langcode); |
|
1034 |
// Existing field collections should be loaded without cache so that |
|
1035 |
// node Preview will work for both existing nodes and new ones. |
|
1036 |
if (isset($item['entity']->item_id)) { |
|
1037 |
// Load without cache. |
|
1038 |
$field_collection = field_collection_item_load($item['entity']->item_id, TRUE); |
|
1039 |
} |
|
1040 |
else { |
|
1041 |
$field_collection = field_collection_field_get_entity($item); |
|
1042 |
} |
|
1043 |
|
|
1044 |
if ($field_collection) { |
|
1045 |
$element[$delta]['entity'] = $field_collection->view($view_mode); |
|
920 | 1046 |
$element[$delta]['#theme_wrappers'] = array('field_collection_view'); |
921 | 1047 |
$element[$delta]['#attributes']['class'][] = 'field-collection-view'; |
922 | 1048 |
$element[$delta]['#attributes']['class'][] = 'clearfix'; |
... | ... | |
949 | 1075 |
$view_mode = !empty($display['settings']['view_mode']) ? $display['settings']['view_mode'] : 'full'; |
950 | 1076 |
foreach ($items as $delta => $item) { |
951 | 1077 |
if ($field_collection = field_collection_field_get_entity($item)) { |
952 |
$element[$delta]['entity'] = $field_collection->view($view_mode, $langcode);
|
|
1078 |
$element[$delta]['entity'] = $field_collection->view($view_mode); |
|
953 | 1079 |
} |
954 | 1080 |
} |
955 | 1081 |
break; |
... | ... | |
998 | 1124 |
$path = field_collection_field_get_path($field); |
999 | 1125 |
list($id) = entity_extract_ids($entity_type, $entity); |
1000 | 1126 |
$element['#suffix'] = ''; |
1001 |
if (!empty($settings['description']) && $entity_type != 'node') {
|
|
1127 |
if ($entity_type != 'node' && !empty($settings['description'])) {
|
|
1002 | 1128 |
$element['#suffix'] .= '<div class="description field-collection-description">' . field_filter_xss($instance['description']) . '</div>'; |
1003 | 1129 |
} |
1004 | 1130 |
$title = entity_i18n_string("field:{$field['field_name']}:{$instance['bundle']}:setting_add", $settings['add']); |
... | ... | |
1052 | 1178 |
'default value' => FIELD_BEHAVIOR_NONE, |
1053 | 1179 |
), |
1054 | 1180 |
), |
1181 |
'field_collection_sorter' => array( |
|
1182 |
'label' => t('Sortable only'), |
|
1183 |
'field types' => array('field_collection'), |
|
1184 |
'behaviors' => array( |
|
1185 |
'multiple values' => FIELD_BEHAVIOR_CUSTOM, |
|
1186 |
'default value' => FIELD_BEHAVIOR_DEFAULT, |
|
1187 |
), |
|
1188 |
), |
|
1055 | 1189 |
); |
1056 | 1190 |
} |
1057 | 1191 |
|
... | ... | |
1092 | 1226 |
|
1093 | 1227 |
$field_state = field_form_get_state($field_parents, $field_name, $language, $form_state); |
1094 | 1228 |
|
1095 |
if (field_collection_hide_blank_items($field) && $delta == $field_state['items_count'] && $delta > 0) {
|
|
1229 |
if ($delta > 0 && $delta == $field_state['items_count'] && field_collection_hide_blank_items($field)) {
|
|
1096 | 1230 |
// Do not add a blank item. Also see |
1097 | 1231 |
// field_collection_field_attach_form() for correcting #max_delta. |
1098 | 1232 |
$recursion--; |
1099 | 1233 |
return FALSE; |
1100 | 1234 |
} |
1101 |
elseif (field_collection_hide_blank_items($field) && $field_state['items_count'] == 0) { |
|
1235 |
|
|
1236 |
if ($field_state['items_count'] == 0 && field_collection_hide_blank_items($field)) { |
|
1102 | 1237 |
// We show one item, so also specify that as item count. So when the |
1103 | 1238 |
// add button is pressed the item count will be 2 and we show two items. |
1104 | 1239 |
$field_state['items_count'] = 1; |
... | ... | |
1191 | 1326 |
|
1192 | 1327 |
$recursion--; |
1193 | 1328 |
return $element; |
1329 |
|
|
1330 |
case 'field_collection_sorter': |
|
1331 |
$elements = array(); |
|
1332 |
|
|
1333 |
$field_name = $field['field_name']; |
|
1334 |
$parents = $form['#parents']; |
|
1335 |
$field_state = field_form_get_state($parents, $field_name, $langcode, $form_state); |
|
1336 |
$count = $field_state['items_count']; |
|
1337 |
|
|
1338 |
for ($delta = 0; $delta < $count; $delta++) { |
|
1339 |
$item_id = isset($items[$delta]['value']) ? $items[$delta]['value'] : NULL; |
|
1340 |
$revision_id = isset($items[$delta]['revision_id']) ? $items[$delta]['revision_id'] : NULL; |
|
1341 |
|
|
1342 |
// add a label component to visually identify this field collection item |
|
1343 |
$element['label'] = array(); |
|
1344 |
if ($item_id) { |
|
1345 |
$item = field_collection_item_load($item_id); |
|
1346 |
$element['label']['#markup'] = $item ? $item->label() : $item_id; |
|
1347 |
} |
|
1348 |
|
|
1349 |
// the field stored value (item_id) and revision_id values |
|
1350 |
// so we need hidden fields to represent them |
|
1351 |
$element['value'] = array( |
|
1352 |
'#type' => 'hidden', |
|
1353 |
'#default_value' => $item_id, |
|
1354 |
); |
|
1355 |
$element['revision_id'] = array( |
|
1356 |
'#type' => 'hidden', |
|
1357 |
'#default_value' => $revision_id, |
|
1358 |
); |
|
1359 |
|
|
1360 |
// Input field for the delta (drag-n-drop reordering). |
|
1361 |
// We name the element '_weight' to avoid clashing with elements |
|
1362 |
// defined by widget. |
|
1363 |
$element['_weight'] = array( |
|
1364 |
'#type' => 'weight', |
|
1365 |
'#title' => t('Weight for row @number', array('@number' => $delta + 1)), |
|
1366 |
'#title_display' => 'invisible', |
|
1367 |
// Note: this 'delta' is the FAPI 'weight' element's property. |
|
1368 |
'#delta' => $count, |
|
1369 |
'#default_value' => isset($items[$delta]['_weight']) ? $items[$delta]['_weight'] : $delta, |
|
1370 |
'#weight' => 100, |
|
1371 |
); |
|
1372 |
|
|
1373 |
$elements[$delta] = $element; |
|
1374 |
} |
|
1375 |
|
|
1376 |
if ($elements) { |
|
1377 |
$elements += array( |
|
1378 |
'#theme' => 'field_multiple_value_form', |
|
1379 |
'#field_name' => $field['field_name'], |
|
1380 |
'#cardinality' => $field['cardinality'], |
|
1381 |
'#title' => check_plain($instance['label']), |
|
1382 |
'#required' => FALSE, |
|
1383 |
'#description' => field_filter_xss($instance['description']), |
|
1384 |
'#max_delta' => $count-1, |
|
1385 |
); |
|
1386 |
} |
|
1387 |
|
|
1388 |
return $elements; |
|
1194 | 1389 |
} |
1195 | 1390 |
} |
1196 | 1391 |
|
... | ... | |
1231 | 1426 |
$field = field_info_field($field_name); |
1232 | 1427 |
|
1233 | 1428 |
if ($field['type'] == 'field_collection' && field_collection_hide_blank_items($field) |
1234 |
&& field_access('edit', $field, $entity_type) && $instance['widget']['type'] == 'field_collection_embed') {
|
|
1429 |
&& field_access('edit', $field, $entity_type)) { |
|
1235 | 1430 |
|
1236 | 1431 |
$element_langcode = $form[$field_name]['#language']; |
1237 | 1432 |
if ($form[$field_name][$element_langcode]['#max_delta'] > 0) { |
... | ... | |
1240 | 1435 |
// Remove blank form elements and force user to explicitly add a field |
1241 | 1436 |
// collection if both 'hide_initial_item' and 'hide_blank_items' are TRUE. |
1242 | 1437 |
if ($field['settings']['hide_initial_item'] |
1243 |
&& $field['settings']['hide_blank_items'] |
|
1244 |
&& field_collection_item_is_empty($form[$field_name][$element_langcode][0]['#entity'])) { |
|
1438 |
&& $field['settings']['hide_blank_items'] |
|
1439 |
&& $form[$field_name][$element_langcode][0]['#entity'] instanceof FieldCollectionItemEntity |
|
1440 |
&& field_collection_item_is_empty($form[$field_name][$element_langcode][0]['#entity'])) { |
|
1245 | 1441 |
|
1246 | 1442 |
_field_collection_process_children_attached($form[$field_name][$element_langcode][0]); |
1247 | 1443 |
unset($form[$field_name][$element_langcode][0]); |
... | ... | |
1249 | 1445 |
} |
1250 | 1446 |
} |
1251 | 1447 |
|
1252 |
if ($field['type'] == 'field_collection' |
|
1253 |
&& $field['cardinality'] == FIELD_CARDINALITY_UNLIMITED |
|
1448 |
if ($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED |
|
1254 | 1449 |
&& empty($form_state['programmed']) |
1450 |
&& $instance['widget']['type'] === 'field_collection_embed' |
|
1255 | 1451 |
&& field_access('edit', $field, $entity_type) |
1256 |
&& $instance['widget']['type'] == 'field_collection_embed') {
|
|
1452 |
&& $field['type'] === 'field_collection') {
|
|
1257 | 1453 |
|
1258 | 1454 |
$element_langcode = $form[$field_name]['#language']; |
1259 | 1455 |
$element_wrapper = $form[$field_name][$element_langcode]['add_more']['#ajax']['wrapper']; |
... | ... | |
1267 | 1463 |
|
1268 | 1464 |
// If FCs are translatable, make sure we mark any necessary sub-fields in the |
1269 | 1465 |
// FC widget as translatable as well. |
1270 |
if ($entity_type == 'field_collection_item' |
|
1466 |
if ($entity_type === 'field_collection_item'
|
|
1271 | 1467 |
&& field_collection_item_is_translatable() |
1272 | 1468 |
) { |
1273 | 1469 |
foreach (field_info_instances($entity_type, $form['#bundle']) as $field_name => $instance) { |
... | ... | |
1433 | 1629 |
*/ |
1434 | 1630 |
function field_collection_field_get_entity(&$item, $field_name = NULL) { |
1435 | 1631 |
if (isset($item['entity']) && ($item['entity']->entityType() == 'field_collection_item')) { |
1632 |
if (count($item) > 1) { |
|
1633 |
// If $item contains more thing than 'entity', then it is sent from VBO. |
|
1634 |
// We clone the object to avoid that the same field collection item of the |
|
1635 |
// faked object is attached to multiple host objects. |
|
1636 |
return clone $item['entity']; |
|
1637 |
} |
|
1436 | 1638 |
return $item['entity']; |
1437 | 1639 |
} |
1438 |
elseif (isset($item['value'])) { |
|
1640 |
|
|
1641 |
if (isset($item['value'])) { |
|
1439 | 1642 |
// By default always load the default revision, so caches get used. |
1440 | 1643 |
$entity = field_collection_item_load($item['value']); |
1441 | 1644 |
if ($entity && $entity->revision_id != $item['revision_id']) { |
... | ... | |
1444 | 1647 |
} |
1445 | 1648 |
return $entity; |
1446 | 1649 |
} |
1447 |
elseif (!isset($item['entity']) && isset($field_name)) { |
|
1650 |
|
|
1651 |
if (isset($field_name) && !isset($item['entity'])) { |
|
1448 | 1652 |
$item['entity'] = entity_create('field_collection_item', array('field_name' => $field_name)); |
1449 | 1653 |
return $item['entity']; |
1450 | 1654 |
} |
... | ... | |
1527 | 1731 |
} |
1528 | 1732 |
|
1529 | 1733 |
// Now validate required elements if the entity is not empty. |
1530 |
if (!field_collection_item_is_empty($field_collection_item) && !empty($element['#field_collection_required_elements'])) {
|
|
1734 |
if (!empty($element['#field_collection_required_elements']) && !field_collection_item_is_empty($field_collection_item)) {
|
|
1531 | 1735 |
foreach ($element['#field_collection_required_elements'] as &$elements) { |
1532 | 1736 |
|
1533 | 1737 |
// Copied from _form_validate(). |
... | ... | |
1550 | 1754 |
$field_values = drupal_array_get_nested_value($form_state['values'], array_slice($elements['#array_parents'], 0, $field_depth)); |
1551 | 1755 |
|
1552 | 1756 |
// Special case lists since we don't get the correct array_parents. |
1553 |
if (count($elements['#array_parents']) < $field_depth && is_array($field_values)) {
|
|
1757 |
if (is_array($field_values) && count($elements['#array_parents']) < $field_depth) {
|
|
1554 | 1758 |
$field_values = reset($field_values); |
1555 | 1759 |
} |
1556 | 1760 |
|
... | ... | |
1574 | 1778 |
|
1575 | 1779 |
// Only if the form is being submitted, finish the collection entity and |
1576 | 1780 |
// prepare it for saving. |
1577 |
if ($form_state['submitted'] && !form_get_errors()) {
|
|
1781 |
if ($form_state['submitted'] && !form_get_error($element)) {
|
|
1578 | 1782 |
|
1579 | 1783 |
field_attach_submit('field_collection_item', $field_collection_item, $element, $form_state); |
1580 | 1784 |
|
... | ... | |
1759 | 1963 |
return entity_metadata_wrapper($item->hostEntityType(), $item->hostEntity()); |
1760 | 1964 |
} |
1761 | 1965 |
|
1966 |
/** |
|
1967 |
* Entity property info getter callback for the host entity property. |
|
1968 |
*/ |
|
1969 |
function field_collection_item_get_specific_type_host_entity($item, array $options, $name) { |
|
1970 |
// These properties' machine names have the form "host_entity_TYPE". |
|
1971 |
if (substr($name, 0, 12) !== 'host_entity_') { |
|
1972 |
return NULL; |
|
1973 |
} |
|
1974 |
return $item->hostEntityType() === substr($name, 12) ? $item->hostEntity() : NULL; |
|
1975 |
} |
|
1976 |
|
|
1762 | 1977 |
/** |
1763 | 1978 |
* Entity property info getter callback for the field collection items. |
1764 | 1979 |
* |
... | ... | |
1805 | 2020 |
$items[$delta][$columns[0]] = $value->item_id; |
1806 | 2021 |
$items[$delta][$columns[1]] = $value->revision_id; |
1807 | 2022 |
} |
1808 |
elseif (is_array($value) && isset($value['value']) && isset($value['revision_id'])) {
|
|
2023 |
elseif (is_array($value) && isset($value['value'], $value['revision_id'])) {
|
|
1809 | 2024 |
$items[$delta][$columns[0]] = $value['value']; |
1810 | 2025 |
$items[$delta][$columns[1]] = $value['revision_id']; |
1811 | 2026 |
} |
... | ... | |
1826 | 2041 |
* Implements hook_devel_generate(). |
1827 | 2042 |
*/ |
1828 | 2043 |
function field_collection_devel_generate($object, $field, $instance, $bundle) { |
2044 |
if (field_behaviors_widget('multiple values', $instance) == FIELD_BEHAVIOR_CUSTOM) { |
|
2045 |
return devel_generate_multiple('_field_collection_devel_generate', $object, $field, $instance, $bundle); |
|
2046 |
} |
|
2047 |
|
|
2048 |
return _field_collection_devel_generate($object, $field, $instance, $bundle); |
|
2049 |
} |
|
2050 |
|
|
2051 |
function _field_collection_devel_generate($object, $field, $instance, $bundle) { |
|
1829 | 2052 |
// Create a new field collection object and add fake data to its fields. |
1830 | 2053 |
$field_collection = entity_create('field_collection_item', array('field_name' => $field['field_name'])); |
1831 | 2054 |
$field_collection->language = $object->language; |
... | ... | |
1927 | 2150 |
if (!empty($value[$language])) { |
1928 | 2151 |
$source_items = !empty($entity->{$field_name}[$source_language]) ? field_collection_field_item_to_ids($entity->{$field_name}[$source_language]) : array(); |
1929 | 2152 |
foreach ($value[$language] as $delta => $field_value) { |
1930 |
if (!isset($field_value['entity'])) { |
|
1931 |
if ($fc_entity = field_collection_field_get_entity($field_value)) { |
|
1932 |
// Check if this field collection item belongs to the source language |
|
1933 |
if (in_array($fc_entity->item_id, $source_items)) { |
|
1934 |
// Clone the field collection item |
|
1935 |
$new_fc_entity = clone $fc_entity; |
|
1936 |
$new_fc_entity->item_id = NULL; |
|
1937 |
$new_fc_entity->revision_id = NULL; |
|
1938 |
$new_fc_entity->is_new = TRUE; |
|
1939 |
|
|
1940 |
// Set the new entity for saving it later |
|
1941 |
$entity->{$field_name}[$language][$delta]['entity'] = $new_fc_entity; |
|
1942 |
} |
|
1943 |
} |
|
2153 |
// Check if this field collection item belongs to the source language |
|
2154 |
if (!isset($field_value['entity']) |
|
2155 |
&& ($fc_entity = field_collection_field_get_entity($field_value)) |
|
2156 |
&& in_array($fc_entity->item_id, $source_items)) { |
|
2157 |
// Clone the field collection item |
|
2158 |
$new_fc_entity = clone $fc_entity; |
|
2159 |
$new_fc_entity->item_id = NULL; |
|
2160 |
$new_fc_entity->revision_id = NULL; |
|
2161 |
$new_fc_entity->is_new = TRUE; |
|
2162 |
|
|
2163 |
// Set the new entity for saving it later |
|
2164 |
$entity->{$field_name}[$language][$delta]['entity'] = $new_fc_entity; |
|
2165 |
} |
|
2166 |
} |
|
2167 |
} |
|
2168 |
} |
|
2169 |
} |
|
2170 |
} |
|
2171 |
} |
|
2172 |
|
|
2173 |
|
|
2174 |
/** |
|
2175 |
* Implements hook_feeds_processor_targets_alter() |
|
2176 |
*/ |
|
2177 |
function field_collection_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_name) { |
|
2178 |
|
|
2179 |
// Load up. |
|
2180 |
$loaded = &drupal_static(__FUNCTION__, FALSE); |
|
2181 |
|
|
2182 |
if (!$loaded) { |
|
2183 |
$loaded = TRUE; |
|
2184 |
$path = drupal_get_path('module', 'feeds') . '/mappers'; |
|
2185 |
$files = drupal_system_listing('/.*\.inc$/', $path, 'name', 0); |
|
2186 |
foreach ($files as $file) { |
|
2187 |
if (strpos($file->uri, '/mappers/') !== FALSE) { |
|
2188 |
require_once DRUPAL_ROOT . '/' . $file->uri; |
|
2189 |
} |
|
2190 |
} |
|
2191 |
} |
|
2192 |
|
|
2193 |
foreach (field_info_instances($entity_type, $bundle_name) as $name => $instance) { |
|
2194 |
$info = field_info_field($name); |
|
2195 |
if ($info['type'] == 'field_collection') { |
|
2196 |
|
|
2197 |
$sub_type = 'field_collection_item'; |
|
2198 |
$new_targets = module_invoke_all('feeds_processor_targets', $sub_type, $info['field_name']); |
|
2199 |
drupal_alter('feeds_processor_targets', $new_targets, $sub_type, $info['field_name']); |
|
2200 |
|
|
2201 |
foreach ($new_targets as $sub_name => $target) { |
|
2202 |
$new_name = t($info['field_name']) . ':' . t($sub_name); |
|
2203 |
$targets[$new_name] = $target; |
|
2204 |
if (isset($target['name'])) { |
|
2205 |
$targets[$new_name]['name'] = $instance['label'] . ':' . $target['name']; |
|
2206 |
} |
|
2207 |
// We override callback for now and retrieve original later. |
|
2208 |
$targets[$new_name]['callback'] = 'field_collection_feeds_set_target'; |
|
2209 |
} |
|
2210 |
} |
|
2211 |
} |
|
2212 |
|
|
2213 |
} |
|
2214 |
|
|
2215 |
|
|
2216 |
/** |
|
2217 |
* Process Field Collection items. |
|
2218 |
* |
|
2219 |
* @param [type] $source [description] |
|
2220 |
* @param [type] $entity [description] |
|
2221 |
* @param [type] $target [description] |
|
2222 |
* @param [type] $value [description] |
|
2223 |
* @param [type] $main_mapping [description] |
|
2224 |
* @return [type] [description] |
|
2225 |
*/ |
|
2226 |
function field_collection_feeds_set_target($source, $entity, $target, $value, $main_mapping) { |
|
2227 |
$sub_targets = &drupal_static(__FUNCTION__, array()); |
|
2228 |
|
|
2229 |
$args = explode(':', $target); |
|
2230 |
$target = array_shift($args); |
|
2231 |
$sub_target = implode(':', $args); |
|
2232 |
|
|
2233 |
$sub_type = 'field_collection_item'; |
|
2234 |
$new_targets = module_invoke_all('feeds_processor_targets', $sub_type, $target); |
|
2235 |
drupal_alter('feeds_processor_targets', $new_targets, $sub_type, $target); |
|
2236 |
|
|
2237 |
// Now we retrieve old callbacks and keep then on a static cache. |
|
2238 |
if (!isset($sub_targets[$target])) { |
|
2239 |
$sub_targets[$target] = array(); |
|
2240 |
drupal_alter('feeds_processor_targets', $sub_targets[$target], $sub_type, $target); |
|
2241 |
} |
|
2242 |
|
|
2243 |
$_sub_targets = $new_targets; |
|
2244 |
|
|
2245 |
$value = is_array($value) ? $value : array($value); |
|
2246 |
$info = field_info_field($target); |
|
2247 |
|
|
2248 |
// Iterate over all values. |
|
2249 |
$delta = 0; |
|
2250 |
$field = isset($entity->$target) ? $entity->$target : array(); |
|
2251 |
try { |
|
2252 |
|
|
2253 |
// $delta = which FC instance. |
|
2254 |
// We iterate by subfield, not by FC. |
|
2255 |
while (isset($value[$delta])) { |
|
2256 |
|
|
2257 |
// Zero out. |
|
2258 |
$field_collection_item = null; |
|
2259 |
|
|
2260 |
// FC is already set on host entity. |
|
2261 |
if (isset($field[LANGUAGE_NONE][$delta]['entity'])) { |
|
2262 |
$field_collection_item = $field[LANGUAGE_NONE][$delta]['entity']; |
|
2263 |
} |
|
2264 |
// FC is on host entity, we have FC item_id, but FC is not loaded. |
|
2265 |
elseif (isset($field[LANGUAGE_NONE][$delta]['value'])) { |
|
2266 |
$field_collection_item = field_collection_item_load($field[LANGUAGE_NONE][$delta]['value']); |
|
2267 |
|
|
2268 |
// Zero out field so that we don't just keep accumulating values. |
|
2269 |
unset($field_collection_item->{$sub_target}[LANGUAGE_NONE] ); |
|
2270 |
} |
|
2271 |
|
|
2272 |
// Host entity does not have any attached FCs yet. |
|
2273 |
if (empty($field_collection_item)) { |
|
2274 |
$field_collection_item = entity_create('field_collection_item', array('field_name' => $target)); |
|
2275 |
$field_collection_item->setHostEntity($entity->feeds_item->entity_type, $entity); |
|
2276 |
} |
|
2277 |
|
|
2278 |
$sub_mapping = array(); |
|
2279 |
$config = $source->importer()->getConfig(); |
|
2280 |
if (!empty($config['processor']['config']['mappings'])) { |
|
2281 |
foreach ($config['processor']['config']['mappings'] as $mapping) { |
|
2282 |
if ($mapping['target'] == $target . ':' . $sub_target) { |
|
2283 |
$sub_mapping = $mapping; |
|
2284 |
$sub_mapping['target'] = $sub_target; |
|
2285 |
// Needs language or feeds mappers shout php notices. |
|
2286 |
$sub_mapping['language'] = !empty($config['processor']['config']['language']) ? $config['processor']['config']['language'] : LANGUAGE_NONE; |
|
2287 |
break; |
|
2288 |
} |
|
2289 |
} |
|
2290 |
} |
|
2291 |
|
|
2292 |
if (isset($_sub_targets[$sub_target]['callback']) && function_exists($_sub_targets[$sub_target]['callback'])) { |
|
2293 |
$callback = $_sub_targets[$sub_target]['callback']; |
|
2294 |
|
|
2295 |
// Normalize |
|
2296 |
if (!is_array($value[$delta])) { |
|
2297 |
$value[$delta] = array($value[$delta]); |
|
2298 |
} |
|
2299 |
|
|
2300 |
// Check for a limit and force that limit. |
|
2301 |
if ($info['cardinality'] !== '-1') { |
|
2302 |
$value[$delta] = array_slice($value[$delta], 0, $info['cardinality']); |
|
2303 |
} |
|
2304 |
|
|
2305 |
// HiJack the file callback so we can make it work. |
|
2306 |
if ($callback == 'file_feeds_set_target') { |
|
2307 |
$callback = 'field_collection_file_feeds_set_target'; |
|
2308 |
} |
|
2309 |
|
|
2310 |
// Allow altering with many parameters. Cannot use drupal_alter here. |
|
2311 |
$implements = module_implements('sub_target_pre_callback_parse'); |
|
2312 |
foreach ($implements as $module_name) { |
|
2313 |
$hook = $module_name . '_' . 'sub_target_pre_callback_parse'; |
|
2314 |
$hook($target, $sub_target, $entity, $field, $field_collection_item, $value[$delta]); |
|
2315 |
} |
|
2316 |
|
|
2317 |
$callback($source, $field_collection_item, $sub_target, $value[$delta], $sub_mapping); |
|
2318 |
} |
|
2319 |
|
|
2320 |
// No need to save the field collection here. Just wait until the node is saved. |
|
2321 |
// If we save the FC here we get a huge performance degregation. |
|
2322 |
$field[LANGUAGE_NONE][$delta]['entity'] = $field_collection_item; |
|
2323 |
|
|
2324 |
// Break when only hitting the max delta. |
|
2325 |
if ($info['cardinality'] == $delta) { |
|
2326 |
break; |
|
2327 |
} |
|
2328 |
|
|
2329 |
$delta++; |
|
2330 |
} |
|
2331 |
|
|
2332 |
} |
|
2333 |
catch (Exception $e) { |
|
2334 |
drupal_set_message($e->getMessage(), 'error'); |
|
2335 |
watchdog_exception('field_collection', $e, $e->getMessage()); |
|
2336 |
throw $e; |
|
2337 |
} |
|
2338 |
|
|
2339 |
$entity->{$target} = $field; |
|
2340 |
} |
|
2341 |
|
|
2342 |
/** |
|
2343 |
* Wrapper function for file_feeds_set_target as it doesn't do the nested stuff. |
|
2344 |
*/ |
|
2345 |
function field_collection_file_feeds_set_target($source, $entity, $target, $value) { |
|
2346 |
|
|
2347 |
if (empty($value)) { |
|
2348 |
return; |
|
2349 |
} |
|
2350 |
module_load_include('inc', 'file'); |
|
2351 |
|
|
2352 |
// Make sure $value is an array of objects of type FeedsEnclosure. |
|
2353 |
if (!is_array($value)) { |
|
2354 |
$value = array($value); |
|
2355 |
} |
|
2356 |
foreach ($value as $k => $v) { |
|
2357 |
if (!($v instanceof FeedsEnclosure)) { |
|
2358 |
if (is_string($v)) { |
|
2359 |
$value[$k] = new FeedsEnclosure($v, file_get_mimetype($v)); |
|
2360 |
} |
|
2361 |
else { |
|
2362 |
unset($value[$k]); |
|
2363 |
} |
|
2364 |
} |
|
2365 |
} |
|
2366 |
if (empty($value)) { |
|
2367 |
return; |
|
2368 |
} |
|
2369 |
|
|
2370 |
$entity_type = 'field_collection_item'; |
|
2371 |
$bundle = $entity->field_name; |
|
2372 |
|
|
2373 |
// Determine file destination. |
|
2374 |
// @todo This needs review and debugging. |
|
2375 |
$instance_info = field_info_instance($entity_type, $target, $bundle); |
|
2376 |
$info = field_info_field($target); |
|
2377 |
$data = array(); |
|
2378 |
if (!empty($entity->uid)) { |
|
2379 |
$data[$entity_type] = $entity; |
|
2380 |
} |
|
2381 |
$destination = file_field_widget_uri($info, $instance_info, $data); |
|
2382 |
|
|
2383 |
// Populate entity. |
|
2384 |
$i = 0; |
|
2385 |
$field = isset($entity->$target) ? $entity->$target : array(); |
|
2386 |
foreach ($value as $v) { |
|
2387 |
$file = FALSE; |
|
2388 |
try { |
|
2389 |
$v->setAllowedExtensions($instance_info['settings']['file_extensions']); |
|
2390 |
$file = $v->getFile($destination); |
|
2391 |
} |
|
2392 |
catch (Exception $e) { |
|
2393 |
watchdog('feeds', check_plain($e->getMessage())); |
|
2394 |
} |
|
2395 |
if ($file) { |
|
2396 |
$field[LANGUAGE_NONE][$i] = (array)$file; |
|
2397 |
$field[LANGUAGE_NONE][$i]['display'] = 1; // @todo: Figure out how to properly populate this field. |
|
2398 |
if ($info['cardinality'] == 1) { |
|
2399 |
break; |
|
2400 |
} |
|
2401 |
$i++; |
|
2402 |
} |
|
2403 |
} |
|
2404 |
$entity->{$target} = $field; |
|
2405 |
|
|
2406 |
} |
|
2407 |
|
|
2408 |
|
|
2409 |
/** |
|
2410 |
* Implementation of hook_feeds_presave(). |
|
2411 |
* Invoked before a feed item is saved. |
|
2412 |
* |
|
2413 |
* @param FeedsSource $source |
|
2414 |
* FeedsSource object that describes the source that is being imported. |
|
2415 |
* @param $entity |
|
2416 |
* The entity object. |
|
2417 |
* @param array $item |
|
2418 |
* The parser result for this entity. |
|
2419 |
* @param int|null $entity_id |
|
2420 |
* The id of the current item which is going to be updated. If this is a new |
|
2421 |
* item, then NULL is passed. |
|
2422 |
*/ |
|
2423 |
function field_collection_feeds_presave(FeedsSource $source, $entity, $item, $entity_id) { |
|
2424 |
$feed_config = $source->importer()->getConfig(); |
|
2425 |
$mappings = $feed_config['processor']['config']['mappings']; |
|
2426 |
|
|
2427 |
// Only hook in when updating the entity. |
|
2428 |
if (empty($entity_id)) { |
|
2429 |
|
|
2430 |
// Go through $mappings and find the FC fields. |
|
2431 |
foreach ($mappings as $mapping) { |
|
2432 |
|
|
2433 |
if (strpos($mapping['target'], ':') !== FALSE) { |
|
2434 |
$parts = explode(':', $mapping['target']); |
|
2435 |
$fc_name = array_shift($parts); |
|
2436 |
$info = field_info_field($fc_name); |
|
2437 |
|
|
2438 |
// If the field is not a field collection, skip it. |
|
2439 |
if ($info['type'] != 'field_collection') { |
|
2440 |
continue; |
|
2441 |
} |
|
2442 |
|
|
2443 |
if (isset($entity->{$fc_name})) { |
|
2444 |
foreach ($entity->{$fc_name}[LANGUAGE_NONE] as $delta => $fc_unloaded) { |
|
2445 |
|
|
2446 |
// If an FC is not loaded, we don't want it. Unset it so it won't save. |
|
2447 |
if (!isset($entity->{$fc_name}[LANGUAGE_NONE][$delta]['entity'])) { |
|
2448 |
unset($entity->{$fc_name}[LANGUAGE_NONE][$delta]); |
|
1944 | 2449 |
} |
1945 | 2450 |
} |
2451 |
|
|
1946 | 2452 |
} |
1947 | 2453 |
} |
1948 | 2454 |
} |
1949 | 2455 |
} |
1950 | 2456 |
} |
2457 |
|
Formats disponibles : Unified diff
Weekly update of contrib modules