WordPress hook/filter для обработки ссылки внутри сообщения

Есть ли hook/filter для обработки ссылки, добавляемой в сообщение WordPress?

Моя цель - предварительно обработать ссылку, вставленную в сообщение, используя следующую кнопку и сократить ее с помощью стороннего API, такого как bit.ly

Я хочу сделать это как для внутренних, так и для внешних ссылок.

Кнопка добавления ссылки TinyMCE

Одно из решений, о котором я думаю, заключается в добавлении дополнительной кнопки в мой редактор, который делает это, но я бы предпочел хук/фильтр, который выполняет эту работу, таким образом, это будет более чистым и Я преобразую это в пользовательский плагин для моего сайта (там, позволяя моему WordPress быть повышающимся).

Я прошел через документы WordPress и просмотрел следующие перехватчики/фильтры, которые мне не нужны

Ответ 1

Обновление 1. Насколько я знаю, внешние URL-адреса вставляются в почтовый контент плагином редактора TinyMCE, PHP ничего не делает.

В WordPress есть два плагина, которые расположены в wp-includes/js/wplink.js и wp-includes/js/tinymce/plugins/wplink/plugin.js. Обратите внимание: если вы не находитесь в режиме SCRIPT_DEBUG, у них есть суффикс .min.

  • wp-includes/js/wplink.js обрабатывает это диалоговое окно:

wplink dialog box 1

Чтобы фильтровать URL-адреса, вставленные в это диалоговое окно, мы должны переопределить метод wpLink.getAttrs. Например, чтобы добавить строку so39115564 к каждому URL-адресу:

jQuery(document).ready(function($) {
  wpLink.getAttrs = function() {
    wpLink.correctURL();
    return {
      href: $.trim( $("#wp-link-url").val() + "so39115564" ),
      target: $("#wp-link-target").prop("checked") ? "_blank" : ""
    };
  }
});

Вы можете посмотреть wp-includes/js/wplink.js для получения дополнительной информации. Это слишком долго, чтобы подробно объяснить здесь.

И пусть говорят, что выше script есть mylink.js, вот как мы должны заключить его в очередь:

add_filter('admin_enqueue_scripts', function()
{
  // { Maybe some conditions for a valid screen here. }

  wp_enqueue_script('mylink', 'link/to/the/mylink.js', ['link'], '1.0', true);
}, 0, 0);
  1. wp-includes/js/tinymce/plugins/wplink/plugin.js обрабатывает это диалоговое окно:

диалог wplink 2

На этот раз мы также должны переопределить метод setURL tinymce.ui.WPLinkPreview. Но это почти невозможно, если вы не отмените регистрацию этого script и не зарегистрируете измененную версию. Затем управляйте этим script самостоятельно с непредсказуемыми изменениями из WordPress.

Теперь, выберите это мудро! Сократите любые внешние URL-адреса, прежде чем вставлять их в свои сообщения или испортить плагины WordPress TinyMCE или использовать диалоговое окно плагина wp-includes/js/wplink.js.


Да! WordPress вставляет встроенные ссылки через wp_link_ajax действие, которое выполняется функция wp_ajax_wp_link_ajax().

Как вы можете видеть в исходном коде этой функции, $results извлекается _WP_Editors::wp_link_query. Проверьте этот метод, вы встретите wp_link_query фильтр. Этот фильтр принимает два аргумента: $results и $query. $results будет тем, что нам нужно отфильтровать.

Например, нам нужно добавить so39115564 в запрошенную ссылку:

add_filter('wp_link_query', function(array $results, array $query)
{
  $results[0]['permalink'] = $results[0]['permalink'] . 'so39115564';

  return $results;
}, PHP_INT_MAX, 2);

Теперь вы должны знать, как это сделать. Обязательно посмотрите _ WP_Editors:: wp_link_query, чтобы фильтр $results стал более эффективным.

Ответ 2

Вы считали, что не обрабатываете ссылку до тех пор, пока не сохраните сообщение? В плагине wordpress api есть действие, называемое "save_post", которое запускается при сохранении.

Используя "save_post", вы можете анализировать содержимое сообщения и заменять ссылки, используя укороченный URL-адрес.

https://codex.wordpress.org/Plugin_API/Action_Reference/save_post

Ответ 3

Для этого могут быть доступны плагины, но здесь используется логика по умолчанию.

1st Way: сохранение сокращенного URL-адреса в DB также

add_action( 'save_post', 'save_book_meta', 10, 3 );
function save_book_meta( $post_id, $post, $update ) {
    global $wpdb;
    $slug = 'event';

    // If this isn't a 'book' post, don't update it.
    if ( $slug != $post->post_type ) {
        return;
    }

    preg_match_all('|<a.*(?=href=\"([^\"]*)\")[^>]*>([^<]*)</a>|i', $post->post_content, $match);

    $new_content = $post->post_content;

    foreach($match[1] as $link){
        $url = 'https://www.googleapis.com/urlshortener/v1/url?key=AIzaSyAnw98CCy5owhpgB2HvW3SkoXfm0MrLjks';

        $json_data = json_encode( array( 'longUrl' => $link ) );

        //open connection
        $ch = curl_init();

        //set the url, number of POST vars, POST data
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $json_data);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

        $result = curl_exec($ch);
        curl_close($ch);


        $result = json_decode($result);
        $new_content = str_replace($link, $result->id, $new_content);

    }

    // unhook this function so it doesn't loop infinitely
    remove_action('save_post', 'save_book_meta' );

    $post_new = array(
        'ID'       => $post_id,
        'post_content'  => $new_content
      );

    $post_id = wp_update_post( $post_new, true );                         
    if (is_wp_error($post_id)) {
        $errors = $post_id->get_error_messages();
        foreach ($errors as $error) {
            echo $error;
        }
    }
    add_action( 'save_post', 'save_book_meta' );

}

Чтобы достичь вышеуказанного, вам нужно будет сделать следующее:

  • Используйте save_post для получения сообщения после сохранения.
  • В этом крюке выберите все внешние ссылки в массиве (измените условия согласно требованиям).
  • Сократите URL-адрес с помощью API Google (требуется ключ).
  • Получите ответ от API Google и обновите post_data соответственно в базе данных.
  • В wp_update_post мы удаляем крючок, чтобы избежать бесконечного цикла.

2nd Way: Чтобы показать URL-адрес укороченного пользователя в интерфейсе (у DB будет longUrl, хотя)

  • Вместо этого используйте крючок фильтра и с той же логикой.

3rd Way: использование плагинов (не используется лично).

Ответ 4

Я не совершенен в TinyMCE, потому что я не использовал TinyMCE в нескольких проектах, но у меня есть опыт работы с javascript, поэтому я нашел какое-то событие TinyMCE api для использования, вы можете сделать короткий URL-адрес. Я проверил последнюю версию WP и версию TinyMCE 4.x. Вы также можете найти подходящий api для запуска пользовательского обратного вызова.

Перед инициализацией tinymce в функции настройки регистра регистратора wordpress с помощью клавиши wordpress tiny_mce_before_init.

add_filter( 'tiny_mce_before_init', 'my_plugin_tiny_mce_before_init' );
function my_plugin_tiny_mce_before_init( $in ){
  $in['setup'] = 'myplugin_tinymce_setup'; // javascript callback 
  return $in;   
}

   add_action( 'admin_footer', 'add_admin_footer' );

После добавления обратного вызова javascript в нижний колонтитул администратора. У меня есть два метода для этого решения.

# 1

function add_admin_footer(){
 ?>
  <script type="text/javascript">
    var counter = 1, insert_url, shorten_url;

    function myplugin_tinymce_setup( editor ){

     editor.onNodeChange.add(function(ed, cm, e) {
          // Activates the link button when the caret is placed in a anchor element
          if (e.nodeName.toLowerCase() == 'a'){
            var element = jQuery(e).not('a[href="_wp_link_placeholder"],a[data-wplink-edit="true"]');
            if( element.length ){
              if( is_shorten = getShortenUrl( element.attr( 'href') ) ){ 
               element.attr( 'href', is_shorten );
               element.attr( 'data-mce-href', is_shorten );
              }
            }
          }

      });

 var hostname = new RegExp(location.host);
    var shorten_host = new RegExp('http://www.example.com'); // enter your short url generate host name
    function getShortenUrl( url ){
        // add more condition here...
        // Add here ajax or shorten javascript api etc.
        // filter and return short url
        if( hostname.test( url ) ){
           // internal link  
           // Return internal url with shorten
           return 'http://www.example.com/Internal/'+counter++;     

        }else if( shorten_host.test( url ) ){
          // not update already update with shorten url
          return false; 

        }else{
          // Return external url with shorten
          return 'http://www.example.com/External/'+counter++;  
        }

    }
</script>
 <?php  

Сокращение ссылки WP в редакторе

# 2

function add_admin_footer(){
 ?>
  <script type="text/javascript">
    var counter = 1, insert_url, shorten_url;

    function myplugin_tinymce_setup( editor ){

        editor.on('ExecCommand', function(e) {

            // Eexcute command when click on button apply on insert/edit link
           if( e.command == 'wp_link_apply' ){

              if( editor.selection.getContent() ){
                element = tinymce.$(editor.selection.getContent()); // Create new link 
              }else{
                element = tinymce.$(editor.selection.getNode()); // Edit link option 
              }
              if( element.prop('tagName').toLowerCase() == 'a' ){
                  current_link_url = element.attr('href'); // Real url added in editor.
                  // and also check current_link_url is not shorten url
                  // add more logic here. Get short url using ajax or bitly javascript api. 
                  if( is_shorten_url = getShortenUrl( element.attr('href')) ){
                    editor.execCommand('mceInsertLink',false,{ href: is_shorten_url });  
                  }

              }
           }

        });
    }

    var hostname = new RegExp(location.host);
    var shorten_host = new RegExp('http://www.example.com'); // enter your short url generate host name
    function getShortenUrl( url ){
        // add more condition here...
        // Add here ajax or shorten javascript api etc.
        // filter and return short url
        if( hostname.test( url ) ){
           // internal link  
           // Return internal url with shorten
           return 'http://www.example.com/Internal/'+counter++;     

        }else if( shorten_host.test( url ) ){
          // not update already update with shorten url
          return false; 

        }else{
          // Return external url with shorten
          return 'http://www.example.com/External/'+counter++;  
        }

    }

  </script>
 <?php  

}

Желаем удачи:)