From 1c8004bf84fd8b32afcbb7301555f5c7200120c1 Mon Sep 17 00:00:00 2001 From: Frederic G. MARAND Date: Thu, 17 May 2012 08:51:07 +0200 Subject: [PATCH] Issue #1586428: add taxonomy_index integration - new taxonomy-index behavior plugin - added entity hooks to entityreference module - glue in entiryreference to enable Field_UI validation --- entityreference.module | 79 +++++++++++- ...EntityReferenceBehavior_TaxonomyIndex.class.php | 140 ++++++++++++++++++++ plugins/behavior/taxonomy-index.inc | 13 ++ 3 files changed, 231 insertions(+), 1 deletions(-) create mode 100644 plugins/behavior/EntityReferenceBehavior_TaxonomyIndex.class.php create mode 100644 plugins/behavior/taxonomy-index.inc diff --git a/entityreference.module b/entityreference.module index 6fbd3ec..a67379d 100644 --- a/entityreference.module +++ b/entityreference.module @@ -36,7 +36,7 @@ function entityreference_behavior_plugin_process(&$plugin, $info) { } /** - * Implementation of hook_field_info(). + * Implements hook_field_info(). */ function entityreference_field_info() { $field_info['entityreference'] = array( @@ -185,6 +185,51 @@ function entityreference_get_selection_handler($field, $instance = NULL, $entity } /** + * Implements hook_entity_delete(). + */ +function entityreference_entity_delete($entity, $entity_type) { + list(, , $bundle) = entity_extract_ids($entity_type, $entity); + foreach (field_info_instances($entity_type, $bundle) as $field_name => $instance) { + $field = field_info_field($field_name); + if ($field['type'] == 'entityreference') { + foreach (entityreference_get_behavior_handlers($field, $instance) as $handler) { + $handler->entityDelete($entity_type, $entity, $field, $instance); + } + } + } +} + +/** + * Implements hook_entity_insert(). + */ +function entityreference_entity_insert($entity, $entity_type) { + list(, , $bundle) = entity_extract_ids($entity_type, $entity); + foreach (field_info_instances($entity_type, $bundle) as $field_name => $instance) { + $field = field_info_field($field_name); + if ($field['type'] == 'entityreference') { + foreach (entityreference_get_behavior_handlers($field, $instance) as $handler) { + $handler->entityInsert($entity_type, $entity, $field, $instance); + } + } + } +} + +/** + * Implements hook_entity_update(). + */ +function entityreference_entity_update($entity, $entity_type) { + list(, , $bundle) = entity_extract_ids($entity_type, $entity); + foreach (field_info_instances($entity_type, $bundle) as $field_name => $instance) { + $field = field_info_field($field_name); + if ($field['type'] == 'entityreference') { + foreach (entityreference_get_behavior_handlers($field, $instance) as $handler) { + $handler->entityUpdate($entity_type, $entity, $field, $instance); + } + } + } +} + +/** * Implements hook_field_load(). */ function entityreference_field_load($entity_type, $entities, $field, $instances, $langcode, &$items) { @@ -1010,3 +1055,35 @@ function entityreference_views_api() { 'path' => drupal_get_path('module', 'entityreference') . '/views', ); } + +/** + * Implements hook_form_FORM_ID_alter(). + * + * Taxonomy_index behavior: Add validate callback to field_ui_field_edit_form(). + */ +function entityreference_form_field_ui_field_edit_form_alter(&$form, $form_state, $form_id) { + $form['#validate'][] = 'entityreference_field_ui_field_edit_form_validate'; +} + +/** + * Validate handler for field_ui_field_edit_form(). + * + * taxonomy_index behavior : ensure that it is only enabled for ER instances on + * nodes targeting terms. + */ +function entityreference_field_ui_field_edit_form_validate($form, $form_state) { + $values = $form_state['values']; + if (!empty($values['instance']['settings']['behaviors']['taxonomy-index']['status'])) { + $target_type = isset($values['field']['settings']['target_type']) + ? $values['field']['settings']['target_type'] + : NULL; + if ($target_type != 'taxonomy_term') { + form_set_error('taxonomy-index', + t('Taxonomy index can only be applied when the target is "taxonomy_term".')); + } + if ($values['instance']['entity_type'] != 'node') { + form_set_error('taxonomy-index', + t('Taxonomy index can only be applied when the entity type is "node".')); + } + } +} diff --git a/plugins/behavior/EntityReferenceBehavior_TaxonomyIndex.class.php b/plugins/behavior/EntityReferenceBehavior_TaxonomyIndex.class.php new file mode 100644 index 0000000..7da2e59 --- /dev/null +++ b/plugins/behavior/EntityReferenceBehavior_TaxonomyIndex.class.php @@ -0,0 +1,140 @@ +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 ($field['module'] == 'entityreference' && $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']; + } + } + } + } + } + // Insert index entries for all the node's terms. + if (!empty($tid_all)) { + $query = db_insert('taxonomy_index')->fields(array('nid', 'tid', 'sticky', 'created')); + foreach ($tid_all as $tid) { + $query->values(array( + 'nid' => $node->nid, + 'tid' => $tid, + 'sticky' => $sticky, + 'created' => $node->created, + )); + } + $query->execute(); + } + } + } + + 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, + )), + ); + } + return $form; + } + + /** + * Implements hook_entity_insert(). + * + * Runs after hook_node_insert() used by taxonomy.module. + */ + public function entityInsert($entity_type, $entity, $field, $instance) { + if ($entity_type != 'node') { + return; + } + // Add taxonomy index entries for the node. + $this->buildNodeIndex($entity); + } + + /** + * Implements hook_entity_update(). + * + * Runs after hook_node_update() used by taxonomy.module. + */ + public function entityUpdate($entity_type, $entity, $field, $instance) { + if ($entity_type != 'node') { + return; + } + // Taxonomy.module always rebuilds the node's taxonomy index entries on node + // save, and is invoked before hook_entity_update(), so this must not call + // taxonomy_delete_node_index($node); + $this->buildNodeIndex($entity); + } +} diff --git a/plugins/behavior/taxonomy-index.inc b/plugins/behavior/taxonomy-index.inc new file mode 100644 index 0000000..58b5ea7 --- /dev/null +++ b/plugins/behavior/taxonomy-index.inc @@ -0,0 +1,13 @@ + t('Taxonomy index'), + 'description' => t('Include the term references created by instances of this field carried by node entities in the core {taxonomy_index} table. This will allow various modules to handle them like core term_reference fields.'), + 'class' => 'EntityReferenceBehavior_TaxonomyIndex', + 'behavior type' => 'instance', +); -- 1.7.4.1