PHP и UTF-8: второй этап (продолжение: ничего не забыли?)
Итак, в прошлый раз мы выяснили какие файлы у нас содержат программы на PHP и какие расширения есть в нашем интерпретаторе. Кстати, не забывайте про внепроектные файлы, те, что лежат в других папках, например, уровнем ниже. Их тоже надо использовать в нашем исследовании.
Выяснить какие же расширения реально используются в проекте нам поможет следующая программа:
<?
$extensions = array_merge(
get_loaded_extensions(true),
get_loaded_extensions()
);
$funcs = array();
foreach ($extensions as $extension) {
if ($extension == 'standard' || $extension == 'session') {
continue;
}
$extfuncs = get_extension_funcs($extension);
if ($extfuncs) {
$funcs = array_merge(
$funcs,
array_combine(
array_map('strtolower', $extfuncs),
array_fill(0, sizeof($extfuncs), $extension)
)
);
};
}
$classes = get_declared_classes();
set_time_limit(0);
$classes_regexp = '/new\s+(?i)(' . implode('|', $classes) . ')/s';
$funcs_regexp = '/(' . implode('|', array_keys($funcs)) . ')/si';
$it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator('.'));
for (;$it->valid(); $it->next()) {
$ext = pathinfo($it->getBaseName(), PATHINFO_EXTENSION);
if ($ext == 'php' || $ext == 'tpl' || $ext == 'inc') {
$content = file_get_contents($it->key());
if (preg_match_all($classes_regexp, $content, $matches)) {
echo $it->key(), "\nClass: ",
implode("\nClass: ", array_map('strtolower', $matches[1])), "\n\n";
}
if (preg_match_all($funcs_regexp, $content, $matches)) {
echo $it->key(), "\n";
foreach ($matches[1] as $func) {
$func = strtolower($func);
if (isset($funcs[$func])) {
echo 'Module: ', $funcs[$func], "\n";
} else {
echo 'Something wrong: ', $func, "\n";
}
}
echo "\n\n";
}
}
}
У меня она отработала достаточно неспешно, за несколько минут. Каковы же результаты?
bolk@dev:~/daproject$ awk -F: '/^Module/{print $2}' tool2.log | sort -u
ctype
curl
date
gettext
hash
iconv
…
bolk@dev:~/daproject$ awk -F: '/^Class/{print $2}' tool2.log | sort -u
exception
simplexmlelement
Начнём с конца — Exception это класс для работы с исключениями, с UTF-8 он вполне себе дружит, SimpleXMLElement (как и расширение SimpleXML, откуда этот класс) так же работает с UTF-8.
А вот остальные 19 модулей, используемых в проекте, просмотреть сложнее. Их тех, что у меня есть я сразу могу исключить SQLITE3, XML, XML-RPC, Zlib, SimpleXML, PCRE, JSON, MySQL, hash, intercept и date — они с UTF-8 дружат, сразу могу сказать, что ctype с ним не работает, а к использованию модулей iconv и mbstring надо присмотреться — значит где-то используются функции конвертирования. Эти ситуации придётся разбирать вручную.
Как я узнаю какие модули работают с UTF-8, а какие нет? Их все можно разделить на четыре группы: придуманы, чтобы работать с разными кодировками (iconv, mbstring, PCRE), нейтральны к любой кодировке (date, intercept, hash), «я точно знаю, что с UTF-8 не дружат» (ctype), «не знаю, надо попробовать» (syck, sanitize).
На что ещё надо обратить внимание? На две вещи — нет ли в файлах где-то явного указания кодировки и не используются ли модули PEAR.
С первым просто, я перевожу проект с windows-1251, значит искать будем эту кодировку:
bolk@dev:~/wiki$ find -type f -name '?*.*' | grep -v '.svn' | xargs -r -n1 egrep -iH 'cp1251|cp\-1251|windows\-1251'
./php/dir1/file1.php: if (strtolower($rss->encoding) != 'windows-1251') {
./php/dir1/file2.php: $c = @iconv($rss->encoding, 'cp1251', $c);
./php/dir2/file3.php: $title = iconv('UTF-8', 'CP1251', $employers[$i]->first_name .' '. $employers[$i]->last_name);
…
У меня таких строк — вагон и маленькая тележка, что с ними делать, будем решать дальше, пока же отметим, что они есть, причём в количестве 158 штук.
А что с PEAR? Точнее, с теми файлами PEAR, которые подключаются не из папки проекта, а из папки PEAR, которая скрыта где-то в операционной системе? Тут всё до предела просто — откройте проект в своей любимой среде программирования (IDE), какой-нибудь Zend Studio или Eclipse, она покажет вам все импорты, которые есть в вашем проекте. Если видите что-то внешнее, то не забудьте включить и эти файлы в исследование.
У меня таких импортов, кстати, не оказалось.
Кажется, информации накоплено достаточно, пора что-то изменить в проекте.
(И тут я предлагаю сделать перерыв до завтра)
Болк — торт!