You are here

entity_block.module in Entity Blocks 7

Display entities (via view modes) as fieldable blocks.

File

entity_block.module
View source
<?php

/**
 * @file
 * Display entities (via view modes) as fieldable blocks.
 */

/**
 * Implements hook_entity_info().
 */
function entity_block_entity_info() {
  return array(
    'entity_block' => array(
      'label' => t('Entity block'),
      'plural label' => t('Entity blocks'),
      'entity class' => 'EntityBlock',
      'controller class' => 'EntityBlockController',
      'module' => 'entity_block',
      'base table' => 'entity_block',
      'label callback' => 'entity_block_label',
      'fieldable' => TRUE,
      'entity keys' => array(
        'id' => 'entity_block_id',
        'bundle' => 'bundle',
      ),
      'bundle keys' => array(
        'bundle' => 'bundle',
      ),
      'bundles' => array(
        'entity_block' => array(
          'label' => 'Entity block',
          'admin' => array(
            'path' => 'admin/structure/entity-blocks/manage',
            'access arguments' => array(
              'administer entity blocks',
            ),
          ),
        ),
      ),
    ),
  );
}

/**
 * Implements hook_permission().
 */
function entity_block_permission() {
  return array(
    'administer entity blocks' => array(
      'title' => t('Administer entity blocks.'),
    ),
  );
}

/**
 * Implements hook_menu().
 */
function entity_block_menu() {
  $items = array();

  // Manage path.
  $items['admin/structure/entity-blocks'] = array(
    'title' => 'Entity blocks',
    'description' => t('Administer entity blocks.'),
    'page callback' => 'entity_block_list',
    'access arguments' => array(
      'adminiter entity blocks',
    ),
  );
  $items['admin/structure/entity-blocks/manage/list'] = array(
    'title' => 'List',
    'type' => MENU_DEFAULT_LOCAL_TASK,
  );

  // Add path.
  $items['admin/structure/entity-blocks/manage/add'] = array(
    'title' => 'Add entity block',
    'page callback' => 'entity_block_add',
    'access arguments' => array(
      'administer entity blocks',
    ),
    'type' => MENU_LOCAL_ACTION,
  );

  // Action link for themes.
  $default_theme = variable_get('theme_default', 'bartik');
  foreach (list_themes() as $key => $theme) {
    if ($key != $default_theme) {
      $items['admin/structure/block/list/' . $key . '/add-entity-block'] = array(
        'title' => 'Add entity block',
        'description' => 'Add a new entity block.',
        'page callback' => 'entity_block_add',
        'access arguments' => array(
          'administer entity blocks',
        ),
        'type' => MENU_LOCAL_ACTION,
      );
    }
  }

  // Edit path.
  $items['admin/structure/entity-blocks/%entity_block/edit'] = array(
    'title' => 'Edit',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'entity_block_form',
      3,
    ),
    'access arguments' => array(
      'administer entity blocks',
    ),
  );

  // Autocomplete path.
  $items['entityreference/autocomplete/entity_block/%/%'] = array(
    'title' => 'Entity Block Autocomplete',
    'page callback' => 'entity_block_autocomplete_callback',
    'page arguments' => array(
      3,
      4,
    ),
    'access arguments' => array(
      'administer entity blocks',
    ),
    'type' => MENU_CALLBACK,
  );
  return $items;
}

/**
 * Page callback for manage path.
 *
 * @return array
 */
function entity_block_list() {
  $content = array();
  $entities = entity_block_load_multiple();
  if (!empty($entities)) {
    foreach ($entities as $entity) {
      $wrapper = entity_metadata_wrapper('entity_block', $entity);
      $rows[] = array(
        'data' => array(
          'id' => $entity->entity_block_id,
          'title' => $entity->title,
          'target_entity_type' => $entity->target_entity_type,
          'target_bundle' => $entity->target_bundle,
          'target_view_mode' => $entity->target_view_mode,
          'target_entity_id' => $entity->target_entity_id,
          'edit' => l(t('Edit'), 'admin/structure/entity-blocks/' . $entity->entity_block_id . '/edit'),
        ),
      );
    }
    $content['entity_table'] = array(
      '#theme' => 'table',
      '#rows' => $rows,
      '#header' => array(
        t('ID'),
        t('Title'),
        t('Type'),
        t('Bundle'),
        t('View mode'),
        t('Entity'),
        t('Edit'),
      ),
    );
  }
  else {
    $content[] = array(
      '#type' => 'item',
      '#markup' => t('No entity blocks created.'),
    );
  }
  return $content;
}

/**
 * Page callback for adding an entity block.
 */
function entity_block_add() {
  $entity = entity_get_controller('entity_block')
    ->create();
  return drupal_get_form('entity_block_form', $entity);
}

/**
 * Callback for the autocompete path.
 *
 * We make use of entityreference_autocomplete_callback_get_matches from entityreference.module.
 *
 * @param $entity_type
 *  The entity type.
 * @param $bundle
 *  The bundle for the entity.
 * @param string $string
 *  The string to match
 * @return array
 */
function entity_block_autocomplete_callback($entity_type, $bundle, $string = '') {

  // Shift off the $entity_type and $bundle_name args.
  $args = func_get_args();
  array_shift($args);
  array_shift($args);
  $string = implode('/', $args);

  // Create a dummy field. Needed by entityreference to get a handler.
  $field = array(
    'field_name' => 'entity_block_target_entity_id',
    'type' => 'text',
    'settings' => array(
      'target_type' => $entity_type,
      'handler' => 'base',
      'handler_settings' => array(
        'target_bundles' => array(
          $bundle => $bundle,
        ),
      ),
    ),
  );

  // Create an instance of dummy field.
  $instance = array(
    'field_name' => 'entity_block_target_entity_id',
    'entity_type' => 'entity_block',
    'bundle' => 'entity_block',
    'widget' => array(
      'settings' => array(
        'match_operator' => 'CONTAINS',
        'size' => 60,
        'path' => '',
      ),
    ),
  );

  // Call entityreference_autocomplete_callback_get_matches from entityreference.module.
  return entityreference_autocomplete_callback_get_matches('single', $field, $instance, $entity_type, 'NULL', $string);
}

/**
 * Implements hook_block_info().
 */
function entity_block_block_info() {
  $info = array();

  // Create a block for each entity.
  $entities = entity_block_load_multiple();
  foreach ($entities as $entity) {
    $info[$entity->entity_block_id] = array(
      'info' => $entity->title,
    );
  }
  return $info;
}

/**
 * Implements hook_block_view().
 */
function entity_block_block_view($delta = '') {

  // Load the entity block and target entity.
  $entity_block = entity_block_load_single($delta);
  $target_entity = entity_load_single($entity_block->target_entity_type, $entity_block->target_entity_id);

  // Build the block array.
  $block = array();
  $block['subject'] = $entity_block->title;
  $block['content'] = entity_view($entity_block->target_entity_type, array(
    $target_entity,
  ), $entity_block->target_view_mode);
  return $block;
}

/**
 * Returns the form for adding an entity block.
 */
function entity_block_form($form, &$form_state, $entity) {

  // Get entity types.
  $entity_types = entity_block_get_entity_types();

  // Attach fields.
  field_attach_form('entity_block', $entity, $form, $form_state);

  // Save entity to form.
  $form['entity_block'] = array(
    '#type' => 'value',
    '#value' => $entity,
  );

  // Title field.
  $form['title'] = array(
    '#title' => t('Title'),
    '#type' => 'textfield',
    '#default_value' => $entity->title,
  );

  // Target entity type field.
  $entity_type_options = entity_block_get_entity_types_options();
  $target_entity_type = !empty($form_state['values']['target_entity_type']) ? $form_state['values']['target_entity_type'] : $entity->target_entity_type;
  $form['target_entity_type'] = array(
    '#title' => t('Entity type'),
    '#type' => 'select',
    '#options' => $entity_type_options,
    '#default_value' => !empty($entity->target_entity_type) ? $entity->target_entity_type : 'node',
    '#required' => TRUE,
    '#prefix' => '<div id="entity-block-target-entity-type">',
    '#suffix' => '</div>',
    '#ajax' => array(
      'callback' => 'entity_block_target_bundle_form_callback',
      'wrapper' => 'entity-block-target-bundle',
    ),
  );

  // Build bundle options.
  $bundles = array();
  foreach ($entity_types[$target_entity_type]['bundles'] as $bundle_name => $bundle_info) {
    $bundles[$bundle_name] = $bundle_info['label'];
  }

  // Default target bundle.
  $target_bundle = !empty($entity->target_bundle) ? $entity->target_bundle : key($bundles);

  // Target bundle field.
  $form['target_bundle'] = array(
    '#type' => 'select',
    '#title' => t('Bundle'),
    '#prefix' => '<div id="entity-block-target-bundle">',
    '#suffix' => '</div>',
    '#options' => $bundles,
    '#required' => TRUE,
    '#default_value' => $target_bundle,
    '#ajax' => array(
      'callback' => 'entity_block_target_entity_id_form_callback',
      'wrapper' => 'entity-block-target-entity-id',
    ),
  );

  // Target view mode.
  if (!empty($target_entity_type)) {

    // Build view mode options.
    $view_modes = array();
    $blacklisted_view_modes = entity_block_get_blacklisted_view_modes();
    foreach ($entity_types[$target_entity_type]['view modes'] as $view_mode_name => $view_mode_info) {
      if (!in_array($view_mode_name, $blacklisted_view_modes)) {
        $view_modes[$view_mode_name] = $view_mode_info['label'];
      }
    }

    // Default target view mode.
    $target_view_mode = !empty($entity->target_view_mode) ? $entity->target_view_mode : key($view_modes);
    $form['target_view_mode'] = array(
      '#type' => 'select',
      '#title' => t('View mode'),
      '#prefix' => '<div id="entity-block-target-view-mode">',
      '#suffix' => '</div>',
      '#options' => $view_modes,
      '#required' => TRUE,
      '#default_value' => $target_view_mode,
    );
    $autocomplete_path = 'entityreference/autocomplete/entity_block/' . $target_entity_type . '/' . $target_bundle;
    $target_entity = entity_load_single($entity->target_entity_type, $entity->target_entity_id);
    $form['target_entity_id'] = array(
      '#title' => 'Entity',
      '#type' => 'textfield',
      '#maxlength' => 1024,
      '#default_value' => '',
      '#prefix' => '<div id="entity-block-target-entity-id">',
      '#suffix' => '</div>',
      '#autocomplete_path' => $autocomplete_path,
      '#default_value' => $entity->target_entity_id,
      // @todo display the entity title using handler
      '#required' => TRUE,
      '#element_validate' => array(
        '_entityreference_autocomplete_validate',
      ),
    );
  }
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save'),
    '#weight' => 500,
  );
  return $form;
}

/**
 * AJAX callback to render the target_bundle, target_view_mode and target_entity_id fields.
 *
 * @return array
 *  A renderable array representing the target_bundle, target_view_mode and target_entity_id fields.
 */
function entity_block_target_bundle_form_callback($form, &$form_state) {
  return array(
    '#type' => 'ajax',
    '#commands' => array(
      ajax_command_replace("#entity-block-target-bundle", render($form['target_bundle'])),
      ajax_command_replace("#entity-block-target-view-mode", render($form['target_view_mode'])),
      ajax_command_replace("#entity-block-target-entity-id", render($form['target_entity_id'])),
    ),
  );
}

/**
 * AJAX callback to render the target_entity_id field.
 *
 * @return array
 *  A renderable array representing the target_entity_id field.
 */
function entity_block_target_entity_id_form_callback($form, $form_state) {
  return $form['target_entity_id'];
}

/**
 * Implements hook_field_extra_fields().
 */
function entity_block_field_extra_fields() {
  $form_elements['entity'] = array(
    'label' => t('Entity block'),
    'description' => t('The entity block element'),
    'weight' => -5,
  );
  $extra_fields['entity_block']['entity_block']['form'] = $form_elements;
  $extra_fields['entity_block']['entity_block']['display'] = $form_elements;
  return $extra_fields;
}

/**
 * Validation handler for entity_block_form form.
 */
function entity_block_form_validate($form, &$form_state) {
  field_attach_form_validate('entity_block', $form_state['values']['entity_block'], $form, $form_state);
}

/**
 * Submit handler for entity_block_form form.
 */
function entity_block_form_submit($form, &$form_state) {
  $entity_block = $form_state['values']['entity_block'];

  // Set values from form.
  $entity_block->title = $form_state['values']['title'];
  $entity_block->target_entity_type = $form_state['values']['target_entity_type'];
  $entity_block->target_bundle = $form_state['values']['target_bundle'];
  $entity_block->target_view_mode = $form_state['values']['target_view_mode'];
  $entity_block->target_entity_id = $form_state['values']['target_entity_id'];

  // Save fields.
  field_attach_submit('entity_block', $entity_block, $form, $form_state);

  // Save entity
  $entity_block = entity_block_save($entity_block);

  // Show a success message.
  $message = t('The entity block%titlehas been saved. !click to assign it to a region.', array(
    '%title' => !empty($entity_block->title) ? ' ' . $entity_block->title . ' ' : ' ',
    '!click' => l(t('Click here'), 'admin/structure/block/manage/entity_block/' . $entity_block->entity_block_id . '/configure'),
  ));
  drupal_set_message($message);
  $form_state['redirect'] = 'admin/structure/entity-blocks/manage';
}

/**
 * Saves an entity block.
 *
 * @param EntityBlock $entity.
 *   The full EntityBlock object to save.
 *
 * @return int
 *   SAVED_NEW or SAVED_UPDATED depending on the operation performed.
 */
function entity_block_save(&$entity) {
  return entity_get_controller('entity_block')
    ->save($entity);
}

/**
 * Deletes an entity block.
 *
 * @param EntityBlock $entity.
 *   The full EntityBlock object to delete.
 */
function entity_block_delete($entity) {
  entity_get_controller('entity_block')
    ->delete($entity);
}

/**
 * Loads an entity block.
 */
function entity_block_load_single($entity_id, $conditions = array()) {
  $entities = entity_get_controller('entity_block')
    ->load(array(
    $entity_id,
  ), $conditions);
  return array_shift($entities);
}

/**
 * Loads multiple entity blocks.
 *
 * @param $entity_block_ids.
 *   An array of entity_block_ids.
 *
 * @return EntityBlock[]
 *   An array of EntityBlock objects.
 */
function entity_block_load_multiple($entity_block_ids = FALSE, $conditions = array(), $reset = FALSE) {
  return entity_load('entity_block', $entity_block_ids, $conditions, $reset);
}

/**
 * Returns an #options ready array.
 *
 * @return array
 */
function entity_block_get_entity_types_options() {
  $entity_types = array();
  $entity_info = entity_block_get_entity_types();
  foreach ($entity_info as $entity_type => $info) {
    $entity_types[$entity_type] = $info['label'];
  }
  return $entity_types;
}

/**
 * Returns an array of entity types.
 *
 * @return array
 */
function entity_block_get_entity_types() {
  $entity_types = array();
  $entity_info = entity_get_info();
  $blacklisted_view_modes = entity_block_get_blacklisted_view_modes();
  foreach ($entity_info as $entity_type => $info) {

    // Filter out entity types with blacklisted-only view modes.
    if (count(array_diff(array_keys($info['view modes']), $blacklisted_view_modes))) {
      $entity_types[$entity_type] = $info;
    }
  }
  return $entity_types;
}

/**
 * Returns an array of blacklisted view modes.
 */
function entity_block_get_blacklisted_view_modes() {
  return array(
    'token',
    'queue',
    'rss',
  );
}

Functions

Namesort descending Description
entity_block_add Page callback for adding an entity block.
entity_block_autocomplete_callback Callback for the autocompete path.
entity_block_block_info Implements hook_block_info().
entity_block_block_view Implements hook_block_view().
entity_block_delete Deletes an entity block.
entity_block_entity_info Implements hook_entity_info().
entity_block_field_extra_fields Implements hook_field_extra_fields().
entity_block_form Returns the form for adding an entity block.
entity_block_form_submit Submit handler for entity_block_form form.
entity_block_form_validate Validation handler for entity_block_form form.
entity_block_get_blacklisted_view_modes Returns an array of blacklisted view modes.
entity_block_get_entity_types Returns an array of entity types.
entity_block_get_entity_types_options Returns an #options ready array.
entity_block_list Page callback for manage path.
entity_block_load_multiple Loads multiple entity blocks.
entity_block_load_single Loads an entity block.
entity_block_menu Implements hook_menu().
entity_block_permission Implements hook_permission().
entity_block_save Saves an entity block.
entity_block_target_bundle_form_callback AJAX callback to render the target_bundle, target_view_mode and target_entity_id fields.
entity_block_target_entity_id_form_callback AJAX callback to render the target_entity_id field.