We have tons of "EntityMetadataWrapperExceptions" as of "data structure is not set".
Mainly field_collection suffers from this like in #1033202: [Meta] Generic entity processor.

To reproduce:

$just_created_node_wrapper->field_collection->field_foo->set($foo);

Result:
* EntityMetadataWrapperException

EntityMetadataWrapperException: Unable to set the data property field_contract_participant as the parent data structure is not set. in EntityStructureWrapper->setProperty() (line 477 of sites/all/modules/entity/includes/entity.wrapper.inc).

Expected:
* field collection wrapper autocreates when needed

For now i use this workaround:

if($just_created_node_wrapper->field_my_collection->value() === NULL) { // Workaround Issue 1911158
  $empty_field_collection_properties = array('field_name' => 'field_my_collection', 'host_entity' => $just_created_node_wrapper);
  $empty_field_collection = entity_property_values_create_entity('field_collection_item', $empty_field_collection_properties);
  $empty_field_collection->field_my_collection->set($empty_field_collection);
}
$just_created_node_wrapper->field_my_collection->field_foo->set($foo);

which might better live where the exception was raised.

Objections?

Comments

geek-merlin’s picture

Project: Entity API » Field collection
Issue summary: View changes

improved workaround

geek-merlin’s picture

Title: Wrappers should autocreate » Wrappers should autocreate ("EntityMetadataWrapperException - Parent data structure is not set")
Project: Field collection » Entity API

It seems we can even do this several levels:

  // Workaround #1911158
  if(!$contract->value()) {
    $empty_field_collection_properties = array('field_name' => 'field_contract', 'host_entity' => $w_node);
    $empty_field_collection = entity_property_values_create_entity('field_collection_item', $empty_field_collection_properties);
    $contract->set($empty_field_collection);
  }
  $agreements = $contract->field_contract_participant_agree;
  if(!$agreements->value()) {
    $empty_field_collections = array();
    $agreements->set($empty_field_collections);

    $role_ids = contract_get_role_ids($w_node->type);
    $empty_field_collection_properties = array('field_name' => 'field_contract_participant_agree', 'host_entity' => $contract);
    foreach($role_ids as $current_role_id) {
      $empty_field_collection = entity_property_values_create_entity('field_collection_item', $empty_field_collection_properties);
      $agreements[$current_role_id]->set($empty_field_collection);
    }
  }

EDIT: but we get an error if we try to set a field of that second level fieldcollection.

geek-merlin’s picture

Project: Entity API » Field collection
Issue summary: View changes

fixed code

geek-merlin’s picture

Title: Wrappers should autocreate ("EntityMetadataWrapperException - Parent data structure is not set") » Fieldcollection Wrappers should autocreate ("EntityMetadataWrapperException - Parent data structure is not set")
Component: Entity property wrapper » Code

Yep, this belongs to fieldcollection and seems related to #1227800: Ease programmatic manipulation of values within collections.

geek-merlin’s picture

Issue summary: View changes

error msg

geek-merlin’s picture

Issue summary: View changes

typo