oEmbed в WordPress
oEmbed — це відкритий формат, створений для спрощення вбудовування вмісту однієї веб-сторінки в іншу. У ролі контенту можуть бути: фотографії, відеоролики, посилання та інші типи контенту.
oEmbed контент – це відео, аудіо, HTML та інші коди на вашому сайті, які були вбудовані з іншого сайту. Наприклад, якщо в WP вставити посилання на відео youtube вона перетвориться на iframe з відео роликом.
Читайте також: Шорткоди в WordPress .
Як це працює
В основі роботи класу WP_oEmbed{} – саме він містить список зареєстрованих провайдерів oEmbed і він займається запитом (отриманням), обробкою Discovery посилання в head частини HTML.
На дуже ранній стадії ще до хука mu_plugin_loaded ініціалізується клас WP_Embed :
$GLOBALS['wp_embed'] = новий WP_Embed();
У конструкторі WP_Embed::__construct() створюються такі хуки:
function __construct() { // Hack to get the shortcode to run before wpautop(). add_filter( 'the_content', array( $this, 'run_shortcode' ), 8); add_filter( 'widget_text_content', array( $this, 'run_shortcode' ), 8); // Shortcode placeholder for strip_shortcodes(). add_shortcode('embed', '__return_false'); // Attempts to embed all URLs in a post. add_filter( 'the_content', array( $this, 'autoembed' ), 8); add_filter( 'widget_text_content', array( $this, 'autoembed' ), 8 ); // Після того, як буде збережено, cache oEmbed items via Ajax. add_action( 'edit_form_advanced', array( $this, 'maybe_run_ajax_cache' ) ); add_action( 'edit_page_form', array( $this, 'maybe_run_ajax_cache' ) ); } </pre> <h3 id="obrabotka-oembed-url-na-fronte"><a rel="nofollow" class="kamatoc-anchlink" href="https://wp-doc.com/handbook/codex/oembed#obrabotka-oembed-url-na-fronte"> <svg> <use xlink:href="#anchor-link-svg"></use> </svg></a>Обробка oEmbed URL на фронті</h3> <p>Контент запису або віджета text перевіряється на наявність шоткоду <code></code>або наявність URL на окремому рядку. Для цього, як видно з коду вище, на хуку <a href="https://wp-doc.com/hook/the_content"><var>the_content</var></a> запускаються два методи:</p> <ol> <li><a href="https://wp-doc.com/function/WP_Embed::run_shortcode">WP_Embed::run_shortcode( $post_content )</a> - обробляє шоткод <code></code>.</li> <li> <p><a href="https://wp-doc.com/function/WP_Embed::shortcode">WP_Embed::shortcode( $attr, $url )</a> . Далі:</p> <ol> <li> <p><strong>Перевіряється внутрішній оброблювач | Embed</strong></p> <p>URL передається у метод <a href="https://wp-doc.com/function/wp_embed_register_handler">wp_embed_register_handler()</a> .</p> <ol> <li>Якщо обробник знайдений, то URL-адреса передається в функцію-обробник і результат повертається. Робота методу <var>WP_Embed::shortcode()</var> при цьому припиняється.</li> <li>Якщо обробник не знайдено, <var>WP_Embed::shortcode()</var> продовжує перевірку oEmbed (зовнішніх) обробників.</li> </ol> </li> <li> <p><strong>Перевіряється зовнішній обробник | oEmbed</strong></p> <ol> <li>Якщо для URL є кеш, то парсинг переривається – результат береться з кешу.</li> <li> <p>Якщо кеша немає, то URL передається в функцію <a href="https://wp-doc.com/function/WP_oEmbed::get_provider">WP_oEmbed::get_provider()</a> , далі з цим URL порівнюються всі зареєстровані провайдери ( <var>WP_oEmbed::$providers</var> ) і якщо є збіг, робить щоб отримати oEmbed вставку з іншого сайту (за цей запит відповідає <var>WP_oEmbed</var> клас ). Наприкінці, будь-який результат, обробка URL кешується.</p> <div class="c_box_note"> <span class="some-icon"></span> <p>При такому варіанті кеш створюється тільки за першого запиту (коли його немає) і він не оновлюється. Оновлення кешу відбувається лише при оновленні запису в адмінці.</p> </div> </li> </ol> </li> </ol> </li> </ol> <h3 id="obrabotka-oembed-url-v-adminke"><a rel="nofollow" class="kamatoc-anchlink" href="https://wp-doc.com/handbook/codex/oembed#obrabotka-oembed-url-v-adminke"> <svg> <use xlink:href="#anchor-link-svg"></use> </svg></a>Обробка oEmbed URL в адмінці</h3> <p>Також oEmbed кеш створюється та (важливо) оновлюється при оновленні запису на сторінці редагування запису в адмінці. Робиться це запитом AJAX. Створюється такий AJAX запит тільки в момент оновлення запису в адмнику - див. <a href="https://wp-doc.com/function/WP_Embed::maybe_run_ajax_cache">WP_Embed::maybe_run_ajax_cache()</a> .</p> <ul> <li><a href="https://wp-doc.com/function/wp_ajax_oembed_cache">wp_ajax_oembed_cache()</a> <ul> <li><a href="https://wp-doc.com/function/WP_Embed::cache_oembed">WP_Embed::cache_oembed( $post_id )</a> <ul> <li>Далі обробка йде за описаною вище схемою, контент посту передається в методи: <a href="https://wp-doc.com/function/WP_Embed::autoembed">WP_Embed::autoembed( $post_content )</a> . <ul> <li><a href="https://wp-doc.com/function/WP_Embed::shortcode">WP_Embed::shortcode( $attr, $url )</a> . <ul> <li>і т.д.</li> </ul></li> </ul></li> </ul></li> </ul></li> </ul> <p>Наприклад, розглянемо, як WordPress обробляє посилання на інші сайти на WordPress, щоб вбудувати контент іншого сайту. Загальний принцип всього цього описаний вище, а нижче розглянемо, як це працює в адмінці.</p> <h4>Блоковий редактор</h4> <p>При вставці посилання в блоковий редактор спрацьовує подію js, що відправляє ajax запит методом GET на роут <code>домен/wp-json/oembed/1.0/proxy</code>, який реєструє метод <a href="https://wp-doc.com/function/WP_oEmbed_Controller::register_routes">WP_oEmbed_Controller::register_routes()</a> . Приклад даних, що відправляються:</p> <pre class="plain">url: https://oddstyle.ru/instrukciya-po-rabote-s-wordpress-rukovodstvo-dlya-novichkov _locale: user</pre> <p>Відповідь генерує метод <a href="https://wp-doc.com/function/WP_oEmbed_Controller::get_proxy_item">WP_oEmbed_Controller::get_proxy_item()</a> :</p> <pre class="json">{ "version":"1.0", "provider_name":"Блог про WordPress", "provider_url":"https://oddstyle.ru", "author_name":"Дмитро", "author_url":"https://oddstyle.ru/author/admin", "title":"Інструкція по роботі з WordPress. Посібник для новачків", "type":"rich", "width":600, "height":338, "html":" <blockquote class="wp-embedded-content" data-secret="X2b9CmjdiG"> <a href="https://oddstyle.ru/instrukciya-po-rabote-s-wordpress-rukovodstvo-dlya-novichkov">Інструкція по роботі з WordPress. Посібник для новачків</a> </blockquote> <iframe class="wp-embedded-content" sandbox="allow-scripts" security="restricted" style="position: absolute; clip: rect(1px, 1px, 1px, 1px);" title=""Інструкція по роботі з WordPress. Посібник для новачків" — Блог про WordPress" src="https://oddstyle.ru/instrukciya-po-rabote-s-wordpress-rukovodstvo-dlya-novichkov/embed#?secret=X2b9CmjdiG" data-secret="X2b9CmjdiG" width="600" height = "338" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" ></iframe> " }</pre> <p>Дані кешуються до таблиці <var>*_options</var> .</p> <h4>Візуальний редактор</h4> <p>При використанні візуального редактора при вставці посилання спрацьовує JS подія, що запускає запит на ajax методом post на файл <a href="https://wp-doc.com/function/wp_ajax_parse_embed">wp_ajax_parse_embed()</a> .</p> <p>Приклад даних, що відправляються:</p> <pre class="plain">post_ID: 31 type: embed shortcode: https://oddstyle.ru/instrukciya-po-rabote-s-wordpress-rukovodstvo-dlya-novichkov maxwidth: 549 action: parse-embed
Вміст поля shortcode передається до Як це працює “.
Приклад даних, що повертаються:
{ "success":true, "data":{ "body":" <blockquote class="wp-embedded-content" data-secret="mf3DjZabsV"> <a href="https://oddstyle.ru/instrukciya-po-rabote-s-wordpress-rukovodstvo-dlya-novichkov">Інструкція по роботі з WordPress. Посібник для новачків</a> </blockquote> <iframe class="wp-embedded-content" sandbox="allow-scripts" security="restricted" style="position: absolute; clip: rect(1px, 1px, 1px, 1px);" title=""Інструкція по роботі з WordPress. Посібник для новачків" — Блог про WordPress" src="https://oddstyle.ru/instrukciya-po-rabote-s-wordpress-rukovodstvo-dlya-novichkov/embed#?secret=mf3DjZabsV" data-secret="mf3DjZabsV" width="549" height = "309" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" ></iframe> ", "attr":{ "width":549, "height":824 }, "head":"<script src="https://wp-test.ru/wp-includes/js/wp-embed.js"></script>", "sandbox":true } }
Дані кешуються в таблицю wp_postmeta або wp_posts .
Кешування oEmbed запиту
Для кешування запитів можуть бути використані метаполя запису (поста) або таблиця wp_posts .
Якщо шоткод або посилання викликається з контенту посту, кеш буде зберігатися в метаполі поточного запису.
Якщо поточний запис немає, то кеш буде зберігатися в таблицю wp_posts під типом запису oembed_cache .
Кеш актуальний 1 день (86 400 секунд). Це значення можна змінити через хук oembed_ttl .
ВАЖЛИВО! Перевірка часу життя та оновлення кешу відбувається лише при оновленні запису зі сторінки редагування запису в адмінці. З фронту кеш не оновлюється. Запуск оновлення кешу в адмінці ініціалізують ці хуки:
add_action( 'edit_form_advanced', array( $this, 'maybe_run_ajax_cache' ) ); add_action( 'edit_page_form', array( $this, 'maybe_run_ajax_cache' ) );
oEmbed Безпека
Вбудовування чужого коду на свій сайт відкриває можливість атаки XSS. Так, наприклад, отриманий код може містити хакерський код, який може отримати куки вашого сайту та й взагалі може робити купу всього.
Щоб убезпечити себе від подібного роду дір у безпеці, WordPress виводить вбудовування в тегу <iframe> . Також очищає отриманий код iframe від небажаних атрибутів. Зокрема код вбудовування допускає такі HTML теги, які перевіряються функцією wp_kses() :
$allowed_html = array( 'a' => array( 'href' => true, ), 'blockquote' => array(), 'iframe' => array( 'src' => true, 'width' => true, 'height' => true, 'frameborder' => true, 'marginwidth' => true, 'marginheight' => true, 'scrolling' => true, 'title' => true, ), ); $html = wp_kses($html, $allowed_html);
Як бачимо код вбудовування може містити лише три теги та обмежена кількість параметрів для цих тегів.
Дивіться код функції oembed_dataparse і застосовується до всіх отриманих кодів для вбудовування.
WordPress як постачальник oEmbed
З версії 4.4. WordPress сам став постачальником/провайдером oEmbed формату. Тепер записи одного сайту WP можна вбудувати в інший сайт.
Щоб це зробити, потрібно до контенту посту додати URL запису. Зробити це можна двома способами:
- Додати URL на окремий рядок.
- Вставити URL в шоткод
</code>. Наприклад <code>http://dom.com/adress
.
WordPress автоматично обробить зазначений URL (визначить чи є той oEmbed провайдером), вбудує дані та створить кеш запиту, щоб не робити цей запит щоразу під час завантаження сторінки.
Вбудовування являють собою коротку версію сторінки. Наприклад, якщо додати /embed
до кінця URL будь-якого запису, ми потрапимо на сторінку вбудовування (яка повинна з’явитися на іншому сайті при вбудовуванні). Ось приклад такої сторінки: https://wp-doc.com/handbook/codex/oembed/embed .
Приклад того, як виглядає вбудовування:
Як змінити HTML код вбудовування?
Для цього потрібно створити в темі файл embed.php
– докладніше про ієрархію шаблону .
Якщо такого файлу у темі немає, то за код вбудовування відповідають файли:
У кожному з цих файлів є хуки, які можна використовувати зміни окремих частин HTML сторінки вбудовування.
Функції oEmbed
- get_post_embed_url() — Отримує URL, який потрібно використовувати в iframe для вбудовування зазначеного запису на іншому сайті (oEmbed формат).
- get_post_embed_html() — Отримує готовий HTML код oEmbed вбудовування зазначеного запису. Передбачається використання цього коду для вбудовування запису на іншому ресурсі.
- is_embed() — Перевірять, чи є запит запитом на сторінку вбудовування запису (embed).
- wp_embed_register_handler() – Реєструє Embed обробник. Це обробник, який перетворює посилання на контент в HTML код.
- wp_oembed_get() — Вбудовує об’єкт з УРЛ. Намагається отримати HTML код із переданого УРЛ на основі підтримуваних oEmbed WordPress.
- wp_oembed_add_provider() — Додає oEmbed провайдера. Це URL, який буде парситися в контенті для виведення HTML коду з іншого сайту.
- wp_oembed_remove_provider() — Removes an oEmbed provider.
Див. Повний список функцій Embed .
Хуки oEmbed
- embed_cache_oembed_types – дозволяє змінити типи записів для яких потрібно обробляти oembed посилання (шоткоди).
- oembed_ttl – дозволяє змінити TTL (time to live) час життя кешу.
- embed_oembed_html – дозволяє змінити вже закешований HTML.
- oembed_dataparse — Дозволяє змінити контент (HTML), що створюється при вбудовуванні URL, що підтримуються oEmbed.
- embed_oembed_discover — Дозволяє вказати, чи потрібно переходити по URL і шукати
<link>
тег вбудовування на віддаленому сайті.
Див. Повний список хуків .
Підтримувані провайдери
Нижче список oEmbed провайдерів, яких WordPress підтримує з коробки. Додаткові провайдери можна додати до цього списку за допомогою wp_oembed_add_provider() .
Provider | Flavor | Since |
---|---|---|
Dailymotion | dailymotion.com | 2.9.0 |
Flickr | flickr.com | 2.9.0 |
Scribd | scribd.com | 2.9.0 |
Vimeo | vimeo.com | 2.9.0 |
WordPress.tv | wordpress.tv | 2.9.0 |
YouTube | youtube.com/watch | 2.9.0 |
Crowdsignal | polldaddy.com | 3.0.0 |
SmugMug | smugmug.com | 3.0.0 |
YouTube | youtu.be | 3.0.0 |
twitter.com | 3.4.0 | |
instagram.com | 3.5.0 | |
instagr.am | 3.5.0 | |
Slideshare | slideshare.net | 3.5.0 |
SoundCloud | soundcloud.com | 3.5.0 |
Dailymotion | dai.ly | 3.6.0 |
Flickr | flic.kr | 3.6.0 |
Spotify | spotify.com | 3.6.0 |
Imgur | imgur.com | 3.9.0 |
Meetup.com | meetup.com | 3.9.0 |
Meetup.com | meetu.ps | 3.9.0 |
Animoto | animoto.com | 4.0.0 |
Animoto | video214.com | 4.0.0 |
Issuu | issuu.com | 4.0.0 |
Mixcloud | mixcloud.com | 4.0.0 |
Crowdsignal | poll.fm | 4.0.0 |
TED | ted.com | 4.0.0 |
YouTube | youtube.com/playlist | 4.0.0 |
Tumblr | tumblr.com | 4.2.0 |
Kickstarter | kickstarter.com | 4.2.0 |
Kickstarter | kck.st | 4.2.0 |
Cloudup | cloudup.com | 4.3.0 |
ReverbNation | reverbnation.com | 4.4.0 |
VideoPress | videopress.com | 4.4.0 |
reddit.com | 4.4.0 | |
Speaker Deck | speakerdeck.com | 4.4.0 |
twitter.com/timelines | 4.5.0 | |
twitter.com/moments | 4.5.0 | |
facebook.com | 4.7.0 | |
twitter.com/user | 4.7.0 | |
twitter.com/likes | 4.7.0 | |
twitter.com/lists | 4.7.0 | |
Screencast | screencast.com | 4.8.0 |
Amazon | amazon.com (com.mx, com.br, ca) | 4.9.0 |
Amazon | amazon.de (fr, it, es, in, nl, ru, co.uk) | 4.9.0 |
Amazon | amazon.co.jp (com.au) | 4.9.0 |
Amazon | amazon.cn | 4.9.0 |
Amazon | a.co | 4.9.0 |
Amazon | amzn.to (eu, in, asia) | 4.9.0 |
Amazon | z.cn | 4.9.0 |
Someecards | someecards.com | 4.9.0 |
Someecards | some.ly | 4.9.0 |
Crowdsignal | survey.fm | 5.1.0 |
Instagram TV | instagram.com | 5.1.0 |
Instagram TV | instagr.am | 5.1.0 |
TikTok | tiktok.com | 5.4.0 |
Видалення простроченого oEmbed Кеша
Для очищення Бази Даних на великих сайтах можна сенс періодично запускати таку функцію, щоб видаляти прострочений кеш.
/** * Remove expired oEmbed Cache. * * @param int $ttl Скасувати термін служби в seconds. * */ function kama_delete_expired_oembed_cache( $ttl = MONTH_IN_SECONDS ){ Global $wpdb; // META $query_data = $wpdb->get_results( "SELECT * FROM $wpdb->postmeta WHERE meta_key LIKE '_oembed_time_%' ORDER BY meta_value+0 DESC" ); $ res = []; foreach( $query_data as $data ){ $post = get_post($ data->post_id ); $info = date( 'dmY', $data->meta_value ) ." - $post->ID: $post->post_title"; if( time() > $data->meta_value + $ttl ){ $oembed_meta_key = str_replace( '_oembed_time_', '_oembed_', $data->meta_key ); delete_post_meta($ data->post_id, $ data-> meta_key ); delete_post_meta( $data->post_id, $oembed_meta_key ); $res['DELETED'][] = $info; } else { $res['NOT DELETED'][] = $info; } } // POSTS $min_allowed_date = date( 'Ymd H:i:59', time() - $ttl ); $posts = $wpdb->get_results( "SELECT * FROM $wpdb->posts WHERE post_type = 'oembed_cache' AND post_modified_gmt < '$min_allowed_date' ORDER BY post_modified_gmt DESC" ); foreach( $posts as $post ){ $res['DELETED POSTS'][] = $post->post_modified_gmt; wp_delete_post( $post->ID, 'force_delete' ); } return $res; } $res = kama_delete_expired_oembed_cache(); print_r ($ res);
Внутрішній embed обробник (з кешуванням)
Для початку зауважу, що це хак – WP на таке не розрахований. Але завдяки хукам можна це зробити.
Для цього використовуємо хук WP_oEmbed::get_html() :
// ... $pre = apply_filters( 'pre_oembed_result', null, $url, $args ); if ( null !== $pre ) { return $pre; } // ...
Потрібно зареєструвати внутрішній обробник через функцію wp_embed_register_handler() . Але у функції оброблювача повернути false і перенести функцію оброблювача в згаданий хук pre_oembed_result .
Тобто. код буде приблизно такий:
add_action( 'init', 'myembed_provider_register'); add_filter( 'pre_oembed_result', 'myembed_provider_handler', 10, 3); function myembed_provider_register(){ wp_embed_register_handler( 'myembed', '~https://foo.bar.com/(w+)~i', '__return_false' ); } function myembed_provider_handler( $null, $url, $args ){ $html = '{{unknown}}'; // Обробляємо $url робимо HTTP запит. Див. WP HTTP API // Повертаємо iframe або HTML код return $html; }
oEmbed для довільного тексту
https://my-youtube.com/watch?v=lWzMBLoLIAc
https://my-youtube.com/watch?v=uDQwKtkXV-0
';
$text = apply_filters( 'the_content', $text );
echo $text;
Варіант 2: Точковий підхід
Робимо з текстом тільки те, що нам потрібно:
$text = ' Один текст до перевірки custom shortcode adding. https://my-youtube.com/watch?v=lWzMBLoLIAc https://my-youtube.com/watch?v=uDQwKtkXV-0 '; $text = $GLOBALS['wp_embed']->run_shortcode( $text ); // shortcode $text = $GLOBALS['wp_embed']->autoembed( $text ); // oEmbed URLs //$text = apply_shortcodes($text); $ Text = wpautop ($ Text); echo $text;
oEmbed в коментарях WordPress
Код нижче дозволяє використовувати oEmbed у коментарях WordPress.
Правка для роботи з AJAX:
Вимкнення oEmbed
Для відключення oEmbed у WP можна використовувати спеціальний плагін Disable Embeds . Але також це можна зробити кодом. Нижче розглянемо варіант із використанням коду.
Відключимо oEmbed маршрут (можливість, щоб наш сайт був постачальником oEmbed):
add_action( 'init', 'wpkama_disable_embed_route', 99); function wpkama_disable_embed_route(){ // Remove the REST API endpoint. remove_action( 'rest_api_init', 'wp_oembed_register_route'); // Remove oEmbed discovery links. remove_action( 'wp_head', 'wp_oembed_add_discovery_links'); // Remove all embeds rewrite rules. add_filter( 'rewrite_rules_array', function ( $rules ){ foreach( $rules as $rule => $rewrite ){ if( false !== strpos( $rewrite, 'embed=true' ) ){ unset($rules[$rule]); } } return $rules; } ); }
Повністю відключаємо всі вбудовування у контенті
Скасування цих хуків повністю відключить можливість вбудовувати посилання на окремому рядку в контенті, а також роботу шорткоду .
// Remove shortcode parser remove_filter( 'the_content', [ $GLOBALS['wp_embed'], 'run_shortcode' ], 8 ); remove_filter( 'widget_text_content', [ $GLOBALS['wp_embed'], 'run_shortcode' ], 8 ); // Remove embed url parser remove_filter( 'the_content', [ $GLOBALS['wp_embed'], 'autoembed' ], 8 ); remove_filter( 'widget_text_content', [ $GLOBALS['wp_embed'], 'autoembed' ], 8 );
Відключаємо вбудовування конкретних URL-адрес (конкретних провайдерів)
Вимикаємо вбудовування для внутрішніх посилань сайту
Нам потрібно, щоб вбудовування не працювало, коли ми вказуємо в пості посилання на поточний сайт на окремому рядку:
// Remove filter of the oEmbed result before any HTTP requests are made. remove_filter( 'pre_oembed_result', 'wp_filter_pre_oembed_result', 10);
Відключаємо усі невідомі провайдери
Це провайдери, які не зареєстровані в WP, але вони мають discovery <link> за яким WP може отримати код вбудовування. Наприклад, таким посиланням може бути посилання на інший сайт WordPress.
// Remove oEmbed iframes communicate JavaScript з front-end and back-end. remove_action( 'wp_head', 'wp_oembed_add_host_js'); // Turn off oEmbed auto discovery request for unknown URLs. add_filter( 'embed_oembed_discover', '__return_false');
Відключаємо відомих провайдерів . Для цього використовуємо функцію wp_oembed_remove_provider() .
У цьому випадку нам потрібно буде точно вказати формати посилань для провайдерів, які ми хочемо відключити.
add_action( 'init', 'my_remove_oembed_providers', 99); function my_remove_oembed_providers(){ // existing providers // print_r(_wp_oembed_get_object()->providers); $ remove_formats = [ // youtube '#https?://((m|www).)?youtube.com/watch.*#i', '#https?://((m|www).)?youtube.com/playlist.*#i', '#https?://youtu.be/.*#i' ]; foreach( $remove_formats as $format ){ wp_oembed_remove_provider( $format ) } }
Помилки, що робити не потрібно
У мережі багато де додається наступний хук для відключення провайдерів. Цього робити не можна! Цей хук потрібний для безпеки під час вбудовування! Він спрацьовує безпосередньо при вбудовуванні, тому правильніше відключити вбудовування, а не цей хук.
// Не фільтрує (HTML sanitize) oEmbed results. remove_filter( 'oembed_dataparse', 'wp_filter_oembed_result', 10);
Читайте Детальніше про безпеку .