Транслитерация имён файлов при загрузке в MODx

Апрель 9, 2010 - 12:24:29 § в Статьи

Сколько бы я не предупреждал контент менеджеров, что нельзя закачивать в MODx файлы с именами, написанными символами, отличными от латиницы, всё-равно периодически кто-нибудь обязательно закачает такой файл и в результате перестаёт работать окно закачки файлов в документах – оно просто не показывает ни одного файла.

Кстати я вообще сторонник того, что названия файлов вообще надо писать латиницей, тогда ни в одной системе не возникнет проблем и файл всегда будет виден и доступен.

Вобщем приходится изредка подчищать такие “неправильные” файлы. И так продолжается до тех пор, пока наконец лень не победит чувство долга :) Сегодня как раз такой день – лень победила, чувство долга забилось в угол и освободило пространство для творчества.

Сегодня будем учить MODx транслитерировать файлы при загрузке на сервер. По правде говоря, так делать не очень хорошо – всё-таки должна быть свобода называть файлы так, как хочет контент менеджер. Но это, если контент менеджер знает, что делает. На практике же – это обычно девочка, секретать/офис менеджер/младший сотрудник отдела маркетинга, которая вовсе не обязана знать все эти тонкости.

Начнём с того самого окна загрузки файлов из документа. Выглядит оно примерно вот так:

Окно Resources Browser

Заходим на сервер в папку с установленным MODx и дальше переходим в папку manager/media/browser/mcpuk/connectors/php/Commands. Здесь открываем на редактирование файл FileUpload.php

Все дальнейшие операции должны проводиться с файлами в кодировке UTF-8. Это ВАЖНО! Я пользуюсь связкой WinSCP и Notepad++, который может перекодировать уже открытый файл в UTF-8. Делается это так:

Notepad++ 

Итак, файл перекодирован в UTF-8, можно продолжать.

В начало файла вставим следующий код:

function niceFilename($filename) {
    $changes = array(
        "Є"=>"EH", "І"=>"I", "і"=>"i", ""=>"#", "є"=>"eh",
        "А"=>"A", "Б"=>"B", "В"=>"V", "Г"=>"G", "Д"=>"D",
        "Е"=>"E", "Ё"=>"E", "Ж"=>"ZH", "З"=>"Z", "И"=>"I",
        "Й"=>"J", "К"=>"K", "Л"=>"L", "М"=>"M", "Н"=>"N",
        "О"=>"O", "П"=>"P", "Р"=>"R", "С"=>"S", "Т"=>"T",
        "У"=>"U", "Ф"=>"F", "Х"=>"H", "Ц"=>"C", "Ч"=>"CH",
        "Ш"=>"SH", "Щ"=>"SCH", "Ъ"=>"", "Ы"=>"Y", "Ь"=>"",
        "Э"=>"E", "Ю"=>"YU", "Я"=>"YA", "Ē"=>"E", "Ū"=>"U",
        "Ī"=>"I", "Ā"=>"A", "Š"=>"S", "Ģ"=>"G", "Ķ"=>"K",
        "Ļ"=>"L", "Ž"=>"Z", "Č"=>"C", "Ņ"=>"N", "ē"=>"e",
        "ū"=>"u", "ī"=>"i", "ā"=>"a", "š"=>"s", "ģ"=>"g",
        "ķ"=>"k", "ļ"=>"l", "ž"=>"z", "č"=>"c", "ņ"=>"n",
        "а"=>"a", "б"=>"b", "в"=>"v", "г"=>"g", "д"=>"d",
        "е"=>"e", "ё"=>"e", "ж"=>"zh", "з"=>"z", "и"=>"i",
        "й"=>"j", "к"=>"k", "л"=>"l", "м"=>"m", "н"=>"n",
        "о"=>"o", "п"=>"p", "р"=>"r", "с"=>"s", "т"=>"t",
        "у"=>"u", "ф"=>"f", "х"=>"h", "ц"=>"c", "ч"=>"ch",
        "ш"=>"sh", "щ"=>"sch", "ъ"=>"", "ы"=>"y", "ь"=>"",
        "э"=>"e", "ю"=>"yu", "я"=>"ya", "Ą"=>"A", "Ę"=>"E",
        "Ė"=>"E", "Į"=>"I", "Ų"=>"U", "ą"=>"a", "ę"=>"e",
        "ė"=>"e", "į"=>"i", "ų"=>"u", "ö"=>"o", "Ö"=>"O",
        "ü"=>"u", "Ü"=>"U", "ä"=>"a", "Ä"=>"A", "õ"=>"o",
        "Õ"=>"O");
    $alias=strtr($filename, $changes);
    $alias = strtolower( $alias );
    $alias = preg_replace('/&.+?;/', '', $alias); // kill entities
    $alias = str_replace( '_', '-', $alias );
    $alias = preg_replace('/[^a-z0-9\s-.]/', '', $alias);
    $alias = preg_replace('/\s+/', '-', $alias);
    $alias = preg_replace('|-+|', '-', $alias);
    $alias = trim($alias, '-');
    return $alias;
}

Далее находим строку:


$filename=basename(str_replace("\\","/",$_FILES['NewFile']['name']));

И меняем её на такую:

$filename=basename(str_replace("\\","/",$this->niceFilename($_FILES['NewFile']['name'])));

Сохраняем и проверяем закачкой файла, названного по-русски, по-латышски, по-литовски или по-эстонски. Если имя файла транслитерировалось, все спец-символы исчезли, все буквы стали строчными, а пробелы заменились на дефис, то всё работает как надо. Если нет – ищите ошибку.

Теперь займёмся менеджером файлов, который находится в MODx здесь:

Ресурсы->Управление файлами

Переходим в папку manager/actions и открываем, находящийся в ней файл files.dynamic.php

Точно также вставляем в него нашу функцию niceFilename(). Далее находим строку:

$userfiles[$i]['name'] = $_FILES['userfile']['name'][$i];

и заменяем её на:

$userfiles[$i]['name'] = niceFilename($_FILES['userfile']['name'][$i]);

Сохраняем файл.

Опять проверяем работу закачкой файла, но теперь уже через файл-менеджер. Если всё в порядке, сообщаем контент менеджерам, что и на их улицу пришёл праздник :)

А чувство долга зашевелилось у себя в углу и, похоже, непрочь набраться наглости, чтобы прогнать лень. Ну что же. Не будем ему мешать…



7 Comments Add Yours ↓

  1. mac #
    1

    Толково, а главное просто

    единственное что хотелось бы дополнить:

    1. стоит добавить символы:

    "є"=>"e",
    "Є"=>"e",
    "ї"=>"yi",
    "Ї"=>"yi",
    "і"=>"i",
    "І"=>"i",
    "ґ"=>"g",
    "Ґ"=>"g"

    из Украинского алфавита

    2. есть смысл немного упростить regex’ы вот так:

    $alias = strtr(trim($filename), $changes);
    $alias = strtolower( $alias );
    $alias = ereg_replace("[^a-zA-Z0-9]","-",$alias);
    $alias = ereg_replace("[-]+","-",$alias);
    $alias = trim($alias, '-');

    тоесть мы просто заменяем любые символы кроме букв и цыфр на дефисы, а затем тримаем результат по этому делу да и все.

  2. bug #
    2

    Спасибо за regexp-ы и отдельно за замены для украинского языка – как раз скоро пригодится!

  3. Yurgen #
    3

    Спасибо!

    Только вот у меня заработало когда строку изменил на:

    $filename=basename(str_replace(»\\»,»/»,niceFilename($_FILES['NewFile']['name'])));

    MODx 1.0.4

  4. 4

    спасибо! Недавно столкнулся с аналогичной проблемой – решение пришлось как нельзя кстати.

  5. 5

    Полагаю следует уточнить, что в файле FileUpload.php функцию niceFilename следует вставить не в начало файла, а после описания переменных класса т.к. она используется как метод класса.

    Вот так

    class FileUpload {
    var $fckphp_config;
    var $type;
    var $cwd;
    var $actual_cwd;
    var $newfolder;

    function niceFilename($filename) {
    $changes = array(

  6. Omio #
    6

    Вот вопрос возник, а как ту же самую процедуру сделать в MODx Revolution? Буду очень признателен если мне помогут

  7. bug #
    7

    Ajpro, спасибо за уточнение! Конечно же niceFilename надо вставлять после описания переменных класса.



Ваш комментарий