Вызов пользовательского действия при нажатии кнопки настроек

9 янв. 2013 г., 20:21:39
Просмотры: 39.7K
Голосов: 11

Это мой первый плагин для WordPress, и у меня возникает много проблем с его работой. Он почти работает нормально, но я не могу найти способ реализовать одну конкретную функцию.

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

Поскольку мой плагин после настройки запускает другое действие, которое создает/обновляет записи в таблице, но в первый раз мне нужно запустить синхронизацию, чтобы создать/обновить записи из старых постов WordPress.

Редактировать:

Исходный код плагина доступен на wsd-parse-api.

3
Комментарии

Можете опубликовать ваш код, пожалуйста?

s_ha_dum s_ha_dum
9 янв. 2013 г. 21:09:17

Это не совсем необходимо, потому что он сейчас довольно сложный (разделен на множество файлов и т.д.). Но ответ toscho был именно тем, что мне нужно. С уважением

norman784 norman784
9 янв. 2013 г. 21:13:46

добавил репозиторий плагина на github!

norman784 norman784
9 янв. 2013 г. 21:52:32
Все ответы на вопрос 1
5
19

Вам понадобится вторая форма form с admin_url('admin-post.php') в качестве действия формы. Затем вы можете подключиться к admin_post_custom_action, чтобы выполнить свое действие.

Пример кода:

add_action( 'admin_post_wpse_79898', 'wpse_79898_test' );

function wpse_79898_test() {
    if ( isset ( $_GET['test'] ) )
        echo esc_html( $_GET['test'] );

    die( __FUNCTION__ );
}

На странице настроек:

<form action="<?php echo admin_url( 'admin-post.php' ); ?>">
<input type="hidden" name="action" value="wpse_79898">
<input type="text" name="test" value="">
<?php submit_button( 'Отправить' ); ?>
</form>

Обновление

Вот более расширенный пример. Он демонстрирует:

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

Пример, который я использовал здесь – обновление опции – не следует использовать для плагинов, активированных только для одного сайта. Однако для плагинов, активированных для сети, это довольно полезно, потому что для них нет API опций.

Я должен был бы добавить комментарии, но мне лень. :) Я напишу пост в блоге об этом и позже обновлю ответ ссылкой.

<?php
/* Plugin Name: admin-post demo */

add_action( 'wp_loaded', array ( WPSE_79898_Admin_Post_Demo::get_instance(), 'register' ) );

class WPSE_79898_Admin_Post_Demo
{
    /**
     * Plugin instance.
     *
     * @see get_instance()
     * @type object
     */
    protected static $instance = NULL;

    protected $action     = 'wpse_79898';
    protected $option_name     = 'wpse_79898';
    protected $page_id = NULL;

    /**
     * Access this plugin’s working instance
     *
     * @wp-hook wp_loaded
     * @return  object of this class
     */
    public static function get_instance()
    {
        NULL === self::$instance and self::$instance = new self;
        return self::$instance;
    }

    public function register()
    {
        add_action( 'admin_menu', array ( $this, 'add_menu' ) );
        add_action( "admin_post_$this->action", array ( $this, 'admin_post' ) );
    }

    public function add_menu()
    {
        $page_id = add_options_page(
            'Admin Post Demo',
            'Admin Post Demo',
            'manage_options',
            'admin-post-demo',
            array ( $this, 'render_options_page' )
        );

        add_action( "load-$page_id", array ( $this, 'parse_message' ) );
    }

    public function parse_message()
    {
        if ( ! isset ( $_GET['msg'] ) )
            return;

        $text = FALSE;

        if ( 'updated' === $_GET['msg'] )
            $this->msg_text = 'Обновлено!';

        if ( 'deleted' === $_GET['msg'] )
            $this->msg_text = 'Удалено!';

        if ( $this->msg_text )
            add_action( 'admin_notices', array ( $this, 'render_msg' ) );
    }

    public function render_msg()
    {
        echo '<div class="' . esc_attr( $_GET['msg'] ) . '"><p>'
            . $this->msg_text . '</p></div>';
    }

    public function render_options_page()
    {
        $option = esc_attr( stripslashes( get_option( $this->option_name ) ) );
        $redirect = urlencode( remove_query_arg( 'msg', $_SERVER['REQUEST_URI'] ) );
        $redirect = urlencode( $_SERVER['REQUEST_URI'] );

        ?><h1><?php echo $GLOBALS['title']; ?></h1>
        <form action="<?php echo admin_url( 'admin-post.php' ); ?>" method="POST">
            <input type="hidden" name="action" value="<?php echo $this->action; ?>">
            <?php wp_nonce_field( $this->action, $this->option_name . '_nonce', FALSE ); ?>
            <input type="hidden" name="_wp_http_referer" value="<?php echo $redirect; ?>">

            <label for="<?php echo $this->option_name; ?>">Введите текст:</label>
            <input type="text" name="<?php echo $this->option_name;
                ?>" id="<?php echo $this->option_name;
                ?>" value="<?php echo $option; ?>">
            <?php submit_button( 'Отправить' ); ?>
        </form>
        <?php
    }

    public function admin_post()
    {
        if ( ! wp_verify_nonce( $_POST[ $this->option_name . '_nonce' ], $this->action ) )
            die( 'Неверный nonce.' . var_export( $_POST, true ) );

        if ( isset ( $_POST[ $this->option_name ] ) )
        {
            update_option( $this->option_name, $_POST[ $this->option_name ] );
            $msg = 'updated';
        }
        else
        {
            delete_option( $this->option_name );
            $msg = 'deleted';
        }

        if ( ! isset ( $_POST['_wp_http_referer'] ) )
            die( 'Отсутствует цель.' );

        $url = add_query_arg( 'msg', $msg, urldecode( $_POST['_wp_http_referer'] ) );

        wp_safe_redirect( $url );
        exit;
    }
}
9 янв. 2013 г. 20:29:32
Комментарии

круто, теперь мне нужно переписать свой плагин! xD и использовать ООП. Спасибо

norman784 norman784
9 янв. 2013 г. 23:28:26

Я готов к публикации в блоге.

lmat - Reinstate Monica lmat - Reinstate Monica
9 июн. 2020 г. 01:07:44

add_action по умолчанию предполагает передачу функции с одним аргументом. У вас функция принимает ноль аргументов. Передает ли WordPress аргумент в вашу функцию, который вы игнорируете? Какой аргумент он передает?

lmat - Reinstate Monica lmat - Reinstate Monica
9 июн. 2020 г. 01:19:20

@LimitedAtonement Нет такого требования относительно аргументов.

fuxia fuxia
9 июн. 2020 г. 07:08:27

Очень полезный ответ. Спасибо!

AidanCurran AidanCurran
7 мая 2021 г. 00:53:22