Как в WordPress загрузить SVG
По умолчанию в WordPress нельзя загружать SVG в целях безопасности. Но что делать, когда очень надо? Решение есть!

О том, будет ли разрешена загрузка SVG в WordPress по умолчанию и почему разработчики этого избегают, читайте в тикете #24251 Reconsider SVG inclusion to get_allowed_mime_types.
Плагин ― включить загрузку svg можно также через плагин Safe SVG. Он кроме прочего очищает код загружаемого файла.
Смотрите также: Разрешаем загрузку запрещенных типов файлов
Шаг 1 - Включение SVG в список разрешенных для загрузки файлов
Для этого воспользуемся хуком upload_mimes, позволяющим изменять список доступных для загрузки файлов по MIME-типу.
add_filter( 'upload_mimes', 'svg_upload_allow' ); # Добавляет SVG в список разрешенных для загрузки файлов. function svg_upload_allow( $mimes ) { $mimes['svg'] = 'image/svg+xml'; return $mimes; }
Иногда этого кода достаточно, но не для всех svg файлов. Разберемся почему так.
Реальный MIME тип svg файла, который в WP определятся php функцией finfo_file() (см. код wp_check_filetype_and_ext() ) может быть двух вариантов:
image/svg+xml
— когда в коде svg есть xml заголовок.image/svg
— когда в коде svg есть только тег <svg>, без каких либо заголовков.
Сюда нужно добавить оба эти варианта, но добавить можно только один, поэтому только этого кода недостаточно и нужен второй шаг.
Шаг 2 - Подмена mime типа SVG
Как описано выше предыдущего кода для решения проблемы недостаточно. Точнее, в результате проверки и несовпадения указанного MIME типа и реального (полученного самим WP) MIME тип будет просто обнулен. Вернуть его обратно нам поможет хук wp_check_filetype_and_ext.
add_filter( 'wp_check_filetype_and_ext', 'fix_svg_mime_type', 10, 5 ); # Исправление MIME типа для SVG файлов. function fix_svg_mime_type( $data, $file, $filename, $mimes, $real_mime = '' ){ // WP 5.1 + if( version_compare( $GLOBALS['wp_version'], '5.1.0', '>=' ) ){ $dosvg = in_array( $real_mime, [ 'image/svg', 'image/svg+xml' ] ); } else { $dosvg = ( '.svg' === strtolower( substr( $filename, -4 ) ) ); } // mime тип был обнулен, поправим его // а также проверим право пользователя if( $dosvg ){ // разрешим if( current_user_can('manage_options') ){ $data['ext'] = 'svg'; $data['type'] = 'image/svg+xml'; } // запретим else { $data['ext'] = false; $data['type'] = false; } } return $data; }
Если из кода выше убрать проверку на право администратора, то код станет небезопасным и потенциально открывает дыру в защите сайта.
В коде выше добавлена проверка на версию WP. С WP 5.1.0 благодаря тикету автора этого сайта в хуке появился параметр $real_mime. Он позволяет сделать более надежную проверку файла — на уровне определения MIME типа файла по его коду, а не расширению.
Также рекомендую ограничить размер загружаемого svg файла, например не более 50кб. SVG файлы как правило маленькие и большой размер может говорить о том, что в файле какой-либо нехороший код.
Кода выше достаточно, чтобы WоrdPress разрешил загружать SVG в медиабиблиотеку. Следующий шаг чисто визуальный.
Отображение SVG в медиабиблиотеке
После проделанных шагов SVG файлы будут отображаться как документы, а не изображения:
За разметку этих блоков с изображениями отвечает код, генерируемый функцией wp_print_media_templates() из файла wp-includes/media-template.php:
<div class="thumbnail"> <# if ( data.uploading ) { #> <div class="media-progress-bar"><div style="width: {{ data.percent }}%"></div></div> <# } else if ( 'image' === data.type && data.sizes ) { #> <div class="centered"> <img src="{{ data.size.url }}" draggable="false" alt="" /> </div> <# } else { #> <div class="centered"> <# if ( data.image && data.image.src && data.image.src !== data.icon ) { #> <img src="{{ data.image.src }}" class="thumbnail" draggable="false" alt="" /> <# } else if ( data.sizes && data.sizes.medium ) { #> <img src="{{ data.sizes.medium.url }}" class="thumbnail" draggable="false" alt="" /> <# } else { #> <img src="{{ data.icon }}" class="icon" draggable="false" alt="" /> <# } #> </div> <div class="filename"> <div>{{ data.filename }}</div> </div> <# } #> </div>
Смысл кода в том, что он отобразит изображение, если
- у него есть свойство src (ссылка на изображение) и оно не равно ссылке на иконку документа (любой файл по сути документ);
- или если у изображения есть размер medium (svg файл вообще не кропается).
Файл SVG не имеет ни первого ни второго, поэтому нам нужно сымитировать самостоятельно один из этих вариантов и в этом нам поможет фильтр wp_prepare_attachment_for_js, используйте любой из вариантов по вкусу.
Вариант 1 - С выводом названия файла

add_filter( 'wp_prepare_attachment_for_js', 'show_svg_in_media_library' ); # Формирует данные для отображения SVG как изображения в медиабиблиотеке. function show_svg_in_media_library( $response ) { if ( $response['mime'] === 'image/svg+xml' ) { // С выводом названия файла $response['image'] = [ 'src' => $response['url'], ]; } return $response; }
Вариант 2 - Без вывода названия файла

add_filter( 'wp_prepare_attachment_for_js', 'show_svg_in_media_library' ); # Формирует данные для отображения SVG как изображения в медиабиблиотеке. function show_svg_in_media_library( $response ) { if ( $response['mime'] === 'image/svg+xml' ) { // Без вывода названия файла $response['sizes'] = [ 'medium' => [ 'url' => $response['url'], ], // при редактирования картинки 'full' => [ 'url' => $response['url'], ], ]; } return $response; }