Comment 17 for bug 803806

Revision history for this message
David E Drury (david-drury) wrote : Re: Recent changes module sort error

OK,
Lets see if I can demonstrate why the current sort is broken.

Below are two segments of code; function print_changes_list (in functions_print_lists.php line 1308) is called directly from the module with parameter 1 being a list of IDs (not only individuals as I said earlier but family, media etc.) meeting the required criteria and lets also assume the $sort parameter is set to either 'date_asc' or 'date_desc'. Function event_sort is found in functions.php at line 988.

The foreach loop at line 5 builds the array $arr needed later; at line 12 $arr[$n]['jd'] is assigned the value of $n (bacause $sort does not equal 'name' (the value of $n is initially 0 and is incremented each time through the foreach at line 14)

When the foreach has completed, the switch statements for one of the date cases will be invoked thus 'uasort'ing the array $arr with event_sort as the compare function. Line 29 checks if $a['jd'] == $b['jd']. They cannot be equal as demonstrated above (they were each assigned a different value of $n), therefore the else statement at line 36 is executed and the result of comparing the two numbers is returned. The code that would actually compare the change dates at lines 30-38 is never invoked.

1. function print_changes_list($change_ids, $sort, $show_parents=false) {
2. global $SHOW_MARRIED_NAMES;
3. $n = 0;
4. $arr=array();
5. foreach ($change_ids as $change_id) {
6. $record = WT_GedcomRecord::getInstance($change_id);
7. if (!$record || !$record->canDisplayDetails()) {
8. continue;
9. }
10. // setup sorting parameters
11. $arr[$n]['record'] = $record;
12. $arr[$n]['jd'] = ($sort == 'name') ? 1 : $n;
13. $arr[$n]['anniv'] = $record->LastChangeTimestamp(false, true);
14. $arr[$n++]['fact'] = $record->getSortName(); // in case two changes have same timestamp
15. }
16.
17. switch ($sort) {
18. case 'name':
19. uasort($arr, 'event_sort_name');
20. break;
21. case 'date_asc':
22. uasort($arr, 'event_sort');
23. $arr = array_reverse($arr);
24. break;
25. case 'date_desc':
26. uasort($arr, 'event_sort');
27. }

 etc...

28. function event_sort($a, $b) {
29. if ($a['jd']==$b['jd']) {
30. if ($a['anniv']==$b['anniv']) {
31. return utf8_strcasecmp($a['fact'], $b['fact']);
32. }
33. else {
34. return $a['anniv']-$b['anniv'];
35. }
36. } else {
37. return $a['jd']-$b['jd'];
38. }
39.}

Now whilst the code I submitted earlier does work, I realised last night that it is unnecessarily complicated, I therefore now submit a revised print_changes_list function and also a modified module.php which introduces an extra sort option to allow sorting by name A-Z or name Z-A. Should you not wish to change the module, the changes to the print_changes_list function will still work

Phew!
Dave