You are here

class EntityStructureWrapper in Entity API 7

Provides a general wrapper for any data structure. For this to work the metadata has to be passed during construction.

Hierarchy

Expanded class hierarchy of EntityStructureWrapper

File

includes/entity.wrapper.inc, line 295
Provides wrappers allowing easy usage of the entity metadata.

View source
class EntityStructureWrapper extends EntityMetadataWrapper implements IteratorAggregate {
  protected $propertyInfo = array(), $propertyInfoAltered = FALSE;
  protected $langcode = LANGUAGE_NONE;
  protected $propertyInfoDefaults = array(
    'type' => 'text',
    'getter callback' => 'entity_property_verbatim_get',
    'clear' => array(),
  );

  /**
   * Construct a new EntityStructureWrapper object.
   *
   * @param $type
   *   The type of the passed data.
   * @param $data
   *   Optional. The data to wrap.
   * @param $info
   *   Used to for specifying metadata about the data and internally to pass
   *   info about properties down the tree. For specifying metadata known keys
   *   are:
   *   - property info: An array of info about the properties of the wrapped
   *     data structure. It has to contain an array of property info in the same
   *     structure as used by hook_entity_property_info().
   */
  public function __construct($type, $data = NULL, $info = array()) {
    parent::__construct($type, $data, $info);
    $this->info += array(
      'property defaults' => array(),
    );
    $info += array(
      'property info' => array(),
    );
    $this->propertyInfo['properties'] = $info['property info'];
  }

  /**
   * May be used to lazy-load additional info about the data, depending on the
   * concrete passed data.
   */
  protected function spotInfo() {

    // Apply the callback if set, such that the caller may alter the info.
    if (!empty($this->info['property info alter']) && !$this->propertyInfoAltered) {
      $this->propertyInfo = call_user_func($this->info['property info alter'], $this, $this->propertyInfo);
      $this->propertyInfoAltered = TRUE;
    }
  }

  /**
   * Gets the info about the given property.
   *
   * @param $name
   *   The name of the property. If not given, info about all properties will
   *   be returned.
   *
   * @return array
   *   An array of info about the property.
   *
   * @throws EntityMetadataWrapperException
   *   If there is no such property.
   */
  public function getPropertyInfo($name = NULL) {
    $this
      ->spotInfo();
    if (!isset($name)) {
      return $this->propertyInfo['properties'];
    }
    if (!isset($this->propertyInfo['properties'][$name])) {
      throw new EntityMetadataWrapperException('Unknown data property ' . check_plain($name) . '.');
    }
    return $this->propertyInfo['properties'][$name] + $this->info['property defaults'] + $this->propertyInfoDefaults;
  }

  /**
   * Returns a reference on the property info.
   *
   * If possible, use the property info alter callback for spotting metadata.
   * The reference may be used to alter the property info for any remaining
   * cases, e.g. if additional metadata has been asserted.
   */
  public function &refPropertyInfo() {
    return $this->propertyInfo;
  }

  /**
   * Sets a new language to use for retrieving properties.
   *
   * @param $langcode
   *   The language code of the language to set.
   *
   * @return EntityWrapper
   */
  public function language($langcode = LANGUAGE_NONE) {
    if ($langcode != $this->langcode) {
      $this->langcode = $langcode;
      $this->cache = array();
    }
    return $this;
  }

  /**
   * Gets the language used for retrieving properties.
   *
   * @return string|null
   *   The language object of the language or NULL for the default language.
   *
   * @see EntityStructureWrapper::language()
   */
  public function getPropertyLanguage() {
    if ($this->langcode != LANGUAGE_NONE && ($list = language_list())) {
      if (isset($list[$this->langcode])) {
        return $list[$this->langcode];
      }
    }
    return NULL;
  }

  /**
   * Get the wrapper for a property.
   *
   * @return EntityMetadataWrapper
   *   An instance of EntityMetadataWrapper.
   */
  public function get($name) {

    // Look it up in the cache if possible.
    if (!array_key_exists($name, $this->cache)) {
      if ($info = $this
        ->getPropertyInfo($name)) {
        $info += array(
          'parent' => $this,
          'name' => $name,
          'langcode' => $this->langcode,
          'property defaults' => array(),
        );
        $info['property defaults'] += $this->info['property defaults'];
        $this->cache[$name] = entity_metadata_wrapper($info['type'], NULL, $info);
      }
      else {
        throw new EntityMetadataWrapperException('There is no property ' . check_plain($name) . " for this entity.");
      }
    }
    return $this->cache[$name];
  }

  /**
   * Magic method: Get a wrapper for a property.
   */
  public function __get($name) {
    if (strpos($name, 'krumo') === 0) {

      // #914934 Ugly workaround to allow krumo to write its recursion property.
      // This is necessary to make dpm() work without throwing exceptions.
      return NULL;
    }
    $get = $this
      ->get($name);
    return $get;
  }

  /**
   * Magic method: Set a property.
   */
  public function __set($name, $value) {
    if (strpos($name, 'krumo') === 0) {

      // #914934 Ugly workaround to allow krumo to write its recursion property.
      // This is necessary to make dpm() work without throwing exceptions.
      $this->{$name} = $value;
    }
    else {
      $this
        ->get($name)
        ->set($value);
    }
  }

  /**
   * Gets the value of a property.
   */
  protected function getPropertyValue($name, &$info) {
    $options = array(
      'language' => $this
        ->getPropertyLanguage(),
      'absolute' => TRUE,
    );
    $data = $this
      ->value();
    if (!isset($data)) {
      throw new EntityMetadataWrapperException('Unable to get the data property ' . check_plain($name) . ' as the parent data structure is not set.');
    }
    return $info['getter callback']($data, $options, $name, $this->type, $info);
  }

  /**
   * Gets the raw value of a property.
   */
  protected function getPropertyRaw($name, &$info) {
    if (!empty($info['raw getter callback'])) {
      $options = array(
        'language' => $this
          ->getPropertyLanguage(),
        'absolute' => TRUE,
      );
      $data = $this
        ->value();
      if (!isset($data)) {
        throw new EntityMetadataWrapperException('Unable to get the data property ' . check_plain($name) . ' as the parent data structure is not set.');
      }
      return $info['raw getter callback']($data, $options, $name, $this->type, $info);
    }
    return $this
      ->getPropertyValue($name, $info);
  }

  /**
   * Sets a property.
   */
  protected function setProperty($name, $value) {
    $info = $this
      ->getPropertyInfo($name);
    if (!empty($info['setter callback'])) {
      $data = $this
        ->value();

      // In case the data structure is not set, support simple auto-creation
      // for arrays. Else an exception is thrown.
      if (!isset($data)) {
        if (!empty($this->info['auto creation']) && !$this instanceof EntityDrupalWrapper) {
          $data = $this->info['auto creation']($name, $this->info);
        }
        else {
          throw new EntityMetadataWrapperException('Unable to set the data property ' . check_plain($name) . ' as the parent data structure is not set.');
        }
      }

      // Invoke the setter callback for updating our data.
      $info['setter callback']($data, $name, $value, $this->langcode, $this->type, $info);

      // If the setter has not thrown any exceptions, proceed and apply the
      // update to the current and any parent wrappers as necessary.
      $data = $this->info['type'] == 'entity' ? $this : $data;
      $this
        ->set($data);

      // Clear the cache of properties dependent on this value.
      foreach ($info['clear'] as $name) {
        if (isset($this->cache[$name])) {
          $this->cache[$name]
            ->clear();
        }
      }
    }
    else {
      throw new EntityMetadataWrapperException('Entity property ' . check_plain($name) . " doesn't support writing.");
    }
  }
  protected function propertyAccess($name, $op, $account = NULL) {
    $info = $this
      ->getPropertyInfo($name);

    // If a property should be edited and this is part of an entity, make sure
    // the user has update access for this entity.
    if ($op == 'edit') {
      $entity = $this;
      while (!$entity instanceof EntityDrupalWrapper && isset($entity->info['parent'])) {
        $entity = $entity->info['parent'];
      }
      if ($entity instanceof EntityDrupalWrapper && $entity
        ->entityAccess('update', $account) === FALSE) {
        return FALSE;
      }
    }
    if (!empty($info['access callback'])) {
      $data = $this
        ->dataAvailable() ? $this
        ->value() : NULL;
      return call_user_func($info['access callback'], $op, $name, $data, $account, $this->type);
    }
    elseif ($op == 'edit' && isset($info['setter permission'])) {
      return user_access($info['setter permission'], $account);
    }

    // If access is unknown, we return TRUE.
    return TRUE;
  }

  /**
   * Magic method: Can be used to check if a property is known.
   */
  public function __isset($name) {
    $this
      ->spotInfo();
    return isset($this->propertyInfo['properties'][$name]);
  }
  public function getIterator() {
    $this
      ->spotInfo();
    return new EntityMetadataWrapperIterator($this, array_keys($this->propertyInfo['properties']));
  }

  /**
   * Returns the identifier of the data structure. If there is none, NULL is
   * returned.
   */
  public function getIdentifier() {
    return isset($this->id) && $this
      ->dataAvailable() ? $this->id
      ->value() : NULL;
  }

  /**
   * Prepare for serializiation.
   */
  public function __sleep() {
    $vars = parent::__sleep();
    unset($vars['propertyInfoDefaults']);
    return $vars;
  }
  public function clear() {
    $this->propertyInfoAltered = FALSE;
    parent::clear();
  }

}

Members

Namesort descending Modifiers Type Description Overrides
EntityMetadataWrapper::$cache protected property
EntityMetadataWrapper::$data protected property
EntityMetadataWrapper::$info protected property
EntityMetadataWrapper::$type protected property 1
EntityMetadataWrapper::access public function Determines whether the given user has access to view or edit this property. Apart from relying on access metadata of properties, this takes into account information about entity level access, if available: 1
EntityMetadataWrapper::dataAvailable protected function Returns whether data is available to work with.
EntityMetadataWrapper::debugIdentifierLocation public function Returns a string to use to identify this wrapper in error messages. 1
EntityMetadataWrapper::info public function Gets info about the wrapped data.
EntityMetadataWrapper::label public function Returns the label for the currently set property value if there is one available, i.e. if an options list has been specified. 2
EntityMetadataWrapper::optionsList public function Returns the options list specifying possible values for the property, if defined.
EntityMetadataWrapper::raw public function Returns the raw, unprocessed data. Most times this is the same as returned by value(), however for already processed and sanitized textual data, this will return the unprocessed data in contrast to value().
EntityMetadataWrapper::set public function Set a new data value. 2
EntityMetadataWrapper::type public function Gets the (entity)type of the wrapped data. 1
EntityMetadataWrapper::updateParent protected function Updates the parent data structure of a data property with the latest data value.
EntityMetadataWrapper::validate public function Returns whether $value is a valid value to set. 1
EntityMetadataWrapper::value public function Returns the wrapped data. If no options are given the data is returned as described in the info. 3
EntityMetadataWrapper::__toString public function
EntityStructureWrapper::$langcode protected property
EntityStructureWrapper::$propertyInfo protected property
EntityStructureWrapper::$propertyInfoDefaults protected property
EntityStructureWrapper::clear public function Clears the data value and the wrapper cache. Overrides EntityMetadataWrapper::clear 1
EntityStructureWrapper::get public function Get the wrapper for a property.
EntityStructureWrapper::getIdentifier public function Returns the identifier of the data structure. If there is none, NULL is returned. 1
EntityStructureWrapper::getIterator public function
EntityStructureWrapper::getPropertyInfo public function Gets the info about the given property.
EntityStructureWrapper::getPropertyLanguage public function Gets the language used for retrieving properties.
EntityStructureWrapper::getPropertyRaw protected function Gets the raw value of a property.
EntityStructureWrapper::getPropertyValue protected function Gets the value of a property.
EntityStructureWrapper::language public function Sets a new language to use for retrieving properties.
EntityStructureWrapper::propertyAccess protected function
EntityStructureWrapper::refPropertyInfo public function Returns a reference on the property info.
EntityStructureWrapper::setProperty protected function Sets a property.
EntityStructureWrapper::spotInfo protected function May be used to lazy-load additional info about the data, depending on the concrete passed data. 1
EntityStructureWrapper::__construct public function Construct a new EntityStructureWrapper object. Overrides EntityMetadataWrapper::__construct 1
EntityStructureWrapper::__get public function Magic method: Get a wrapper for a property.
EntityStructureWrapper::__isset public function Magic method: Can be used to check if a property is known.
EntityStructureWrapper::__set public function Magic method: Set a property.
EntityStructureWrapper::__sleep public function Prepare for serializiation. Overrides EntityMetadataWrapper::__sleep 1