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

sort.php ➔ intl_ksort()   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 1
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.
23
 * The collation takes "natural ordering" into account, that is, "page 2" is before "page 10".
24
 *
25
 * @return Collator Returns a configured collator or NULL if the collator cannot be created.
26
 *
27
 * @author Moisés Braga Ribeiro <[email protected]>
28
 */
29
function _get_collator() {
30
    global $conf, $intl_extension_available;
31
    static $collator = NULL;
32
33
    if ($intl_extension_available && !isset($collator)) {
34
        $collator = Collator::create($conf['lang']);
35
        if (isset($collator)) {
36
            $collator->setAttribute(Collator::NUMERIC_COLLATION, Collator::ON);
37
            dbglog('Collator created with locale "' . $conf['lang'] . '": numeric collation on, ' .
38
                   'valid locale "' . $collator->getLocale(Locale::VALID_LOCALE) . '", ' .
39
                   'actual locale "' . $collator->getLocale(Locale::ACTUAL_LOCALE) . '"');
40
        }
41
    }
42
    return $collator;
43
}
44
45
/**
46
 * Drop-in replacement for strcmp(), strcasecmp(), strnatcmp() and strnatcasecmp().
47
 * It uses a collator-based comparison, or strnatcasecmp() as a fallback.
48
 *
49
 * @param string $str1 The first string.
50
 * @param string $str2 The second string.
51
 * @return int Returns < 0 if $str1 is less than $str2; > 0 if $str1 is greater than $str2, and 0 if they are equal.
52
 *
53
 * @author Moisés Braga Ribeiro <[email protected]>
54
 */
55
function intl_strcmp($str1, $str2) {
56
    $collator = _get_collator();
57
    if (isset($collator))
58
        return $collator->compare($str1, $str2);
59
    else
60
        return strnatcasecmp($str1, $str2);
61
}
62
63
/**
64
 * Drop-in replacement for sort().
65
 * It uses a collator-based sort, or sort() with flags SORT_NATURAL and SORT_FLAG_CASE as a fallback.
66
 *
67
 * @param array $array The input array.
68
 * @return bool Returns TRUE on success or FALSE on failure.
69
 *
70
 * @author Moisés Braga Ribeiro <[email protected]>
71
 */
72
function intl_sort(&$array) {
73
    $collator = _get_collator();
74
    if (isset($collator))
75
        return $collator->sort($array);
76
    else
77
        return sort($array, SORT_NATURAL | SORT_FLAG_CASE);
78
}
79
80
/**
81
 * Drop-in replacement for ksort().
82
 * It uses a collator-based sort, or ksort() with flags SORT_NATURAL and SORT_FLAG_CASE as a fallback.
83
 *
84
 * @param array $array The input array.
85
 * @return bool Returns TRUE on success or FALSE on failure.
86
 *
87
 * @author Moisés Braga Ribeiro <[email protected]>
88
 */
89
function intl_ksort(&$array) {
90
    $collator = _get_collator();
91
    if (isset($collator))
92
        return uksort($array, array($collator, 'compare'));
93
    else
94
        return ksort($array, SORT_NATURAL | SORT_FLAG_CASE);
95
}
96
97
/**
98
 * Drop-in replacement for asort(), natsort() and natcasesort().
99
 * It uses a collator-based sort, or asort() with flags SORT_NATURAL and SORT_FLAG_CASE as a fallback.
100
 *
101
 * @param array $array The input array.
102
 * @return bool Returns TRUE on success or FALSE on failure.
103
 *
104
 * @author Moisés Braga Ribeiro <[email protected]>
105
 */
106
function intl_asort(&$array) {
107
    $collator = _get_collator();
108
    if (isset($collator))
109
        return $collator->asort($array);
110
    else
111
        return asort($array, SORT_NATURAL | SORT_FLAG_CASE);
112
}
113
114
/**
115
 * Drop-in replacement for asort(), natsort() and natcasesort() when the parameter is an array of filenames.
116
 * Filenames may not be equal to page names, depending on the setting in $conf['fnencode'],
117
 * so the correct behavior is to sort page names and reflect this sorting in the filename array.
118
 *
119
 * @param array $array The input array.
120
 * @return bool Returns TRUE on success or FALSE on failure.
121
 *
122
 * @author Moisés Braga Ribeiro <[email protected]>
123
 */
124
function intl_asortFN(&$array) {
125
    $collator = _get_collator();
126
    if (isset($collator))
127
        return uasort($array, '_sort_filenames_with_collator');
128
    else
129
        return uasort($array, '_sort_filenames_without_collator');
130
}
131
132
/**
133
 * Collator-based string comparison for filenames.
134
 * The filenames are converted to page names with utf8_decodeFN() before the comparison.
135
 * 
136
 * @param string $fn1 The first filename.
137
 * @param string $fn2 The second filename.
138
 * @return int Returns < 0 if $fn1 is less than $fn2; > 0 if $fn1 is greater than $fn2, and 0 if they are equal.
139
 *
140
 * @author Moisés Braga Ribeiro <[email protected]>
141
 */
142
function _sort_filenames_with_collator($fn1, $fn2) {
143
    $collator = _get_collator();
144
    return $collator->compare(utf8_decodeFN($fn1), utf8_decodeFN($fn2));
145
}
146
147
/**
148
 * Fallback string comparison for filenames, using strnatcasecmp().
149
 * The filenames are converted to page names with utf8_decodeFN() before the comparison.
150
 * 
151
 * @param string $fn1 The first filename.
152
 * @param string $fn2 The second filename.
153
 * @return int Returns < 0 if $fn1 is less than $fn2; > 0 if $fn1 is greater than $fn2, and 0 if they are equal.
154
 *
155
 * @author Moisés Braga Ribeiro <[email protected]>
156
 */
157
function _sort_filenames_without_collator($fn1, $fn2) {
158
    return strnatcasecmp(utf8_decodeFN($fn1), utf8_decodeFN($fn2));
159
}
160