Продолжая писать компонент медиасурса (mediasource) Dropbox, о котором я говорил вчера (да-да, он пилится и уже сегодня будет опубликован:)), наткнулся на весьма неприятный баг. Собственно, самые наблюдательные могли его заметить еще вчера на этой картинке:
?
На ней две директории представлены как корневые, то есть имеют только слеш / и все. На самом деле это просто косяк с кириллическими именами файлов. При чем _и_Я — это тоже не полное название, просто после некириллических символов кириллические тоже начинают восприниматься.
Так вот, эта проблема проявилась и в админке при работе с источником файлов:
?
При этом самая печаль была с перетаскиванием. Если перетащить такую папку, то в новую она запишется с обрезанным именем. Как многие конечно же догадались, виновата в этом была функция basepath(), которая никак не хочет дружить с кириллицей. Ответ нашел здесь. Запись 2011-го года. Уже тогда автор задавался вопросом:
одно не понятно, в PHP этот баг уже несколько лет существует, почему бы не поправить… Пых, одним словом...
На носу 2015-ый, а бага так до сих пор не поправлена…
P.S. повторю спасительный код:
function pcgbasename($param, $suffix=null) {
if ( $suffix ) {
$tmpstr = ltrim(substr($param, strrpos($param, DIRECTORY_SEPARATOR) ), DIRECTORY_SEPARATOR);
if ( (strpos($param, $suffix)+strlen($suffix) ) == strlen($param) ) {
return str_ireplace( $suffix, '', $tmpstr);
} else {
return ltrim(substr($param, strrpos($param, DIRECTORY_SEPARATOR) ), DIRECTORY_SEPARATOR);
}
} else {
return ltrim(substr($param, strrpos($param, DIRECTORY_SEPARATOR) ), DIRECTORY_SEPARATOR);
}
}
P.P.S Переписал на мультибайтовые функции для MODX-а:
protected function basename($param, $suffix=null){
$charset = $this->xpdo->getOption('charset', 'utf-8');
if ( $suffix ) {
$tmpstr = ltrim(mb_substr($param, mb_strrpos($param, DIRECTORY_SEPARATOR, null, $charset), null, $charset), DIRECTORY_SEPARATOR);
if ( (mb_strpos($param, $suffix, null, $charset)+mb_strlen($suffix, $charset) ) == mb_strlen($param, $charset) ) {
return str_ireplace( $suffix, '', $tmpstr);
} else {
return ltrim(mb_substr($param, mb_strrpos($param, DIRECTORY_SEPARATOR, null, $charset), null, $charset), DIRECTORY_SEPARATOR);
}
} else {
return ltrim(mb_substr($param, mb_strrpos($param, DIRECTORY_SEPARATOR, null, $charset), null, $charset), DIRECTORY_SEPARATOR);
}
}