Колись, коли мій блог ще працював на WordPress, я часто викладав ноти й тексти пісень у PDF. Щоб документ можна було переглянути просто на сторінці, я ставив плаґін PDF Viewer, а кожне посилання на файл вручну загортав у його шорткод. Набридло мені це дуже швидко, тож я знайшов фільтр, який робив це сам під час вставки файлу. Відтоді WordPress перейшов на блоковий редактор, і той фільтр там просто не спрацьовує. А плаґін для перегляду PDF узагалі став не потрібен. Тож розповім, як змінити посилання на медіафайли сьогодні: у блоковому редакторі і, про всяк випадок, у класичному.

Перегляд PDF без плаґіна

Почну з доброї новини: якщо тобі, як колись мені, потрібно показати PDF просто на сторінці, нічого ставити не треба. Вставляєш файл блоком «Файл» (або просто перетягуєш PDF у редактор), і в налаштуваннях блоку праворуч з'являється перемикач вбудованого перегляду (Show inline embed). Там же можна задати висоту рамки і вимкнути кнопку «Завантажити», якщо вона не потрібна.

Документ показує сам браузер, без жодних сторонніх скриптів. А там, де браузер вбудований перегляд PDF не підтримує (буває на телефонах), WordPress його ховає, і лишається звичайне посилання на файл.

Як змінити посилання в блоковому редакторі

Інша справа, коли посилання на файли треба якось змінити: додати свій клас, відкривати в новій вкладці, підлаштувати під свій дизайн чи якийсь скрипт. У блоковому редакторі для цього є фільтр render_block. Він спрацьовує щоразу, коли WordPress виводить блок на сторінці, і дає змінити його HTML.

Ось приклад, який додає всім посиланням на PDF у блоці «Файл» клас pdf-link і відкриває їх у новій вкладці:

function mytheme_pdf_file_links( $block_content, $block ) {
    $id = $block['attrs']['id'] ?? 0;

    if ( ! $id || 'application/pdf' !== get_post_mime_type( $id ) ) {
        return $block_content;
    }

    $tags = new WP_HTML_Tag_Processor( $block_content );

    while ( $tags->next_tag( 'a' ) ) {
        $tags->add_class( 'pdf-link' );
        $tags->set_attribute( 'target', '_blank' );
        $tags->set_attribute( 'rel', 'noopener' );
    }

    return $tags->get_updated_html();
}

add_filter( 'render_block_core/file', 'mytheme_pdf_file_links', 10, 2 );

Що тут відбувається:

  • render_block_core/file – варіант фільтра лише для блоку «Файл». Для інших блоків назва інша: render_block_core/image для зображень, render_block_core/video для відео і так далі. Так функція не запускається для кожного абзацу на сторінці.
  • $block['attrs']['id'] – ID файлу в медіабібліотеці. За ним get_post_mime_type() дізнається тип файлу, і ми змінюємо лише PDF, а архіви чи документи Word лишаємо як є.
  • WP_HTML_Tag_Processor – вбудований у WordPress інструмент, який проходить по тегах у HTML і змінює їхні атрибути. Це надійніше, ніж шукати й замінювати шматки тексту регулярними виразами: розмітка не зламається, навіть якщо в назві файлу трапляться лапки чи інші дивні символи.

І головна перевага цього способу: фільтр змінює посилання під час виведення сторінки, а не в самому записі. Тож він одразу діє на всі файли на сайті, і на ті, що ти вставив/ла роками раніше. А якщо колись прибереш код, усе повернеться до звичайного вигляду.

Повністю своя розмітка

Якщо стандартний вигляд блоку зовсім не підходить, фільтр може повернути замість нього будь-який HTML. Наприклад, власну картку файлу з назвою і розміром:

function mytheme_pdf_file_card( $block_content, $block ) {
    $id = $block['attrs']['id'] ?? 0;

    if ( ! $id || 'application/pdf' !== get_post_mime_type( $id ) ) {
        return $block_content;
    }

    $url  = wp_get_attachment_url( $id );
    $size = size_format( filesize( get_attached_file( $id ) ) );

    return sprintf(
        '<p class="pdf-card"><a href="%s" target="_blank" rel="noopener">%s</a> <span>PDF, %s</span></p>',
        esc_url( $url ),
        esc_html( get_the_title( $id ) ),
        esc_html( $size )
    );
}

add_filter( 'render_block_core/file', 'mytheme_pdf_file_card', 10, 2 );

Тут ми вже не правимо HTML блоку, а складаємо свій. Назву беремо з медіабібліотеки, розмір рахуємо з самого файлу на диску, а size_format() перетворює байти на зрозуміле «1,2 МБ». І, як завжди, усе, що виводимо, пропускаємо через esc_url() та esc_html().

Класичний редактор: фільтр media_send_to_editor

Якщо на сайті досі класичний редактор, працює той самий фільтр, який я колись знайшов. Він спрацьовує в момент, коли ти натискаєш «Вставити в запис» у вікні медіабібліотеки, і дає замінити HTML, який потрапить у текст:

function mytheme_pdf_link_classic( $html, $id ) {
    if ( 'application/pdf' !== get_post_mime_type( $id ) ) {
        return $html;
    }

    return sprintf(
        '<a class="pdf-link" href="%s" target="_blank" rel="noopener">%s</a>',
        esc_url( wp_get_attachment_url( $id ) ),
        esc_html( get_the_title( $id ) )
    );
}

add_filter( 'media_send_to_editor', 'mytheme_pdf_link_classic', 20, 2 );

Різниця з render_block принципова: цей фільтр змінює посилання лише в момент вставки, і змінений HTML зберігається в самому записі. Файли, вставлені раніше, він не зачепить, а прибравши код, ти нічого не повернеш назад. Тому, якщо є вибір, я беру блоковий варіант.

Куди вставляти код

Найпростіше – у файл functions.php своєї теми. Але пам'ятай: зміниш тему – код зникне разом з нею. Якщо зміна посилань потрібна незалежно від дизайну, краще зробити маленький плаґін: файл у теці wp-content/plugins з коментарем-заголовком /* Plugin Name: PDF links */ на початку. Тоді його можна вмикати й вимикати в адмінці, як будь-який інший плаґін.

Що далі

Фільтр render_block корисний не лише для файлів: так само можна змінювати будь-які блоки, зокрема й блоки WooCommerce, – ось приклад, як додати категорії товарів до блоків WooCommerce. Якщо твоя тема ще не дружить із блоковим редактором, глянь, як підготувати класичну тему WordPress до Gutenberg. А ще одна корисна задача для хуків – правильне сортування статей у WordPress.

Більше про це – за позначками Хуки WordPress та PHP.

А ти викладаєш на сайті PDF чи інші файли? Як вони у тебе виглядають? Пиши в коментарях 🙂