views_natural_sort.inc 7.47 KB
Newer Older
1 2
<?php

3 4
/**
 * @file
5
 * The Views Natural Sort module include file.
6 7 8
 */

/**
9
 * Remove all the configured words from the beginning of the string only.
10
 *
11 12 13 14 15
 * @param string $string
 *   The string we wish to transform.
 *
 * @return string
 *   The transformed string.
16
 */
17 18 19 20 21 22 23 24 25 26 27 28 29 30
function views_natural_sort_remove_beginning_words($string) {
  $beginning_words = variable_get('views_natural_sort_beginning_words_remove', array());
  if (empty($beginning_words)) {
    return $string;
  }

  array_walk($beginning_words, 'preg_quote');
  return preg_replace(
    '/^(' . implode('|', $beginning_words) . ')\s+/i',
    '',
    $string
  );
}

31
/**
32
 * Remove all the configured words from the string.
33
 *
34 35 36 37 38
 * @param string $string
 *   The string we wish to transform.
 *
 * @return string
 *   The transformed string.
39
 */
40 41 42 43 44 45 46 47 48 49 50 51 52 53
function views_natural_sort_remove_words($string) {
  $words = variable_get('views_natural_sort_words_remove', array());
  if (empty($words)) {
    return $string;
  }

  array_walk($words, 'preg_quote');
  return preg_replace(
    array(
      '/\s(' . implode('|', $words) . ')\s+/i',
      '/^(' . implode('|', $words) . ')\s+/i',
    ),
    array(
      ' ',
54
      '',
55 56 57 58 59
    ),
    $string
  );
}

60
/**
61
 * Remove all the configured symbols from the string.
62
 *
63 64 65 66 67
 * @param string $string
 *   The string we wish to transform.
 *
 * @return string
 *   The transformed string.
68
 */
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
function views_natural_sort_remove_symbols($string) {
  $symbols = variable_get('views_natural_sort_symbols_remove', '');
  if (strlen($symbols) == 0) {
    return $string;
  }
  return preg_replace(
    '/[' . preg_quote($symbols) . ']/',
    '',
    $string
  );
}

/**
 * Transform numbers in a string into a natural sortable string.
 *
 * Rules are as follows:
 *  - Embeded numbers will sort in numerical order. The following possibilities
 *    are supported
 *    - A leading dash indicates a negative number, unless it is preceded by a
 *      non-whitespace character, which case it is considered just a dash.
 *    - Leading zeros are properly ignored so as to not influence sort order
 *    - Decimal numbers are supported using a period as the decimal character
 *    - Thousands separates are ignored, using the comma as the thous. character
 *    - Numbers may be up to 99 digits before the decimal, up to the precision
 *      of the processor.
94 95 96
 *
 * @param string $string
 *   The string we wish to transform.
97 98 99 100
 */
function views_natural_sort_numbers($string) {
  // Find an optional leading dash (either preceded by whitespace or the first
  // character) followed by either:
101 102 103
  // - an optional series of digits (with optional embedded commas), then a
  //   period, then an optional series of digits
  // - a series of digits (with optional embedded commas)
104 105 106 107 108 109 110 111
  return preg_replace_callback(
    '/(\s-|^-)?(?:(\d[\d,]*)?\.(\d+)|(\d[\d,]*))/',
    '_views_natural_sort_number_transform_match_callback',
    $string
  );
}

/**
112 113 114 115
 * Transforms a string representing numbers into a special format.
 *
 * This special format can be sorted as if it was a number but in reality is
 *   being sorted alphanumerically.
116 117
 *
 * @param array $match
118
 *   Array of matches passed from preg_replace_callback
119 120 121 122
 *   $match[0] is the entire matching string
 *   $match[1] if present, is the optional dash, preceded by optional whitespace
 *   $match[2] if present, is whole number portion of the decimal number
 *   $match[3] if present, is the fractional portion of the decimal number
123
 *   $match[4] if present, is the integer (when no fraction is matched).
124 125 126 127 128
 *
 * @return string
 *   String representing a numerical value that will sort numerically in an
 *   alphanumeric search.
 */
129
function _views_natural_sort_number_transform_match_callback(array $match) {
130

131 132
  // Remove commas and leading zeros from whole number.
  $whole = (string) (int) str_replace(',', '', (isset($match[4]) && strlen($match[4]) > 0) ? $match[4] : $match[2]);
133 134
  // Remove traililng 0's from fraction, then add the decimal and one trailing
  // 0.
135 136 137
  $fraction = trim('.' . $match[3], '0') . '0';
  $encode = sprintf('%02u', strlen($whole)) . $whole . $fraction;
  if (strlen($match[1])) {
138 139 140 141 142
    // Negative number. Make 10's complement. Put back any leading white space
    // and the dash requires intermediate to avoid double-replacing the same
    // digit. str_replace() seems to work by copying the source to the result,
    // then successively replacing within it, rather than replacing from the
    // source to the result.
143 144 145
    $digits       = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9');
    $intermediate = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j');
    $rev_digits   = array('9', '8', '7', '6', '5', '4', '3', '2', '1', '0');
146
    $encode       = $match[1] . str_replace($intermediate, $rev_digits, str_replace($digits, $intermediate, $encode));
147 148 149
  }
  return $encode;
}
150 151 152 153 154

/**
 * Simply convert days of the week over to numbers.
 *
 * This "should" be multilingual safe.
155 156 157 158 159 160
 *
 * @param string $string
 *   The string we are transforming days to numbers in.
 *
 * @return string
 *   The transformed string.
161 162 163 164 165 166 167 168 169 170 171 172 173 174
 */
function views_natural_sort_days_of_the_week_sort_days($string) {

  global $language;

  // Adding a configuration so that in the future an admin page can be made
  // to switch which day is the first day of the week based on local.
  $used_language = isset($language->language) ? $language->language : 'en';
  $first_day = variable_get('views_natural_sort_days_of_the_week_first_day_' . $used_language, "Sunday");

  $day_list = views_natural_sort_days_of_the_week_get_default_days();
  $sorted_days = $day_list;
  // Go through list and resort it and Translate it.
  $start = array_search($first_day, $day_list);
175 176
  for ($i = 0; $i < 7; $i++) {
    $current_day = ($i + $start) % 7;
177
    $abbreviations = views_natural_sort_days_of_the_week_get_acceptable_day_abbreviations($day_list[$current_day], $used_language);
178
    $translated_day = t('@day', array('@day' => $day_list[$current_day]);
179 180 181
    $string = preg_replace(
      array(
        '/\b' . $translated_day . '\b/i',
182
        '/\b(' . implode(views_natural_sort_days_of_the_week_get_acceptable_day_abbreviations($day_list[$current_day]), '\.?|') . ')\b/i',
183
      ),
184
      ' ' . $i . ' ',
185 186 187 188 189 190
      $string
    );
  }
  return $string;
}

191
/**
192
 * The default days of the week.
193
 */
194
function views_natural_sort_days_of_the_week_get_default_days() {
195
  return array(
196 197 198 199 200 201
    "Sunday",
    "Monday",
    "Tuesday",
    "Wednesday",
    "Thursday",
    "Friday",
202
    "Saturday",
203 204 205
  );
}

206
/**
207 208 209 210 211 212
 * Gets all the configured abbreviations for a certain day of the week.
 *
 * @param string $day
 *   The day of the week we want to get abbreviations for.
 * @param string $lang
 *   Determines which configuration to search for as they are keyed by language.
213
 *
214 215
 * @return array
 *   The abbreviations for the day of the week and language passed in.
216
 */
217 218
function views_natural_sort_days_of_the_week_get_acceptable_day_abbreviations($day, $lang = 'en') {
  $default_days = views_natural_sort_days_of_the_week_get_default_days();
219
  $index = array_search($day, $default_days);
220 221 222 223 224 225 226
  $default_abbrev = views_natural_sort_days_of_the_week_get_default_day_abbreviations();
  return variable_get(
    'views_natural_sort_days_of_the_week_' . $lang . '_' . $day,
    $default_abbrev[$index]
  );
}

227
/**
228
 * Default mappings of days of the week abbreviationas.
229
 */
230
function views_natural_sort_days_of_the_week_get_default_day_abbreviations() {
231
  return array(
232 233 234 235 236 237 238 239 240
    array("Sun"),
    array("Mon"),
    array("Tu", "Tue", "Tues"),
    array("Wed"),
    array("Th", "Thu", "Thur", "Thurs"),
    array("Fri"),
    array("Sat"),
  );
}