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

@@ -5,29 +5,73 @@
* Views integration of Synonyms module.
*/
/**
* Implements hook_views_data().
*/
function synonyms_views_data() {
$data = array();
foreach (entity_get_info() as $entity_type => $entity_info) {
$wrapper = entity_metadata_wrapper($entity_type);
$property_info = $wrapper->getPropertyInfo();
if (isset($property_info['synonyms']) && isset($entity_info['base table']) && $entity_info['base table']) {
$data[$entity_info['base table']]['synonyms'] = array(
'title' => t('All synonyms'),
'help' => t('All synonyms of @entity_type', array(
'@entity_type' => $entity_info['label'],
)),
'field' => array(
'handler' => 'synonyms_views_handler_field_synonyms',
'real field' => $entity_info['entity keys']['id'],
'click sortable' => FALSE,
'synonyms entity type' => $entity_type,
),
);
}
}
return $data;
}
/**
* Implements hook_views_plugins_alter().
*/
function synonyms_views_plugins_alter(&$plugins) {
// Replace default taxonomy term argument validator with our extended version,
// which can also handle a term synonym as an argument.
$plugins['argument validator']['taxonomy_term']['handler'] = 'synonyms_views_plugin_argument_validate_taxonomy_term';
if (module_exists('taxonomy')) {
// Replace default taxonomy term argument validator with our extended
// version, which can also handle a term synonym as an argument.
$plugins['argument validator']['taxonomy_term']['handler'] = 'synonyms_views_plugin_argument_validate_taxonomy_term';
}
}
/**
* Implements hook_field_views_data_alter().
*/
function synonyms_field_views_data_alter(&$result, $field, $module) {
if ($field['type'] == 'taxonomy_term_reference') {
// Add synonyms friendly autocomplete filter.
foreach ($field['storage']['details']['sql'] as $table) {
$tid_column = reset($table);
$tid_column = $tid_column['tid'];
$table = array_keys($table);
$table = $table[0];
if (isset($result[$table][$tid_column]['filter'])) {
$result[$table][$tid_column]['filter']['handler'] = 'synonyms_views_handler_filter_term_tid';
switch ($field['type']) {
case 'taxonomy_term_reference':
// Add synonyms friendly filters.
foreach ($field['storage']['details']['sql'] as $table) {
$tid_column = reset($table);
$tid_column = $tid_column['tid'];
$table = array_keys($table);
$table = $table[0];
if (isset($result[$table][$tid_column]['filter'])) {
$result[$table][$tid_column]['filter']['handler'] = 'synonyms_views_handler_filter_term_tid';
}
}
}
break;
case 'entityreference':
foreach ($field['storage']['details']['sql'] as $table) {
$target_id_column = reset($table);
$target_id_column = $target_id_column['target_id'];
$table = array_keys($table);
$table = $table[0];
if (isset($result[$table][$target_id_column]['filter'])) {
$result[$table][$target_id_column]['filter']['handler'] = 'synonyms_views_handler_filter_entityreference_synonyms';
}
}
break;
}
}

View File

@@ -0,0 +1,102 @@
<?php
/**
* @file
* Definition of synonyms_handler_field_synonyms class.
*/
/**
* Views field handler for displaying synonyms of an entity.
*/
class synonyms_views_handler_field_synonyms extends views_handler_field {
function option_definition() {
$options = parent::option_definition();
$options['list'] = array(
'default' => 'ul',
);
$options['separator'] = array(
'default' => '',
'translatable' => TRUE,
);
return $options;
}
function options_form(&$form, &$form_state) {
parent::options_form($form, $form_state);
$form['list'] = array(
'#type' => 'radios',
'#title' => t('Display type'),
'#options' => array(
'ul' => t('Unordered list'),
'ol' => t('Ordered list'),
'separator' => t('Simple separator'),
),
'#default_value' => $this->options['list'],
);
$form['separator'] = array(
'#type' => 'textfield',
'#title' => t('Separator'),
'#default_value' => $this->options['separator'],
'#dependency' => array(
'radio:options[list]' => array('separator'),
),
);
}
function pre_render(&$values) {
// Load all the queried entities in a single batch.
$entity_ids = array();
foreach ($values as $value) {
$entity_ids[] = $value->{$this->definition['real field']};
}
$entity_ids = array_unique($entity_ids);
if (!empty($entity_ids)) {
$entities = entity_load($this->definition['synonyms entity type'], $entity_ids);
foreach ($values as &$value) {
$value->synonyms_entity = $entities[$value->{$this->definition['real field']}];
unset($value);
}
}
parent::pre_render($values);
}
function get_value($values, $field = NULL) {
$property = $this->field;
$wrapper = entity_metadata_wrapper($this->definition['synonyms entity type'], $values->synonyms_entity);
$synonyms = $wrapper->$property->value(array('sanitize' => TRUE));
if (empty($synonyms)) {
$synonyms = '';
}
else {
switch ($this->options['list']) {
case 'ol':
case 'ul':
$synonyms = theme('item_list', array(
'type' => $this->options['list'],
'items' => $synonyms,
));
break;
case 'separator':
$synonyms = implode($this->options['separator'], $synonyms);
break;
}
}
return $synonyms;
}
function sanitize_value($value, $type = NULL) {
if (is_null($type)) {
$type = 'xss_admin';
}
return parent::sanitize_value($value, $type);
}
}

View File

@@ -0,0 +1,144 @@
<?php
/**
* @file
* Definition of synonyms_views_handler_filter_entityreference_synonyms class.
*/
/**
* Definition of synonyms friendly entity reference field filter.
*/
class synonyms_views_handler_filter_entityreference_synonyms extends views_handler_filter_numeric {
function option_definition() {
$options = parent::option_definition();
$options['type'] = array(
'default' => 'numeric',
);
return $options;
}
function extra_options_form(&$form, &$form_state) {
parent::extra_options_form($form, $form_state);
$form['type'] = array(
'#type' => 'radios',
'#title' => t('Type'),
'#options' => array(
'numeric' => t('Numeric'),
'synonyms_autocomplete' => t('Synonyms friendly autocomplete'),
'synonyms_select' => t('Synonyms friendly select list'),
),
'#default_value' => $this->options['type'],
);
}
function has_extra_options() {
return TRUE;
}
function operators() {
$operators = parent::operators();
switch ($this->options['type']) {
case 'synonyms_autocomplete':
case 'synonyms_select':
// Only "equals" and "not equals" make sense, other operators are rather
// funky when it comes to IDs and not simple integers.
$operators = array_intersect_key($operators, drupal_map_assoc(array(
'=', '!=',
)));
break;
}
return $operators;
}
function value_form(&$form, &$form_state) {
parent::value_form($form, $form_state);
if (isset($form['value']['#type'])) {
$element = &$form['value'];
}
elseif (isset($form['value']['value']['#type'])) {
$element = &$form['value']['value'];
}
if (isset($element)) {
$field = field_info_field($this->definition['field_name']);
$entity_type = array_keys($field['bundles']);
$entity_type = reset($entity_type);
$bundle = reset($field['bundles'][$entity_type]);
$instance = field_info_instance($entity_type, $field['field_name'], $bundle);
switch ($this->options['type']) {
case 'synonyms_autocomplete':
$widget = field_info_widget_settings('synonyms_autocomplete_entity');
$element['#autocomplete_path'] = $widget['synonyms_autocomplete_path'] . '/' . $field['field_name'] . '/' . $instance['entity_type'] . '/' . $instance['bundle'];
$element['#attached']['js'][drupal_get_path('module', 'synonyms') . '/js/synonyms-autocomplete.js'] = array();
$element['#attributes']['class'][] = 'synonyms-autocomplete';
break;
case 'synonyms_select':
$element['#type'] = 'select';
$element['#options'] = synonyms_select_entity_options($field, $instance);
if (!$this->is_exposed()) {
$element['#empty_option'] = t('- None -');
}
$element['#element_validate'][] = 'synonyms_select_validate';
$element['#element_validate'][] = 'synonyms_select_views_entityreference_filter_validate';
unset($element['#size']);
break;
}
}
}
function query() {
switch ($this->options['type']) {
case 'synonyms_autocomplete':
$field = field_info_field($this->definition['field_name']);
$this->value['value'] = synonyms_get_entity_by_synonym($field['settings']['target_type'], $this->value['value'], synonyms_field_target_bundles($field));
break;
}
parent::query();
}
function admin_summary() {
if ($this->is_a_group()) {
return t('grouped');
}
if (!empty($this->options['exposed'])) {
return t('exposed');
}
switch ($this->options['type']) {
case 'numeric':
case 'synonyms_autocomplete':
return parent::admin_summary();
break;
case 'synonyms_select':
$field = field_info_field($this->definition['field_name']);
$entity = entity_load($field['settings']['target_type'], array($this->value['value']));
$entity = reset($entity);
if (is_object($entity)) {
$label = entity_label($field['settings']['target_type'], $entity);
$options = $this->operator_options('short');
return check_plain($options[$this->operator]) . ' ' . check_plain($label);
}
break;
}
}
}
/**
* Form element validate handler.
*
* Simply convert select value from an array (as mostly operated within Field
* module) to a single value.
*/
function synonyms_select_views_entityreference_filter_validate($element, &$form_state) {
$value = drupal_array_get_nested_value($form_state['values'], $element['#parents']);
$value = reset($value);
form_set_value($element, $value, $form_state);
}

View File

@@ -13,97 +13,162 @@ class synonyms_views_handler_filter_term_tid extends views_handler_filter_term_n
parent::extra_options_form($form, $form_state);
$form['type']['#options']['synonyms_autocomplete'] = t('Synonyms friendly autocomplete');
$form['type']['#options']['synonyms_select'] = t('Synonyms friendly select');
}
function value_form(&$form, &$form_state) {
$restore_value = $this->options['type'] == 'synonyms_autocomplete';
if ($restore_value) {
$this->options['type'] = 'textfield';
$vocabulary = taxonomy_vocabulary_machine_name_load($this->options['vocabulary']);
if (empty($vocabulary) && $this->options['limit']) {
$form['markup'] = array(
'#markup' => '<div class="form-item">' . t('An invalid vocabulary is selected. Please change it in the options.') . '</div>',
);
return;
}
parent::value_form($form, $form_state);
if ($restore_value) {
// We need to determine the entity type onto which this field is attached
// that is used in this view.
$entity_type_base_table = $this->view->base_table;
// TODO: it would be nice to consider the existence of relationships, but
// I just couldn't figure it out at that time.
$entity_info = entity_get_info();
$field_entity_type = FALSE;
$field = field_info_field($this->definition['field_name']);
foreach ($field['bundles'] as $entity_type => $bundles) {
if ($entity_info[$entity_type]['base table'] == $entity_type_base_table) {
$field_entity_type = $entity_type;
break;
switch ($this->options['type']) {
case 'synonyms_autocomplete':
$tags = array();
if ($this->value) {
$result = taxonomy_term_load_multiple($this->value);
foreach ($result as $entity_term) {
$tags[] = entity_label('taxonomy_term', $entity_term);
}
}
}
$tags = drupal_implode_tags($tags);
if (!$field_entity_type) {
// Seems like we failed to determine the entity type which is used for
// this field in the view. Well, it's not a fatal fail, we'll just use
// whatever then.
$field_entity_type = array_keys($field['bundles']);
$field_entity_type = $field_entity_type[0];
}
$info = $this->synonyms_field_instance();
// We just grab the first instance of this field within the determined
// entity type.
$bundle = $field['bundles'][$field_entity_type][0];
if ($info['instance']['widget']['type'] == 'synonyms_autocomplete_taxonomy_term') {
$widget = $info['instance']['widget']['settings'];
}
else {
$widget = field_info_widget_settings('synonyms_autocomplete_taxonomy_term');
}
$autocomplete_path = $widget['synonyms_autocomplete_path'];
$size = $widget['size'];
$instance = field_info_instance($field_entity_type, $field['field_name'], $bundle);
if ($instance['widget']['type'] == 'synonyms_autocomplete') {
$widget = $instance['widget']['settings'];
}
else {
$widget = field_info_widget_settings('synonyms_autocomplete');
}
$autocomplete_path = $widget['synonyms_autocomplete_path'];
$size = $widget['size'];
$form['value'] = array(
'#title' => $this->options['limit'] ? t('Select terms from vocabulary @voc', array('@voc' => $vocabulary->name)) : t('Select terms'),
'#type' => 'textfield',
'#default_value' => $tags,
'#autocomplete_path' => $autocomplete_path . '/' . $this->definition['field_name'] . '/' . $info['instance']['entity_type'] . '/' . $info['instance']['bundle'],
'#size' => $size,
'#auto_creation' => FALSE,
'#attributes' => array('class' => array('synonyms-autocomplete')),
'#attached' => array('js' => array(
drupal_get_path('module', 'synonyms') . '/js/synonyms-autocomplete.js' => array(),
)),
);
break;
$form['value']['#autocomplete_path'] = $autocomplete_path . '/' . $this->definition['field_name'] . '/' . $field_entity_type . '/' . $bundle;
$form['value']['#size'] = $size;
$form['value']['#auto_creation'] = FALSE;
$form['value']['#attributes']['class'][] = 'synonyms-autocomplete';
$form['value']['#attached']['js'][drupal_get_path('module', 'synonyms') . '/js/synonyms-autocomplete.js'] = array();
$this->options['type'] = 'synonyms_autocomplete';
case 'synonyms_select':
$info = $this->synonyms_field_instance();
$options = array();
$widget = $info['instance']['widget']['type'] == 'synonyms_select_taxonomy_term' ? $info['instance']['widget']['settings'] : field_info_widget_settings('synonyms_select_taxonomy_term');
foreach ($info['field']['settings']['allowed_values'] as $tree) {
if ($vocabulary = taxonomy_vocabulary_machine_name_load($tree['vocabulary'])) {
switch ($widget['sort']) {
case 'weight':
if ($terms = taxonomy_get_tree($vocabulary->vid, $tree['parent'], NULL, TRUE)) {
$behavior_implementations = synonyms_behavior_get('select', 'taxonomy_term', field_extract_bundle('taxonomy_term', $vocabulary), TRUE);
foreach ($terms as $term) {
$options[] = synonyms_select_option_entity($term, 'taxonomy_term', NULL, NULL, array('depth'));
foreach ($behavior_implementations as $implementation) {
foreach ($implementation['object']->extractSynonyms($term) as $synonym) {
$options[] = synonyms_select_option_entity($term, 'taxonomy_term', $synonym, $implementation, array('depth'));
}
}
}
}
break;
case 'name':
// TODO: is there any way to leverage DB for the sorting routine?
$options = synonyms_select_taxonomy_term_sort_name_options_recursive($vocabulary, $tree['parent']);
break;
}
}
}
$form['value'] = array(
'#type' => 'select',
'#title' => $this->options['limit'] ? t('Select terms from vocabulary @voc', array('@voc' => $vocabulary->name)) : t('Select terms'),
'#multiple' => TRUE,
'#options' => $options,
'#size' => min(9, count($options)),
'#default_value' => (array) $this->value,
'#element_validate' => array('synonyms_select_validate'),
);
break;
default:
parent::value_form($form, $form_state);
break;
}
}
function value_validate($form, &$form_state) {
if ($this->options['type'] == 'synonyms_autocomplete') {
$values = drupal_explode_tags($form_state['values']['options']['value']);
$tids = $this->synonyms_validate_term_strings($form['value'], $values);
switch ($this->options['type']) {
case 'synonyms_autocomplete':
$values = drupal_explode_tags($form_state['values']['options']['value']);
$tids = $this->synonyms_validate_term_strings($form['value'], $values);
if ($tids) {
$form_state['values']['options']['value'] = $tids;
}
}
else {
parent::value_validate($form, $form_state);
if ($tids) {
$form_state['values']['options']['value'] = $tids;
}
break;
case 'synonyms_select':
break;
default:
parent::value_validate($form, $form_state);
break;
}
}
function exposed_validate(&$form, &$form_state) {
if ($this->options['type'] == 'synonyms_autocomplete') {
if (empty($this->options['exposed'])) {
return;
}
if (empty($this->options['expose']['identifier'])) {
return;
}
switch ($this->options['type']) {
case 'synonyms_autocomplete':
if (empty($this->options['exposed'])) {
return;
}
if (empty($this->options['expose']['identifier'])) {
return;
}
$identifier = $this->options['expose']['identifier'];
$values = drupal_explode_tags($form_state['values'][$identifier]);
$tids = $this->synonyms_validate_term_strings($form[$identifier], $values);
$identifier = $this->options['expose']['identifier'];
$values = drupal_explode_tags($form_state['values'][$identifier]);
$tids = $this->synonyms_validate_term_strings($form[$identifier], $values);
if ($tids) {
$this->validated_exposed_input = $tids;
}
}
else {
parent::exposed_validate($form, $form_state);
if ($tids) {
$this->validated_exposed_input = $tids;
}
break;
case 'synonyms_select':
if (empty($this->options['exposed'])) {
return;
}
if (empty($this->options['expose']['identifier'])) {
return;
}
$all_key = array_search('All', $form_state['values'][$this->options['expose']['identifier']]);
if ($all_key !== FALSE) {
unset($form_state['values'][$this->options['expose']['identifier']][$all_key]);
}
if (!empty($form_state['values'][$this->options['expose']['identifier']])) {
return;
}
$this->validated_exposed_input = $form_state['values'][$this->options['expose']['identifier']];
break;
default:
parent::exposed_validate($form, $form_state);
break;
}
}
@@ -154,9 +219,9 @@ class synonyms_views_handler_filter_term_tid extends views_handler_filter_term_n
if (!empty($missing)) {
$condition = db_or();
foreach ($missing as $tag => $v) {
$condition->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, $tag);
$condition->condition(AbstractSynonymsBehavior::COLUMN_SYNONYM_PLACEHOLDER, $tag);
}
$synonyms = synonyms_synonyms_find_behavior($condition, $behavior_implementation);
$synonyms = $behavior_implementation['object']->synonymsFind($condition);
foreach ($synonyms as $synonym) {
$synonym->synonym = drupal_strtolower($synonym->synonym);
unset($missing[$synonym->synonym]);
@@ -171,4 +236,49 @@ class synonyms_views_handler_filter_term_tid extends views_handler_filter_term_n
return $tids;
}
/**
* Collect info about field and instance that correspond to this filter.
*
* @return array
* Array with the following structure:
* - field: (array) Field definition array that corresponds to this filter
* - instance: (array) Field instance definition array that corresponds to
* this filter
*/
protected function synonyms_field_instance() {
$entity_type_base_table = $this->view->base_table;
// TODO: it would be nice to consider the existence of relationships, but
// I just couldn't figure it out at that time.
$entity_info = entity_get_info();
$field_entity_type = FALSE;
$field = field_info_field($this->definition['field_name']);
foreach ($field['bundles'] as $entity_type => $bundles) {
if ($entity_info[$entity_type]['base table'] == $entity_type_base_table) {
$field_entity_type = $entity_type;
break;
}
}
if (!$field_entity_type) {
// Seems like we failed to determine the entity type which is used for
// this field in the view. Well, it's not a fatal fail, we'll just use
// whatever then.
$field_entity_type = array_keys($field['bundles']);
$field_entity_type = $field_entity_type[0];
}
// We just grab the first instance of this field within the determined
// entity type.
$bundle = $field['bundles'][$field_entity_type][0];
$instance = field_info_instance($field_entity_type, $field['field_name'], $bundle);
return array(
'field' => $field,
'instance' => $instance,
);
}
}

View File

@@ -57,18 +57,18 @@ class synonyms_views_plugin_argument_validate_taxonomy_term extends views_plugin
if (empty($vocabularies)) {
// At this point we want to convert an empty $vocabularies (implicitly
// meaning "all") into actually a list of all vocabularies.
$bundles = array_keys(taxonomy_vocabulary_get_names());
$bundles = synonyms_bundle_normalize('taxonomy_term', $vocabularies);
}
foreach ($bundles as $bundle) {
$condition = db_and();
if ($transform) {
$condition->where("REPLACE(" . AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER . ", ' ', '-') = :argument", array(
$condition->where("REPLACE(" . AbstractSynonymsBehavior::COLUMN_SYNONYM_PLACEHOLDER . ", ' ', '-') = :argument", array(
':argument' => $argument,
));
}
else {
$condition->condition(AbstractSynonymsSynonymsBehavior::COLUMN_PLACEHOLDER, $argument);
$condition->condition(AbstractSynonymsBehavior::COLUMN_SYNONYM_PLACEHOLDER, $argument);
}
$synonyms = synonyms_synonyms_find($condition, 'taxonomy_term', $bundle);
if (!empty($synonyms)) {