Как создать эффективный фильтр контента для определенных сообщений?

Я пометил этот пост как WordPress, но я не совсем уверен, что он специфичен для WordPress, поэтому я размещаю его на StackOverflow, а не ВПСЭ. Решение не обязательно должно быть специфичным для WordPress, достаточно PHP.

Сценарий
Я веду веб-сайт по рыбному хозяйствус несколькими статьями о тропических рыбах Профили видови Глоссарий.

Наш сайт ориентирован на наши профили. Они, как вы можете назвать, хлеб с маслом веб-сайта.

Чего я надеюсь добиться, так это того, что в описании каждого вида, в котором упоминается другой вид или запись в глоссарии, я могу заменить эти слова ссылкой – такой, как вы увидите здесь. В идеале я также хотел бы, чтобы это происходило в новостях, статьях и сообщениях в блогах.

У нас есть около 1400 профилей видови 1700 статей в словарях. Профили наших видов часто бывают длинными, и, по последним подсчетам, одни только профили наших видов насчитывают более 1,7 миллиона словинформации.

Что я сейчас пытаюсь сделать
В настоящее время у меня есть filter.phpс функцией, которая, как мне кажется, делает то, что мне нужно. Код довольно длинный, и его можно найти полностью здесь.

Кроме того, в моей теме WordPress functions.php, у меня есть следующее:

# ==============================================================================================
# [Filter]
#
# Every hour, using WP_Cron, `my_updated_posts` is checked. If there are new Post IDs in there,
# it will run a filter on all of the post's content. The filter will search for Glossary terms
# and scientific species names. If found, it will replace those names with links including a 
# pop-up.

    include "filter.php";

# ==============================================================================================
# When saving a post (new or edited), check to make sure it isn't a revision then add its ID
# to `my_updated_posts`.

    add_action( 'save_post', 'my_set_content_filter' );
    function my_set_content_filter( $post_id ) {
        if ( !wp_is_post_revision( $post_id ) ) {

            $post_type = get_post_type( $post_id );

            if ( $post_type == "species" || ( $post_type == "post" && in_category( "articles", $post_id ) ) || ( $post_type == "post" && in_category( "blogs", $post_id ) ) ) {
                //get the previous value
                $ids = get_option( 'my_updated_posts' );

                //add new value if necessary
                if( !in_array( $post_id, $ids ) ) {
                    $ids[] = $post_id;
                    update_option( 'my_updated_posts', $ids );
                }
            }
        }
    }

# ==============================================================================================
# Add the filter to WP_Cron.

    add_action( 'my_filter_posts_content', 'my_filter_content' );
    if( !wp_next_scheduled( 'my_filter_posts_content' ) ) {
        wp_schedule_event( time(), 'hourly', 'my_filter_posts_content' );
    }

# ==============================================================================================
# Run the filter.

    function my_filter_content() {
        //check to see if posts need to be parsed
        if ( !get_option( 'my_updated_posts' ) )
            return false;

        //parse posts
        $ids = get_option( 'my_updated_posts' );

        update_option( 'error_check', $ids );

        foreach( $ids as $v ) {
            if ( get_post_status( $v ) == 'publish' )
                run_filter( $v );

            update_option( 'error_check', "filter has run at least once" );
        }

        //make sure no values have been added while loop was running
        $id_recheck = get_option( 'my_updated_posts' );
        my_close_out_filter( $ids, $id_recheck );

        //once all options, including any added during the running of what could be a long cronjob are done, remove the value and close out
        delete_option( 'my_updated_posts' );
        update_option( 'error_check', 'working m8' );
        return true;
    }

# ==============================================================================================
# A "difference" function to make sure no new posts have been added to `my_updated_posts` whilst
# the potentially time-consuming filter was running.

    function my_close_out_filter( $beginning_array, $end_array ) {
        $diff = array_diff( $beginning_array, $end_array );
        if( !empty ( $diff ) ) {
            foreach( $diff as $v ) {
                run_filter( $v );
            }
        }
        my_close_out_filter( $end_array, get_option( 'my_updated_posts' ) );
    }

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

Обоснование запуска на почасовой основе заключалось в том, что если бы мы попытались запускать его при сохранении каждого сообщения, это нанесло бы ущерб автору. Как только мы привлекаем приглашенных авторов, это, очевидно, неприемлемый способ.

Проблема...
Вот уже несколько месяцев у меня возникают проблемы с надежной работой этого фильтра. Я не верю, что проблема заключается не в самом фильтре, а в одной из функций, которая включает фильтр, т. е. в задании cron, или в функции, которая выбирает, какие сообщения фильтруются, или в функции, которая подготавливает списки слов и т. д. для фильтр.

К сожалению, диагностировать проблему довольно сложно (как я вижу) из-за того, что она работает в фоновом режиме и только ежечасно. Я пытался использовать функцию WordPress update_option(которая в основном записывает простое значение базы данных) для проверки ошибок, но мне не очень повезло — и, честно говоря, я совсем запутался. относительно того, в чем заключается проблема.

В результате мы запустили веб-сайт без корректной работы этого фильтра. Иногда кажется, что это работает, иногда нет. В результате у нас теперь есть довольно много профилей видов, которые не отфильтрованы должным образом.

Чего бы я хотел...
В общем, мне нужен совет, как лучше запустить этот фильтр.

Является ли Cron Job ответом? Я могу настроить файл .php, который запускается каждый день, это не проблема. Как он определит, какие посты нужно фильтровать? Какое влияние это окажет на сервер во время его запуска?

В качестве альтернативы, страница администратора WordPress является ответом? Если бы я знал, как это сделать, то что-то вроде страницы — с использованием AJAX — которая позволяла бы мне выбирать сообщения для запуска фильтра, было бы идеальным. Есть плагин под названием AJAX Regenerate Thumbnails, который работает так, может быть, он будет наиболее эффективным?

Соображения

  • Размер базы данных/информации, на которую воздействуют/читаются/записываются
  • Какие посты фильтруются
  • Влияние фильтра на сервер; особенно учитывая, что я, похоже, не могу увеличить лимит памяти WordPress выше 32 МБ.
  • Является ли сам фильтр эффективным, действенным и надежным?

Это довольно сложный вопрос, и я неизбежно (поскольку коллеги отвлекали меня примерно 18 раз в процессе) упустил некоторые детали. Пожалуйста, не стесняйтесь исследовать меня для получения дополнительной информации.

Заранее спасибо,

12
задан dunc 15 June 2012 в 15:10
поделиться