- Published on
 
Alter Views sort by taxonomy weight
- Authors
 - Name
 - Christophe Jossart
 - Mastodon
 - @colorfield
 

The use case is to sort a list of users by job title, where job title is a term reference to a dedicated vocabulary.
The sort is done by the job title term weight (defined via the vocabulary list).
I choosed to apply a custom sort function on a view, instead of a custom dynamic / entity query for two reasons :
- the client have access to Views so he can continue to apply changes via the UI (format, fields, filters, ...)
 - the query involves third party database (CiviCRM) that is already well handled by the CiviCRM Entity module so we can avoid custom API call to CiviCRM.
 
/**
 * Implements hook_views_pre_render().
 *
 * Applies custom sort by job title weight on a view.
 *
 * @param $view
 */
function my_module_views_pre_render(&$view) {
  if($view->name == 'my_view') {
    // load vocabulary
    $job_title_vocab = taxonomy_vocabulary_machine_name_load('job_title');
    $job_titles = taxonomy_get_tree($job_title_vocab->vid);
    // index for fast weight retrieval, avoids nested foreach
    $job_title_weight = array();
    foreach ($job_titles as $job_title) {
      $job_title_weight[$job_title->tid] = $job_title->weight;
    }
    foreach ($view->result as $user) {
      // assume we fetch the first one if multiple
      $user_job_title = $user->field_field_job_title[0]['raw']['tid'];
      // append my_module_job_title_weight property to sort on, shorthand
      $user->my_module_job_title_weight = $job_title_weight[$user_job_title];
    }
    usort($view->result, '_my_module_job_title_weight_compare');
  }
}
/**
 * Comparable functor to be used by usort.
 *
 * @param $a
 * @param $b
 *
 * @return int
 */
function _my_module_job_title_weight_compare($a, $b) {
  if ($a->my_module_job_title_weight == $b->my_module_job_title_weight) {
    return 0;
  }
  return ($a->my_module_job_title_weight < $b->my_module_job_title_weight) ? -1 : 1;
}