Conjunto de cambios 49072ea en sipes para modules_contrib/pathauto/pathauto.inc
- Fecha y hora:
- 26/05/2016 18:10:02 (hace 8 años)
- Branches:
- stable, version-3.0
- Children:
- 2efe680
- Parents:
- cd414e9
- Fichero:
-
- 1 editado
Leyenda
- No modificado
- Añadido
- Eliminado
-
modules_contrib/pathauto/pathauto.inc
r177a560 r49072ea 1 1 <?php 2 // $Id: pathauto.inc,v 1.45.2.29 2010/09/27 15:52:58 greggles Exp $3 2 4 3 /** … … 6 5 * Miscellaneous functions for Pathauto. 7 6 * 7 * This also contains some constants giving human readable names to some numeric 8 * settings; they're included here as they're only rarely used outside this file 9 * anyway. Use module_load_include('inc', 'pathauto') if the constants need to 10 * be available. 11 * 8 12 * @ingroup pathauto 9 13 */ 14 15 /** 16 * Case should be left as is in the generated path. 17 */ 18 define('PATHAUTO_CASE_LEAVE_ASIS', 0); 19 20 /** 21 * Case should be lowercased in the generated path. 22 */ 23 define('PATHAUTO_CASE_LOWER', 1); 24 25 /** 26 * "Do nothing. Leave the old alias intact." 27 */ 28 define('PATHAUTO_UPDATE_ACTION_NO_NEW', 0); 29 30 /** 31 * "Create a new alias. Leave the existing alias functioning." 32 */ 33 define('PATHAUTO_UPDATE_ACTION_LEAVE', 1); 34 35 /** 36 * "Create a new alias. Delete the old alias." 37 */ 38 define('PATHAUTO_UPDATE_ACTION_DELETE', 2); 39 40 /** 41 * "Create a new alias. Redirect from old alias." 42 * 43 * This is only available when the Path Redirect module is. 44 */ 45 define('PATHAUTO_UPDATE_ACTION_REDIRECT', 3); 46 47 /** 48 * Remove the punctuation from the alias. 49 */ 50 define('PATHAUTO_PUNCTUATION_REMOVE', 0); 51 52 /** 53 * Replace the punctuation with the separator in the alias. 54 */ 55 define('PATHAUTO_PUNCTUATION_REPLACE', 1); 56 57 /** 58 * Leave the punctuation as it is in the alias. 59 */ 60 define('PATHAUTO_PUNCTUATION_DO_NOTHING', 2); 61 62 /** 63 * Matches Unicode characters that are word boundaries. 64 * 65 * Characters with the following General_category (gc) property values are used 66 * as word boundaries. While this does not fully conform to the Word Boundaries 67 * algorithm described in http://unicode.org/reports/tr29, as PCRE does not 68 * contain the Word_Break property table, this simpler algorithm has to do. 69 * - Cc, Cf, Cn, Co, Cs: Other. 70 * - Pc, Pd, Pe, Pf, Pi, Po, Ps: Punctuation. 71 * - Sc, Sk, Sm, So: Symbols. 72 * - Zl, Zp, Zs: Separators. 73 * 74 * Non-boundary characters include the following General_category (gc) property 75 * values: 76 * - Ll, Lm, Lo, Lt, Lu: Letters. 77 * - Mc, Me, Mn: Combining Marks. 78 * - Nd, Nl, No: Numbers. 79 * 80 * Note that the PCRE property matcher is not used because we wanted to be 81 * compatible with Unicode 5.2.0 regardless of the PCRE version used (and any 82 * bugs in PCRE property tables). 83 * 84 * @see http://unicode.org/glossary 85 */ 86 define('PATHAUTO_PREG_CLASS_UNICODE_WORD_BOUNDARY', 87 '\x{0}-\x{2F}\x{3A}-\x{40}\x{5B}-\x{60}\x{7B}-\x{A9}\x{AB}-\x{B1}\x{B4}' . 88 '\x{B6}-\x{B8}\x{BB}\x{BF}\x{D7}\x{F7}\x{2C2}-\x{2C5}\x{2D2}-\x{2DF}' . 89 '\x{2E5}-\x{2EB}\x{2ED}\x{2EF}-\x{2FF}\x{375}\x{37E}-\x{385}\x{387}\x{3F6}' . 90 '\x{482}\x{55A}-\x{55F}\x{589}-\x{58A}\x{5BE}\x{5C0}\x{5C3}\x{5C6}' . 91 '\x{5F3}-\x{60F}\x{61B}-\x{61F}\x{66A}-\x{66D}\x{6D4}\x{6DD}\x{6E9}' . 92 '\x{6FD}-\x{6FE}\x{700}-\x{70F}\x{7F6}-\x{7F9}\x{830}-\x{83E}' . 93 '\x{964}-\x{965}\x{970}\x{9F2}-\x{9F3}\x{9FA}-\x{9FB}\x{AF1}\x{B70}' . 94 '\x{BF3}-\x{BFA}\x{C7F}\x{CF1}-\x{CF2}\x{D79}\x{DF4}\x{E3F}\x{E4F}' . 95 '\x{E5A}-\x{E5B}\x{F01}-\x{F17}\x{F1A}-\x{F1F}\x{F34}\x{F36}\x{F38}' . 96 '\x{F3A}-\x{F3D}\x{F85}\x{FBE}-\x{FC5}\x{FC7}-\x{FD8}\x{104A}-\x{104F}' . 97 '\x{109E}-\x{109F}\x{10FB}\x{1360}-\x{1368}\x{1390}-\x{1399}\x{1400}' . 98 '\x{166D}-\x{166E}\x{1680}\x{169B}-\x{169C}\x{16EB}-\x{16ED}' . 99 '\x{1735}-\x{1736}\x{17B4}-\x{17B5}\x{17D4}-\x{17D6}\x{17D8}-\x{17DB}' . 100 '\x{1800}-\x{180A}\x{180E}\x{1940}-\x{1945}\x{19DE}-\x{19FF}' . 101 '\x{1A1E}-\x{1A1F}\x{1AA0}-\x{1AA6}\x{1AA8}-\x{1AAD}\x{1B5A}-\x{1B6A}' . 102 '\x{1B74}-\x{1B7C}\x{1C3B}-\x{1C3F}\x{1C7E}-\x{1C7F}\x{1CD3}\x{1FBD}' . 103 '\x{1FBF}-\x{1FC1}\x{1FCD}-\x{1FCF}\x{1FDD}-\x{1FDF}\x{1FED}-\x{1FEF}' . 104 '\x{1FFD}-\x{206F}\x{207A}-\x{207E}\x{208A}-\x{208E}\x{20A0}-\x{20B8}' . 105 '\x{2100}-\x{2101}\x{2103}-\x{2106}\x{2108}-\x{2109}\x{2114}' . 106 '\x{2116}-\x{2118}\x{211E}-\x{2123}\x{2125}\x{2127}\x{2129}\x{212E}' . 107 '\x{213A}-\x{213B}\x{2140}-\x{2144}\x{214A}-\x{214D}\x{214F}' . 108 '\x{2190}-\x{244A}\x{249C}-\x{24E9}\x{2500}-\x{2775}\x{2794}-\x{2B59}' . 109 '\x{2CE5}-\x{2CEA}\x{2CF9}-\x{2CFC}\x{2CFE}-\x{2CFF}\x{2E00}-\x{2E2E}' . 110 '\x{2E30}-\x{3004}\x{3008}-\x{3020}\x{3030}\x{3036}-\x{3037}' . 111 '\x{303D}-\x{303F}\x{309B}-\x{309C}\x{30A0}\x{30FB}\x{3190}-\x{3191}' . 112 '\x{3196}-\x{319F}\x{31C0}-\x{31E3}\x{3200}-\x{321E}\x{322A}-\x{3250}' . 113 '\x{3260}-\x{327F}\x{328A}-\x{32B0}\x{32C0}-\x{33FF}\x{4DC0}-\x{4DFF}' . 114 '\x{A490}-\x{A4C6}\x{A4FE}-\x{A4FF}\x{A60D}-\x{A60F}\x{A673}\x{A67E}' . 115 '\x{A6F2}-\x{A716}\x{A720}-\x{A721}\x{A789}-\x{A78A}\x{A828}-\x{A82B}' . 116 '\x{A836}-\x{A839}\x{A874}-\x{A877}\x{A8CE}-\x{A8CF}\x{A8F8}-\x{A8FA}' . 117 '\x{A92E}-\x{A92F}\x{A95F}\x{A9C1}-\x{A9CD}\x{A9DE}-\x{A9DF}' . 118 '\x{AA5C}-\x{AA5F}\x{AA77}-\x{AA79}\x{AADE}-\x{AADF}\x{ABEB}' . 119 '\x{E000}-\x{F8FF}\x{FB29}\x{FD3E}-\x{FD3F}\x{FDFC}-\x{FDFD}' . 120 '\x{FE10}-\x{FE19}\x{FE30}-\x{FE6B}\x{FEFF}-\x{FF0F}\x{FF1A}-\x{FF20}' . 121 '\x{FF3B}-\x{FF40}\x{FF5B}-\x{FF65}\x{FFE0}-\x{FFFD}'); 10 122 11 123 /** … … 54 166 */ 55 167 function _pathauto_existing_alias_data($source, $language = '') { 56 return db_fetch_array(db_query_range("SELECT pid, dst AS alias FROM {url_alias} WHERE src = '%s' AND language IN ('%s', '') ORDER BY language DESC, pid DESC", $source, $language, 0, 1));168 return db_fetch_array(db_query_range("SELECT pid, dst AS alias, language FROM {url_alias} WHERE src = '%s' AND language IN ('%s', '') ORDER BY language DESC, pid DESC", $source, $language, 0, 1)); 57 169 } 58 170 … … 61 173 * 62 174 * Performs the following possible alterations: 175 * - Remove all HTML tags. 63 176 * - Process the string through the transliteration module. 64 177 * - Replace or remove punctuation with the separator character. … … 76 189 * @param $string 77 190 * A string to clean. 191 * @param array $options 192 * (optional) A keyed array of settings and flags to control the Pathauto 193 * clean string replacement process. Supported options are: 194 * - langcode: A language code to be used when translating strings. 195 * 78 196 * @return 79 197 * The cleaned string. 80 198 */ 81 199 function pathauto_cleanstring($string) { 82 $output = $string; 83 84 // Optionally remove accents and transliterate 85 if (variable_get('pathauto_transliterate', FALSE)) { 86 static $translations; 87 88 if (!isset($translations)) { 89 $translations = FALSE; 90 if ($file = _pathauto_get_i18n_file()) { 91 $translations = parse_ini_file($file); 92 } 93 } 94 95 if (!empty($translations)) { 96 $output = strtr($output, $translations); 97 } 98 } 99 100 // Replace or drop punctuation based on user settings 101 $separator = variable_get('pathauto_separator', '-'); 102 $punctuation = pathauto_punctuation_chars(); 103 foreach ($punctuation as $name => $details) { 104 $action = variable_get('pathauto_punctuation_'. $name, 0); 105 // 2 is the action for "do nothing" with the punctuation 106 if ($action != 2) { 107 // Slightly tricky inline if which either replaces with the separator or nothing 108 $output = str_replace($details['value'], ($action ? $separator : ''), $output); 109 } 110 } 111 112 // Reduce strings to letters and numbers 113 if (variable_get('pathauto_reduce_ascii', FALSE)) { 114 $pattern = '/[^a-zA-Z0-9\/]+/'; 115 $output = preg_replace($pattern, $separator, $output); 116 } 117 118 // Calculate and statically cache the ignored words regex expression. 119 static $ignore_words_regex; 120 if (!isset($ignore_words_regex)) { 121 $ignore_words = array( 122 'a', 'an', 'as', 'at', 'before', 'but', 'by', 'for', 'from', 'is', 'in', 123 'into', 'like', 'of', 'off', 'on', 'onto', 'per', 'since', 'than', 'the', 124 'this', 'that', 'to', 'up', 'via', 'with', 200 // Use the advanced drupal_static() pattern, since this is called very often. 201 static $drupal_static_fast; 202 if (!isset($drupal_static_fast)) { 203 $drupal_static_fast['cache'] = &pathauto_static(__FUNCTION__); 204 } 205 $cache = &$drupal_static_fast['cache']; 206 207 // Generate and cache variables used in this function so that on the second 208 // call to pathauto_cleanstring() we focus on processing. 209 if (!isset($cache)) { 210 $cache = array( 211 'separator' => variable_get('pathauto_separator', '-'), 212 'strings' => array(), 213 'transliterate' => variable_get('pathauto_transliterate', FALSE) && module_exists('transliteration'), 214 'punctuation' => array(), 215 'reduce_ascii' => (bool) variable_get('pathauto_reduce_ascii', FALSE), 216 'ignore_words_regex' => FALSE, 217 'lowercase' => (bool) variable_get('pathauto_case', PATHAUTO_CASE_LOWER), 218 'maxlength' => min(variable_get('pathauto_max_component_length', 100), _pathauto_get_schema_alias_maxlength()), 125 219 ); 126 $ignore_words = variable_get('pathauto_ignore_words', $ignore_words); 220 221 // Generate and cache the punctuation replacements for strtr(). 222 $punctuation = pathauto_punctuation_chars(); 223 foreach ($punctuation as $name => $details) { 224 $action = variable_get('pathauto_punctuation_' . $name, PATHAUTO_PUNCTUATION_REMOVE); 225 switch ($action) { 226 case PATHAUTO_PUNCTUATION_REMOVE: 227 $cache['punctuation'][$details['value']] = ''; 228 break; 229 case PATHAUTO_PUNCTUATION_REPLACE: 230 $cache['punctuation'][$details['value']] = $cache['separator']; 231 break; 232 case PATHAUTO_PUNCTUATION_DO_NOTHING: 233 // Literally do nothing. 234 break; 235 } 236 } 237 238 // Generate and cache the ignored words regular expression. 239 $ignore_words = variable_get('pathauto_ignore_words', PATHAUTO_IGNORE_WORDS); 127 240 $ignore_words_regex = preg_replace(array('/^[,\s]+|[,\s]+$/', '/[,\s]+/'), array('', '\b|\b'), $ignore_words); 128 241 if ($ignore_words_regex) { 129 $ignore_words_regex = '\b' . $ignore_words_regex . '\b'; 130 } 242 $cache['ignore_words_regex'] = '\b' . $ignore_words_regex . '\b'; 243 if (function_exists('mb_eregi_replace')) { 244 $cache['ignore_words_callback'] = 'mb_eregi_replace'; 245 } 246 else { 247 $cache['ignore_words_callback'] = 'preg_replace'; 248 $cache['ignore_words_regex'] = '/' . $cache['ignore_words_regex'] . '/i'; 249 } 250 } 251 } 252 253 // Empty strings do not need any proccessing. 254 if ($string === '' || $string === NULL) { 255 return ''; 256 } 257 258 $langcode = NULL; 259 if (!empty($options['language']->language)) { 260 $langcode = $options['language']->language; 261 } 262 elseif (!empty($options['langcode'])) { 263 $langcode = $options['langcode']; 264 } 265 266 // Check if the string has already been processed, and if so return the 267 // cached result. 268 if (isset($cache['strings'][$langcode][$string])) { 269 return $cache['strings'][$langcode][$string]; 270 } 271 272 // Remove all HTML tags from the string. 273 $output = strip_tags(decode_entities($string)); 274 275 // Optionally transliterate (by running through the Transliteration module) 276 if ($cache['transliterate']) { 277 $output = transliteration_get($output, $cache['reduce_ascii'] ? '' : '?', $langcode); 278 } 279 280 // Replace or drop punctuation based on user settings 281 $output = strtr($output, $cache['punctuation']); 282 283 // Reduce strings to letters and numbers 284 if ($cache['reduce_ascii']) { 285 $output = preg_replace('/[^a-zA-Z0-9\/]+/', $cache['separator'], $output); 131 286 } 132 287 133 288 // Get rid of words that are on the ignore list 134 if ($ignore_words_regex) { 135 if (function_exists('mb_eregi_replace')) { 136 $words_removed = mb_eregi_replace($ignore_words_regex, '', $output); 137 } 138 else { 139 $words_removed = preg_replace("/$ignore_words_regex/i", '', $output); 140 } 289 if ($cache['ignore_words_regex']) { 290 $words_removed = $cache['ignore_words_callback']($cache['ignore_words_regex'], '', $output); 141 291 if (drupal_strlen(trim($words_removed)) > 0) { 142 292 $output = $words_removed; … … 145 295 146 296 // Always replace whitespace with the separator. 147 $output = preg_replace('/\s+/', $ separator, $output);297 $output = preg_replace('/\s+/', $cache['separator'], $output); 148 298 149 299 // Trim duplicates and remove trailing and leading separators. 150 $output = _pathauto_clean_separators($output );300 $output = _pathauto_clean_separators($output, $cache['separator']); 151 301 152 302 // Optionally convert to lower case. 153 if ( variable_get('pathauto_case', 1)) {303 if ($cache['lowercase']) { 154 304 $output = drupal_strtolower($output); 155 305 } 156 306 157 // Enforce the maximum component length. 158 $maxlength = min(variable_get('pathauto_max_component_length', 100), _pathauto_get_schema_alias_maxlength()); 159 $output = drupal_substr($output, 0, $maxlength); 307 // Shorten to a logical place based on word boundaries. 308 $output = pathauto_truncate_utf8($output, $cache['maxlength'], TRUE); 309 310 // Cache this result in the static array. 311 $cache['strings'][$langcode][$string] = $output; 160 312 161 313 return $output; … … 176 328 */ 177 329 function _pathauto_clean_separators($string, $separator = NULL) { 330 static $default_separator; 331 332 if (!isset($separator)) { 333 if (!isset($default_separator)) { 334 $default_separator = variable_get('pathauto_separator', '-'); 335 } 336 $separator = $default_separator; 337 } 338 178 339 $output = $string; 179 340 180 if (!isset($separator)) {181 $separator = variable_get('pathauto_separator', '-');182 }183 184 // Clean duplicate or trailing separators.185 341 if (strlen($separator)) { 186 // Escape the separator. 342 // Trim any leading or trailing separators. 343 $output = trim($output, $separator); 344 345 // Escape the separator for use in regular expressions. 187 346 $seppattern = preg_quote($separator, '/'); 188 347 189 // Trim any leading or trailing separators.190 $output = preg_replace("/ ^$seppattern+|$seppattern+$/", '', $output);348 // Replace multiple separators with a single one. 349 $output = preg_replace("/$seppattern+/", $separator, $output); 191 350 192 351 // Replace trailing separators around slashes. 193 352 if ($separator !== '/') { 194 $output = preg_replace("/$seppattern+\/|\/$seppattern+/", "/", $output); 195 } 196 197 // Replace multiple separators with a single one. 198 $output = preg_replace("/$seppattern+/", $separator, $output); 353 $output = preg_replace("/\/+$seppattern\/+|$seppattern\/+|\/+$seppattern/", "/", $output); 354 } 199 355 } 200 356 … … 216 372 */ 217 373 function pathauto_clean_alias($alias) { 374 $cache = &pathauto_static(__FUNCTION__); 375 376 if (!isset($cache)) { 377 $cache = array( 378 'maxlength' => min(variable_get('pathauto_max_length', 100), _pathauto_get_schema_alias_maxlength()), 379 ); 380 } 381 218 382 $output = $alias; 219 383 220 // Trim duplicate, leading, and trailing back-slashes. 384 // Trim duplicate, leading, and trailing separators. Do this before cleaning 385 // backslashes since a pattern like "[token1]/[token2]-[token3]/[token4]" 386 // could end up like "value1/-/value2" and if backslashes were cleaned first 387 // this would result in a duplicate blackslash. 388 $output = _pathauto_clean_separators($output); 389 390 // Trim duplicate, leading, and trailing backslashes. 221 391 $output = _pathauto_clean_separators($output, '/'); 222 392 223 // Trim duplicate, leading, and trailing separators. 224 $output = _pathauto_clean_separators($output); 225 226 // Enforce the maximum length. 227 $separator = variable_get('pathauto_separator', '-'); 228 $maxlength = min(variable_get('pathauto_max_length', 100), _pathauto_get_schema_alias_maxlength()); 229 $output = drupal_substr($output, 0, $maxlength); 393 // Shorten to a logical place based on word boundaries. 394 $output = pathauto_truncate_utf8($output, $cache['maxlength'], TRUE); 230 395 231 396 return $output; … … 240 405 * Operation being performed on the content being aliased 241 406 * ('insert', 'update', 'return', or 'bulkupdate'). 242 * @param $placeholders243 * An array whose keys consist of the translated placeholders244 * which appear in patterns (e.g., t('[title]')) and values are the245 * actual values to be substituted into the pattern (e.g., $node->title).246 407 * @param $source 247 408 * An internal Drupal path to be aliased. 409 * @param $data 410 * An array of keyed objects to pass to token_replace(). For simple 411 * replacement scenarios 'node', 'user', and others are common keys, with an 412 * accompanying node or user object being the value. Only one key/value pair 413 * is supported, otherwise you may pass the results from 414 * pathauto_get_placeholders() here. 248 415 * @param $entity_id 249 * The entity ID (node ID, user ID, etc.). 416 * (deprecated) The entity ID (node ID, user ID, etc.). This parameter is 417 * deprecated and is not actually used. 250 418 * @param $type 251 419 * For modules which provided pattern items in hook_pathauto(), … … 260 428 * @see pathauto_get_placeholders() 261 429 */ 262 function pathauto_create_alias($module, $op, $placeholders, $source, $entity_id, $type = NULL, $language = '') { 263 // Retrieve and apply the pattern for this content type 264 if (!empty($type)) { 265 $pattern = trim(variable_get("pathauto_{$module}_{$type}_{$language}_pattern", '')); 266 if (empty($pattern)) { 267 $pattern = trim(variable_get("pathauto_{$module}_{$type}_pattern", '')); 268 } 269 } 430 function pathauto_create_alias($module, $op, $source, $data, $entity_id = NULL, $type = NULL, $language = '') { 431 // Retrieve and apply the pattern for this content type. 432 $pattern = pathauto_pattern_load_by_entity($module, $type, $language); 433 434 // Allow other modules to alter the pattern. 435 $context = array( 436 'module' => $module, 437 'op' => $op, 438 'source' => $source, 439 'data' => $data, 440 'type' => $type, 441 'language' => &$language, 442 ); 443 drupal_alter('pathauto_pattern', $pattern, $context); 444 270 445 if (empty($pattern)) { 271 $pattern = trim(variable_get("pathauto_{$module}_pattern", '')); 272 } 273 // No pattern? Do nothing (otherwise we may blow away existing aliases...) 274 if (empty($pattern)) { 446 // No pattern? Do nothing (otherwise we may blow away existing aliases...) 275 447 return ''; 276 448 } 277 449 278 if ($module == 'taxonomy') {279 // Get proper path for term.280 $ term_path = taxonomy_term_path(taxonomy_get_term($entity_id));281 if ($term_path != $source) {282 // Quietly alias 'taxonomy/term/[tid]' with proper path for term.283 $update_data = _pathauto_existing_alias_data($source, $language);284 _pathauto_set_alias($source, $term_path, $module, $entity_id, $update_data['pid'], FALSE, $update_data['old_alias'], $language);285 // Set $source as proper path.286 $source = $term_path;287 }450 // Support for when $source and $placeholders were swapped. 451 if (is_array($source) && is_string($data)) { 452 $placeholders = $source; 453 $source = $data; 454 } 455 elseif (is_array($data) && !isset($data['tokens']) && !isset($data['values'])) { 456 $placeholders = pathauto_get_placeholders(key($data), current($data), $pattern, array('language' => (object) array('language' => $language))); 457 } 458 else { 459 $placeholders = $data; 288 460 } 289 461 … … 292 464 if ($op == 'update' || $op == 'bulkupdate') { 293 465 if ($existing_alias = _pathauto_existing_alias_data($source, $language)) { 294 switch (variable_get('pathauto_update_action', 2)) {295 case 0:466 switch (variable_get('pathauto_update_action', PATHAUTO_UPDATE_ACTION_DELETE)) { 467 case PATHAUTO_UPDATE_ACTION_NO_NEW: 296 468 // If an alias already exists, and the update action is set to do nothing, 297 469 // then gosh-darn it, do nothing. … … 315 487 316 488 // Allow other modules to alter the alias. 317 $context = array( 318 'module' => $module, 319 'op' => $op, 320 'source' => $source, 321 'entity_id' => $entity_id, 322 'type' => $type, 323 'language' => $language, 324 'pattern' => $pattern, 325 ); 489 $context['source'] = &$source; 490 $context['pattern'] = $pattern; 326 491 drupal_alter('pathauto_alias', $alias, $context); 327 492 … … 331 496 } 332 497 333 // If the alias already exists, generate a new, hopefully unique, variant 334 if (_pathauto_alias_exists($alias, $source, $language)) { 335 $maxlength = min(variable_get('pathauto_max_length', 100), _pathauto_get_schema_alias_maxlength()); 336 $separator = variable_get('pathauto_separator', '-'); 337 $original_alias = $alias; 338 339 $i = 0; 340 do { 341 // Append an incrementing numeric suffix until we find a unique alias. 342 $unique_suffix = $separator . $i; 343 $alias = drupal_substr($original_alias, 0, $maxlength - drupal_strlen($unique_suffix, TRUE)) . $unique_suffix; 344 $i++; 345 } while (_pathauto_alias_exists($alias, $source, $language)); 346 498 // If the alias already exists, generate a new, hopefully unique, variant. 499 $original_alias = $alias; 500 pathauto_alias_uniquify($alias, $source, $language); 501 if ($original_alias != $alias) { 347 502 // Alert the user why this happened. 348 503 _pathauto_verbose(t('The automatically generated alias %original_alias conflicted with an existing alias. Alias changed to %alias.', array( … … 363 518 'language' => $language, 364 519 ); 365 _pathauto_set_alias($path, $existing_alias, $op); 366 367 // Also create a related feed alias if requested and supported. 368 $feedappend = trim(variable_get('pathauto_' . $module . '_applytofeeds', '')); 369 if (drupal_strlen($feedappend)) { 370 // For forums and taxonomies, the source doesn't always form the base of the RSS feed (i.e. image galleries) 371 if ($module == 'taxonomy' || $module == 'forum' && !empty($entity_id)) { 372 $source = "taxonomy/term/{$entity_id}"; 373 } 374 375 // Build the feed path alias array and send it off to be created. 376 $path = array( 377 'source' => "$source/$feedappend", 378 'alias' => "$alias/feed", 379 'language' => $language, 380 ); 381 $existing_alias = _pathauto_existing_alias_data($path['source'], $path['language']); 382 _pathauto_set_alias($path, $existing_alias, $op); 383 } 384 385 return $alias; 520 $success = _pathauto_set_alias($path, $existing_alias, $op); 521 return $success ? $alias : NULL; 522 } 523 524 /** 525 * Check to ensure a path alias is unique and add suffix variants if necessary. 526 * 527 * Given an alias 'content/test' if a path alias with the exact alias already 528 * exists, the function will change the alias to 'content/test-0' and will 529 * increase the number suffix until it finds a unique alias. 530 * 531 * @param $alias 532 * A string with the alias. Can be altered by reference. 533 * @param $source 534 * A string with the path source. 535 * @param $langcode 536 * A string with a language code. 537 */ 538 function pathauto_alias_uniquify(&$alias, $source, $langcode) { 539 if (!_pathauto_alias_exists($alias, $source, $langcode)) { 540 return; 541 } 542 543 // If the alias already exists, generate a new, hopefully unique, variant 544 $maxlength = min(variable_get('pathauto_max_length', 100), _pathauto_get_schema_alias_maxlength()); 545 $separator = variable_get('pathauto_separator', '-'); 546 $original_alias = $alias; 547 548 $i = 0; 549 do { 550 // Append an incrementing numeric suffix until we find a unique alias. 551 $unique_suffix = $separator . $i; 552 $alias = pathauto_truncate_utf8($original_alias, $maxlength - drupal_strlen($unique_suffix), TRUE) . $unique_suffix; 553 $i++; 554 } while (_pathauto_alias_exists($alias, $source, $langcode)); 386 555 } 387 556 … … 399 568 $menu = menu_get_item($path); 400 569 if (isset($menu['path']) && $menu['path'] == $path) { 570 return TRUE; 571 } 572 elseif (is_file('./' . $path) || is_dir('./' . $path)) { 573 // Do not allow existing files or directories to get assigned an automatic 574 // alias. Note that we do not need to use is_link() to check for symbolic 575 // links since this returns TRUE for either is_file() or is_dir() already. 401 576 return TRUE; 402 577 } … … 417 592 * @param $op 418 593 * An optional string with the operation being performed. 419 * @return 420 * TRUE if the path was saved, or NULL otherwise. 594 * 595 * @return 596 * The saved path from path_save() or NULL if the path was not saved. 421 597 * 422 598 * @see path_set_alias() … … 440 616 } 441 617 442 $path += array(443 'pid' => NULL,444 'language' => '',445 );446 447 618 // Skip replacing the current alias with an identical alias 448 619 if (empty($existing_alias) || $existing_alias['alias'] != $path['alias']) { 620 $path += array('pid' => NULL, 'language' => ''); 621 449 622 // If there is already an alias, respect some update actions. 450 623 if (!empty($existing_alias)) { 451 switch (variable_get('pathauto_update_action', 2)) {452 case 0:624 switch (variable_get('pathauto_update_action', PATHAUTO_UPDATE_ACTION_DELETE)) { 625 case PATHAUTO_UPDATE_ACTION_NO_NEW: 453 626 // Do not create the alias. 454 627 return; 455 case 1:628 case PATHAUTO_UPDATE_ACTION_LEAVE: 456 629 // Create a new alias instead of overwriting the existing by leaving 457 630 // $path['pid'] empty. 458 631 break; 459 case 3:632 case PATHAUTO_UPDATE_ACTION_REDIRECT: 460 633 // Create a redirect 461 634 if (module_exists('path_redirect') && function_exists('path_redirect_save')) { 462 635 $redirect = array( 463 636 'source' => $existing_alias['alias'], 637 'language' => $existing_alias['language'], 464 638 'redirect' => $path['source'], 465 639 ); … … 468 642 // Intentionally fall through to the next condition since we still 469 643 // want to replace the existing alias. 470 case 2:644 case PATHAUTO_UPDATE_ACTION_DELETE: 471 645 // Both the redirect and delete actions should overwrite the existing 472 646 // alias. … … 491 665 } 492 666 493 return TRUE;667 return $path; 494 668 } 495 669 } … … 532 706 * Generalized function to get tokens across all Pathauto types. 533 707 * 708 * @param $type 709 * The token type to pass to token_get_values(). 534 710 * @param $object 535 * A user, node, or category object. 711 * The object to pass to token_get_values(). 712 * @param $text 713 * (optional) The string that will be replaced with tokens. If provided 714 * and the token_scan() function is available it will be used to trim down 715 * the number of tokens that need to be passed to 716 * pathauto_clean_token_values(). 717 * 536 718 * @return 537 719 * Tokens for that object formatted in the way that 538 720 * Pathauto expects to see them. 539 721 */ 540 function pathauto_get_placeholders($type, $object) { 541 if (!function_exists('token_get_values')) { 542 // TODO at some point try removing this and see if install profiles have problems again. 543 watchdog('Pathauto', 'It appears that you have installed Pathauto, which depends on token, but token is either not installed or not installed properly.'); 544 return array('tokens' => array(), 'values' => array()); 545 } 546 547 $options = array('pathauto' => TRUE); 722 function pathauto_get_placeholders($type, $object, $text = '', array $options = array()) { 723 $options += array('pathauto' => TRUE); 724 548 725 $full = token_get_values($type, $object, TRUE, $options); 726 727 // Attempt to reduce the tokens to only the ones that will actually be used 728 // before passing into pathauto_clean_token_values(). 729 static $token_scan_exists; 730 if (!isset($token_scan_exists)) { 731 $token_scan_exists = function_exists('token_scan'); 732 } 733 if ($token_scan_exists && !empty($text)) { 734 $used_tokens = token_scan($text); 735 foreach ($full->tokens as $index => $token) { 736 if (!in_array($token, $used_tokens)) { 737 unset($full->tokens[$index]); 738 unset($full->values[$index]); 739 } 740 } 741 } 742 549 743 $tokens = token_prepare_tokens($full->tokens); 550 744 $values = pathauto_clean_token_values($full, $options); … … 571 765 // should have each segment cleaned, and then glued back together to 572 766 // construct a value resembling an URL. 573 $segments = array_map('pathauto_cleanstring', $value); 767 $segments = array(); 768 foreach ($value as $segment) { 769 $segments[] = pathauto_cleanstring($segment, $options); 770 } 574 771 $replacements[$token] = implode('/', $segments); 575 772 } … … 580 777 else { 581 778 // Token is not an URL, so it should have its value cleaned. 582 $replacements[$token] = pathauto_cleanstring($value );779 $replacements[$token] = pathauto_cleanstring($value, $options); 583 780 } 584 781 } … … 598 795 */ 599 796 function pathauto_punctuation_chars() { 600 static $punctuation;797 $punctuation = &pathauto_static(__FUNCTION__); 601 798 602 799 if (!isset($punctuation)) { 603 $punctuation = array(); 604 $punctuation['double_quotes'] = array('value' => '"', 'name' => t('Double quotes "')); 605 $punctuation['quotes'] = array('value' => "'", 'name' => t("Single quotes (apostrophe) '")); 606 $punctuation['backtick'] = array('value' => '`', 'name' => t('Back tick `')); 607 $punctuation['comma'] = array('value' => ',', 'name' => t('Comma ,')); 608 $punctuation['period'] = array('value' => '.', 'name' => t('Period .')); 609 $punctuation['hyphen'] = array('value' => '-', 'name' => t('Hyphen -')); 610 $punctuation['underscore'] = array('value' => '_', 'name' => t('Underscore _')); 611 $punctuation['colon'] = array('value' => ':', 'name' => t('Colon :')); 612 $punctuation['semicolon'] = array('value' => ';', 'name' => t('Semicolon ;')); 613 $punctuation['pipe'] = array('value' => '|', 'name' => t('Pipe |')); 614 $punctuation['left_curly'] = array('value' => '{', 'name' => t('Left curly bracket {')); 615 $punctuation['left_square'] = array('value' => '[', 'name' => t('Left square bracket [')); 616 $punctuation['right_curly'] = array('value' => '}', 'name' => t('Right curly bracket }')); 617 $punctuation['right_square'] = array('value' => ']', 'name' => t('Right square bracket ]')); 618 $punctuation['plus'] = array('value' => '+', 'name' => t('Plus +')); 619 $punctuation['equal'] = array('value' => '=', 'name' => t('Equal =')); 620 $punctuation['asterisk'] = array('value' => '*', 'name' => t('Asterisk *')); 621 $punctuation['ampersand'] = array('value' => '&', 'name' => t('Ampersand &')); 622 $punctuation['percent'] = array('value' => '%', 'name' => t('Percent %')); 623 $punctuation['caret'] = array('value' => '^', 'name' => t('Caret ^')); 624 $punctuation['dollar'] = array('value' => '$', 'name' => t('Dollar $')); 625 $punctuation['hash'] = array('value' => '#', 'name' => t('Hash #')); 626 $punctuation['at'] = array('value' => '@', 'name' => t('At @')); 627 $punctuation['exclamation'] = array('value' => '!', 'name' => t('Exclamation !')); 628 $punctuation['tilde'] = array('value' => '~', 'name' => t('Tilde ~')); 629 $punctuation['left_parenthesis'] = array('value' => '(', 'name' => t('Left parenthesis (')); 630 $punctuation['right_parenthesis'] = array('value' => ')', 'name' => t('Right parenthesis )')); 631 $punctuation['question_mark'] = array('value' => '?', 'name' => t('Question mark ?')); 632 $punctuation['less_than'] = array('value' => '<', 'name' => t('Less than <')); 633 $punctuation['greater_than'] = array('value' => '>', 'name' => t('Greater than >')); 634 $punctuation['slash'] = array('value' => '/', 'name' => t('Slash /')); 635 $punctuation['back_slash'] = array('value' => '\\', 'name' => t('Backslash \\')); 800 $cid = 'pathauto:punctuation:' . $GLOBALS['language']->language; 801 if ($cache = cache_get($cid)) { 802 $punctuation = $cache->data; 803 } 804 else { 805 $punctuation = array(); 806 $punctuation['double_quotes'] = array('value' => '"', 'name' => t('Double quotation marks')); 807 $punctuation['quotes'] = array('value' => '\'', 'name' => t("Single quotation marks (apostrophe)")); 808 $punctuation['backtick'] = array('value' => '`', 'name' => t('Back tick')); 809 $punctuation['comma'] = array('value' => ',', 'name' => t('Comma')); 810 $punctuation['period'] = array('value' => '.', 'name' => t('Period')); 811 $punctuation['hyphen'] = array('value' => '-', 'name' => t('Hyphen')); 812 $punctuation['underscore'] = array('value' => '_', 'name' => t('Underscore')); 813 $punctuation['colon'] = array('value' => ':', 'name' => t('Colon')); 814 $punctuation['semicolon'] = array('value' => ';', 'name' => t('Semicolon')); 815 $punctuation['pipe'] = array('value' => '|', 'name' => t('Vertical bar (pipe)')); 816 $punctuation['left_curly'] = array('value' => '{', 'name' => t('Left curly bracket')); 817 $punctuation['left_square'] = array('value' => '[', 'name' => t('Left square bracket')); 818 $punctuation['right_curly'] = array('value' => '}', 'name' => t('Right curly bracket')); 819 $punctuation['right_square'] = array('value' => ']', 'name' => t('Right square bracket')); 820 $punctuation['plus'] = array('value' => '+', 'name' => t('Plus sign')); 821 $punctuation['equal'] = array('value' => '=', 'name' => t('Equal sign')); 822 $punctuation['asterisk'] = array('value' => '*', 'name' => t('Asterisk')); 823 $punctuation['ampersand'] = array('value' => '&', 'name' => t('Ampersand')); 824 $punctuation['percent'] = array('value' => '%', 'name' => t('Percent sign')); 825 $punctuation['caret'] = array('value' => '^', 'name' => t('Caret')); 826 $punctuation['dollar'] = array('value' => '$', 'name' => t('Dollar sign')); 827 $punctuation['hash'] = array('value' => '#', 'name' => t('Number sign (pound sign, hash)')); 828 $punctuation['at'] = array('value' => '@', 'name' => t('At sign')); 829 $punctuation['exclamation'] = array('value' => '!', 'name' => t('Exclamation mark')); 830 $punctuation['tilde'] = array('value' => '~', 'name' => t('Tilde')); 831 $punctuation['left_parenthesis'] = array('value' => '(', 'name' => t('Left parenthesis')); 832 $punctuation['right_parenthesis'] = array('value' => ')', 'name' => t('Right parenthesis')); 833 $punctuation['question_mark'] = array('value' => '?', 'name' => t('Question mark')); 834 $punctuation['less_than'] = array('value' => '<', 'name' => t('Less-than sign')); 835 $punctuation['greater_than'] = array('value' => '>', 'name' => t('Greater-than sign')); 836 $punctuation['slash'] = array('value' => '/', 'name' => t('Slash')); 837 $punctuation['back_slash'] = array('value' => '\\', 'name' => t('Backslash')); 838 839 // Allow modules to alter the punctuation list and cache the result. 840 drupal_alter('pathauto_punctuation_chars', $punctuation); 841 cache_set($cid, $punctuation); 842 } 636 843 } 637 844 … … 655 862 656 863 /** 864 * Truncates a UTF-8-encoded string safely to a number of characters. 865 * 866 * This is a functional backport of Drupal 7's truncate_utf8(). 867 * 868 * @param $string 869 * The string to truncate. 870 * @param $max_length 871 * An upper limit on the returned string length, including trailing ellipsis 872 * if $add_ellipsis is TRUE. 873 * @param $wordsafe 874 * If TRUE, attempt to truncate on a word boundary. Word boundaries are 875 * spaces, punctuation, and Unicode characters used as word boundaries in 876 * non-Latin languages; see PREG_CLASS_UNICODE_WORD_BOUNDARY for more 877 * information. If a word boundary cannot be found that would make the length 878 * of the returned string fall within length guidelines (see parameters 879 * $max_return_length and $min_wordsafe_length), word boundaries are ignored. 880 * @param $add_ellipsis 881 * If TRUE, add t('...') to the end of the truncated string (defaults to 882 * FALSE). The string length will still fall within $max_return_length. 883 * @param $min_wordsafe_length 884 * If $wordsafe is TRUE, the minimum acceptable length for truncation (before 885 * adding an ellipsis, if $add_ellipsis is TRUE). Has no effect if $wordsafe 886 * is FALSE. This can be used to prevent having a very short resulting string 887 * that will not be understandable. For instance, if you are truncating the 888 * string "See myverylongurlexample.com for more information" to a word-safe 889 * return length of 20, the only available word boundary within 20 characters 890 * is after the word "See", which wouldn't leave a very informative string. If 891 * you had set $min_wordsafe_length to 10, though, the function would realize 892 * that "See" alone is too short, and would then just truncate ignoring word 893 * boundaries, giving you "See myverylongurl..." (assuming you had set 894 * $add_ellipses to TRUE). 895 * 896 * @return 897 * The truncated string. 898 */ 899 function pathauto_truncate_utf8($string, $max_length, $wordsafe = FALSE, $add_ellipsis = FALSE, $min_wordsafe_length = 1) { 900 $ellipsis = ''; 901 $max_length = max($max_length, 0); 902 $min_wordsafe_length = max($min_wordsafe_length, 0); 903 904 if (drupal_strlen($string) <= $max_length) { 905 // No truncation needed, so don't add ellipsis, just return. 906 return $string; 907 } 908 909 if ($add_ellipsis) { 910 // Truncate ellipsis in case $max_length is small. 911 $ellipsis = drupal_substr(t('...'), 0, $max_length); 912 $max_length -= drupal_strlen($ellipsis); 913 $max_length = max($max_length, 0); 914 } 915 916 if ($max_length <= $min_wordsafe_length) { 917 // Do not attempt word-safe if lengths are bad. 918 $wordsafe = FALSE; 919 } 920 921 if ($wordsafe) { 922 $matches = array(); 923 // Find the last word boundary, if there is one within $min_wordsafe_length 924 // to $max_length characters. preg_match() is always greedy, so it will 925 // find the longest string possible. 926 $found = preg_match('/^(.{' . $min_wordsafe_length . ',' . $max_length . '})[' . PATHAUTO_PREG_CLASS_UNICODE_WORD_BOUNDARY . ']/u', $string, $matches); 927 if ($found) { 928 $string = $matches[1]; 929 } 930 else { 931 $string = drupal_substr($string, 0, $max_length); 932 } 933 } 934 else { 935 $string = drupal_substr($string, 0, $max_length); 936 } 937 938 if ($add_ellipsis) { 939 $string .= $ellipsis; 940 } 941 942 return $string; 943 } 944 945 /** 657 946 * Fetch an array of non-raw tokens that have matching raw tokens. 658 947 * … … 683 972 return $raw_tokens; 684 973 } 685 686 /**687 * Return all the possible paths of the i18n-ascii.txt transliteration file.688 *689 * @return690 * An array of possible file paths.691 */692 function _pathauto_get_i18n_possible_files() {693 $file = 'i18n-ascii.txt';694 $files = array(695 conf_path() . '/' . $file,696 "sites/all/$file",697 drupal_get_path('module', 'pathauto') . '/' . $file,698 );699 // Always prefer $conf['pathauto_i18n_file'] if defined.700 if ($conf_file = variable_get('pathauto_i18n_file', '')) {701 array_unshift($files, $conf_file);702 }703 return $files;704 }705 706 /**707 * Fetch the path to the i18n-ascii.txt transliteration file708 *709 * @return710 * The complete path or FALSE if not found in any of the possible paths.711 *712 * @see _pathauto_get_i18n_possible_files()713 */714 function _pathauto_get_i18n_file() {715 static $i18n_file;716 717 if (!isset($i18n_file)) {718 $i18n_file = FALSE;719 foreach (_pathauto_get_i18n_possible_files() as $file) {720 if (file_exists($file)) {721 $i18n_file = $file;722 break;723 }724 }725 }726 727 return $i18n_file;728 }
Nota: Vea TracChangeset
para ayuda en el uso del visor de conjuntos de cambios.