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

@@ -1,84 +0,0 @@
<?php
/**
* @file
* Enables Entity Reference field type to be source of synonyms.
*/
/**
* Definition of EntityReferenceSynonymsBehavior class.
*/
class EntityReferenceSynonymsBehavior extends AbstractSynonymsSynonymsBehavior implements SynonymsSynonymsBehavior, AutocompleteSynonymsBehavior, SelectSynonymsBehavior {
public function extractSynonyms($items, $field, $instance, $entity, $entity_type) {
$synonyms = array();
$target_tids = array();
foreach ($items as $item) {
$target_tids[] = $item['target_id'];
}
$entities = entity_load($field['settings']['target_type'], $target_tids);
foreach ($entities as $entity) {
$synonyms[] = entity_label($field['settings']['target_type'], $entity);
}
return $synonyms;
}
public function mergeEntityAsSynonym($items, $field, $instance, $synonym_entity, $synonym_entity_type) {
// Firstly validating that this entity reference is able to reference to
// that type of entity.
$expected_synonym_entity_type = $field['settings']['target_type'];
if ($expected_synonym_entity_type != $synonym_entity_type) {
return array();
}
$synonym_entity_id = entity_id($synonym_entity_type, $synonym_entity);
return array(array(
'target_id' => $synonym_entity_id,
));
}
public function synonymItemHash($item, $field, $instance) {
return $field['settings']['target_type'] . $item['target_id'];
}
public function synonymsFind(QueryConditionInterface $condition, $field, $instance) {
if ($field['storage']['type'] != 'field_sql_storage') {
throw new SynonymsSynonymsBehaviorException(t('Not supported storage engine %type in synonymsFind() method.', array(
'%type' => $field['storage']['type'],
)));
}
$table = array_keys($field['storage']['details']['sql'][FIELD_LOAD_CURRENT]);
$table = reset($table);
$column = $field['storage']['details']['sql'][FIELD_LOAD_CURRENT][$table]['target_id'];
$query = db_select($table, 'field');
$target_entity_type_info = entity_get_info($field['settings']['target_type']);
if (!isset($target_entity_type_info['base table']) || !$target_entity_type_info['base table']) {
throw new SynonymsSynonymsBehaviorException(t('Target entity type %entity_type is not stored in database.', array(
'%entity_type' => $field['settings']['target_type'],
)));
}
if (!isset($target_entity_type_info['entity keys']['id'])) {
throw new SynonymsSynonymsBehaviorException(t('Target entity type %entity_type does not declare primary key.', array(
'%entity_type' => $field['settings']['target_type'],
)));
}
if (!isset($target_entity_type_info['entity keys']['label'])) {
throw new SynonymsSynonymsBehaviorException(t('Target entity type %entity_type does not declare label column.', array(
'%entity_type' => $field['settings']['target_type'],
)));
}
$target_entity_alias = $query->innerJoin($target_entity_type_info['base table'], 'target_entity', 'field.' . $column . ' = target_entity.' . $target_entity_type_info['entity keys']['id']);
$query->addField($target_entity_alias, $target_entity_type_info['entity keys']['label'], 'synonym');
$query->fields('field', array('entity_id'));
$query->condition('field.entity_type', $instance['entity_type']);
$query->condition('field.bundle', $instance['bundle']);
$this->synonymsFindProcessCondition($condition, $target_entity_alias . '.' . $target_entity_type_info['entity keys']['label']);
$query->condition($condition);
return $query->execute();
}
}

View File

@@ -11,114 +11,61 @@
* All synonyms behaviors must extend this interface.
*/
interface SynonymsBehavior {
}
/**
* Interface of "synonyms" behavior.
*
* The most basic synonyms behavior.
*/
interface SynonymsSynonymsBehavior extends SynonymsBehavior {
/**
* Extract synonyms from a field attached to an entity.
* Extract synonyms from an entity within a specific behavior implementation.
*
* We try to pass as many info about context as possible, however, normally
* you will only need $items to extract the synonyms.
*
* @param array $items
* Array of items
* @param array $field
* Array of field definition according to Field API
* @param array $instance
* Array of instance definition according to Field API
* @param object $entity
* Fully loaded entity object to which the $field and $instance with $item
* values is attached to
* @param string $entity_type
* Type of the entity $entity according to Field API definition of entity
* types
* Entity from which to extract synonyms
*
* @return array
* Array of synonyms extracted from $items
* Array of synonyms extracted from $entity
*/
public function extractSynonyms($items, $field, $instance, $entity, $entity_type);
public function extractSynonyms($entity);
/**
* Add an entity as a synonym into a field of another entity.
* Add an entity as a synonym into another entity.
*
* Basically this method should be called when you want to add some entity
* as a synonym to another entity (for example when you merge one entity
* into another and besides merging want to add synonym of the merged entity
* into the trunk entity). You should extract synonym value (according to what
* value is expected in this field) and return it. We try to provide you with
* as much of context as possible, but normally you would only need
* $synonym_entity and $synonym_entity_type parameters. Return an empty array
* if entity of type $synonym_entity_type cannot be converted into a format
* expected by $field.
* Basically this method should be called when you want to add some entity as
* a synonym to another entity (for example when you merge one entity into
* another and besides merging want to add synonym of the merged entity into
* the trunk entity). You should update $trunk_entity in such a way that it
* holds $synonym_entity as a synonym (it all depends on how data is stored in
* your behavior implementation, but probably you will store entity label or
* its ID as you cannot literally store an entity inside of another entity).
* If entity of type $synonym_entity_type cannot be converted into a format
* expected by your behavior implementation, just do nothing.
*
* @param array $items
* Array items that already exist in the field into which new synonyms is to
* be added
* @param array $field
* Field array definition according to Field API of the field into which new
* synonym is to be added
* @param array $instance
* Instance array definition according to Field API of the instance into
* which new synonym is to be added
* @param object $trunk_entity
* Entity into which another one should be added as synonym
* @param object $synonym_entity
* Fully loaded entity object which has to be added as synonym
* @param string $synonym_entity_type
* Entity type of $synonym_entity
*
* @return array
* Array of extra items to be merged into the items that already exist in
* field values
*/
public function mergeEntityAsSynonym($items, $field, $instance, $synonym_entity, $synonym_entity_type);
public function mergeEntityAsSynonym($trunk_entity, $synonym_entity, $synonym_entity_type);
/**
* Hash a field item that is enabled as synonym.
*
* Your hash function must return such hash that for 2 items that yield the
* same synonyms their hash must be the same. There is no limit on minimal or
* maximum hash length, but keep it reasonable, something below 512 symbols.
* Also, your hash function should strive to minimize hash collisions, i.e.
* when 2 different items yield the same hash.
*
* @param array $item
* Field item whose hash is requested
* @param array $field
* Field from which the $item comes from
* @param array $instance
* Instance from which the $item comes from
*
* @return string
* Hash of the provided $item
*/
public function synonymItemHash($item, $field, $instance);
/**
* Look up entities by their synonyms within a provided field.
* Look up entities by their synonyms within a behavior implementation.
*
* You are provided with a SQL condition that you should apply to the storage
* of synonyms within the provided field. And then return result: what
* entities match by the provided condition through what synonyms.
* of synonyms within the provided behavior implementation. And then return
* result: what entities match by the provided condition through what
* synonyms.
*
* @param QueryConditionInterface $condition
* Condition that defines what to search for. It may contain a placeholder
* of AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER which you should
* replace by the column name where the synonyms data for your field is
* stored in plain text. For it to do, you may extend the
* AbstractSynonymsSynonymsBehavior class and then just invoke the
* AbstractSynonymsSynonymsBehavior->synonymsFindProcessCondition() method,
* so you won't have to worry much about it
* @param array $field
* Field API field definition array of the field within which the search
* for synonyms should be performed
* @param array $instance
* Field API instance definition array of the instance within which the
* search for synonyms should be performed
* Condition that defines what to search for. Apart from normal SQL
* conditions as known in Drupal, it may contain the following placeholders:
* - AbstractSynonymsBehavior::COLUMN_SYNONYM_PLACEHOLDER: to denote
* synonyms column which you should replace with the actual column name
* where the synonyms data for your provider is stored in plain text.
* - AbstractSynonymsBehavior::COLUMN_ENTITY_ID_PLACEHOLDER: to denote
* column that holds entity ID. You are supposed to replace this
* placeholder with actual column name that holds entity ID in your case.
* For ease of work with these placeholders, you may extend the
* AbstractSynonymsBehavior class and then just invoke the
* AbstractSynonymsBehavior->synonymsFindProcessCondition() method, so you
* won't have to worry much about it
*
* @return Traversable
* Traversable result set of found synonyms and entity IDs to which those
@@ -128,47 +75,86 @@ interface SynonymsSynonymsBehavior extends SynonymsBehavior {
* provided condition
* - entity_id: (int) ID of the entity to which the found synonym belongs
*/
public function synonymsFind(QueryConditionInterface $condition, $field, $instance);
public function synonymsFind(QueryConditionInterface $condition);
/**
* Collect info on features pipe during invocation of hook_features_export().
*
* If your synonyms provider depends on some other features components, this
* method should return them.
*
* @return array
* Array of features pipe as per hook_features_export() specification
*/
public function featuresExportPipe();
}
/**
* Exception thrown by implementations of SynonymsSynonymsBehavior interface.
* Exception thrown by implementations of SynonymsBehavior interface.
*/
class SynonymsSynonymsBehaviorException extends Exception {}
class SynonymsBehaviorException extends Exception {}
/**
* Starting point for implementing SynonymsSynonymsBehavior interface.
* Starting point for implementing SynonymsBehavior interface.
*/
abstract class AbstractSynonymsSynonymsBehavior implements SynonymsSynonymsBehavior {
abstract class AbstractSynonymsBehavior implements SynonymsBehavior {
/**
* Constant which denotes placeholder of a synonym column.
*
* @var string
*/
const COLUMN_PLACEHOLDER = '***COLUMN***';
const COLUMN_SYNONYM_PLACEHOLDER = '***COLUMN***';
/**
* Constant which denotes placeholder of an entity ID column.
*
* @var string
*/
const COLUMN_ENTITY_ID_PLACEHOLDER = '***ENTITY_ID***';
/**
* Behavior implementation on which this class was initialized.
*
* @var array
*/
protected $behavior_implementation;
public function __construct($behavior_implementation) {
$this->behavior_implementation = $behavior_implementation;
}
public function featuresExportPipe() {
return array();
}
/**
* Process condition in 'synonymsFind' method.
*
* Process condition in 'synonymsFind' method replacing all references of
* synonym column with the real name of that column.
* synonym and entity ID columns with the real names of those columns.
*
* @param QueryConditionInterface $condition
* Condition that should be processed
* @param string $column
* @param string $column_synonym
* Real name of the synonym column
* @param string $column_entity_id
* Real name of the entity ID column
*/
protected function synonymsFindProcessCondition(QueryConditionInterface $condition, $column) {
protected function synonymsFindProcessCondition(QueryConditionInterface $condition, $column_synonym, $column_entity_id) {
$condition_array = &$condition->conditions();
foreach ($condition_array as &$v) {
if (is_array($v) && isset($v['field'])) {
if ($v['field'] instanceof QueryConditionInterface) {
// Recursively process this condition too.
$this->synonymsFindProcessCondition($v['field'], $column);
$this->synonymsFindProcessCondition($v['field'], $column_synonym, $column_entity_id);
}
else {
$v['field'] = str_replace(self::COLUMN_PLACEHOLDER, $column, $v['field']);
$replace = array(
self::COLUMN_SYNONYM_PLACEHOLDER => $column_synonym,
self::COLUMN_ENTITY_ID_PLACEHOLDER => $column_entity_id,
);
$v['field'] = str_replace(array_keys($replace), array_values($replace), $v['field']);
}
}
}
@@ -178,11 +164,11 @@ abstract class AbstractSynonymsSynonymsBehavior implements SynonymsSynonymsBehav
/**
* Interface of the autocomplete synonyms behavior.
*/
interface AutocompleteSynonymsBehavior extends SynonymsSynonymsBehavior {
interface AutocompleteSynonymsBehavior extends SynonymsBehavior {
}
/**
* Interface of the synonyms friendly select behavior.
*/
interface SelectSynonymsBehavior extends SynonymsSynonymsBehavior {
interface SelectSynonymsBehavior extends SynonymsBehavior {
}

View File

@@ -1,88 +0,0 @@
<?php
/**
* @file
* Enables Taxonomy Term Reference field type to be source of synonyms.
*/
/**
* Definition of TaxonomySynonymsBehavior class.
*/
class TaxonomySynonymsBehavior extends AbstractSynonymsSynonymsBehavior implements SynonymsSynonymsBehavior, AutocompleteSynonymsBehavior, SelectSynonymsBehavior {
public function extractSynonyms($items, $field, $instance, $entity, $entity_type) {
$synonyms = array();
$terms = array();
foreach ($items as $item) {
$terms[] = $item['tid'];
}
$terms = taxonomy_term_load_multiple($terms);
foreach ($terms as $term) {
$synonyms[] = entity_label('taxonomy_term', $term);
}
return $synonyms;
}
public function mergeEntityAsSynonym($items, $field, $instance, $synonym_entity, $synonym_entity_type) {
// Taxonomy term reference supports only referencing of entity types
// 'taxonomy_term'.. duh.
if ($synonym_entity_type != 'taxonomy_term') {
return array();
}
// Checking that $field is configured to reference the vocabulary of
// $synonym_entity term.
$is_allowed = FALSE;
foreach ($field['settings']['allowed_values'] as $setting) {
if ($synonym_entity->vocabulary_machine_name == $setting['vocabulary']) {
if ($setting['parent'] == 0) {
// No need to check parent property as there is no limitation on it.
$is_allowed = TRUE;
break;
}
else {
foreach (taxonomy_get_parents_all($synonym_entity->tid) as $parent) {
if ($parent->tid == $setting['parent']) {
$is_allowed = TRUE;
break(2);
}
}
}
}
}
if (!$is_allowed) {
// Synonym term is from a vocabulary that is not expected by this field,
// or under unexpected parent.
return array();
}
return array(array(
'tid' => $synonym_entity->tid,
));
}
public function synonymItemHash($item, $field, $instance) {
return $item['tid'];
}
public function synonymsFind(QueryConditionInterface $condition, $field, $instance) {
if ($field['storage']['type'] != 'field_sql_storage') {
throw new SynonymsSynonymsBehaviorException(t('Not supported storage engine %type in synonymsFind() method.', array(
'%type' => $field['storage']['type'],
)));
}
$table = array_keys($field['storage']['details']['sql'][FIELD_LOAD_CURRENT]);
$table = reset($table);
$column = $field['storage']['details']['sql'][FIELD_LOAD_CURRENT][$table]['tid'];
$query = db_select($table, 'field');
$term_alias = $query->innerJoin('taxonomy_term_data', 'term', 'field.' . $column . ' = term.tid');
$query->addField($term_alias, 'name', 'synonym');
$query->fields('field', array('entity_id'));
$query->condition('field.entity_type', $instance['entity_type']);
$query->condition('field.bundle', $instance['bundle']);
$this->synonymsFindProcessCondition($condition, $term_alias . '.name');
$query->condition($condition);
return $query->execute();
}
}

View File

@@ -1,68 +0,0 @@
<?php
/**
* @file
* Enables text and number field types to be source of synonyms.
*/
/**
* Definition of TextSynonymsBehavior class.
*/
class TextSynonymsBehavior extends AbstractSynonymsSynonymsBehavior implements SynonymsSynonymsBehavior, AutocompleteSynonymsBehavior, SelectSynonymsBehavior {
public function extractSynonyms($items, $field, $instance, $entity, $entity_type) {
$synonyms = array();
foreach ($items as $item) {
$synonyms[] = $item['value'];
}
return $synonyms;
}
public function mergeEntityAsSynonym($items, $field, $instance, $synonym_entity, $synonym_entity_type) {
$synonym = entity_label($synonym_entity_type, $synonym_entity);
switch ($field['type']) {
case 'text':
break;
// We add synonyms for numbers only if $synonym is a number.
case 'number_integer':
case 'number_float':
case 'number_decimal':
if (!is_numeric($synonym)) {
return array();
}
break;
}
return array(array(
'value' => $synonym,
));
}
public function synonymItemHash($item, $field, $instance) {
return $item['value'];
}
public function synonymsFind(QueryConditionInterface $condition, $field, $instance) {
if ($field['storage']['type'] != 'field_sql_storage') {
throw new SynonymsSynonymsBehaviorException(t('Not supported storage engine %type in synonymsFind() method.', array(
'%type' => $field['storage']['type'],
)));
}
$table = array_keys($field['storage']['details']['sql'][FIELD_LOAD_CURRENT]);
$table = reset($table);
$column = $field['storage']['details']['sql'][FIELD_LOAD_CURRENT][$table]['value'];
$this->synonymsFindProcessCondition($condition, $column);
$query = db_select($table);
$query->fields($table, array('entity_id'));
$query->addField($table, $column, 'synonym');
return $query->condition($condition)
->condition('entity_type', $instance['entity_type'])
->condition('bundle', $instance['bundle'])
->execute();
}
}