I explain my situation :
I have two entity types : 'tribe_type' and 'tribe'. It must work like 'node_type' and 'node'.
So I have declared two entity types in hook_entity_info in this way :

function mymodule_entity_info() {
  $items['tribe_type'] = array(
    'label' => t('Tribe type'),
    'controller class' => 'EntityAPIController', //base class
    'entity class' => 'TribeType', //this type is declared
    'base table' => 'tribe_type', //this table is declared
    'fieldable' => TRUE,
    'entity keys' => array(
      'id' => 'id',
      'label' => 'description',
      'name' => 'name',
    ),
    'exportable' => FALSE,
    'bundle of' => 'tribe',
    'module' => 'mymodule',
    'access callback' => 'tribe_type_access',
    // Enable the entity API's admin UI.
    'admin ui' => array(
      'path' => 'admin/structure/tribe-types',
      'file' => 'mymodule.admin.inc',
      'controller class' => 'TribeTypeUIController',
      'file path' => drupal_get_path('module','mymodule'),
    ),
  );
  $items['tribe'] = array(
    'label' => t('Tribe'),
    'controller class' => 'EntityAPIController',
    'entity class' => 'Tribe', //this type is declared
    'base table' => 'tribe', //this table is declared
    'fieldable' => TRUE,
    'access callback' => 'tribe_access',
    'uri callback' => 'tribe_uri',
    'entity keys' => array(
      'id' => 'jtid',
      'label' => 'label',
      'bundle' => 'type',
      'name' => 'name',
    ),
    'bundles' => array(),
    'bundle keys' => array(
      'bundle' => 'type',
    ),
    // Enable the entity API's admin UI.
    'admin ui' => array(
      'path' => 'tribe',
      'file' => 'mymodule.tribe.admin.inc',
      'file path' => drupal_get_path('module','mymodule'),
    ),
    'module' => 'mymodule',
  );
  return $items;
}

I fill the 'bundles' key for 'tribe' entity in hook_entity_info_alter.
I've declared tribe_load(), etc... and all necessary function.

The admin admin UI for tribe_type works well, exactly like node_type.
But for the admin UI for tribe, it doesn't work, and it seems it's the fields which are not attached (for 'create' op, the others I haven't tested yet).

The error is :
Fatal error: Cannot access empty property in D:\wamp\www\drupal7\modules\field\field.attach.inc on line 198

So I wonder if it's my prog which is wrong, or if it's a bug. But I have try in many ways, and always entity_load doesn't load fields for bundled entity types...

Comments

fago’s picture

Category: bug » support

I'd say you miss information about your bundles, which is usually added in via hook_entity_info_alter(). E.g. compare your code to the one of profile2 or messages which works.

I never tested the UI for an entity type which itself has bundle entities, however I don't think there should be a problem that.

nicodh’s picture

In mymodule_entity_info_alter, I put this :

function mymodule_entity_info_alter(&$entity_info) {
  $tribe_types = entity_load('tribe_type');
  foreach ($tribe_types as $type_name => $type) {
    $entity_info['tribe']['bundles'][$type_name] = array(
      'label' => $type->name,
      'admin' => array(
        'path' => 'admin/structure/tribe-types/manage/%tribe_type',
        'real path' => 'admin/structure/tribe-types/manage/' . str_replace('_', '-', $type->name),
        'bundle argument' => 4,
        'access arguments' => array('administer tribe types'),
      ),
    );
  }
}

But when I try to acces to 'tribe/add' (the path defined in mymodule_entity_info at 'admin ui'), there is a fatal error :

Fatal error: Cannot access empty property in /.../www/modules/field/field.attach.inc on line 198

And in field.attach.inc, I think it's fields attachements which doesn't work correctly. I look in this file, and I ask, in my tribe_form (the form for editing/adding), how $entity (or $tribe in my case) is initialized ?
Because it seems that in field.attach.inc, field_attach_form try to access to a property of $tribe object for each field associated. So entity.module make this or it's to me to create an empty property for each field for adding a 'tribe' entity ?
It's my tribe_form code :

function tribe_form($form, &$form_state, $tribe, $op = 'edit') {
  global $user;
  if ($op == 'clone') {
    $tribe->label .= ' (cloned)';
    $tribe->name .= '_clone';
  }
  if ($op == 'add') {
    $tribe->created = time();
    $tribe->updated = time();
    $tribe->uid = $user->uid;
		if($tribe->type == '')
		$tribe_type = arg(2);	
  }
  if ($op == 'edit') {
    $tribe->updated = time();
  }

  if($op == 'add' || $op == 'create') {
    $form['label'] = array(
      '#title' => t('Description'),
      '#type' => 'textfield',
      '#default_value' => $tribe->label,
      '#description' => t('The human-readable name of this tribe.'),
      '#required' => TRUE,
    );
    // Machine-readable type name.
    $form['name'] = array(
      '#type' => 'machine_name',
      '#default_value' => isset($tribe->name) ? $tribe->name : '',
      '#disabled' => entity_has_status('tribe', $tribe, ENTITY_IN_CODE),
      '#machine_name' => array(
        'exists' => 'tribe_load',
        'source' => array('label'),
      ),
      '#description' => t('A unique machine-readable name for this tribe. It must only contain lowercase letters, numbers, and underscores.'),
    );
  }
  else {
    $form['description'] = array(
      '#title' => t('Description'),
      '#type' => 'item',
      '#markup' => 'Nom : "'.$tribe->label.'" ('.$tribe->name.')',
    );
    $form['label'] = array(
      '#type' => 'hidden',
      '#default_value' => $tribe->label,
    );
    // Machine-readable type name.
    $form['name'] = array(
      '#type' => 'hidden',
      '#default_value' => $tribe->name,
    );
  }
  // values.
  $form['created'] = array(
    '#type' => 'hidden',
    '#default_value' => isset($tribe->created) ? $tribe->created : time(),
  );
  $form['updated'] = array(
    '#type' => 'hidden',
    '#default_value' => isset($tribe->updated) ? $tribe->updated : time(),
  );
  $form['type'] = array(
    '#type' => 'hidden',
    '#default_value' => isset($tribe->type) ? $tribe->type : '',
  );
  $form['uid'] = array(
    '#type' => 'hidden',
    '#default_value' => isset($tribe->uid) ? $tribe->uid : 0,
  );

  field_attach_form('tribe', $tribe, $form, $form_state);

  $form['actions'] = array('#type' => 'actions');
  $form['actions']['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save tribe'),
    '#weight' => 40,
  );

  if (!entity_has_status('tribe', $tribe, ENTITY_IN_CODE) && $op != 'add') {
    $form['actions']['delete'] = array(
      '#type' => 'submit',
      '#value' => t('Delete tribe'),
      '#weight' => 45,
      '#limit_validation_errors' => array(),
      '#submit' => array('tribe_form_submit_delete')
    );
  }
  return $form;
}

And I've changed the fieldable property of 'tribe_type' entity to FALSE, and it works.

And I have a second question : the error happens when I try to access 'tribe/add', or because 'tribe' entity type has bundles, so doesn't 'tribe/add' is a path for displaying different bundles (like 'node/add' displays different node-types), for me the tribe-type entities ?

Sorry for english once again, it's difficult to explain this more or less complex problem...

nicodh’s picture

Status: Active » Needs work

It's ok, the UI seems to work in fact, just the 'tribe/add' page doesn't work, it will be useful if this page load links for different bundles.
So the error for bundled entity type is for adding, the path '/add' try to load the edit form, but the bundle field is not set so the error is triggered.

nicodh’s picture

I've discover another bug I think, the path returned by 'uri callback', so for my 'tribe' entity type, 'tribe_uri()', is well-set in the page '/tribe' (for the links for each tribe), but when I access this path, the page isn't found.
So there is a problem for uri callback.

garphy’s picture

StatusFileSize
new1.09 KB

Follow up to @rkcreation's post (#3) :

Here's a quick patch that remplace the 'add' form with a list of possible bundles if the entity type has several bundles.
Each link adds a ?type= to the 'add' form URL and then inject the correct type at entity creation time.
I'm pretty sure the 'type' hardcoded key is invalid and should be extracted from entity metadata but that's a WIP.

joachim’s picture

I've filed a duplicate of this at #1619628: Entity UI '/add' page doesn't provide for an entity with bundles -- oops.

I've filed a patch there too -- somewhat more complex, as it adds menu items for BASEPATH/add/type, with the type converted to use hyphens in the URL and so on.

bojanz’s picture

Issue summary: View changes
Status: Needs work » Closed (duplicate)

The issue referenced in #6 got committed and is a part of the 1.2 release.