2

I am trying to find a way to sort the referenced entities in a node. I have found a related question "Ordering of referenced entity" but it cannot be applied in my case for the following reasons:

1) The manual ordering is out of the question in my case. In some of the nodes that need to be fixed there are more than 2000 referenced entities and they are ordered randomly right now. I also need to find a way to do that efficiently, since there will be a lot of nodes in the future that will also have multiple entity references that will need to be ordered.

2) The array_reverse option will obviously not work since the referenced entities are ordered in a completely random manner.

3) The third option in the accepted answer does not even apply to sorting.

4) The rest of the answers are just improvements over the accepted answer's methodology and obviously cannot be applied.

What I would ideally like to achieve is grab the first number in the title of the referenced entity and use this to sort the referenced entities.

Note: It is very important to handle cases of "software release number ordering" which in plain English means that 1.1 comes before 1.2 which in turn comes before 1.10.

1 Answer 1

2

I recently faced a similar problem and I solved it using the hook_form_FORM_ID_alter hook so that I can have an overview of the changes before actually applying them. My idea was to set the weight of each entity reference field to the number that can be found in the referenced entity's title. In your case however, the "numbers" in your title are not actual numbers with decimal parts but 2 different numbers that happen to be connected with a period (the first number has higher priority in the ordering than the second).

In your case you should do something like this:

function YOUR_MODULE_NAME_form_YOUR_CONTENT_TYPE_node_form_alter(&$form, &$form_state, $form_id) {
  if($form['nid']['#value'] == "22312") {  // The node id instead of 22312
    $keys = array_keys($form['field_FROM_ENTITY_REFERENCE']['und']);
    foreach ($keys as $value) {
      if (is_numeric($value)) {
        $weight = preg_match_all("/\d+\.\d+/", $form['field_FROM_ENTITY_REFERENCE']['und'][$value]['target_id']['#default_value'], $matches);
        if (empty($matches[0])) {
          $weight = preg_match_all("/\d+/", $form['field_FROM_ENTITY_REFERENCE']['und'][$value]['target_id']['#default_value'], $matches);
        }
        if (!empty($matches[0])) {
          $tempweight = explode(".", $matches[0][0]);
          $lengthtopad = (isset($tempweight[1])) ? 5 - strlen($tempweight[1]) : 5;
          $tempweight[0] = str_pad($tempweight[0], $lengthtopad, "0");
          $finalweight = implode("", $tempweight);
          $form['field_FROM_ENTITY_REFERENCE']['und'][$value]['_weight']['#default_value'] = $finalweight;
        }
      }
    }
  }
}

This solution is based on the idea that if from the 2 different-priority numbers that you have, you create numbers with the same amount of digits by padding the number with the highest priority with zeros, your final numbers will be properly ordered.

I assumed that the first number is single digit and that the second number can only go up to 3 digits. You can however adjust this to support more digits in the "decimal" part of the number.

Just to give you a couple of quick examples of how the numbers will look like after the transformation described above:

1 -> 10000
1.1 -> 10001
1.2 -> 10002
1.10 -> 10010
2.45 -> 20045
2.456 -> 20456

Of course, you can apply the same method to change the weights implicitly by using node_load, altering the weights and then using node_save to apply the new weights. It would work just fine, but with the solution described above, you edit the node-in-question and you can inspect the referenced entities and their ordering before deciding whether to save the node or not.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.