entity.info.inc 5.97 KB
Newer Older
1 2 3 4
<?php

/**
 * @file
5 6 7
 * Provides basic entity property info for entities provided via the CRUD API,
 * as well as property info for all entity types defined by core. For that
 * the respective modules/MODULE.info.inc files are included.
8 9 10
 */

/**
11 12 13 14 15 16
 * Implements hook_entity_property_info().
 */
function entity_entity_property_info() {
  $items = array();
  // Add in info about entities provided by the CRUD API.
  foreach (entity_crud_get_info() as $type => $info) {
17 18 19 20 21
    // Automatically enable the controller only if the module does not implement
    // the hook itself.
    if (!isset($info['metadata controller class']) && (!isset($info['module']) || !module_hook($info['module'], 'entity_property_info'))) {
      $info['metadata controller class'] = 'EntityDefaultMetadataController';
    }
22
    if (!empty($info['metadata controller class'])) {
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
      $controller = new $info['metadata controller class']($type);
      $items += $controller->entityPropertyInfo();
    }
  }
  // Add in info for all core entities.
  foreach (_entity_metadata_core_modules() as $module) {
    module_load_include('inc', 'entity', "modules/$module.info");
    if (function_exists($function = "entity_metadata_{$module}_entity_property_info")) {
      if ($return = $function()) {
        $items = array_merge_recursive($items, $return);
      }
    }
  }
  return $items;
}

/**
 * Implements hook_entity_property_info_alter().
 */
function entity_entity_property_info_alter(&$entity_info) {
  // Add in info for all core entities.
  foreach (_entity_metadata_core_modules() as $module) {
    module_load_include('inc', 'entity', "modules/$module.info");
    if (function_exists($function = "entity_metadata_{$module}_entity_property_info_alter")) {
      $function($entity_info);
    }
  }
}

function _entity_metadata_core_modules() {
53
  return array_filter(array('book', 'comment', 'field', 'node', 'taxonomy', 'user', 'system', 'statistics'), 'module_exists');
54 55 56 57
}

/**
 * Default controller for generating some basic metadata for CRUD entity types.
58 59 60 61 62 63 64 65 66 67 68
 */
class EntityDefaultMetadataController {

  protected $type, $info;

  public function __construct($type) {
    $this->type = $type;
    $this->info = entity_get_info($type);
  }

  public function entityPropertyInfo() {
69 70 71
    $entity_label = drupal_strtolower($this->info['label']);

    // Provide defaults based on the schema.
72
    $info['properties'] = $this->convertSchema();
73
    foreach ($info['properties'] as $name => &$property) {
74 75 76 77 78 79
      // Add a description.
      $property['description'] = t('@entity "@property" property.', array('@entity' => drupal_ucfirst($entity_label), '@property' => $name));
    }

    // Set better metadata for known entity keys.
    $id_key = $this->info['entity keys']['id'];
80

81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
    if (!empty($this->info['entity keys']['name']) && $key = $this->info['entity keys']['name']) {
      $info['properties'][$key]['type'] = 'token';
      $info['properties'][$key]['label'] = t('Machine-readable name');
      $info['properties'][$key]['description'] = t('The machine-readable name identifying this @entity.', array('@entity' => $entity_label));
      $info['properties'][$id_key]['label'] = t('Internal, numeric @entity ID', array('@entity' => $entity_label));
      $info['properties'][$id_key]['description'] = t('The ID used to identify this @entity internally.', array('@entity' => $entity_label));
    }
    else {
      $info['properties'][$id_key]['label'] = t('@entity ID', array('@entity' => drupal_ucfirst($entity_label)));
      $info['properties'][$id_key]['description'] = t('The unique ID of the @entity.', array('@entity' => $entity_label));
    }
    // Care for the bundle.
    if (!empty($this->info['entity keys']['bundle']) && $key = $this->info['entity keys']['bundle']) {
      $info['properties'][$key]['type'] = 'token';
      $info['properties'][$key]['options list'] = array(get_class($this), 'bundleOptionsList');
    }
    // Care for the label.
    if (!empty($this->info['entity keys']['label']) && $key = $this->info['entity keys']['label']) {
      $info['properties'][$key]['label'] = t('Label');
      $info['properties'][$key]['description'] = t('The human readable label.');
101 102 103
    }
    return array($this->type => $info);
  }
104 105 106 107 108 109 110 111 112 113 114 115 116 117

  /**
   * A options list callback returning all bundles for an entity type.
   */
  public static function bundleOptionsList($name, $info) {
    if (!empty($info['parent']) && $type = $info['parent']) {
      $entity_info = $info['parent']->entityInfo();
      $options = array();
      foreach ($entity_info['bundles'] as $name => $bundle_info) {
        $options[$name] = $bundle_info['label'];
      }
      return $options;
    }
  }
118 119 120 121 122 123 124

  /**
   * Return a set of properties for an entity based on the schema definition
   */
  protected function convertSchema() {
    return entity_metadata_convert_schema($this->info['base table']);
  }
125 126 127
}

/**
128 129 130 131 132 133
 * Converts the schema information available for the given table to property info.
 *
 * @param $table
 *   The name of the table as used in hook_schema().
 * @return
 *   An array of property info as suiting for hook_entity_property_info().
134
 */
135 136 137 138 139 140 141 142
function entity_metadata_convert_schema($table) {
  $schema = drupal_get_schema($table);
  $properties = array();
  foreach ($schema['fields'] as $name => $info) {
    if ($type = _entity_metadata_convert_schema_type($info['type'])) {
      $properties[$name] = array(
        'type' => $type,
        'label' => drupal_ucfirst($name),
143
        'schema field' => $name,
144 145 146
        // As we cannot know about any setter access, leave out the setter
        // callback. For getting usually no further access callback is needed.
      );
147
      if ($info['type'] == 'serial') {
148 149
        $properties[$name]['validation callback'] = 'entity_metadata_validate_integer_positive';
      }
150
    }
151
  }
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
  return $properties;
}

function _entity_metadata_convert_schema_type($type) {
  switch ($type) {
    case 'int':
    case 'serial':
      return 'integer';
    case 'float':
    case 'numeric':
      return 'decimal';
    case 'char':
    case 'varchar':
    case 'text':
      return 'text';
  }
168
}