View source  
  <?php
namespace Drupal\restful\Plugin\resource\Field;
use Drupal\restful\Exception\ServerConfigurationException;
use Drupal\restful\Exception\InaccessibleRecordException;
use Drupal\restful\Exception\UnprocessableEntityException;
use Drupal\restful\Http\Request;
use Drupal\restful\Http\RequestInterface;
use Drupal\restful\Plugin\resource\DataProvider\DataProvider;
use Drupal\restful\Plugin\resource\DataInterpreter\DataInterpreterInterface;
use Drupal\restful\Plugin\resource\Field\PublicFieldInfo\PublicFieldInfoEntity;
use Drupal\restful\Plugin\resource\Field\PublicFieldInfo\PublicFieldInfoEntityInterface;
use Drupal\restful\Plugin\resource\Field\PublicFieldInfo\PublicFieldInfoInterface;
use Drupal\restful\Plugin\resource\ResourceInterface;
class ResourceFieldEntity implements ResourceFieldEntityInterface {
  
  protected $decorated;
  
  protected $property;
  
  protected $subProperty;
  
  protected $formatter;
  
  protected $wrapperMethod = 'value';
  
  protected $wrapperMethodOnEntity = FALSE;
  
  protected $column;
  
  protected $imageStyles = array();
  
  protected $entityType;
  
  protected $bundle;
  
  public function __construct(array $field, RequestInterface $request) {
    if ($this->decorated) {
      $this
        ->setRequest($request);
    }
    if (empty($field['entityType'])) {
      throw new ServerConfigurationException(sprintf('Unknown entity type for %s resource field.', __CLASS__));
    }
    $this
      ->setEntityType($field['entityType']);
    $this->wrapperMethod = isset($field['wrapper_method']) ? $field['wrapper_method'] : $this->wrapperMethod;
    $this->subProperty = isset($field['sub_property']) ? $field['sub_property'] : $this->subProperty;
    $this->formatter = isset($field['formatter']) ? $field['formatter'] : $this->formatter;
    $this->wrapperMethodOnEntity = isset($field['wrapper_method_on_entity']) ? $field['wrapper_method_on_entity'] : $this->wrapperMethodOnEntity;
    $this->column = isset($field['column']) ? $field['column'] : $this->column;
    $this->imageStyles = isset($field['image_styles']) ? $field['image_styles'] : $this->imageStyles;
    if (!empty($field['bundle'])) {
      
      $this
        ->setBundle($field['bundle']);
    }
  }
  
  public static function create(array $field, RequestInterface $request = NULL, ResourceFieldInterface $decorated = NULL) {
    $request = $request ?: restful()
      ->getRequest();
    $resource_field = NULL;
    $class_name = static::fieldClassName($field);
    
    if ($class_name && class_exists($class_name) && in_array('Drupal\\restful\\Plugin\\resource\\Field\\ResourceFieldEntityInterface', class_implements($class_name))) {
      $resource_field = new $class_name($field, $request);
    }
    
    if (!$resource_field) {
      
      $resource_field = new static($field, $request);
    }
    if (!$resource_field) {
      throw new ServerConfigurationException('Unable to create resource field');
    }
    
    $resource_field
      ->decorate($decorated ? $decorated : new ResourceField($field, $request));
    $resource_field->decorated
      ->addDefaults();
    
    $resource_field
      ->addDefaults();
    return $resource_field;
  }
  
  public function value(DataInterpreterInterface $interpreter) {
    $value = $this->decorated
      ->value($interpreter);
    if (isset($value)) {
      
      return $value;
    }
    
    if (!$this
      ->access('view', $interpreter)) {
      return NULL;
    }
    $property_wrapper = $this
      ->propertyWrapper($interpreter);
    $wrapper = $interpreter
      ->getWrapper();
    if ($property_wrapper instanceof \EntityListWrapper) {
      $values = array();
      
      foreach ($property_wrapper
        ->getIterator() as $item_wrapper) {
        $values[] = $this
          ->singleValue($item_wrapper, $wrapper, $interpreter
          ->getAccount());
      }
      return $values;
    }
    return $this
      ->singleValue($property_wrapper, $wrapper, $interpreter
      ->getAccount());
  }
  
  public function compoundDocumentId(DataInterpreterInterface $interpreter) {
    $collections = $this
      ->render($interpreter);
    
    $process = function ($collection) {
      if (!$collection instanceof ResourceFieldCollectionInterface) {
        return $collection;
      }
      $id_field = $collection
        ->getIdField();
      return $id_field
        ->render($collection
        ->getInterpreter());
    };
    
    return $this
      ->getCardinality() == 1 ? $process($collections) : array_map($process, array_filter($collections));
  }
  
  protected function propertyIdentifier(\EntityMetadataWrapper $property_wrapper) {
    if ($property_wrapper instanceof \EntityDrupalWrapper) {
      
      $identifier = $this
        ->referencedId($property_wrapper);
      $resource = $this
        ->getResource();
      
      if (!$resource || !$identifier || isset($resource['fullView']) && $resource['fullView'] === FALSE) {
        return $identifier;
      }
      
      $instance_id = sprintf('%s:%d.%d', $resource['name'], $resource['majorVersion'], $resource['minorVersion']);
      
      $resource = restful()
        ->getResourceManager()
        ->getPluginCopy($instance_id, Request::create('', array(), RequestInterface::METHOD_GET));
      $plugin_definition = $resource
        ->getPluginDefinition();
      if (empty($plugin_definition['dataProvider']['idField'])) {
        return $identifier;
      }
      try {
        return $property_wrapper->{$plugin_definition['dataProvider']['idField']}
          ->value();
      } catch (\EntityMetadataWrapperException $e) {
        return $identifier;
      }
    }
    
    return $this
      ->fieldValue($property_wrapper);
  }
  
  public function set($value, DataInterpreterInterface $interpreter) {
    try {
      $property_wrapper = $interpreter
        ->getWrapper()->{$this
        ->getProperty()};
      $property_wrapper
        ->set($value);
    } catch (\Exception $e) {
      $this->decorated
        ->set($value, $interpreter);
    }
  }
  
  protected function singleValue(\EntityMetadataWrapper $property_wrapper, \EntityDrupalWrapper $wrapper, $account) {
    if ($resource = $this
      ->getResource()) {
      
      $embedded_identifier = $this
        ->propertyIdentifier($property_wrapper);
      
      if (empty($embedded_identifier) && $embedded_identifier !== 0) {
        return NULL;
      }
      if (isset($resource['fullView']) && $resource['fullView'] === FALSE) {
        return $embedded_identifier;
      }
      
      $parsed_input = array(
        'fields' => implode(',', $this
          ->nestedDottedChildren('fields')),
        'include' => implode(',', $this
          ->nestedDottedChildren('include')),
        'filter' => $this
          ->nestedDottedChildren('filter'),
      );
      $request = Request::create('', array_filter($parsed_input), RequestInterface::METHOD_GET);
      
      $embedded_resource = restful()
        ->getResourceManager()
        ->getPluginCopy(sprintf('%s:%d.%d', $resource['name'], $resource['majorVersion'], $resource['minorVersion']));
      
      $embedded_resource
        ->setPath($embedded_identifier);
      $embedded_resource
        ->setRequest($request);
      $embedded_resource
        ->setAccount($account);
      $metadata = $this
        ->getMetadata($wrapper
        ->getIdentifier());
      $metadata = $metadata ?: array();
      $metadata[] = $this
        ->buildResourceMetadataItem($property_wrapper);
      $this
        ->addMetadata($wrapper
        ->getIdentifier(), $metadata);
      try {
        
        
        $embedded_entity = $embedded_resource
          ->getDataProvider()
          ->view($embedded_identifier);
      } catch (InaccessibleRecordException $e) {
        
        return NULL;
      } catch (UnprocessableEntityException $e) {
        
        return NULL;
      }
      
      if (empty($parsed_input['filter'])) {
        return $embedded_entity;
      }
      foreach ($parsed_input['filter'] as $filter) {
        
        if (!empty($filter['target']) && $filter['target'] == $this
          ->getPublicName() && !$embedded_entity
          ->evalFilter($filter)) {
          
          return NULL;
        }
      }
      return $embedded_entity;
    }
    if ($this
      ->getFormatter()) {
      
      $value = $this
        ->formatterValue($property_wrapper, $wrapper);
    }
    else {
      
      $value = $this
        ->fieldValue($property_wrapper);
    }
    return $value;
  }
  
  public function access($op, DataInterpreterInterface $interpreter) {
    
    if (!$this->decorated
      ->access($op, $interpreter)) {
      return FALSE;
    }
    if (!$this
      ->getProperty()) {
      
      return TRUE;
    }
    
    if (!($property_wrapper = $this
      ->propertyWrapper($interpreter))) {
      return FALSE;
    }
    if ($this
      ->isWrapperMethodOnEntity() && $this
      ->getWrapperMethod() && $this
      ->getProperty()) {
      
      $property_wrapper = $property_wrapper->{$this
        ->getProperty()};
    }
    $account = $interpreter
      ->getAccount();
    
    if ($op == 'edit' && $property_wrapper
      ->type() == 'text_formatted' && $property_wrapper
      ->value() && $property_wrapper->format
      ->value()) {
      $format = (object) array(
        'format' => $property_wrapper->format
          ->value(),
      );
      
      if (!filter_access($format, $account)) {
        return FALSE;
      }
    }
    $info = $property_wrapper
      ->info();
    if ($op == 'edit' && empty($info['setter callback'])) {
      
      return FALSE;
    }
    
    $access = $interpreter
      ->getWrapper()
      ->value() !== FALSE && $property_wrapper
      ->access($op, $account);
    return $access !== FALSE;
  }
  
  protected function propertyWrapper(DataInterpreterInterface $interpreter) {
    
    $this
      ->setBundle($interpreter
      ->getWrapper()
      ->getBundle());
    
    $wrapper = $interpreter
      ->getWrapper();
    
    if (!$wrapper instanceof \EntityDrupalWrapper) {
      throw new ServerConfigurationException('Cannot get a value without an entity metadata wrapper data source.');
    }
    $property = $this
      ->getProperty();
    try {
      return $property && !$this
        ->isWrapperMethodOnEntity() ? $wrapper->{$property} : $wrapper;
    } catch (\EntityMetadataWrapperException $e) {
      throw new UnprocessableEntityException(sprintf('The property %s could not be found in %s:%s.', $property, $wrapper
        ->type(), $wrapper
        ->getBundle()));
    }
  }
  
  protected function fieldValue(\EntityMetadataWrapper $property_wrapper) {
    if ($this
      ->getSubProperty() && $property_wrapper
      ->value()) {
      $property_wrapper = $property_wrapper->{$this
        ->getSubProperty()};
    }
    
    return $property_wrapper
      ->{$this
      ->getWrapperMethod()}();
  }
  
  protected function formatterValue(\EntityMetadataWrapper $property_wrapper, \EntityDrupalWrapper $wrapper) {
    $value = NULL;
    if (!ResourceFieldEntity::propertyIsField($this
      ->getProperty())) {
      
      throw new ServerConfigurationException(format_string('@property is not a configurable field, so it cannot be processed using field API formatter', array(
        '@property' => $this
          ->getProperty(),
      )));
    }
    
    $output = field_view_field($this
      ->getEntityType(), $wrapper
      ->value(), $this
      ->getProperty(), $this
      ->getFormatter());
    
    unset($output['#theme']);
    if ($property_wrapper instanceof \EntityListWrapper) {
      
      foreach (element_children($output) as $delta) {
        $value[] = drupal_render($output[$delta]);
      }
    }
    else {
      
      $value = drupal_render($output);
    }
    return $value;
  }
  
  protected function nestedDottedChildren($key) {
    
    if ($key == 'filter') {
      return $this
        ->nestedDottedFilters();
    }
    $allowed_values = array(
      'include',
      'fields',
    );
    if (!in_array($key, $allowed_values)) {
      return array();
    }
    $input = $this
      ->getRequest()
      ->getParsedInput();
    $limit_values = !empty($input[$key]) ? explode(',', $input[$key]) : array();
    $limit_values = array_filter($limit_values, function ($value) {
      $parts = explode('.', $value);
      return $parts[0] == $this
        ->getPublicName() && $value != $this
        ->getPublicName();
    });
    return array_map(function ($value) {
      return substr($value, strlen($this
        ->getPublicName()) + 1);
    }, $limit_values);
  }
  
  protected function nestedDottedFilters() {
    $input = $this
      ->getRequest()
      ->getParsedInput();
    if (empty($input['filter'])) {
      return array();
    }
    $output_filters = array();
    $filters = $input['filter'];
    foreach ($filters as $filter_public_name => $filter) {
      $filter = DataProvider::processFilterInput($filter, $filter_public_name);
      if (strpos($filter_public_name, $this
        ->getPublicName() . '.') === 0) {
        
        $new_name = substr($filter_public_name, strlen($this
          ->getPublicName()) + 1);
        $filter['public_field'] = $new_name;
        $output_filters[$new_name] = $filter;
      }
    }
    return $output_filters;
  }
  
  public function addMetadata($key, $value) {
    $this->decorated
      ->addMetadata($key, $value);
  }
  
  public function getMetadata($key) {
    return $this->decorated
      ->getMetadata($key);
  }
  
  public function getRequest() {
    return $this->decorated
      ->getRequest();
  }
  
  public function setRequest(RequestInterface $request) {
    $this->decorated
      ->setRequest($request);
  }
  
  public function executeProcessCallbacks($value) {
    return $this->decorated
      ->executeProcessCallbacks($value);
  }
  
  public function render(DataInterpreterInterface $interpreter) {
    return $this
      ->executeProcessCallbacks($this
      ->value($interpreter));
  }
  
  public function getDefinition() {
    return $this->decorated
      ->getDefinition();
  }
  
  public function getPublicFieldInfo() {
    return $this->decorated
      ->getPublicFieldInfo();
  }
  
  public function setPublicFieldInfo(PublicFieldInfoInterface $public_field_info) {
    $this->decorated
      ->setPublicFieldInfo($public_field_info);
  }
  
  protected function resourceValue(DataInterpreterInterface $source) {
  }
  
  public function decorate(ResourceFieldInterface $decorated) {
    $this->decorated = $decorated;
  }
  
  public function getSubProperty() {
    return $this->subProperty;
  }
  
  public function setSubProperty($sub_property) {
    $this->subProperty = $sub_property;
  }
  
  public function getFormatter() {
    return $this->formatter;
  }
  
  public function setFormatter($formatter) {
    $this->formatter = $formatter;
  }
  
  public function getWrapperMethod() {
    return $this->wrapperMethod;
  }
  
  public function setWrapperMethod($wrapper_method) {
    $this->wrapperMethod = $wrapper_method;
  }
  
  public function isWrapperMethodOnEntity() {
    return $this->wrapperMethodOnEntity;
  }
  
  public function setWrapperMethodOnEntity($wrapper_method_on_entity) {
    $this->wrapperMethodOnEntity = $wrapper_method_on_entity;
  }
  
  public function getColumn() {
    if (isset($this->column)) {
      return $this->column;
    }
    if ($this
      ->getProperty() && ($field = $this::fieldInfoField($this
      ->getProperty()))) {
      if ($field['type'] == 'text_long') {
        
        $this
          ->setColumn('value');
      }
      else {
        
        $this
          ->setColumn(key($field['columns']));
      }
    }
    return $this->column;
  }
  
  public function setColumn($column) {
    $this->column = $column;
  }
  
  public function getImageStyles() {
    return $this->imageStyles;
  }
  
  public function setImageStyles($image_styles) {
    $this->imageStyles = $image_styles;
  }
  
  public function getEntityType() {
    return $this->entityType;
  }
  
  public function setEntityType($entity_type) {
    $this->entityType = $entity_type;
  }
  
  protected function entityTypeWrapper() {
    static $entity_wrappers = array();
    $key = sprintf('%s:%s', $this
      ->getEntityType(), $this
      ->getBundle());
    if (isset($entity_wrappers[$key])) {
      return $entity_wrappers[$key];
    }
    $entity_wrappers[$key] = entity_metadata_wrapper($this
      ->getEntityType(), NULL, array(
      'bundle' => $this
        ->getBundle(),
    ));
    return $entity_wrappers[$key];
  }
  
  public function getBundle() {
    return $this->bundle;
  }
  
  public function setBundle($bundle) {
    
    if (!empty($this->bundle) && $this->bundle == $bundle) {
      return;
    }
    $this->bundle = $bundle;
    
    if ($this
      ->getRequest()
      ->getMethod() == RequestInterface::METHOD_OPTIONS) {
      $this
        ->populatePublicInfoField();
    }
  }
  
  public function addDefaults() {
    
    $this
      ->setResource($this->decorated
      ->getResource());
    
    if ($this
      ->isWrapperMethodOnEntity() && $this
      ->getWrapperMethod()) {
      $this
        ->propertyOnEntity();
    }
    
    if (($this->property = $this->decorated
      ->getProperty()) && ($field = $this::fieldInfoField($this->property)) && $field['type'] == 'image' && ($image_styles = $this
      ->getImageStyles())) {
      
      $process_callbacks = $this
        ->getProcessCallbacks();
      array_unshift($process_callbacks, array(
        array(
          $this,
          'getImageUris',
        ),
        array(
          $image_styles,
        ),
      ));
      $this
        ->setProcessCallbacks($process_callbacks);
    }
  }
  
  public static function getImageUris(array $file_array, $image_styles) {
    
    if (empty($image_styles)) {
      return $file_array;
    }
    
    if (static::isArrayNumeric($file_array)) {
      $output = array();
      foreach ($file_array as $item) {
        $output[] = static::getImageUris($item, $image_styles);
      }
      return $output;
    }
    $file_array['image_styles'] = array();
    foreach ($image_styles as $style) {
      $file_array['image_styles'][$style] = image_style_url($style, $file_array['uri']);
    }
    return $file_array;
  }
  
  public static function propertyIsField($name) {
    return (bool) static::fieldInfoField($name);
  }
  
  public function preprocess($value) {
    
    return $value;
  }
  
  public static function fieldClassName(array $field_definition) {
    if (!empty($field_definition['class']) && $field_definition['class'] != '\\Drupal\\restful\\Plugin\\resource\\Field\\ResourceFieldEntity') {
      
      return $field_definition['class'];
    }
    
    if (empty($field_definition['property']) || !($field_info = static::fieldInfoField($field_definition['property']))) {
      return NULL;
    }
    switch ($field_info['type']) {
      case 'entityreference':
      case 'taxonomy_term_reference':
        return '\\Drupal\\restful\\Plugin\\resource\\Field\\ResourceFieldEntityReference';
      case 'text':
      case 'text_long':
      case 'text_with_summary':
        return '\\Drupal\\restful\\Plugin\\resource\\Field\\ResourceFieldEntityText';
      case 'file':
      case 'image':
        
        if (!empty($field_definition['resource'])) {
          return '\\Drupal\\restful\\Plugin\\resource\\Field\\ResourceFieldFileEntityReference';
        }
        return '\\Drupal\\restful\\Plugin\\resource\\Field\\ResourceFieldEntityFile';
      default:
        return NULL;
    }
  }
  
  public function getPublicName() {
    return $this->decorated
      ->getPublicName();
  }
  
  public function setPublicName($public_name) {
    $this->decorated
      ->setPublicName($public_name);
  }
  
  public function getAccessCallbacks() {
    return $this->decorated
      ->getAccessCallbacks();
  }
  
  public function setAccessCallbacks($access_callbacks) {
    $this->decorated
      ->setAccessCallbacks($access_callbacks);
  }
  
  public function getProperty() {
    return $this->property;
  }
  
  public function setProperty($property) {
    $this->property = $property;
    $this->decorated
      ->setProperty($property);
  }
  
  public function getCallback() {
    return $this->decorated
      ->getCallback();
  }
  
  public function setCallback($callback) {
    $this->decorated
      ->setCallback($callback);
  }
  
  public function getProcessCallbacks() {
    return $this->decorated
      ->getProcessCallbacks();
  }
  
  public function setProcessCallbacks($process_callbacks) {
    $this->decorated
      ->setProcessCallbacks($process_callbacks);
  }
  
  public function getResource() {
    return $this->decorated
      ->getResource();
  }
  
  public function setResource($resource) {
    $this->decorated
      ->setResource($resource);
  }
  
  public function getMethods() {
    return $this->decorated
      ->getMethods();
  }
  
  public function setMethods($methods) {
    $this->decorated
      ->setMethods($methods);
  }
  
  public function id() {
    return $this->decorated
      ->id();
  }
  
  public function isComputed() {
    return $this->decorated
      ->isComputed();
  }
  
  public function autoDiscovery() {
    if (method_exists($this->decorated, 'autoDiscovery')) {
      return $this->decorated
        ->autoDiscovery();
    }
    return ResourceFieldBase::emptyDiscoveryInfo($this
      ->getPublicName());
  }
  
  public function getCardinality() {
    if (isset($this->cardinality)) {
      return $this->cardinality;
    }
    
    $this->cardinality = 1;
    if ($field_info = $this::fieldInfoField($this
      ->getProperty())) {
      $this->cardinality = empty($field_info['cardinality']) ? $this->cardinality : $field_info['cardinality'];
    }
    return $this->cardinality;
  }
  
  public function setCardinality($cardinality) {
    $this->cardinality = $cardinality;
  }
  
  public static function isArrayNumeric(array $input) {
    return ResourceFieldBase::isArrayNumeric($input);
  }
  
  protected function buildResourceMetadataItem($wrapper) {
    if ($wrapper instanceof \EntityValueWrapper) {
      $wrapper = entity_metadata_wrapper($this
        ->getEntityType(), $wrapper
        ->value());
    }
    $id = $wrapper
      ->getIdentifier();
    $bundle = $wrapper
      ->getBundle();
    $resource = $this
      ->getResource();
    return array(
      'id' => $id,
      'entity_type' => $wrapper
        ->type(),
      'bundle' => $bundle,
      'resource_name' => $resource['name'],
    );
  }
  
  protected function referencedId($property_wrapper) {
    return $property_wrapper
      ->getIdentifier() ?: NULL;
  }
  
  protected function propertyOnEntity() {
    
    $property = NULL;
    $wrapper_method = $this
      ->getWrapperMethod();
    $wrapper = $this
      ->entityTypeWrapper();
    if ($wrapper_method == 'label') {
      
      $property = $wrapper
        ->entityKey('label');
    }
    elseif ($wrapper_method == 'getBundle') {
      
      $property = $wrapper
        ->entityKey('bundle');
    }
    elseif ($wrapper_method == 'getIdentifier') {
      
      $property = $wrapper
        ->entityKey('id');
    }
    
    if (!is_a($wrapper, '\\EntityStructureWrapper')) {
      
      return;
    }
    
    foreach ($wrapper
      ->getPropertyInfo() as $wrapper_property => $property_info) {
      if (!empty($property_info['schema field']) && $property_info['schema field'] == $property) {
        $property = $wrapper_property;
        break;
      }
    }
    $this
      ->setProperty($property);
  }
  
  protected function populatePublicInfoField() {
    $field_definition = $this
      ->getDefinition();
    $discovery_info = empty($field_definition['discovery']) ? array() : $field_definition['discovery'];
    $public_field_info = new PublicFieldInfoEntity($this
      ->getPublicName(), $this
      ->getProperty(), $this
      ->getEntityType(), $this
      ->getBundle(), $discovery_info);
    $this
      ->setPublicFieldInfo($public_field_info);
    if ($field_instance = field_info_instance($this
      ->getEntityType(), $this
      ->getProperty(), $this
      ->getBundle())) {
      $public_field_info
        ->addSectionDefaults('info', array(
        'label' => $field_instance['label'],
        'description' => $field_instance['description'],
      ));
      $field_info = $this::fieldInfoField($this
        ->getProperty());
      $section_info = array();
      $section_info['label'] = empty($field_info['label']) ? NULL : $field_info['label'];
      $section_info['description'] = empty($field_info['description']) ? NULL : $field_info['description'];
      $public_field_info
        ->addSectionDefaults('info', $section_info);
      $type = $public_field_info instanceof PublicFieldInfoEntityInterface ? $public_field_info
        ->getFormSchemaAllowedType() : NULL;
      $public_field_info
        ->addSectionDefaults('form_element', array(
        'default_value' => isset($field_instance['default_value']) ? $field_instance['default_value'] : NULL,
        'type' => $type,
      ));
      
      $form_element_info = $public_field_info
        ->getSection('form_element');
      if (!isset($form_element_info['allowed_values'])) {
        $allowed_values = $public_field_info instanceof PublicFieldInfoEntityInterface ? $public_field_info
          ->getFormSchemaAllowedValues() : NULL;
        $public_field_info
          ->addSectionDefaults('form_element', array(
          'allowed_values' => $allowed_values,
        ));
      }
    }
    else {
      
      try {
        $property_info = $this
          ->entityTypeWrapper()
          ->getPropertyInfo($this
          ->getProperty());
      } catch (\EntityMetadataWrapperException $e) {
        return;
      }
      if (empty($property_info)) {
        return;
      }
      $public_field_info
        ->addSectionDefaults('data', array(
        'type' => $property_info['type'],
        'required' => empty($property_info['required']) ? FALSE : $property_info['required'],
      ));
      $public_field_info
        ->addSectionDefaults('info', array(
        'label' => $property_info['label'],
        'description' => $property_info['description'],
      ));
    }
  }
  
  protected static function fieldInfoField($field_name) {
    return field_info_field($field_name);
  }
}