You are here

class EntityReferenceBehavior_TaxonomyIndex in Entity reference 7

Extends an entityreference field to maintain its references to taxonomy terms in the {taxonomy_index} table.

Note, unlike entityPostInsert() and entityPostUpdate(), entityDelete() is not needed as cleanup is performed by taxonomy module in taxonomy_delete_node_index().

Hierarchy

Expanded class hierarchy of EntityReferenceBehavior_TaxonomyIndex

1 string reference to 'EntityReferenceBehavior_TaxonomyIndex'
taxonomy-index.inc in plugins/behavior/taxonomy-index.inc

File

plugins/behavior/EntityReferenceBehavior_TaxonomyIndex.class.php, line 16
CTools plugin class for the taxonomy-index behavior.

View source
class EntityReferenceBehavior_TaxonomyIndex extends EntityReference_BehaviorHandler_Abstract {

  /**
   * Overrides EntityReference_BehaviorHandler_Abstract::access().
   *
   * Ensure that it is only enabled for ER instances on nodes targeting
   * terms, and the core variable to maintain index is enabled.
   */
  public function access($field, $instance) {
    if ($instance['entity_type'] != 'node' || $field['settings']['target_type'] != 'taxonomy_term') {
      return;
    }
    if ($field['storage']['type'] !== 'field_sql_storage') {

      // Field doesn't use SQL storage.
      return;
    }
    return variable_get('taxonomy_maintain_index_table', TRUE);
  }

  /**
   * Overrides EntityReference_BehaviorHandler_Abstract::entityPostInsert().
   *
   * Runs after hook_node_insert() used by taxonomy module.
   */
  public function entityPostInsert($entity_type, $entity, $field, $instance) {
    if ($entity_type != 'node') {
      return;
    }
    $this
      ->buildNodeIndex($entity);
  }

  /**
   * Overrides EntityReference_BehaviorHandler_Abstract::entityPostUpdate().
   *
   * Runs after hook_node_update() used by taxonomy module.
   */
  public function entityPostUpdate($entity_type, $entity, $field, $instance) {
    if ($entity_type != 'node') {
      return;
    }
    $this
      ->buildNodeIndex($entity);
  }

  /**
   * Builds and inserts taxonomy index entries for a given node.
   *
   * The index lists all terms that are related to a given node entity, and is
   * therefore maintained at the entity level.
   *
   * @param $node
   *   The node object.
   *
   * @see taxonomy_build_node_index()
   */
  protected function buildNodeIndex($node) {

    // We maintain a denormalized table of term/node relationships, containing
    // only data for current, published nodes.
    $status = NULL;
    if (variable_get('taxonomy_maintain_index_table', TRUE)) {

      // If a node property is not set in the node object when node_save() is
      // called, the old value from $node->original is used.
      if (!empty($node->original)) {
        $status = (int) (!empty($node->status) || !isset($node->status) && !empty($node->original->status));
        $sticky = (int) (!empty($node->sticky) || !isset($node->sticky) && !empty($node->original->sticky));
      }
      else {
        $status = (int) (!empty($node->status));
        $sticky = (int) (!empty($node->sticky));
      }
    }

    // We only maintain the taxonomy index for published nodes.
    if ($status) {

      // Collect a unique list of all the term IDs from all node fields.
      $tid_all = array();
      foreach (field_info_instances('node', $node->type) as $instance) {
        $field_name = $instance['field_name'];
        $field = field_info_field($field_name);
        if (!empty($field['settings']['target_type']) && $field['settings']['target_type'] == 'taxonomy_term' && $field['storage']['type'] == 'field_sql_storage') {

          // If a field value is not set in the node object when node_save() is
          // called, the old value from $node->original is used.
          if (isset($node->{$field_name})) {
            $items = $node->{$field_name};
          }
          elseif (isset($node->original->{$field_name})) {
            $items = $node->original->{$field_name};
          }
          else {
            continue;
          }
          foreach (field_available_languages('node', $field) as $langcode) {
            if (!empty($items[$langcode])) {
              foreach ($items[$langcode] as $item) {
                $tid_all[$item['target_id']] = $item['target_id'];
              }
            }
          }
        }

        // Re-calculate the terms added in taxonomy_build_node_index() so
        // we can optimize database queries.
        $original_tid_all = array();
        if ($field['module'] == 'taxonomy' && $field['storage']['type'] == 'field_sql_storage') {

          // If a field value is not set in the node object when node_save() is
          // called, the old value from $node->original is used.
          if (isset($node->{$field_name})) {
            $items = $node->{$field_name};
          }
          elseif (isset($node->original->{$field_name})) {
            $items = $node->original->{$field_name};
          }
          else {
            continue;
          }
          foreach (field_available_languages('node', $field) as $langcode) {
            if (!empty($items[$langcode])) {
              foreach ($items[$langcode] as $item) {
                $original_tid_all[$item['tid']] = $item['tid'];
              }
            }
          }
        }
      }

      // Insert index entries for all the node's terms, that were not
      // already inserted in taxonomy_build_node_index().
      $tid_all = array_diff($tid_all, $original_tid_all);

      // Insert index entries for all the node's terms, preventing duplicates.
      if (!empty($tid_all)) {
        foreach ($tid_all as $tid) {
          $row = array(
            'nid' => $node->nid,
            'tid' => $tid,
            'sticky' => $sticky,
            'created' => $node->created,
          );
          $query = db_merge('taxonomy_index')
            ->key($row)
            ->fields($row);
          $query
            ->execute();
        }
      }
    }
  }

  /**
   * Overrides EntityReference_BehaviorHandler_Abstract::settingsForm().
   */
  public function settingsForm($field, $instance) {
    $form = array();
    $target = $field['settings']['target_type'];
    if ($target != 'taxonomy_term') {
      $form['ti-on-terms'] = array(
        '#markup' => t('This behavior can only be set when the target type is taxonomy_term, but the target of this field is %target.', array(
          '%target' => $target,
        )),
      );
    }
    $entity_type = $instance['entity_type'];
    if ($entity_type != 'node') {
      $form['ti-on-nodes'] = array(
        '#markup' => t('This behavior can only be set when the entity type is node, but the entity type of this instance is %type.', array(
          '%type' => $entity_type,
        )),
      );
    }
    if (!variable_get('taxonomy_maintain_index_table', TRUE)) {
      $form['ti-disabled'] = array(
        '#markup' => t('This core variable "taxonomy_maintain_index_table" is disabled.'),
      );
    }
    return $form;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
EntityReferenceBehavior_TaxonomyIndex::access public function Overrides EntityReference_BehaviorHandler_Abstract::access(). Overrides EntityReference_BehaviorHandler_Abstract::access
EntityReferenceBehavior_TaxonomyIndex::buildNodeIndex protected function Builds and inserts taxonomy index entries for a given node.
EntityReferenceBehavior_TaxonomyIndex::entityPostInsert public function Overrides EntityReference_BehaviorHandler_Abstract::entityPostInsert(). Overrides EntityReference_BehaviorHandler_Abstract::entityPostInsert
EntityReferenceBehavior_TaxonomyIndex::entityPostUpdate public function Overrides EntityReference_BehaviorHandler_Abstract::entityPostUpdate(). Overrides EntityReference_BehaviorHandler_Abstract::entityPostUpdate
EntityReferenceBehavior_TaxonomyIndex::settingsForm public function Overrides EntityReference_BehaviorHandler_Abstract::settingsForm(). Overrides EntityReference_BehaviorHandler_Abstract::settingsForm
EntityReference_BehaviorHandler_Abstract::$behavior protected property The name of the behavior plugin.
EntityReference_BehaviorHandler_Abstract::$plugin protected property The plugin definition.
EntityReference_BehaviorHandler_Abstract::delete public function Act before deleting an entity with an entity reference field. Overrides EntityReference_BehaviorHandler::delete 2
EntityReference_BehaviorHandler_Abstract::entityPostDelete public function Act after deleting an entity. Overrides EntityReference_BehaviorHandler::entityPostDelete
EntityReference_BehaviorHandler_Abstract::insert public function Act before inserting an entity reference field. Overrides EntityReference_BehaviorHandler::insert 2
EntityReference_BehaviorHandler_Abstract::is_empty_alter public function Alter the empty status of a field item. Overrides EntityReference_BehaviorHandler::is_empty_alter
EntityReference_BehaviorHandler_Abstract::load public function Act on loading entity reference fields of entities. Overrides EntityReference_BehaviorHandler::load 2
EntityReference_BehaviorHandler_Abstract::postDelete public function Act after deleting an entity with an entity reference field. Overrides EntityReference_BehaviorHandler::postDelete
EntityReference_BehaviorHandler_Abstract::postInsert public function Act after inserting an entity reference field. Overrides EntityReference_BehaviorHandler::postInsert
EntityReference_BehaviorHandler_Abstract::postUpdate public function Act after updating an entity reference field. Overrides EntityReference_BehaviorHandler::postUpdate
EntityReference_BehaviorHandler_Abstract::presave public function Act on presaving an entity reference field. Overrides EntityReference_BehaviorHandler::presave
EntityReference_BehaviorHandler_Abstract::property_info_alter public function Alter the properties information of a field instance. Overrides EntityReference_BehaviorHandler::property_info_alter
EntityReference_BehaviorHandler_Abstract::schema_alter public function Alter the field schema. Overrides EntityReference_BehaviorHandler::schema_alter
EntityReference_BehaviorHandler_Abstract::update public function Act before updating an entity reference field. Overrides EntityReference_BehaviorHandler::update 2
EntityReference_BehaviorHandler_Abstract::validate public function Act on validating an entity reference field. Overrides EntityReference_BehaviorHandler::validate
EntityReference_BehaviorHandler_Abstract::views_data_alter public function Alter the views data of a field. Overrides EntityReference_BehaviorHandler::views_data_alter 1
EntityReference_BehaviorHandler_Abstract::__construct public function Constructor for the behavior. Overrides EntityReference_BehaviorHandler::__construct