You are here

bean.core.inc in Bean (for Drupal 7) 7

Bean classes and plugin interface

File

includes/bean.core.inc
View source
<?php

/**
 * @file
 * Bean classes and plugin interface
 */

/**
 * Interface for Plugin Classes
 */
interface BeanTypePluginInterface {

  /**
   * Constructor
   *
   * Plugin info should be called using bean_fetch_plugin_info().
   *
   * @abstract
   *
   * @param  $plugin_info array of information from the ctools plugin.
   */
  public function __construct($plugin_info);

  /**
   * Get the ctools plugin info.
   *
   * If you pass in a key, then the key from the plugin info will be returned
   * otherwise the entire plugin will be returned
   *
   * @abstract
   *
   * @param  $key
   * @return array of plugin info for value froma key
   */
  public function getInfo($key = NULL);

  /**
   * Build the URL string for the plugin
   *
   * @abstract
   *
   * @return url
   */
  public function buildURL();

  /**
   * Get the label name of the plugin
   *
   * @abstract
   *
   * @return label of the type
   */
  public function getLabel();

  /**
   * Get the description of the plugin
   *
   * @abstract
   *
   * @return
   *  description of the type
   */
  public function getDescription();

  /**
   * Set the Bean object for later use
   *
   * @abstract
   *
   * @param Bean $bean
   */
  public function setBean($bean);

  /**
   * Is this type editable?
   *
   * @abstract
   *
   * @return boolean
   */
  public function isEditable();

  /**
   * Define the form values and their defaults
   */
  public function values();

  /**
   * The Plugin Form
   *
   * The Bean object will be either loaded from the database or filled with the defaults.
   *
   * @param $bean
   * @param $form
   * @param $form_state
   * @return array
   *  form array
   */
  public function form($bean, $form, &$form_state);

  /**
   * Validate function for bean type form
   *
   * @abstract
   *
   * @param  $values
   * @param $form_state
   */
  public function validate($values, &$form_state);

  /**
   * React to a bean being saved
   *
   * @abstract
   *
   * @param Bean $bean
   */
  public function submit(Bean $bean);

  /**
   * Return the block content.
   *
   * @abstract
   *
   * @param        $bean
   *   The bean object being viewed.
   * @param        $content
   *   The default content array created by Entity API.  This will include any
   *   fields attached to the entity.
   * @param string $view_mode
   *   The view mode passed into $entity->view().
   *
   * @param null   $langcode
   *
   * @return
   *   Return a renderable content array.
   */
  public function view($bean, $content, $view_mode = 'default', $langcode = NULL);

}

/**
 * The Bean entity class
 */
class Bean extends Entity {
  public $label;
  public $description;
  public $title;
  public $type;
  public $data;
  public $delta;
  public $view_mode;
  public $bid;
  public $vid;
  public $created;
  public $changed;
  public $log;
  public $uid;
  public $default_revision;
  public $revisions = array();
  protected $plugin;

  /**
   * Get Plugin info
   *
   * @param $key
   *  The plugin key to get the info for.
   *
   * @return array|null
   */
  public function getInfo($key = NULL) {
    if ($this->plugin instanceof BeanTypePluginInterface) {
      return $this->plugin
        ->getInfo($key);
    }
    return NULL;
  }
  public function __construct(array $values = array()) {

    // If this is new then set the type first.
    if (isset($values['is_new'])) {
      $this->type = isset($values['type']) ? $values['type'] : '';
    }
    parent::__construct($values, 'bean');
  }
  public function adminTitle() {
    return filter_xss_admin($this->label);
  }
  protected function setUp() {
    parent::setUp();
    if (!empty($this->type)) {
      $plugin = bean_load_plugin_class($this->type);
      $this
        ->loadUp($plugin);
    }
    return $this;
  }

  /**
   * This is a work around for version of PDO that call __construct() before
   * it loads up the object with values from the DB.
   */
  public function loadUp($plugin) {
    if (empty($this->plugin)) {

      // If the plugin has been disabled, the $plugin will be a boolean.
      // just load the base plugin so something will render.
      if (!$plugin instanceof BeanTypePluginInterface) {
        $plugin = bean_load_plugin_class('bean_default');
      }
      $this
        ->setPlugin($plugin)
        ->setFields();
    }
    return $this;
  }

  /**
   * Load and set the plugin info.
   * This can be called externally via loadUP()
   */
  protected function setPlugin($plugin) {
    $this->plugin = $plugin;
    return $this;
  }

  /**
   * Set the fields from the defaults and plugin
   * This can be called externally via loadUP()
   */
  protected function setFields() {

    // NOTE: When setFields is called externally $this->data is already unserialized.
    if (!empty($this->plugin) && !empty($this->type)) {
      $values = is_array($this->data) ? $this->data : unserialize($this->data);
      foreach ($this->plugin
        ->values() as $field => $default) {
        $this->{$field} = isset($values[$field]) ? $values[$field] : $default;
      }
    }
    return $this;
  }

  /**
   * Override this in order to implement a custom default URI and specify
   * 'entity_class_uri' as 'uri callback' hook_entity_info().
   */
  protected function defaultUri() {
    return array(
      'path' => 'block/' . strtolower($this
        ->identifier()),
    );
  }

  /**
   * Get the default label
   *
   * @return string
   */
  protected function defaultLabel() {
    if (empty($this->title)) {
      return $this->label;
    }
    return $this->title;
  }

  /**
   * Set the revision as default
   *
   * @return Bean
   */
  public function setDefault() {
    $this->default_revision = TRUE;
    return $this;
  }

  /**
   * Get the plugin form
   */
  public function getForm($form, &$form_state) {
    return $this->plugin
      ->form($this, $form, $form_state);
  }

  /**
   * Validate the plugin form
   */
  public function validate($values, &$form_state) {
    $this->plugin
      ->validate($values, $form_state);
  }

  /**
   * URL string
   */
  public function url() {
    $uri = $this
      ->defaultUri();
    return $uri['path'];
  }

  /**
   * Build the URL string
   */
  protected function buildURL($type) {
    $url = $this
      ->url();
    return $url . '/' . $type;
  }

  /**
   * View URL
   */
  public function viewURL() {
    return $this
      ->buildURL('view');
  }

  /**
   * View URL
   */
  public function editURL() {
    return $this
      ->buildURL('edit');
  }

  /**
   * View URL
   */
  public function deleteURL() {
    return $this
      ->buildURL('delete');
  }

  /**
   * Type name
   */
  public function typeName() {
    return $this
      ->getInfo('label');
  }

  /**
   * Set the values from a plugin
   */
  public function setValues($values) {
    $this->data = array();
    foreach ($this->plugin
      ->values() as $field => $value) {
      $this->data[$field] = $values[$field];
    }
    return $this;
  }

  /**
   * Generate an array for rendering the entity.
   *
   * @see entity_view()
   */
  public function view($view_mode = 'default', $langcode = NULL, $page = NULL) {
    $content = parent::view($view_mode, $langcode);
    if (empty($this->plugin)) {
      return $content;
    }
    return $this->plugin
      ->view($this, $content, $view_mode, $langcode);
  }

  /**
   * Override the save to add clearing of caches
   */
  public function save() {
    $this
      ->setUid()
      ->checkDelta();
    if (empty($this->created)) {
      $this->created = REQUEST_TIME;
    }
    $this->changed = REQUEST_TIME;
    $this->plugin
      ->submit($this);
    $return = parent::save();
    bean_reset(TRUE, TRUE);
    if (module_exists('block')) {
      bean_cache_clear_block($this);
    }
    return $return;
  }

  /**
   * Get the user
   */
  protected function setUid() {
    global $user;
    $this->uid = empty($this->uid) ? $user->uid : $this->uid;
    return $this;
  }

  /**
   * Set the delta function
   */
  protected function checkDelta() {
    if (empty($this->delta)) {
      $max_length = 32;

      // Base it on the label and make sure it isn't too long for the database.
      if (module_exists('transliteration')) {
        $delta = drupal_clean_css_identifier(strtolower(transliteration_get($this->label)));
      }
      else {
        $delta = drupal_clean_css_identifier(strtolower($this->label));
      }

      // Add 'bean-' prefix when it's need to avoid a purely numeric delta.
      if (is_numeric($delta)) {
        $delta = 'bean-' . $delta;
      }
      $this->delta = substr($delta, 0, $max_length);

      // Check if delta is unique.
      if ($this
        ->deltaExists($this->delta)) {
        $i = 0;
        $separator = '-';
        $original_delta = $this->delta;
        do {
          $unique_suffix = $separator . $i++;
          $this->delta = substr($original_delta, 0, $max_length - drupal_strlen($unique_suffix)) . $unique_suffix;
        } while ($this
          ->deltaExists($this->delta));
      }
    }
    return $this;
  }

  /**
   * Check against the Database if a specific delta exists.
   */
  protected function deltaExists($delta) {
    return db_select('bean', 'b')
      ->fields('b', array(
      'bid',
    ))
      ->condition('delta', $delta)
      ->execute()
      ->fetchField();
  }

  /**
   * Load the revisions from the DB
   */
  public function loadRevisions() {
    $this->revisions = db_select('bean_revision', 'br')
      ->condition('delta', $this
      ->identifier())
      ->fields('br')
      ->execute();
    return $this;
  }

}
class BeanEntityAPIController extends EntityAPIControllerExportable {
  protected function setPlugin(Bean $bean) {
    static $plugins = array();
    if (empty($plugins[$bean->type])) {
      $plugins[$bean->type] = bean_load_plugin_class($bean->type);
      $bean
        ->loadUp($plugins[$bean->type]);
    }
  }
  protected function attachLoad(&$queried_entities, $revision_id = FALSE) {
    foreach ($queried_entities as $entity) {
      $this
        ->setPlugin($entity);
    }
    parent::attachLoad($queried_entities, $revision_id);
  }
  public function delete($ids, DatabaseTransaction $transaction = NULL) {
    $beans = $ids ? $this
      ->load($ids) : array();
    $deltas = array();
    foreach ($beans as $bean) {
      if ($bean
        ->internalIdentifier()) {
        field_attach_delete('bean', $bean);
        $deltas[] = $bean
          ->identifier();
      }
    }
    if (!empty($deltas)) {
      try {

        // @see block_custom_block_delete_submit()
        if (module_exists('block')) {
          db_delete('block')
            ->condition('module', 'bean')
            ->condition('delta', $deltas)
            ->execute();
          db_delete('block_role')
            ->condition('module', 'bean')
            ->condition('delta', $deltas)
            ->execute();

          // @see node_form_block_custom_block_delete_submit()
          db_delete('block_node_type')
            ->condition('module', 'bean')
            ->condition('delta', $deltas)
            ->execute();
        }
      } catch (Exception $e) {
        if (isset($transaction)) {
          $transaction
            ->rollback();
        }
        watchdog_exception('bean', $e);
        throw $e;
      }
    }
    parent::delete($ids, $transaction);
  }

  /**
   * Overridden to add Rules integration back in.
   */
  public function invoke($hook, $entity) {
    parent::invoke($hook, $entity);

    // Invoke rules.
    if (module_exists('rules')) {
      rules_invoke_event($this->entityType . '_' . $hook, $entity);
    }
  }
  protected function saveRevision($entity) {
    global $user;
    $org_uid = $entity->uid;
    $entity->uid = $user->uid;
    $return = parent::saveRevision($entity);
    $entity->uid = $org_uid;
    return $return;
  }

}
class BeanException extends Exception {

}

Classes

Namesort descending Description
Bean The Bean entity class
BeanEntityAPIController
BeanException

Interfaces

Namesort descending Description
BeanTypePluginInterface Interface for Plugin Classes