Force Search API To Re-index affected Commerce Entities/Nodes after "Discount" manipulations
/**
* Implements hook_commerce_discount_insert().
*
* Re-index related Product-Nodes.
*/
function MY_MODULE_commerce_discount_insert($entity) {
MY_MODULE_discount_update_search_index($entity);
}
/**
* Implements hook_commerce_discount_update().
*
* Re-index related Product-Nodes.
*/
function MY_MODULE_commerce_discount_update($entity) {
MY_MODULE_discount_update_search_index($entity);
}
/**
* Implements hook_commerce_discount_delete().
*
* Re-index related Product-Nodes.
*/
function MY_MODULE_commerce_discount_delete($entity) {
MY_MODULE_discount_update_search_index($entity);
}
/**
* Get and re-index related Product-Nids of the Discount.
*
* @param $entity
*
* @see: commerce_product_contains_products_build
* hook_inline_conditions_build_alter
*/
function MY_MODULE_discount_update_search_index($entity) {
$nids = array();
// Get related Nids of the current Discount.
$wrapper = entity_metadata_wrapper('commerce_discount', $entity);
$line_items = $wrapper->inline_conditions->value();
$nids = MY_MODULE_discount_get_related_discount_nids($line_items);
// Check for deleted values.
if (!empty($entity->original)) {
$wrapper_old = entity_metadata_wrapper('commerce_discount', $entity->original);
$line_items = $wrapper_old->inline_conditions->value();
$old_nids = MY_MODULE_discount_get_related_discount_nids($line_items);
if (!empty($old_nids)) {
$nids = array_unique(array_merge($nids, $old_nids));
}
}
// Immediately Re-index the Nodes.
MY_MODULE_reindex_nodes($nids);
}
/**
* Get related Nids by Inline conditions.
*
* @param $inline_conditions
* @return array
*/
function MY_MODULE_discount_get_related_discount_nids($inline_conditions) {
$nids = array();
// Loop through all the inline condition and get the Node IDs.
foreach ($inline_conditions as $condition) {
// Field load is not fired here for some reason.
if (is_string($condition['condition_settings'])) {
$condition['condition_settings'] = unserialize($condition['condition_settings']);
}
// Detect by Discount type.
switch ($condition['condition_name']) {
// By direct product reference.
case 'commerce_product_contains_products':
$entity_ids = array();
foreach ($condition['condition_settings']['sku'] as $delta) {
$entity_ids[] = reset($delta);
}
// Get the referenced Node of the product.
$query = db_select('field_data_field_product', 'fp')
->fields('fp', array('entity_id'))
->condition('fp.deleted', 1, '<>')
->condition('fp.field_product_product_id', $entity_ids, 'IN');
$p_nids = $query->execute()->fetchCol();
$nids = array_merge($nids, $p_nids);
break;
// By taxonomy Term.
case 'commerce_product_has_specified_terms':
$term_ids = array();
foreach ($condition['condition_settings']['terms'] as $tid) {
$term_ids[] = $tid['target_id'];
}
// Get all the "taxonomy_term_reference" fields.
$term_reference_fields = field_read_fields(array('type' => 'taxonomy_term_reference'));
$product_bundles = array('product_type');
foreach ($term_reference_fields as $field) {
$field_table = 'field_data_' . $field['field_name'];
$field_value_column = $field['field_name'] . '_tid';
// Get the referenced Node of the product linked to the Term.
try {
$query = db_select('field_data_field_product', 'fp');
$query->innerJoin($field_table, 'ft', 'ft.entity_id=fp.field_product_product_id');
$query->fields('fp', array('entity_id'))
->condition('fp.deleted', 1, '<>')
->condition('ft.deleted', 1, '<>')
->condition('ft.entity_type', 'commerce_product')
->condition('ft.bundle', $product_bundles, 'IN')
->condition("ft.$field_value_column", $term_ids, 'IN');
$t_nids = $query->execute()->fetchCol();
if (!empty($t_nids)) {
$nids = array_merge($nids, $t_nids);
}
} catch (\Exception $e) {
// Log.
}
}
break;
}
}
return array_unique($nids);
}
/**
* Helper function.
*
* Force node Search API re-indexing.
*
* @param array $nids
*/
function MY_MODULE_reindex_nodes($nids = array()) {
if (!is_array($nids)) {
return;
}
// Clear the field cache first.
foreach ($nids as $nid) {
cache_clear_all('field:node:' . $nid, 'cache_field');
}
// Reindex the node.
search_api_track_item_change('node', $nids);
}