diff --git a/transliteration.inc b/transliteration.inc index f09af6c..17d0ac0 100644 --- a/transliteration.inc +++ b/transliteration.inc @@ -205,3 +205,65 @@ function _transliteration_replace($ord, $unknown = '?', $langcode = NULL) { return isset($map[$bank][$langcode][$ord]) ? $map[$bank][$langcode][$ord] : $unknown; } + +/** + * Return an array of arrays for punctuation values. + * + * Returns an array of arrays for punctuation values keyed by a name, including + * the value and a textual description. + * Can and should be expanded to include "all" non text punctuation values. + * + * @return + * An array of arrays for punctuation values keyed by a name, including the + * value and a textual description. + */ +function _transliteration_punctuation_chars() { + $punctuation = &drupal_static(__FUNCTION__); + + if (!isset($punctuation)) { + $cid = 'transliteration:file_punctuation:' . $GLOBALS['language']->language; + if ($cache = cache_get($cid)) { + $punctuation = $cache->data; + } + else { + $punctuation = array(); + $punctuation['space'] = array('value' => '\s', 'name' => t('Space')); + $punctuation['double_quotes'] = array('value' => '"', 'name' => t('Double quotation marks')); + $punctuation['quotes'] = array('value' => '\'', 'name' => t("Single quotation marks (apostrophe)")); + $punctuation['backtick'] = array('value' => '`', 'name' => t('Back tick')); + $punctuation['comma'] = array('value' => ',', 'name' => t('Comma')); + $punctuation['hyphen'] = array('value' => '-', 'name' => t('Hyphen')); + $punctuation['underscore'] = array('value' => '_', 'name' => t('Underscore')); + $punctuation['colon'] = array('value' => ':', 'name' => t('Colon')); + $punctuation['semicolon'] = array('value' => ';', 'name' => t('Semicolon')); + $punctuation['pipe'] = array('value' => '|', 'name' => t('Vertical bar (pipe)')); + $punctuation['left_curly'] = array('value' => '{', 'name' => t('Left curly bracket')); + $punctuation['left_square'] = array('value' => '[', 'name' => t('Left square bracket')); + $punctuation['right_curly'] = array('value' => '}', 'name' => t('Right curly bracket')); + $punctuation['right_square'] = array('value' => ']', 'name' => t('Right square bracket')); + $punctuation['plus'] = array('value' => '+', 'name' => t('Plus sign')); + $punctuation['equal'] = array('value' => '=', 'name' => t('Equal sign')); + $punctuation['asterisk'] = array('value' => '*', 'name' => t('Asterisk')); + $punctuation['ampersand'] = array('value' => '&', 'name' => t('Ampersand')); + $punctuation['percent'] = array('value' => '%', 'name' => t('Percent sign')); + $punctuation['caret'] = array('value' => '^', 'name' => t('Caret')); + $punctuation['dollar'] = array('value' => '$', 'name' => t('Dollar sign')); + $punctuation['hash'] = array('value' => '#', 'name' => t('Number sign (pound sign, hash)')); + $punctuation['at'] = array('value' => '@', 'name' => t('At sign')); + $punctuation['exclamation'] = array('value' => '!', 'name' => t('Exclamation mark')); + $punctuation['tilde'] = array('value' => '~', 'name' => t('Tilde')); + $punctuation['left_parenthesis'] = array('value' => '(', 'name' => t('Left parenthesis')); + $punctuation['right_parenthesis'] = array('value' => ')', 'name' => t('Right parenthesis')); + $punctuation['question_mark'] = array('value' => '?', 'name' => t('Question mark')); + $punctuation['less_than'] = array('value' => '<', 'name' => t('Less-than sign')); + $punctuation['greater_than'] = array('value' => '>', 'name' => t('Greater-than sign')); + $punctuation['back_slash'] = array('value' => '\\', 'name' => t('Backslash')); + + // Allow modules to alter the punctuation list and cache the result. + drupal_alter('transliteration_file_punctuation_chars', $punctuation); + cache_set($cid, $punctuation); + } + } + + return $punctuation; +} diff --git a/transliteration.install b/transliteration.install index 0071033..4620c18 100644 --- a/transliteration.install +++ b/transliteration.install @@ -27,6 +27,8 @@ function transliteration_install() { * Implements hook_uninstall(). */ function transliteration_uninstall() { - variable_del('transliteration_file_uploads'); - variable_del('transliteration_file_lowercase'); + // Delete all the transliteration file variables and then clear the variable + // cache. + db_query("DELETE FROM {variable} WHERE name LIKE 'transliteration_file_%'"); + cache_clear_all('variables', 'cache'); } diff --git a/transliteration.module b/transliteration.module index 4742bbf..f575ed8 100644 --- a/transliteration.module +++ b/transliteration.module @@ -8,6 +8,21 @@ */ /** + * Remove the punctuation from the file name. + */ +define('TRANSLITERATION_FILE_PUNCTUATION_REMOVE', 0); + +/** + * Replace the punctuation with the separator in the file name. + */ +define('TRANSLITERATION_FILE_PUNCTUATION_REPLACE', 1); + +/** + * Leave the punctuation as it is in the file name. + */ +define('TRANSLITERATION_FILE_PUNCTUATION_DO_NOTHING', 2); + +/** * Implements hook_menu(). */ function transliteration_menu() { @@ -53,6 +68,45 @@ function transliteration_form_system_file_system_settings_alter(&$form, &$form_s '#default_value' => variable_get('transliteration_file_lowercase', TRUE), '#description' => t('This is a recommended setting to prevent issues with case-insensitive file systems. It has no effect if transliteration has been disabled.'), ); + $form['transliteration']['transliteration_file_separator'] = array( + '#type' => 'select', + '#title' => t('Separator'), + '#options' => array( + '_' => t('_'), + '-' => t('-'), + ), + '#default_value' => variable_get('transliteration_file_separator', '_'), + '#description' => t('Character used to separate words in file names. This will replace any spaces and punctuation characters.'), + ); + $form['transliteration']['punctuation'] = array( + '#type' => 'fieldset', + '#title' => t('Punctuation'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + ); + + module_load_include('inc', 'transliteration'); + $punctuation = _transliteration_punctuation_chars(); + foreach ($punctuation as $name => $details) { + $details['default'] = TRANSLITERATION_FILE_PUNCTUATION_REMOVE; + if ($details['value'] == variable_get('transliteration_file_separator', '_')) { + $details['default'] = TRANSLITERATION_FILE_PUNCTUATION_REPLACE; + } + // Keep the previous value for the hyphen (-) character. + if ($details['value'] == '-') { + $details['default'] = TRANSLITERATION_FILE_PUNCTUATION_DO_NOTHING; + } + $form['transliteration']['punctuation']['transliteration_file_punctuation_' . $name] = array( + '#type' => 'select', + '#title' => $details['name'] . ' (' . check_plain($details['value']) . ')', + '#default_value' => variable_get('transliteration_file_punctuation_' . $name, $details['default']), + '#options' => array( + TRANSLITERATION_FILE_PUNCTUATION_REMOVE => t('Remove'), + TRANSLITERATION_FILE_PUNCTUATION_REPLACE => t('Replace by separator'), + TRANSLITERATION_FILE_PUNCTUATION_DO_NOTHING => t('No action (do not replace)'), + ), + ); + } $form['buttons']['#weight'] = 1; } @@ -78,6 +132,38 @@ function transliteration_form_system_file_system_settings_alter(&$form, &$form_s * @see language_default() */ function transliteration_clean_filename($filename, $source_langcode = NULL) { + $settings = &drupal_static(__FUNCTION__); + + // Generate and cache variables used in this function so that on the second + // call to pathauto_cleanstring() we focus on processing. + if (!isset($settings)) { + $settings = array( + 'separator' => variable_get('transliteration_file_separator', '_'), + 'punctuation' => array(), + 'punctuation_values' => '', + 'lowercase' => (bool) variable_get('transliteration_file_lowercase', TRUE), + ); + + // Generate and cache the punctuation replacements for strtr(). + module_load_include('inc', 'transliteration'); + $punctuation = _transliteration_punctuation_chars(); + foreach ($punctuation as $name => $details) { + $settings['punctuation_values'] .= $details['value']; + $action = variable_get('transliteration_file_punctuation_' . $name, TRANSLITERATION_FILE_PUNCTUATION_REMOVE); + switch ($action) { + case TRANSLITERATION_FILE_PUNCTUATION_REMOVE: + $settings['punctuation'][$details['value']] = ''; + break; + case TRANSLITERATION_FILE_PUNCTUATION_REPLACE: + $settings['punctuation'][$details['value']] = $settings['separator']; + break; + case TRANSLITERATION_FILE_PUNCTUATION_DO_NOTHING: + // Literally do nothing. + break; + } + } + } + if (is_array($filename)) { foreach ($filename as $key => $value) { $filename[$key] = transliteration_clean_filename($value, $source_langcode); @@ -85,14 +171,19 @@ function transliteration_clean_filename($filename, $source_langcode = NULL) { return $filename; } $filename = transliteration_get($filename, '', $source_langcode); - // Replace whitespace. - $filename = str_replace(' ', '_', $filename); + + // Replace or drop punctuation based on user settings + $filename = strtr($filename, $settings['punctuation']); + // Remove remaining unsafe characters. - $filename = preg_replace('![^0-9A-Za-z_.-]!', '', $filename); + $punctuation_regex = preg_quote($settings['punctuation_values']); + $filename = preg_replace('![^0-9A-Za-z.' . $punctuation_regex . ']!', '', $filename); + // Force lowercase to prevent issues on case-insensitive file systems. - if (variable_get('transliteration_file_lowercase', TRUE)) { + if ($settings['lowercase']) { $filename = strtolower($filename); } + return $filename; }