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.
 
  
    View source  
  <?php
function entity_entity_property_info() {
  $items = array();
  
  foreach (entity_crud_get_info() as $type => $info) {
    
    if (!isset($info['metadata controller class']) && !empty($info['base table']) && (!isset($info['module']) || !module_hook($info['module'], 'entity_property_info'))) {
      $info['metadata controller class'] = 'EntityDefaultMetadataController';
    }
    if (!empty($info['metadata controller class'])) {
      $controller = new $info['metadata controller class']($type);
      $items += $controller
        ->entityPropertyInfo();
    }
  }
  
  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;
}
function entity_entity_property_info_alter(&$entity_info) {
  
  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() {
  return array_filter(array(
    'book',
    'comment',
    'field',
    'locale',
    'node',
    'taxonomy',
    'user',
    'system',
    'statistics',
  ), 'module_exists');
}
class EntityDefaultMetadataController {
  protected $type, $info;
  public function __construct($type) {
    $this->type = $type;
    $this->info = entity_get_info($type);
  }
  public function entityPropertyInfo() {
    $entity_label = drupal_strtolower($this->info['label']);
    
    $info['properties'] = $this
      ->convertSchema();
    foreach ($info['properties'] as $name => &$property) {
      
      $property['description'] = t('@entity "@property" property.', array(
        '@entity' => drupal_ucfirst($entity_label),
        '@property' => $name,
      ));
    }
    
    $id_key = $this->info['entity keys']['id'];
    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,
      ));
    }
    
    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',
      );
    }
    
    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.');
    }
    
    if (empty($info['properties']['url']) && !empty($this->info['uri callback'])) {
      $info['properties']['url'] = array(
        'label' => t('URL'),
        'description' => t('The URL of the entity.'),
        'getter callback' => 'entity_metadata_entity_get_properties',
        'type' => 'uri',
        'computed' => TRUE,
        'entity views field' => TRUE,
      );
    }
    return array(
      $this->type => $info,
    );
  }
  
  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;
    }
  }
  
  protected function convertSchema() {
    return entity_metadata_convert_schema($this->info['base table']);
  }
}
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),
        'schema field' => $name,
      );
      if ($info['type'] == 'serial') {
        $properties[$name]['validation callback'] = 'entity_metadata_validate_integer_positive';
      }
    }
  }
  return $properties;
}
function _entity_metadata_convert_schema_type($type) {
  switch ($type) {
    case 'int':
    case 'serial':
    case 'date':
      return 'integer';
    case 'float':
    case 'numeric':
      return 'decimal';
    case 'char':
    case 'varchar':
    case 'text':
      return 'text';
  }
}
interface EntityExtraFieldsControllerInterface {
  
  public function fieldExtraFields();
}
class EntityDefaultExtraFieldsController implements EntityExtraFieldsControllerInterface {
  
  protected $entityType;
  
  protected $entityInfo;
  
  public function __construct($type) {
    $this->entityType = $type;
    $this->entityInfo = entity_get_info($type);
    $this->propertyInfo = entity_get_property_info($type);
  }
  
  public function fieldExtraFields() {
    $extra = array();
    foreach ($this->propertyInfo['properties'] as $name => $property_info) {
      
      if ($this->entityInfo['entity keys']['id'] == $name || $this->entityInfo['entity keys']['bundle'] == $name) {
        continue;
      }
      $extra[$this->entityType][$this->entityType]['display'][$name] = $this
        ->generateExtraFieldInfo($name, $property_info);
    }
    
    $this->propertyInfo += array(
      'bundles' => array(),
    );
    foreach ($this->propertyInfo['bundles'] as $bundle_name => $info) {
      foreach ($info['properties'] as $name => $property_info) {
        if (empty($property_info['field'])) {
          $extra[$this->entityType][$bundle_name]['display'][$name] = $this
            ->generateExtraFieldInfo($name, $property_info);
        }
      }
    }
    return $extra;
  }
  
  protected function generateExtraFieldInfo($name, $property_info) {
    $info = array(
      'label' => $property_info['label'],
      'weight' => 0,
    );
    if (!empty($property_info['description'])) {
      $info['description'] = $property_info['description'];
    }
    return $info;
  }
}