diff --git a/entity.module b/entity.module index 30030b4..9fb90a2 100644 --- a/entity.module +++ b/entity.module @@ -114,6 +114,62 @@ function entity_object_load($entity_id, $entity_type) { } /** + * Page callback to show links to add an entity of a specific bundle. + * + * This shows links to all bundles, as we don't have access permissions at a + * bundle granularity. + * + * Entity modules that provide a further description to their bundles may wish + * to implement their own version of this to show these. + * + * @param $entity_type + * The type of the entity. + */ +function entity_ui_bundle_add_page($entity_type) { + // Set the title, as we're a MENU_LOCAL_ACTION and hence just get tab titles. + module_load_include('inc', 'entity', 'includes/entity.ui'); + drupal_set_title(entity_ui_get_action_title('add', $entity_type)); + + // Get entity info for our bundles. + $info = entity_get_info($entity_type); + $items = array(); + foreach ($info['bundles'] as $bundle_name => $bundle_info) { + // Create an empty entity with just the bundle set to check for access. + $dummy_entity = entity_create($entity_type, array( + 'bundle' => $bundle_name, + )); + // If modules use a uid, they can default to the current-user + // in their create() method on the storage controller. + if (entity_access('create', $entity_type, $dummy_entity, $account = NULL)) { + $add_path = $info['admin ui']['path'] . '/add/' . $bundle_name; + $items[] = l(t('Add @label', array('@label' => $bundle_info['label'])), $add_path); + } + } + return theme('item_list', array('items' => $items)); +} + +/** + * Page callback to add an entity of a specific bundle. + * + * @param $entity_type + * The type of the entity. + * @param $bundle_name + * The bundle machine name. + */ +function entity_ui_get_bundle_add_form($entity_type, $bundle_name) { + $info = entity_get_info($entity_type); + $bundle_key = $info['entity keys']['bundle']; + + // Make a stub entity of the right bundle to pass to the entity_ui_get_form(). + $values = array( + $bundle_key => $bundle_name, + ); + $entity = entity_create($entity_type, $values); + + return entity_ui_get_form($entity_type, $entity, 'add'); +} + +/** * A wrapper around entity_load() to load a single entity by name or numeric id. * * @todo: Re-name entity_load() to entity_load_multiple() in d8 core and this diff --git a/includes/entity.ui.inc b/includes/entity.ui.inc index a449b25..680001b 100644 --- a/includes/entity.ui.inc +++ b/includes/entity.ui.inc @@ -12,6 +12,7 @@ class EntityDefaultUIController { protected $entityType; protected $entityInfo, $path; + protected $id_count; /** * Defines the number of entries to show per page in overview table. @@ -30,7 +31,8 @@ class EntityDefaultUIController { */ public function hook_menu() { $items = array(); - $id_count = count(explode('/', $this->path)); + // Set this on the object so classes that extend hook_menu() can use it. + $this->id_count = count(explode('/', $this->path)); $wildcard = isset($this->entityInfo['admin ui']['menu wildcard']) ? $this->entityInfo['admin ui']['menu wildcard'] : '%entity_object'; $plural_label = isset($this->entityInfo['plural label']) ? $this->entityInfo['plural label'] : $this->entityInfo['label'] . 's'; @@ -60,12 +62,12 @@ class EntityDefaultUIController { $items[$this->path . '/manage/' . $wildcard] = array( 'title' => 'Edit', 'title callback' => 'entity_label', - 'title arguments' => array($this->entityType, $id_count + 1), + 'title arguments' => array($this->entityType, $this->id_count + 1), 'page callback' => 'entity_ui_get_form', - 'page arguments' => array($this->entityType, $id_count + 1), + 'page arguments' => array($this->entityType, $this->id_count + 1), 'load arguments' => array($this->entityType), 'access callback' => 'entity_access', - 'access arguments' => array('update', $this->entityType, $id_count + 1), + 'access arguments' => array('update', $this->entityType, $this->id_count + 1), ); $items[$this->path . '/manage/' . $wildcard . '/edit'] = array( 'title' => 'Edit', @@ -77,7 +79,7 @@ class EntityDefaultUIController { $items[$this->path . '/manage/' . $wildcard . '/clone'] = array( 'title' => 'Clone', 'page callback' => 'entity_ui_get_form', - 'page arguments' => array($this->entityType, $id_count + 1, 'clone'), + 'page arguments' => array($this->entityType, $this->id_count + 1, 'clone'), 'load arguments' => array($this->entityType), 'access callback' => 'entity_access', 'access arguments' => array('create', $this->entityType), @@ -85,10 +87,10 @@ class EntityDefaultUIController { // Menu item for operations like revert and delete. $items[$this->path . '/manage/' . $wildcard . '/%'] = array( 'page callback' => 'drupal_get_form', - 'page arguments' => array($this->entityType . '_operation_form', $this->entityType, $id_count + 1, $id_count + 2), + 'page arguments' => array($this->entityType . '_operation_form', $this->entityType, $this->id_count + 1, $this->id_count + 2), 'load arguments' => array($this->entityType), 'access callback' => 'entity_access', - 'access arguments' => array('delete', $this->entityType, $id_count + 1), + 'access arguments' => array('delete', $this->entityType, $this->id_count + 1), 'file' => 'includes/entity.ui.inc', ); @@ -493,6 +495,50 @@ class EntityDefaultUIController { } /** + * Controller for providing UI for entities with multiple bundles. + * + * Adds a bundle selection page to the entity/add path. + */ +class EntityBundlesUIController extends EntityDefaultUIController { + + /** + * Provides definitions for implementing hook_menu(). + */ + public function hook_menu() { + $items = parent::hook_menu(); + + // Extend the 'add' path. + $items[$this->path . '/add'] = array( + 'title callback' => 'entity_ui_get_action_title', + 'title arguments' => array('add', $this->entityType), + 'page callback' => 'entity_ui_bundle_add_page', + 'page arguments' => array($this->entityType), + 'access callback' => 'entity_access', + 'access arguments' => array('create', $this->entityType), + 'type' => MENU_LOCAL_ACTION, + ); + $items[$this->path . '/add/%'] = array( + 'title callback' => 'entity_ui_get_action_title', + 'title arguments' => array('add', $this->entityType, $this->id_count + 1), + 'page callback' => 'entity_ui_get_bundle_add_form', + 'page arguments' => array($this->entityType, $this->id_count + 1), + 'access callback' => 'entity_access', + 'access arguments' => array('create', $this->entityType), + ); + + if (!empty($this->entityInfo['admin ui']['file'])) { + // Add in the include file for the entity form. + foreach (array('/add', '/add/%') as $path_end) { + $items[$this->path . $path_end]['file'] = $this->entityInfo['admin ui']['file']; + $items[$this->path . $path_end]['file path'] = isset($this->entityInfo['admin ui']['file path']) ? $this->entityInfo['admin ui']['file path'] : drupal_get_path('module', $this->entityInfo['module']); + } + } + + return $items; + } +} + +/** * Form builder function for the overview form. * * @see EntityDefaultUIController::overviewForm() @@ -614,17 +660,37 @@ function entity_ui_get_page_title($op, $entity_type, $entity = NULL) { case 'export': return t('Export @label', array('@label' => $label)); } - return entity_ui_get_action_title($op, $entity_type); + if (isset($entity)) { + list(, , $bundle) = entity_extract_ids($entity_type, $entity); + } + return entity_ui_get_action_title($op, $entity_type, $bundle); } /** * Gets the page/menu title for local action operations. + * + * @param $op + * The current operation. One of 'add' or 'import'. + * @param $entity_type + * The entity type. + * @param $bundle_name + * (Optional) The name of the bundle. May be NULL if the bundle name is not + * relevant to the current page. If the entity type has only one bundle, or no + * bundles, this will be the same as the entity type. */ -function entity_ui_get_action_title($op, $entity_type) { +function entity_ui_get_action_title($op, $entity_type, $bundle_name = NULL) { $info = entity_get_info($entity_type); switch ($op) { case 'add': - return t('Add @entity_type', array('@entity_type' => drupal_strtolower($info['label']))); + if (isset($bundle_name) && $bundle_name != $entity_type) { + return t('Add @bundle_name @entity_type', array( + '@bundle_name' => drupal_strtolower($info['bundles'][$bundle_name]['label']), + '@entity_type' => drupal_strtolower($info['label']), + )); + } + else { + return t('Add @entity_type', array('@entity_type' => drupal_strtolower($info['label']))); + } case 'import': return t('Import @entity_type', array('@entity_type' => drupal_strtolower($info['label']))); }