diff --git a/entity.module b/entity.module index df59079..b3dbd80 100644 --- a/entity.module +++ b/entity.module @@ -114,6 +114,54 @@ 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) { + $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..171077d 100644 --- a/includes/entity.ui.inc +++ b/includes/entity.ui.inc @@ -30,7 +30,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 +61,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 +78,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 +86,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 +494,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 +659,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']))); }