Completed
Pull Request — master (#3115)
by
unknown
02:51
created

sort.php ➔ intl_strcmp()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 2
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * DokuWiki sort functions
4
 *
5
 * When "intl" extension is available, all sorts are done using a collator.
6
 * Otherwise, primitive PHP functions are called.
7
 *
8
 * The collator is created using the locale given in $conf['lang'].
9
 * It always uses case insensitive "natural" ordering in its collation.
10
 * The fallback solution uses the primitive PHP functions that return almost the same results
11
 * when the input is text with only [A-Za-z0-9] characters.
12
 *
13
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
14
 * @author     Moisés Braga Ribeiro <[email protected]>
15
 */
16
17
/* @var bool $intl_extension_available */
18
$intl_extension_available = class_exists('Collator');
19
20
/**
21
 * Initialize a collator using $conf['lang'] as the locale.
22
 * The initialization is done only once, except when $reload is set to TRUE.
23
 * The collation takes "natural ordering" into account, that is, "page 2" is before "page 10".
24
 *
25
 * @param bool $reload Usually FALSE; TRUE forces collator re-creation after a change in $conf['lang']
26
 * @return Collator Returns a configured collator or NULL if the collator cannot be created.
27
 *
28
 * @author Moisés Braga Ribeiro <[email protected]>
29
 */
30
function _get_collator($reload = FALSE) {
31
    global $conf, $intl_extension_available;
32
    static $collator = NULL;
33
34
    if (!$intl_extension_available)
35
        return NULL;
36
    if ($reload || !isset($collator)) {
37
        $collator = Collator::create($conf['lang']);
38
        if (isset($collator)) {
39
            $collator->setAttribute(Collator::NUMERIC_COLLATION, Collator::ON);
40
            dbglog('Collator created with locale "' . $conf['lang'] . '": numeric collation on, ' .
41
                   'valid locale "' . $collator->getLocale(Locale::VALID_LOCALE) . '", ' .
42
                   'actual locale "' . $collator->getLocale(Locale::ACTUAL_LOCALE) . '"');
43
        }
44
    }
45
    return $collator;
46
}
47
48
/**
49
 * Drop-in replacement for strcmp(), strcasecmp(), strnatcmp() and strnatcasecmp().
50
 * It uses a collator-based comparison, or strnatcasecmp() as a fallback.
51
 *
52
 * @param string $str1 The first string.
53
 * @param string $str2 The second string.
54
 * @return int Returns < 0 if $str1 is less than $str2; > 0 if $str1 is greater than $str2, and 0 if they are equal.
55
 *
56
 * @author Moisés Braga Ribeiro <[email protected]>
57
 */
58
function intl_strcmp($str1, $str2) {
59
    $collator = _get_collator();
60
    if (isset($collator))
61
        return $collator->compare($str1, $str2);
62
    else
63
        return strnatcasecmp($str1, $str2);
64
}
65
66
/**
67
 * Drop-in replacement for sort().
68
 * It uses a collator-based sort, or sort() with flags SORT_NATURAL and SORT_FLAG_CASE as a fallback.
69
 *
70
 * @param array $array The input array.
71
 * @return bool Returns TRUE on success or FALSE on failure.
72
 *
73
 * @author Moisés Braga Ribeiro <[email protected]>
74
 */
75
function intl_sort(&$array) {
76
    $collator = _get_collator();
77
    if (isset($collator))
78
        return $collator->sort($array);
79
    else
80
        return sort($array, SORT_NATURAL | SORT_FLAG_CASE);
81
}
82
83
/**
84
 * Drop-in replacement for ksort().
85
 * It uses a collator-based sort, or ksort() with flags SORT_NATURAL and SORT_FLAG_CASE as a fallback.
86
 *
87
 * @param array $array The input array.
88
 * @return bool Returns TRUE on success or FALSE on failure.
89
 *
90
 * @author Moisés Braga Ribeiro <[email protected]>
91
 */
92
function intl_ksort(&$array) {
93
    $collator = _get_collator();
94
    if (isset($collator))
95
        return uksort($array, array($collator, 'compare'));
96
    else
97
        return ksort($array, SORT_NATURAL | SORT_FLAG_CASE);
98
}
99
100
/**
101
 * Drop-in replacement for asort(), natsort() and natcasesort().
102
 * It uses a collator-based sort, or asort() with flags SORT_NATURAL and SORT_FLAG_CASE as a fallback.
103
 *
104
 * @param array $array The input array.
105
 * @return bool Returns TRUE on success or FALSE on failure.
106
 *
107
 * @author Moisés Braga Ribeiro <[email protected]>
108
 */
109
function intl_asort(&$array) {
110
    $collator = _get_collator();
111
    if (isset($collator))
112
        return $collator->asort($array);
113
    else
114
        return asort($array, SORT_NATURAL | SORT_FLAG_CASE);
115
}
116
117
/**
118
 * Drop-in replacement for asort(), natsort() and natcasesort() when the parameter is an array of filenames.
119
 * Filenames may not be equal to page names, depending on the setting in $conf['fnencode'],
120
 * so the correct behavior is to sort page names and reflect this sorting in the filename array.
121
 *
122
 * @param array $array The input array.
123
 * @return bool Returns TRUE on success or FALSE on failure.
124
 *
125
 * @author Moisés Braga Ribeiro <[email protected]>
126
 */
127
function intl_asortFN(&$array) {
128
    $collator = _get_collator();
129
    if (isset($collator))
130
        return uasort($array, '_sort_filenames_with_collator');
131
    else
132
        return uasort($array, '_sort_filenames_without_collator');
133
}
134
135
/**
136
 * Collator-based string comparison for filenames.
137
 * The filenames are converted to page names with utf8_decodeFN() before the comparison.
138
 * 
139
 * @param string $fn1 The first filename.
140
 * @param string $fn2 The second filename.
141
 * @return int Returns < 0 if $fn1 is less than $fn2; > 0 if $fn1 is greater than $fn2, and 0 if they are equal.
142
 *
143
 * @author Moisés Braga Ribeiro <[email protected]>
144
 */
145
function _sort_filenames_with_collator($fn1, $fn2) {
146
    $collator = _get_collator();
147
    return $collator->compare(utf8_decodeFN($fn1), utf8_decodeFN($fn2));
148
}
149
150
/**
151
 * Fallback string comparison for filenames, using strnatcasecmp().
152
 * The filenames are converted to page names with utf8_decodeFN() before the comparison.
153
 * 
154
 * @param string $fn1 The first filename.
155
 * @param string $fn2 The second filename.
156
 * @return int Returns < 0 if $fn1 is less than $fn2; > 0 if $fn1 is greater than $fn2, and 0 if they are equal.
157
 *
158
 * @author Moisés Braga Ribeiro <[email protected]>
159
 */
160
function _sort_filenames_without_collator($fn1, $fn2) {
161
    return strnatcasecmp(utf8_decodeFN($fn1), utf8_decodeFN($fn2));
162
}
163