updated synonyms to 1.5

This commit is contained in:
Bachir Soussi Chiadmi
2016-11-05 17:54:56 +01:00
parent 773e7fbddd
commit 252abe9b0e
51 changed files with 6500 additions and 2484 deletions

View File

@@ -0,0 +1,66 @@
<?php
/**
* @file
* Enables Commerce Product Reference field type for synonyms integration.
*/
/**
* Definition of CommerceProductReferenceSynonymsBehavior class.
*/
class CommerceProductReferenceSynonymsBehavior extends AbstractFieldSynonymsBehavior {
public function extractSynonyms($entity) {
$synonyms = array();
$product_ids = array();
foreach ($this->entityItems($entity) as $item) {
$product_ids[] = $item['product_id'];
}
$entities = commerce_product_load_multiple($product_ids);
foreach ($entities as $entity) {
$synonyms[] = entity_label('commerce_product', $entity);
}
return $synonyms;
}
public function mergeEntityAsSynonym($trunk_entity, $synonym_entity, $synonym_entity_type) {
if ('commerce_product' != $synonym_entity_type) {
return;
}
$items = $this->entityItems($trunk_entity);
$synonym_entity_id = entity_extract_ids($synonym_entity_type, $synonym_entity);
$items[] = array(
'product_id' => $synonym_entity_id[0],
);
$trunk_entity->{$this->field['field_name']}[LANGUAGE_NONE] = $this->uniqueItems($items, array('product_id'));
}
public function synonymsFind(QueryConditionInterface $condition) {
if ($this->field['storage']['type'] != 'field_sql_storage') {
throw new SynonymsBehaviorException(t('Not supported storage engine %type in @method() method.', array(
'%type' => $this->field['storage']['type'],
'@method' => __METHOD__,
)));
}
$table = array_keys($this->field['storage']['details']['sql'][FIELD_LOAD_CURRENT]);
$table = reset($table);
$column = $this->field['storage']['details']['sql'][FIELD_LOAD_CURRENT][$table]['product_id'];
$query = db_select($table, 'field');
$product_entity_type_info = entity_get_info('commerce_product');
$product_entity_alias = $query->innerJoin($product_entity_type_info['base table'], 'product', 'field.' . $column . ' = %alias.' . $product_entity_type_info['entity keys']['id']);
$query->addField($product_entity_alias, $product_entity_type_info['entity keys']['label'], 'synonym');
$query->fields('field', array('entity_id'));
$query->condition('field.entity_type', $this->instance['entity_type']);
$query->condition('field.bundle', $this->instance['bundle']);
$this->synonymsFindProcessCondition($condition, $product_entity_alias . '.' . $product_entity_type_info['entity keys']['label'], 'field.entity_id');
$query->condition($condition);
return $query->execute();
}
}

View File

@@ -0,0 +1,19 @@
name = Synonyms Commerce
description = "Provides synonyms integration with Commerce."
package = Synonyms
core = 7.x
dependencies[] = synonyms_provider_field
dependencies[] = commerce_product_reference
test_dependencies[] = commerce:commerce_product_ui
files[] = synonyms_commerce.test
files[] = includes/CommerceProductReferenceSynonymsBehavior.class.inc
; Information added by Drupal.org packaging script on 2016-05-07
version = "7.x-1.5"
core = "7.x"
project = "synonyms"
datestamp = "1462586641"

View File

@@ -0,0 +1,247 @@
<?php
/**
* @file
* Provides synonyms integration with Commerce.
*/
/**
* Implements hook_menu().
*/
function synonyms_commerce_menu() {
$items = array();
$items['synonyms-commerce/autocomplete'] = array(
'title' => 'Synonyms-friendly product autocomplete widget',
'page callback' => 'synonyms_commerce_autocomplete',
'access callback' => TRUE,
'type' => MENU_CALLBACK,
'file' => 'synonyms_commerce.pages.inc',
);
return $items;
}
/**
* Implements hook_field_widget_info().
*/
function synonyms_commerce_field_widget_info() {
return array(
'synonyms_commerce_autocomplete' => array(
'label' => t('Synonyms friendly autocomplete'),
'field types' => array('commerce_product_reference'),
'settings' => array(
'size' => 60,
'synonyms_autocomplete_path' => 'synonyms-commerce/autocomplete',
'suggestion_size' => 10,
'suggest_only_unique' => FALSE,
),
'behaviors' => array(
'multiple values' => FIELD_BEHAVIOR_CUSTOM,
),
),
'synonyms_commerce_select' => array(
'label' => t('Synonyms friendly select list'),
'field types' => array('commerce_product_reference'),
'settings' => array(),
'behaviors' => array(
'multiple values' => FIELD_BEHAVIOR_CUSTOM,
),
),
);
}
/**
* Implements hook_field_widget_settings_form().
*/
function synonyms_commerce_field_widget_settings_form($field, $instance) {
$widget = $instance['widget'];
$settings = $widget['settings'] + field_info_widget_settings($widget['type']);
$form = array();
switch ($widget['type']) {
case 'synonyms_commerce_autocomplete':
$form['suggestion_size'] = array(
'#type' => 'textfield',
'#title' => t('Suggestions Size'),
'#description' => t('Please, enter how many suggested entities to show in the autocomplete textfield.'),
'#required' => TRUE,
'#element_validate' => array('element_validate_integer_positive'),
'#default_value' => $settings['suggestion_size'],
);
$form['suggest_only_unique'] = array(
'#type' => 'checkbox',
'#title' => t('Suggest only one entry per product'),
'#description' => t('If you want to include only product name or a single synonym, suggesting a particular product, while disregarding all ongoing ones, please, tick this checkbox on.'),
'#default_value' => $settings['suggest_only_unique'],
);
break;
}
return $form;
}
/**
* Implements hook_field_widget_form().
*/
function synonyms_commerce_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
$default_value = synonyms_select_default_value($field, $instance, $items);
switch ($instance['widget']['type']) {
case 'synonyms_commerce_autocomplete':
$default_value_string = array();
foreach (commerce_product_load_multiple($default_value) as $product) {
$default_value_string[] = entity_label('commerce_product', $product);
}
$default_value_string = drupal_implode_tags($default_value_string);
$element += array(
'#type' => 'textfield',
'#default_value' => $default_value_string,
'#autocomplete_path' => $instance['widget']['settings']['synonyms_autocomplete_path'] . '/' . $field['field_name'] . '/' . $instance['entity_type'] . '/' . $instance['bundle'],
'#size' => $instance['widget']['settings']['size'],
'#maxlength' => 1024,
'#element_validate' => array('synonyms_commerce_autocomplete_validate'),
'#attached' => array(
'js' => array(
drupal_get_path('module', 'synonyms') . '/js/synonyms-autocomplete.js' => array(),
),
),
'#attributes' => array(
'class' => array('synonyms-autocomplete'),
),
);
if (isset($instance['widget']['settings']['auto_creation'])) {
$element['#auto_creation'] = $instance['widget']['settings']['auto_creation'];
}
break;
case 'synonyms_commerce_select':
$multiple = $field['cardinality'] > 1 || $field['cardinality'] == FIELD_CARDINALITY_UNLIMITED;
$options = module_invoke('commerce_product_reference', 'options_list', $field, $instance);
$tmp = reset($options);
if (is_array($tmp)) {
// These options have optgroups.
foreach ($options as $k => $v) {
$options[$k] = synonyms_commerce_product_options_expand($v);
}
}
else {
$options = synonyms_commerce_product_options_expand($options);
}
$element += array(
'#type' => 'select',
'#empty_option' => t('- None -'),
'#options' => $options,
'#multiple' => $multiple,
'#element_validate' => array('synonyms_select_validate', 'synonyms_select_form_to_storage'),
'#default_value' => $default_value,
);
break;
}
return $element;
}
/**
* Implements hook_synonyms_provider_field_behavior_implementation_info().
*/
function synonyms_commerce_synonyms_provider_field_behavior_implementation_info($behavior) {
switch ($behavior) {
case 'select':
case 'autocomplete':
return array(
'commerce_product_reference' => 'CommerceProductReferenceSynonymsBehavior',
);
break;
}
return array();
}
/**
* Expand the options for commerce product select widget with synonyms.
*
* @param array $options
* Array of commerce product reference widget options that should be expanded
* with synonyms
*
* @return array
* Expanded with synonyms version of the provided $options
*/
function synonyms_commerce_product_options_expand($options) {
$synonyms_options = array();
$behavior_implementations = array();
foreach (commerce_product_load_multiple(array_keys($options)) as $product) {
if (!isset($behavior_implementations[$product->type])) {
$behavior_implementations[$product->type] = synonyms_behavior_get('select', 'commerce_product', $product->type, TRUE);
}
$synonyms_options[] = synonyms_select_option_entity($product, 'commerce_product');
foreach ($behavior_implementations[$product->type] as $behavior_implementation) {
foreach ($behavior_implementation['object']->extractSynonyms($product) as $synonym) {
$synonyms_options[] = synonyms_select_option_entity($product, $behavior_implementation['entity_type'], $synonym, $behavior_implementation);
}
}
}
usort($synonyms_options , 'synonyms_select_sort_name');
return $synonyms_options;
}
/**
* Element validate for commerce product synonyms friendly autocomplete widget.
*/
function synonyms_commerce_autocomplete_validate($element, &$form_state) {
$input = drupal_map_assoc(drupal_explode_tags(drupal_strtolower($element['#value'])));
$value = array();
$field = field_info_field($element['#field_name']);
$instance = field_info_instance($element['#entity_type'], $field['field_name'], $element['#bundle']);
if (!empty($input)) {
$target_bundles = synonyms_bundle_normalize('commerce_product', array_filter($instance['settings']['referenceable_types']));
$efq = new EntityFieldQuery();
$efq->entityCondition('entity_type', 'commerce_product');
$efq->entityCondition('bundle', $target_bundles);
$efq->propertyCondition('title', $input, 'IN');
$result = $efq->execute();
if (isset($result['commerce_product'])) {
foreach (commerce_product_load_multiple(array_keys($result['commerce_product'])) as $product) {
$label = drupal_strtolower(entity_label('commerce_product', $product));
unset($input[$label]);
$entity_id = entity_extract_ids('commerce_product', $product);
$value[] = $entity_id[0];
}
}
if (!empty($input)) {
$behavior_implementations = synonyms_behavior_get('autocomplete', 'commerce_product', $target_bundles, TRUE);
foreach ($behavior_implementations as $implementation) {
$condition = db_and();
$condition->condition(AbstractSynonymsBehavior::COLUMN_SYNONYM_PLACEHOLDER, $input, 'IN');
foreach ($implementation['object']->synonymsFind($condition) as $synonym) {
$value[] = $synonym->entity_id;
unset($input[drupal_strtolower($synonym->synonym)]);
if (empty($input)) {
break(2);
}
}
}
}
}
$tmp = array_unique($value);
$value = array();
$column = array_keys($field['columns']);
$column = reset($column);
foreach ($tmp as $target_id) {
$value[] = array($column => $target_id);
}
form_set_value($element, $value, $form_state);
}

View File

@@ -0,0 +1,128 @@
<?php
/**
* @file
* Menu page callbacks of the module.
*/
/**
* Menu page callback for synonyms commerce autocomplete widget.
*/
function synonyms_commerce_autocomplete($field_name, $entity_type, $bundle) {
// If the request has a '/' in the search text, then the menu system will have
// split it into multiple arguments, recover the intended $tags_typed.
$args = func_get_args();
// Shift off the $field_name argument.
array_shift($args);
// Shift off the $entity_type argument.
array_shift($args);
// Shift off the $bundle argument.
array_shift($args);
$tags_typed = implode('/', $args);
if (!($field = field_info_field($field_name)) || $field['type'] != 'commerce_product_reference') {
print t('Commerce product reference field @field_name not found.', array('@field_name' => $field_name));
exit;
}
if (!($instance = field_info_instance($entity_type, $field['field_name'], $bundle))) {
// Error string. The JavaScript handler will realize this is not JSON and
// will display it as debugging information.
print t('There was not found an instance of @field_name in @entity_type.', array(
'@field_name' => $field_name,
'@entity_type' => $entity_type,
));
exit;
}
module_load_include('inc', 'synonyms', 'synonyms.pages');
$widget = $instance['widget']['type'] == 'synonyms_commerce_autocomplete' ? $instance['widget']['settings'] : field_info_widget_settings('synonyms_commerce_autocomplete');
// How many suggestions maximum we are able to output.
$max_suggestions = $widget['suggestion_size'];
// Whether we are allowed to suggest more than one entry per term, shall that
// entry be either term name itself or one of its synonyms.
$suggest_only_unique = $widget['suggest_only_unique'];
$tags_typed = drupal_explode_tags($tags_typed);
$tag_last = drupal_strtolower(array_pop($tags_typed));
$prefix = count($tags_typed) ? drupal_implode_tags($tags_typed) . ', ' : '';
$matches = array();
if ($tag_last) {
$tags_typed_entity_ids = array();
if (!empty($tags_typed)) {
foreach (commerce_product_load_multiple(array(), array('title' => $tags_typed)) as $product) {
$product_ids = entity_extract_ids('commerce_product', $product);
$tags_typed_entity_ids[] = $product_ids[0];
}
}
$new_target_ids = array();
foreach (commerce_product_match_products($field, $instance, $tag_last, 'contains', array(), $max_suggestions) as $product) {
$product = commerce_product_load_by_sku($product['sku']);
$product_id = entity_extract_ids('commerce_product', $product);
$product_id = $product_id[0];
if (!in_array($product_id, $tags_typed_entity_ids)) {
$matches[] = array(
'name' => entity_label('commerce_product', $product),
);
$new_target_ids[] = $product_id;
}
}
if (count($matches) < $max_suggestions) {
$target_bundles = synonyms_bundle_normalize('commerce_product', array_filter($instance['settings']['referenceable_types']));
$behavior_implementations = synonyms_behavior_get('autocomplete', 'commerce_product', $target_bundles, TRUE);
foreach ($behavior_implementations as $implementation) {
$condition = db_and();
$condition->condition(AbstractSynonymsBehavior::COLUMN_SYNONYM_PLACEHOLDER, '%' . db_like($tag_last) . '%', 'LIKE');
if (!empty($tags_typed_entity_ids)) {
$condition->condition(AbstractSynonymsBehavior::COLUMN_ENTITY_ID_PLACEHOLDER, $tags_typed_entity_ids, 'NOT IN');
}
if ($suggest_only_unique && !empty($new_target_ids)) {
$condition->condition(AbstractSynonymsBehavior::COLUMN_ENTITY_ID_PLACEHOLDER, $new_target_ids, 'NOT IN');
}
foreach ($implementation['object']->synonymsFind($condition) as $synonym) {
if (!$suggest_only_unique || !in_array($synonym->entity_id, $new_target_ids)) {
$matches[] = array(
'target_id' => $synonym->entity_id,
'synonym' => $synonym->synonym,
'behavior_implementation' => $implementation,
);
$new_target_ids[] = $synonym->entity_id;
if (count($matches) == $max_suggestions) {
break (2);
}
}
}
}
}
$synonym_entities = array();
foreach ($matches as $match) {
if (!isset($match['wording']) && isset($match['synonym'])) {
$synonym_entities[] = $match['target_id'];
}
}
if (!empty($synonym_entities)) {
$synonym_entities = commerce_product_load_multiple($synonym_entities);
foreach ($matches as $k => $match) {
if (!isset($match['name']) && isset($match['synonym'])) {
$matches[$k]['name'] = entity_label('commerce_product', $synonym_entities[$match['target_id']]);
}
}
$matches = array_values($matches);
}
}
drupal_json_output(synonyms_autocomplete_format($matches, $prefix));
}

View File

@@ -0,0 +1,849 @@
<?php
/**
* @file
* Tests for the Synonyms Commerce module.
*/
/**
* Test synonyms autocomplete widget for commerce product reference field type.
*/
class CommerceProductReferenceAutocompleteSynonymsWebTestCase extends AbstractAutocompleteSynonymsWebTestCase {
/**
* GetInfo method.
*/
public static function getInfo() {
return array(
'name' => 'Commerce product reference synonyms autocomplete',
'description' => 'Ensure that the "synonym friendly autocomplete" widget works correctly with commerce product reference field type.',
'group' => 'Synonyms',
);
}
public function setUp($modules = array()) {
$modules[] = 'commerce_product_reference';
$modules[] = 'commerce_product_ui';
$modules[] = 'synonyms_commerce';
$this->fields['enabled']['instance']['entity_type'] = 'commerce_product';
$this->fields['enabled']['instance']['bundle'] = 'product';
$this->fields['disabled']['instance']['entity_type'] = 'commerce_product';
$this->fields['disabled']['instance']['bundle'] = 'product';
$this->behavior_implementation['entity_type'] = $this->fields['enabled']['instance']['entity_type'];
parent::setUp($modules);
$this->reference_field = array(
'type' => 'commerce_product_reference',
'field_name' => 'synonyms_commerce',
'cardinality' => FIELD_CARDINALITY_UNLIMITED,
'settings' => array(),
);
$this->reference_field = field_create_field($this->reference_field);
$this->reference_instance = array(
'field_name' => $this->reference_field['field_name'],
'entity_type' => $this->entity_type,
'bundle' => $this->bundle,
'label' => 'Synonym Commerce Autocomplete',
'settings' => array(
'referenceable_types' => drupal_map_assoc(array('product')),
),
'widget' => array(
'type' => 'synonyms_commerce_autocomplete',
),
);
$this->reference_instance = field_create_instance($this->reference_instance);
$this->reference_instance = field_info_instance($this->reference_instance['entity_type'], $this->reference_instance['field_name'], $this->reference_instance['bundle']);
}
protected function createTerms() {
$name = $this->randomName();
$product = (object) array(
'type' => 'product',
'title' => $name,
'sku' => 'a' . drupal_strtolower($this->randomName()),
$this->fields['disabled']['field']['field_name'] => array(
LANGUAGE_NONE => array(
array('value' => $this->randomName()),
),
),
);
commerce_product_save($product);
$this->terms['term1'] = $product;
$name .= $this->randomName();
$product = (object) array(
'type' => 'product',
'title' => $name,
'sku' => 'z' . drupal_strtolower($this->randomName()),
$this->fields['disabled']['field']['field_name'] => array(
LANGUAGE_NONE => array(
array('value' => $this->randomName()),
),
),
);
commerce_product_save($product);
$this->terms['term1_longer_name'] = $product;
$product = (object) array(
'type' => 'product',
'title' => $this->randomName(),
'sku' => drupal_strtolower($this->randomName()),
$this->fields['disabled']['field']['field_name'] => array(
LANGUAGE_NONE => array(
array('value' => $this->randomName()),
),
),
);
commerce_product_save($product);
$this->terms['no_synonyms'] = $product;
$product = (object) array(
'type' => 'product',
'title' => $this->randomName(),
'sku' => drupal_strtolower($this->randomName()),
$this->fields['enabled']['field']['field_name'] => array(
LANGUAGE_NONE => array(
array('value' => $this->randomName()),
),
),
$this->fields['disabled']['field']['field_name'] => array(
LANGUAGE_NONE => array(
array('value' => $this->randomName()),
),
),
);
commerce_product_save($product);
$this->terms['one_synonym'] = $product;
$product = (object) array(
'type' => 'product',
'title' => $this->randomName(),
'sku' => drupal_strtolower($this->randomName()),
$this->fields['enabled']['field']['field_name'] => array(
LANGUAGE_NONE => array(
array('value' => $this->randomName()),
array('value' => $this->randomName()),
),
),
$this->fields['disabled']['field']['field_name'] => array(
LANGUAGE_NONE => array(
array('value' => $this->randomName()),
),
),
);
commerce_product_save($product);
$this->terms['two_synonyms'] = $product;
$name = $this->randomName();
$product = (object) array(
'type' => 'product',
'title' => $name,
'sku' => drupal_strtolower($this->randomName()),
$this->fields['enabled']['field']['field_name'] => array(
LANGUAGE_NONE => array(
array('value' => $name . $this->randomName()),
),
),
$this->fields['disabled']['field']['field_name'] => array(
LANGUAGE_NONE => array(
array('value' => $this->randomName()),
),
),
);
commerce_product_save($product);
$this->terms['name_similar_synonym'] = $product;
$name = 'similar_synonyms_';
$product = (object) array(
'type' => 'product',
'title' => $this->randomName(),
'sku' => drupal_strtolower($this->randomName()),
$this->fields['enabled']['field']['field_name'] => array(
LANGUAGE_NONE => array(
array('value' => $name . $this->randomName()),
array('value' => $name . $this->randomName()),
),
),
$this->fields['disabled']['field']['field_name'] => array(
LANGUAGE_NONE => array(
array('value' => $this->randomName()),
),
),
);
commerce_product_save($product);
$this->terms['similar_synonyms'] = $product;
$name = 'one_term_name_another_synonym_';
$product = (object) array(
'type' => 'product',
'title' => $name . $this->randomName(),
'sku' => drupal_strtolower($this->randomName()),
$this->fields['disabled']['field']['field_name'] => array(
LANGUAGE_NONE => array(
array('value' => $this->randomName()),
),
),
);
commerce_product_save($product);
$this->terms['name_another_synonym'] = $product;
$product = (object) array(
'type' => 'product',
'title' => $this->randomName(),
'sku' => drupal_strtolower($this->randomName()),
$this->fields['enabled']['field']['field_name'] => array(
LANGUAGE_NONE => array(
array('value' => $name . $this->randomName()),
),
),
$this->fields['disabled']['field']['field_name'] => array(
LANGUAGE_NONE => array(
array('value' => $this->randomName()),
),
),
);
commerce_product_save($product);
$this->terms['synonym_another_name'] = $product;
$another_product_type = commerce_product_ui_product_type_new();
$another_product_type['type'] = 'another_vocabulary';
$another_product_type['name'] = $this->randomName();
commerce_product_ui_product_type_save($another_product_type);
$product_similar_product = (object) array(
'type' => $another_product_type['type'],
'title' => $this->entityLabel($this->terms['no_synonyms']),
'sku' => drupal_strtolower($this->randomName()),
);
commerce_product_save($product_similar_product);
$product_similar_synonym = (object) array(
'type' => $another_product_type['type'],
'title' => $this->terms['one_synonym']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
'sku' => drupal_strtolower($this->randomName()),
);
commerce_product_save($product_similar_synonym);
$synonym_similar_product = (object) array(
'type' => $another_product_type['type'],
'title' => $this->randomName(),
'sku' => drupal_strtolower($this->randomName()),
$this->fields['enabled']['field']['field_name'] => array(LANGUAGE_NONE => array(
$this->entityLabel($this->terms['no_synonyms']),
)),
);
commerce_product_save($synonym_similar_product);
$synonym_similar_synonym = (object) array(
'type' => $another_product_type['type'],
'title' => $this->randomName(),
'sku' => drupal_strtolower($this->randomName()),
$this->fields['enabled']['field']['field_name'] => array(LANGUAGE_NONE => array(
$this->terms['one_synonym']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
)),
);
commerce_product_save($synonym_similar_synonym);
}
}
/**
* Test synonyms-friendly select widget for commerce product reference field.
*/
class CommerceProductReferenceSelectSynonymsWebTestCase extends AbstractSelectSynonymsWebTestCase {
/**
* Array of products on which the testing is held.
*
* @var array
*/
protected $products = array();
public static function getInfo() {
return array(
'name' => 'Commerce product reference synonyms select',
'description' => 'Ensure that the "synonym friendly select" widget works correctly with commerce product reference field.',
'group' => 'Synonyms',
);
}
public function setUp($modules = array()) {
$modules[] = 'commerce_product_reference';
$modules[] = 'synonyms_commerce';
$this->fields['enabled']['instance']['entity_type'] = 'commerce_product';
$this->fields['enabled']['instance']['bundle'] = 'product';
$this->fields['disabled']['instance']['entity_type'] = 'commerce_product';
$this->fields['disabled']['instance']['bundle'] = 'product';
$this->behavior_implementation['entity_type'] = $this->fields['enabled']['instance']['entity_type'];
parent::setUp($modules);
$this->reference_field = array(
'type' => 'commerce_product_reference',
'field_name' => 'synonyms_commerce',
'cardinality' => FIELD_CARDINALITY_UNLIMITED,
'settings' => array(),
);
$this->reference_field = field_create_field($this->reference_field);
$this->reference_instance = array(
'field_name' => $this->reference_field['field_name'],
'entity_type' => $this->entity_type,
'bundle' => $this->bundle,
'label' => 'Synonym Commerce Select',
'widget' => array(
'type' => 'synonyms_commerce_select',
),
);
$this->reference_instance = field_create_instance($this->reference_instance);
}
public function testWidgetSorting() {
$cardinality = array(
1 => 1,
FIELD_CARDINALITY_UNLIMITED => 'unlimited',
);
$required = array(
TRUE => 'required',
FALSE => 'not required',
);
foreach ($cardinality as $cardinality_k => $cardinality_v) {
foreach ($required as $required_k => $required_v) {
$this->reference_field['cardinality'] = $cardinality_k;
field_update_field($this->reference_field);
$this->reference_instance['required'] = $required_k;
field_update_instance($this->reference_instance);
$options = array();
$options[] = array(
'entity' => $this->terms['product3'],
'synonym' => $this->terms['product3']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
);
$options[] = array(
'entity' => $this->terms['product3'],
'synonym' => $this->terms['product3']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
);
$options[] = array(
'entity' => $this->terms['product1'],
);
$options[] = array(
'entity' => $this->terms['product1'],
'synonym' => $this->terms['product1']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
);
$options[] = array(
'entity' => $this->terms['product1'],
'synonym' => $this->terms['product1']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
);
$options[] = array(
'entity' => $this->terms['product2'],
);
$options[] = array(
'entity' => $this->terms['product2'],
'synonym' => $this->terms['product2']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
);
$options[] = array(
'entity' => $this->terms['product2'],
'synonym' => $this->terms['product2']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
);
$options[] = array(
'entity' => $this->terms['product3'],
);
$this->drupalGet('node/add/synonyms-test-content');
$this->assertSynonymsSelect($options, 'Synonyms select sorting by name works for the cardinality of ' . $cardinality_v . ' and ' . $required_v);
}
}
}
public function testWidget() {
$name = $this->randomName();
$this->drupalPost('node/add/synonyms-test-content', array(
'title' => $name,
$this->reference_field['field_name'] . '[' . LANGUAGE_NONE . '][]' => array(
$this->synonymSelectKey($this->terms['product1'], $this->terms['product1']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value']),
$this->terms['product2']->product_id,
$this->terms['product3']->product_id,
$this->synonymSelectKey($this->terms['product3'], $this->terms['product3']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value']),
),
), 'Save');
$node = $this->drupalGetNodeByTitle($name);
$this->drupalGet('node/' . $node->nid);
$this->assertText($this->terms['product1']->title, 'Product is saved when its synonym is submitted through synonyms friendly select for the unlimited cardinality.');
$this->assertText($this->terms['product2']->title, 'Product is saved when it is submitted through synonyms friendly select for the unlimited cardinality.');
$this->assertText($this->terms['product3']->title, 'Product is saved only once when the term and its synonym are submitted through synonyms friendly select for the unlimited cardinality.');
$options = array();
$options[] = array(
'entity' => $this->terms['product3'],
'synonym' => $this->terms['product3']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
);
$options[] = array(
'entity' => $this->terms['product3'],
'synonym' => $this->terms['product3']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
);
$options[] = array(
'entity' => $this->terms['product1'],
'selected' => TRUE,
);
$options[] = array(
'entity' => $this->terms['product1'],
'synonym' => $this->terms['product1']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
);
$options[] = array(
'entity' => $this->terms['product1'],
'synonym' => $this->terms['product1']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
);
$options[] = array(
'entity' => $this->terms['product2'],
'selected' => TRUE,
);
$options[] = array(
'entity' => $this->terms['product2'],
'synonym' => $this->terms['product2']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
);
$options[] = array(
'entity' => $this->terms['product2'],
'synonym' => $this->terms['product2']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
);
$options[] = array(
'entity' => $this->terms['product3'],
'selected' => TRUE,
);
$this->drupalGet('node/' . $node->nid . '/edit');
$this->assertSynonymsSelect($options, 'Default values are set correctly in the synonyms friendly select widget when working with field cardinality more than 1.');
$this->reference_field['cardinality'] = 2;
field_update_field($this->reference_field);
$name = $this->randomName();
$this->drupalPost('node/add/synonyms-test-content', array(
'title' => $name,
$this->reference_field['field_name'] . '[' . LANGUAGE_NONE . '][]' => array(
$this->synonymSelectKey($this->terms['product1'], $this->terms['product1']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value']),
$this->terms['product2']->product_id,
$this->terms['product3']->product_id,
),
), 'Save');
$this->assertText('this field cannot hold more than 2 values.', 'Submitting 3 entries into a field with cardinality of 2, that refer to 3 products, results in a form error.');
$this->drupalPost('node/add/synonyms-test-content', array(
'title' => $name,
$this->reference_field['field_name'] . '[' . LANGUAGE_NONE . '][]' => array(
$this->synonymSelectKey($this->terms['product1'], $this->terms['product1']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value']),
$this->terms['product2']->product_id,
$this->synonymSelectKey($this->terms['product2'], $this->terms['product2']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value']),
),
), 'Save');
$node = $this->drupalGetNodeByTitle($name);
$this->drupalGet('node/' . $node->nid);
$this->assertText($this->terms['product1']->title, 'Submitting 3 entries into a field with cardinality of 2, that refer to only 2 products, results in form getting submitted. Product #1 is saved.');
$this->assertText($this->terms['product2']->title, 'Product #2 is saved.');
$this->reference_field['cardinality'] = 1;
field_update_field($this->reference_field);
// We need to invoke this one. Without it some caching within Entity
// metadata wrappers interferes. See https://www.drupal.org/node/2717019 for
// details.
entity_flush_caches();
$name = $this->randomName();
$this->drupalPost('node/add/synonyms-test-content', array(
'title' => $name,
$this->reference_field['field_name'] . '[' . LANGUAGE_NONE . ']' => $this->synonymSelectKey($this->terms['product1'], $this->terms['product1']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value']),
), 'Save');
$node = $this->drupalGetNodeByTitle($name);
$this->drupalGet('node/' . $node->nid);
$this->assertText($this->terms['product1']->title, 'Product is saved when its synonym is submitted through synonyms friendly select for the cardinality of 1.');
$options = array();
$options[] = array(
'entity' => $this->terms['product3'],
'synonym' => $this->terms['product3']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
);
$options[] = array(
'entity' => $this->terms['product3'],
'synonym' => $this->terms['product3']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
);
$options[] = array(
'entity' => $this->terms['product1'],
'selected' => TRUE,
);
$options[] = array(
'entity' => $this->terms['product1'],
'synonym' => $this->terms['product1']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
);
$options[] = array(
'entity' => $this->terms['product1'],
'synonym' => $this->terms['product1']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
);
$options[] = array(
'entity' => $this->terms['product2'],
);
$options[] = array(
'entity' => $this->terms['product2'],
'synonym' => $this->terms['product2']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
);
$options[] = array(
'entity' => $this->terms['product2'],
'synonym' => $this->terms['product2']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
);
$options[] = array(
'entity' => $this->terms['product3'],
);
$this->drupalGet('node/' . $node->nid . '/edit');
$this->assertSynonymsSelect($options, 'Default values are set correctly in the synonyms friendly select widget when working with the field cardinality of 1.');
$this->drupalPost('node/' . $node->nid . '/edit', array(
$this->reference_field['field_name'] . '[' . LANGUAGE_NONE . ']' => $this->terms['product2']->product_id,
), 'Save');
$this->drupalGet('node/' . $node->nid);
$this->assertNoText($this->terms['product1']->title, 'After updating entity the old product is removed.');
$this->assertText($this->terms['product2']->title, 'Product is saved when it is submitted through synonyms friendly select for the cardinality of 1.');
$options = array();
$options[] = array(
'entity' => $this->terms['product3'],
'synonym' => $this->terms['product3']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
);
$options[] = array(
'entity' => $this->terms['product3'],
'synonym' => $this->terms['product3']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
);
$options[] = array(
'entity' => $this->terms['product1'],
);
$options[] = array(
'entity' => $this->terms['product1'],
'synonym' => $this->terms['product1']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
);
$options[] = array(
'entity' => $this->terms['product1'],
'synonym' => $this->terms['product1']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
);
$options[] = array(
'entity' => $this->terms['product2'],
'selected' => TRUE,
);
$options[] = array(
'entity' => $this->terms['product2'],
'synonym' => $this->terms['product2']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][1]['value'],
);
$options[] = array(
'entity' => $this->terms['product2'],
'synonym' => $this->terms['product2']->{$this->fields['enabled']['field']['field_name']}[LANGUAGE_NONE][0]['value'],
);
$options[] = array(
'entity' => $this->terms['product3'],
);
$this->drupalGet('node/' . $node->nid . '/edit');
$this->assertSynonymsSelect($options, 'Default values are set correctly in the synonyms friendly select widget when working with the field cardinality of 1.');
}
protected function createTerms() {
$this->terms['product1'] = (object) array(
'type' => $this->behavior_implementation['bundle'],
'title' => 'Product 1',
'sku' => drupal_strtolower($this->randomName()),
$this->fields['enabled']['field']['field_name'] => array(
LANGUAGE_NONE => array(
array('value' => 'Product 1A' . $this->randomName()),
array('value' => 'Product 1Z' . $this->randomName()),
),
),
);
commerce_product_save($this->terms['product1']);
$this->terms['product2'] = (object) array(
'type' => $this->behavior_implementation['bundle'],
'title' => 'Product 2',
'sku' => drupal_strtolower($this->randomName()),
$this->fields['enabled']['field']['field_name'] => array(
LANGUAGE_NONE => array(
array('value' => 'Product 2Z' . $this->randomName()),
array('value' => 'Product 2A' . $this->randomName()),
),
),
);
commerce_product_save($this->terms['product2']);
$this->terms['product3'] = (object) array(
'type' => $this->behavior_implementation['bundle'],
'title' => 'Product 3',
'sku' => drupal_strtolower($this->randomName()),
$this->fields['enabled']['field']['field_name'] => array(
LANGUAGE_NONE => array(
array('value' => 'Another Product 3A' . $this->randomName()),
array('value' => 'Another Product 3Z' . $this->randomName()),
),
),
);
commerce_product_save($this->terms['product3']);
}
}
/**
* Test CommerceProductReferenceSynonymsBehavior class.
*/
class CommerceProductReferenceSynonymsBehaviorWebTestCase extends AbstractSynonymsProviderFieldWebTestCase {
/**
* GetInfo method.
*/
public static function getInfo() {
return array(
'name' => 'CommerceProductReferenceSynonymsBehavior',
'description' => 'Ensure that the synonyms module extracts synonyms from commerce product reference fields correctly.',
'group' => 'Synonyms',
);
}
/**
* SetUp method.
*/
public function setUp($modules = array()) {
$modules[] = 'commerce_product_reference';
$modules[] = 'commerce_product_ui';
$modules[] = 'synonyms_commerce';
$this->fields['enabled']['field'] = array(
'field_name' => 'reference',
'cardinality' => FIELD_CARDINALITY_UNLIMITED,
'type' => 'commerce_product_reference',
);
parent::setUp($modules);
}
/**
* Test synonyms extraction for 'commerce_product_reference' field type.
*/
public function testCommerceProductReference() {
// Testing synonymsExtract().
$this->assertSynonymsExtract(array(), array(), 'on empty field.');
$synonym_entity = $this->createProduct();
$this->assertSynonymsExtract(array(
LANGUAGE_NONE => array(
0 => array(
'product_id' => entity_id('commerce_product', $synonym_entity),
),
),
), array(entity_label('commerce_product', $synonym_entity)), 'on a field that holds one value.');
// Testing mergeEntityAsSynonym() method.
$product = $this->createProduct();
$this->assertMergeEntityAsSynonym(array(), $product, 'commerce_product', array(array('product_id' => $product->product_id)), 'on a product.');
// Testing synonymFind() method.
$this->assertSynonymsFind(array(), db_and()->condition(AbstractSynonymsBehavior::COLUMN_SYNONYM_PLACEHOLDER, $this->randomName()), 'on empty field');
$meta_data = array();
$meta_data[] = array(
'items' => array(),
'found_synonyms' => array(),
);
$this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsBehavior::COLUMN_SYNONYM_PLACEHOLDER, $this->randomName()), 'on a field without values');
$meta_data = array();
$meta_data[] = array(
'items' => array(
LANGUAGE_NONE => array(
array('product_id' => entity_id('commerce_product', $this->createProduct())),
),
),
'found_synonyms' => array(),
);
$this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsBehavior::COLUMN_SYNONYM_PLACEHOLDER, $this->randomName()), 'on a field with a value but searching for another string');
$meta_data = array();
$synonym_entity = $this->createProduct();
$meta_data[] = array(
'items' => array(
LANGUAGE_NONE => array(
array('product_id' => entity_id('commerce_product', $synonym_entity)),
),
),
'found_synonyms' => array(entity_label('commerce_product', $synonym_entity)),
);
$this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsBehavior::COLUMN_SYNONYM_PLACEHOLDER, entity_label('commerce_product', $synonym_entity)), 'on a field with a single value searching for that string');
$meta_data = array();
$synonym_entity = $this->createProduct();
$meta_data[] = array(
'items' => array(
LANGUAGE_NONE => array(
array('product_id' => entity_id('commerce_product', $synonym_entity)),
array('product_id' => entity_id('commerce_product', $this->createProduct())),
),
),
'found_synonyms' => array(entity_label('commerce_product', $synonym_entity)),
);
$this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsBehavior::COLUMN_SYNONYM_PLACEHOLDER, entity_label('commerce_product', $synonym_entity)), 'on a field with 2 values searching for one of those 2 values');
$meta_data = array();
$synonym_entity = $this->createProduct();
$meta_data[] = array(
'items' => array(
LANGUAGE_NONE => array(
array('product_id' => entity_id('commerce_product', $synonym_entity)),
array('product_id' => entity_id('commerce_product', $this->createProduct())),
),
),
'found_synonyms' => array(entity_label('commerce_product', $synonym_entity)),
);
$meta_data[] = array(
'items' => array(
LANGUAGE_NONE => array(
array('product_id' => entity_id('commerce_product', $this->createProduct())),
array('product_id' => entity_id('commerce_product', $this->createProduct())),
),
),
'found_synonyms' => array(),
);
$this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsBehavior::COLUMN_SYNONYM_PLACEHOLDER, entity_label('commerce_product', $synonym_entity)), 'on 2 fields with 2 values each searching for one of those values');
$meta_data = array();
$synonym_entity = $this->createProduct();
$meta_data[] = array(
'items' => array(
LANGUAGE_NONE => array(
array('product_id' => entity_id('commerce_product', $synonym_entity)),
),
),
'found_synonyms' => array(entity_label('commerce_product', $synonym_entity)),
);
$this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsBehavior::COLUMN_SYNONYM_PLACEHOLDER, '%' . db_like(drupal_substr(entity_label('commerce_product', $synonym_entity), 1, -1)) . '%', 'LIKE'), 'on a field with a value searching for a string LIKE the %value%');
$meta_data = array();
$tag = $this->randomName();
$synonym_entity1 = $this->createProduct($tag . $this->randomName());
$synonym_entity2 = $this->createProduct($tag . $this->randomName());
$meta_data[] = array(
'items' => array(
LANGUAGE_NONE => array(
array('product_id' => entity_id('commerce_product', $synonym_entity1)),
array('product_id' => entity_id('commerce_product', $synonym_entity2)),
),
),
'found_synonyms' => array(
entity_label('commerce_product', $synonym_entity1),
entity_label('commerce_product', $synonym_entity2),
),
);
$this->assertSynonymsFind($meta_data, db_and()->condition(AbstractSynonymsBehavior::COLUMN_SYNONYM_PLACEHOLDER, db_like($tag) . '%', 'LIKE'), 'on a field with 2 similar values searching a string like %both values%');
$meta_data = array();
$synonym_entity1 = $this->createProduct();
$synonym_entity2 = $this->createProduct();
$meta_data[] = array(
'items' => array(
LANGUAGE_NONE => array(
array('product_id' => entity_id('commerce_product', $synonym_entity1)),
array('product_id' => entity_id('commerce_product', $synonym_entity2)),
),
),
'found_synonyms' => array(
entity_label('commerce_product', $synonym_entity1),
entity_label('commerce_product', $synonym_entity2),
),
);
$condition = db_or()
->condition(AbstractSynonymsBehavior::COLUMN_SYNONYM_PLACEHOLDER, entity_label('commerce_product', $synonym_entity1))
->condition(AbstractSynonymsBehavior::COLUMN_SYNONYM_PLACEHOLDER, entity_label('commerce_product', $synonym_entity2));
$this->assertSynonymsFind($meta_data, $condition, 'on a field with 2 values searching for value1 or value2');
$meta_data = array();
$synonym_entity = $this->createProduct();
$meta_data[] = array(
'items' => array(
LANGUAGE_NONE => array(
array('product_id' => entity_id('commerce_product', $synonym_entity)),
array('product_id' => entity_id('commerce_product', $this->createProduct())),
),
),
'found_synonyms' => array(entity_label('commerce_product', $synonym_entity)),
);
$condition = db_and()
->condition(AbstractSynonymsBehavior::COLUMN_SYNONYM_PLACEHOLDER, entity_label('commerce_product', $synonym_entity))
->condition(AbstractSynonymsBehavior::COLUMN_SYNONYM_PLACEHOLDER, '%' . db_like(drupal_substr(entity_label('commerce_product', $synonym_entity), 1, -1)) . '%', 'LIKE');
$this->assertSynonymsFind($meta_data, $condition, 'on a field with 2 values searching for value1 and LIKE value1%');
$meta_data = array();
$synonym_entity1 = $this->createProduct();
$synonym_entity2 = $this->createProduct();
$meta_data[] = array(
'items' => array(
LANGUAGE_NONE => array(
array('product_id' => entity_id('commerce_product', $synonym_entity1)),
array('product_id' => entity_id('commerce_product', $synonym_entity2)),
),
),
'found_synonyms' => array(
entity_label('commerce_product', $synonym_entity1),
entity_label('commerce_product', $synonym_entity2),
),
);
$condition = db_or()
->condition(AbstractSynonymsBehavior::COLUMN_SYNONYM_PLACEHOLDER, entity_label('commerce_product', $synonym_entity1))
->condition(db_and()->condition(AbstractSynonymsBehavior::COLUMN_SYNONYM_PLACEHOLDER, entity_label('commerce_product', $synonym_entity2))->condition(AbstractSynonymsBehavior::COLUMN_SYNONYM_PLACEHOLDER, '%' . db_like(drupal_substr(entity_label('commerce_product', $synonym_entity2), 1, -1)) . '%', 'LIKE'));
$this->assertSynonymsFind($meta_data, $condition, 'on a field with 2 values searching for (value1 or (value2 AND value2%))');
$meta_data = array();
$synonym_entity1 = $this->createProduct($this->randomName() . ' ' . $this->randomName() . ' ' . $this->randomName());
$synonym_entity2 = $this->createProduct(str_replace(' ', '-', entity_label('commerce_product', $synonym_entity1)));
$meta_data[] = array(
'items' => array(
LANGUAGE_NONE => array(
array('product_id' => entity_id('commerce_product', $synonym_entity1)),
array('product_id' => entity_id('commerce_product', $synonym_entity2)),
),
),
'found_synonyms' => array(
entity_label('commerce_product', $synonym_entity1),
entity_label('commerce_product', $synonym_entity2),
),
);
$condition = db_and()
->where("REPLACE(" . AbstractSynonymsBehavior::COLUMN_SYNONYM_PLACEHOLDER . ", ' ', '-') = :synonym", array(
':synonym' => entity_label('commerce_product', $synonym_entity2),
));
$this->assertSynonymsFind($meta_data, $condition, "on a field with 2 values, where 2nd value replaces spaces with dashes in the 1st value, searching for REPLACE(column, ' ', '-') = value2");
}
/**
* Supportive function.
*
* Create an entity of necessary entity type (in our test it's commerce
* product).
*
* @param string $label
* Label to use for the entity that is about to be created
* @param string $bundle
* Bundle to use for the entity that is about to be created
*
* @return object
* Fully loaded entity object of the just created entity
*/
protected function createProduct($label = NULL, $bundle = 'product') {
if (is_null($label)) {
$label = $this->randomName();
}
$entity = commerce_product_new($bundle);
$entity->title = $label;
$entity->sku = drupal_html_id($label);
commerce_product_save($entity);
return $entity;
}
}