Плагин для WordPress

И так, ранее я писал про классификацию сообщеий. Теперь неплохо дыло бы использовать его на практике. Заодно не плохо было бы разобраться как написать пдлагин для WordPress. В данном случае это будет плагин в тени, т.е. он будет проверять сообщения комментариев без участия пользователя.

Скелет

Для начала не плохо было бы понять с чего начать. Я достаточно долго блуждал по интернету в поисках информации. Когда впервые что-то берешь в руки и не знаешь что с этим делом начинаешь искать хоть какую-то вводную статью. Нашел я пару статей, но они не для моей версии (на текущий момент 5.8.2). Хотелось что-то свежее.

В результате поисков я нашел пару интересных и полезные статей. Но мне повезло еще в одном: генератор скелета. Чтобы со всем этим добром не ковыряться ребята выложили форму, в которой можно просто сгенерировать шаблон. Думаю с формой можно разобраться. Там все просто.

Подготовка

Вот мы сгенерировали скелет, скачали, распаковали в wp/wp-content/plugins/classify-comments-wp-plugin (в моем случае). Что дальше? А дальше нужно начинать писать, так как в нем уже все готово.

Для начала открываем основной файл (в моем случае classify-comment.php) и правим заголовок:


/**
 * The plugin bootstrap file
 *
 * This file is read by WordPress to generate the plugin information in the plugin
 * admin area. This file also includes all of the dependencies used by the plugin,
 * registers the activation and deactivation functions, and defines a function
 * that starts the plugin.
 *
 * @since             1.0.0
 * @package           Classify_Comment
 *
 * @wordpress-plugin
 * Plugin Name:       Classify Comment
 * Plugin URI:        https://ymnuktech.ru
 * Description:       Classify comments for toxic messages
 * Version:           1.0.0
 * Author:            Alexandr Fedoryuk
 * Author URI:        https://ymnuktech.ru
 * License:           GPL-2.0+
 * License URI:       http://www.gnu.org/licenses/gpl-2.0.txt
 * Text Domain:       classify-comment
 * Domain Path:       /languages
 */

Эти комментарии нужны чтобы WordPress показал информацию о плагине: кто написал, ссылки, адреса и т.д. Теперь нужно немного подредактировать скелет, так как мне лично не нравится, что я должен дублировать некоторую информацию. Для этого я создал файл includes/class-classify-comment-ext.php и добавил следующее:


class Classify_Comment_Ext
{

    public const table_classify_comments = "classify_comments";

    public const table_classify_comments_option = "classify_comments_option";

    public $address;
    public $cats;

    public function __constructor()
    {
    }

    /**
     * Проверяет переданное сообщение и возвращает его категорию
     * @param string $msg - Сообщение
     * @return string - возвращает категорию
     */
    protected function verifyMessage($msg, $moreInfo = null)
    {
        $this->loadOptions();

        $data = array(
            'text' => $msg
        );
        $payload = json_encode($data);

        $ch = curl_init($this->address . "/api/v1/fisher");

        curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type:application/json'));
        # Return response instead of printing.
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        # Send request.
        $result = curl_exec($ch);
        curl_close($ch);
        $result = json_decode($result);

        global $wpdb;

        $q = $wpdb->prepare(
            "
        INSERT INTO `" . $wpdb->prefix . Classify_Comment_Ext::table_classify_comments . "`
        (`comment_content`, `cat`, `comment_post_ID`, `comment_author`, `comment_author_email`, `comment_author_url`, `comment_author_IP`, `comment_agent`, `user_ID`)
        VALUES
        (%s, %s, %d, %s, %s, %s, %s, %s, %d)",
            $msg,
            $result->data,
            !is_null($moreInfo) ? $moreInfo['comment_post_ID'] : null,
            !is_null($moreInfo) ? $moreInfo['comment_author'] : null,
            !is_null($moreInfo) ? $moreInfo['comment_author_email'] : null,
            !is_null($moreInfo) ? $moreInfo['comment_author_url'] : null,
            !is_null($moreInfo) ? $moreInfo['comment_author_IP'] : null,
            !is_null($moreInfo) ? $moreInfo['comment_agent'] : null,
            !is_null($moreInfo) ? $moreInfo['user_ID'] : null
        );

        $wpdb->query($q);

        if ($result->result) return $result->data;



        return null;
    }

    /**
     * Проверка по списку блокировки категории
     * @param string Категория для проверки
     * @param boolean Если попадает в указанную категорию в настройках, то возвращает true
     */
    protected function validateCats($msg, $moreInfo = null)
    {
        $cat = $this->verifyMessage($msg, $moreInfo);

        // error_log($cat);

        if (count($this->cats) === 0) return false;

        foreach ($this->cats as $val) {
            if ($val == $cat) return true;
        }

        return false;
    }

    protected function loadOptions()
    {
        global $wpdb;

        $res = $wpdb->get_results("
		SELECT value FROM {$wpdb->prefix}classify_comments_option WHERE name = 'address'");
        $this->address = $res[0]->value;

        $res = $wpdb->get_results("
		SELECT value FROM {$wpdb->prefix}classify_comments_option WHERE name = 'cats'");

        $cats = array();

        if (isset($res) && count($res) > 0 && !is_null($res[0]->value)) {
            $res = explode(",", $res[0]->value);
            if (count($res) > 0) {
                foreach ($res as $val) {
                    $val = trim($val);
                    if (strlen($val) > 0) {
                        array_push($cats, $val);
                    }
                }
            }
        }

        $this->cats = array_unique($cats);
    }
}

После, для классов Classify_Comment_Admin и Classify_Comment_Public я добавил extends Classify_Comment_Ext. Далее чтобы это заработало (иначе упадет в ошибку) в классе includes/class-classify-comment.php в функцию load_dependencies() добавляем строчку:


require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-classify-comment-ext.php';

На этом подготовка закончена.

Реализация админки

Первым делом можно создать меню для админки. Для этого добавляем функцию admin_generate_menu():


public function admin_generate_menu()
{
	// Добавляем основной раздел меню
	add_menu_page('Добро пожаловать в модуль классификации комментариев', 'Токсичность', 'manage_options', 'options_toxic_comments', array(&$this, 'admin_options'));;
	// Добавляем дополнительный раздел
	add_submenu_page('options_toxic_comments', 'Управление содержимом', 'Проверка', 'manage_options', 'toxic_test', array(&$this, 'admin_comment_test'));
	add_submenu_page('options_toxic_comments', 'Управление содержимом', 'Список сообщений', 'manage_options', 'toxic_list', array(&$this, 'admin_comment_list'));
}

В функции define_admin_hooks() регистрируем наше меню:


$this->loader->add_action('admin_menu', $plugin_admin, 'admin_generate_menu');

Теперь для страниц напишем 3 функции в классе админки:


/**
 * Настройка параметров плагина
 */
public function admin_options()
{
	global $wpdb;

	if ($_SERVER['REQUEST_METHOD'] === 'POST') {
		// Обновляем данные настроек
		$q = $wpdb->prepare("
		INSERT INTO {$wpdb->prefix}classify_comments_option (name, value)
		VALUES ('address' ,%s)
		ON DUPLICATE KEY UPDATE value = %s", $_POST['address'], $_POST['address']);
		$wpdb->query($q);

		$q = $wpdb->prepare("
		INSERT INTO {$wpdb->prefix}classify_comments_option (name, value)
		VALUES ('cats'
		, %s)
		ON DUPLICATE KEY UPDATE value = %s", $_POST['cats'], $_POST['cats']);
		$wpdb->query($q);
	}

	$this->loadOptions();

	$options = array(
		'address' => $this->address,
		'cats' => $this->cats
	);

	require_once('partials/classify-comment-admin-options.php');
}

/**
 * Список проверенных сообщений
 */
public function admin_comment_list()
{
	global $wpdb;

	$res = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}classify_comments ORDER BY date_filtered DESC LIMIT 500");

	require_once('partials/classify-comment-admin-list.php');
}

/**
 * Проверка работы сервиса
 */
public function admin_comment_test()
{

	$result = null;

	if ($_SERVER['REQUEST_METHOD'] === 'POST') {
		$result = $this->verifyMessage($_POST['message']);
	}

	require_once('partials/classify-comment-admin-test.php');
}

В директории partials размещаем наши файлы представления для отображения информации. classify-comment-admin-list.php:


<?php

/**
 * Provide a admin area view for the plugin
 *
 * This file is used to markup the admin-facing aspects of the plugin.
 *
 * @since      1.0.0
 *
 * @package    Classify_Comment
 * @subpackage Classify_Comment/admin/partials
 */
?>

<!-- This file should primarily consist of HTML with a little bit of PHP. -->
<div class="classify-comments-content">
    <h1>Список обработанных комментариев</h1>
    <table>
        <tr>
            <th>Автор</th>
            <th>E-Mail</th>
            <th>URL</th>
            <th>IP</th>
            <th>Комментарий</th>
            <th>Агент</th>
            <th>Категория</th>
            <th>Дата фильтрации</th>
        </tr>
        <?php foreach ($res as $row) { ?>
            <tr>
                <td><?php echo $row->comment_author; ?></td>
                <td><?php echo $row->comment_author_email; ?></td>
                <td><?php echo $row->comment_author_url; ?></td>
                <td><?php echo $row->comment_author_IP; ?></td>
                <td><?php echo $row->comment_content; ?></td>
                <td><?php echo $row->comment_agent; ?></td>
                <td><?php echo $row->cat; ?></td>
                <td><?php echo $row->date_filtered; ?></td>
            </tr>
        <?php } ?>
    </table>

    <p>Всего показано строк: <?php echo count($res); ?>

</div>

classify-comment-admin-options.php:


<?php

/**
 * Provide a admin area view for the plugin
 *
 * This file is used to markup the admin-facing aspects of the plugin.
 *
 * @since      1.0.0
 *
 * @package    Classify_Comment
 * @subpackage Classify_Comment/admin/partials
 */
?>

<!-- This file should primarily consist of HTML with a little bit of PHP. -->
<div class="classify-comments-content">
    <h1>Настройки Токсичности</h1>
    <form method="POST">
        <p>
            <label>Адрес обработчика</label>
            <input name="address" value="<?php echo $options['address']; ?>">
        </p>
        <p>
            <label>Категории для блокировки (через запятую)</label>
            <input name="cats" value="<?php echo implode(", ", $options['cats']); ?>">
        </p>
        <input type="submit" value="Сохранить">
    </form>
</div>

classify-comment-admin-test.php:


<?php

/**
 * Provide a admin area view for the plugin
 *
 * This file is used to markup the admin-facing aspects of the plugin.
 *
 * @since      1.0.0
 *
 * @package    Classify_Comment
 * @subpackage Classify_Comment/admin/partials
 */
?>

<form method="POST">
    <p>
        <label>Введите сообщение для проверки</label>
        <input type="text" name="message" value="<?php echo $message; ?>">
    </p>
    <input type="submit" value="Проверить">
</form>

<?php if (isset($result) && !is_null($result)) { ?>

    <div class="result">
        <p>
            Результат: <?php echo $result; ?>
        </p>
    </div>

<?php } ?>

С админкой закончили.

Основной функционал

Теперь не плохо было бы реализовать саму фильтрацию. В классе Classify_Comment_Public добавим функцию:


/**
 * Проверяем комментарий на токсичность. Если это будет группа из списка настроек, то вернем результат 'spam' чтобы заблокировать.
 */
public function pre_filter_comment($approved, $commentdata)
{
	if ($approved === 'spam') return $approved;

	if ($this->validateCats($commentdata['comment_content'], $commentdata) === true) return 'spam';

	return $approved;
}

А в функцию define_public_hooks() добавим хук:


$this->loader->add_filter('pre_comment_approved', $plugin_public, 'pre_filter_comment', 10, 2);

Тут все просто, потому как основной функционал уже реализован в классе Classify_Comment_Ext.

Последний штрих

Еще нужно реализовать маленькую функцию удаления плагина. В файле uninstall.php запишем следующее:


if (!defined('WP_UNINSTALL_PLUGIN')) {
	global $wpdb;
	wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}classify_comments");
	wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}.classify_comments_option");
	exit;
}

Теперь все готово и можно активировать плагин.

Что получилось

В админке должно появиться 3 страницы. Заходим в Токсичность и указываем адрес до сервиса и через запятую перечисляем категории, которые будем блокировать.

Настройка плагина

В меню проверки можем написать текст и посмотреть как оно работает.

Проверка сообщения

А в списке сообщений можем посмотреть историю.

История обработки

Исходный код можно взять из гита.

Поделиться
Вы можете оставить комментарий, или ссылку на Ваш сайт.

Оставить комментарий

Вы должны быть авторизованы, чтобы разместить комментарий.