Daniel-KM / Omeka-plugin-Reference

Plugin for Omeka that allows to serve alphabetized indexes of selected item types and elements of all items of an Omeka instance, or an expandable hierarchical list of all subjects. These pages can be displayed in any page via a helper or a shortcode.
8 stars 4 forks source link

Sort special characters #4

Open laportjo opened 7 years ago

laportjo commented 7 years ago

Hi Daniel,

Is there a way to sort correctly special characters in a list via the helper reference() ? For example, I have this list (excerpt) :

But I expect this order :

Thanks ! Your plugin is very wonderful.

Daniel-KM commented 7 years ago

You have to change the line https://github.com/Daniel-KM/Reference/blob/master/views/helpers/Reference.php#L287 with " utf8_roman_ci" (or add an option to manage it cleanly).

laportjo commented 7 years ago

It doesn't seem to work. I get the same list order.

Daniel-KM commented 7 years ago

So you can sort the resulting array via php just after that.

silviaegt commented 5 years ago

Hi @Daniel-KM, thank you so much for your tool. We find it very useful! However we encountered the same problem as @laportjo (cf. http://sandbox.colmex.mx/~silvia/omeka25/references/creator#number) We also changed the Reference.php line you mentioned (we tried utf8_roman_ci; utf8_general_ci; and utf8mb4_unicode_ci [following this post]), but it didn't have any effect.

Also, we don't quite understand what you mean by: "or add an option to manage it cleanly" nor with " you can sort the resulting array via php just after that"

Thanks in advance for any help you could provide us :)

Daniel-KM commented 5 years ago

The file to edit is the view one : https://github.com/Daniel-KM/Omeka-plugin-Reference/blob/master/views/public/common/reference-list.php. It's hard to resolve, because it's a mix of locale format of the server, of the database and of php. As always with cms, copy this file in your theme (in common/reference-list.php), in order to keep the plugin clean and your site maintainable.

zerocrates commented 5 years ago

MySQL should be handling this sorting fine, whether under the default Omeka collation of utf8_unicode_ci or with utf8_general_ci.

I think the issue here is actually happening because of the PHP-side "re-sorting" that happens when the strip option is enabled. You can turn off strip and thereby rely only on the MySQL-side sorting, or you can replace the uksort in the Reference helper with something like this: (you'll need the PHP intl extension, though)

$collator = new Collator('root');
uksort($references, array($collator, 'compare'));

But, this would also require a change in the logic for generating headings: it will currently "see" the change from A to Á (and back again to A if the accented word appears in the middle of the list) and output extra headings.

Daniel-KM commented 5 years ago

Thanks, I'll give it a try.

rodyoukai commented 5 years ago

Hi all,

I solve the problem.

First, Comment this line:

https://github.com/Daniel-KM/Omeka-plugin-Reference/blob/master/views/helpers/Reference.php#L128

Because natcasesort does not support diacritics.

Second add this function on top of https://github.com/Daniel-KM/Omeka-plugin-Reference/blob/master/views/public/common/reference-list.php

<?php
function normaliza ($cadena){
    $originales = 'ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûýýþÿŔŕ';
    $modificadas = strtoupper('aaaaaaaceeeeiiiidnoooooouuuuy').'bsaaaaaaaceeeeiiiidnoooooouuuyybyRr';
    $cadena = utf8_decode($cadena);
    $cadena = strtr($cadena, utf8_decode($originales), $modificadas);
    return utf8_encode($cadena);
}

Third apply this function in reference-list.php in lines 22 & 60, as follows:

$first_char = normaliza(function_exists('mb_substr') ? mb_substr($reference, 0, 1) : substr($reference, 0, 1));

Fourth step... enjoy!!!

DBinaghi commented 4 years ago

Sorry, @rodyoukai, but I've tried your method and don't see any change. Could you please provide a working example, like a live repository? thanks

DBinaghi commented 4 years ago
$collator = new Collator('root');
uksort($references, array($collator, 'compare'));

This solution works very well for me, thanks. I've also changed the headings functions, like this:

// Get the list of headers.
$collator = new Collator('root');
uksort($references, array($collator, 'compare'));
$alphabet = array('A','B','C','Ĉ','D','E','È','F','G','Ĝ','H','Ĥ','I','J','Ĵ','K','L','M','N','O','P','Q','R','S','Ŝ','T','U','Ŭ','V','X','Y','W','Z');
$letters = array('number' => false) + array_fill_keys($alphabet, false);
foreach ($references as $reference => $referenceData):
    $first_char = mb_substr($reference, 0, 1, 'UTF-8');
    if (strlen($first_char) == 0 || preg_match('/\W|\d/u', $first_char)):
        $letters['number'] = true;
    else:
        $first_char = mb_strtoupper($first_char, 'UTF-8');;
        $letters[$first_char] = true;
    endif;
endforeach;
$pagination_list = '<ul class="pagination_list">';
foreach ($letters as $letter => $isSet):
    $letterDisplay = ($letter == 'number' ? '#0-9' : $letter);
    if ($isSet):
        $pagination_list .= sprintf('<li class="pagination_range"><a href="#%s">%s</a></li>', $letter, $letterDisplay);
    else:
        $pagination_list .= sprintf('<li class="pagination_range"><span>%s</span></li>', $letterDisplay);
    endif;
endforeach;

Similarly, then, for the references list. Hope this helps.

DBinaghi commented 4 years ago
$alphabet = array('A','B','C','Ĉ','D','E','È','F','G','Ĝ','H','Ĥ','I','J','Ĵ','K','L','M','N','O','P','Q','R','S','Ŝ','T','U','Ŭ','V','X','Y','W','Z');
$letters = array('number' => false) + array_fill_keys($alphabet, false);

I've amended my fork, with a config option to add a custom alphabet to be used for skip links headers:

$alphabet = (get_option('reference_list_alphabet') != '' ? explode(' ', get_option('reference_list_alphabet')) : array_fill_keys(range('A', 'Z'), false)); 
$letters = array('number' => false) + array_fill_keys($alphabet, false);