| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566 | <?php/** * @file * Provide synonyms feature for Drupal entities. *//** * Implements hook_menu(). */function synonyms_menu() {  $items = array();  $items['admin/structure/synonyms'] = array(    'title' => 'Synonyms',    'description' => 'Manage synonyms settings for all entity types.',    'page callback' => 'synonyms_settings_overview',    'access arguments' => array('administer synonyms'),    'file' => 'synonyms.pages.inc',    'type' => MENU_NORMAL_ITEM,  );  $items['admin/structure/synonyms/%synonyms_entity_type/%synonyms_bundle'] = array(    'title' => 'Synonyms settings',    'title callback' => 'synonyms_settings_title',    'title arguments' => array(3, 4),    'description' => 'Manage synonyms settings.',    'page callback' => 'drupal_get_form',    'page arguments' => array('synonyms_settings_form', 3, 4),    'access arguments' => array('administer synonyms'),    'load arguments' => array(3),    'file' => 'synonyms.pages.inc',  );  if (module_exists('taxonomy')) {    $items['synonyms/autocomplete-taxonomy-term/%/%/%'] = array(      'title' => 'Autocomplete Synonyms',      'page callback' => 'synonyms_autocomplete_taxonomy_term',      'page arguments' => array(2, 3, 4),      'access arguments' => array('access content'),      'file' => 'synonyms.pages.inc',      'type' => MENU_CALLBACK,    );  }  $items['synonyms/autocomplete-entity/%/%/%'] = array(    'title' => 'Autocomplete Synonyms',    'page callback' => 'synonyms_autocomplete_entity',    'page arguments' => array(2, 3, 4),    'access callback' => 'entityreference_autocomplete_access_callback',    'access arguments' => array('tags', 2, 3, 4),    'file' => 'synonyms.pages.inc',    'type' => MENU_CALLBACK,  );  return $items;}/** * Implements hook_permission(). */function synonyms_permission() {  return array(    'administer synonyms' => array(      'title' => t('Administer synonyms'),      'description' => t('Administer synonyms of all entity types.'),    ),  );}/** * Implements hook_ctools_plugin_type(). */function synonyms_ctools_plugin_type() {  $plugins = array();  $plugins['behavior'] = array(    'defaults' => array(      'title' => NULL,      'description' => NULL,      'settings form callback' => NULL,      'interface' => NULL,      'enabled callback' => NULL,      'disabled callback' => NULL,    ),  );  return $plugins;}/** * Implements hook_ctools_plugin_directory(). */function synonyms_ctools_plugin_directory($owner, $plugin_type) {  switch ($owner) {    case 'synonyms':      switch ($plugin_type) {        case 'behavior':          return 'plugins/' . $plugin_type;      }      break;    case 'ctools':      switch ($plugin_type) {        case 'arguments':          return 'plugins/' . $plugin_type;      }      break;  }}/** * Implements hook_theme(). */function synonyms_theme() {  return array(    'synonyms_behaviors_settings' => array(      'render element' => 'element',      'file' => 'synonyms.pages.inc',    ),  );}/** * Implements hook_entity_property_info(). */function synonyms_entity_property_info() {  $info = array();  foreach (entity_get_info() as $entity_type => $entity_info) {    $entity_type = synonyms_entity_type_load($entity_type);    if ($entity_type) {      $info[$entity_type]['properties']['synonyms'] = array(        'label' => t('Synonyms'),        'description' => t('Synonyms of entity.'),        'type' => 'list<text>',        'getter callback' => 'synonyms_get_sanitized',        'computed' => TRUE,        'sanitized' => TRUE,        'raw getter callback' => 'synonyms_get_raw',      );    }  }  return $info;}/** * Implements hook_form_FORM_ID_alter(). */function synonyms_form_taxonomy_form_vocabulary_alter(&$form, &$form_state) {  // TODO: remove this function after a few releases of Synonyms module, since  // now the module oversees synonyms of all entities, not only taxonomy terms.  if (isset($form_state['confirm_delete']) && $form_state['confirm_delete']) {    return;  }  if (!isset($form['#vocabulary']->vid) || !$form['#vocabulary']->vid) {    return;  }  $form['synonyms'] = array(    '#type' => 'fieldset',    '#title' => t('Synonyms'),    '#collapsible' => TRUE,  );  $form['synonyms']['link'] = array(    '#markup' => t('You can configure synonyms of @vocabulary following <a href="@url">this link</a>.', array(      '@vocabulary' => $form['#vocabulary']->name,      '@url' => url('admin/structure/synonyms/taxonomy_term/' . $form['#vocabulary']->machine_name, array('query' => drupal_get_destination())),    )),  );}/** * Implements hook_field_widget_info(). */function synonyms_field_widget_info() {  return array(    'synonyms_autocomplete_taxonomy_term' => array(      'label' => t('Synonyms friendly autocomplete'),      'field types' => array('taxonomy_term_reference'),      'settings' => array(        'size' => 60,        'synonyms_autocomplete_path' => 'synonyms/autocomplete-taxonomy-term',        'suggestion_size' => 10,        'suggest_only_unique' => FALSE,        'auto_creation' => 1,      ),      'behaviors' => array(        'multiple values' => FIELD_BEHAVIOR_CUSTOM,      ),    ),    'synonyms_autocomplete_entity' => array(      'label' => t('Synonyms friendly autocomplete'),      'field types' => array('entityreference'),      'settings' => array(        'size' => 60,        'synonyms_autocomplete_path' => 'synonyms/autocomplete-entity',        'suggestion_size' => 10,        'suggest_only_unique' => FALSE,      ),      'behaviors' => array(        'multiple values' => FIELD_BEHAVIOR_CUSTOM,      ),    ),    'synonyms_select_taxonomy_term' => array(      'label' => t('Synonyms friendly select list'),      'field types' => array('taxonomy_term_reference'),      'settings' => array(        'sort' => 'weight',      ),      'behaviors' => array(        'multiple values' => FIELD_BEHAVIOR_CUSTOM,      ),    ),    'synonyms_select_entity' => array(      'label' => t('Synonyms friendly select list'),      'field types' => array('entityreference'),      'settings' => array(),      'behaviors' => array(        'multiple values' => FIELD_BEHAVIOR_CUSTOM,      ),    ),  );}/** * Implements hook_field_widget_settings_form(). */function synonyms_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_autocomplete_taxonomy_term':    case 'synonyms_autocomplete_entity':      if ($widget['type'] == 'synonyms_autocomplete_taxonomy_term') {        $form['auto_creation'] = array(          '#type' => 'checkbox',          '#title' => t('Allow auto-creation?'),          '#description' => t('Whether users may create a new term by typing in a non-existing name into this field.'),          '#default_value' => $settings['auto_creation'],        );      }      $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 term'),        '#description' => t('If you want to include only term name or a single synonym, suggesting a particular term, while disregarding all ongoing ones, please, tick this checkbox on.'),        '#default_value' => $settings['suggest_only_unique'],      );      break;    case 'synonyms_select_taxonomy_term':      $form['sort'] = array(        '#type' => 'radios',        '#title' => t('Sort'),        '#description' => t('Choose by what criterion the items within select should be sorted.'),        '#options' => array(          'weight' => t('As in taxonomy vocabulary (by weight)'),          'name' => t('By name of terms and their synonyms'),        ),        '#default_value' => $settings['sort'],      );      break;  }  return $form;}/** * Implements hook_field_widget_form(). */function synonyms_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_autocomplete_taxonomy_term':    case 'synonyms_autocomplete_entity':      switch ($instance['widget']['type']) {        case 'synonyms_autocomplete_taxonomy_term':          $default_value_string = taxonomy_implode_tags(taxonomy_term_load_multiple($default_value));          $element_validate = array('taxonomy_autocomplete_validate', 'synonyms_autocomplete_taxonomy_term_validate');          break;        case 'synonyms_autocomplete_entity':          $default_value_string = array();          $entity = isset($element['#entity']) ? $element['#entity'] : NULL;          $handler = entityreference_get_selection_handler($field, $instance, $instance['entity_type'], $entity);          $target_entities = entity_load($field['settings']['target_type'], $default_value);          foreach ($target_entities as $target_entity_id => $target_entity) {            $default_value_string[] = synonyms_autocomplete_escape($handler->getLabel($target_entity));          }          $default_value_string = drupal_implode_tags($default_value_string);          $element_validate = array('synonyms_autocomplete_entity_validate');          break;      }      $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' => $element_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_select_taxonomy_term':      $multiple = $field['cardinality'] > 1 || $field['cardinality'] == FIELD_CARDINALITY_UNLIMITED;      $options = array();      foreach ($field['settings']['allowed_values'] as $tree) {        if ($vocabulary = taxonomy_vocabulary_machine_name_load($tree['vocabulary'])) {          switch ($instance['widget']['settings']['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;          }        }      }      $element += array(        '#type' => 'select',        '#multiple' => $multiple,        '#options' => $options,        '#default_value' => $default_value,        '#element_validate' => array('synonyms_select_validate', 'synonyms_select_form_to_storage'),        '#empty_option' => t('- None -'),      );      break;    case 'synonyms_select_entity':      $multiple = $field['cardinality'] > 1 || $field['cardinality'] == FIELD_CARDINALITY_UNLIMITED;      $element += array(        '#type' => 'select',        '#multiple' => $multiple,        '#options' => synonyms_select_entity_options($field, $instance, $element['#entity']),        '#default_value' => $default_value,        '#element_validate' => array('synonyms_select_validate', 'synonyms_select_form_to_storage'),        '#empty_option' => t('- None -'),      );      break;  }  return $element;}/** * Implements hook_field_widget_error(). */function synonyms_field_widget_error($element, $error, $form, &$form_state) {  form_error($element, $error['message']);}/** * Implements hook_features_api(). */function synonyms_features_api() {  return array(    'synonyms' => array(      'name' => t('Synonyms'),      'file' => drupal_get_path('module', 'synonyms') . '/synonyms.features.inc',      'default_hook' => 'default_synonyms',      'feature_source' => TRUE,    ),  );}/** * Implements hook_modules_disabled(). */function synonyms_modules_disabled($modules) {  foreach ($modules as $module) {    db_delete('synonyms_settings')      ->condition('provider', db_like($module) . '%', 'LIKE')      ->execute();  }}/** * Form element validate handler. * * Handle validation for taxonomy term synonym-friendly autocomplete element. */function synonyms_autocomplete_taxonomy_term_validate($element, &$form_state) {  // After taxonomy_autocomplete_validate() has finished its job any terms it  // didn't find have been set for autocreation. We need to:  // (a) Double-check that those terms are not synonyms.  // (b) Check that synonyms' configurable auto-creation option is enabled.  $value = drupal_array_get_nested_value($form_state['values'], $element['#parents']);  $tids = array();  $field = field_widget_field($element, $form_state);  foreach ($value as $delta => $term) {    if ($term['tid'] == 'autocreate') {      $synonym_tid = 0;      foreach ($field['settings']['allowed_values'] as $tree) {        $behavior_implementations = synonyms_behavior_get('autocomplete', 'taxonomy_term', $tree['vocabulary'], TRUE);        foreach ($behavior_implementations as $behavior_implementation) {          $synonyms = $behavior_implementation['object']->synonymsFind(db_and()->condition(AbstractSynonymsBehavior::COLUMN_SYNONYM_PLACEHOLDER, $term['name']));          foreach ($synonyms as $synonym) {            $synonym_tid = $synonym->entity_id;            break(2);          }        }      }      if ($synonym_tid != 0 && !in_array($synonym_tid, $tids)) {        $value[$delta]['tid'] = $synonym_tid;        $tids[] = $synonym_tid;      }      elseif (!$element['#auto_creation']) {        unset($value[$delta]);      }    }    else {      $tids[] = $term['tid'];    }  }  $value = array_values($value);  form_set_value($element, $value, $form_state);}/** * Form element validate handler. * * Validate entity reference synonyms friendly autocomplete element. */function synonyms_autocomplete_entity_validate($element, &$form_state) {  $input = drupal_map_assoc(drupal_explode_tags(drupal_strtolower($element['#value'])));  $value = array();  if (!empty($input)) {    $field = field_info_field($element['#field_name']);    $instance = field_info_instance($element['#entity_type'], $field['field_name'], $element['#bundle']);    $handler = entityreference_get_selection_handler($field, $instance);    $matches = $handler->getReferencableEntities($input, 'IN');    foreach ($matches as $bundle => $entity_ids) {      foreach ($entity_ids as $entity_id => $label) {        $value[] = $entity_id;        unset($input[drupal_strtolower($label)]);      }    }    if (!empty($input)) {      $behavior_implementations = synonyms_behavior_get('autocomplete', $field['settings']['target_type'], synonyms_field_target_bundles($field), 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();  foreach ($tmp as $target_id) {    $value[] = array('target_id' => $target_id);  }  form_set_value($element, $value, $form_state);}/** * Try finding an entity by its name or synonym. * * @param string $entity_type *   What entity type is being searched * @param string $name *   The look up keyword (the supposed name or synonym) * @param string $bundle *   Optionally limit the search within a specific bundle name of the provided *   entity type * * @return int *   ID of the looked up entity. If such entity was not found, then 0 is *   returned */function synonyms_get_entity_by_synonym($entity_type, $name, $bundle = NULL) {  $name = trim($name);  $entity_info = entity_get_info($entity_type);  // This is somewhat hacky, but it's the best we can do: user.module does not  // declare 'label' entity key on 'user' entity type, while there is clearly  // one: the 'name' column. In fact, entityreference.module does about the same  // thing in EntityReference_SelectionHandler_Generic_user class.  if ($entity_type == 'user') {    $entity_info['entity keys']['label'] = 'name';  }  if (isset($entity_info['entity keys']['label'])) {    $efq = new EntityFieldQuery();    $efq->entityCondition('entity_type', $entity_type);    if ($bundle) {      $efq->entityCondition('bundle', $bundle);    }    $efq->propertyCondition($entity_info['entity keys']['label'], $name);    $result = $efq->execute();    if (isset($result[$entity_type])) {      $result = array_keys($result[$entity_type]);      return reset($result);    }  }  $synonyms = synonyms_synonyms_find(db_and()->condition(AbstractSynonymsBehavior::COLUMN_SYNONYM_PLACEHOLDER, $name), $entity_type, $bundle);  if (!empty($synonyms)) {    return reset($synonyms)->entity_id;  }  return 0;}/** * Try to find a term by its name or synonym. * * You are advised to use the more general function * synonyms_get_entity_by_synonym() unless you really need $parent input * argument from this function for additional filtering by Taxonomy hierarchy. * * @param string $name *   The string to be searched for its {taxonomy_term_data}.tid * @param object $vocabulary *   Fully loaded vocabulary object in which you wish to search * @param int $parent *   Optional. In case you want to narrow your search scope, this parameter *   takes in the {taxonomy_term_data}.tid of the parent term, letting you *   search only among its children * * @return int *   If the look up was successful returns the {taxonomy_term_data}.tid of the *   found term, otherwise returns 0 */function synonyms_get_term_by_synonym($name, $vocabulary, $parent = 0) {  if (!module_exists('taxonomy')) {    return 0;  }  $name = trim($name);  $terms = taxonomy_get_term_by_name($name, $vocabulary->machine_name);  foreach ($terms as $term) {    if (!$parent || synonyms_taxonomy_term_is_child_of($term->tid, $parent)) {      // TODO: actually it could be so that there is more than 1 term that      // satisfies the search query, i.e. the name and parent constraints. At      // the moment we are going to return the first one we encounter, though      // something better could be thought of in the future.      return $term->tid;    }  }  // We have failed to find a term with the provided $name. So let's search now  // among the term synonyms.  $bundle = field_extract_bundle('taxonomy_term', $vocabulary);  $synonyms = synonyms_synonyms_find(db_and()->condition(AbstractSynonymsBehavior::COLUMN_SYNONYM_PLACEHOLDER, $name), 'taxonomy_term', $bundle);  foreach ($synonyms as $synonym) {    if (!$parent || synonyms_taxonomy_term_is_child_of($synonym->entity_id, $parent)) {      // TODO: similarly here, as above, we could have more than 1 match, but      // for now we will simply return the first one encountered.      return $synonym->entity_id;    }  }  // If we have reached down here, this means we haven't got any match  // as fallback we return 0.  return 0;}/** * Look up a term considering synonyms and if nothing is found add one. * * This function is useful for automated creation of new terms as it won't * generate the same terms over and over again. * * @param string $name *   The string to be searched for its {taxonomy_term_data}.tid * @param object $vocabulary *   Fully loaded vocabulary object in which you wish to search * @param int $parent *   Optional. In case you want to narrow your search scope, this parameter *   takes in the {taxonomy_term_data}.tid of the parent term, letting you *   search only among its children * * @return int *   If a term already exists, its {taxonomy_term_data}.tid is returned, *   otherwise it creates a new term and returns its {taxonomy_term_data}.tid */function synonyms_add_term_by_synonym($name, $vocabulary, $parent = 0) {  if (!module_exists('taxonomy')) {    return 0;  }  $tid = synonyms_get_term_by_synonym($name, $vocabulary, $parent);  if ($tid) {    // We found some term, returning its tid.    return $tid;  }  // We haven't found any term, so we create one.  $term = (object) array(    'name' => $name,    'vid' => $vocabulary->vid,    'parent' => array($parent),  );  taxonomy_term_save($term);  if (isset($term->tid)) {    return $term->tid;  }  // Normally we shouldn't reach up to here, because a term would have got  // created and the just created tid would have been returned. Nevertheless,  // as a fallback in case of any error we return 0.  return 0;}/** * Retrieve list of sanitized synonyms of an entity. * * @param $entity object *   Fully loaded entity * * @return array *   List of sanitized synonyms of an entity */function synonyms_get_sanitized($entity, array $options, $name, $entity_type, &$context) {  return array_map('check_plain', synonyms_get_raw($entity, $options, $name, $entity_type, $context));}/** * Retrieve list of raw synonyms of an entity. * * @param $entity object *   Fully loaded entity * * @return array *   List of raw synonyms of an entity */function synonyms_get_raw($entity, array $options, $name, $entity_type, &$context) {  $synonyms = array();  $bundle = entity_extract_ids($entity_type, $entity);  $bundle = $bundle[2];  $behavior_implementations = synonyms_behavior_get_all_enabled($entity_type, $bundle);  $providers = array();  foreach ($behavior_implementations as $implementation) {    if (!in_array($implementation['provider'], $providers)) {      $synonyms = array_merge($synonyms, $implementation['object']->extractSynonyms($entity));      $providers[] = $implementation['provider'];    }  }  return $synonyms;}/** * Public function for retrieving synonyms of a taxonomy term. * * You are encouraged to use synonyms_get_sanitized() or synonyms_get_raw() * instead. This function soon will be removed from the source code. * * @param object $term *   Fully loaded taxonomy term for which the synonyms are desired * * @return array *   Array of synonyms, if synonyms are disabled for the taxonomy term's *   vocabulary, an empty array is returned. Each synonym subarray consists of *   the following keys: *   - value: (string) the value of a synonym as it was input by user *   - safe_value: (string) a sanitized value of a synonym * * @deprecated */function synonyms_get_term_synonyms($term) {  if (!module_exists('taxonomy')) {    return array();  }  $synonyms = array();  $vocabulary = taxonomy_vocabulary_load($term->vid);  $bundle = field_extract_bundle('taxonomy_term', $vocabulary);  $behavior_implementations = synonyms_behavior_get_all_enabled('taxonomy_term', $bundle);  foreach ($behavior_implementations as $implementation) {    foreach  ($implementation['object']->extractSynonyms($term) as $synonym) {      $synonyms[] = array(        'value' => $synonym,        'safe_value' => check_plain($synonym),      );    }  }  return $synonyms;}/** * Look up entities by their synonyms. * * @param QueryConditionInterface $condition *   Object of QueryConditionInterface that specifies conditions by which you *   want to find synonyms. When building this condition object, use *   AbstractSynonymsBehavior::COLUMN_PLACEHOLDER as a placeholder for real *   column name that contains synonym as text. For example, if you were to find *   all entities with synonyms that begin with "synonym-come-here" substring, *   case insensitive and replacing all spaces in original synonym string by a *   dash sign, then you would have to create the following condition object: *   db_and() *     ->where("LOWER(REPLACE(" . AbstractSynonymsBehavior::COLUMN_PLACEHOLDER . ", ' ', '-')) LIKE :synonym", array( *       ':synonym' => '%' . db_like($some-var) . '%' *     )) *   And then just supply this object as an input parameter to this function * @param string $entity_type *   Among synonyms of what entity type to search * @param string|array $bundle *   Optionally specify among synonyms of what bundle(-s) to search. You can *   specify here a string - bundle name to search within or an array of bundles *   within which to search * * @return array *   Array of found synonyms and entity IDs to which those belong. Each element *   in the array will be an object and will have the following structure: *   - synonym: (string) Synonym that was found and which satisfies the *     $condition you specified *   - entity_id: (int) ID of the entity to which the found synonym belongs */function synonyms_synonyms_find(QueryConditionInterface $condition, $entity_type, $bundle = NULL) {  $rows = array();  $behavior_implementations = synonyms_behavior_get_all_enabled($entity_type, $bundle);  foreach ($behavior_implementations as $behavior_implementation) {    foreach ($behavior_implementation['object']->synonymsFind($condition) as $row) {      $rows[] = $row;    }  }  return $rows;}/** * Allow to merge $synonym_entity as a synonym into $trunk_entity. * * Helpful function during various merging operations. It allows you to add a * synonym (where possible) into one entity, which will represent another entity * in the format expected by the field in which the synonym is being added. * Important note: if the cardinality limit of the field into which you are * adding synonym has been reached, calling to this function will take no * effect. * * @param object $trunk_entity *   Fully loaded entity object in which the synonym is being added * @param string $trunk_entity_type *   Entity type of $trunk_entity * @param string $field *   Field name that should exist in $trunk_entity and have enabled the *   "synonyms" behavior. Into this field synonym will be added * @param object $synonym_entity *   Fully loaded entity object which will be added as a synonym * @param string $synonym_entity_type *   Entity type of $synonym_entity * * @return bool *   Whether synonym has been successfully added * * TODO: This should be shifted into Term Merge module. */function synonyms_add_entity_as_synonym($trunk_entity, $trunk_entity_type, $field, $synonym_entity, $synonym_entity_type) {  $bundle = entity_extract_ids($trunk_entity_type, $trunk_entity);  $bundle = $bundle[2];  // TODO: this somehow must be incorporated into synonyms_provider_field  // submodule.  $behavior_implementations = synonyms_behavior_get_all_enabled($trunk_entity_type, $bundle, synonyms_provider_field_provider_name(field_info_field($field)));  if (empty($behavior_implementations)) {    // $field either doesn't exist in the $trunk_entity or it does not have any    // enabled behavior.    return FALSE;  }  $behavior_implementation = reset($behavior_implementations);  $behavior_implementation['object']->mergeEntityAsSynonym($trunk_entity, $synonym_entity, $synonym_entity_type);  entity_save($trunk_entity_type, $trunk_entity);  return TRUE;}/** * Return array of field names that are sources of synonyms. * * Return array of field names that are currently have enabled the synonyms * behavior in the supplied vocabulary. This function is deprecated and shortly * will be removed from the code. All clients of this function are encourage to * use synonyms_behavior_get() function, which provides a richer set of * functionality than this one. * * @param object $vocabulary *   Fully loaded taxonomy vocabulary object * * @return array *   Array of field names * * @deprecated */function synonyms_synonyms_fields($vocabulary) {  // TODO: remove this ugly function as soon as possible. It has got hacky since  // now not only fields may be providers of synonyms.  if (!module_exists('taxonomy')) {    return array();  }  $fields = array();  $bundle = field_extract_bundle('taxonomy_term', $vocabulary);  $behavior_implementations = synonyms_behavior_get_all_enabled('taxonomy_term', $bundle);  foreach ($behavior_implementations as $v) {    $field_name = synonyms_provider_field_field_name($v['provider']);    if (field_info_field($field_name)) {      $fields[] = $field_name;    }  }  return $fields;}/** * Implements hook_views_api(). */function synonyms_views_api() {  return array(    'api' => 3,    'path' => drupal_get_path('module', 'synonyms') . '/views',  );}/** * Load function for existing implementations of synonyms behaviors. * * @param string $behavior *   Name of the synonyms behavior whose existing implementations should be *   loaded. Basically it has to be name of a ctools plugin of "behavior" type. * @param string $entity_type *   Behavior implementations of what entity type should be looked up * @param string|array $bundle *   Behavior implementations of what bundle(-s) should be looked up. If you *   want to look up only a single bundle, provide a string. If you want to *   look up multiple bundles at a time, provide an array of bundles. Empty *   array here would mean to include all bundles that are known within provided *   $entity_type * @param bool $only_enabled *   Optional filter to limit the search for existing implementations only to *   those that are currently enabled * * @return array *   Array of loaded existing synonyms behavior implementations. The underlying *   array will have the following structure: *   - behavior: (string) Behavior name of this behavior implementation, i.e. *     name of a ctools plugin of "behavior" type *   - entity_type: (string) Entity type to which this behavior implementation *     applies *   - bundle: (string) Bundle name to which this behavior implementation *     applies *   - provider: (string) Machine name of this synonyms behavior implementation *   - label: (string) Human friendly name of this synonyms behavior *     implementation *   - class: (string) Name of PHP class that implements behavior interface *   - settings: (mixed) Behavior settings, its internal structure depends on *     the type of behavior. If this value is NULL, it means the behavior *     implementation is currently disabled *   - object: (SynonymsBehavior) If the synonyms behavior implementation is *     enabled, this property will contain a fully initialized object that *     corresponds to this behavior implementation. This object is ready for *     use: to query for synonyms or invoke any other methods behavior interface *     declares *   - module: (string) Name of the module that provides this synonyms behavior *     implementation */function synonyms_behavior_get($behavior, $entity_type, $bundle, $only_enabled = FALSE) {  $behavior_implementations = array();  $enabled_behavior_implementations = array();  $query = db_select('synonyms_settings', 's');  $query->fields('s');  $query->condition('behavior', $behavior);  $query->condition('entity_type', $entity_type);  $query->condition('bundle', synonyms_bundle_normalize($entity_type, $bundle));  $result = $query->execute();  foreach ($result as $row) {    $row = (array) $row;    if ($only_enabled) {      $behavior_implementations[] = $row;    }    else {      $enabled_behavior_implementations[$row['bundle']][$row['provider']] = $row;    }  }  if (!$only_enabled) {    foreach (synonyms_bundle_normalize($entity_type, $bundle) as $bundle_name) {      foreach (synonyms_behavior_implementation_info($entity_type, $bundle_name, $behavior) as $provider_info) {        if (isset($enabled_behavior_implementations[$bundle_name][$provider_info['provider']])) {          $provider_info['settings_serialized'] = $enabled_behavior_implementations[$bundle_name][$provider_info['provider']]['settings_serialized'];        }        $behavior_implementations[] = $provider_info;      }    }  }  return synonyms_behavior_settings_unpack($behavior_implementations);}/** * Load all enabled behavior implementations on an entity_type and a bundle. * * This is useful when you want to do some operation on all enabled behavior * implementations for a specific entity_type and a bundle. * * @param string $entity_type *   Optionally filter by entity type whose enabled behavior implementations *   should be loaded * @param string|array $bundle *   Optionally filter by bundle whose enabled behavior implementations should *   be loaded. You can supply here string - single bundle name or an array of *   bundle names. Empty array implies all existing bundle names for a provided *   $entity_type * @param string $provider *   Optional filter to only return enabled synonyms behavior implementations of *   a specific provider * @param string $behavior *   Optional filter to only return enabled synonyms behavior implementations of *   a specific behavior * * @return array *   Array of enabled behavior implementations for a provided entity type and a *   bundle. Return structure of this function is identical to the return *   structure of synonyms_behavior_get() */function synonyms_behavior_get_all_enabled($entity_type = NULL, $bundle = array(), $provider = NULL, $behavior = NULL) {  $query = db_select('synonyms_settings', 's');  $query->fields('s');  if ($entity_type) {    $query->condition('entity_type', $entity_type);    $query->condition('bundle', synonyms_bundle_normalize($entity_type, $bundle));  }  if ($provider) {    $query->condition('provider', $provider);  }  if ($behavior) {    $query->condition('behavior', $behavior);  }  $result = $query->execute();  $behavior_implementations = array();  foreach ($result as $row) {    $behavior_implementations[] = (array) $row;  }  return synonyms_behavior_settings_unpack($behavior_implementations);}/** * Retrieve information about all cTools plugins of type 'synonyms behavior'. * * @return array *   Array of information on all available synonyms behavior plugins */function synonyms_behaviors() {  ctools_include('plugins');  return ctools_get_plugins('synonyms', 'behavior');}/** * Collect info on available synonyms behavior implementations. * * @param string $entity_type *   Entity type whose available synonyms behavior implementations to collect * @param string $bundle *   Bundle whose available synonyms behavior implementations to collect * @param string $behavior *   Name of behavior whose available synonyms behavior implementations to *   collect * * @return array *   Array of available synonyms behavior implementations. Each synonym behavior *   implementation will be an array with the following structure: *   - provider: (string) Machine name of the synonyms behavior implementation *   - label: (string) Human name of the synonyms behavior implementation *   - class: (string) Name of PHP class that implements behavior interface *     which is stated in cTools behavior plugin definition *   - entity_type: (string) Entity type that corresponds to this synonyms *     behavior implementation *   - bundle: (string) Bundle that corresponds to this synonyms behavior *     implementation *   - behavior: (string) Name of behavior that corresponds to this synonyms *     behavior implementation *   - module: (string) Name of the module that provides this synonyms behavior *     implementation */function synonyms_behavior_implementation_info($entity_type, $bundle, $behavior) {  $providers = array();  foreach (module_implements('synonyms_behavior_implementation_info') as $module) {    foreach (module_invoke($module, 'synonyms_behavior_implementation_info', $entity_type, $bundle, $behavior) as $provider) {      $provider['entity_type'] = $entity_type;      $provider['behavior'] = $behavior;      $provider['bundle'] = $bundle;      $provider['module'] = $module;      $providers[$provider['provider']] = $provider;    }  }  return $providers;}/** * Execute unpacking on the just loaded synonyms behavior implementations. * * @param array $behavior_implementations *   Array of the just loaded behavior_implementations. Each sub array should *   contain the following keys: *   - entity_type: (string) Entity type that corresponds to this behavior *     implementation *   - bundle: (string) Bundle that corresponds to this behavior implementation *   - provider: (string) Machine name of this synonyms behavior implementation *   - behavior: (string) name of the synonyms behavior to which these settings *     apply *   - settings_serialized: (string) serialized content of the settings * * @return array *   Unpacked version of the provided $settings */function synonyms_behavior_settings_unpack($behavior_implementations) {  // Array of previously queried synonyms provider info.  $cache = array();  foreach ($behavior_implementations as &$behavior_implementation) {    if (!isset($cache[$behavior_implementation['behavior']][$behavior_implementation['entity_type']][$behavior_implementation['bundle']])) {      $cache[$behavior_implementation['behavior']][$behavior_implementation['entity_type']][$behavior_implementation['bundle']] = synonyms_behavior_implementation_info($behavior_implementation['entity_type'], $behavior_implementation['bundle'], $behavior_implementation['behavior']);    }    // Behavior implementation info may be not available in some rare extreme    // cases. For example, when a field instance is being deleted.    if (isset($cache[$behavior_implementation['behavior']][$behavior_implementation['entity_type']][$behavior_implementation['bundle']][$behavior_implementation['provider']])) {      $behavior_implementation += $cache[$behavior_implementation['behavior']][$behavior_implementation['entity_type']][$behavior_implementation['bundle']][$behavior_implementation['provider']];    }    if (isset($behavior_implementation['settings_serialized'])) {      $behavior_implementation['settings'] = unserialize($behavior_implementation['settings_serialized']);      if (isset($behavior_implementation['class'])) {        $class = $behavior_implementation['class'];        $behavior_implementation['object'] = new $class($behavior_implementation);      }    }  }  unset($behavior_implementation);  return $behavior_implementations;}/** * Save the provided synonyms behavior implementation into the database. * * @param array $behavior_implementation *   Behavior implementation array, such as one from synonyms_behavior_get() or *   alike */function synonyms_behavior_implementation_save($behavior_implementation) {  if (!isset($behavior_implementation['settings'])) {    $behavior_implementation['settings'] = array();  }  $behavior_implementation['settings_serialized'] = serialize($behavior_implementation['settings']);  $result = db_merge('synonyms_settings')    ->key(array(      'entity_type' => $behavior_implementation['entity_type'],      'bundle' => $behavior_implementation['bundle'],      'provider' => $behavior_implementation['provider'],      'behavior' => $behavior_implementation['behavior'],    ))    ->fields(array(      'entity_type' => $behavior_implementation['entity_type'],      'bundle' => $behavior_implementation['bundle'],      'provider' => $behavior_implementation['provider'],      'behavior' => $behavior_implementation['behavior'],      'settings_serialized' => $behavior_implementation['settings_serialized'],    ))    ->execute();  switch ($result) {    case MergeQuery::STATUS_INSERT:      $behavior_definition = synonyms_behaviors();      $behavior_definition = $behavior_definition[$behavior_implementation['behavior']];      $enabled_callback = ctools_plugin_get_function($behavior_definition, 'enabled callback');      if ($enabled_callback) {        $enabled_callback($behavior_definition, $behavior_implementation);      }      break;  }}/** * Delete behavior implementation from database. * * @param array $behavior_implementation *   Behavior implementation array, such as one from synonyms_behavior_get() or *   alike */function synonyms_behavior_implementation_delete($behavior_implementation) {  $behavior_definition = synonyms_behaviors();  $behavior_definition = $behavior_definition[$behavior_implementation['behavior']];  $disabled_callback = ctools_plugin_get_function($behavior_definition, 'disabled callback');  if ($disabled_callback) {    foreach (synonyms_behavior_get($behavior_implementation['behavior'], $behavior_implementation['entity_type'], $behavior_implementation['bundle'], TRUE) as $enabled_behavior_implementation) {      if ($enabled_behavior_implementation['provider'] == $behavior_implementation['provider']) {        $disabled_callback($behavior_definition, $behavior_implementation);        break;      }    }  }  db_delete('synonyms_settings')    ->condition('provider', $behavior_implementation['provider'])    ->condition('entity_type', $behavior_implementation['entity_type'])    ->condition('bundle', $behavior_implementation['bundle'])    ->condition('behavior', $behavior_implementation['behavior'])    ->execute();}/** * Convert synonyms friendly select widget values for storage friendly format. * * It acts similar to what the _options_form_to_storage() function does - * bridges between how values are returned from form API to how they are * expected by Field module. */function synonyms_select_form_to_storage($element, &$form_state) {  $form_state_value = array();  foreach (drupal_array_get_nested_value($form_state['values'], $element['#parents']) as $entity_id) {    $form_state_value[] = array($element['#columns'][0] => $entity_id);  }  form_set_value($element, $form_state_value, $form_state);}/** * Element validate handler. * * Convert selected synonyms into their terms and save the updated data in the * value of the form element. */function synonyms_select_validate($element, &$form_state) {  $value = array();  if ($element['#multiple']) {    $value = $element['#value'];  }  else {    $value[] = $element['#value'];  }  foreach ($value as $k => $v) {    // For the cases when a synonym was selected and not an entity option, we    // process the selected values stripping everything that goes after    // semicolon.    if (!is_numeric($v)) {      $entity_id = explode(':', $v);      $value[$k] = $entity_id[0];    }  }  // The user also might have selected multiple times the same entity, given  // that an entity can be represented by more than 1 option (an entity and its  // synonym), then it's possible in theory, so we should be ready for this  // scenario.  $value = array_unique($value);  form_set_value($element, $value, $form_state);}/** * Check whether a taxonomy term $tid is a child of a taxonomy term $parent_tid. * * Supportive function, used throughout this module for parent constrains. * * @param int $tid *   {taxonomy_term}.tid of the term that is tested for being a child of the *   $parent_tid term * @param int $parent_tid *   {taxonomy_term}.tid of the term that is tested for being parent of the $tid *   term * * @return bool *   Whether $tid is a child of $parent_tid */function synonyms_taxonomy_term_is_child_of($tid, $parent_tid) {  $term_parents = taxonomy_get_parents_all($tid);  // Dropping out the term itself from its array of parents.  array_shift($term_parents);  foreach ($term_parents as $term_parent) {    if ($term_parent->tid == $parent_tid) {      return TRUE;    }  }  return FALSE;}/** * Format an option for entity reference select form element. * * @param object $entity *   Fully loaded entity which is represented by this option * @param string $entity_type *   Entity type of the $entity object * @param string $synonym *   If the provided entity is represented in this option by a synonym, then *   provide it here * @param array $behavior_implementation *   Behavior implementation array from which the $synonym comes from * @param array $options *   Array of additional settings or options that may influence execution of *   this function. Currently supported options are: *   - depth: Whether to prefix wording of option labels with depth of the *     entity. This will work only for taxonomy term entities, as they are the *     only ones that have notion of depth * * @return object *   An option for entity reference select form element */function synonyms_select_option_entity($entity, $entity_type, $synonym = NULL, $behavior_implementation = NULL, $options = array()) {  $entity_id = entity_extract_ids($entity_type, $entity);  $entity_id = $entity_id[0];  $key = $synonym ? $entity_id . ':' . drupal_html_class($synonym) : $entity_id;  $wording = entity_label($entity_type, $entity);  if ($synonym) {    $wording = format_string($behavior_implementation['settings']['wording'], array(      '@synonym' => $synonym,      '@entity' => entity_label($behavior_implementation['entity_type'], $entity),      '@field_name' => drupal_strtolower($behavior_implementation['label']),    ));  }  if (in_array('depth', $options) && $entity_type == 'taxonomy_term') {    $depth = count(taxonomy_get_parents_all($entity_id)) - 1;    $wording = str_repeat('-', $depth) . $wording;  }  return (object) array(    'option' => array($key => $wording),  );}/** * Construct options array for entity reference synonyms friendly select list. * * @param array $field *   Field definition array of entityreference type for which to construct the *   options * @param array $instance *   Field instance definition array that corresponds to $field * @param object $entity *   If entity is known for which the options should be generated, provide it *   here. It is safe to omit this parameter. Frankly, I do not understand well *   why or how it is used. It is just directly passed into entityreference *   selection handler class * * @return array *   Options array that can be plugged in directly into any #select form element */function synonyms_select_entity_options($field, $instance, $entity = NULL) {  $options = entityreference_get_selection_handler($field, $instance, $instance['entity_type'], $entity)->getReferencableEntities();  $synonyms_options = array();  $target_entity_info = entity_get_info($field['settings']['target_type']);  $entity_ids = array();  foreach ($options as $bundle_entity_ids) {    $entity_ids = array_merge($entity_ids, array_keys($bundle_entity_ids));  }  $entities = entity_load($field['settings']['target_type'], $entity_ids);  foreach ($options as $bundle => $bundle_entity_ids) {    $synonyms_options[$target_entity_info['bundles'][$bundle]['label']] = array();    $behavior_implementations = synonyms_behavior_get('select', $field['settings']['target_type'], $bundle, TRUE);    foreach ($bundle_entity_ids as $entity_id => $v) {      $entity = $entities[$entity_id];      $synonyms_options[$target_entity_info['bundles'][$bundle]['label']][] = synonyms_select_option_entity($entity, $field['settings']['target_type']);      foreach ($behavior_implementations as $behavior_implementation) {        foreach ($behavior_implementation['object']->extractSynonyms($entity) as $synonym) {          $synonyms_options[$target_entity_info['bundles'][$bundle]['label']][] = synonyms_select_option_entity($entity, $field['settings']['target_type'], $synonym, $behavior_implementation);        }      }    }    usort($synonyms_options[$target_entity_info['bundles'][$bundle]['label']], 'synonyms_select_sort_name');  }  if (count($synonyms_options) == 1) {    $synonyms_options = reset($synonyms_options);  }  return $synonyms_options;}/** * Supportive function to build taxonomy term options array sorted by name. * * The function starts from the 0-depth level and starts to recursively build * the options and to sort the labels on each level, then it merges the bottom * to up all the levels maintaining correct order within the final options * array. * * @param object $vocabulary *   Within which vocabulary to execute the function. Supply here the fully *   loaded taxonomy vocabulary object * @param int $parent *   Only children of this term will be included in the output. You can supply *   0 which means to include all the terms from the vocabulary * @param int $depth *   Used for internal purposes. Clients of this function should supply here 0, *   unless they know what they are doing. It is used internally to keep track *   of the nesting level * * @return array *   Array of options that can be inserted directly into 'select' form element. *   The options will be sorted by name (term or synonym), respecting the *   hierarchy restrictions */function synonyms_select_taxonomy_term_sort_name_options_recursive($vocabulary, $parent = 0, $depth = 0) {  // We statically cache behavior implementations in order to not DDOS the data  // base.  $behavior_implementations = &drupal_static(__FUNCTION__, array());  $bundle = field_extract_bundle('taxonomy_term', $vocabulary);  if (!isset($behavior_implementations[$bundle])) {    $behavior_implementations[$bundle] = synonyms_behavior_get('select', 'taxonomy_term', $bundle, TRUE);  }  $options = array();  if ($terms = taxonomy_get_tree($vocabulary->vid, $parent, 1, TRUE)) {    $options = array();    foreach ($terms as $term) {      $term->depth = $depth;      $options[] = synonyms_select_option_entity($term, 'taxonomy_term', NULL, NULL, array('depth'));      foreach ($behavior_implementations[$bundle] as $implementation) {        foreach ($implementation['object']->extractSynonyms($term) as $synonym) {          $options[] = synonyms_select_option_entity($term, 'taxonomy_term', $synonym, $implementation, array('depth'));        }      }    }    usort($options, 'synonyms_select_sort_name');    // Now recursively go one level nested into each of the terms that we have    // on this level.    $options_copy = $options;    $i = 0;    foreach ($options_copy as $v) {      $i++;      $tid = array_keys($v->option);      $tid = $tid[0];      if (is_numeric($tid)) {        $nested_options = synonyms_select_taxonomy_term_sort_name_options_recursive($vocabulary, $tid, $depth + 1);        $options = array_merge(array_slice($options, 0, $i), $nested_options, array_slice($options, $i));      }    }  }  return $options;}/** * Supportive function. * * It is used for string comparison within synonyms friendly select widget. */function synonyms_select_sort_name($a, $b) {  return strcasecmp(reset($a->option), reset($b->option));}/** * Test if entity type is applicable for having synonyms. * * @param string $entity_type *   Entity type to test * * @return bool|string *   Whether the provided entity type is applicable for having synonyms. If it *   is applicable, the $entity_type input argument will be returned. Otherwise *   FALSE is returned */function synonyms_entity_type_load($entity_type) {  if (module_exists('synonyms_provider_property')) {    // If this submodule is enabled, we get into infinite recursion. Moreover,    // it is very likely all entity types will have at least 1 property on them,    // so the synonyms_provider_property module will get at least 1 synonym for    // every entity type. So it is quite safe assumption to say we accept about    // any entity type.    return $entity_type;  }  $bundles = synonyms_bundle_normalize($entity_type, array());  foreach (synonyms_behaviors() as $behavior => $behavior_definition) {    foreach ($bundles as $bundle) {      $behavior_implementations = synonyms_behavior_implementation_info($entity_type, $bundle, $behavior);      if (!empty($behavior_implementations)) {        return $entity_type;      }    }  }  return FALSE;}/** * Test if provided entity type and bundle are applicable for having synonyms. * * @param string $bundle *   Bundle name to test for ability to have synonyms * @param string $entity_type *   Entity type to test for ability to have synonyms * * @return bool|string *   Whether the provided entity type and bundle may have synonyms. If they do, *   the $bundle input argument is returned. Otherwise FALSE is returned */function synonyms_bundle_load($bundle, $entity_type) {  foreach (synonyms_behaviors() as $behavior => $behavior_definition) {    $behavior_implementations = synonyms_behavior_implementation_info($entity_type, $bundle, $behavior);    if (!empty($behavior_implementations)) {      return $bundle;    }  }  return FALSE;}/** * Menu title callback function for synonyms settings page. * * @param string $entity_type *   Entity type whose synonyms settings are managed * @param string $bundle *   Bundle whose synonyms settings are managed * * @return string *   Title of the synonyms settings page */function synonyms_settings_title($entity_type, $bundle) {  $entity_info = entity_get_info($entity_type);  $entity_label = isset($entity_info['plural label']) ? $entity_info['plural label'] : $entity_info['label'];  if ($entity_type == $bundle) {    return t('Synonyms settings of @entity_type', array(      '@entity_type' => $entity_label,    ));  }  return t('Synonyms settings of @bundle @entity_type', array(    '@bundle' => $entity_info['bundles'][$bundle]['label'],    '@entity_type' => $entity_label,  ));}/** * Escape string to safely use in autocomplete text field as default value. * * @param string $value *   String to be escaped * * @return string *   Escaped string $value */function synonyms_autocomplete_escape($value) {  // Commas or quotes must be wrapped in quotes.  if (strpos($value, ',') !== FALSE || strpos($value, '"') !== FALSE) {    $value = '"' . str_replace('"', '""', $value) . '"';  }  return $value;}/** * Determine a list of target bundles of an entityreference field. * * @param array $field *   Field definition array. This field must be of type 'entityreference' * * @return array|null *   List of target bundles per the settings of provided field or NULL if the *   provided field does not expose any limitations on target bundles */function synonyms_field_target_bundles($field) {  $target_bundles = isset($field['settings']['handler_settings']['target_bundles']) ? array_values($field['settings']['handler_settings']['target_bundles']) : array();  if (empty($target_bundles)) {    $target_bundles = NULL;  }  return $target_bundles;}/** * Normalize bundle argument. * * @param string $entity_type *   Entity type to define scope of bundles * @param string|array $bundle *   Either a single bundle name or an array of bundle names. Empty array *   implies all known bundles for $entity_type * * @return array *   Normalized array bundle names */function synonyms_bundle_normalize($entity_type, $bundle) {  $bundle = (array) $bundle;  if (empty($bundle)) {    $bundle = array_keys(field_info_bundles($entity_type));  }  return $bundle;}/** * Extract default value for a select widget of Synonyms module. * * @param array $field *   Field definition array whose default value should be extracted * @param array $instance *   Field instance definition array whose default value should be extracted * @param array $items *   Array of items that should compose default value * * @return array *   Array of default value that can be plugged in into a select widget */function synonyms_select_default_value($field, $instance, $items) {  $default_value = array();  $column = array_keys($field['columns']);  $column = reset($column);  foreach ($items as $item) {    $default_value[] = $item[$column];  }  return $default_value;}
 |