You are here

eck.module in Entity Construction Kit (ECK) 7

Same filename and directory in other branches
  1. 8 eck.module
  2. 7.3 eck.module
  3. 7.2 eck.module

ENTITY CONSTRUCTION KIT

This module is a fairly simple module. It exposes an administration section for creating entity types, bundles and entities. This module also keeps track in the database of the entities that have been created with eck (eck db table), and the different bundles that have been creates (eck_type db table).

If you want to follow the flow of this modules functionality I suggest starting with the hook menu, where all of the paths for the administration section are defined.

File

eck.module
View source
<?php

/**
 * @file
 *
 * ENTITY CONSTRUCTION KIT
 *
 * This module is a fairly simple module. It exposes an administration section
 * for creating entity types, bundles and entities. This module also keeps track
 * in the database of the entities that have been created with eck (eck db
 * table), and the different bundles that have been creates (eck_type db table).
 *
 * If you want to follow the flow of this modules functionality I suggest
 * starting with the hook menu, where all of the paths for the administration
 * section are defined.
 */

/**
 * Implements hook_features_api().
 */
function eck_features_api() {
  return array(
    'eck_entity_type' => array(
      'name' => t('Entity Types'),
      'feature_source' => TRUE,
      'default_hook' => 'eck_entity_type_info',
    ),
  );
}

/**
 * Implements hook_entity_info().
 *
 * The Entity information for all the entity types created with eck.
 */
function eck_entity_info() {
  module_load_include('inc', 'eck', 'eck.entity_type');
  $info = array();

  // Get all the names of all the entity types from the eck table
  // for each of the created entity types add its info to the $info array.
  foreach (eck__entity_type__load() as $entity_type) {

    // eck__entity_info creates the entity_info for each entity type.
    $info = array_merge($info, eck__entity_type__info($entity_type));
  }
  return $info;
}

/**
 * Implements hook_entity_property_info_alter().
 */
function eck_entity_property_info_alter(&$info) {
  module_load_include('inc', 'eck', 'eck.entity_type');

  // Create property infos for all defined entites.
  foreach (eck__entity_type__load() as $entity_type_object) {
    eck__entity_type__property_info($info[$entity_type_object->name], $entity_type_object);
  }
}

/**
 * Implements hook_menu().
 *
 * Define the paths for the administration section of the Entity Factory
 * The  menues get created in three functions
 * eck__entity_type__mene()
 * eck__bundle__menu()
 * eck__entity__menu()
 * This approach made sense thanks to the recursive nature of the menu itmes
 * that need to be created
 */
function eck_menu() {
  module_load_include('inc', 'eck', 'eck.entity_type');
  $menu = eck__entity_type__menu();
  return $menu;
}

/**
 * Implements hook_permission().
 *
 * A pretty through set of permission
 * you can set permissiona at each level: entity_type, bundle, entity
 * and for each action of the CRUD
 */
function eck_permission() {
  module_load_include('inc', 'eck', 'eck.entity_type');
  module_load_include('inc', 'eck', 'eck.bundle');
  $perms = array();
  $perms['administer entity types'] = array(
    'title' => t('Administer Entity Types'),
    'restrict access' => TRUE,
  );
  $perms['add entity types'] = array(
    'title' => t('Add Entity Types'),
    'restrict access' => TRUE,
  );
  foreach (eck__entity_type__load() as $entity_type) {
    foreach (array(
      'administer' => 'Administer',
      'add' => "Add",
    ) as $op => $op_label) {
      $perms["{$op} {$entity_type->name} bundles"] = array(
        'title' => "{$op_label} {$entity_type->label} Bundles",
      );
    }
    foreach (eck__bundle__load($entity_type->name) as $bundle) {
      foreach (array(
        'administer' => 'Administer',
        'add' => "Add",
        'view' => 'View',
        'edit' => 'Edit',
        'delete' => 'Delete',
      ) as $op => $op_label) {
        $perms["{$op} {$entity_type->name} {$bundle->name} entities"] = array(
          'title' => "{$op_label} {$entity_type->label} {$bundle->label} Entities",
        );
      }
    }
  }
  return $perms;
}

/**
 * This function creates an entity
 * @param $entity_type_name
 *  A string witht the type of entity to be created (node, user, etc)
 * @param $bundle_name
 *  The bundle for the entity to be created (String)
 */
function eck__entity_create($entity_type_name, $bundle_name) {
  global $user;
  $values = array(
    'entity_type' => $entity_type_name,
    'type' => $bundle_name,
    'uid' => $user->uid,
    'created' => REQUEST_TIME,
    'changed' => REQUEST_TIME,
  );
  return entity_create($entity_type_name, $values);
}
function eck_forms($form_id, $args) {
  $forms = array();
  if (strpos($form_id, 'entity_table_select_') === 0) {
    $forms[$form_id] = array(
      'callback' => 'entity_table_select',
    );
  }
  return $forms;
}

/**
 * Creates a table showing a group of entities.
 *
 * @param $entities
 *  the entities to create the table from
 * @param $select
 *  a boolean value that will determine whether the
 *  table is a select table or a regular table
 */
function entity_table($entities, $select = FALSE) {
  module_load_include('inc', 'eck', 'eck.entity');

  //This is information set up for each bundle in the hook_entity_info

  //look there for more details
  $crud_info = NULL;
  $rows = array();
  $header = array(
    t('Name'),
    array(
      'data' => t('Operations'),
      'colspan' => '1',
    ),
  );
  $info = NULL;
  foreach ($entities as $entity) {
    $info = array();
    $entity_type = $entity
      ->entityType();
    $bundle = $entity->type;
    $id = $entity->id;
    if ($crud_info == NULL) {
      $crud_info = get_bundle_crud_info($entity_type, $bundle);
    }
    $edit_path = str_replace('%', $id, $crud_info['edit']['path']);
    $delete_path = str_replace('%', $id, $crud_info['delete']['path']);
    $uri = entity_uri($entity_type, $entity);
    $row = array(
      l(entity_label($entity_type, $entity), $uri['path'], $uri['options']),
    );
    $row[] = array(
      'data' => l(t('edit'), $edit_path) . "<br>" . l(t('delete'), $delete_path),
    );

    //"admin/structure/eck/{$entity_type}/{$bundle}/{$id}/delete"));
    $info['entity'] = $entity;
    drupal_alter("entity_{$entity_type}_{$bundle}_tr", $row, $info);
    $info['bundle'] = $bundle;
    drupal_alter("entity_{$entity_type}_tr", $row, $info);
    $info['entity_type'] = $entity_type;
    drupal_alter("entity_tr", $row, $info);
    $rows[$id] = $row;
  }
  if ($info) {
    unset($info['entity']);
    drupal_alter("entity_th", $header, $info);
    unset($info['entity_type']);
    drupal_alter("entity_{$entity_type}_th", $header, $info);
    unset($info['bundle']);
    drupal_alter("entity_{$entity_type}_{$bundle}_th", $header, $info);
  }
  if ($select) {
    if (!isset($entity_type)) {
      return array(
        '#theme' => 'table',
        '#header' => $header,
        '#rows' => $rows,
      );
    }
    else {
      return drupal_get_form("entity_table_select_{$entity_type}_{$bundle}", $entity_type, $bundle, $header, $rows);
    }
  }
  else {
    return array(
      '#theme' => 'table',
      '#header' => $header,
      '#rows' => $rows,
    );
  }
}

/**
 * Helper function for the entities_table.
 * This function creates a select table.
 *
 * @param $form
 *  A form arrary as returned by drupal_get_form
 * @param $state
 *  The form state, this is also provided by the Form API
 * @param $enttiy_type
 *  (String) the type of the entities that will be in the table
 * @param $bundle
 *  (String) The bundle of the entity that will be in the table
 * @param $header
 *  An array for the table header for more info look at theme_table
 * @param $rows
 *  The rows of the table for more info on what this should look like look
 *  at theme_table
 */
function entity_table_select($form, &$state, $entity_type, $bundle, $header, $rows) {
  $form['entity_type'] = array(
    '#type' => 'value',
    '#value' => $entity_type,
  );
  $form['bundle'] = array(
    '#type' => 'value',
    '#value' => $bundle,
  );
  $form['entity_table'] = array(
    // '#theme' => 'table',
    '#type' => 'tableselect',
    '#header' => $header,
    '#options' => $rows,
  );
  return $form;
}

/**
 * When an entity form is submitted, field for which no information  was inputed
 * are still returned, then if we submit that data, empty rows are created in
 * those field databases cluttering them. This function checks and makes sure
 * that the data returned for a field is not empty and unsets it if it is, so no
 * empty data will be added to the database.
 *
 * @param $field_name
 *   The name of the field.
 * @param $data
 *   The data for the field: It usually has this format
 *   array(lang => array( 0 => array( <field stuff> ), 1 => ...));
 */
function _field_unset_empty($field_name, $data) {

  // If there is a value we need to check that it is not empty.
  $info = field_info_field($field_name);
  foreach ($data[LANGUAGE_NONE] as $key => $values) {
    $empty = TRUE;
    foreach (array_keys($info['columns']) as $index) {
      if (!empty($values[$index])) {
        $empty = FALSE;
      }
    }
    if ($empty) {
      unset($data[LANGUAGE_NONE][$key]);
    }
  }
  return $data;
}

/**
 * As you can see this is just use to comply with requirements
 * probably no one will use this
 */
function _eck_fake_exists() {
  return FALSE;
}

/**
 * Generates an upper camel case class name from a machine name.
 *
 * @params $name
 *   The machine name to convert to camel case.
 * @params $suffix
 *   Optional class name suffix.
 */
function eck_get_class_name($name, $suffix = '') {
  $parts = array_map('ucfirst', explode('_', $name));
  if ($suffix) {
    $parts[] = $suffix;
  }
  return implode('', $parts);
}
function eck_get_parent_classes($class_name) {
  $classes = array(
    $class_name,
  );
  while (($class_name = get_parent_class($class_name)) !== false) {
    $classes[] = $class_name;
  }
  return $classes;
}

/**
 * Retrieve the entity label
 * 
 * @todo Where am I using this??
 */
function eck_get_entity_label($entity_type, $entity_id) {
  if (!is_numeric($entity_id)) {
    return FALSE;
  }
  $entity = entity_load($entity_type, array(
    $entity_id,
  ));
  $entity = $entity[$entity_id];
  if (is_object($entity) && !empty($entity)) {
    return entity_label($entity_type, $entity);
  }
  else {
    return NULL;
  }
}

/**
 * Base controller class for ECK entites.
 */
class EckController extends EntityAPIController {
  public function create(array $values = array()) {
    global $user;

    // Set default values.
    $values += array(
      'type' => $this->entityType,
      'uid' => $user->uid,
      'created' => REQUEST_TIME,
      'changed' => REQUEST_TIME,
    );

    // Allow to create custom per-bundle specific class implementations.
    $class_name = eck_get_class_name($values['type'], 'EntityType');
    if (drupal_autoload_class($class_name)) {
      $this->entityInfo['entity class'] = $class_name;
    }
    return parent::create($values);
  }
  public function query($ids, $conditions, $revision_id = FALSE) {
    $result = parent::query($ids, $conditions, $revision_id);
    if (!empty($this->entityInfo['entity class']) && $result
      ->rowCount()) {
      $row = $result
        ->fetch(PDO::FETCH_ASSOC);

      // Allow to create custom per-bundle specific class implementations.
      $class_name = eck_get_class_name($row['type'], 'EntityType');
      if (drupal_autoload_class($class_name)) {
        $this->entityInfo['entity class'] = $class_name;
      }
      $result = parent::query($ids, $conditions, $revision_id);
    }
    return $result;
  }

}

/**
 * Base class for ECK entites.
 */
class EckEntity extends Entity {
  public $id;
  public $uid;
  public $changed;
  public $created;
  public $type;
  public function save() {

    // Update changed timestamp
    $this->changed = REQUEST_TIME;
    return parent::save();
  }

}

/**
 * This is the callback function for an entities label
 * By default the label is the id of the entity, but a number of
 * hooks are defined to customize the label if needed
 *
 * @param $entity
 *  an object as returned by entity_load()
 */
function eck__entity__label($entity) {
  $hook_names = array(
    "entity_label",
    "entity_{$entity->entityType()}_label",
    "entity_{$entity->entityType()}_{$entity->type}_label",
  );
  foreach ($hook_names as $hook_name) {
    $new_label = module_invoke_all($hook_name, $entity, $entity->id);
    $empty = empty($new_label);
    if (!$empty) {
      break;
    }
  }
  if (!$empty) {
    return $new_label[0];
  }
  else {
    return $entity->id;
  }
}

/**
 * Entity URI callback
 *
 * @param $entity
 *  an object as returned by entity_load()
 */
function eck__entity__uri($entity) {
  module_load_include('inc', 'eck', 'eck.entity');
  $crud_info = get_bundle_crud_info($entity
    ->entityType(), $entity->type);
  $view_path = str_replace('%', $entity
    ->identifier(), $crud_info['view']['path']);
  return array(
    'path' => $view_path,
  );
}

Functions

Namesort descending Description
eck_entity_info Implements hook_entity_info().
eck_entity_property_info_alter Implements hook_entity_property_info_alter().
eck_features_api Implements hook_features_api().
eck_forms
eck_get_class_name Generates an upper camel case class name from a machine name.
eck_get_entity_label Retrieve the entity label
eck_get_parent_classes
eck_menu Implements hook_menu().
eck_permission Implements hook_permission().
eck__entity_create This function creates an entity
eck__entity__label This is the callback function for an entities label By default the label is the id of the entity, but a number of hooks are defined to customize the label if needed
eck__entity__uri Entity URI callback
entity_table Creates a table showing a group of entities.
entity_table_select Helper function for the entities_table. This function creates a select table.
_eck_fake_exists As you can see this is just use to comply with requirements probably no one will use this
_field_unset_empty When an entity form is submitted, field for which no information was inputed are still returned, then if we submit that data, empty rows are created in those field databases cluttering them. This function checks and makes sure that the data returned…

Classes

Namesort descending Description
EckController Base controller class for ECK entites.
EckEntity Base class for ECK entites.